#-- # Rubygame -- Ruby bindings to SDL to facilitate game creation # Copyright (C) 2004-2005 John 'jacius' Croisant # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #++ require "singleton" require "rubygame/event" module Rubygame # (Note: I'm not putting much effort into documenting the current Queue # class, because it is going to be changing substantially in the next # version. It is mostly usable for now, but neither elegant nor fun to use. # Frankly, I think it's an abomination, and it took all my willpower to # put off rewriting it until next version.) # # Queue provides an interface to SDL's events, allowing the # application to detect keyboard presses, mouse movements and clicks, # joystick movement, etc. # # The full list of default events is: # - Event (base class, not useful by itself) # - ActiveEvent # - JoyAxisEvent # - JoyBallEvent # - JoyDownEvent # - JoyHatEvent # - JoyUpEvent # - KeyDownEvent # - KeyUpEvent # - MouseDownEvent # - MouseMotionEvent # - MouseUpEvent # - QuitEvent # - ResizeEvent # # You are allowed to create new child classes of Event and post them to # the Queue, but for now you would probably be better off using some other # data structure to hold your own events. I recommend checking out the queue # class in Ruby's stardard library. # # P.S. Queue is a singleton, so you must use Queue.instance, not Queue.new. # class Queue include Singleton def initialize() # :nodoc: @@pending = [] @@allowed = Rubygame::ALL_EVENT_CLASSES end # Allow the given event classes. Returns all event classes that had # previously been disallowed, but are now allowed. def allow(*types) added = (Rubygame::ALL_EVENT_CLASSES - types.flatten()) & @@allowed for type in types.flatten() if type.kind_of? Class if not @@allowed.include? type @@allowed.push(type) end elsif type.kind_of? Event @@allowed.push(type.class) end end return added end # Returns all event classes which are allowed. def allowed return @@allowed.dup end # Allow ONLY the given event classes. Returns all event classes that had # previously been disallowed, but are now allowed. def allowed=(*types) added = Rubygame::ALL_EVENT_CLASSES - (types.flatten() & @@allowed) @@allowed = [] self.allow(types) return added end # Disallow the given event classes from being posted. Returns all classes # which had previously been allowed, but are now disallowed. def block(*types) removed = @@allowed & types.flatten() for type in types.flatten() if type.kind_of? Class if @@allowed.include? type @@allowed.delete(type) end elsif type.kind_of? Event @allowed.delete(type.class) end end return blocked end # Return all default Rubygame event classes which are disallowed # by the Queue. def blocked return Rubygame::ALL_EVENT_CLASSES - @@allowed.dup end # Cause the Queue to allow ONLY all default Rubygame event classes EXCEPT # the given classes. Returns all classes which had previously been allowed, # but are now disallowed. def blocked=(*types) removed = types.flatten() & @@allowed @@allowed = Rubygame.ALL_EVENT_CLASSES self.block(types) return removed end # call-seq: get( *klasses ) -> Array # # Get all events currently in the Queue which match the classes in the # Array +klasses+, and return them in an Array. If +klasses+ is omitted, # returns all # # Events which did not match will remain on the Queue, so make sure you # eventually #get every class of events that is #allowed, or they might # build up in the Queue.) def get(*types) allow = [] if types.length > 0 for type in types.flatten() if type.kind_of? Class if not allow.include? type allow.push(type) end elsif type.kind_of? Event allow.push(type.class) end end else allow = @@allowed end update_pending() get = @@pending.delete_if{|event| not allow.include? event.class} @@pending -= get return get end # call-seq: post( *events ) -> Array # # Post one or more events to the Queue. Only events which meet these # criteria will be posted: # - its class is a child class of Event. # - its class is allowed by the Queue. # # Returns all the given events which were not posted. def post(*events) update_pending() # so posted events will appear after SDL events not_added = [] for event in events.flatten() if event.kind_of? Event and @@allowed.include?(event.class) @@pending.push(event) else not_added.push(event) end end return not_added end # Adds SDL hardware events to the Queue's list of pending events. def update_pending # :nodoc: @@pending += get_sdl() end private :update_pending # call-seq: wait( *klasses ) -> Event # # Waits until an event matching the classes in Array +klasses+ occurs, # then return that event. All non-matching events will be *discarded* in # the meantime. # # If +klasses+ is omitted, ANY event class allowed by the Queue will # trigger return. (Important: omitting +klasses+ is not the same as # giving +nil+.) # # +klasses+ is an Array of the Event classes which will trigger this method # to return. Any classes which are blocked by the Queue or are # not Rubygame-generated hardware events will be stripped from +klasses+. # # If +klasses+ is given, but does not contain any valid classes, # this method will immediately return +nil+. # def wait( *klasses ) klasses.flatten! if klasses.length < 1 # no args klasses = Rubygame::ALL_EVENT_CLASSES end # eliminate invalid args klasses = klasses.delete_if{ |klass| !(Rubygame::ALL_EVENT_CLASSES.include?(klass) and\ @@allowed.include?(klass)) } if klasses.length < 1 # no _valid_ args return nil end loop do self.get().each { |event| return event if klasses.include? event.class } end end end # class Queue end # module Rubygame