├── .gitignore ├── COPYING ├── README.md ├── ext └── glfw3 │ ├── extconf.rb │ └── glfw3.c ├── glfw3.gemspec └── lib ├── glfw3.rb └── glfw3 ├── callbacks.rb ├── monitor.rb └── window.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | coverage 6 | InstalledFiles 7 | lib/bundler/man 8 | pkg 9 | rdoc 10 | spec/reports 11 | test/tmp 12 | test/version_tmp 13 | tmp 14 | 15 | # YARD artifacts 16 | .yardoc 17 | _yardoc 18 | doc/ 19 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Noel Raymond Cower . 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ruby-glfw3 2 | ========== 3 | 4 | $ gem install glfw3 5 | 6 | Intro 7 | ----- 8 | 9 | [GLFW 3] bindings gem for Ruby 2.x. 10 | 11 | To install the gem, you'll need GLFW 3 built and installed where pkg-config can 12 | find it. You may also want to grab some [OpenGL bindings] as well. 13 | 14 | [OpenGL bindings]: https://github.com/nilium/ruby-opengl 15 | [GLFW 3]: https://github.com/glfw/glfw 16 | 17 | Once that's taken care of, you can install it simply by installing the gem via RubyGems.org using 18 | 19 | $ gem install glfw3 20 | 21 | Or by building and installing the gem, making note of the version so you know 22 | the gem package to install, like so: 23 | 24 | $ gem build glfw3.gemspec 25 | $ gem install glfw3-VERSION-HERE.gemspec 26 | 27 | After that, write a quick script to toy with it. For example: 28 | 29 | require 'glfw3' 30 | require 'opengl-core' 31 | 32 | # Initialize GLFW 3 33 | Glfw.init 34 | 35 | # Create a window 36 | window = Glfw::Window.new(800, 600, "Foobar") 37 | 38 | # Set some callbacks 39 | window.set_key_callback do |window, key, code, action, mods| 40 | window.should_close = true if key == Glfw::KEY_ESCAPE 41 | end 42 | 43 | window.set_close_callback do |window| 44 | window.should_close = true 45 | end 46 | 47 | # Make the window's context current 48 | window.make_context_current 49 | loop do 50 | # And do stuff 51 | Glfw.wait_events 52 | GL.glClear(GL::GL_COLOR_BUFFER_BIT | GL::GL_DEPTH_BUFFER_BIT) 53 | window.swap_buffers 54 | break if window.should_close? 55 | end 56 | 57 | # Explicitly destroy the window when done with it. 58 | window.destroy 59 | 60 | 61 | License 62 | ------- 63 | 64 | ruby-glfw3 is licensed under a simplified BSD license because it seems the most 65 | reasonable. If there's a problem with that, let me know. 66 | 67 | Copyright (c) 2013, Noel Raymond Cower . 68 | All rights reserved. 69 | 70 | Redistribution and use in source and binary forms, with or without 71 | modification, are permitted provided that the following conditions are met: 72 | 73 | 1. Redistributions of source code must retain the above copyright notice, this 74 | list of conditions and the following disclaimer. 75 | 2. Redistributions in binary form must reproduce the above copyright notice, 76 | this list of conditions and the following disclaimer in the documentation 77 | and/or other materials provided with the distribution. 78 | 79 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 80 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 81 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 82 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 83 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 84 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 85 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 86 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 87 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 88 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 89 | 90 | -------------------------------------------------------------------------------- /ext/glfw3/extconf.rb: -------------------------------------------------------------------------------- 1 | require 'mkmf' 2 | 3 | $LDFLAGS += " #{`pkg-config --static --libs glfw3`}" 4 | $CFLAGS += " #{`pkg-config --cflags glfw3`}" 5 | 6 | create_makefile('glfw3/glfw3') 7 | -------------------------------------------------------------------------------- /ext/glfw3/glfw3.c: -------------------------------------------------------------------------------- 1 | #include "ruby.h" 2 | #include 3 | 4 | void Init_glfw3(void); 5 | 6 | static const char *kRB_IVAR_WINDOW_INTERNAL_NAME = "@__internal_window"; 7 | static const char *kRB_IVAR_WINDOW_KEY_CALLBACK_NAME = "@__key_callback"; 8 | static const char *kRB_IVAR_WINDOW_CHAR_CALLBACK_NAME = "@__char_callback"; 9 | static const char *kRB_IVAR_WINDOW_MOUSE_BUTTON_CALLBACK_NAME = "@__mouse_button_callback"; 10 | static const char *kRB_IVAR_WINDOW_CURSOR_POSITION_CALLBACK_NAME = "@__cursor_position_callback"; 11 | static const char *kRB_IVAR_WINDOW_CURSOR_ENTER_CALLBACK_NAME = "@__cursor_enter_callback"; 12 | static const char *kRB_IVAR_WINDOW_SCROLL_CALLBACK_NAME = "@__scroll_callback"; 13 | static const char *kRB_IVAR_WINDOW_POSITION_CALLBACK_NAME = "@__position_callback"; 14 | static const char *kRB_IVAR_WINDOW_SIZE_CALLBACK_NAME = "@__size_callback"; 15 | static const char *kRB_IVAR_WINDOW_CLOSE_CALLBACK_NAME = "@__close_callback"; 16 | static const char *kRB_IVAR_WINDOW_REFRESH_CALLBACK_NAME = "@__refresh_callback"; 17 | static const char *kRB_IVAR_WINDOW_FOCUS_CALLBACK_NAME = "@__focus_callback"; 18 | static const char *kRB_IVAR_WINDOW_ICONIFY_CALLBACK_NAME = "@__iconify_callback"; 19 | static const char *kRB_IVAR_WINDOW_FRAMEBUFFER_SIZE_CALLBACK_NAME = "@__framebuffer_size_callback"; 20 | static const char *kRB_CVAR_WINDOW_WINDOWS_NAME = "@@__windows"; 21 | static const char *kRB_CVAR_GLFW_ERROR_CALLBACK_NAME = "@@__error_callback"; 22 | static const char *kRB_CVAR_GLFW_MONITOR_CALLBACK_NAME = "@@__monitor_callback"; 23 | static const char *kRB_CALL_NAME = "call"; 24 | static const char *kRB_RED_NAME = "red"; 25 | static const char *kRB_GREEN_NAME = "green"; 26 | static const char *kRB_BLUE_NAME = "blue"; 27 | 28 | 29 | static ID kRB_IVAR_WINDOW_INTERNAL; 30 | static ID kRB_IVAR_WINDOW_KEY_CALLBACK; 31 | static ID kRB_IVAR_WINDOW_CHAR_CALLBACK; 32 | static ID kRB_IVAR_WINDOW_MOUSE_BUTTON_CALLBACK; 33 | static ID kRB_IVAR_WINDOW_CURSOR_POSITION_CALLBACK; 34 | static ID kRB_IVAR_WINDOW_CURSOR_ENTER_CALLBACK; 35 | static ID kRB_IVAR_WINDOW_SCROLL_CALLBACK; 36 | static ID kRB_IVAR_WINDOW_POSITION_CALLBACK; 37 | static ID kRB_IVAR_WINDOW_SIZE_CALLBACK; 38 | static ID kRB_IVAR_WINDOW_CLOSE_CALLBACK; 39 | static ID kRB_IVAR_WINDOW_REFRESH_CALLBACK; 40 | static ID kRB_IVAR_WINDOW_FOCUS_CALLBACK; 41 | static ID kRB_IVAR_WINDOW_ICONIFY_CALLBACK; 42 | static ID kRB_IVAR_WINDOW_FRAMEBUFFER_SIZE_CALLBACK; 43 | static ID kRB_CVAR_WINDOW_WINDOWS; 44 | static ID kRB_CVAR_GLFW_ERROR_CALLBACK; 45 | static ID kRB_CVAR_GLFW_MONITOR_CALLBACK; 46 | static ID kRB_CALL; 47 | static ID kRB_RED; 48 | static ID kRB_GREEN; 49 | static ID kRB_BLUE; 50 | 51 | 52 | static VALUE s_glfw_module = Qundef; 53 | static VALUE s_glfw_window_klass = Qundef; 54 | static VALUE s_glfw_window_internal_klass = Qundef; 55 | static VALUE s_glfw_monitor_klass = Qundef; 56 | static VALUE s_glfw_videomode_klass = Qundef; 57 | 58 | 59 | static void rb_glfw_error_callback(int error_code, const char *description); 60 | static void rb_glfw_monitor_callback(GLFWmonitor *monitor, int message); 61 | 62 | 63 | #define Q_IS_A(OBJ, KLASS) RTEST(rb_obj_is_kind_of((OBJ), (KLASS))) 64 | 65 | 66 | #define RB_ENABLE_CALLBACK_DEF(NAME, CALLBACK, GLFW_FUNC) \ 67 | static VALUE NAME (VALUE self, VALUE enabled) \ 68 | { \ 69 | if (RTEST(enabled)) { \ 70 | GLFW_FUNC ( rb_get_window(self), CALLBACK ); \ 71 | } else { \ 72 | GLFW_FUNC ( rb_get_window(self), NULL ); \ 73 | } \ 74 | return self; \ 75 | } 76 | 77 | 78 | /* 79 | * Initializes GLFW. Returns true on success, false on failure. 80 | * 81 | * call-seq: 82 | * init -> true or false 83 | * 84 | * Wraps glfwInit. 85 | */ 86 | static VALUE rb_glfw_init(VALUE self) 87 | { 88 | VALUE result = glfwInit() ? Qtrue : Qfalse; 89 | if (result == Qtrue) { 90 | glfwSetMonitorCallback(rb_glfw_monitor_callback); 91 | } 92 | return result; 93 | } 94 | 95 | 96 | 97 | 98 | /* 99 | * Terminates GLFW. 100 | * 101 | * Wraps glfwTerminate. 102 | */ 103 | static VALUE rb_glfw_terminate(VALUE self) 104 | { 105 | glfwTerminate(); 106 | return self; 107 | } 108 | 109 | 110 | 111 | /* 112 | * Returns GLFW's version in an array. 113 | * 114 | * call-seq: 115 | * version -> [major, minor, revision] 116 | * 117 | * Wraps glfwGetVersion. 118 | */ 119 | static VALUE rb_glfw_version(VALUE self) 120 | { 121 | int major = 0; 122 | int minor = 0; 123 | int revision = 0; 124 | glfwGetVersion(&major, &minor, &revision); 125 | return rb_ary_new3(3, INT2NUM(major), INT2NUM(minor), INT2NUM(revision)); 126 | } 127 | 128 | 129 | 130 | static void rb_glfw_error_callback(int error_code, const char *description) 131 | { 132 | VALUE lambda = rb_cvar_get(s_glfw_module, kRB_CVAR_GLFW_ERROR_CALLBACK); 133 | 134 | if (rb_obj_respond_to(lambda, kRB_CALL, 0)) { 135 | VALUE rb_description = rb_str_new2(description); 136 | VALUE rb_error_code = INT2FIX(error_code); 137 | OBJ_FREEZE(rb_description); 138 | OBJ_FREEZE(rb_error_code); 139 | rb_funcall(lambda, kRB_CALL, 2, rb_error_code, rb_description); 140 | } else { 141 | rb_raise(rb_eRuntimeError, "GLFW Error 0x%X: %s", error_code, description); 142 | } 143 | } 144 | 145 | 146 | 147 | /* 148 | * Gets an array of all currently connected monitors. 149 | * 150 | * call-seq: 151 | * monitors -> [Glfw::Monitor, ...] 152 | * 153 | * Wraps glfwGetMonitors. 154 | */ 155 | static VALUE rb_glfw_get_monitors(VALUE self) 156 | { 157 | long monitor_index = 0; 158 | int num_monitors = 0; 159 | GLFWmonitor **monitors = glfwGetMonitors(&num_monitors); 160 | VALUE monitors_out = Qnil; 161 | 162 | if (monitors) { 163 | monitors_out = rb_ary_new(); 164 | for (; monitor_index < num_monitors; ++monitor_index) { 165 | VALUE monitor = Data_Wrap_Struct(s_glfw_monitor_klass, 0, 0, monitors[monitor_index]); 166 | rb_obj_call_init(monitor, 0, 0); 167 | rb_ary_push(monitors_out, monitor); 168 | } 169 | } 170 | return monitors_out; 171 | } 172 | 173 | 174 | 175 | /* 176 | * Gets the primary monitor. 177 | * 178 | * call-seq: 179 | * primary_monitor -> Glfw::Monitor 180 | * 181 | * Wraps glfwGetPrimaryMonitor. 182 | */ 183 | static VALUE rb_glfw_get_primary_monitor(VALUE self) 184 | { 185 | GLFWmonitor *monitor = glfwGetPrimaryMonitor(); 186 | VALUE rb_monitor = Qnil; 187 | if (monitor != NULL) { 188 | rb_monitor = Data_Wrap_Struct(s_glfw_monitor_klass, 0, 0, monitor); 189 | rb_obj_call_init(rb_monitor, 0, 0); 190 | } 191 | return rb_monitor; 192 | } 193 | 194 | 195 | 196 | /* 197 | * Gets the monitor's position in screen-space. 198 | * 199 | * call-seq: 200 | * position -> [x, y] 201 | * 202 | * Wraps glfwGetMonitorPos. 203 | */ 204 | static VALUE rb_monitor_position(VALUE self) 205 | { 206 | GLFWmonitor *monitor = NULL; 207 | int xpos = 0; 208 | int ypos = 0; 209 | Data_Get_Struct(self, GLFWmonitor, monitor); 210 | glfwGetMonitorPos(monitor, &xpos, &ypos); 211 | return rb_ary_new3(2, INT2FIX(xpos), INT2FIX(ypos)); 212 | } 213 | 214 | 215 | 216 | /* 217 | * Gets the physical size of the monitor. 218 | * 219 | * call-seq: 220 | * physical_size -> [width, height] 221 | * 222 | * Wraps glfwGetMonitorPhysicalSize. 223 | */ 224 | static VALUE rb_monitor_physical_size(VALUE self) 225 | { 226 | GLFWmonitor *monitor = NULL; 227 | int width = 0; 228 | int height = 0; 229 | Data_Get_Struct(self, GLFWmonitor, monitor); 230 | glfwGetMonitorPhysicalSize(monitor, &width, &height); 231 | return rb_ary_new3(2, INT2FIX(width), INT2FIX(height)); 232 | } 233 | 234 | 235 | 236 | /* 237 | * Gets the name of the monitor. 238 | * 239 | * call-seq: 240 | * name -> String 241 | * 242 | * Wraps glfwGetMonitorName. 243 | */ 244 | static VALUE rb_monitor_name(VALUE self) 245 | { 246 | GLFWmonitor *monitor = NULL; 247 | const char *monitor_name = NULL; 248 | Data_Get_Struct(self, GLFWmonitor, monitor); 249 | monitor_name = glfwGetMonitorName(monitor); 250 | return monitor_name ? rb_str_new2(monitor_name) : Qnil; 251 | } 252 | 253 | 254 | 255 | static void rb_glfw_monitor_callback(GLFWmonitor *monitor, int message) 256 | { 257 | VALUE lambda = rb_cvar_get(s_glfw_module, kRB_CVAR_GLFW_MONITOR_CALLBACK); 258 | if (rb_obj_respond_to(lambda, kRB_CALL, 0)) { 259 | VALUE rb_monitor = Data_Wrap_Struct(s_glfw_monitor_klass, 0, 0, monitor); 260 | rb_obj_call_init(rb_monitor, 0, 0); 261 | rb_funcall(lambda, kRB_CALL, 2, rb_monitor, INT2FIX(message)); 262 | } 263 | } 264 | 265 | 266 | 267 | /* 268 | * The width of the video mode. 269 | * 270 | * call-seq: 271 | * width -> Fixed 272 | * 273 | * Wraps GLFWvidmode.width. 274 | */ 275 | static VALUE rb_videomode_width(VALUE self) 276 | { 277 | GLFWvidmode *mode = NULL; 278 | Data_Get_Struct(self, GLFWvidmode, mode); 279 | return INT2FIX(mode->width); 280 | } 281 | 282 | /* 283 | * The height of the video mode. 284 | * 285 | * call-seq: 286 | * height -> Fixed 287 | * 288 | * Wraps GLFWvidmode.height. 289 | */ 290 | static VALUE rb_videomode_height(VALUE self) 291 | { 292 | GLFWvidmode *mode = NULL; 293 | Data_Get_Struct(self, GLFWvidmode, mode); 294 | return INT2FIX(mode->height); 295 | } 296 | 297 | /* 298 | * The number of red bits in the video mode. 299 | * 300 | * call-seq: 301 | * red_bits -> Fixed 302 | * 303 | * Wraps GLFWvidmode.redBits. 304 | */ 305 | static VALUE rb_videomode_red_bits(VALUE self) 306 | { 307 | GLFWvidmode *mode = NULL; 308 | Data_Get_Struct(self, GLFWvidmode, mode); 309 | return INT2FIX(mode->redBits); 310 | } 311 | 312 | /* 313 | * The number of green bits in the video mode. 314 | * 315 | * call-seq: 316 | * green_bits -> Fixed 317 | * 318 | * Wraps GLFWvidmode.greenBits. 319 | */ 320 | static VALUE rb_videomode_green_bits(VALUE self) 321 | { 322 | GLFWvidmode *mode = NULL; 323 | Data_Get_Struct(self, GLFWvidmode, mode); 324 | return INT2FIX(mode->greenBits); 325 | } 326 | 327 | /* 328 | * The number of blue bits in the video mode. 329 | * 330 | * call-seq: 331 | * blue_bits -> Fixed 332 | * 333 | * Wraps GLFWvidmode.blueBits. 334 | */ 335 | static VALUE rb_videomode_blue_bits(VALUE self) 336 | { 337 | GLFWvidmode *mode = NULL; 338 | Data_Get_Struct(self, GLFWvidmode, mode); 339 | return INT2FIX(mode->blueBits); 340 | } 341 | 342 | /* 343 | * The video mode's refresh rate. 344 | * 345 | * call-seq: 346 | * refresh_rate -> Fixed 347 | * 348 | * Wraps GLFWvidmode.refreshRate. 349 | */ 350 | static VALUE rb_videomode_refresh_rate(VALUE self) 351 | { 352 | GLFWvidmode *mode = NULL; 353 | Data_Get_Struct(self, GLFWvidmode, mode); 354 | return INT2FIX(mode->refreshRate); 355 | } 356 | 357 | /* 358 | * Gets an array of all video modes associated with the monitor, sorted 359 | * ascending first by color depth and then the video mode's area 360 | * (width x height). 361 | * 362 | * call-seq: 363 | * video_mode -> [Glfw::VideoMode, ...] 364 | * 365 | * Wraps glfwGetVideoModes. 366 | */ 367 | static VALUE rb_monitor_video_modes(VALUE self) 368 | { 369 | GLFWmonitor *monitor = NULL; 370 | const GLFWvidmode *modes = NULL; 371 | VALUE rb_modes = Qnil; 372 | int num_modes = 0; 373 | int mode_index = 0; 374 | VALUE rb_mode = Qnil; 375 | GLFWvidmode *mode = NULL; 376 | 377 | Data_Get_Struct(self, GLFWmonitor, monitor); 378 | rb_modes = rb_ary_new(); 379 | modes = glfwGetVideoModes(monitor, &num_modes); 380 | 381 | for (; mode_index < num_modes; ++mode_index) { 382 | mode = ALLOC(GLFWvidmode); 383 | *mode = modes[mode_index]; 384 | rb_mode = Data_Wrap_Struct(s_glfw_videomode_klass, 0, free, mode); 385 | rb_obj_call_init(rb_mode, 0, 0); 386 | rb_ary_push(rb_modes, rb_mode); 387 | } 388 | return rb_modes; 389 | } 390 | 391 | 392 | 393 | /* 394 | * Gets the monitor's current video mode. 395 | * 396 | * call-seq: 397 | * video_mode -> Glfw::VideoMode 398 | * 399 | * Wraps glfwGetVideoMode. 400 | */ 401 | static VALUE rb_monitor_video_mode(VALUE self) 402 | { 403 | GLFWmonitor *monitor = NULL; 404 | GLFWvidmode *mode = NULL; 405 | VALUE rb_mode = Qnil; 406 | Data_Get_Struct(self, GLFWmonitor, monitor); 407 | mode = ALLOC(GLFWvidmode); 408 | *mode = *glfwGetVideoMode(monitor); 409 | rb_mode = Data_Wrap_Struct(s_glfw_videomode_klass, 0, free, mode); 410 | rb_obj_call_init(rb_mode, 0, 0); 411 | return rb_mode; 412 | } 413 | 414 | 415 | 416 | /* 417 | * Sets the monitor's gamma ramp to a 256-element ramp generated by the given 418 | * exponent. 419 | * 420 | * call-seq: 421 | * set_gamma(gamma) -> self 422 | * 423 | * Wraps glfwSetGamma. 424 | */ 425 | static VALUE rb_monitor_set_gamma(VALUE self, VALUE gamma) 426 | { 427 | GLFWmonitor *monitor = NULL; 428 | Data_Get_Struct(self, GLFWmonitor, monitor); 429 | glfwSetGamma(monitor, (float)NUM2DBL(gamma)); 430 | return self; 431 | } 432 | 433 | 434 | 435 | /* 436 | * Gets the monitor's gamma ramp and returns it as a hash of its red, green, and 437 | * blue gamma ramps. By default, this might be equal to 438 | * `{ :red => [], :green => [], :blue => []}`. Ramp values are in the range of 439 | * 0 through 65535, or the 0 through USHRT_MAX (in C). 440 | * 441 | * call-seq: 442 | * get_gamma_ramp -> { :red => [...], :green => [...], :blue => [...] } or nil 443 | * gamma_ramp = -> hash or nil 444 | * 445 | * Wraps glfwGetGammaRamp. 446 | */ 447 | static VALUE rb_monitor_get_gamma_ramp(VALUE self) 448 | { 449 | GLFWmonitor *monitor = NULL; 450 | const GLFWgammaramp *ramp = NULL; 451 | VALUE rb_gamma_hash, rb_red, rb_green, rb_blue; 452 | unsigned int ramp_index; 453 | unsigned int ramp_len; 454 | 455 | Data_Get_Struct(self, GLFWmonitor, monitor); 456 | ramp = glfwGetGammaRamp(monitor); 457 | 458 | if (ramp == NULL) { 459 | return Qnil; 460 | } 461 | ramp_len = ramp->size; 462 | 463 | rb_gamma_hash = rb_hash_new(); 464 | rb_red = rb_ary_new(); 465 | rb_green = rb_ary_new(); 466 | rb_blue = rb_ary_new(); 467 | 468 | for (ramp_index = 0; ramp_index < ramp_len; ++ramp_index) { 469 | rb_ary_push(rb_red, INT2NUM(ramp->red[ramp_index])); 470 | rb_ary_push(rb_green, INT2NUM(ramp->green[ramp_index])); 471 | rb_ary_push(rb_blue, INT2NUM(ramp->blue[ramp_index])); 472 | } 473 | 474 | rb_hash_aset(rb_gamma_hash, ID2SYM(kRB_RED), rb_red); 475 | rb_hash_aset(rb_gamma_hash, ID2SYM(kRB_GREEN), rb_green); 476 | rb_hash_aset(rb_gamma_hash, ID2SYM(kRB_BLUE), rb_blue); 477 | 478 | return rb_gamma_hash; 479 | } 480 | 481 | 482 | 483 | /* 484 | * Sets the monitor's gamma ramp with the ramps provided in the ramp hash. The 485 | * ramp hash must have arrays for :red, :green, and :blue keys. The arrays 486 | * should be the same length, otherwise the shortest array length will be used. 487 | * 488 | * Gamma ramps should be in the range of an usngiend short, so 0 through 65535 489 | * or USHRT_MAX. 490 | * 491 | * For example, to set a linear gamma ramp that is half as intense as what is 492 | * likely your default: 493 | * 494 | * ramp = (0 ... 32768).step(128).to_a 495 | * monitor.set_gamma_ramp({ :red => ramp, :green => ramp, :blue => ramp }) 496 | * 497 | * call-seq: 498 | * set_gamma_ramp(ramp) -> self 499 | * gamma_ramp = ramp -> self 500 | * 501 | * Wraps glfwSetGammaRamp. 502 | * 503 | */ 504 | static VALUE rb_monitor_set_gamma_ramp(VALUE self, VALUE ramp_hash) 505 | { 506 | GLFWmonitor *monitor = NULL; 507 | GLFWgammaramp ramp; 508 | VALUE rb_red, rb_green, rb_blue; 509 | unsigned int ramp_index = 0; 510 | unsigned int ramp_len = 0; 511 | unsigned short *ramp_buffer = NULL; 512 | 513 | if (!Q_IS_A(ramp_hash, rb_cHash)) { 514 | rb_raise(rb_eArgError, "ramp_hash must be a Hash"); 515 | } 516 | 517 | Data_Get_Struct(self, GLFWmonitor, monitor); 518 | 519 | rb_red = rb_hash_aref(ramp_hash, ID2SYM(kRB_RED)); 520 | rb_green = rb_hash_aref(ramp_hash, ID2SYM(kRB_GREEN)); 521 | rb_blue = rb_hash_aref(ramp_hash, ID2SYM(kRB_BLUE)); 522 | 523 | if (!(Q_IS_A(rb_red, rb_cArray) && Q_IS_A(rb_green, rb_cArray) && Q_IS_A(rb_blue, rb_cArray))) { 524 | rb_raise(rb_eArgError, "Ramp Hash must contain :red, :green, and :blue arrays"); 525 | } 526 | 527 | /* NOTE: loses precision */ 528 | ramp_len = (unsigned int)RARRAY_LEN(rb_red); 529 | if (RARRAY_LEN(rb_green) != ramp_len || RARRAY_LEN(rb_blue) != ramp_len) { 530 | rb_raise(rb_eArgError, "All ramps must have the same length"); 531 | } 532 | 533 | ramp_buffer = ALLOC_N(unsigned short, 3 * ramp_len); 534 | ramp.red = ramp_buffer; 535 | ramp.green = &ramp_buffer[ramp_len]; 536 | ramp.blue = &ramp_buffer[ramp_len * 2]; 537 | 538 | for (; ramp_index < ramp_len; ++ramp_index) { 539 | ramp.red[ramp_index] = (unsigned short)NUM2UINT(rb_ary_entry(rb_red, ramp_index)); 540 | ramp.green[ramp_index] = (unsigned short)NUM2UINT(rb_ary_entry(rb_green, ramp_index)); 541 | ramp.blue[ramp_index] = (unsigned short)NUM2UINT(rb_ary_entry(rb_blue, ramp_index)); 542 | } 543 | 544 | ramp.size = ramp_len; 545 | 546 | glfwSetGammaRamp(monitor, &ramp); 547 | 548 | free(ramp_buffer); 549 | 550 | return self; 551 | } 552 | 553 | 554 | 555 | /* 556 | * Sets the window hints to their default values. See GLFW 3 documentation for 557 | * details on what those values are. 558 | * 559 | * call-seq: 560 | * default_window_hints() -> self 561 | * 562 | * Wraps glfwDefaultWindowHints. 563 | */ 564 | static VALUE rb_window_default_window_hints(VALUE self) 565 | { 566 | glfwDefaultWindowHints(); 567 | return self; 568 | } 569 | 570 | 571 | 572 | /* 573 | * Sets a window hint to the given value. 574 | * 575 | * call-seq: 576 | * window_hint(target, hint) -> self 577 | * 578 | * Wraps glfwWindowHint. 579 | */ 580 | static VALUE rb_window_window_hint(VALUE self, VALUE target, VALUE hint) 581 | { 582 | glfwWindowHint(NUM2INT(target), NUM2INT(hint)); 583 | return self; 584 | } 585 | 586 | 587 | /* Auxiliary function for extracting a Glfw::Window object from a GLFWwindow. */ 588 | static VALUE rb_lookup_window(GLFWwindow *window) 589 | { 590 | if (window) { 591 | void *uptr = glfwGetWindowUserPointer(window); 592 | if (uptr) { 593 | return (VALUE)uptr; 594 | } 595 | } 596 | return Qnil; 597 | } 598 | 599 | /* And the opposite of rb_lookup_window */ 600 | static GLFWwindow *rb_get_window(VALUE rb_window) 601 | { 602 | GLFWwindow *window = NULL; 603 | if (RTEST(rb_window)) { 604 | ID ivar_window = kRB_IVAR_WINDOW_INTERNAL; 605 | VALUE rb_window_data = Qnil; 606 | if (RTEST((rb_window_data = rb_ivar_get(rb_window, ivar_window)))) { 607 | Data_Get_Struct(rb_window_data, GLFWwindow, window); 608 | } 609 | } 610 | return window; 611 | } 612 | 613 | /* 614 | * Creates a new window with the given parameters. If a shared window is 615 | * provided, the new window will use the context of the shared window. 616 | * 617 | * If GLFW fails to create the window or an error occurred, this function will 618 | * return nil. 619 | * 620 | * call-seq: 621 | * new(width, height, title='', monitor=nil, shared_window=nil) -> Glfw::Window or nil 622 | * 623 | * Wraps glfwCreateWindow. 624 | */ 625 | static VALUE rb_window_new(int argc, VALUE *argv, VALUE self) 626 | { 627 | ID ivar_window = kRB_IVAR_WINDOW_INTERNAL; 628 | VALUE rb_width, rb_height, rb_title, rb_monitor, rb_share; 629 | VALUE rb_window; 630 | VALUE rb_window_data; 631 | VALUE rb_windows; 632 | GLFWwindow *window = NULL; 633 | int width, height; 634 | const char *title = ""; 635 | GLFWmonitor *monitor = NULL; 636 | GLFWwindow *share = NULL; 637 | 638 | /* Grab arguments */ 639 | rb_scan_args(argc, argv, "23", &rb_width, &rb_height, &rb_title, &rb_monitor, &rb_share); 640 | 641 | width = NUM2INT(rb_width); 642 | height = NUM2INT(rb_height); 643 | 644 | if (RTEST(rb_title)) { 645 | if (rb_type(rb_title) != T_STRING) { 646 | rb_title = rb_any_to_s(rb_title); 647 | } 648 | title = StringValueCStr(rb_title); 649 | } 650 | 651 | if (Q_IS_A(rb_monitor, s_glfw_monitor_klass)) { 652 | Data_Get_Struct(rb_monitor, GLFWmonitor, monitor); 653 | } 654 | 655 | if (Q_IS_A(rb_share, s_glfw_window_klass)) { 656 | VALUE rb_shared_window = rb_ivar_get(rb_share, ivar_window); 657 | Data_Get_Struct(rb_shared_window, GLFWwindow, share); 658 | } 659 | 660 | /* Create GLFW window */ 661 | window = glfwCreateWindow(width, height, title, monitor, share); 662 | if (window == NULL) { 663 | return Qnil; 664 | } 665 | 666 | /* Allocate the window wrapper (only used to store the window pointer) */ 667 | rb_window_data = Data_Wrap_Struct(s_glfw_window_internal_klass, 0, 0, window); 668 | rb_obj_call_init(rb_window_data, 0, 0); 669 | 670 | /* Allocate the window */ 671 | rb_window = rb_obj_alloc(s_glfw_window_klass); 672 | 673 | rb_ivar_set(rb_window, ivar_window, rb_window_data); 674 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_KEY_CALLBACK, Qnil); 675 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_CHAR_CALLBACK, Qnil); 676 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_MOUSE_BUTTON_CALLBACK, Qnil); 677 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_CURSOR_POSITION_CALLBACK, Qnil); 678 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_CURSOR_ENTER_CALLBACK, Qnil); 679 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_SCROLL_CALLBACK, Qnil); 680 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_POSITION_CALLBACK, Qnil); 681 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_SIZE_CALLBACK, Qnil); 682 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_CLOSE_CALLBACK, Qnil); 683 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_REFRESH_CALLBACK, Qnil); 684 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_FOCUS_CALLBACK, Qnil); 685 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_ICONIFY_CALLBACK, Qnil); 686 | rb_ivar_set(rb_window, kRB_IVAR_WINDOW_FRAMEBUFFER_SIZE_CALLBACK, Qnil); 687 | 688 | glfwSetWindowUserPointer(window, (void *)rb_window); 689 | rb_obj_call_init(rb_window, 0, 0); 690 | 691 | /* Store the window so it can't go out of scope until explicitly destroyed. */ 692 | rb_windows = rb_cvar_get(self, kRB_CVAR_WINDOW_WINDOWS); 693 | rb_hash_aset(rb_windows, INT2FIX((int)window), rb_window); 694 | 695 | return rb_window; 696 | } 697 | 698 | 699 | 700 | /* 701 | * Destroys the window. 702 | * 703 | * Wraps glfwDestroyWindow. 704 | */ 705 | static VALUE rb_window_destroy(VALUE self) 706 | { 707 | VALUE rb_windows = Qnil; 708 | GLFWwindow *window = rb_get_window(self); 709 | if (window) { 710 | glfwDestroyWindow(window); 711 | rb_ivar_set(self, kRB_IVAR_WINDOW_INTERNAL, Qnil); 712 | rb_windows = rb_cvar_get(s_glfw_window_klass, kRB_CVAR_WINDOW_WINDOWS); 713 | rb_hash_delete(rb_windows, INT2FIX((int)window)); 714 | } 715 | return self; 716 | } 717 | 718 | 719 | 720 | /* 721 | * Gets the window's should-close flag. 722 | * 723 | * call-seq: 724 | * should_close? -> true or false 725 | * 726 | * Wraps glfwWindowShouldClose. 727 | */ 728 | static VALUE rb_window_should_close(VALUE self) 729 | { 730 | GLFWwindow *window = rb_get_window(self); 731 | return glfwWindowShouldClose(window) ? Qtrue : Qfalse; 732 | } 733 | 734 | 735 | 736 | /* 737 | * Sets the window's should-close flag. Ideally, the value provided should be 738 | * a boolean, though it is only tested for non-nil and -false status, so it can 739 | * be anything that would yield true for !!value. 740 | * 741 | * call-seq: 742 | * should_close=(value) -> value 743 | * should_close = value -> value 744 | * 745 | * Wraps glfwSetWindowShouldClose. 746 | */ 747 | static VALUE rb_window_set_should_close(VALUE self, VALUE value) 748 | { 749 | GLFWwindow *window = rb_get_window(self); 750 | glfwSetWindowShouldClose(window, RTEST(value) ? GL_TRUE : GL_FALSE); 751 | return value; 752 | } 753 | 754 | 755 | 756 | /* 757 | * Sets the window's title. 758 | * 759 | * call-seq: 760 | * title=(new_title) -> new_title 761 | * title = new_title -> new_title 762 | * 763 | * Wraps glfwSetWindowTitle. 764 | */ 765 | static VALUE rb_window_set_title(VALUE self, VALUE new_title) 766 | { 767 | glfwSetWindowTitle(rb_get_window(self), StringValueCStr(new_title)); 768 | return new_title; 769 | } 770 | 771 | 772 | 773 | /* 774 | * Gets the windows position. 775 | * 776 | * call-seq: 777 | * position -> [x, y] 778 | * 779 | * Wraps glfwGetWindowPos. 780 | */ 781 | static VALUE rb_window_get_position(VALUE self) 782 | { 783 | int xpos = 0; 784 | int ypos = 0; 785 | glfwGetWindowPos(rb_get_window(self), &xpos, &ypos); 786 | return rb_ary_new3(2, INT2FIX(xpos), INT2FIX(ypos)); 787 | } 788 | 789 | 790 | 791 | /* 792 | * Moves the window to a new location (sets its position). 793 | * 794 | * call-seq: 795 | * set_position(x, y) -> self 796 | * move(x, y) -> self 797 | * 798 | * Wraps glfwSetWindowPos. 799 | */ 800 | static VALUE rb_window_set_position(VALUE self, VALUE x, VALUE y) 801 | { 802 | glfwSetWindowPos(rb_get_window(self), NUM2INT(x), NUM2INT(y)); 803 | return self; 804 | } 805 | 806 | 807 | 808 | /* 809 | * Gets the window's size. 810 | * 811 | * call-seq: 812 | * size -> [width, height] 813 | * 814 | * Wraps glfwGetWindowSize. 815 | */ 816 | static VALUE rb_window_get_size(VALUE self) 817 | { 818 | int width = 0; 819 | int height = 0; 820 | glfwGetWindowSize(rb_get_window(self), &width, &height); 821 | return rb_ary_new3(2, INT2FIX(width), INT2FIX(height)); 822 | } 823 | 824 | 825 | 826 | /* 827 | * Sets the window's size. 828 | * 829 | * call-seq: 830 | * set_size(width, height) -> self 831 | * resize(width, height) -> self 832 | * 833 | * Wraps glfwSetWindowSize. 834 | */ 835 | static VALUE rb_window_set_size(VALUE self, VALUE width, VALUE height) 836 | { 837 | glfwSetWindowSize(rb_get_window(self), NUM2INT(width), NUM2INT(height)); 838 | return self; 839 | } 840 | 841 | 842 | 843 | /* 844 | * Gets the window context's framebuffer size. 845 | * 846 | * call-seq: 847 | * framebuffer_size -> [width, height] 848 | * 849 | * Wraps glfwGetFramebufferSize. 850 | */ 851 | static VALUE rb_window_get_framebuffer_size(VALUE self) 852 | { 853 | int width = 0; 854 | int height = 0; 855 | glfwGetFramebufferSize(rb_get_window(self), &width, &height); 856 | return rb_ary_new3(2, INT2FIX(width), INT2FIX(height)); 857 | } 858 | 859 | 860 | 861 | /* 862 | * Iconifies the window. 863 | * 864 | * Wraps glfwIconifyWindow. 865 | */ 866 | static VALUE rb_window_iconify(VALUE self) 867 | { 868 | glfwIconifyWindow(rb_get_window(self)); 869 | return self; 870 | } 871 | 872 | 873 | 874 | /* 875 | * Restores the window. 876 | * 877 | * Wraps glfwRestoreWindow. 878 | */ 879 | static VALUE rb_window_restore(VALUE self) 880 | { 881 | glfwRestoreWindow(rb_get_window(self)); 882 | return self; 883 | } 884 | 885 | 886 | 887 | /* 888 | * Shows the window. 889 | * 890 | * Wraps glfwShowWindow. 891 | */ 892 | static VALUE rb_window_show(VALUE self) 893 | { 894 | glfwShowWindow(rb_get_window(self)); 895 | return self; 896 | } 897 | 898 | 899 | 900 | /* 901 | * Hides the window. 902 | * 903 | * Wraps glfwHideWindow. 904 | */ 905 | static VALUE rb_window_hide(VALUE self) 906 | { 907 | glfwHideWindow(rb_get_window(self)); 908 | return self; 909 | } 910 | 911 | 912 | 913 | /* 914 | * Gets the window's monitor. 915 | * 916 | * call-seq: 917 | * monitor -> Glfw::Monitor 918 | * 919 | * Wraps glfwGetWindowMonitor. 920 | */ 921 | static VALUE rb_window_get_monitor(VALUE self) 922 | { 923 | GLFWmonitor *monitor = glfwGetWindowMonitor(rb_get_window(self)); 924 | VALUE rb_monitor = Qnil; 925 | if (monitor != NULL) { 926 | /* windowed mode */ 927 | Data_Wrap_Struct(s_glfw_monitor_klass, 0, 0, monitor); 928 | rb_obj_call_init(rb_monitor, 0, 0); 929 | } 930 | return rb_monitor; 931 | } 932 | 933 | 934 | 935 | static void rb_window_window_position_callback(GLFWwindow *window, int x, int y) 936 | { 937 | VALUE rb_window = rb_lookup_window(window); 938 | if (RTEST(rb_window)) { 939 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_POSITION_CALLBACK); 940 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 941 | rb_funcall(rb_func, kRB_CALL, 3, rb_window, INT2FIX(x), INT2FIX(y)); 942 | } 943 | } 944 | } 945 | 946 | RB_ENABLE_CALLBACK_DEF(rb_window_set_window_position_callback, rb_window_window_position_callback, glfwSetWindowPosCallback); 947 | 948 | 949 | 950 | static void rb_window_window_size_callback(GLFWwindow *window, int width, int height) 951 | { 952 | VALUE rb_window = rb_lookup_window(window); 953 | if (RTEST(rb_window)) { 954 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_SIZE_CALLBACK); 955 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 956 | rb_funcall(rb_func, kRB_CALL, 3, rb_window, INT2FIX(width), INT2FIX(height)); 957 | } 958 | } 959 | } 960 | 961 | RB_ENABLE_CALLBACK_DEF(rb_window_set_window_size_callback, rb_window_window_size_callback, glfwSetWindowSizeCallback); 962 | 963 | 964 | 965 | static void rb_window_close_callback(GLFWwindow *window) 966 | { 967 | VALUE rb_window = rb_lookup_window(window); 968 | if (RTEST(rb_window)) { 969 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_CLOSE_CALLBACK); 970 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 971 | rb_funcall(rb_func, kRB_CALL, 1, rb_window); 972 | } 973 | } 974 | } 975 | 976 | RB_ENABLE_CALLBACK_DEF(rb_window_set_close_callback, rb_window_close_callback, glfwSetWindowCloseCallback); 977 | 978 | 979 | 980 | static void rb_window_refresh_callback(GLFWwindow *window) 981 | { 982 | VALUE rb_window = rb_lookup_window(window); 983 | if (RTEST(rb_window)) { 984 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_REFRESH_CALLBACK); 985 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 986 | rb_funcall(rb_func, kRB_CALL, 1, rb_window); 987 | } 988 | } 989 | } 990 | 991 | RB_ENABLE_CALLBACK_DEF(rb_window_set_refresh_callback, rb_window_refresh_callback, glfwSetWindowRefreshCallback); 992 | 993 | 994 | 995 | static void rb_window_focus_callback(GLFWwindow *window, int focused) 996 | { 997 | VALUE rb_window = rb_lookup_window(window); 998 | if (RTEST(rb_window)) { 999 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_FOCUS_CALLBACK); 1000 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 1001 | rb_funcall(rb_func, kRB_CALL, 2, rb_window, focused ? Qtrue : Qfalse); 1002 | } 1003 | } 1004 | } 1005 | 1006 | RB_ENABLE_CALLBACK_DEF(rb_window_set_focus_callback, rb_window_focus_callback, glfwSetWindowFocusCallback); 1007 | 1008 | 1009 | 1010 | static void rb_window_iconify_callback(GLFWwindow *window, int iconified) 1011 | { 1012 | VALUE rb_window = rb_lookup_window(window); 1013 | if (RTEST(rb_window)) { 1014 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_ICONIFY_CALLBACK); 1015 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 1016 | rb_funcall(rb_func, kRB_CALL, 2, rb_window, iconified ? Qtrue : Qfalse); 1017 | } 1018 | } 1019 | } 1020 | 1021 | RB_ENABLE_CALLBACK_DEF(rb_window_set_iconify_callback, rb_window_iconify_callback, glfwSetWindowIconifyCallback); 1022 | 1023 | 1024 | 1025 | static void rb_window_fbsize_callback(GLFWwindow *window, int width, int height) 1026 | { 1027 | VALUE rb_window = rb_lookup_window(window); 1028 | if (RTEST(rb_window)) { 1029 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_FRAMEBUFFER_SIZE_CALLBACK); 1030 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 1031 | rb_funcall(rb_func, kRB_CALL, 3, rb_window, INT2FIX(width), INT2FIX(height)); 1032 | } 1033 | } 1034 | } 1035 | 1036 | RB_ENABLE_CALLBACK_DEF(rb_window_set_fbsize_callback, rb_window_fbsize_callback, glfwSetFramebufferSizeCallback); 1037 | 1038 | 1039 | 1040 | /* 1041 | * Polls for events without blocking until an event occurs. 1042 | * 1043 | * Wraps glfwPollEvents. 1044 | * 1045 | * This would likely be called at the beginning of your main loop, like so: 1046 | * 1047 | * loop { 1048 | * Glfw.poll_events() 1049 | * 1050 | * # ... 1051 | * } 1052 | */ 1053 | static VALUE rb_glfw_poll_events(VALUE self) 1054 | { 1055 | glfwPollEvents(); 1056 | return self; 1057 | } 1058 | 1059 | 1060 | 1061 | /* 1062 | * Polls for events. Blocks until an event occurs. 1063 | * 1064 | * Wraps glfwWaitEvents. 1065 | * 1066 | * This would likely be called at the beginning of your main loop, like so: 1067 | * 1068 | * loop { 1069 | * Glfw.wait_events() 1070 | * 1071 | * # ... 1072 | * } 1073 | */ 1074 | static VALUE rb_glfw_wait_events(VALUE self) 1075 | { 1076 | glfwWaitEvents(); 1077 | return self; 1078 | } 1079 | 1080 | 1081 | 1082 | /* 1083 | * Gets the current value for the given input mode. 1084 | * 1085 | * call-seq: 1086 | * get_input_mode(mode) -> Fixed 1087 | * 1088 | * Wraps glfwGetInputMode. 1089 | */ 1090 | static VALUE rb_window_get_input_mode(VALUE self, VALUE mode) 1091 | { 1092 | return INT2FIX(glfwGetInputMode(rb_get_window(self), NUM2INT(mode))); 1093 | } 1094 | 1095 | 1096 | 1097 | /* 1098 | * Sets the value of the given input mode. 1099 | * 1100 | * call-seq: 1101 | * set_input_mode(mode, value) -> self 1102 | * 1103 | * Wraps glfwSetInputMode. 1104 | */ 1105 | static VALUE rb_window_set_input_mode(VALUE self, VALUE mode, VALUE value) 1106 | { 1107 | glfwSetInputMode(rb_get_window(self), NUM2INT(mode), NUM2INT(value)); 1108 | return self; 1109 | } 1110 | 1111 | 1112 | 1113 | /* 1114 | * Gets the last-reported state of the given keyboard key for the window. 1115 | * 1116 | * call-seq: 1117 | * key(key) -> Fixed 1118 | * 1119 | * Wraps glfwGetKey. 1120 | */ 1121 | static VALUE rb_window_get_key(VALUE self, VALUE key) 1122 | { 1123 | return INT2FIX(glfwGetKey(rb_get_window(self), NUM2INT(key))); 1124 | } 1125 | 1126 | 1127 | 1128 | /* 1129 | * Gets the last-reported state of the given mouse button for the window. 1130 | * 1131 | * call-seq: 1132 | * mouse_button(key) -> Fixed 1133 | * 1134 | * Wraps glfwGetMouseButton. 1135 | */ 1136 | static VALUE rb_window_get_mouse_button(VALUE self, VALUE button) 1137 | { 1138 | return INT2FIX(glfwGetMouseButton(rb_get_window(self), NUM2INT(button))); 1139 | } 1140 | 1141 | 1142 | 1143 | /* 1144 | * Gets the last-reported cursor position in the window. 1145 | * 1146 | * call-seq: 1147 | * cursor_pos -> [x, y] 1148 | * 1149 | * Wraps glfwGetCursorPos. 1150 | */ 1151 | static VALUE rb_window_get_cursor_pos(VALUE self) 1152 | { 1153 | double xpos = 0; 1154 | double ypos = 0; 1155 | glfwGetCursorPos(rb_get_window(self), &xpos, &ypos); 1156 | return rb_ary_new3(2, rb_float_new(xpos), rb_float_new(ypos)); 1157 | } 1158 | 1159 | 1160 | 1161 | /* 1162 | * Sets the position of the mouse cursor relative to the client area of the 1163 | * window. If the window isn't focused at the time of the call, this silently 1164 | * fails. 1165 | * 1166 | * call-seq: 1167 | * set_cursor_pos(x, y) -> self 1168 | * 1169 | * Wraps glfwSetCursorPos. 1170 | */ 1171 | static VALUE rb_window_set_cursor_pos(VALUE self, VALUE x, VALUE y) 1172 | { 1173 | glfwSetCursorPos(rb_get_window(self), NUM2DBL(x), NUM2DBL(y)); 1174 | return self; 1175 | } 1176 | 1177 | 1178 | 1179 | static void rb_window_key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) 1180 | { 1181 | VALUE rb_window = rb_lookup_window(window); 1182 | if (RTEST(rb_window)) { 1183 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_KEY_CALLBACK); 1184 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 1185 | rb_funcall(rb_func, kRB_CALL, 5, rb_window, INT2FIX(key), INT2FIX(scancode), INT2FIX(action), INT2FIX(mods)); 1186 | } 1187 | } 1188 | } 1189 | 1190 | RB_ENABLE_CALLBACK_DEF(rb_window_set_key_callback, rb_window_key_callback, glfwSetKeyCallback); 1191 | 1192 | 1193 | 1194 | static void rb_window_char_callback(GLFWwindow *window, unsigned int code) 1195 | { 1196 | VALUE rb_window = rb_lookup_window(window); 1197 | if (RTEST(rb_window)) { 1198 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_CHAR_CALLBACK); 1199 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 1200 | rb_funcall(rb_func, kRB_CALL, 2, rb_window, UINT2NUM(code)); 1201 | } 1202 | } 1203 | } 1204 | 1205 | RB_ENABLE_CALLBACK_DEF(rb_window_set_char_callback, rb_window_char_callback, glfwSetCharCallback); 1206 | 1207 | 1208 | 1209 | 1210 | static void rb_window_mouse_button_callback(GLFWwindow *window, int button, int action, int mods) 1211 | { 1212 | VALUE rb_window = rb_lookup_window(window); 1213 | if (RTEST(rb_window)) { 1214 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_MOUSE_BUTTON_CALLBACK); 1215 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 1216 | rb_funcall(rb_func, kRB_CALL, 4, rb_window, INT2FIX(button), INT2FIX(action), INT2FIX(mods)); 1217 | } 1218 | } 1219 | } 1220 | 1221 | RB_ENABLE_CALLBACK_DEF(rb_window_set_mouse_button_callback, rb_window_mouse_button_callback, glfwSetMouseButtonCallback); 1222 | 1223 | 1224 | 1225 | static void rb_window_cursor_position_callback(GLFWwindow *window, double x, double y) 1226 | { 1227 | VALUE rb_window = rb_lookup_window(window); 1228 | if (RTEST(rb_window)) { 1229 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_CURSOR_POSITION_CALLBACK); 1230 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 1231 | rb_funcall(rb_func, kRB_CALL, 3, rb_window, rb_float_new(x), rb_float_new(y)); 1232 | } 1233 | } 1234 | } 1235 | 1236 | RB_ENABLE_CALLBACK_DEF(rb_window_set_cursor_position_callback, rb_window_cursor_position_callback, glfwSetCursorPosCallback); 1237 | 1238 | 1239 | 1240 | static void rb_window_cursor_enter_callback(GLFWwindow *window, int entered) 1241 | { 1242 | VALUE rb_window = rb_lookup_window(window); 1243 | if (RTEST(rb_window)) { 1244 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_CURSOR_ENTER_CALLBACK); 1245 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 1246 | rb_funcall(rb_func, kRB_CALL, 2, rb_window, entered ? Qtrue : Qfalse); 1247 | } 1248 | } 1249 | } 1250 | 1251 | RB_ENABLE_CALLBACK_DEF(rb_window_set_cursor_enter_callback, rb_window_cursor_enter_callback, glfwSetCursorEnterCallback); 1252 | 1253 | 1254 | 1255 | static void rb_window_scroll_callback(GLFWwindow *window, double x, double y) 1256 | { 1257 | VALUE rb_window = rb_lookup_window(window); 1258 | if (RTEST(rb_window)) { 1259 | VALUE rb_func = rb_ivar_get(rb_window, kRB_IVAR_WINDOW_SCROLL_CALLBACK); 1260 | if (rb_obj_respond_to(rb_func, kRB_CALL, 0)) { 1261 | rb_funcall(rb_func, kRB_CALL, 3, rb_window, rb_float_new(x), rb_float_new(y)); 1262 | } 1263 | } 1264 | } 1265 | 1266 | RB_ENABLE_CALLBACK_DEF(rb_window_set_scroll_callback, rb_window_scroll_callback, glfwSetScrollCallback); 1267 | 1268 | 1269 | 1270 | 1271 | /* 1272 | * Returns whether the given joystick is present. 1273 | * 1274 | * call-seq: 1275 | * joystick_present?(joystick) -> true or false 1276 | * 1277 | * Wraps glfwJoystickPresent. 1278 | */ 1279 | static VALUE rb_glfw_joystick_present(VALUE self, VALUE joystick) 1280 | { 1281 | return glfwJoystickPresent(NUM2INT(joystick)) ? Qtrue : Qfalse; 1282 | } 1283 | 1284 | 1285 | 1286 | /* 1287 | * Gets the values of all axes of the given joystick. Returns nil if the 1288 | * joystick isn't present. See #joystick_present?. 1289 | * 1290 | * call-seq: 1291 | * joystick_axes(joystick) -> [Float, ...] or nil 1292 | * 1293 | * Wraps glfwGetJoystickAxes. 1294 | */ 1295 | static VALUE rb_glfw_get_joystick_axes(VALUE self, VALUE joystick) 1296 | { 1297 | VALUE rb_axes = Qnil; 1298 | int num_axes = 0; 1299 | int axis_index = 0; 1300 | const float *axes = glfwGetJoystickAxes(NUM2INT(joystick), &num_axes); 1301 | if (num_axes > 0) { 1302 | rb_axes = rb_ary_new(); 1303 | for (; axis_index < num_axes; ++axis_index) { 1304 | rb_ary_push(rb_axes, rb_float_new(axes[axis_index])); 1305 | } 1306 | } 1307 | return rb_axes; 1308 | } 1309 | 1310 | 1311 | 1312 | /* 1313 | * Gets the button values of the given joystick. Returns nil if the joystick 1314 | * isn't present. See #joystick_present?. 1315 | * 1316 | * call-seq: 1317 | * joystick_buttons(joystick) -> [Fixed, ...] or nil 1318 | * 1319 | * Wraps glfwGetJoystickButtons. 1320 | */ 1321 | static VALUE rb_glfw_get_joystick_buttons(VALUE self, VALUE joystick) 1322 | { 1323 | VALUE rb_buttons = Qnil; 1324 | int num_buttons = 0; 1325 | int button_index = 0; 1326 | const unsigned char *buttons = glfwGetJoystickButtons(NUM2INT(joystick), &num_buttons); 1327 | if (num_buttons > 0) { 1328 | rb_buttons = rb_ary_new(); 1329 | for (; button_index < num_buttons; ++button_index) { 1330 | rb_ary_push(rb_buttons, rb_float_new(INT2FIX((int)buttons[button_index]))); 1331 | } 1332 | } 1333 | return rb_buttons; 1334 | } 1335 | 1336 | 1337 | 1338 | /* 1339 | * Returns the name of the given joystick. 1340 | * 1341 | * call-seq: 1342 | * joystick_name(joystick) -> String 1343 | * 1344 | * Wraps glfwGetJoystickName. 1345 | */ 1346 | static VALUE rb_glfw_get_joystick_name(VALUE self, VALUE joystick) 1347 | { 1348 | const char *joy_name = glfwGetJoystickName(NUM2INT(joystick)); 1349 | if (joy_name) { 1350 | return rb_str_new2(joy_name); 1351 | } else { 1352 | return Qnil; 1353 | } 1354 | } 1355 | 1356 | 1357 | 1358 | /* 1359 | * Sets the system clipboard string. The window this is set for will own the 1360 | * given string. 1361 | * 1362 | * call-seq: 1363 | * clipboard_string=(string) -> String 1364 | * clipboard_string = string -> String 1365 | * 1366 | * Wraps glfwSetClipboardString. 1367 | */ 1368 | static VALUE rb_window_set_clipboard_string(VALUE self, VALUE string) 1369 | { 1370 | glfwSetClipboardString(rb_get_window(self), StringValueCStr(string)); 1371 | return string; 1372 | } 1373 | 1374 | 1375 | 1376 | /* 1377 | * Gets the system clipboard's contents as a string. The window this is called 1378 | * from will request the clipboard contents. 1379 | * 1380 | * call-seq: 1381 | * clipboard_string() -> String 1382 | * 1383 | * Wraps glfwGetClipboardString. 1384 | */ 1385 | static VALUE rb_window_get_clipboard_string(VALUE self) 1386 | { 1387 | return rb_str_new2(glfwGetClipboardString(rb_get_window(self))); 1388 | } 1389 | 1390 | 1391 | 1392 | /* 1393 | * Gets the current time in seconds. The returned time is relative to the time 1394 | * since GLFW was initialized unless the time has been set using #timer=. 1395 | * 1396 | * call-seq: 1397 | * time -> Float 1398 | * 1399 | * Wraps glfwGetTime. 1400 | */ 1401 | static VALUE rb_glfw_get_time(VALUE self) 1402 | { 1403 | return rb_float_new(glfwGetTime()); 1404 | } 1405 | 1406 | 1407 | 1408 | /* 1409 | * Sets the current time in seconds. If set, GLFW will continue measuring time 1410 | * elapsed from that time forward. 1411 | * 1412 | * In most cases, you will not need to use this. 1413 | * 1414 | * call-seq: 1415 | * time = Float 1416 | * 1417 | * Wraps glfwSetTime. 1418 | */ 1419 | static VALUE rb_glfw_set_time(VALUE self, VALUE time_) 1420 | { 1421 | glfwSetTime(NUM2DBL(time_)); 1422 | return time_; 1423 | } 1424 | 1425 | 1426 | 1427 | /* 1428 | * Makes the window's GL context current. You will need to call this before 1429 | * calling any OpenGL functions. See also ::unset_context to unset a context. 1430 | * 1431 | * Wraps glfwMakeContextCurrent(window). 1432 | * 1433 | * # Good 1434 | * window.make_context_current() 1435 | * Gl.glClear(Gl::GL_COLOR_BUFFER_BIT) 1436 | * 1437 | * # Bad 1438 | * Gl.glClear(Gl::GL_COLOR_BUFFER_BIT) 1439 | * window.make_context_current() 1440 | * 1441 | * Remember to make a window's context current before calling any OpenGL 1442 | * functions. A window's GL context may only be current in one thread at a time. 1443 | */ 1444 | static VALUE rb_window_make_context_current(VALUE self) 1445 | { 1446 | glfwMakeContextCurrent(rb_get_window(self)); 1447 | return self; 1448 | } 1449 | 1450 | 1451 | 1452 | /* 1453 | * Unsets the current GL context. 1454 | * 1455 | * Wraps glfwMakeContextCurrent(NULL). 1456 | */ 1457 | static VALUE rb_window_unset_context(VALUE self) 1458 | { 1459 | glfwMakeContextCurrent(NULL); 1460 | return self; 1461 | } 1462 | 1463 | 1464 | 1465 | /* 1466 | * Gets the window for the current GL context in this thread. 1467 | * 1468 | * call-seq: 1469 | * current_context() -> Glfw::Window 1470 | * 1471 | * Wraps glfwGetCurrentContext. 1472 | */ 1473 | static VALUE rb_window_get_current_context(VALUE self) 1474 | { 1475 | return rb_lookup_window(glfwGetCurrentContext()); 1476 | } 1477 | 1478 | 1479 | 1480 | /* 1481 | * Swaps the front and back buffers for the window. You will typically call this 1482 | * at the end of your drawing routines. 1483 | * 1484 | * Wraps glfwSwapBuffers. 1485 | * 1486 | * loop { 1487 | * Glfw.poll_events() 1488 | * 1489 | * # ... 1490 | * 1491 | * window.swap_buffers() 1492 | * } 1493 | */ 1494 | static VALUE rb_window_swap_buffers(VALUE self) 1495 | { 1496 | glfwSwapBuffers(rb_get_window(self)); 1497 | return self; 1498 | } 1499 | 1500 | 1501 | 1502 | /* 1503 | * Sets the swap interval for the current context. 1504 | * (See Glfw::Window#make_context_current) 1505 | * 1506 | * call-seq: 1507 | * swap_interval=(interval) -> self 1508 | * swap_interval = interval -> self 1509 | * 1510 | * Wraps glfwSwapInterval. 1511 | */ 1512 | static VALUE rb_glfw_swap_interval(VALUE self, VALUE interval) 1513 | { 1514 | glfwSwapInterval(NUM2INT(interval)); 1515 | return self; 1516 | } 1517 | 1518 | 1519 | 1520 | /* 1521 | * Retursn whether a given OpenGL or context creation API extension is supported 1522 | * by the current context. 1523 | * (See Glfw::Window#make_context_current) 1524 | * 1525 | * Bear in mind that this function does not cache its results, so calls may be 1526 | * expensive. If you find yourself using it, consider caching the results 1527 | * yourself. 1528 | * 1529 | * call-seq: 1530 | * extension_supported?(extension) -> true or false 1531 | * 1532 | * Wraps glfwExtensionSupported. 1533 | */ 1534 | static VALUE rb_glfw_extension_supported(VALUE self, VALUE extension) 1535 | { 1536 | return glfwExtensionSupported(StringValueCStr(extension)) ? Qtrue : Qfalse; 1537 | } 1538 | 1539 | 1540 | 1541 | void Init_glfw3(void) 1542 | { 1543 | kRB_IVAR_WINDOW_INTERNAL = rb_intern(kRB_IVAR_WINDOW_INTERNAL_NAME); 1544 | kRB_IVAR_WINDOW_KEY_CALLBACK = rb_intern(kRB_IVAR_WINDOW_KEY_CALLBACK_NAME); 1545 | kRB_IVAR_WINDOW_CHAR_CALLBACK = rb_intern(kRB_IVAR_WINDOW_CHAR_CALLBACK_NAME); 1546 | kRB_IVAR_WINDOW_MOUSE_BUTTON_CALLBACK = rb_intern(kRB_IVAR_WINDOW_MOUSE_BUTTON_CALLBACK_NAME); 1547 | kRB_IVAR_WINDOW_CURSOR_POSITION_CALLBACK = rb_intern(kRB_IVAR_WINDOW_CURSOR_POSITION_CALLBACK_NAME); 1548 | kRB_IVAR_WINDOW_CURSOR_ENTER_CALLBACK = rb_intern(kRB_IVAR_WINDOW_CURSOR_ENTER_CALLBACK_NAME); 1549 | kRB_IVAR_WINDOW_SCROLL_CALLBACK = rb_intern(kRB_IVAR_WINDOW_SCROLL_CALLBACK_NAME); 1550 | kRB_IVAR_WINDOW_POSITION_CALLBACK = rb_intern(kRB_IVAR_WINDOW_POSITION_CALLBACK_NAME); 1551 | kRB_IVAR_WINDOW_SIZE_CALLBACK = rb_intern(kRB_IVAR_WINDOW_SIZE_CALLBACK_NAME); 1552 | kRB_IVAR_WINDOW_CLOSE_CALLBACK = rb_intern(kRB_IVAR_WINDOW_CLOSE_CALLBACK_NAME); 1553 | kRB_IVAR_WINDOW_REFRESH_CALLBACK = rb_intern(kRB_IVAR_WINDOW_REFRESH_CALLBACK_NAME); 1554 | kRB_IVAR_WINDOW_FOCUS_CALLBACK = rb_intern(kRB_IVAR_WINDOW_FOCUS_CALLBACK_NAME); 1555 | kRB_IVAR_WINDOW_ICONIFY_CALLBACK = rb_intern(kRB_IVAR_WINDOW_ICONIFY_CALLBACK_NAME); 1556 | kRB_IVAR_WINDOW_FRAMEBUFFER_SIZE_CALLBACK = rb_intern(kRB_IVAR_WINDOW_FRAMEBUFFER_SIZE_CALLBACK_NAME); 1557 | kRB_CVAR_WINDOW_WINDOWS = rb_intern(kRB_CVAR_WINDOW_WINDOWS_NAME); 1558 | kRB_CVAR_GLFW_ERROR_CALLBACK = rb_intern(kRB_CVAR_GLFW_ERROR_CALLBACK_NAME); 1559 | kRB_CVAR_GLFW_MONITOR_CALLBACK = rb_intern(kRB_CVAR_GLFW_MONITOR_CALLBACK_NAME); 1560 | kRB_CALL = rb_intern(kRB_CALL_NAME); 1561 | kRB_RED = rb_intern(kRB_RED_NAME); 1562 | kRB_GREEN = rb_intern(kRB_GREEN_NAME); 1563 | kRB_BLUE = rb_intern(kRB_BLUE_NAME); 1564 | 1565 | s_glfw_module = rb_define_module("Glfw"); 1566 | s_glfw_monitor_klass = rb_define_class_under(s_glfw_module, "Monitor", rb_cData); 1567 | s_glfw_window_klass = rb_define_class_under(s_glfw_module, "Window", rb_cObject); 1568 | s_glfw_window_internal_klass = rb_define_class_under(s_glfw_window_klass, "InternalWindow", rb_cData); 1569 | s_glfw_videomode_klass = rb_define_class_under(s_glfw_module, "VideoMode", rb_cData); 1570 | 1571 | /* Glfw::Monitor */ 1572 | rb_define_singleton_method(s_glfw_monitor_klass, "monitors", rb_glfw_get_monitors, 0); 1573 | rb_define_singleton_method(s_glfw_monitor_klass, "primary_monitor", rb_glfw_get_primary_monitor, 0); 1574 | rb_define_method(s_glfw_monitor_klass, "name", rb_monitor_name, 0); 1575 | rb_define_method(s_glfw_monitor_klass, "position", rb_monitor_position, 0); 1576 | rb_define_method(s_glfw_monitor_klass, "physical_size", rb_monitor_physical_size, 0); 1577 | rb_define_method(s_glfw_monitor_klass, "video_modes", rb_monitor_video_modes, 0); 1578 | rb_define_method(s_glfw_monitor_klass, "video_mode", rb_monitor_video_mode, 0); 1579 | rb_define_method(s_glfw_monitor_klass, "set_gamma", rb_monitor_set_gamma, 1); 1580 | rb_define_method(s_glfw_monitor_klass, "set_gamma_ramp", rb_monitor_set_gamma_ramp, 1); 1581 | rb_define_method(s_glfw_monitor_klass, "get_gamma_ramp", rb_monitor_get_gamma_ramp, 0); 1582 | 1583 | /* Glfw::VideoMode */ 1584 | rb_define_method(s_glfw_videomode_klass, "width", rb_videomode_width, 0); 1585 | rb_define_method(s_glfw_videomode_klass, "height", rb_videomode_height, 0); 1586 | rb_define_method(s_glfw_videomode_klass, "red_bits", rb_videomode_red_bits, 0); 1587 | rb_define_method(s_glfw_videomode_klass, "green_bits", rb_videomode_green_bits, 0); 1588 | rb_define_method(s_glfw_videomode_klass, "blue_bits", rb_videomode_blue_bits, 0); 1589 | rb_define_method(s_glfw_videomode_klass, "refresh_rate", rb_videomode_refresh_rate, 0); 1590 | 1591 | /* Glfw::Window */ 1592 | rb_define_singleton_method(s_glfw_window_klass, "new", rb_window_new, -1); 1593 | rb_define_singleton_method(s_glfw_window_klass, "window_hint", rb_window_window_hint, 2); 1594 | rb_define_singleton_method(s_glfw_window_klass, "default_window_hints", rb_window_default_window_hints, 0); 1595 | rb_define_singleton_method(s_glfw_window_klass, "unset_context", rb_window_unset_context, 0); 1596 | rb_define_singleton_method(s_glfw_window_klass, "current_context", rb_window_get_current_context, 0); 1597 | rb_define_method(s_glfw_window_klass, "destroy", rb_window_destroy, 0); 1598 | rb_define_method(s_glfw_window_klass, "get_should_close", rb_window_should_close, 0); 1599 | rb_define_method(s_glfw_window_klass, "set_should_close", rb_window_set_should_close, 1); 1600 | rb_define_method(s_glfw_window_klass, "make_context_current", rb_window_make_context_current, 0); 1601 | rb_define_method(s_glfw_window_klass, "swap_buffers", rb_window_swap_buffers, 0); 1602 | rb_define_method(s_glfw_window_klass, "title=", rb_window_set_title, 1); 1603 | rb_define_method(s_glfw_window_klass, "get_position", rb_window_get_position, 0); 1604 | rb_define_method(s_glfw_window_klass, "set_position", rb_window_set_position, 2); 1605 | rb_define_method(s_glfw_window_klass, "get_size", rb_window_get_size, 0); 1606 | rb_define_method(s_glfw_window_klass, "set_size", rb_window_set_size, 2); 1607 | rb_define_method(s_glfw_window_klass, "framebuffer_size", rb_window_get_framebuffer_size, 0); 1608 | rb_define_method(s_glfw_window_klass, "iconify", rb_window_iconify, 0); 1609 | rb_define_method(s_glfw_window_klass, "restore", rb_window_restore, 0); 1610 | rb_define_method(s_glfw_window_klass, "show", rb_window_show, 0); 1611 | rb_define_method(s_glfw_window_klass, "hide", rb_window_hide, 0); 1612 | rb_define_method(s_glfw_window_klass, "monitor", rb_window_get_monitor, 0); 1613 | rb_define_method(s_glfw_window_klass, "set_window_position_callback__", rb_window_set_window_position_callback, 1); 1614 | rb_define_method(s_glfw_window_klass, "set_window_size_callback__", rb_window_set_window_size_callback, 1); 1615 | rb_define_method(s_glfw_window_klass, "set_close_callback__", rb_window_set_close_callback, 1); 1616 | rb_define_method(s_glfw_window_klass, "set_refresh_callback__", rb_window_set_refresh_callback, 1); 1617 | rb_define_method(s_glfw_window_klass, "set_focus_callback__", rb_window_set_focus_callback, 1); 1618 | rb_define_method(s_glfw_window_klass, "set_iconify_callback__", rb_window_set_iconify_callback, 1); 1619 | rb_define_method(s_glfw_window_klass, "set_fbsize_callback__", rb_window_set_fbsize_callback, 1); 1620 | rb_define_method(s_glfw_window_klass, "get_input_mode", rb_window_get_input_mode, 1); 1621 | rb_define_method(s_glfw_window_klass, "set_input_mode", rb_window_set_input_mode, 2); 1622 | rb_define_method(s_glfw_window_klass, "key", rb_window_get_key, 1); 1623 | rb_define_method(s_glfw_window_klass, "mouse_button", rb_window_get_mouse_button, 1); 1624 | rb_define_method(s_glfw_window_klass, "get_cursor_pos", rb_window_get_cursor_pos, 0); 1625 | rb_define_method(s_glfw_window_klass, "set_cursor_pos", rb_window_set_cursor_pos, 2); 1626 | rb_define_method(s_glfw_window_klass, "set_key_callback__", rb_window_set_key_callback, 1); 1627 | rb_define_method(s_glfw_window_klass, "set_char_callback__", rb_window_set_char_callback, 1); 1628 | rb_define_method(s_glfw_window_klass, "set_mouse_button_callback__", rb_window_set_mouse_button_callback, 1); 1629 | rb_define_method(s_glfw_window_klass, "set_cursor_position_callback__", rb_window_set_cursor_position_callback, 1); 1630 | rb_define_method(s_glfw_window_klass, "set_cursor_enter_callback__", rb_window_set_cursor_enter_callback, 1); 1631 | rb_define_method(s_glfw_window_klass, "set_scroll_callback__", rb_window_set_scroll_callback, 1); 1632 | rb_define_method(s_glfw_window_klass, "clipboard_string=", rb_window_set_clipboard_string, 1); 1633 | rb_define_method(s_glfw_window_klass, "clipboard_string", rb_window_get_clipboard_string, 0); 1634 | rb_cvar_set(s_glfw_window_klass, kRB_CVAR_WINDOW_WINDOWS, rb_hash_new()); 1635 | 1636 | /* Glfw */ 1637 | rb_cvar_set(s_glfw_module, kRB_CVAR_GLFW_ERROR_CALLBACK, Qnil); 1638 | rb_cvar_set(s_glfw_module, kRB_CVAR_GLFW_MONITOR_CALLBACK, Qnil); 1639 | rb_define_singleton_method(s_glfw_module, "version", rb_glfw_version, 0); 1640 | rb_define_singleton_method(s_glfw_module, "terminate", rb_glfw_terminate, 0); 1641 | rb_define_singleton_method(s_glfw_module, "init", rb_glfw_init, 0); 1642 | rb_define_singleton_method(s_glfw_module, "poll_events", rb_glfw_poll_events, 0); 1643 | rb_define_singleton_method(s_glfw_module, "wait_events", rb_glfw_wait_events, 0); 1644 | rb_define_singleton_method(s_glfw_module, "joystick_present?", rb_glfw_joystick_present, 1); 1645 | rb_define_singleton_method(s_glfw_module, "joystick_axes", rb_glfw_get_joystick_axes, 1); 1646 | rb_define_singleton_method(s_glfw_module, "joystick_buttons", rb_glfw_get_joystick_buttons, 1); 1647 | rb_define_singleton_method(s_glfw_module, "joystick_name", rb_glfw_get_joystick_name, 1); 1648 | rb_define_singleton_method(s_glfw_module, "time", rb_glfw_get_time, 0); 1649 | rb_define_singleton_method(s_glfw_module, "time=", rb_glfw_set_time, 1); 1650 | rb_define_singleton_method(s_glfw_module, "swap_interval=", rb_glfw_swap_interval, 1); 1651 | rb_define_singleton_method(s_glfw_module, "extension_supported?", rb_glfw_extension_supported, 1); 1652 | 1653 | /* DEFINE ALL THE THINGS */ 1654 | rb_const_set(s_glfw_module, rb_intern("VERSION_MAJOR"), INT2FIX(GLFW_VERSION_MAJOR)); 1655 | rb_const_set(s_glfw_module, rb_intern("VERSION_MINOR"), INT2FIX(GLFW_VERSION_MINOR)); 1656 | rb_const_set(s_glfw_module, rb_intern("VERSION_REVISION"), INT2FIX(GLFW_VERSION_REVISION)); 1657 | rb_const_set(s_glfw_module, rb_intern("RELEASE"), INT2FIX(GLFW_RELEASE)); 1658 | rb_const_set(s_glfw_module, rb_intern("PRESS"), INT2FIX(GLFW_PRESS)); 1659 | rb_const_set(s_glfw_module, rb_intern("REPEAT"), INT2FIX(GLFW_REPEAT)); 1660 | rb_const_set(s_glfw_module, rb_intern("KEY_UNKNOWN"), INT2FIX(GLFW_KEY_UNKNOWN)); 1661 | rb_const_set(s_glfw_module, rb_intern("KEY_SPACE"), INT2FIX(GLFW_KEY_SPACE)); 1662 | rb_const_set(s_glfw_module, rb_intern("KEY_APOSTROPHE"), INT2FIX(GLFW_KEY_APOSTROPHE)); 1663 | rb_const_set(s_glfw_module, rb_intern("KEY_COMMA"), INT2FIX(GLFW_KEY_COMMA)); 1664 | rb_const_set(s_glfw_module, rb_intern("KEY_MINUS"), INT2FIX(GLFW_KEY_MINUS)); 1665 | rb_const_set(s_glfw_module, rb_intern("KEY_PERIOD"), INT2FIX(GLFW_KEY_PERIOD)); 1666 | rb_const_set(s_glfw_module, rb_intern("KEY_SLASH"), INT2FIX(GLFW_KEY_SLASH)); 1667 | rb_const_set(s_glfw_module, rb_intern("KEY_0"), INT2FIX(GLFW_KEY_0)); 1668 | rb_const_set(s_glfw_module, rb_intern("KEY_1"), INT2FIX(GLFW_KEY_1)); 1669 | rb_const_set(s_glfw_module, rb_intern("KEY_2"), INT2FIX(GLFW_KEY_2)); 1670 | rb_const_set(s_glfw_module, rb_intern("KEY_3"), INT2FIX(GLFW_KEY_3)); 1671 | rb_const_set(s_glfw_module, rb_intern("KEY_4"), INT2FIX(GLFW_KEY_4)); 1672 | rb_const_set(s_glfw_module, rb_intern("KEY_5"), INT2FIX(GLFW_KEY_5)); 1673 | rb_const_set(s_glfw_module, rb_intern("KEY_6"), INT2FIX(GLFW_KEY_6)); 1674 | rb_const_set(s_glfw_module, rb_intern("KEY_7"), INT2FIX(GLFW_KEY_7)); 1675 | rb_const_set(s_glfw_module, rb_intern("KEY_8"), INT2FIX(GLFW_KEY_8)); 1676 | rb_const_set(s_glfw_module, rb_intern("KEY_9"), INT2FIX(GLFW_KEY_9)); 1677 | rb_const_set(s_glfw_module, rb_intern("KEY_SEMICOLON"), INT2FIX(GLFW_KEY_SEMICOLON)); 1678 | rb_const_set(s_glfw_module, rb_intern("KEY_EQUAL"), INT2FIX(GLFW_KEY_EQUAL)); 1679 | rb_const_set(s_glfw_module, rb_intern("KEY_A"), INT2FIX(GLFW_KEY_A)); 1680 | rb_const_set(s_glfw_module, rb_intern("KEY_B"), INT2FIX(GLFW_KEY_B)); 1681 | rb_const_set(s_glfw_module, rb_intern("KEY_C"), INT2FIX(GLFW_KEY_C)); 1682 | rb_const_set(s_glfw_module, rb_intern("KEY_D"), INT2FIX(GLFW_KEY_D)); 1683 | rb_const_set(s_glfw_module, rb_intern("KEY_E"), INT2FIX(GLFW_KEY_E)); 1684 | rb_const_set(s_glfw_module, rb_intern("KEY_F"), INT2FIX(GLFW_KEY_F)); 1685 | rb_const_set(s_glfw_module, rb_intern("KEY_G"), INT2FIX(GLFW_KEY_G)); 1686 | rb_const_set(s_glfw_module, rb_intern("KEY_H"), INT2FIX(GLFW_KEY_H)); 1687 | rb_const_set(s_glfw_module, rb_intern("KEY_I"), INT2FIX(GLFW_KEY_I)); 1688 | rb_const_set(s_glfw_module, rb_intern("KEY_J"), INT2FIX(GLFW_KEY_J)); 1689 | rb_const_set(s_glfw_module, rb_intern("KEY_K"), INT2FIX(GLFW_KEY_K)); 1690 | rb_const_set(s_glfw_module, rb_intern("KEY_L"), INT2FIX(GLFW_KEY_L)); 1691 | rb_const_set(s_glfw_module, rb_intern("KEY_M"), INT2FIX(GLFW_KEY_M)); 1692 | rb_const_set(s_glfw_module, rb_intern("KEY_N"), INT2FIX(GLFW_KEY_N)); 1693 | rb_const_set(s_glfw_module, rb_intern("KEY_O"), INT2FIX(GLFW_KEY_O)); 1694 | rb_const_set(s_glfw_module, rb_intern("KEY_P"), INT2FIX(GLFW_KEY_P)); 1695 | rb_const_set(s_glfw_module, rb_intern("KEY_Q"), INT2FIX(GLFW_KEY_Q)); 1696 | rb_const_set(s_glfw_module, rb_intern("KEY_R"), INT2FIX(GLFW_KEY_R)); 1697 | rb_const_set(s_glfw_module, rb_intern("KEY_S"), INT2FIX(GLFW_KEY_S)); 1698 | rb_const_set(s_glfw_module, rb_intern("KEY_T"), INT2FIX(GLFW_KEY_T)); 1699 | rb_const_set(s_glfw_module, rb_intern("KEY_U"), INT2FIX(GLFW_KEY_U)); 1700 | rb_const_set(s_glfw_module, rb_intern("KEY_V"), INT2FIX(GLFW_KEY_V)); 1701 | rb_const_set(s_glfw_module, rb_intern("KEY_W"), INT2FIX(GLFW_KEY_W)); 1702 | rb_const_set(s_glfw_module, rb_intern("KEY_X"), INT2FIX(GLFW_KEY_X)); 1703 | rb_const_set(s_glfw_module, rb_intern("KEY_Y"), INT2FIX(GLFW_KEY_Y)); 1704 | rb_const_set(s_glfw_module, rb_intern("KEY_Z"), INT2FIX(GLFW_KEY_Z)); 1705 | rb_const_set(s_glfw_module, rb_intern("KEY_LEFT_BRACKET"), INT2FIX(GLFW_KEY_LEFT_BRACKET)); 1706 | rb_const_set(s_glfw_module, rb_intern("KEY_BACKSLASH"), INT2FIX(GLFW_KEY_BACKSLASH)); 1707 | rb_const_set(s_glfw_module, rb_intern("KEY_RIGHT_BRACKET"), INT2FIX(GLFW_KEY_RIGHT_BRACKET)); 1708 | rb_const_set(s_glfw_module, rb_intern("KEY_GRAVE_ACCENT"), INT2FIX(GLFW_KEY_GRAVE_ACCENT)); 1709 | rb_const_set(s_glfw_module, rb_intern("KEY_WORLD_1"), INT2FIX(GLFW_KEY_WORLD_1)); 1710 | rb_const_set(s_glfw_module, rb_intern("KEY_WORLD_2"), INT2FIX(GLFW_KEY_WORLD_2)); 1711 | rb_const_set(s_glfw_module, rb_intern("KEY_ESCAPE"), INT2FIX(GLFW_KEY_ESCAPE)); 1712 | rb_const_set(s_glfw_module, rb_intern("KEY_ENTER"), INT2FIX(GLFW_KEY_ENTER)); 1713 | rb_const_set(s_glfw_module, rb_intern("KEY_TAB"), INT2FIX(GLFW_KEY_TAB)); 1714 | rb_const_set(s_glfw_module, rb_intern("KEY_BACKSPACE"), INT2FIX(GLFW_KEY_BACKSPACE)); 1715 | rb_const_set(s_glfw_module, rb_intern("KEY_INSERT"), INT2FIX(GLFW_KEY_INSERT)); 1716 | rb_const_set(s_glfw_module, rb_intern("KEY_DELETE"), INT2FIX(GLFW_KEY_DELETE)); 1717 | rb_const_set(s_glfw_module, rb_intern("KEY_RIGHT"), INT2FIX(GLFW_KEY_RIGHT)); 1718 | rb_const_set(s_glfw_module, rb_intern("KEY_LEFT"), INT2FIX(GLFW_KEY_LEFT)); 1719 | rb_const_set(s_glfw_module, rb_intern("KEY_DOWN"), INT2FIX(GLFW_KEY_DOWN)); 1720 | rb_const_set(s_glfw_module, rb_intern("KEY_UP"), INT2FIX(GLFW_KEY_UP)); 1721 | rb_const_set(s_glfw_module, rb_intern("KEY_PAGE_UP"), INT2FIX(GLFW_KEY_PAGE_UP)); 1722 | rb_const_set(s_glfw_module, rb_intern("KEY_PAGE_DOWN"), INT2FIX(GLFW_KEY_PAGE_DOWN)); 1723 | rb_const_set(s_glfw_module, rb_intern("KEY_HOME"), INT2FIX(GLFW_KEY_HOME)); 1724 | rb_const_set(s_glfw_module, rb_intern("KEY_END"), INT2FIX(GLFW_KEY_END)); 1725 | rb_const_set(s_glfw_module, rb_intern("KEY_CAPS_LOCK"), INT2FIX(GLFW_KEY_CAPS_LOCK)); 1726 | rb_const_set(s_glfw_module, rb_intern("KEY_SCROLL_LOCK"), INT2FIX(GLFW_KEY_SCROLL_LOCK)); 1727 | rb_const_set(s_glfw_module, rb_intern("KEY_NUM_LOCK"), INT2FIX(GLFW_KEY_NUM_LOCK)); 1728 | rb_const_set(s_glfw_module, rb_intern("KEY_PRINT_SCREEN"), INT2FIX(GLFW_KEY_PRINT_SCREEN)); 1729 | rb_const_set(s_glfw_module, rb_intern("KEY_PAUSE"), INT2FIX(GLFW_KEY_PAUSE)); 1730 | rb_const_set(s_glfw_module, rb_intern("KEY_F1"), INT2FIX(GLFW_KEY_F1)); 1731 | rb_const_set(s_glfw_module, rb_intern("KEY_F2"), INT2FIX(GLFW_KEY_F2)); 1732 | rb_const_set(s_glfw_module, rb_intern("KEY_F3"), INT2FIX(GLFW_KEY_F3)); 1733 | rb_const_set(s_glfw_module, rb_intern("KEY_F4"), INT2FIX(GLFW_KEY_F4)); 1734 | rb_const_set(s_glfw_module, rb_intern("KEY_F5"), INT2FIX(GLFW_KEY_F5)); 1735 | rb_const_set(s_glfw_module, rb_intern("KEY_F6"), INT2FIX(GLFW_KEY_F6)); 1736 | rb_const_set(s_glfw_module, rb_intern("KEY_F7"), INT2FIX(GLFW_KEY_F7)); 1737 | rb_const_set(s_glfw_module, rb_intern("KEY_F8"), INT2FIX(GLFW_KEY_F8)); 1738 | rb_const_set(s_glfw_module, rb_intern("KEY_F9"), INT2FIX(GLFW_KEY_F9)); 1739 | rb_const_set(s_glfw_module, rb_intern("KEY_F10"), INT2FIX(GLFW_KEY_F10)); 1740 | rb_const_set(s_glfw_module, rb_intern("KEY_F11"), INT2FIX(GLFW_KEY_F11)); 1741 | rb_const_set(s_glfw_module, rb_intern("KEY_F12"), INT2FIX(GLFW_KEY_F12)); 1742 | rb_const_set(s_glfw_module, rb_intern("KEY_F13"), INT2FIX(GLFW_KEY_F13)); 1743 | rb_const_set(s_glfw_module, rb_intern("KEY_F14"), INT2FIX(GLFW_KEY_F14)); 1744 | rb_const_set(s_glfw_module, rb_intern("KEY_F15"), INT2FIX(GLFW_KEY_F15)); 1745 | rb_const_set(s_glfw_module, rb_intern("KEY_F16"), INT2FIX(GLFW_KEY_F16)); 1746 | rb_const_set(s_glfw_module, rb_intern("KEY_F17"), INT2FIX(GLFW_KEY_F17)); 1747 | rb_const_set(s_glfw_module, rb_intern("KEY_F18"), INT2FIX(GLFW_KEY_F18)); 1748 | rb_const_set(s_glfw_module, rb_intern("KEY_F19"), INT2FIX(GLFW_KEY_F19)); 1749 | rb_const_set(s_glfw_module, rb_intern("KEY_F20"), INT2FIX(GLFW_KEY_F20)); 1750 | rb_const_set(s_glfw_module, rb_intern("KEY_F21"), INT2FIX(GLFW_KEY_F21)); 1751 | rb_const_set(s_glfw_module, rb_intern("KEY_F22"), INT2FIX(GLFW_KEY_F22)); 1752 | rb_const_set(s_glfw_module, rb_intern("KEY_F23"), INT2FIX(GLFW_KEY_F23)); 1753 | rb_const_set(s_glfw_module, rb_intern("KEY_F24"), INT2FIX(GLFW_KEY_F24)); 1754 | rb_const_set(s_glfw_module, rb_intern("KEY_F25"), INT2FIX(GLFW_KEY_F25)); 1755 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_0"), INT2FIX(GLFW_KEY_KP_0)); 1756 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_1"), INT2FIX(GLFW_KEY_KP_1)); 1757 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_2"), INT2FIX(GLFW_KEY_KP_2)); 1758 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_3"), INT2FIX(GLFW_KEY_KP_3)); 1759 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_4"), INT2FIX(GLFW_KEY_KP_4)); 1760 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_5"), INT2FIX(GLFW_KEY_KP_5)); 1761 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_6"), INT2FIX(GLFW_KEY_KP_6)); 1762 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_7"), INT2FIX(GLFW_KEY_KP_7)); 1763 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_8"), INT2FIX(GLFW_KEY_KP_8)); 1764 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_9"), INT2FIX(GLFW_KEY_KP_9)); 1765 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_DECIMAL"), INT2FIX(GLFW_KEY_KP_DECIMAL)); 1766 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_DIVIDE"), INT2FIX(GLFW_KEY_KP_DIVIDE)); 1767 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_MULTIPLY"), INT2FIX(GLFW_KEY_KP_MULTIPLY)); 1768 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_SUBTRACT"), INT2FIX(GLFW_KEY_KP_SUBTRACT)); 1769 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_ADD"), INT2FIX(GLFW_KEY_KP_ADD)); 1770 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_ENTER"), INT2FIX(GLFW_KEY_KP_ENTER)); 1771 | rb_const_set(s_glfw_module, rb_intern("KEY_KP_EQUAL"), INT2FIX(GLFW_KEY_KP_EQUAL)); 1772 | rb_const_set(s_glfw_module, rb_intern("KEY_LEFT_SHIFT"), INT2FIX(GLFW_KEY_LEFT_SHIFT)); 1773 | rb_const_set(s_glfw_module, rb_intern("KEY_LEFT_CONTROL"), INT2FIX(GLFW_KEY_LEFT_CONTROL)); 1774 | rb_const_set(s_glfw_module, rb_intern("KEY_LEFT_ALT"), INT2FIX(GLFW_KEY_LEFT_ALT)); 1775 | rb_const_set(s_glfw_module, rb_intern("KEY_LEFT_SUPER"), INT2FIX(GLFW_KEY_LEFT_SUPER)); 1776 | rb_const_set(s_glfw_module, rb_intern("KEY_RIGHT_SHIFT"), INT2FIX(GLFW_KEY_RIGHT_SHIFT)); 1777 | rb_const_set(s_glfw_module, rb_intern("KEY_RIGHT_CONTROL"), INT2FIX(GLFW_KEY_RIGHT_CONTROL)); 1778 | rb_const_set(s_glfw_module, rb_intern("KEY_RIGHT_ALT"), INT2FIX(GLFW_KEY_RIGHT_ALT)); 1779 | rb_const_set(s_glfw_module, rb_intern("KEY_RIGHT_SUPER"), INT2FIX(GLFW_KEY_RIGHT_SUPER)); 1780 | rb_const_set(s_glfw_module, rb_intern("KEY_MENU"), INT2FIX(GLFW_KEY_MENU)); 1781 | rb_const_set(s_glfw_module, rb_intern("KEY_LAST"), INT2FIX(GLFW_KEY_LAST)); 1782 | rb_const_set(s_glfw_module, rb_intern("MOD_SHIFT"), INT2FIX(GLFW_MOD_SHIFT)); 1783 | rb_const_set(s_glfw_module, rb_intern("MOD_CONTROL"), INT2FIX(GLFW_MOD_CONTROL)); 1784 | rb_const_set(s_glfw_module, rb_intern("MOD_ALT"), INT2FIX(GLFW_MOD_ALT)); 1785 | rb_const_set(s_glfw_module, rb_intern("MOD_SUPER"), INT2FIX(GLFW_MOD_SUPER)); 1786 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_1"), INT2FIX(GLFW_MOUSE_BUTTON_1)); 1787 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_2"), INT2FIX(GLFW_MOUSE_BUTTON_2)); 1788 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_3"), INT2FIX(GLFW_MOUSE_BUTTON_3)); 1789 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_4"), INT2FIX(GLFW_MOUSE_BUTTON_4)); 1790 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_5"), INT2FIX(GLFW_MOUSE_BUTTON_5)); 1791 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_6"), INT2FIX(GLFW_MOUSE_BUTTON_6)); 1792 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_7"), INT2FIX(GLFW_MOUSE_BUTTON_7)); 1793 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_8"), INT2FIX(GLFW_MOUSE_BUTTON_8)); 1794 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_LAST"), INT2FIX(GLFW_MOUSE_BUTTON_LAST)); 1795 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_LEFT"), INT2FIX(GLFW_MOUSE_BUTTON_LEFT)); 1796 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_RIGHT"), INT2FIX(GLFW_MOUSE_BUTTON_RIGHT)); 1797 | rb_const_set(s_glfw_module, rb_intern("MOUSE_BUTTON_MIDDLE"), INT2FIX(GLFW_MOUSE_BUTTON_MIDDLE)); 1798 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_1"), INT2FIX(GLFW_JOYSTICK_1)); 1799 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_2"), INT2FIX(GLFW_JOYSTICK_2)); 1800 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_3"), INT2FIX(GLFW_JOYSTICK_3)); 1801 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_4"), INT2FIX(GLFW_JOYSTICK_4)); 1802 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_5"), INT2FIX(GLFW_JOYSTICK_5)); 1803 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_6"), INT2FIX(GLFW_JOYSTICK_6)); 1804 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_7"), INT2FIX(GLFW_JOYSTICK_7)); 1805 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_8"), INT2FIX(GLFW_JOYSTICK_8)); 1806 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_9"), INT2FIX(GLFW_JOYSTICK_9)); 1807 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_10"), INT2FIX(GLFW_JOYSTICK_10)); 1808 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_11"), INT2FIX(GLFW_JOYSTICK_11)); 1809 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_12"), INT2FIX(GLFW_JOYSTICK_12)); 1810 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_13"), INT2FIX(GLFW_JOYSTICK_13)); 1811 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_14"), INT2FIX(GLFW_JOYSTICK_14)); 1812 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_15"), INT2FIX(GLFW_JOYSTICK_15)); 1813 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_16"), INT2FIX(GLFW_JOYSTICK_16)); 1814 | rb_const_set(s_glfw_module, rb_intern("JOYSTICK_LAST"), INT2FIX(GLFW_JOYSTICK_LAST)); 1815 | rb_const_set(s_glfw_module, rb_intern("NOT_INITIALIZED"), INT2FIX(GLFW_NOT_INITIALIZED)); 1816 | rb_const_set(s_glfw_module, rb_intern("NO_CURRENT_CONTEXT"), INT2FIX(GLFW_NO_CURRENT_CONTEXT)); 1817 | rb_const_set(s_glfw_module, rb_intern("INVALID_ENUM"), INT2FIX(GLFW_INVALID_ENUM)); 1818 | rb_const_set(s_glfw_module, rb_intern("INVALID_VALUE"), INT2FIX(GLFW_INVALID_VALUE)); 1819 | rb_const_set(s_glfw_module, rb_intern("OUT_OF_MEMORY"), INT2FIX(GLFW_OUT_OF_MEMORY)); 1820 | rb_const_set(s_glfw_module, rb_intern("API_UNAVAILABLE"), INT2FIX(GLFW_API_UNAVAILABLE)); 1821 | rb_const_set(s_glfw_module, rb_intern("VERSION_UNAVAILABLE"), INT2FIX(GLFW_VERSION_UNAVAILABLE)); 1822 | rb_const_set(s_glfw_module, rb_intern("PLATFORM_ERROR"), INT2FIX(GLFW_PLATFORM_ERROR)); 1823 | rb_const_set(s_glfw_module, rb_intern("FORMAT_UNAVAILABLE"), INT2FIX(GLFW_FORMAT_UNAVAILABLE)); 1824 | rb_const_set(s_glfw_module, rb_intern("FOCUSED"), INT2FIX(GLFW_FOCUSED)); 1825 | rb_const_set(s_glfw_module, rb_intern("ICONIFIED"), INT2FIX(GLFW_ICONIFIED)); 1826 | rb_const_set(s_glfw_module, rb_intern("RESIZABLE"), INT2FIX(GLFW_RESIZABLE)); 1827 | rb_const_set(s_glfw_module, rb_intern("VISIBLE"), INT2FIX(GLFW_VISIBLE)); 1828 | rb_const_set(s_glfw_module, rb_intern("DECORATED"), INT2FIX(GLFW_DECORATED)); 1829 | rb_const_set(s_glfw_module, rb_intern("RED_BITS"), INT2FIX(GLFW_RED_BITS)); 1830 | rb_const_set(s_glfw_module, rb_intern("GREEN_BITS"), INT2FIX(GLFW_GREEN_BITS)); 1831 | rb_const_set(s_glfw_module, rb_intern("BLUE_BITS"), INT2FIX(GLFW_BLUE_BITS)); 1832 | rb_const_set(s_glfw_module, rb_intern("ALPHA_BITS"), INT2FIX(GLFW_ALPHA_BITS)); 1833 | rb_const_set(s_glfw_module, rb_intern("DEPTH_BITS"), INT2FIX(GLFW_DEPTH_BITS)); 1834 | rb_const_set(s_glfw_module, rb_intern("STENCIL_BITS"), INT2FIX(GLFW_STENCIL_BITS)); 1835 | rb_const_set(s_glfw_module, rb_intern("ACCUM_RED_BITS"), INT2FIX(GLFW_ACCUM_RED_BITS)); 1836 | rb_const_set(s_glfw_module, rb_intern("ACCUM_GREEN_BITS"), INT2FIX(GLFW_ACCUM_GREEN_BITS)); 1837 | rb_const_set(s_glfw_module, rb_intern("ACCUM_BLUE_BITS"), INT2FIX(GLFW_ACCUM_BLUE_BITS)); 1838 | rb_const_set(s_glfw_module, rb_intern("ACCUM_ALPHA_BITS"), INT2FIX(GLFW_ACCUM_ALPHA_BITS)); 1839 | rb_const_set(s_glfw_module, rb_intern("AUX_BUFFERS"), INT2FIX(GLFW_AUX_BUFFERS)); 1840 | rb_const_set(s_glfw_module, rb_intern("STEREO"), INT2FIX(GLFW_STEREO)); 1841 | rb_const_set(s_glfw_module, rb_intern("SAMPLES"), INT2FIX(GLFW_SAMPLES)); 1842 | rb_const_set(s_glfw_module, rb_intern("SRGB_CAPABLE"), INT2FIX(GLFW_SRGB_CAPABLE)); 1843 | rb_const_set(s_glfw_module, rb_intern("REFRESH_RATE"), INT2FIX(GLFW_REFRESH_RATE)); 1844 | rb_const_set(s_glfw_module, rb_intern("CLIENT_API"), INT2FIX(GLFW_CLIENT_API)); 1845 | rb_const_set(s_glfw_module, rb_intern("CONTEXT_VERSION_MAJOR"), INT2FIX(GLFW_CONTEXT_VERSION_MAJOR)); 1846 | rb_const_set(s_glfw_module, rb_intern("CONTEXT_VERSION_MINOR"), INT2FIX(GLFW_CONTEXT_VERSION_MINOR)); 1847 | rb_const_set(s_glfw_module, rb_intern("CONTEXT_REVISION"), INT2FIX(GLFW_CONTEXT_REVISION)); 1848 | rb_const_set(s_glfw_module, rb_intern("CONTEXT_ROBUSTNESS"), INT2FIX(GLFW_CONTEXT_ROBUSTNESS)); 1849 | rb_const_set(s_glfw_module, rb_intern("OPENGL_FORWARD_COMPAT"), INT2FIX(GLFW_OPENGL_FORWARD_COMPAT)); 1850 | rb_const_set(s_glfw_module, rb_intern("OPENGL_DEBUG_CONTEXT"), INT2FIX(GLFW_OPENGL_DEBUG_CONTEXT)); 1851 | rb_const_set(s_glfw_module, rb_intern("OPENGL_PROFILE"), INT2FIX(GLFW_OPENGL_PROFILE)); 1852 | rb_const_set(s_glfw_module, rb_intern("OPENGL_API"), INT2FIX(GLFW_OPENGL_API)); 1853 | rb_const_set(s_glfw_module, rb_intern("OPENGL_ES_API"), INT2FIX(GLFW_OPENGL_ES_API)); 1854 | rb_const_set(s_glfw_module, rb_intern("NO_ROBUSTNESS"), INT2FIX(GLFW_NO_ROBUSTNESS)); 1855 | rb_const_set(s_glfw_module, rb_intern("NO_RESET_NOTIFICATION"), INT2FIX(GLFW_NO_RESET_NOTIFICATION)); 1856 | rb_const_set(s_glfw_module, rb_intern("LOSE_CONTEXT_ON_RESET"), INT2FIX(GLFW_LOSE_CONTEXT_ON_RESET)); 1857 | rb_const_set(s_glfw_module, rb_intern("OPENGL_ANY_PROFILE"), INT2FIX(GLFW_OPENGL_ANY_PROFILE)); 1858 | rb_const_set(s_glfw_module, rb_intern("OPENGL_CORE_PROFILE"), INT2FIX(GLFW_OPENGL_CORE_PROFILE)); 1859 | rb_const_set(s_glfw_module, rb_intern("OPENGL_COMPAT_PROFILE"), INT2FIX(GLFW_OPENGL_COMPAT_PROFILE)); 1860 | rb_const_set(s_glfw_module, rb_intern("CURSOR"), INT2FIX(GLFW_CURSOR)); 1861 | rb_const_set(s_glfw_module, rb_intern("STICKY_KEYS"), INT2FIX(GLFW_STICKY_KEYS)); 1862 | rb_const_set(s_glfw_module, rb_intern("STICKY_MOUSE_BUTTONS"), INT2FIX(GLFW_STICKY_MOUSE_BUTTONS)); 1863 | rb_const_set(s_glfw_module, rb_intern("CURSOR_NORMAL"), INT2FIX(GLFW_CURSOR_NORMAL)); 1864 | rb_const_set(s_glfw_module, rb_intern("CURSOR_HIDDEN"), INT2FIX(GLFW_CURSOR_HIDDEN)); 1865 | rb_const_set(s_glfw_module, rb_intern("CURSOR_DISABLED"), INT2FIX(GLFW_CURSOR_DISABLED)); 1866 | rb_const_set(s_glfw_module, rb_intern("CONNECTED"), INT2FIX(GLFW_CONNECTED)); 1867 | rb_const_set(s_glfw_module, rb_intern("DISCONNECTED"), INT2FIX(GLFW_DISCONNECTED)); 1868 | 1869 | glfwSetErrorCallback(rb_glfw_error_callback); 1870 | } 1871 | 1872 | -------------------------------------------------------------------------------- /glfw3.gemspec: -------------------------------------------------------------------------------- 1 | # This file is part of ruby-glfw3. 2 | # Copyright (c) 2013 Noel Raymond Cower. All rights reserved. 3 | # See COPYING for license details. 4 | 5 | Gem::Specification.new { |s| 6 | s.name = 'glfw3' 7 | s.version = '0.4.8' 8 | s.summary = 'GLFW3' 9 | s.description = 'GLFW 3 bindings for Ruby 2.x' 10 | s.authors = [ 'Noel Raymond Cower' ] 11 | s.email = 'ncower@gmail.com' 12 | s.files = Dir.glob('lib/**/*.rb') + 13 | Dir.glob('ext/**/*.{c,rb}') + 14 | [ 'COPYING', 'README.md' ] 15 | s.extensions << 'ext/glfw3/extconf.rb' 16 | s.homepage = 'https://github.com/nilium/ruby-glfw3' 17 | s.license = 'Simplified BSD' 18 | s.has_rdoc = true 19 | s.extra_rdoc_files = [ 20 | 'ext/glfw3/glfw3.c', 21 | 'README.md', 22 | 'COPYING' 23 | ] 24 | s.rdoc_options << '--title' << 'GLFW 3 Bindings' << 25 | '--main' << 'README.md' << 26 | '--line-numbers' 27 | } 28 | -------------------------------------------------------------------------------- /lib/glfw3.rb: -------------------------------------------------------------------------------- 1 | require 'glfw3/glfw3' 2 | require 'glfw3/callbacks' 3 | require 'glfw3/monitor' 4 | require 'glfw3/window' 5 | 6 | # 7 | # The core Glfw module, contains functions for setting error and monitor 8 | # callbacks, joystick input, constants, timing, event handling, and so on. 9 | # 10 | # See also Glfw::Window, Glfw::Monitor, and Glfw::VideoMode. 11 | # 12 | module Glfw 13 | end 14 | -------------------------------------------------------------------------------- /lib/glfw3/callbacks.rb: -------------------------------------------------------------------------------- 1 | require 'glfw3/glfw3' 2 | 3 | module Glfw 4 | @@__error_callback = nil 5 | @@__monitor_callback = nil 6 | 7 | # 8 | # Gets the current error callback object. 9 | # 10 | # call-seq: 11 | # error_callback -> obj or nil 12 | # 13 | def self.error_callback 14 | @@__error_callback 15 | end 16 | 17 | # 18 | # Sets the current error callback object to the given value. Presumably a 19 | # Proc or some other object, but one that implements a call(...) function. 20 | # 21 | # If set to nil, any GLFW error will raise a RuntimeError exception. 22 | # 23 | # The error callback is expected to take two arguments: the error code and a 24 | # description of the error. For example: 25 | # 26 | # Glfw.error_callback = lambda { |error_code, description| 27 | # raise RuntimeError, "GLFW Error #{error_code}: #{description}" 28 | # } 29 | # 30 | def self.error_callback=(lambda) 31 | @@__error_callback = lambda 32 | end 33 | 34 | # 35 | # Sets the current error callback to a Proc generated from the provided block. 36 | # 37 | def self.set_error_callback(&block) 38 | self.error_callback = block 39 | end 40 | 41 | # 42 | # Gets the current monitor callback object. 43 | # 44 | # call-seq: 45 | # monitor_callback -> obj or nil 46 | # 47 | def self.monitor_callback 48 | @@__monitor_callback 49 | end 50 | 51 | # 52 | # Sets the current monitor callback object to the given object. Presumably a 53 | # Proc or some other object, but one that implements a call(...) function. 54 | # 55 | # If set to nil, the callback is disabled. 56 | # 57 | # The monitor callback is expected to take two arguments: the monitor and an 58 | # event (one of either Glfw::CONNECTED or Glfw::DISCONNECTED). For example: 59 | # 60 | # Glfw.monitor_callback = lambda { |monitor, event| 61 | # # ... 62 | # } 63 | # 64 | def self.monitor_callback=(lambda) 65 | @@__monitor_callback = lambda 66 | end 67 | 68 | # 69 | # Sets the current monitor callback to a Proc generated from the provided 70 | # block. 71 | # 72 | def self.set_monitor_callback(&block) 73 | self.monitor_callback = block 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /lib/glfw3/monitor.rb: -------------------------------------------------------------------------------- 1 | require 'glfw3/glfw3' 2 | 3 | module Glfw ; end 4 | 5 | class Glfw::Monitor 6 | alias_method :gamma_ramp=, :set_gamma_ramp 7 | alias_method :gamma_ramp, :get_gamma_ramp 8 | end 9 | -------------------------------------------------------------------------------- /lib/glfw3/window.rb: -------------------------------------------------------------------------------- 1 | require 'glfw3/glfw3' 2 | 3 | module Glfw; end 4 | 5 | # 6 | # A GLFW window. These contain a context, optionally one shared with other 7 | # windows and generate events. Each window maintains its own event callbacks. 8 | # 9 | # Wraps GLFWwindow and its associated functions, for the most part. 10 | # 11 | # 12 | # === Event Callbacks 13 | # 14 | # All window event callbacks' first argument is the window that generated the 15 | # event. These event callbacks all receive the same arguments as their GLFW C 16 | # counterparts, so refer to the 17 | # {GLFW 3 documentation}[http://www.glfw.org/docs/3.0/group__input.html] 18 | # for that. 19 | # 20 | # 21 | # === User Data 22 | # 23 | # If you need to associate a particular object or value with a window, you can 24 | # use its #user_data attribute to store and retreive an arbitrary object for 25 | # the window. If you need to store multiple values with the window, you might 26 | # set its user data object to a Hash. 27 | # 28 | class Glfw::Window 29 | 30 | # 31 | # User data attribute, can be set to any arbitrary object. Used to associate 32 | # any object with the window for later retrieval. 33 | # 34 | attr_accessor :user_data 35 | 36 | 37 | 38 | alias_method :should_close?, :get_should_close 39 | alias_method :should_close=, :set_should_close 40 | 41 | alias_method :cursor_pos, :get_cursor_pos 42 | 43 | def cursor_pos=(xy) 44 | set_cursor_pos(*xy) 45 | end 46 | 47 | alias_method :move, :set_position 48 | alias_method :resize, :set_size 49 | 50 | alias_method :position, :get_position 51 | alias_method :size, :get_size 52 | 53 | def position=(xy) 54 | set_position(*xy) 55 | end 56 | 57 | def size=(wh) 58 | set_size(*wh) 59 | end 60 | 61 | # 62 | # Returns an array of all allocated GLFW windows. 63 | # 64 | # call-seq: 65 | # windows -> [Glfw::Window, ...] 66 | # 67 | def self.windows 68 | @@__windows.values 69 | end 70 | 71 | # 72 | # Gets the X position of the window in screen space. See also #position. 73 | # 74 | def x 75 | position[0] 76 | end 77 | 78 | # 79 | # Gets the Y position of the window in screen space. See also #position. 80 | # 81 | def y 82 | position[1] 83 | end 84 | 85 | # 86 | # Gets the width of the window. See also #size. 87 | # 88 | def width 89 | size[0] 90 | end 91 | 92 | # 93 | # Gets the width of the window. See also #size. 94 | # 95 | def height 96 | size[1] 97 | end 98 | 99 | def key_callback=(func) 100 | @__key_callback = func 101 | set_key_callback__(func.respond_to?(:call)) 102 | end 103 | 104 | def set_key_callback(&block) 105 | self.key_callback = block 106 | end 107 | 108 | def char_callback=(func) 109 | @__char_callback = func 110 | set_char_callback__(func.respond_to?(:call)) 111 | end 112 | 113 | def set_char_callback(&block) 114 | self.char_callback = block 115 | end 116 | 117 | def mouse_button_callback=(func) 118 | @__mouse_button_callback = func 119 | set_mouse_button_callback__(func.respond_to?(:call)) 120 | end 121 | 122 | def set_mouse_button_callback(&block) 123 | self.mouse_button_callback = block 124 | end 125 | 126 | def cursor_position_callback=(func) 127 | @__cursor_position_callback = func 128 | set_cursor_position_callback__(func.respond_to?(:call)) 129 | end 130 | 131 | def set_cursor_position_callback(&block) 132 | self.cursor_position_callback = block 133 | end 134 | 135 | def cursor_enter_callback=(func) 136 | @__cursor_enter_callback = func 137 | set_cursor_enter_callback__(func.respond_to?(:call)) 138 | end 139 | 140 | def set_cursor_enter_callback(&block) 141 | self.cursor_enter_callback = block 142 | end 143 | 144 | def scroll_callback=(func) 145 | @__scroll_callback = func 146 | set_scroll_callback__(func.respond_to?(:call)) 147 | end 148 | 149 | def set_scroll_callback(&block) 150 | self.scroll_callback = block 151 | end 152 | 153 | def position_callback=(func) 154 | @__position_callback = func 155 | set_window_position_callback__(func.respond_to?(:call)) 156 | end 157 | 158 | def set_position_callback(&block) 159 | self.position_callback = block 160 | end 161 | 162 | def size_callback=(func) 163 | @__size_callback = func 164 | set_window_size_callback__(func.respond_to?(:call)) 165 | end 166 | 167 | def set_size_callback(&block) 168 | self.size_callback = block 169 | end 170 | 171 | def close_callback=(func) 172 | @__close_callback = func 173 | set_close_callback__(func.respond_to?(:call)) 174 | end 175 | 176 | def set_close_callback(&block) 177 | self.close_callback = block 178 | end 179 | 180 | def refresh_callback=(func) 181 | @__refresh_callback = func 182 | set_refresh_callback__(func.respond_to?(:call)) 183 | end 184 | 185 | def set_refresh_callback(&block) 186 | self.refresh_callback = block 187 | end 188 | 189 | def focus_callback=(func) 190 | @__focus_callback = func 191 | set_focus_callback__(func.respond_to?(:call)) 192 | end 193 | 194 | def set_focus_callback(&block) 195 | self.focus_callback = block 196 | end 197 | 198 | def iconify_callback=(func) 199 | @__iconify_callback = func 200 | set_iconify_callback__(func.respond_to?(:call)) 201 | end 202 | 203 | def set_iconify_callback(&block) 204 | self.iconify_callback = block 205 | end 206 | 207 | def framebuffer_size_callback=(func) 208 | @__framebuffer_size_callback = func 209 | set_fbsize_callback__(func.respond_to?(:call)) 210 | end 211 | 212 | def set_framebuffer_size_callback(&block) 213 | self.framebuffer_size_callback = block 214 | end 215 | 216 | 217 | end 218 | --------------------------------------------------------------------------------