module Gosu class Window %w(update draw needs_redraw? needs_cursor? capture_cursor? hit_test gain_focus lose_focus button_down button_up gamepad_connected gamepad_disconnected drop close).each do |callback| define_method "protected_#{callback}" do |*args| begin # If there has been an exception, don't do anything as to not make matters worse. # Conveniently turn the return value into a boolean result (for needs_cursor? etc). defined?(@__exception) ? false : send(callback, *args) rescue Exception => e # Exit the message loop naturally, then re-throw during the next tick. @__exception = e close! false ensure $gosu_gl_blocks = nil if callback == "draw" end end end def initialize(width, height, _fullscreen = nil, _update_interval = nil, _resizable = nil, _borderless = nil, fullscreen: false, update_interval: 16.66666667, resizable: false, borderless: false) fullscreen = _fullscreen if _fullscreen update_interval = _update_interval if _update_interval resizable = _resizable if _resizable borderless = _borderless if _borderless window_flags = GosuFFI.window_flags(fullscreen: fullscreen, resizable: resizable, borderless: borderless) __window = GosuFFI.Gosu_Window_create(width, height, window_flags, update_interval) GosuFFI.check_last_error @memory_pointer = FFI::AutoPointer.new(__window, GosuFFI.method(:Gosu_Window_destroy)) @text_input = nil { update: [], draw: [], button_down: [:id], button_up: [:id], gamepad_connected: [:id], gamepad_disconnected: [:id], drop: [:filename], needs_redraw?: [], needs_cursor?: [], close: [], gain_focus: [], lose_focus: [], }.each do |callback, args| callback_safename = callback.to_s.sub("?", "") instance_eval("@__#{callback_safename}_proc = proc { |#{[:data, args].flatten.join(",")}| protected_#{callback}(#{args.join(",")}) }") GosuFFI.send(:"Gosu_Window_set_#{callback_safename}", __pointer, instance_variable_get(:"@__#{callback_safename}_proc"), nil) GosuFFI.check_last_error end end # Returns FFI pointer of C side Gosu::Window def __pointer @memory_pointer end def update end def draw end def button_down(id) GosuFFI.Gosu_Window_default_button_down(__pointer, id) GosuFFI.check_last_error end def button_up(id) end def gamepad_connected(id) end def gamepad_disconnected(id) end def drop(filename) end def needs_redraw? true end def needs_cursor? false end def capture_cursor? false end def close close! end def gain_focus end def lose_focus end def caption GosuFFI.check_last_error(GosuFFI.Gosu_Window_caption(__pointer)) end def caption=(text) GosuFFI.Gosu_Window_set_caption(__pointer, text) GosuFFI.check_last_error end def fullscreen? GosuFFI.check_last_error(GosuFFI.Gosu_Window_is_fullscreen(__pointer)) end def fullscreen=(boolean) GosuFFI.Gosu_Window_resize(__pointer, width, height, !!boolean) GosuFFI.check_last_error end def resizable? GosuFFI.check_last_error(GosuFFI.Gosu_Window_is_resizable(__pointer)) end def resizable=(boolean) GosuFFI.Gosu_Window_set_resizable(__pointer, !!boolean) GosuFFI.check_last_error end def borderless? GosuFFI.check_last_error(GosuFFI.Gosu_Window_is_borderless(__pointer)) end def borderless=(boolean) GosuFFI.Gosu_Window_set_borderless(__pointer, !!boolean) GosuFFI.check_last_error end def text_input @text_input || nil end def text_input=(text_input) if not text_input.nil? and not text_input.is_a? Gosu::TextInput raise ArgumentError, "text_input must be nil or a Gosu::TextInput" end @text_input = text_input GosuFFI.Gosu_Window_set_text_input(__pointer, text_input&.__pointer) GosuFFI.check_last_error end def update_interval GosuFFI.check_last_error(GosuFFI.Gosu_Window_update_interval(__pointer)) end def update_interval=(double) GosuFFI.Gosu_Window_set_update_interval(__pointer, double) GosuFFI.check_last_error end def width GosuFFI.check_last_error(GosuFFI.Gosu_Window_width(__pointer)) end def width=(int) GosuFFI.Gosu_Window_resize(__pointer, int, height, fullscreen?) GosuFFI.check_last_error end def height GosuFFI.check_last_error(GosuFFI.Gosu_Window_height(__pointer)) end def height=(int) GosuFFI.Gosu_Window_resize(__pointer, width, int, fullscreen?) GosuFFI.check_last_error end def mouse_x GosuFFI.check_last_error(GosuFFI.Gosu_Window_mouse_x(__pointer)) end def mouse_x=(double) GosuFFI.Gosu_Window_set_mouse_x(__pointer, double) GosuFFI.check_last_error end def mouse_y GosuFFI.check_last_error(GosuFFI.Gosu_Window_mouse_y(__pointer)) end def mouse_y=(double) GosuFFI.Gosu_Window_set_mouse_y(__pointer, double) GosuFFI.check_last_error end def show GosuFFI.Gosu_Window_show(__pointer) raise @__exception if defined?(@__exception) GosuFFI.check_last_error end def tick value = GosuFFI.check_last_error(GosuFFI.Gosu_Window_tick(__pointer)) raise @__exception if defined?(@__exception) value end def close! GosuFFI.Gosu_Window_close_immediately(__pointer) GosuFFI.check_last_error end def sdl_window GosuFFI.check_last_error(GosuFFI.Gosu_Window_sdl_window(__pointer)) end end end