lib/ruby2d/window.rb in ruby2d-0.9.5 vs lib/ruby2d/window.rb in ruby2d-0.10.0

- old
+ new

@@ -4,24 +4,21 @@ module Ruby2D class Window # Event structures - EventDescriptor = Struct.new(:type, :id) - MouseEvent = Struct.new(:type, :button, :direction, :x, :y, :delta_x, :delta_y) - KeyEvent = Struct.new(:type, :key) + EventDescriptor = Struct.new(:type, :id) + MouseEvent = Struct.new(:type, :button, :direction, :x, :y, :delta_x, :delta_y) + KeyEvent = Struct.new(:type, :key) ControllerEvent = Struct.new(:which, :type, :axis, :value, :button) ControllerAxisEvent = Struct.new(:which, :axis, :value) ControllerButtonEvent = Struct.new(:which, :button) def initialize(args = {}) - # This window instance, stored so it can be called by the class methods - @@window = self - # Title of the window - @title = args[:title] || "Ruby 2D" + @title = args[:title] || "Ruby 2D" # Window background color @background = Color.new([0.0, 0.0, 0.0, 1.0]) # Window icon @@ -49,18 +46,43 @@ @fps = @fps_cap # Vertical synchronization, set to prevent screen tearing (recommended) @vsync = args[:vsync] || true + # Renderable objects currently in the window, like a linear scene graph + @objects = [] + + # Entities currently in the window + @entities = [] + # Mouse X and Y position in the window @mouse_x, @mouse_y = 0, 0 # Controller axis and button mappings file @controller_mappings = File.expand_path('~') + "/.ruby2d/controllers.txt" - # Renderable objects currently in the window, like a linear scene graph - @objects = [] + # Event stores for class pattern + @keys_down = [] + @keys_held = [] + @keys_up = [] + @mouse_buttons_down = [] + @mouse_buttons_up = [] + @mouse_scroll_event = false + @mouse_scroll_direction = nil + @mouse_scroll_delta_x = 0 + @mouse_scroll_delta_y = 0 + @mouse_move_event = false + @mouse_move_delta_x = 0 + @mouse_move_delta_y = 0 + @controller_id = nil + @controller_axes_moved = [] + @controller_axis_left_x = 0 + @controller_axis_left_y = 0 + @controller_axis_right_x = 0 + @controller_axis_right_y = 0 + @controller_buttons_down = [] + @controller_buttons_up = [] # Unique ID for the input event being registered @event_key = 0 # Registered input events @@ -81,10 +103,18 @@ } # The window update block @update_proc = Proc.new {} + # The window render block + @render_proc = Proc.new {} + + # Detect if window is being used through the DSL or as a class instance + unless method(:update).parameters.empty? || method(:render).parameters.empty? + @using_dsl = true + end + # Whether diagnostic messages should be printed @diagnostics = false # Console mode, enabled at command line if RUBY_ENGINE == 'ruby' @@ -116,47 +146,51 @@ def mouse_y; get(:mouse_y) end def diagnostics; get(:diagnostics) end def screenshot(opts = nil); get(:screenshot, opts) end def get(sym, opts = nil) - @@window.get(sym, opts) + DSL.window.get(sym, opts) end def set(opts) - @@window.set(opts) + DSL.window.set(opts) end def on(event, &proc) - @@window.on(event, &proc) + DSL.window.on(event, &proc) end def off(event_descriptor) - @@window.off(event_descriptor) + DSL.window.off(event_descriptor) end def add(o) - @@window.add(o) + DSL.window.add(o) end def remove(o) - @@window.remove(o) + DSL.window.remove(o) end def clear - @@window.clear + DSL.window.clear end def update(&proc) - @@window.update(&proc) + DSL.window.update(&proc) end + def render(&proc) + DSL.window.render(&proc) + end + def show - @@window.show + DSL.window.show end def close - @@window.close + DSL.window.close end end # Public instance methods @@ -217,10 +251,12 @@ # Add an object to the window def add(o) case o when nil raise Error, "Cannot add '#{o.class}' to window!" + when Entity + @entities.push(o) when Array o.each { |x| add_object(x) } else add_object(o) end @@ -230,29 +266,37 @@ def remove(o) if o == nil raise Error, "Cannot remove '#{o.class}' from window!" end - if i = @objects.index(o) - @objects.delete_at(i) + collection = o.class.ancestors.include?(Ruby2D::Entity) ? @entities : @objects + if i = collection.index(o) + collection.delete_at(i) true else false end end # Clear all objects from the window def clear @objects.clear + @entities.clear end - # Set an update callback + # Set the update callback def update(&proc) @update_proc = proc true end + # Set the render callback + def render(&proc) + @render_proc = proc + true + end + # Generate a new event key (ID) def new_event_key @event_key = @event_key.next end @@ -269,10 +313,25 @@ # Remove an event handler def off(event_descriptor) @events[event_descriptor.type].delete(event_descriptor.id) end + # Key down event method for class pattern + def key_down(key) + @keys_down.include? key + end + + # Key held event method for class pattern + def key_held(key) + @keys_held.include? key + end + + # Key up event method for class pattern + def key_up(key) + @keys_up.include? key + end + # Key callback method, called by the native and web extentions def key_callback(type, key) key = key.downcase # All key events @@ -281,51 +340,128 @@ end case type # When key is pressed, fired once when :down + # For class pattern + unless @using_dsl + unless @keys_down.include? key + @keys_down << key + end + end + + # Call event handler @events[:key_down].each do |id, e| e.call(KeyEvent.new(type, key)) end # When key is being held down, fired every frame when :held + # For class pattern + unless @using_dsl + unless @keys_held.include? key + @keys_held << key + end + end + + # Call event handler @events[:key_held].each do |id, e| e.call(KeyEvent.new(type, key)) end # When key released, fired once when :up + # For class pattern + unless @using_dsl + unless @keys_up.include? key + @keys_up << key + end + end + + # Call event handler @events[:key_up].each do |id, e| e.call(KeyEvent.new(type, key)) end end end + # Mouse down event method for class pattern + def mouse_down(btn) + @mouse_buttons_down.include? btn + end + + # Mouse up event method for class pattern + def mouse_up(btn) + @mouse_buttons_up.include? btn + end + + # Mouse scroll event method for class pattern + def mouse_scroll + @mouse_scroll_event + end + + # Mouse move event method for class pattern + def mouse_move + @mouse_move_event + end + # Mouse callback method, called by the native and web extentions def mouse_callback(type, button, direction, x, y, delta_x, delta_y) # All mouse events @events[:mouse].each do |id, e| e.call(MouseEvent.new(type, button, direction, x, y, delta_x, delta_y)) end case type # When mouse button pressed when :down + # For class pattern + unless @using_dsl + unless @mouse_buttons_down.include? button + @mouse_buttons_down << button + end + end + + # Call event handler @events[:mouse_down].each do |id, e| e.call(MouseEvent.new(type, button, nil, x, y, nil, nil)) end # When mouse button released when :up + # For class pattern + unless @using_dsl + unless @mouse_buttons_up.include? button + @mouse_buttons_up << button + end + end + + # Call event handler @events[:mouse_up].each do |id, e| e.call(MouseEvent.new(type, button, nil, x, y, nil, nil)) end # When mouse motion / movement when :scroll + # For class pattern + unless @using_dsl + @mouse_scroll_event = true + @mouse_scroll_direction = direction + @mouse_scroll_delta_x = delta_x + @mouse_scroll_delta_y = delta_y + end + + # Call event handler @events[:mouse_scroll].each do |id, e| e.call(MouseEvent.new(type, nil, direction, nil, nil, delta_x, delta_y)) end # When mouse scrolling, wheel or trackpad when :move + # For class pattern + unless @using_dsl + @mouse_move_event = true + @mouse_move_delta_x = delta_x + @mouse_move_delta_y = delta_y + end + + # Call event handler @events[:mouse_move].each do |id, e| e.call(MouseEvent.new(type, nil, nil, x, y, delta_x, delta_y)) end end end @@ -335,40 +471,104 @@ if File.exist? @controller_mappings ext_add_controller_mappings(@controller_mappings) end end + # Controller axis event method for class pattern + def controller_axis(axis) + @controller_axes_moved.include? axis + end + + # Controller button down event method for class pattern + def controller_button_down(btn) + @controller_buttons_down.include? btn + end + + # Controller button up event method for class pattern + def controller_button_up(btn) + @controller_buttons_up.include? btn + end + # Controller callback method, called by the native and web extentions def controller_callback(which, type, axis, value, button) # All controller events @events[:controller].each do |id, e| e.call(ControllerEvent.new(which, type, axis, value, button)) end case type # When controller axis motion, like analog sticks when :axis + + # For class pattern + unless @using_dsl + @controller_id = which + + unless @controller_axes_moved.include? axis + @controller_axes_moved << axis + end + + case axis + when :left_x + @controller_axis_left_x = value + when :left_y + @controller_axis_left_y = value + when :right_x + @controller_axis_right_x = value + when :right_y + @controller_axis_right_y = value + end + end + + # Call event handler @events[:controller_axis].each do |id, e| e.call(ControllerAxisEvent.new(which, axis, value)) end # When controller button is pressed when :button_down + # For class pattern + unless @using_dsl + @controller_id = which + unless @controller_buttons_down.include? button + @controller_buttons_down << button + end + end + + # Call event handler @events[:controller_button_down].each do |id, e| e.call(ControllerButtonEvent.new(which, button)) end # When controller button is released when :button_up + # For class pattern + unless @using_dsl + @controller_id = which + unless @controller_buttons_up.include? button + @controller_buttons_up << button + end + end + + # Call event handler @events[:controller_button_up].each do |id, e| e.call(ControllerButtonEvent.new(which, button)) end end end # Update callback method, called by the native and web extentions def update_callback + unless @using_dsl + update + end + @update_proc.call + # Run update method on all entities + @entities.each do |e| + e.update + end + # Accept and eval commands if in console mode if @console if STDIN.ready? cmd = STDIN.gets begin @@ -383,9 +583,36 @@ STDOUT.flush end end end + # Clear inputs if using class pattern + unless @using_dsl + @keys_down.clear + @keys_held.clear + @keys_up.clear + @mouse_buttons_down.clear + @mouse_buttons_up.clear + @mouse_scroll_event = false + @mouse_move_event = false + @controller_axes_moved.clear + @controller_buttons_down.clear + @controller_buttons_up.clear + end + end + + # Render callback method, called by the native and web extentions + def render_callback + unless @using_dsl + render + end + + @render_proc.call + + # Run render method on all entities + @entities.each do |e| + e.render + end end # Show the window def show ext_show