diff --git a/.autotest b/.autotest
new file mode 100644
index 0000000..9147a57
--- /dev/null
+++ b/.autotest
@@ -0,0 +1,29 @@
+require 'autotest/restart'
+
+Autotest.add_hook :initialize do |at|
+ at.add_exception /\.git/
+ at.add_exception /doc/
+ at.add_exception /examples/
+ at.add_exception /utils/
+ at.add_exception /website/
+
+ at.add_mapping(/^lib\/.*(\.bundle|so|dll)$/) do |filename, match|
+ possible = File.basename(filename, match[1])
+ at.files_matching %r%^test/test_#{possible}%
+ end
+
+ def at.path_to_classname s
+ sep = File::SEPARATOR
+ n = s.sub(/^test#{sep}test_(.*)\.rb/, '\1')
+ c = if n =~ /^(glu?)_?(.*)/ then
+ "#{$1.capitalize}#{$2.split(/_|(\d+)/).map { |seg| seg.capitalize }.join}"
+ end
+
+ "Test#{c}"
+ end
+end
+
+Autotest.add_hook :run_command do |at|
+ at.unit_diff = 'cat'
+ system Gem.ruby, Gem.bin_path('rake', 'rake'), 'compile'
+end
diff --git a/.gemtest b/.gemtest
new file mode 100644
index 0000000..e69de29
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..39447a5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+*.swp
+/TAGS
+/lib/glut/*.so
+/lib/glut/*.bundle
+/pkg
+/tmp
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..5f515e7
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,15 @@
+language: ruby
+rvm:
+# - "1.9.3"
+ - "2.0.0"
+# - jruby-19mode # JRuby in 1.9 mode
+# - rbx-19mode
+before_install:
+ - gem install hoe rake-compiler;
+ - sudo apt-get install xpra xserver-xorg-video-dummy freeglut3-dev;
+before_script:
+ - "xpra --xvfb=\"Xorg +extension GLX -config `pwd`/test/dummy.xorg.conf -logfile ${HOME}/.xpra/xorg.log\" start :9"
+script: "env DISPLAY=:9 rake test"
+after_script:
+ - "xpra stop :9"
+ - "cat ~/.xpra/*"
diff --git a/History.rdoc b/History.rdoc
new file mode 100644
index 0000000..ba7b3c9
--- /dev/null
+++ b/History.rdoc
@@ -0,0 +1,25 @@
+=== 8.3.0 / 2017-05-30
+
+* Add ruby-2.4 to binary windows gems and remove ruby-1.9.
+* Add support for source gems on RubyInstaller-2.4 and MSYS2.
+
+=== 8.2.2 / 2016-01-21
+
+* Add ruby-2.2 and 2.3 to binary windows gems.
+* Fix compilation on OS-X. Github #2
+
+=== 8.2.1 / 2014-10-06
+
+* Add ruby-2.1 to binary windows gems.
+* Fix segmentation fault in glutKeyboardUpFunc callback
+
+=== 8.2.0 / 2014-03-14
+
+* Add x64-mingw platform for cross build and add ruby-2.0.0 to binary gems.
+* Update to freeglut-2.8.1 for cross build.
+* Don't pollute the global namespace. Use GLUT namespace.
+* Replace deprecated rb_thread_blocking_region() by rb_thread_call_with_gvl()
+
+=== 8.1.0 / 2013-03-03
+
+* Moved glut into a standalone gem.
diff --git a/MIT-LICENSE b/MIT-LICENSE
new file mode 100644
index 0000000..0860220
--- /dev/null
+++ b/MIT-LICENSE
@@ -0,0 +1,18 @@
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/Manifest.txt b/Manifest.txt
new file mode 100644
index 0000000..0362286
--- /dev/null
+++ b/Manifest.txt
@@ -0,0 +1,16 @@
+.autotest
+.gemtest
+.gitignore
+.travis.yml
+History.rdoc
+MIT-LICENSE
+Manifest.txt
+README.rdoc
+Rakefile
+ext/glut/common.h
+ext/glut/extconf.rb
+ext/glut/glut.c
+ext/glut/glut_callbacks.c
+ext/glut/glut_ext.c
+lib/glut.rb
+lib/glut/dummy.rb
diff --git a/README.rdoc b/README.rdoc
new file mode 100644
index 0000000..e71fc5e
--- /dev/null
+++ b/README.rdoc
@@ -0,0 +1,77 @@
+= glut
+
+== Description
+
+Glut bindings for OpenGL. To be used with the {opengl}[https://github.com/larskanis/opengl] gem.
+
+== Features and Problems
+
+* available for Windows, Linux and OS X
+
+== Requirements
+
+* Ruby 1.9.2+
+ * see {0.7}[https://github.com/archSeer/opengl/tree/0.7] for Ruby 1.8.x compatible branch
+* (free-)GLUT development files installed
+
+== Install
+
+ gem install glut
+
+== Cross compiling for Windows
+
+Using rake-compiler a cross compiled opengl gem can be build on a Linux or MacOS X
+host for the win32 platform. The generated gem is statically linked against
+libfreeglut. Freeglut is downloaded and compiled from the sources.
+There are no runtime dependencies to any but the standard Windows
+DLLs.
+
+Install mingw32 or w64 using the instructions in rake-compiler's README.
+For Debian/Ubuntu it is apt-get install gcc-mingw-w64 .
+
+Download and cross compile ruby 1.9 for win32 with:
+
+ rake-compiler cross-ruby VERSION=1.9.3-p0
+
+Download and cross compile opengl for win32:
+
+ rake cross native gem
+
+or with custom versions:
+
+ rake cross native gem RUBY_CC_VERSION=1.9.3 LIBFREEGLUT_VERSION=2.8.0
+
+If everything works, there should be ruby-opengl-VERSION-x86-mingw32.gem in the pkg
+directory.
+
+
+== License
+
+(The MIT License)
+
+Copyright (c) Blaž Hrastnik (current maintainer)
+Copyright (c) Eric Hodel (current maintainer)
+Copyright (c) Alain Hoang (previous maintainer)
+Copyright (c) Jan Dvorak (contributor)
+Copyright (c) Minh Thu Vo (contributor)
+Copyright (c) James Adam (contributor)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..d4a7a30
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,79 @@
+# -*- coding: UTF-8 -*-
+# -*-ruby-*-
+#
+# Copyright (C) 2006 John M. Gabriele
+# Copyright (C) Eric Hodel
+#
+# This program is distributed under the terms of the MIT license.
+# See the included MIT-LICENSE file for the terms of this license.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require 'hoe'
+require 'rake/extensiontask'
+
+hoe = Hoe.spec 'glut' do
+ developer 'Eric Hodel', 'drbrain@segment7.net'
+ developer 'Lars Kanis', 'lars@greiz-reinsdorf.de'
+ developer 'Blaž Hrastnik', 'speed.the.bboy@gmail.com'
+ developer 'Alain Hoang', ''
+ developer 'Jan Dvorak', ''
+ developer 'Minh Thu Vo', ''
+ developer 'James Adam', ''
+
+ self.readme_file = 'README.rdoc'
+ self.history_file = 'History.rdoc'
+ self.extra_rdoc_files = FileList['*.rdoc']
+
+ extra_dev_deps << ['rake-compiler', '~> 1.0']
+ extra_dev_deps << ['rake-compiler-dock', '~> 0.6.0']
+ extra_dev_deps << ['mini_portile2', '~> 2.1']
+
+ self.spec_extras = {
+ :extensions => %w[ext/glut/extconf.rb],
+ :required_ruby_version => '>= 1.9.2',
+ :metadata => {'msys2_mingw_dependencies' => 'freeglut'},
+ }
+end
+
+Rake::ExtensionTask.new 'glut', hoe.spec do |ext|
+ ext.lib_dir = 'lib/glut'
+
+ ext.cross_compile = true
+ ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
+ ext.cross_config_options += [
+ "--enable-win32-cross",
+ ]
+ ext.cross_compiling do |spec|
+ # The fat binary gem doesn't depend on the freeglut package, since it bundles the library.
+ spec.metadata.delete('msys2_mingw_dependencies')
+ end
+end
+
+
+# To reduce the gem file size strip mingw32 dlls before packaging
+ENV['RUBY_CC_VERSION'].to_s.split(':').each do |ruby_version|
+ task "copy:glut:x86-mingw32:#{ruby_version}" do |t|
+ sh "i686-w64-mingw32-strip -S tmp/x86-mingw32/stage/lib/glut/#{ruby_version[/^\d+\.\d+/]}/glut.so"
+ end
+
+ task "copy:glut:x64-mingw32:#{ruby_version}" do |t|
+ sh "x86_64-w64-mingw32-strip -S tmp/x64-mingw32/stage/lib/glut/#{ruby_version[/^\d+\.\d+/]}/glut.so"
+ end
+end
+
+desc "Build windows binary gems per rake-compiler-dock."
+task "gem:windows" do
+ require "rake_compiler_dock"
+ RakeCompilerDock.sh <<-EOT
+ rake cross native gem MAKE='nice make -j`nproc`'
+ EOT
+end
+
+task :test => :compile
diff --git a/ext/glut/common.h b/ext/glut/common.h
new file mode 100644
index 0000000..e570693
--- /dev/null
+++ b/ext/glut/common.h
@@ -0,0 +1,68 @@
+/*
+ * Last edit by previous maintainer:
+ * 2000/01/06 16:37:43, kusano
+ *
+ * Copyright (C) 1999 - 2005 Yoshi
+ * Copyright (C) 2006 John M. Gabriele
+ * Copyright (C) 2007 James Adam
+ * Copyright (C) 2007 Jan Dvorak
+ *
+ * This program is distributed under the terms of the MIT license.
+ * See the included MIT-LICENSE file for the terms of this license.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include
+#include "extconf.h"
+
+#ifdef HAVE_GL_FREEGLUT_H
+#include
+#endif
+
+#ifdef HAVE_GL_GLUT_H
+#include
+#endif
+
+#ifdef HAVE_GLUT_GLUT_H
+#include
+#endif
+
+#ifndef GLUTCALLBACK
+#define GLUTCALLBACK
+#endif
+
+#ifdef HAVE_WINDOWS_H
+#define DLLEXPORT __declspec(dllexport)
+#else
+#define DLLEXPORT
+#endif
+
+/* these two macros are cast to a 32 bit type in the places they are used */
+#ifndef RARRAY_LENINT
+#define RARRAY_LENINT RARRAY_LEN
+#endif
+
+/* GLUT */
+
+#define GLUT_SIMPLE_FUNCTION(_name_) \
+static VALUE \
+glut_##_name_(obj) \
+VALUE obj; \
+{ \
+ glut##_name_(); \
+ return Qnil; \
+}
+
+VALUE rb_glut_check_callback(VALUE, VALUE);
+
+#endif
diff --git a/ext/glut/extconf.rb b/ext/glut/extconf.rb
new file mode 100644
index 0000000..96a97a7
--- /dev/null
+++ b/ext/glut/extconf.rb
@@ -0,0 +1,72 @@
+require 'mkmf'
+
+def have_framework(fw, &b)
+ checking_for fw do
+ src = cpp_include("#{fw}/#{fw}.h") << "\n" "int main(void){return 0;}"
+ if try_link(src, opt = "-ObjC -framework #{fw}", &b)
+ $defs.push(format("-DHAVE_FRAMEWORK_%s", fw.tr_cpp))
+ $LDFLAGS << " " << opt
+ true
+ else
+ false
+ end
+ end
+end unless respond_to? :have_framework
+
+if enable_config('win32-cross')
+ require "rubygems"
+ gem "mini_portile2", "~> 2.0"
+ require "mini_portile2"
+
+ LIBFREEGLUT_VERSION = ENV['LIBFREEGLUT_VERSION'] || '2.8.1'
+ LIBFREEGLUT_SOURCE_URI = "http://downloads.sourceforge.net/project/freeglut/freeglut/#{LIBFREEGLUT_VERSION}/freeglut-#{LIBFREEGLUT_VERSION}.tar.gz"
+
+ recipe = MiniPortile.new("libglut", LIBFREEGLUT_VERSION)
+ recipe.files = [LIBFREEGLUT_SOURCE_URI]
+ recipe.target = portsdir = File.expand_path('../../../ports', __FILE__)
+ # Prefer host_alias over host in order to use i586-mingw32msvc as
+ # correct compiler prefix for cross build, but use host if not set.
+ recipe.host = RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"]
+ recipe.configure_options = [
+ "--enable-static",
+ "--target=#{recipe.host}",
+ "--host=#{recipe.host}",
+ ]
+
+ checkpoint = File.join(portsdir, "#{recipe.name}-#{recipe.version}-#{recipe.host}.installed")
+ unless File.exist?(checkpoint)
+ recipe.cook
+ # --disable-static can not be used since it breaks the freeglut build,
+ # but to enforce static linking, we delete the import lib.
+ FileUtils.rm File.join(recipe.path, "lib", "libglut.dll.a")
+ FileUtils.touch checkpoint
+ end
+ recipe.activate
+
+ $defs.push "-DFREEGLUT_EXPORTS"
+ dir_config('freeglut', "#{recipe.path}/include", "#{recipe.path}/lib")
+
+ # libfreeglut is linked to gdi32 and winmm
+ have_library( 'gdi32', 'CreateDC' ) && append_library( $libs, 'gdi32' )
+ have_library( 'winmm', 'timeBeginPeriod' ) && append_library( $libs, 'winmm' )
+end
+
+ok =
+ (have_library('opengl32.lib', 'glVertex3d') && have_library('glut32.lib', 'gluSolidTeapot')) ||
+ (have_library('opengl32') && (have_library('glut') || have_library('freeglut'))) ||
+ (have_library('GL', 'glVertex3d') && have_library('glut', 'glutSolidTeapot')) ||
+ (have_framework('OpenGL') && have_framework('GLUT') && have_framework('Cocoa'))
+
+ok &&=
+ have_header('GL/freeglut.h') ||
+ have_header('GL/glut.h') ||
+ have_header('GLUT/glut.h') # OS X
+
+if String === ?a then
+ $defs.push "-DHAVE_SINGLE_BYTE_STRINGS"
+end
+
+if ok then
+ create_header
+ create_makefile 'glut/glut'
+end
diff --git a/ext/glut/glut.c b/ext/glut/glut.c
new file mode 100644
index 0000000..daa0df6
--- /dev/null
+++ b/ext/glut/glut.c
@@ -0,0 +1,1152 @@
+/*
+ * Last edit by previous maintainer:
+ * 2004/03/02 01:13:06, yoshi
+ *
+ * Copyright (C) 1999 - 2005 Yoshi
+ * Copyright (C) 2005 James Adam
+ * Copyright (C) 2006 John M. Gabriele
+ * Copyright (C) 2007 Jan Dvorak
+ *
+ * This program is distributed under the terms of the MIT license.
+ * See the included COPYRIGHT file for the terms of this license.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common.h"
+extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
+ rb_unblock_function_t *ubf, void *data2);
+
+static VALUE menu_callback = Qnil;
+static ID call_id; /* 'call' method id */
+
+VALUE
+rb_glut_check_callback(VALUE self, VALUE callback)
+{
+ VALUE inspect;
+
+ if (NIL_P(callback))
+ return callback;
+
+ if (rb_respond_to(callback, call_id))
+ return callback;
+
+ if (SYMBOL_P(callback))
+ return rb_obj_method(self, callback);
+
+ inspect = rb_inspect(callback);
+ rb_raise(rb_eArgError, "%s must respond to call", StringValueCStr(inspect));
+}
+
+static VALUE glut_Init( int argc, VALUE * argv, VALUE obj)
+{
+ int largc;
+ char** largv;
+ VALUE new_argv;
+ VALUE orig_arg;
+ int i;
+
+ if (rb_scan_args(argc, argv, "01", &orig_arg) == 0)
+ orig_arg = rb_eval_string("[$0] + ARGV");
+ else
+ Check_Type(orig_arg, T_ARRAY);
+
+ /* converts commandline parameters from ruby to C, passes them
+ to glutInit and returns the parameters stripped of glut-specific
+ commands ("-display","-geometry" etc.) */
+ largc = (int)RARRAY_LENINT(orig_arg);
+ largv = ALLOCA_N(char*, largc);
+ for (i = 0; i < largc; i++)
+ largv[i] = StringValueCStr(RARRAY_PTR(orig_arg)[i]);
+
+ glutInit(&largc, largv);
+
+ new_argv = rb_ary_new2(largc);
+ for (i = 0; i < largc; i++)
+ rb_ary_push(new_argv,rb_str_new2(largv[i]));
+
+ rb_ary_shift(new_argv);
+
+ return new_argv;
+}
+
+static VALUE glut_InitDisplayMode(obj,arg1)
+VALUE obj,arg1;
+{
+ unsigned int mode;
+ mode = (unsigned int)NUM2INT(arg1);
+ glutInitDisplayMode(mode);
+ return Qnil;
+}
+
+static VALUE
+glut_InitDisplayString(obj,arg1)
+VALUE obj,arg1;
+{
+ Check_Type(arg1,T_STRING);
+ glutInitDisplayString(RSTRING_PTR(arg1));
+ return Qnil;
+}
+
+static VALUE
+glut_InitWindowPosition(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int x,y;
+ x = NUM2INT(arg1);
+ y = NUM2INT(arg2);
+ glutInitWindowPosition(x,y);
+ return Qnil;
+}
+
+static VALUE
+glut_InitWindowSize(obj, arg1, arg2)
+VALUE obj,arg1,arg2;
+{
+ int width,height;
+ width = NUM2INT(arg1);
+ height = NUM2INT(arg2);
+ glutInitWindowSize(width,height);
+ return Qnil;
+}
+
+void *glut_MainLoop0(void *ignored) {
+ glutMainLoop();
+
+ return NULL; /* never reached */
+}
+
+static VALUE
+glut_MainLoop(void) {
+ rb_thread_call_without_gvl(glut_MainLoop0, NULL, NULL, NULL);
+
+ return Qnil; /* never reached */
+}
+
+static VALUE
+glut_CheckLoop(void) {
+ rb_warn("calling fake CheckLoop implementation which never returns");
+
+ glut_MainLoop();
+
+ return Qnil;
+}
+
+/* GLUT window sub-API. */
+static VALUE glut_CreateWindow(argc, argv, obj)
+int argc;
+VALUE* argv;
+VALUE obj;
+{
+ int ret;
+ VALUE title;
+ rb_scan_args(argc, argv, "01", &title);
+ if (argc == 0)
+ title = rb_eval_string("$0");
+ Check_Type(title,T_STRING);
+ ret = glutCreateWindow(RSTRING_PTR(title));
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_CreateSubWindow(obj,arg1,arg2,arg3,arg4,arg5)
+VALUE obj,arg1,arg2,arg3,arg4,arg5;
+{
+ int win, x, y, width, height;
+ int ret;
+ win = NUM2INT(arg1);
+ x = NUM2INT(arg2);
+ y = NUM2INT(arg3);
+ width = NUM2INT(arg4);
+ height = NUM2INT(arg5);
+ ret = glutCreateSubWindow(win, x, y, width, height);
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_DestroyWindow(obj,arg1)
+VALUE obj,arg1;
+{
+ int win;
+ win = NUM2INT(arg1);
+ glutDestroyWindow(win);
+ return Qnil;
+}
+
+GLUT_SIMPLE_FUNCTION(PostRedisplay)
+GLUT_SIMPLE_FUNCTION(SwapBuffers)
+
+static VALUE
+glut_GetWindow(obj)
+VALUE obj;
+{
+ int ret;
+ ret = glutGetWindow();
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_SetWindow(obj,arg1)
+VALUE obj,arg1;
+{
+ int win;
+ win = NUM2INT(arg1);
+ glutSetWindow(win);
+ return Qnil;
+}
+
+static VALUE
+glut_SetWindowTitle(obj,arg1)
+VALUE obj,arg1;
+{
+ Check_Type(arg1,T_STRING);
+ glutSetWindowTitle(RSTRING_PTR(arg1));
+ return Qnil;
+}
+
+static VALUE
+glut_SetIconTitle(obj, arg1)
+VALUE obj,arg1;
+{
+ Check_Type(arg1,T_STRING);
+ glutSetIconTitle(RSTRING_PTR(arg1));
+ return Qnil;
+}
+
+static VALUE
+glut_PositionWindow(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int x,y;
+ x = NUM2INT(arg1);
+ y = NUM2INT(arg2);
+ glutPositionWindow(x,y);
+ return Qnil;
+}
+
+static VALUE
+glut_ReshapeWindow(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int width,height;
+ width = NUM2INT(arg1);
+ height = NUM2INT(arg2);
+ glutReshapeWindow(width, height);
+ return Qnil;
+}
+
+GLUT_SIMPLE_FUNCTION(PopWindow)
+GLUT_SIMPLE_FUNCTION(PushWindow)
+GLUT_SIMPLE_FUNCTION(IconifyWindow)
+GLUT_SIMPLE_FUNCTION(ShowWindow)
+GLUT_SIMPLE_FUNCTION(HideWindow)
+GLUT_SIMPLE_FUNCTION(FullScreen)
+
+static VALUE
+glut_SetCursor(obj,arg1)
+VALUE obj,arg1;
+{
+ int cursor;
+ cursor = NUM2INT(arg1);
+ glutSetCursor(cursor);
+ return Qnil;
+}
+
+static VALUE
+glut_WarpPointer(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int x,y;
+ x = NUM2INT(arg1);
+ y = NUM2INT(arg2);
+ glutWarpPointer(x,y);
+ return Qnil;
+}
+
+/* GLUT overlay sub-API. */
+GLUT_SIMPLE_FUNCTION(EstablishOverlay)
+GLUT_SIMPLE_FUNCTION(RemoveOverlay)
+GLUT_SIMPLE_FUNCTION(PostOverlayRedisplay)
+GLUT_SIMPLE_FUNCTION(ShowOverlay)
+GLUT_SIMPLE_FUNCTION(HideOverlay)
+
+static VALUE
+glut_UseLayer(obj,arg1)
+VALUE obj, arg1;
+{
+ GLenum layer;
+ layer = (GLenum)NUM2INT(arg1);
+ glutUseLayer(layer);
+ return Qnil;
+}
+
+static void GLUTCALLBACK
+glut_CreateMenuCallback(int value)
+{
+ VALUE func;
+ int menu;
+ menu = glutGetMenu();
+ func = rb_ary_entry(menu_callback, menu);
+
+ rb_funcall(func, call_id, 1, INT2NUM(value));
+}
+
+static VALUE
+glut_CreateMenu(VALUE obj, VALUE callback) {
+ int menu;
+
+ callback = rb_glut_check_callback(obj, callback);
+
+ if (NIL_P(callback))
+ menu = glutCreateMenu(NULL);
+ else
+ menu = glutCreateMenu(glut_CreateMenuCallback);
+
+ rb_ary_store(menu_callback, menu, callback);
+
+ return INT2FIX(menu);
+}
+
+static VALUE
+glut_DestroyMenu(obj,arg1)
+VALUE obj,arg1;
+{
+ int menu;
+ menu = NUM2INT(arg1);
+ glutDestroyMenu(menu);
+ //rb_hash_aset(g_menucallback, menu, Qnil);
+ //rb_hash_aset(g_menuargs, menu, Qnil);
+ return Qnil;
+}
+
+static VALUE
+glut_GetMenu(obj)
+VALUE obj;
+{
+ int ret;
+ ret = glutGetMenu();
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_SetMenu(obj,arg1)
+VALUE obj,arg1;
+{
+ glutSetMenu(NUM2INT(arg1));
+ return Qnil;
+}
+
+static VALUE
+glut_AddMenuEntry(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ Check_Type(arg1,T_STRING);
+ glutAddMenuEntry(RSTRING_PTR(arg1), NUM2INT(arg2));
+ return Qnil;
+}
+
+static VALUE
+glut_AddSubMenu(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ Check_Type(arg1,T_STRING);
+ glutAddSubMenu(RSTRING_PTR(arg1), NUM2INT(arg2));
+ return Qnil;
+}
+
+static VALUE glut_ChangeToMenuEntry(obj,arg1,arg2,arg3)
+VALUE obj,arg1,arg2,arg3;
+{
+ Check_Type(arg2,T_STRING);
+ glutChangeToMenuEntry(NUM2INT(arg1), RSTRING_PTR(arg2), NUM2INT(arg3));
+ return Qnil;
+}
+
+static VALUE glut_ChangeToSubMenu(obj,arg1,arg2,arg3)
+VALUE obj,arg1,arg2,arg3;
+{
+ Check_Type(arg2,T_STRING);
+ glutChangeToSubMenu(NUM2INT(arg1), RSTRING_PTR(arg2), NUM2INT(arg3));
+ return Qnil;
+}
+
+static VALUE glut_RemoveMenuItem( VALUE obj, VALUE arg1 )
+{
+ glutRemoveMenuItem(NUM2INT(arg1));
+ return Qnil;
+}
+
+static VALUE
+glut_AttachMenu(obj,arg1)
+VALUE obj, arg1;
+{
+ glutAttachMenu(NUM2INT(arg1));
+ return Qnil;
+}
+
+static VALUE
+glut_DetachMenu(obj,arg1)
+VALUE obj, arg1;
+{
+ glutDetachMenu(NUM2INT(arg1));
+ return Qnil;
+}
+
+/* GLUT color index sub-API. */
+static VALUE
+glut_SetColor(obj,arg1,arg2,arg3,arg4)
+VALUE obj,arg1,arg2,arg3,arg4;
+{
+ int set;
+ GLfloat red;
+ GLfloat green;
+ GLfloat blue;
+ set = NUM2INT(arg1);
+ red = (GLfloat)NUM2DBL(arg2);
+ green = (GLfloat)NUM2DBL(arg3);
+ blue = (GLfloat)NUM2DBL(arg4);
+ glutSetColor(set, red, green, blue);
+ return Qnil;
+}
+
+static VALUE
+glut_GetColor(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int ndx;
+ int component;
+ GLfloat ret;
+ ndx = NUM2INT(arg1);
+ component = NUM2INT(arg2);
+ ret = (GLfloat)glutGetColor(ndx, component);
+ return rb_float_new(ret);
+}
+
+static VALUE
+glut_CopyColormap(obj,arg1)
+VALUE obj,arg1;
+{
+ int win;
+ win = NUM2INT(arg1);
+ glutCopyColormap(win);
+ return Qnil;
+}
+
+/* GLUT state retrieval sub-API. */
+static VALUE
+glut_Get(obj,arg1)
+VALUE obj,arg1;
+{
+ GLenum type;
+ int ret;
+ type = (GLenum)NUM2INT(arg1);
+ ret = glutGet(type);
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_DeviceGet(obj,arg1)
+VALUE obj,arg1;
+{
+ GLenum type;
+ int ret;
+ type = (GLenum)NUM2INT(arg1);
+ ret = glutDeviceGet(type);
+ return INT2NUM(ret);
+}
+
+/* GLUT extension support sub-API */
+static VALUE
+glut_ExtensionSupported(obj,arg1)
+VALUE obj,arg1;
+{
+ int ret;
+ Check_Type(arg1,T_STRING);
+ ret = glutExtensionSupported(RSTRING_PTR(arg1));
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_GetModifiers(obj)
+VALUE obj;
+{
+ int ret;
+ ret = glutGetModifiers();
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_LayerGet(obj,arg1)
+VALUE obj,arg1;
+{
+ GLenum type;
+ int ret;
+ type = (GLenum)NUM2INT(arg1);
+ ret = glutLayerGet(type);
+ return INT2NUM(ret);
+}
+
+/* GLUT font sub-API */
+
+/* Some glut implementations define font enums as addresses of local functions
+ * which are then called by glut internally. This may lead to crashes or bus
+ * errors on some platforms, so to be safe we hardcode the values passed
+ * to/from ruby
+ */
+
+static inline void * bitmap_font_map(int f)
+{
+ switch (f) {
+ case 0: return (void *)GLUT_BITMAP_9_BY_15;
+ case 1: return (void *)GLUT_BITMAP_8_BY_13;
+ case 2: return (void *)GLUT_BITMAP_TIMES_ROMAN_10;
+ case 3: return (void *)GLUT_BITMAP_TIMES_ROMAN_24;
+ case 4: return (void *)GLUT_BITMAP_HELVETICA_10;
+ case 5: return (void *)GLUT_BITMAP_HELVETICA_12;
+ case 6: return (void *)GLUT_BITMAP_HELVETICA_18;
+ default:
+ rb_raise(rb_eArgError, "Unsupported font %d", f);
+ }
+
+ return (void *) 0; /* not reached */
+}
+
+static inline void * stroke_font_map(int f)
+{
+ switch (f) {
+ case 7: return (void *)GLUT_STROKE_ROMAN;
+ case 8: return (void *)GLUT_STROKE_MONO_ROMAN;
+ default:
+ rb_raise(rb_eArgError, "Unsupported font %d", f);
+ }
+
+ return (void *) 0; /* not reached */
+}
+
+static VALUE
+glut_BitmapCharacter(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int character;
+ int font;
+ font = NUM2INT(arg1);
+ character = NUM2INT(arg2);
+ glutBitmapCharacter(bitmap_font_map(font),character);
+ return Qnil;
+}
+
+static VALUE
+glut_BitmapWidth(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int font;
+ int character;
+ int ret;
+ font = NUM2INT(arg1);
+ character = NUM2INT(arg2);
+ ret = glutBitmapWidth(bitmap_font_map(font), character);
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_StrokeCharacter(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int font;
+ int character;
+ font = NUM2INT(arg1);
+ character = NUM2INT(arg2);
+ glutStrokeCharacter(stroke_font_map(font), character);
+ return Qnil;
+}
+
+static VALUE
+glut_StrokeWidth(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int font;
+ int character;
+ int ret;
+ font = NUM2INT(arg1);
+ character = NUM2INT(arg2);
+ ret = glutStrokeWidth(stroke_font_map(font), character);
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_BitmapLength(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int font;
+ int ret;
+ Check_Type(arg2,T_STRING);
+ font = NUM2INT(arg1);
+ ret = glutBitmapLength(bitmap_font_map(font), (const unsigned char*)RSTRING_PTR(arg2));
+ return INT2NUM(ret);
+}
+
+static VALUE
+glut_StrokeLength(obj,arg1,arg2)
+VALUE obj,arg1,arg2;
+{
+ int font;
+ int ret;
+ Check_Type(arg2,T_STRING);
+ font = NUM2INT(arg1);
+ ret = glutStrokeLength(stroke_font_map(font), (const unsigned char*)RSTRING_PTR(arg2));
+ return INT2NUM(ret);
+}
+
+/* GLUT pre-built models sub-API */
+static VALUE
+glut_WireSphere(obj,arg1,arg2,arg3)
+VALUE obj,arg1,arg2,arg3;
+{
+ GLdouble radius;
+ GLint slices;
+ GLint stacks;
+ radius = (GLdouble)NUM2DBL(arg1);
+ slices = (GLint)NUM2INT(arg2);
+ stacks = (GLint)NUM2INT(arg3);
+ glutWireSphere(radius, slices, stacks);
+ return Qnil;
+}
+
+static VALUE
+glut_SolidSphere(obj,arg1,arg2,arg3)
+VALUE obj,arg1,arg2,arg3;
+{
+ GLdouble radius;
+ GLint slices;
+ GLint stacks;
+ radius = (GLdouble)NUM2DBL(arg1);
+ slices = (GLint)NUM2INT(arg2);
+ stacks = (GLint)NUM2INT(arg3);
+ glutSolidSphere(radius, slices, stacks);
+ return Qnil;
+}
+
+static VALUE
+glut_WireCone(obj,arg1,arg2,arg3,arg4)
+VALUE obj,arg1,arg2,arg3,arg4;
+{
+ GLdouble base;
+ GLdouble height;
+ GLint slices;
+ GLint stacks;
+ base = (GLdouble)NUM2DBL(arg1);
+ height = (GLdouble)NUM2DBL(arg2);
+ slices = (GLint)NUM2INT(arg3);
+ stacks = (GLint)NUM2INT(arg4);
+ glutWireCone(base, height, slices, stacks);
+ return Qnil;
+}
+
+static VALUE
+glut_SolidCone(obj,arg1,arg2,arg3,arg4)
+VALUE obj,arg1,arg2,arg3,arg4;
+{
+ GLdouble base;
+ GLdouble height;
+ GLint slices;
+ GLint stacks;
+ base = (GLdouble)NUM2DBL(arg1);
+ height = (GLdouble)NUM2DBL(arg2);
+ slices = (GLint)NUM2INT(arg3);
+ stacks = (GLint)NUM2INT(arg4);
+ glutSolidCone(base, height, slices, stacks);
+ return Qnil;
+}
+
+static VALUE
+glut_WireCube(obj,arg1)
+VALUE obj,arg1;
+{
+ GLdouble size;
+ size = (GLdouble)NUM2DBL(arg1);
+ glutWireCube(size);
+ return Qnil;
+}
+
+static VALUE
+glut_SolidCube(obj,arg1)
+VALUE obj,arg1;
+{
+ GLdouble size;
+ size = (GLdouble)NUM2DBL(arg1);
+ glutSolidCube(size);
+ return Qnil;
+}
+
+static VALUE
+glut_WireTorus(obj,arg1,arg2,arg3,arg4)
+VALUE obj,arg1,arg2,arg3,arg4;
+{
+ GLdouble innerRadius;
+ GLdouble outerRadius;
+ GLint sides;
+ GLint rings;
+ innerRadius = (GLdouble)NUM2DBL(arg1);
+ outerRadius = (GLdouble)NUM2DBL(arg2);
+ sides = (GLint)NUM2INT(arg3);
+ rings = (GLint)NUM2INT(arg4);
+ glutWireTorus(innerRadius, outerRadius, sides, rings);
+ return Qnil;
+}
+
+static VALUE
+glut_SolidTorus(obj,arg1,arg2,arg3,arg4)
+VALUE obj,arg1,arg2,arg3,arg4;
+{
+ GLdouble innerRadius;
+ GLdouble outerRadius;
+ GLint sides;
+ GLint rings;
+ innerRadius = (GLdouble)NUM2DBL(arg1);
+ outerRadius = (GLdouble)NUM2DBL(arg2);
+ sides = (GLint)NUM2INT(arg3);
+ rings = (GLint)NUM2INT(arg4);
+ glutSolidTorus(innerRadius, outerRadius, sides, rings);
+ return Qnil;
+}
+
+GLUT_SIMPLE_FUNCTION(WireDodecahedron)
+GLUT_SIMPLE_FUNCTION(SolidDodecahedron)
+GLUT_SIMPLE_FUNCTION(WireOctahedron)
+GLUT_SIMPLE_FUNCTION(SolidOctahedron)
+GLUT_SIMPLE_FUNCTION(WireTetrahedron)
+GLUT_SIMPLE_FUNCTION(SolidTetrahedron)
+GLUT_SIMPLE_FUNCTION(WireIcosahedron)
+GLUT_SIMPLE_FUNCTION(SolidIcosahedron)
+
+static VALUE
+glut_WireTeapot(obj,arg1)
+VALUE obj,arg1;
+{
+ GLdouble size;
+ size = (GLdouble)NUM2DBL(arg1);
+ glutWireTeapot(size);
+ return Qnil;
+}
+
+static VALUE
+glut_SolidTeapot(obj,arg1)
+VALUE obj,arg1;
+{
+ GLdouble size;
+ size = (GLdouble)NUM2DBL(arg1);
+ glutSolidTeapot(size);
+ return Qnil;
+}
+
+/* GLUT video resize sub-API. */
+static VALUE
+glut_VideoResizeGet(obj,arg1)
+VALUE obj,arg1;
+{
+ GLenum param;
+ int ret;
+ param = (GLenum)NUM2INT(arg1);
+ ret = glutVideoResizeGet(param);
+ return INT2NUM(ret);
+}
+
+GLUT_SIMPLE_FUNCTION(SetupVideoResizing)
+GLUT_SIMPLE_FUNCTION(StopVideoResizing)
+
+static VALUE
+glut_VideoResize(obj,arg1,arg2,arg3,arg4)
+VALUE obj,arg1,arg2,arg3,arg4;
+{
+ int x;
+ int y;
+ int width;
+ int height;
+ x = NUM2INT(arg1);
+ y = NUM2INT(arg2);
+ width = NUM2INT(arg3);
+ height = NUM2INT(arg4);
+ glutVideoResize(x,y, width, height);
+ return Qnil;
+}
+
+static VALUE
+glut_VideoPan(obj,arg1,arg2,arg3,arg4)
+VALUE obj,arg1,arg2,arg3,arg4;
+{
+ int x;
+ int y;
+ int width;
+ int height;
+ x = NUM2INT(arg1);
+ y = NUM2INT(arg2);
+ width = NUM2INT(arg3);
+ height = NUM2INT(arg4);
+ glutVideoPan(x,y, width, height);
+ return Qnil;
+}
+
+/* GLUT debugging sub-API. */
+GLUT_SIMPLE_FUNCTION(ReportErrors)
+
+static VALUE
+glut_GameModeString(obj,arg1)
+VALUE obj,arg1;
+{
+ Check_Type(arg1,T_STRING);
+ glutGameModeString((const char*)RSTRING_PTR(arg1));
+ return Qnil;
+}
+
+GLUT_SIMPLE_FUNCTION(EnterGameMode)
+GLUT_SIMPLE_FUNCTION(LeaveGameMode)
+
+static VALUE
+glut_GameModeGet(obj,arg1)
+VALUE obj,arg1;
+{
+ GLenum info;
+ int i;
+ info = (GLenum)NUM2INT(arg1);
+ i = glutGameModeGet(info);
+ return INT2NUM(i);
+}
+
+static VALUE
+glut_SetKeyRepeat(obj,arg1)
+VALUE obj,arg1;
+{
+ GLenum repeatMode;
+ repeatMode = (int) NUM2INT(arg1);
+ glutSetKeyRepeat(repeatMode);
+ return Qnil;
+}
+
+static VALUE
+glut_IgnoreKeyRepeat(obj,arg1)
+VALUE obj,arg1;
+{
+ GLenum ignore;
+ ignore = (int) NUM2INT(arg1);
+ glutIgnoreKeyRepeat(ignore);
+ return Qnil;
+}
+
+static VALUE
+glut_PostWindowOverlayRedisplay(obj,arg1)
+VALUE obj,arg1;
+{
+ int win;
+ win = (int) NUM2INT(arg1);
+ glutPostWindowOverlayRedisplay(win);
+ return Qnil;
+}
+
+static VALUE
+glut_PostWindowRedisplay(obj,arg1)
+VALUE obj,arg1;
+{
+ int win;
+ win = (int) NUM2INT(arg1);
+ glutPostWindowRedisplay(win);
+ return Qnil;
+}
+
+void Init_glut_callbacks(void);
+void Init_glut_ext(void);
+
+void Init_glut() {
+ VALUE mGlut;
+
+ call_id = rb_intern("call");
+ mGlut = rb_define_module("Glut");
+
+ menu_callback = rb_ary_new();
+ rb_global_variable(&menu_callback);
+
+ rb_define_module_function(mGlut, "glutInit", glut_Init, -1);
+ rb_define_module_function(mGlut, "glutInitDisplayMode", glut_InitDisplayMode, 1);
+ rb_define_module_function(mGlut, "glutInitDisplayString", glut_InitDisplayString, 1);
+ rb_define_module_function(mGlut, "glutInitWindowPosition", glut_InitWindowPosition, 2);
+ rb_define_module_function(mGlut, "glutInitWindowSize", glut_InitWindowSize, 2);
+ rb_define_module_function(mGlut, "glutMainLoop", glut_MainLoop, 0);
+ rb_define_module_function(mGlut, "glutCheckLoop", glut_CheckLoop, 0);
+ rb_define_module_function(mGlut, "glutGameModeString", glut_GameModeString, 1);
+ rb_define_module_function(mGlut, "glutEnterGameMode", glut_EnterGameMode, 0);
+ rb_define_module_function(mGlut, "glutLeaveGameMode", glut_LeaveGameMode, 0);
+ rb_define_module_function(mGlut, "glutCreateWindow", glut_CreateWindow, -1);
+ rb_define_module_function(mGlut, "glutCreateSubWindow", glut_CreateSubWindow, 5);
+ rb_define_module_function(mGlut, "glutDestroyWindow", glut_DestroyWindow, 1);
+ rb_define_module_function(mGlut, "glutPostRedisplay", glut_PostRedisplay, 0);
+ rb_define_module_function(mGlut, "glutSwapBuffers", glut_SwapBuffers, 0);
+ rb_define_module_function(mGlut, "glutGetWindow", glut_GetWindow, 0);
+ rb_define_module_function(mGlut, "glutSetWindow", glut_SetWindow, 1);
+ rb_define_module_function(mGlut, "glutSetWindowTitle", glut_SetWindowTitle, 1);
+ rb_define_module_function(mGlut, "glutSetIconTitle", glut_SetIconTitle, 1);
+ rb_define_module_function(mGlut, "glutPositionWindow", glut_PositionWindow, 2);
+ rb_define_module_function(mGlut, "glutReshapeWindow", glut_ReshapeWindow, 2);
+ rb_define_module_function(mGlut, "glutPopWindow", glut_PopWindow, 0);
+ rb_define_module_function(mGlut, "glutPushWindow", glut_PushWindow, 0);
+ rb_define_module_function(mGlut, "glutIconifyWindow", glut_IconifyWindow, 0);
+ rb_define_module_function(mGlut, "glutShowWindow", glut_ShowWindow, 0);
+ rb_define_module_function(mGlut, "glutHideWindow", glut_HideWindow, 0);
+ rb_define_module_function(mGlut, "glutFullScreen", glut_FullScreen, 0);
+ rb_define_module_function(mGlut, "glutSetCursor", glut_SetCursor, 1);
+ rb_define_module_function(mGlut, "glutWarpPointer", glut_WarpPointer, 2);
+ rb_define_module_function(mGlut, "glutEstablishOverlay", glut_EstablishOverlay, 0);
+ rb_define_module_function(mGlut, "glutRemoveOverlay", glut_RemoveOverlay, 0);
+ rb_define_module_function(mGlut, "glutUseLayer", glut_UseLayer, 1);
+ rb_define_module_function(mGlut, "glutPostOverlayRedisplay", glut_PostOverlayRedisplay, 0);
+ rb_define_module_function(mGlut, "glutShowOverlay", glut_ShowOverlay, 0);
+ rb_define_module_function(mGlut, "glutHideOverlay", glut_HideOverlay, 0);
+ rb_define_module_function(mGlut, "glutCreateMenu", glut_CreateMenu, 1);
+ rb_define_module_function(mGlut, "glutDestroyMenu", glut_DestroyMenu, 1);
+ rb_define_module_function(mGlut, "glutGetMenu", glut_GetMenu, 0);
+ rb_define_module_function(mGlut, "glutSetMenu", glut_SetMenu, 1);
+ rb_define_module_function(mGlut, "glutAddMenuEntry", glut_AddMenuEntry, 2);
+ rb_define_module_function(mGlut, "glutAddSubMenu", glut_AddSubMenu, 2);
+ rb_define_module_function(mGlut, "glutChangeToMenuEntry", glut_ChangeToMenuEntry, 3);
+ rb_define_module_function(mGlut, "glutChangeToSubMenu", glut_ChangeToSubMenu, 3);
+ rb_define_module_function(mGlut, "glutRemoveMenuItem", glut_RemoveMenuItem, 1);
+ rb_define_module_function(mGlut, "glutAttachMenu", glut_AttachMenu, 1);
+ rb_define_module_function(mGlut, "glutDetachMenu", glut_DetachMenu, 1);
+ rb_define_module_function(mGlut, "glutSetColor", glut_SetColor, 4);
+ rb_define_module_function(mGlut, "glutGetColor", glut_GetColor, 2);
+ rb_define_module_function(mGlut, "glutCopyColormap", glut_CopyColormap, 1);
+ rb_define_module_function(mGlut, "glutGet", glut_Get, 1);
+ rb_define_module_function(mGlut, "glutDeviceGet", glut_DeviceGet, 1);
+ rb_define_module_function(mGlut, "glutExtensionSupported", glut_ExtensionSupported, 1);
+ rb_define_module_function(mGlut, "glutGetModifiers", glut_GetModifiers, 0);
+ rb_define_module_function(mGlut, "glutLayerGet", glut_LayerGet, 1);
+ rb_define_module_function(mGlut, "glutBitmapCharacter", glut_BitmapCharacter, 2);
+ rb_define_module_function(mGlut, "glutBitmapWidth", glut_BitmapWidth, 2);
+ rb_define_module_function(mGlut, "glutStrokeCharacter", glut_StrokeCharacter, 2);
+ rb_define_module_function(mGlut, "glutStrokeWidth", glut_StrokeWidth, 2);
+ rb_define_module_function(mGlut, "glutBitmapLength", glut_BitmapLength, 2);
+ rb_define_module_function(mGlut, "glutStrokeLength", glut_StrokeLength, 2);
+ rb_define_module_function(mGlut, "glutWireSphere", glut_WireSphere, 3);
+ rb_define_module_function(mGlut, "glutSolidSphere", glut_SolidSphere, 3);
+ rb_define_module_function(mGlut, "glutWireCone", glut_WireCone, 4);
+ rb_define_module_function(mGlut, "glutSolidCone", glut_SolidCone, 4);
+ rb_define_module_function(mGlut, "glutWireCube", glut_WireCube, 1);
+ rb_define_module_function(mGlut, "glutSolidCube", glut_SolidCube, 1);
+ rb_define_module_function(mGlut, "glutWireTorus", glut_WireTorus, 4);
+ rb_define_module_function(mGlut, "glutSolidTorus", glut_SolidTorus, 4);
+ rb_define_module_function(mGlut, "glutWireDodecahedron", glut_WireDodecahedron, 0);
+ rb_define_module_function(mGlut, "glutSolidDodecahedron", glut_SolidDodecahedron, 0);
+ rb_define_module_function(mGlut, "glutWireTeapot", glut_WireTeapot, 1);
+ rb_define_module_function(mGlut, "glutSolidTeapot", glut_SolidTeapot, 1);
+ rb_define_module_function(mGlut, "glutWireOctahedron", glut_WireOctahedron, 0);
+ rb_define_module_function(mGlut, "glutSolidOctahedron", glut_SolidOctahedron, 0);
+ rb_define_module_function(mGlut, "glutWireTetrahedron", glut_WireTetrahedron, 0);
+ rb_define_module_function(mGlut, "glutSolidTetrahedron", glut_SolidTetrahedron, 0);
+ rb_define_module_function(mGlut, "glutWireIcosahedron", glut_WireIcosahedron, 0);
+ rb_define_module_function(mGlut, "glutSolidIcosahedron", glut_SolidIcosahedron, 0);
+ rb_define_module_function(mGlut, "glutVideoResizeGet", glut_VideoResizeGet, 1);
+ rb_define_module_function(mGlut, "glutSetupVideoResizing", glut_SetupVideoResizing, 0);
+ rb_define_module_function(mGlut, "glutStopVideoResizing", glut_StopVideoResizing, 0);
+ rb_define_module_function(mGlut, "glutVideoResize", glut_VideoResize, 4);
+ rb_define_module_function(mGlut, "glutVideoPan", glut_VideoPan, 4);
+ rb_define_module_function(mGlut, "glutReportErrors", glut_ReportErrors, 0);
+
+ rb_define_module_function(mGlut, "glutGameModeGet", glut_GameModeGet, 1);
+ rb_define_module_function(mGlut, "glutSetKeyRepeat", glut_SetKeyRepeat, 1);
+ rb_define_module_function(mGlut, "glutIgnoreKeyRepeat", glut_IgnoreKeyRepeat, 1);
+ rb_define_module_function(mGlut, "glutPostWindowOverlayRedisplay", glut_PostWindowOverlayRedisplay, 1);
+ rb_define_module_function(mGlut, "glutPostWindowRedisplay", glut_PostWindowRedisplay, 1);
+
+ rb_define_const(mGlut, "GLUT_API_VERSION", INT2NUM(GLUT_API_VERSION));
+ rb_define_const(mGlut, "GLUT_XLIB_IMPLEMENTATION", INT2NUM(GLUT_XLIB_IMPLEMENTATION));
+ rb_define_const(mGlut, "GLUT_RGB", INT2NUM(GLUT_RGB));
+ rb_define_const(mGlut, "GLUT_RGBA", INT2NUM(GLUT_RGBA));
+ rb_define_const(mGlut, "GLUT_INDEX", INT2NUM(GLUT_INDEX));
+ rb_define_const(mGlut, "GLUT_SINGLE", INT2NUM(GLUT_SINGLE));
+ rb_define_const(mGlut, "GLUT_DOUBLE", INT2NUM(GLUT_DOUBLE));
+ rb_define_const(mGlut, "GLUT_ACCUM", INT2NUM(GLUT_ACCUM));
+ rb_define_const(mGlut, "GLUT_ALPHA", INT2NUM(GLUT_ALPHA));
+ rb_define_const(mGlut, "GLUT_DEPTH", INT2NUM(GLUT_DEPTH));
+ rb_define_const(mGlut, "GLUT_STENCIL", INT2NUM(GLUT_STENCIL));
+ rb_define_const(mGlut, "GLUT_MULTISAMPLE", INT2NUM(GLUT_MULTISAMPLE));
+ rb_define_const(mGlut, "GLUT_STEREO", INT2NUM(GLUT_STEREO));
+ rb_define_const(mGlut, "GLUT_LUMINANCE", INT2NUM(GLUT_LUMINANCE));
+ rb_define_const(mGlut, "GLUT_LEFT_BUTTON", INT2NUM(GLUT_LEFT_BUTTON));
+ rb_define_const(mGlut, "GLUT_MIDDLE_BUTTON", INT2NUM(GLUT_MIDDLE_BUTTON));
+ rb_define_const(mGlut, "GLUT_RIGHT_BUTTON", INT2NUM(GLUT_RIGHT_BUTTON));
+ rb_define_const(mGlut, "GLUT_DOWN", INT2NUM(GLUT_DOWN));
+ rb_define_const(mGlut, "GLUT_UP", INT2NUM(GLUT_UP));
+ rb_define_const(mGlut, "GLUT_KEY_F1", INT2NUM(GLUT_KEY_F1));
+ rb_define_const(mGlut, "GLUT_KEY_F2", INT2NUM(GLUT_KEY_F2));
+ rb_define_const(mGlut, "GLUT_KEY_F3", INT2NUM(GLUT_KEY_F3));
+ rb_define_const(mGlut, "GLUT_KEY_F4", INT2NUM(GLUT_KEY_F4));
+ rb_define_const(mGlut, "GLUT_KEY_F5", INT2NUM(GLUT_KEY_F5));
+ rb_define_const(mGlut, "GLUT_KEY_F6", INT2NUM(GLUT_KEY_F6));
+ rb_define_const(mGlut, "GLUT_KEY_F7", INT2NUM(GLUT_KEY_F7));
+ rb_define_const(mGlut, "GLUT_KEY_F8", INT2NUM(GLUT_KEY_F8));
+ rb_define_const(mGlut, "GLUT_KEY_F9", INT2NUM(GLUT_KEY_F9));
+ rb_define_const(mGlut, "GLUT_KEY_F10", INT2NUM(GLUT_KEY_F10));
+ rb_define_const(mGlut, "GLUT_KEY_F11", INT2NUM(GLUT_KEY_F11));
+ rb_define_const(mGlut, "GLUT_KEY_F12", INT2NUM(GLUT_KEY_F12));
+ rb_define_const(mGlut, "GLUT_KEY_LEFT", INT2NUM(GLUT_KEY_LEFT));
+ rb_define_const(mGlut, "GLUT_KEY_UP", INT2NUM(GLUT_KEY_UP));
+ rb_define_const(mGlut, "GLUT_KEY_RIGHT", INT2NUM(GLUT_KEY_RIGHT));
+ rb_define_const(mGlut, "GLUT_KEY_DOWN", INT2NUM(GLUT_KEY_DOWN));
+ rb_define_const(mGlut, "GLUT_KEY_PAGE_UP", INT2NUM(GLUT_KEY_PAGE_UP));
+ rb_define_const(mGlut, "GLUT_KEY_PAGE_DOWN", INT2NUM(GLUT_KEY_PAGE_DOWN));
+ rb_define_const(mGlut, "GLUT_KEY_HOME", INT2NUM(GLUT_KEY_HOME));
+ rb_define_const(mGlut, "GLUT_KEY_END", INT2NUM(GLUT_KEY_END));
+ rb_define_const(mGlut, "GLUT_KEY_INSERT", INT2NUM(GLUT_KEY_INSERT));
+ rb_define_const(mGlut, "GLUT_LEFT", INT2NUM(GLUT_LEFT));
+ rb_define_const(mGlut, "GLUT_ENTERED", INT2NUM(GLUT_ENTERED));
+ rb_define_const(mGlut, "GLUT_MENU_NOT_IN_USE", INT2NUM(GLUT_MENU_NOT_IN_USE));
+ rb_define_const(mGlut, "GLUT_MENU_IN_USE", INT2NUM(GLUT_MENU_IN_USE));
+ rb_define_const(mGlut, "GLUT_NOT_VISIBLE", INT2NUM(GLUT_NOT_VISIBLE));
+ rb_define_const(mGlut, "GLUT_VISIBLE", INT2NUM(GLUT_VISIBLE));
+ rb_define_const(mGlut, "GLUT_HIDDEN", INT2NUM(GLUT_HIDDEN));
+ rb_define_const(mGlut, "GLUT_FULLY_RETAINED", INT2NUM(GLUT_FULLY_RETAINED));
+ rb_define_const(mGlut, "GLUT_PARTIALLY_RETAINED", INT2NUM(GLUT_PARTIALLY_RETAINED));
+ rb_define_const(mGlut, "GLUT_FULLY_COVERED", INT2NUM(GLUT_FULLY_COVERED));
+ rb_define_const(mGlut, "GLUT_RED", INT2NUM(GLUT_RED));
+ rb_define_const(mGlut, "GLUT_GREEN", INT2NUM(GLUT_GREEN));
+ rb_define_const(mGlut, "GLUT_BLUE", INT2NUM(GLUT_BLUE));
+ rb_define_const(mGlut, "GLUT_WINDOW_X", INT2NUM(GLUT_WINDOW_X));
+ rb_define_const(mGlut, "GLUT_WINDOW_Y", INT2NUM(GLUT_WINDOW_Y));
+ rb_define_const(mGlut, "GLUT_WINDOW_WIDTH", INT2NUM(GLUT_WINDOW_WIDTH));
+ rb_define_const(mGlut, "GLUT_WINDOW_HEIGHT", INT2NUM(GLUT_WINDOW_HEIGHT));
+ rb_define_const(mGlut, "GLUT_WINDOW_BUFFER_SIZE", INT2NUM(GLUT_WINDOW_BUFFER_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_STENCIL_SIZE", INT2NUM(GLUT_WINDOW_STENCIL_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_DEPTH_SIZE", INT2NUM(GLUT_WINDOW_DEPTH_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_RED_SIZE", INT2NUM(GLUT_WINDOW_RED_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_GREEN_SIZE", INT2NUM(GLUT_WINDOW_GREEN_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_BLUE_SIZE", INT2NUM(GLUT_WINDOW_BLUE_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_ALPHA_SIZE", INT2NUM(GLUT_WINDOW_ALPHA_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_ACCUM_RED_SIZE", INT2NUM(GLUT_WINDOW_ACCUM_RED_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_ACCUM_GREEN_SIZE", INT2NUM(GLUT_WINDOW_ACCUM_GREEN_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_ACCUM_BLUE_SIZE", INT2NUM(GLUT_WINDOW_ACCUM_BLUE_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_ACCUM_ALPHA_SIZE", INT2NUM(GLUT_WINDOW_ACCUM_ALPHA_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_DOUBLEBUFFER", INT2NUM(GLUT_WINDOW_DOUBLEBUFFER));
+ rb_define_const(mGlut, "GLUT_WINDOW_RGBA", INT2NUM(GLUT_WINDOW_RGBA));
+ rb_define_const(mGlut, "GLUT_WINDOW_PARENT", INT2NUM(GLUT_WINDOW_PARENT));
+ rb_define_const(mGlut, "GLUT_WINDOW_NUM_CHILDREN", INT2NUM(GLUT_WINDOW_NUM_CHILDREN));
+ rb_define_const(mGlut, "GLUT_WINDOW_COLORMAP_SIZE", INT2NUM(GLUT_WINDOW_COLORMAP_SIZE));
+ rb_define_const(mGlut, "GLUT_WINDOW_NUM_SAMPLES", INT2NUM(GLUT_WINDOW_NUM_SAMPLES));
+ rb_define_const(mGlut, "GLUT_WINDOW_STEREO", INT2NUM(GLUT_WINDOW_STEREO));
+ rb_define_const(mGlut, "GLUT_WINDOW_CURSOR", INT2NUM(GLUT_WINDOW_CURSOR));
+ rb_define_const(mGlut, "GLUT_SCREEN_WIDTH", INT2NUM(GLUT_SCREEN_WIDTH));
+ rb_define_const(mGlut, "GLUT_SCREEN_HEIGHT", INT2NUM(GLUT_SCREEN_HEIGHT));
+ rb_define_const(mGlut, "GLUT_SCREEN_WIDTH_MM", INT2NUM(GLUT_SCREEN_WIDTH_MM));
+ rb_define_const(mGlut, "GLUT_SCREEN_HEIGHT_MM", INT2NUM(GLUT_SCREEN_HEIGHT_MM));
+ rb_define_const(mGlut, "GLUT_MENU_NUM_ITEMS", INT2NUM(GLUT_MENU_NUM_ITEMS));
+ rb_define_const(mGlut, "GLUT_DISPLAY_MODE_POSSIBLE", INT2NUM(GLUT_DISPLAY_MODE_POSSIBLE));
+ rb_define_const(mGlut, "GLUT_INIT_WINDOW_X", INT2NUM(GLUT_INIT_WINDOW_X));
+ rb_define_const(mGlut, "GLUT_INIT_WINDOW_Y", INT2NUM(GLUT_INIT_WINDOW_Y));
+ rb_define_const(mGlut, "GLUT_INIT_WINDOW_WIDTH", INT2NUM(GLUT_INIT_WINDOW_WIDTH));
+ rb_define_const(mGlut, "GLUT_INIT_WINDOW_HEIGHT", INT2NUM(GLUT_INIT_WINDOW_HEIGHT));
+ rb_define_const(mGlut, "GLUT_INIT_DISPLAY_MODE", INT2NUM(GLUT_INIT_DISPLAY_MODE));
+ rb_define_const(mGlut, "GLUT_ELAPSED_TIME", INT2NUM(GLUT_ELAPSED_TIME));
+ rb_define_const(mGlut, "GLUT_HAS_KEYBOARD", INT2NUM(GLUT_HAS_KEYBOARD));
+ rb_define_const(mGlut, "GLUT_HAS_MOUSE", INT2NUM(GLUT_HAS_MOUSE));
+ rb_define_const(mGlut, "GLUT_HAS_SPACEBALL", INT2NUM(GLUT_HAS_SPACEBALL));
+ rb_define_const(mGlut, "GLUT_HAS_DIAL_AND_BUTTON_BOX", INT2NUM(GLUT_HAS_DIAL_AND_BUTTON_BOX));
+ rb_define_const(mGlut, "GLUT_HAS_TABLET", INT2NUM(GLUT_HAS_TABLET));
+ rb_define_const(mGlut, "GLUT_NUM_MOUSE_BUTTONS", INT2NUM(GLUT_NUM_MOUSE_BUTTONS));
+ rb_define_const(mGlut, "GLUT_NUM_SPACEBALL_BUTTONS", INT2NUM(GLUT_NUM_SPACEBALL_BUTTONS));
+ rb_define_const(mGlut, "GLUT_NUM_BUTTON_BOX_BUTTONS", INT2NUM(GLUT_NUM_BUTTON_BOX_BUTTONS));
+ rb_define_const(mGlut, "GLUT_NUM_DIALS", INT2NUM(GLUT_NUM_DIALS));
+ rb_define_const(mGlut, "GLUT_NUM_TABLET_BUTTONS", INT2NUM(GLUT_NUM_TABLET_BUTTONS));
+ rb_define_const(mGlut, "GLUT_OVERLAY_POSSIBLE", INT2NUM(GLUT_OVERLAY_POSSIBLE));
+ rb_define_const(mGlut, "GLUT_LAYER_IN_USE", INT2NUM(GLUT_LAYER_IN_USE));
+ rb_define_const(mGlut, "GLUT_HAS_OVERLAY", INT2NUM(GLUT_HAS_OVERLAY));
+ rb_define_const(mGlut, "GLUT_TRANSPARENT_INDEX", INT2NUM(GLUT_TRANSPARENT_INDEX));
+ rb_define_const(mGlut, "GLUT_NORMAL_DAMAGED", INT2NUM(GLUT_NORMAL_DAMAGED));
+ rb_define_const(mGlut, "GLUT_OVERLAY_DAMAGED", INT2NUM(GLUT_OVERLAY_DAMAGED));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_POSSIBLE", INT2NUM(GLUT_VIDEO_RESIZE_POSSIBLE));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_IN_USE", INT2NUM(GLUT_VIDEO_RESIZE_IN_USE));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_X_DELTA", INT2NUM(GLUT_VIDEO_RESIZE_X_DELTA));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_Y_DELTA", INT2NUM(GLUT_VIDEO_RESIZE_Y_DELTA));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_WIDTH_DELTA", INT2NUM(GLUT_VIDEO_RESIZE_WIDTH_DELTA));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_HEIGHT_DELTA", INT2NUM(GLUT_VIDEO_RESIZE_HEIGHT_DELTA));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_X", INT2NUM(GLUT_VIDEO_RESIZE_X));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_Y", INT2NUM(GLUT_VIDEO_RESIZE_Y));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_WIDTH", INT2NUM(GLUT_VIDEO_RESIZE_WIDTH));
+ rb_define_const(mGlut, "GLUT_VIDEO_RESIZE_HEIGHT", INT2NUM(GLUT_VIDEO_RESIZE_HEIGHT));
+ rb_define_const(mGlut, "GLUT_NORMAL", INT2NUM(GLUT_NORMAL));
+ rb_define_const(mGlut, "GLUT_OVERLAY", INT2NUM(GLUT_OVERLAY));
+ rb_define_const(mGlut, "GLUT_ACTIVE_SHIFT", INT2NUM(GLUT_ACTIVE_SHIFT));
+ rb_define_const(mGlut, "GLUT_ACTIVE_CTRL", INT2NUM(GLUT_ACTIVE_CTRL));
+ rb_define_const(mGlut, "GLUT_ACTIVE_ALT", INT2NUM(GLUT_ACTIVE_ALT));
+ rb_define_const(mGlut, "GLUT_CURSOR_RIGHT_ARROW", INT2NUM(GLUT_CURSOR_RIGHT_ARROW));
+ rb_define_const(mGlut, "GLUT_CURSOR_LEFT_ARROW", INT2NUM(GLUT_CURSOR_LEFT_ARROW));
+ rb_define_const(mGlut, "GLUT_CURSOR_INFO", INT2NUM(GLUT_CURSOR_INFO));
+ rb_define_const(mGlut, "GLUT_CURSOR_DESTROY", INT2NUM(GLUT_CURSOR_DESTROY));
+ rb_define_const(mGlut, "GLUT_CURSOR_HELP", INT2NUM(GLUT_CURSOR_HELP));
+ rb_define_const(mGlut, "GLUT_CURSOR_CYCLE", INT2NUM(GLUT_CURSOR_CYCLE));
+ rb_define_const(mGlut, "GLUT_CURSOR_SPRAY", INT2NUM(GLUT_CURSOR_SPRAY));
+ rb_define_const(mGlut, "GLUT_CURSOR_WAIT", INT2NUM(GLUT_CURSOR_WAIT));
+ rb_define_const(mGlut, "GLUT_CURSOR_TEXT", INT2NUM(GLUT_CURSOR_TEXT));
+ rb_define_const(mGlut, "GLUT_CURSOR_CROSSHAIR", INT2NUM(GLUT_CURSOR_CROSSHAIR));
+ rb_define_const(mGlut, "GLUT_CURSOR_UP_DOWN", INT2NUM(GLUT_CURSOR_UP_DOWN));
+ rb_define_const(mGlut, "GLUT_CURSOR_LEFT_RIGHT", INT2NUM(GLUT_CURSOR_LEFT_RIGHT));
+ rb_define_const(mGlut, "GLUT_CURSOR_TOP_SIDE", INT2NUM(GLUT_CURSOR_TOP_SIDE));
+ rb_define_const(mGlut, "GLUT_CURSOR_BOTTOM_SIDE", INT2NUM(GLUT_CURSOR_BOTTOM_SIDE));
+ rb_define_const(mGlut, "GLUT_CURSOR_LEFT_SIDE", INT2NUM(GLUT_CURSOR_LEFT_SIDE));
+ rb_define_const(mGlut, "GLUT_CURSOR_RIGHT_SIDE", INT2NUM(GLUT_CURSOR_RIGHT_SIDE));
+ rb_define_const(mGlut, "GLUT_CURSOR_TOP_LEFT_CORNER", INT2NUM(GLUT_CURSOR_TOP_LEFT_CORNER));
+ rb_define_const(mGlut, "GLUT_CURSOR_TOP_RIGHT_CORNER", INT2NUM(GLUT_CURSOR_TOP_RIGHT_CORNER));
+ rb_define_const(mGlut, "GLUT_CURSOR_BOTTOM_RIGHT_CORNER", INT2NUM(GLUT_CURSOR_BOTTOM_RIGHT_CORNER));
+ rb_define_const(mGlut, "GLUT_CURSOR_BOTTOM_LEFT_CORNER", INT2NUM(GLUT_CURSOR_BOTTOM_LEFT_CORNER));
+ rb_define_const(mGlut, "GLUT_CURSOR_INHERIT", INT2NUM(GLUT_CURSOR_INHERIT));
+ rb_define_const(mGlut, "GLUT_CURSOR_NONE", INT2NUM(GLUT_CURSOR_NONE));
+ rb_define_const(mGlut, "GLUT_CURSOR_FULL_CROSSHAIR", INT2NUM(GLUT_CURSOR_FULL_CROSSHAIR));
+
+ /* hardcoded, see bitmap_font_map for explanation */
+ rb_define_const(mGlut, "GLUT_BITMAP_9_BY_15", INT2NUM(0));
+ rb_define_const(mGlut, "GLUT_BITMAP_8_BY_13", INT2NUM(1));
+ rb_define_const(mGlut, "GLUT_BITMAP_TIMES_ROMAN_10", INT2NUM(2));
+ rb_define_const(mGlut, "GLUT_BITMAP_TIMES_ROMAN_24", INT2NUM(3));
+ rb_define_const(mGlut, "GLUT_BITMAP_HELVETICA_10", INT2NUM(4));
+ rb_define_const(mGlut, "GLUT_BITMAP_HELVETICA_12", INT2NUM(5));
+ rb_define_const(mGlut, "GLUT_BITMAP_HELVETICA_18", INT2NUM(6));
+ rb_define_const(mGlut, "GLUT_STROKE_ROMAN", INT2NUM(7));
+ rb_define_const(mGlut, "GLUT_STROKE_MONO_ROMAN", INT2NUM(8));
+
+ rb_define_const(mGlut, "GLUT_WINDOW_FORMAT_ID", INT2NUM(GLUT_WINDOW_FORMAT_ID));
+ rb_define_const(mGlut, "GLUT_DEVICE_IGNORE_KEY_REPEAT", INT2NUM(GLUT_DEVICE_IGNORE_KEY_REPEAT));
+ rb_define_const(mGlut, "GLUT_DEVICE_KEY_REPEAT", INT2NUM(GLUT_DEVICE_KEY_REPEAT));
+ rb_define_const(mGlut, "GLUT_HAS_JOYSTICK", INT2NUM(GLUT_HAS_JOYSTICK));
+ rb_define_const(mGlut, "GLUT_OWNS_JOYSTICK", INT2NUM(GLUT_OWNS_JOYSTICK));
+ rb_define_const(mGlut, "GLUT_JOYSTICK_BUTTONS", INT2NUM(GLUT_JOYSTICK_BUTTONS));
+ rb_define_const(mGlut, "GLUT_JOYSTICK_AXES", INT2NUM(GLUT_JOYSTICK_AXES));
+ rb_define_const(mGlut, "GLUT_JOYSTICK_POLL_RATE", INT2NUM(GLUT_JOYSTICK_POLL_RATE));
+ rb_define_const(mGlut, "GLUT_KEY_REPEAT_OFF", INT2NUM(GLUT_KEY_REPEAT_OFF));
+ rb_define_const(mGlut, "GLUT_KEY_REPEAT_ON", INT2NUM(GLUT_KEY_REPEAT_ON));
+ rb_define_const(mGlut, "GLUT_KEY_REPEAT_DEFAULT", INT2NUM(GLUT_KEY_REPEAT_DEFAULT));
+ rb_define_const(mGlut, "GLUT_JOYSTICK_BUTTON_A", INT2NUM(GLUT_JOYSTICK_BUTTON_A));
+ rb_define_const(mGlut, "GLUT_JOYSTICK_BUTTON_B", INT2NUM(GLUT_JOYSTICK_BUTTON_B));
+ rb_define_const(mGlut, "GLUT_JOYSTICK_BUTTON_C", INT2NUM(GLUT_JOYSTICK_BUTTON_C));
+ rb_define_const(mGlut, "GLUT_JOYSTICK_BUTTON_D", INT2NUM(GLUT_JOYSTICK_BUTTON_D));
+ rb_define_const(mGlut, "GLUT_GAME_MODE_ACTIVE", INT2NUM(GLUT_GAME_MODE_ACTIVE));
+ rb_define_const(mGlut, "GLUT_GAME_MODE_POSSIBLE", INT2NUM(GLUT_GAME_MODE_POSSIBLE));
+ rb_define_const(mGlut, "GLUT_GAME_MODE_WIDTH", INT2NUM(GLUT_GAME_MODE_WIDTH));
+ rb_define_const(mGlut, "GLUT_GAME_MODE_HEIGHT", INT2NUM(GLUT_GAME_MODE_HEIGHT));
+ rb_define_const(mGlut, "GLUT_GAME_MODE_PIXEL_DEPTH", INT2NUM(GLUT_GAME_MODE_PIXEL_DEPTH));
+ rb_define_const(mGlut, "GLUT_GAME_MODE_REFRESH_RATE", INT2NUM(GLUT_GAME_MODE_REFRESH_RATE));
+ rb_define_const(mGlut, "GLUT_GAME_MODE_DISPLAY_CHANGED", INT2NUM(GLUT_GAME_MODE_DISPLAY_CHANGED));
+
+ // Some OSX specific constants
+#ifdef GLUT_NO_RECOVERY
+ rb_define_const(mGlut, "GLUT_NO_RECOVERY", INT2NUM(GLUT_NO_RECOVERY));
+#endif
+#ifdef GLUT_3_2_CORE_PROFILE
+ rb_define_const(mGlut, "GLUT_3_2_CORE_PROFILE", INT2NUM(GLUT_3_2_CORE_PROFILE));
+#endif
+
+ Init_glut_callbacks();
+ Init_glut_ext();
+}
diff --git a/ext/glut/glut_callbacks.c b/ext/glut/glut_callbacks.c
new file mode 100644
index 0000000..5ad16bc
--- /dev/null
+++ b/ext/glut/glut_callbacks.c
@@ -0,0 +1,845 @@
+#include "common.h"
+
+/* HACK experimental API */
+void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
+
+static ID call_id; /* 'call' method id */
+static VALUE idle_func = Qnil;
+static VALUE joystick_func = Qnil;
+static VALUE menustate_func = Qnil;
+static VALUE menustatus_func = Qnil;
+static VALUE timer_func = Qnil;
+
+typedef void *(*gvl_call)(void *);
+
+struct callback_args {
+ union {
+ int button;
+ int dial;
+ int special;
+ int state;
+ int value;
+ int width;
+ int x;
+ unsigned char key;
+ unsigned int button_mask;
+ } arg0;
+ union {
+ int height;
+ int state;
+ int value;
+ int x;
+ int y;
+ } arg1;
+ union {
+ int x;
+ int y;
+ int z;
+ } arg2;
+ union {
+ int y;
+ int z;
+ } arg3;
+} ;
+
+static struct callback_args *
+alloc_callback_args(void) {
+ struct callback_args *args;
+ args = (struct callback_args *)malloc(sizeof(struct callback_args));
+
+ if (args == NULL) {
+ fprintf(stderr, "[BUG] out of memory in opengl callback");
+ abort();
+ }
+
+ return args;
+}
+
+/*
+ * macros for registering callbacks -
+ *
+ * most GLUT callback functions are part of specific window state, so
+ * the same callback may have different functions for each GLUT window
+ *
+ * callbacks that are not tied to specific window (idle,timer,menustate) are
+ * registered manually
+ */
+
+#define WINDOW_CALLBACK_SETUP(_funcname) \
+static VALUE _funcname = Qnil; \
+static VALUE \
+glut_ ## _funcname(VALUE self, VALUE callback) \
+{ \
+ int win = glutGetWindow(); \
+ \
+ if (win == 0) { \
+ rb_raise(rb_eRuntimeError, "glut%s needs current window", #_funcname); \
+ } \
+ \
+ callback = rb_glut_check_callback(self, callback); \
+ \
+ rb_ary_store(_funcname, win, callback); \
+ \
+ if (NIL_P(callback)) \
+ glut##_funcname(NULL); \
+ else \
+ glut##_funcname(&glut_##_funcname##Callback0); \
+ \
+ return Qnil; \
+}
+
+#define WINDOW_CALLBACK_DEFINE(module, _funcname) \
+ rb_define_module_function(module, "glut"#_funcname, glut_##_funcname, 1); \
+ rb_global_variable(&_funcname); \
+ _funcname = rb_ary_new()
+
+static void GLUTCALLBACK glut_DisplayFuncCallback0(void);
+static void GLUTCALLBACK glut_ReshapeFuncCallback0(int, int);
+static void GLUTCALLBACK glut_KeyboardFuncCallback0(unsigned char, int, int);
+static void GLUTCALLBACK glut_MouseFuncCallback0(int, int, int, int);
+static void GLUTCALLBACK glut_MotionFuncCallback0(int, int);
+static void GLUTCALLBACK glut_PassiveMotionFuncCallback0(int, int);
+static void GLUTCALLBACK glut_EntryFuncCallback0(int);
+static void GLUTCALLBACK glut_VisibilityFuncCallback0(int);
+static void GLUTCALLBACK glut_SpecialFuncCallback0(int, int, int);
+static void GLUTCALLBACK glut_SpaceballMotionFuncCallback0(int, int, int);
+static void GLUTCALLBACK glut_SpaceballRotateFuncCallback0(int, int, int);
+static void GLUTCALLBACK glut_SpaceballButtonFuncCallback0(int, int);
+static void GLUTCALLBACK glut_ButtonBoxFuncCallback0(int, int);
+static void GLUTCALLBACK glut_DialsFuncCallback0(int, int);
+static void GLUTCALLBACK glut_TabletMotionFuncCallback0(int, int);
+static void GLUTCALLBACK glut_TabletButtonFuncCallback0(int, int, int, int);
+static void GLUTCALLBACK glut_OverlayDisplayFuncCallback0(void);
+static void GLUTCALLBACK glut_WindowStatusFuncCallback0(int);
+static void GLUTCALLBACK glut_JoystickFuncCallback0(unsigned int, int, int, int);
+static void GLUTCALLBACK glut_KeyboardUpFuncCallback0(unsigned char, int, int);
+static void GLUTCALLBACK glut_SpecialUpFuncCallback0(int, int, int);
+
+WINDOW_CALLBACK_SETUP(DisplayFunc)
+WINDOW_CALLBACK_SETUP(ReshapeFunc)
+WINDOW_CALLBACK_SETUP(KeyboardFunc)
+WINDOW_CALLBACK_SETUP(MouseFunc)
+WINDOW_CALLBACK_SETUP(MotionFunc)
+WINDOW_CALLBACK_SETUP(PassiveMotionFunc)
+WINDOW_CALLBACK_SETUP(EntryFunc)
+WINDOW_CALLBACK_SETUP(VisibilityFunc)
+WINDOW_CALLBACK_SETUP(SpecialFunc)
+WINDOW_CALLBACK_SETUP(SpaceballMotionFunc)
+WINDOW_CALLBACK_SETUP(SpaceballRotateFunc)
+WINDOW_CALLBACK_SETUP(SpaceballButtonFunc)
+WINDOW_CALLBACK_SETUP(ButtonBoxFunc)
+WINDOW_CALLBACK_SETUP(DialsFunc)
+WINDOW_CALLBACK_SETUP(TabletMotionFunc)
+WINDOW_CALLBACK_SETUP(TabletButtonFunc)
+WINDOW_CALLBACK_SETUP(OverlayDisplayFunc)
+WINDOW_CALLBACK_SETUP(WindowStatusFunc)
+WINDOW_CALLBACK_SETUP(KeyboardUpFunc)
+WINDOW_CALLBACK_SETUP(SpecialUpFunc)
+
+GLUT_SIMPLE_FUNCTION(ForceJoystickFunc)
+
+static void *
+glut_DisplayFuncCallback(void *ignored) {
+ VALUE func;
+
+ func = rb_ary_entry(DisplayFunc, glutGetWindow());
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 0);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_DisplayFuncCallback0(void) {
+ rb_thread_call_with_gvl(glut_DisplayFuncCallback, NULL);
+}
+
+static void *
+glut_ReshapeFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(ReshapeFunc, glutGetWindow());
+ VALUE width = INT2FIX(args->arg0.width);
+ VALUE height = INT2FIX(args->arg1.height);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 2, width, height);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_ReshapeFuncCallback0(int width, int height) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.width = width;
+ args->arg1.height = height;
+
+ rb_thread_call_with_gvl((gvl_call)glut_ReshapeFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_KeyboardFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(KeyboardFunc, glutGetWindow());
+#if HAVE_SINGLE_BYTE_STRINGS
+ VALUE key = rb_str_new((char *)&args->arg0.key, 1);
+#else
+ VALUE key = UINT2NUM((unsigned char)args->arg0.key);
+#endif
+ VALUE x = INT2FIX(args->arg1.x);
+ VALUE y = INT2FIX(args->arg2.y);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 3, key, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_KeyboardFuncCallback0(unsigned char key, int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.key = key;
+ args->arg1.x = x;
+ args->arg2.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_KeyboardFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_KeyboardUpFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(KeyboardUpFunc, glutGetWindow());
+#if HAVE_SINGLE_BYTE_STRINGS
+ VALUE key = rb_str_new((char *)&args->arg0.key, 1);
+#else
+ VALUE key = UINT2NUM((unsigned char)args->arg0.key);
+#endif
+ VALUE x = INT2FIX(args->arg1.x);
+ VALUE y = INT2FIX(args->arg2.y);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 3, key, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_KeyboardUpFuncCallback0(unsigned char key, int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.key = key;
+ args->arg1.x = x;
+ args->arg2.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_KeyboardUpFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_MouseFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(MouseFunc, glutGetWindow());
+
+ VALUE button = INT2FIX(args->arg0.button);
+ VALUE state = INT2FIX(args->arg1.state);
+ VALUE x = INT2FIX(args->arg2.x);
+ VALUE y = INT2FIX(args->arg3.y);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 4, button, state, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_MouseFuncCallback0(int button, int state, int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.button = button;
+ args->arg1.state = state;
+ args->arg2.x = x;
+ args->arg3.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_MouseFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_MotionFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(MotionFunc, glutGetWindow());
+ VALUE x = INT2FIX(args->arg0.x);
+ VALUE y = INT2FIX(args->arg1.y);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 2, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_MotionFuncCallback0(int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.x = x;
+ args->arg1.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_MotionFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_PassiveMotionFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(PassiveMotionFunc, glutGetWindow());
+ VALUE x = INT2FIX(args->arg0.x);
+ VALUE y = INT2FIX(args->arg1.y);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 2, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_PassiveMotionFuncCallback0(int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.x = x;
+ args->arg1.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_PassiveMotionFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_EntryFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(EntryFunc, glutGetWindow());
+ VALUE state = INT2NUM(args->arg0.state);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 1, state);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_EntryFuncCallback0(int state) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.state = state;
+
+ rb_thread_call_with_gvl((gvl_call)glut_EntryFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_VisibilityFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(VisibilityFunc, glutGetWindow());
+ VALUE state = INT2NUM(args->arg0.state);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 1, state);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_VisibilityFuncCallback0(int state) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.state = state;
+
+ rb_thread_call_with_gvl((gvl_call)glut_VisibilityFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_IdleFuncCallback(void *ignored) {
+ if (!NIL_P(idle_func))
+ rb_funcall(idle_func, call_id, 0);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_IdleFuncCallback0(void) {
+ rb_thread_call_with_gvl((gvl_call)glut_IdleFuncCallback, NULL);
+}
+
+static void *
+glut_TimerFuncCallback(struct callback_args *args) {
+ VALUE value = INT2NUM(args->arg0.value);
+
+ if (!NIL_P(timer_func))
+ rb_funcall(timer_func, call_id, 1, value);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_TimerFuncCallback0(int value) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.value = value;
+
+ rb_thread_call_with_gvl((gvl_call)glut_TimerFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_MenuStateFuncCallback(struct callback_args *args) {
+ VALUE state = INT2NUM(args->arg0.state);
+
+ if (!NIL_P(menustate_func))
+ rb_funcall(menustate_func, call_id, 1, state);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_MenuStateFuncCallback0(int state) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.state = state;
+
+ rb_thread_call_with_gvl((gvl_call)glut_MenuStateFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_MenuStatusFuncCallback(struct callback_args *args) {
+ VALUE state = INT2NUM(args->arg0.state);
+ VALUE x = INT2NUM(args->arg1.x);
+ VALUE y = INT2NUM(args->arg2.y);
+
+ if (!NIL_P(menustatus_func))
+ rb_funcall(menustatus_func, call_id, 3, state, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_MenuStatusFuncCallback0(int state, int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.state = state;
+ args->arg1.x = x;
+ args->arg2.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_MenuStatusFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_SpecialFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(SpecialFunc, glutGetWindow());
+ VALUE key = INT2NUM(args->arg0.key);
+ VALUE x = INT2NUM(args->arg1.x);
+ VALUE y = INT2NUM(args->arg2.y);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 3, key, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_SpecialFuncCallback0(int key, int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.key = key;
+ args->arg1.x = x;
+ args->arg2.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_SpecialFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_SpecialUpFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(SpecialUpFunc, glutGetWindow());
+ VALUE key = INT2NUM(args->arg0.key);
+ VALUE x = INT2NUM(args->arg1.x);
+ VALUE y = INT2NUM(args->arg2.y);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 3, key, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_SpecialUpFuncCallback0(int key, int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.key = key;
+ args->arg1.x = x;
+ args->arg2.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_SpecialUpFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_SpaceballMotionFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(SpaceballMotionFunc, glutGetWindow());
+ VALUE x = INT2NUM(args->arg0.x);
+ VALUE y = INT2NUM(args->arg1.y);
+ VALUE z = INT2NUM(args->arg2.z);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 3, x, y, z);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_SpaceballMotionFuncCallback0(int x, int y, int z) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.x = x;
+ args->arg1.y = y;
+ args->arg2.z = z;
+
+ rb_thread_call_with_gvl((gvl_call)glut_SpaceballMotionFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_SpaceballRotateFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(SpaceballRotateFunc, glutGetWindow());
+ VALUE x = INT2NUM(args->arg0.x);
+ VALUE y = INT2NUM(args->arg1.y);
+ VALUE z = INT2NUM(args->arg2.z);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 3, x, y, z);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_SpaceballRotateFuncCallback0(int x, int y, int z) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.x = x;
+ args->arg1.y = y;
+ args->arg2.z = z;
+
+ rb_thread_call_with_gvl((gvl_call)glut_SpaceballRotateFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_SpaceballButtonFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(SpaceballButtonFunc, glutGetWindow());
+ VALUE button = INT2NUM(args->arg0.button);
+ VALUE state = INT2NUM(args->arg1.state);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 2, button, state);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_SpaceballButtonFuncCallback0(int button, int state) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.button = button;
+ args->arg1.state = state;
+
+ rb_thread_call_with_gvl((gvl_call)glut_SpaceballButtonFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_ButtonBoxFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(ButtonBoxFunc, glutGetWindow());
+ VALUE button = INT2NUM(args->arg0.button);
+ VALUE state = INT2NUM(args->arg1.state);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 2, button, state);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_ButtonBoxFuncCallback0(int button, int state) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.button = button;
+ args->arg1.state = state;
+
+ rb_thread_call_with_gvl((gvl_call)glut_ButtonBoxFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_DialsFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(DialsFunc, glutGetWindow());
+ VALUE dial = INT2NUM(args->arg0.dial);
+ VALUE value = INT2NUM(args->arg1.value);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 2, dial, value);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_DialsFuncCallback0(int dial, int value) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.dial = dial;
+ args->arg1.value = value;
+
+ rb_thread_call_with_gvl((gvl_call)glut_DialsFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_TabletMotionFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(TabletMotionFunc, glutGetWindow());
+ VALUE x = INT2NUM(args->arg0.x);
+ VALUE y = INT2NUM(args->arg1.y);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 2, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_TabletMotionFuncCallback0(int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.x = x;
+ args->arg1.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_TabletMotionFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_TabletButtonFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(TabletButtonFunc, glutGetWindow());
+ VALUE button = INT2NUM(args->arg0.button);
+ VALUE state = INT2NUM(args->arg1.state);
+ VALUE x = INT2NUM(args->arg2.x);
+ VALUE y = INT2NUM(args->arg3.y);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 4, button, state, x, y);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_TabletButtonFuncCallback0(int button, int state, int x, int y) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.button = button;
+ args->arg1.state = state;
+ args->arg2.x = x;
+ args->arg3.y = y;
+
+ rb_thread_call_with_gvl((gvl_call)glut_TabletButtonFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_OverlayDisplayFuncCallback(void) {
+ VALUE func = rb_ary_entry(OverlayDisplayFunc, glutGetWindow());
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 0);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_OverlayDisplayFuncCallback0(void) {
+ rb_thread_call_with_gvl((gvl_call)glut_OverlayDisplayFuncCallback, NULL);
+}
+
+static void *
+glut_WindowStatusFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(WindowStatusFunc, glutGetWindow());
+ VALUE state = INT2NUM(args->arg0.state);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 1, state);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_WindowStatusFuncCallback0(int state) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.state = state;
+
+ rb_thread_call_with_gvl((gvl_call)glut_WindowStatusFuncCallback, args);
+
+ free(args);
+}
+
+static void *
+glut_JoystickFuncCallback(struct callback_args *args) {
+ VALUE func = rb_ary_entry(joystick_func, glutGetWindow());
+ VALUE button_mask = UINT2NUM(args->arg0.button_mask);
+ VALUE x = INT2NUM(args->arg1.x);
+ VALUE y = INT2NUM(args->arg2.y);
+ VALUE z = INT2NUM(args->arg3.z);
+
+ if (!NIL_P(func))
+ rb_funcall(func, call_id, 4, button_mask, x, y, z);
+
+ return NULL;
+}
+
+static void GLUTCALLBACK
+glut_JoystickFuncCallback0(unsigned int button_mask, int x, int y, int z) {
+ struct callback_args *args = alloc_callback_args();
+
+ args->arg0.button_mask = button_mask;
+ args->arg1.x = x;
+ args->arg2.y = y;
+ args->arg3.z = z;
+
+ rb_thread_call_with_gvl((gvl_call)glut_JoystickFuncCallback, args);
+
+ free(args);
+}
+
+static VALUE
+glut_JoystickFunc(VALUE self, VALUE callback, VALUE _poll_interval) {
+ int win = glutGetWindow();
+ int poll_interval = NUM2INT(_poll_interval);
+
+ if (win == 0)
+ rb_raise(rb_eRuntimeError, "glutJoystickFunc needs current window");
+
+ callback = rb_glut_check_callback(self, callback);
+
+ rb_ary_store(joystick_func, win, callback);
+
+ if (NIL_P(callback))
+ glutJoystickFunc(NULL, -1);
+ else
+ glutJoystickFunc(glut_JoystickFuncCallback0, poll_interval);
+
+ return Qnil;
+}
+
+static VALUE
+glut_IdleFunc(VALUE self, VALUE callback) {
+ callback = rb_glut_check_callback(self, callback);
+
+ idle_func = callback;
+
+ if (NIL_P(callback))
+ glutIdleFunc(NULL);
+ else
+ glutIdleFunc(glut_IdleFuncCallback0);
+
+ return Qnil;
+}
+
+static VALUE
+glut_MenuStateFunc(VALUE self, VALUE callback) {
+ menustate_func = rb_glut_check_callback(self, callback);
+
+ if (NIL_P(menustate_func))
+ glutMenuStateFunc(NULL);
+ else
+ glutMenuStateFunc(glut_MenuStateFuncCallback0);
+
+ return Qnil;
+}
+
+static VALUE
+glut_MenuStatusFunc(VALUE self, VALUE callback) {
+ menustatus_func = rb_glut_check_callback(self, callback);
+
+ if (NIL_P(menustatus_func))
+ glutMenuStatusFunc(NULL);
+ else
+ glutMenuStatusFunc(glut_MenuStatusFuncCallback0);
+
+ return Qnil;
+}
+
+static VALUE
+glut_TimerFunc(VALUE self, VALUE _msec, VALUE callback, VALUE _value) {
+ unsigned int msec = NUM2UINT(_msec);
+ int value = NUM2INT(_value);
+
+ timer_func = rb_glut_check_callback(self, callback);
+
+ glutTimerFunc(msec, glut_TimerFuncCallback0, value);
+
+ return Qnil;
+}
+
+void Init_glut_callbacks() {
+ VALUE mGlut = rb_path2class("Glut");
+
+ call_id = rb_intern("call");
+ joystick_func = rb_ary_new();
+
+ rb_global_variable(&joystick_func);
+ rb_gc_register_address(&idle_func);
+ rb_gc_register_address(&timer_func);
+ rb_gc_register_address(&menustate_func);
+
+ rb_define_module_function(mGlut, "glutJoystickFunc", glut_JoystickFunc, 2);
+ rb_define_module_function(mGlut, "glutForceJoystickFunc", glut_ForceJoystickFunc, 0);
+ rb_define_module_function(mGlut, "glutIdleFunc", glut_IdleFunc, 1);
+ rb_define_module_function(mGlut, "glutMenuStateFunc", glut_MenuStateFunc, 1);
+ rb_define_module_function(mGlut, "glutMenuStatusFunc", glut_MenuStatusFunc, 1);
+ rb_define_module_function(mGlut, "glutTimerFunc", glut_TimerFunc, 3);
+
+ WINDOW_CALLBACK_DEFINE(mGlut, ButtonBoxFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, DialsFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, DisplayFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, EntryFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, KeyboardFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, KeyboardUpFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, MotionFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, MouseFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, OverlayDisplayFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, PassiveMotionFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, ReshapeFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, SpaceballButtonFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, SpaceballMotionFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, SpaceballRotateFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, SpecialFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, SpecialUpFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, TabletButtonFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, TabletMotionFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, VisibilityFunc);
+ WINDOW_CALLBACK_DEFINE(mGlut, WindowStatusFunc);
+}
+
diff --git a/ext/glut/glut_ext.c b/ext/glut/glut_ext.c
new file mode 100644
index 0000000..8f865b1
--- /dev/null
+++ b/ext/glut/glut_ext.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 Blaž Hrastnik
+ *
+ * This program is distributed under the terms of the MIT license.
+ * See the included COPYRIGHT file for the terms of this license.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "common.h"
+
+/*
+ * Process loop function, see freeglut_main.c
+ */
+GLUT_SIMPLE_FUNCTION(MainLoopEvent)
+GLUT_SIMPLE_FUNCTION(LeaveMainLoop)
+GLUT_SIMPLE_FUNCTION(Exit)
+
+/*
+ * Window management functions, see freeglut_window.c
+ */
+GLUT_SIMPLE_FUNCTION(FullScreenToggle)
+GLUT_SIMPLE_FUNCTION(LeaveFullScreen)
+
+/* Initialization functions */
+static VALUE
+glut_InitContextVersion(VALUE obj, VALUE majorVersion, VALUE minorVersion)
+{
+ glutInitContextVersion(NUM2INT(majorVersion), NUM2INT(minorVersion));
+ return Qnil;
+}
+
+static VALUE
+glut_InitContextFlags(VALUE obj, VALUE flags)
+{
+ glutInitContextFlags(NUM2INT(flags));
+ return Qnil;
+}
+
+static VALUE
+glut_InitContextProfile(VALUE obj, VALUE profile)
+{
+ glutInitContextProfile(NUM2INT(profile));
+ return Qnil;
+}
+
+void Init_glut_ext() {
+ VALUE mGlut = rb_path2class("Glut");
+
+ /* Process loop functions */
+ rb_define_module_function(mGlut, "glutMainLoopEvent", glut_MainLoopEvent, 0);
+ rb_define_module_function(mGlut, "glutLeaveMainLoop", glut_LeaveMainLoop, 0);
+ rb_define_module_function(mGlut, "glutExit", glut_Exit, 0);
+
+ /* Window management functions */
+ rb_define_module_function(mGlut, "glutFullScreenToggle", glut_FullScreenToggle, 0);
+ rb_define_module_function(mGlut, "glutLeaveFullScreen", glut_LeaveFullScreen, 0);
+
+ /* Initialization functions */
+ rb_define_module_function(mGlut, "glutInitContextVersion", glut_InitContextVersion, 2);
+ rb_define_module_function(mGlut, "glutInitContextFlags", glut_InitContextFlags, 1);
+ rb_define_module_function(mGlut, "glutInitContextProfile", glut_InitContextProfile, 1);
+
+ /* Context-related flags */
+#ifdef GLUT_INIT_MAJOR_VERSION
+ rb_define_const(mGlut, "GLUT_INIT_MAJOR_VERSION", INT2NUM(GLUT_INIT_MAJOR_VERSION));
+#endif
+#ifdef GLUT_INIT_MINOR_VERSION
+ rb_define_const(mGlut, "GLUT_INIT_MINOR_VERSION", INT2NUM(GLUT_INIT_MINOR_VERSION));
+#endif
+#ifdef GLUT_INIT_FLAGS
+ rb_define_const(mGlut, "GLUT_INIT_FLAGS", INT2NUM(GLUT_INIT_FLAGS));
+#endif
+#ifdef GLUT_INIT_PROFILE
+ rb_define_const(mGlut, "GLUT_INIT_PROFILE", INT2NUM(GLUT_INIT_PROFILE));
+#endif
+
+ /* Flags for glutInitContextFlags */
+#ifdef GLUT_FORWARD_COMPATIBLE
+ rb_define_const(mGlut, "GLUT_FORWARD_COMPATIBLE", INT2NUM(GLUT_FORWARD_COMPATIBLE));
+#endif
+#ifdef GLUT_DEBUG
+ rb_define_const(mGlut, "GLUT_DEBUG", INT2NUM(GLUT_DEBUG));
+#endif
+
+ /* Flags for glutInitContextProfile */
+#ifdef GLUT_CORE_PROFILE
+ rb_define_const(mGlut, "GLUT_CORE_PROFILE", INT2NUM(GLUT_CORE_PROFILE));
+#endif
+#ifdef GLUT_COMPATIBILITY_PROFILE
+ rb_define_const(mGlut, "GLUT_COMPATIBILITY_PROFILE", INT2NUM(GLUT_COMPATIBILITY_PROFILE));
+#endif
+}
diff --git a/glut.gemspec b/glut.gemspec
new file mode 100644
index 0000000..127c01e
--- /dev/null
+++ b/glut.gemspec
@@ -0,0 +1,50 @@
+#########################################################
+# This file has been automatically generated by gem2tgz #
+#########################################################
+# -*- encoding: utf-8 -*-
+# stub: glut 8.3.0 ruby lib
+# stub: ext/glut/extconf.rb
+
+Gem::Specification.new do |s|
+ s.name = "glut".freeze
+ s.version = "8.3.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
+ s.require_paths = ["lib".freeze]
+ s.authors = ["Eric Hodel".freeze, "Lars Kanis".freeze, "Bla\u017E Hrastnik".freeze, "Alain Hoang".freeze, "Jan Dvorak".freeze, "Minh Thu Vo".freeze, "James Adam".freeze]
+ s.date = "2017-06-02"
+ s.description = "Glut bindings for OpenGL. To be used with the {opengl}[https://github.com/larskanis/opengl] gem.".freeze
+ s.email = ["drbrain@segment7.net".freeze, "lars@greiz-reinsdorf.de".freeze, "speed.the.bboy@gmail.com".freeze, "".freeze, "".freeze, "".freeze, "".freeze]
+ s.extensions = ["ext/glut/extconf.rb".freeze]
+ s.extra_rdoc_files = ["History.rdoc".freeze, "Manifest.txt".freeze, "README.rdoc".freeze]
+ s.files = [".autotest".freeze, ".gemtest".freeze, ".gitignore".freeze, ".travis.yml".freeze, "History.rdoc".freeze, "MIT-LICENSE".freeze, "Manifest.txt".freeze, "README.rdoc".freeze, "Rakefile".freeze, "ext/glut/common.h".freeze, "ext/glut/extconf.rb".freeze, "ext/glut/glut.c".freeze, "ext/glut/glut_callbacks.c".freeze, "ext/glut/glut_ext.c".freeze, "lib/glut.rb".freeze, "lib/glut/dummy.rb".freeze]
+ s.licenses = ["MIT".freeze]
+ s.rdoc_options = ["--main".freeze, "README.rdoc".freeze]
+ s.required_ruby_version = Gem::Requirement.new(">= 1.9.2".freeze)
+ s.rubygems_version = "2.7.6.2".freeze
+ s.summary = "Glut bindings for OpenGL".freeze
+
+ if s.respond_to? :specification_version then
+ s.specification_version = 4
+
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
+ s.add_development_dependency(%q.freeze, ["~> 3.16"])
+ s.add_development_dependency(%q.freeze, ["~> 2.1"])
+ s.add_development_dependency(%q.freeze, ["~> 1.0"])
+ s.add_development_dependency(%q.freeze, ["~> 0.6.0"])
+ s.add_development_dependency(%q.freeze, ["~> 4.0"])
+ else
+ s.add_dependency(%q.freeze, ["~> 3.16"])
+ s.add_dependency(%q.freeze, ["~> 2.1"])
+ s.add_dependency(%q.freeze, ["~> 1.0"])
+ s.add_dependency(%q.freeze, ["~> 0.6.0"])
+ s.add_dependency(%q.freeze, ["~> 4.0"])
+ end
+ else
+ s.add_dependency(%q.freeze, ["~> 3.16"])
+ s.add_dependency(%q.freeze, ["~> 2.1"])
+ s.add_dependency(%q.freeze, ["~> 1.0"])
+ s.add_dependency(%q.freeze, ["~> 0.6.0"])
+ s.add_dependency(%q.freeze, ["~> 4.0"])
+ end
+end
diff --git a/lib/glut/dummy.rb b/lib/glut/dummy.rb
new file mode 100644
index 0000000..8231ff7
--- /dev/null
+++ b/lib/glut/dummy.rb
@@ -0,0 +1,2 @@
+# Unless this file exists, rake-compiler/hoe won't create this folder
+# and the extension won't build.
\ No newline at end of file
diff --git a/lib/glut.rb b/lib/glut.rb
new file mode 100644
index 0000000..95d0d7b
--- /dev/null
+++ b/lib/glut.rb
@@ -0,0 +1,29 @@
+begin
+ RUBY_VERSION =~ /(\d+.\d+)/
+ require "glut/#{$1}/glut"
+rescue LoadError
+ require 'glut/glut'
+end
+
+# (Glut.)glutInit -> GLUT.Init
+# (Glut::)GLUT_RGBA -> GLUT::RGBA
+module GLUT
+ extend self
+ include Glut
+
+ Glut.constants.each do |cn|
+ n = cn.to_s.sub(/^GLUT_/,'')
+ next if n =~ /^[0-9]/
+ const_set( n, Glut.const_get( cn ) )
+ end
+
+ Glut.methods( false ).each do |mn|
+ n = mn.to_s.sub(/^glut/,'')
+ alias_method( n, mn )
+ public( n )
+ end
+end
+
+module Glut
+ VERSION = "8.3.0"
+end