rubygame 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CREDITS +5 -0
- data/NEWS +88 -0
- data/README +8 -4
- data/ROADMAP +19 -43
- data/Rakefile +94 -10
- data/doc/macosx_install.rdoc +2 -2
- data/doc/windows_install.rdoc +2 -2
- data/ext/rubygame/rubygame_event.c +116 -0
- data/ext/rubygame/rubygame_event2.c +661 -0
- data/ext/rubygame/rubygame_event2.h +29 -0
- data/ext/rubygame/rubygame_joystick.c +106 -17
- data/ext/rubygame/rubygame_main.c +3 -0
- data/ext/rubygame/rubygame_shared.c +2 -5
- data/ext/rubygame/rubygame_shared.h +1 -0
- data/ext/rubygame/rubygame_surface.c +11 -9
- data/lib/rubygame.rb +14 -3
- data/lib/rubygame/event_actions.rb +203 -0
- data/lib/rubygame/event_handler.rb +454 -0
- data/lib/rubygame/event_hook.rb +112 -0
- data/lib/rubygame/event_triggers.rb +692 -0
- data/lib/rubygame/events.rb +44 -0
- data/lib/rubygame/events/joystick_events.rb +342 -0
- data/lib/rubygame/events/keyboard_events.rb +132 -0
- data/lib/rubygame/events/misc_events.rb +144 -0
- data/lib/rubygame/events/mouse_events.rb +155 -0
- data/lib/rubygame/ftor.rb +2 -2
- data/lib/rubygame/queue.rb +50 -29
- data/samples/demo_draw.rb +175 -0
- data/samples/demo_rubygame.rb +421 -165
- metadata +18 -5
@@ -0,0 +1,112 @@
|
|
1
|
+
#--
|
2
|
+
# Rubygame -- Ruby code and bindings to SDL to facilitate game creation
|
3
|
+
# Copyright (C) 2004-2008 John Croisant
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'rubygame/event_triggers'
|
21
|
+
require 'rubygame/event_actions'
|
22
|
+
|
23
|
+
module Rubygame
|
24
|
+
|
25
|
+
# The EventHook class provides the bare framework for event hooks
|
26
|
+
# used by EventHandler. Each hook has a trigger, which controls what
|
27
|
+
# types of events cause the hook to engage, and an action, which
|
28
|
+
# controls what should happen when the hook engages.
|
29
|
+
#
|
30
|
+
# An instance of EventHook has these attributes:
|
31
|
+
#
|
32
|
+
# owner:: the object that this hook applies to. This value will
|
33
|
+
# be provided to the action when the hook engages.
|
34
|
+
#
|
35
|
+
# trigger:: an instance of a trigger class, used to test every
|
36
|
+
# event to check whether the hook should engage.
|
37
|
+
# A valid trigger must have a #match? method which
|
38
|
+
# accepts an event and returns either true or false.
|
39
|
+
#
|
40
|
+
# action:: an instance of an action class, which is performed
|
41
|
+
# when the trigger matches an event. A valid action
|
42
|
+
# must have a #perform method which accepts two values:
|
43
|
+
# the hook's owner and the matching event.
|
44
|
+
#
|
45
|
+
# consumes:: if true, the event hook "eats" every event that it
|
46
|
+
# matches, so that hooks that come after it will not
|
47
|
+
# see the event. Has no effect on non-matching events.
|
48
|
+
#
|
49
|
+
# active:: if false, the event hook is disabled, and will not
|
50
|
+
# match any event until it is set to true again. You can
|
51
|
+
# use this to temporarily disable the hook.
|
52
|
+
#
|
53
|
+
class EventHook
|
54
|
+
attr_accessor :owner, :trigger, :action, :consumes, :active
|
55
|
+
|
56
|
+
# Create a new instance of EventHook. Description is a Hash with
|
57
|
+
# the following keys. See the class documentation for EventHook for
|
58
|
+
# more information about what these mean.
|
59
|
+
#
|
60
|
+
# :owner:: the hook's owner. (any object, required)
|
61
|
+
# :trigger:: an event trigger which matches certain events.
|
62
|
+
# (Object with +#match?(event)+, required)
|
63
|
+
# :action:: an event action to do when an event matches.
|
64
|
+
# (Object with +#perform(owner,event)+, required)
|
65
|
+
# :consumes:: if true, the hook will "eat" matching so
|
66
|
+
# later hooks won't see them. Default: false.
|
67
|
+
# (true or false, optional)
|
68
|
+
# :active:: if false, the hook will ignore all events.
|
69
|
+
# Default: true. (true or false, optional)
|
70
|
+
#
|
71
|
+
# NOTE: None of the attributes are truly required to create a hook.
|
72
|
+
# But, the hook will do nothing unless both @trigger and @action are
|
73
|
+
# set. Setting @owner is also highly recommended, because some types
|
74
|
+
# of actions use the owner, and may raise an error if it is nil.
|
75
|
+
#
|
76
|
+
# TIP: It's possible to set these attributes at any time using the
|
77
|
+
# accessors. For example, You could change keyboard controls on the
|
78
|
+
# fly, or temporarily deactivate a hook to stop it from engaging.
|
79
|
+
#
|
80
|
+
# Example:
|
81
|
+
#
|
82
|
+
# # Call player1.jump() when the space bar is pressed.
|
83
|
+
# EventHook.new( :owner => player1,
|
84
|
+
# :trigger => KeyPressTrigger.new(:space)
|
85
|
+
# :action => MethodAction.new(:jump) )
|
86
|
+
#
|
87
|
+
def initialize( description={} )
|
88
|
+
@owner = description[:owner]
|
89
|
+
@trigger = description[:trigger]
|
90
|
+
@action = description[:action]
|
91
|
+
@consumes = (description[:consumes] or false)
|
92
|
+
@active = (description[:active].nil? ? true : description[:active])
|
93
|
+
end
|
94
|
+
|
95
|
+
# Passes the event to @trigger's #match? method, and returns the
|
96
|
+
# result. If there is no @trigger or if @active is false, returns
|
97
|
+
# nil immediately.
|
98
|
+
def match?( event )
|
99
|
+
if (@trigger and @active)
|
100
|
+
@trigger.match?( event )
|
101
|
+
else
|
102
|
+
false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Passes @owner and event to the @action's #perform method.
|
107
|
+
def perform( event )
|
108
|
+
@action.perform( owner, event ) if @action
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,692 @@
|
|
1
|
+
#--
|
2
|
+
# Rubygame -- Ruby code and bindings to SDL to facilitate game creation
|
3
|
+
# Copyright (C) 2004-2008 John Croisant
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'rubygame'
|
21
|
+
|
22
|
+
# This module contains all the event trigger classes that
|
23
|
+
# come with Rubygame.
|
24
|
+
#
|
25
|
+
# An event trigger class is simply a class which can be
|
26
|
+
# used as a trigger an EventHook. The trigger is used to
|
27
|
+
# determine whether the EventHook matches a particular
|
28
|
+
# event that occurs.
|
29
|
+
#
|
30
|
+
# The only requirement for an event trigger is this:
|
31
|
+
#
|
32
|
+
# * It must have a #match? method which takes exactly one
|
33
|
+
# argument (an event) and always returns either true or
|
34
|
+
# false.
|
35
|
+
#
|
36
|
+
# You can make your own custom event trigger classes and
|
37
|
+
# use them in an EventHook if they meet that requirement.
|
38
|
+
#
|
39
|
+
# NOTE: The #match? method may be called many times every
|
40
|
+
# second, even if there is no matching event. So, you should
|
41
|
+
# try to keep the method simple and fast, to have the least
|
42
|
+
# impact on your game's framerate.
|
43
|
+
#
|
44
|
+
# Here is an overview of the event trigger classes that
|
45
|
+
# come with Rubygame as of version 2.4:
|
46
|
+
#
|
47
|
+
#
|
48
|
+
# AndTrigger:: Holds multiple other triggers, and
|
49
|
+
# matches if ALL of the triggers
|
50
|
+
# match the event.
|
51
|
+
#
|
52
|
+
# OrTrigger:: Holds multiple other triggers, and
|
53
|
+
# matches if ONE OR MORE of the
|
54
|
+
# triggers match the event.
|
55
|
+
#
|
56
|
+
# AttrTrigger:: Matches if the event's attributes
|
57
|
+
# have the expected values.
|
58
|
+
#
|
59
|
+
# BlockTrigger:: Passes the event to a custom code
|
60
|
+
# block to check whether it matches.
|
61
|
+
#
|
62
|
+
# InstanceOfTrigger:: Matches if the event is an
|
63
|
+
# instance of a particular class.
|
64
|
+
#
|
65
|
+
# KeyPressTrigger:: Matches certain KeyPressed events.
|
66
|
+
#
|
67
|
+
# KeyReleaseTrigger:: Matches certain KeyReleased events.
|
68
|
+
#
|
69
|
+
# KindOfTrigger:: Matches if the event is #kind_of? a
|
70
|
+
# particular class or module.
|
71
|
+
#
|
72
|
+
# MousePressTrigger:: Matches certain MousePressed events.
|
73
|
+
#
|
74
|
+
# MouseMoveTrigger:: Matches certain MouseMoved events.
|
75
|
+
#
|
76
|
+
# MouseReleaseTrigger:: Matches certain MouseReleased events.
|
77
|
+
#
|
78
|
+
# YesTrigger:: Matches every event, no matter what.
|
79
|
+
#
|
80
|
+
module Rubygame::EventTriggers
|
81
|
+
|
82
|
+
#
|
83
|
+
# AndTrigger is an event trigger which contains one or
|
84
|
+
# more other triggers, and fires when an event matches
|
85
|
+
# all of its triggers. You can use this to create more
|
86
|
+
# complex logic than is possible with a single trigger.
|
87
|
+
#
|
88
|
+
# Contrast with OrTrigger.
|
89
|
+
#
|
90
|
+
class AndTrigger
|
91
|
+
|
92
|
+
# Initialize a new instance of AndTrigger, containing
|
93
|
+
# the given triggers.
|
94
|
+
#
|
95
|
+
# \*triggers:: The triggers to contain.
|
96
|
+
# (Array of triggers, required)
|
97
|
+
#
|
98
|
+
# Example:
|
99
|
+
#
|
100
|
+
# gameover_trigger = InstanceOfTrigger.new( GameOver )
|
101
|
+
# won_trigger = AttrTrigger.new( :won_game => true )
|
102
|
+
#
|
103
|
+
# # Matches only an event which is BOTH:
|
104
|
+
# # 1. an instance of class GameOver, AND
|
105
|
+
# # 2. returns true when #won_game is called
|
106
|
+
# AndTrigger.new( gameover_trigger, won_trigger )
|
107
|
+
#
|
108
|
+
def initialize( *triggers )
|
109
|
+
@triggers = triggers
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns true if the event matches all the triggers
|
113
|
+
# that the AndTrigger contains.
|
114
|
+
#
|
115
|
+
def match?( event )
|
116
|
+
@triggers.all? { |trigger| trigger.match? event }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
#
|
123
|
+
# OrTrigger is an event trigger which contains one or
|
124
|
+
# more other triggers, and fires when an event matches
|
125
|
+
# one or more of its triggers.
|
126
|
+
#
|
127
|
+
# Contrast with AndTrigger.
|
128
|
+
#
|
129
|
+
class OrTrigger
|
130
|
+
|
131
|
+
# Initialize a new instance of OrTrigger, containing
|
132
|
+
# the given triggers.
|
133
|
+
#
|
134
|
+
# \*triggers:: The triggers to contain.
|
135
|
+
# (Array of triggers, required)
|
136
|
+
#
|
137
|
+
# Example:
|
138
|
+
#
|
139
|
+
# is_red = AttrTrigger.new( :color => :red )
|
140
|
+
# is_blue = AttrTrigger.new( :color => :blue )
|
141
|
+
#
|
142
|
+
# # Matches only an event which has EITHER:
|
143
|
+
# # 1. #color == :red, OR
|
144
|
+
# # 2. #color == :blue
|
145
|
+
# is_red_or_blue = OrTrigger.new( is_red, is_blue )
|
146
|
+
#
|
147
|
+
#
|
148
|
+
# # More complex example with nested logic triggers:
|
149
|
+
#
|
150
|
+
# changed = InstanceOfTrigger.new( ColorChanged )
|
151
|
+
#
|
152
|
+
# changed_to_red_or_blue =
|
153
|
+
# AndTrigger.new( changed, is_red_or_blue )
|
154
|
+
#
|
155
|
+
def initialize( *triggers )
|
156
|
+
@triggers = triggers
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns true if the event matches one or more of
|
160
|
+
# the triggers that the OrTrigger contains.
|
161
|
+
#
|
162
|
+
def match?( event )
|
163
|
+
@triggers.any? { |trigger| trigger.match? event }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
#
|
170
|
+
# AttrTrigger is an event trigger which fires when an event
|
171
|
+
# has the expected value(s) for one or more attributes.
|
172
|
+
#
|
173
|
+
# AttrTrigger stores a Hash of :attr => value pairs, and
|
174
|
+
# checks each event to see if event.attr returns value.
|
175
|
+
# If all attributes have the expected value, the trigger fires.
|
176
|
+
#
|
177
|
+
class AttrTrigger
|
178
|
+
|
179
|
+
# Initialize a new instance of AttrTrigger with a
|
180
|
+
# Hash of one or more :attr => value pairs.
|
181
|
+
#
|
182
|
+
# attributes:: The attributes / value pairs to check.
|
183
|
+
# (Hash, required)
|
184
|
+
#
|
185
|
+
# Example:
|
186
|
+
#
|
187
|
+
# # Matches if event.color returns :red and
|
188
|
+
# # event.size returns :big
|
189
|
+
# AttrTrigger.new( :color => :red, :size => :big )
|
190
|
+
#
|
191
|
+
def initialize( attributes )
|
192
|
+
@attributes = attributes
|
193
|
+
end
|
194
|
+
|
195
|
+
# Returns true if, for every :attr => value pair, the event
|
196
|
+
# responds to :attr and calling event.attr returns value.
|
197
|
+
#
|
198
|
+
# Returns false if any of the attributes is not the expected value.
|
199
|
+
#
|
200
|
+
def match?( event )
|
201
|
+
@attributes.all? { |key, value|
|
202
|
+
event.respond_to?(key) and (event.send(key) == value)
|
203
|
+
}
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
|
209
|
+
#
|
210
|
+
# BlockTrigger is an event trigger which calls a block
|
211
|
+
# to check events. The trigger fires if the block returns
|
212
|
+
# true when called with the event as the only parameter.
|
213
|
+
#
|
214
|
+
class BlockTrigger
|
215
|
+
|
216
|
+
# Initialize a new instance of BlockTrigger with the given
|
217
|
+
# block. The block should take only 1 parameter, the event,
|
218
|
+
# and return true for matching events.
|
219
|
+
#
|
220
|
+
# &block:: The block to pass events to. (Proc, required)
|
221
|
+
#
|
222
|
+
def initialize( &block )
|
223
|
+
raise ArgumentError, "BlockTrigger needs a block" unless block_given?
|
224
|
+
@block = block
|
225
|
+
end
|
226
|
+
|
227
|
+
# Returns true if the block returns true when called
|
228
|
+
# with the event as the only parameter.
|
229
|
+
#
|
230
|
+
def match?( event )
|
231
|
+
@block.call( event ) == true
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
# class CollisionTrigger
|
238
|
+
#
|
239
|
+
# # type can be :start, :hold, :end, or :any
|
240
|
+
# def initialize( a=:any, b=:any, type=:any )
|
241
|
+
# @a, @b, @type = a, b, type
|
242
|
+
# end
|
243
|
+
#
|
244
|
+
# def match?( event )
|
245
|
+
# matching_types =
|
246
|
+
# case( event )
|
247
|
+
# when CollisionStartEvent
|
248
|
+
# [:start, :any]
|
249
|
+
# when CollisionEvent
|
250
|
+
# [:hold, :any]
|
251
|
+
# when CollisionEndEvent
|
252
|
+
# [:end, :any]
|
253
|
+
# else
|
254
|
+
# []
|
255
|
+
# end
|
256
|
+
#
|
257
|
+
# matching_types.include?(@type) and _has_objects?( event )
|
258
|
+
# end
|
259
|
+
#
|
260
|
+
# private
|
261
|
+
#
|
262
|
+
# # True if the event concerns the object(s) this trigger
|
263
|
+
# # is watching. It's not important that the event's pair order
|
264
|
+
# # matches the trigger's pair order.
|
265
|
+
# def _has_objects?( event )
|
266
|
+
# obs = [event.a, event.a.sprite, event.b, event.b.sprite]
|
267
|
+
#
|
268
|
+
# (@a == :any or obs.include?(@a)) and \
|
269
|
+
# (@b == :any or obs.include?(@b))
|
270
|
+
# end
|
271
|
+
#end
|
272
|
+
|
273
|
+
|
274
|
+
|
275
|
+
#
|
276
|
+
# InstanceOfTrigger is an event trigger which fires when
|
277
|
+
# the event is an instance of the given class. (In other
|
278
|
+
# words, when event.instance_of?( klass ) is true.)
|
279
|
+
#
|
280
|
+
# Contrast with KindOfTrigger.
|
281
|
+
#
|
282
|
+
class InstanceOfTrigger
|
283
|
+
|
284
|
+
# Initialize a new instance of InstanceOfTrigger with the
|
285
|
+
# given class.
|
286
|
+
#
|
287
|
+
# klass:: The class to check for. (Class, required)
|
288
|
+
#
|
289
|
+
def initialize( klass )
|
290
|
+
@klass = klass
|
291
|
+
end
|
292
|
+
|
293
|
+
# Returns true if the event is an instance of the class.
|
294
|
+
#
|
295
|
+
def match?( event )
|
296
|
+
event.instance_of?( @klass )
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
|
302
|
+
#
|
303
|
+
# KeyPressTrigger is an event trigger which fires when
|
304
|
+
# a key on the keyboard is pressed down (i.e. KeyPressed).
|
305
|
+
# See also KeyReleaseTrigger.
|
306
|
+
#
|
307
|
+
# This trigger can be configured to fire for any key,
|
308
|
+
# or a specific key. It can also fire depending on which
|
309
|
+
# modifier keys are held (ctrl, shift, alt, etc.).
|
310
|
+
#
|
311
|
+
# NOTE: This trigger only works with the new-style KeyPressed
|
312
|
+
# event class, not with the older KeyDownEvent.
|
313
|
+
# See EventQueue#enable_new_style_events
|
314
|
+
#
|
315
|
+
class KeyPressTrigger
|
316
|
+
|
317
|
+
# Initialize a new instance of KeyPressTrigger with the
|
318
|
+
# given key and modifier keys.
|
319
|
+
#
|
320
|
+
# key:: the key symbol to detect, or :any (default)
|
321
|
+
# to detect any key. (Symbol, optional)
|
322
|
+
#
|
323
|
+
# mods:: an Array of one or more modifier key symbols, or
|
324
|
+
# :none to detect key presses with exactly no modifiers,
|
325
|
+
# or :any (default) to detect any key modifiers.
|
326
|
+
#
|
327
|
+
# Valid modifiers are:
|
328
|
+
# * :alt, :left_alt, :right_alt,
|
329
|
+
# * :ctrl, :left_ctrl, :right_ctrl,
|
330
|
+
# * :shift, :left_shift, :right_shift,
|
331
|
+
# * :meta, :left_meta, :right_meta,
|
332
|
+
# * :numlock
|
333
|
+
# * :capslock
|
334
|
+
# * :mode
|
335
|
+
#
|
336
|
+
# :alt, :ctrl, :shift, and :meta will match either the
|
337
|
+
# left version or right version (e.g. :left_alt or
|
338
|
+
# :right_alt).
|
339
|
+
#
|
340
|
+
# Example:
|
341
|
+
#
|
342
|
+
# # Matches any key press, regardless of the key or modifiers.
|
343
|
+
# KeyPressTrigger.new
|
344
|
+
#
|
345
|
+
# # Matches the 'A' key with any (or no) modifiers.
|
346
|
+
# KeyPressTrigger.new( :a )
|
347
|
+
#
|
348
|
+
# # Matches the 'A' with both Ctrl and Shift modifiers.
|
349
|
+
# KeyPressTrigger.new( :a, [:ctrl, :shift] )
|
350
|
+
#
|
351
|
+
# # Matches the 'A' with both Left Ctrl and Left Shift modifiers.
|
352
|
+
# KeyPressTrigger.new( :a, [:left_ctrl, :left_shift] )
|
353
|
+
#
|
354
|
+
#
|
355
|
+
def initialize( key=:any, mods=:any )
|
356
|
+
@key = key
|
357
|
+
@mods = mods
|
358
|
+
end
|
359
|
+
|
360
|
+
# Returns true if the event is a KeyPressed event and the event's
|
361
|
+
# key and mods BOTH match the trigger's expectations.
|
362
|
+
#
|
363
|
+
# Key matches if either of these is true:
|
364
|
+
# * the trigger's key is the symbol :any
|
365
|
+
# * the event's key is the same as the trigger's key
|
366
|
+
#
|
367
|
+
# Modifiers matches if any of these is true:
|
368
|
+
# * the trigger's @mods is the symbol :any
|
369
|
+
# * the event has no modifiers and the trigger's @mods is
|
370
|
+
# the symbol :none
|
371
|
+
# * every one of the trigger's @mods matches one of the event's
|
372
|
+
# modifiers. "Matches" means either it is the same symbol,
|
373
|
+
# or it is a more general version. For example, :alt will
|
374
|
+
# match either :left_alt or :right_alt.
|
375
|
+
#
|
376
|
+
def match?( event )
|
377
|
+
if event.kind_of?( Events::KeyPressed )
|
378
|
+
((@key == :any) or (event.key == @key)) and \
|
379
|
+
((@mods == :any) or (@mods == :none and event.modifiers == [])\
|
380
|
+
or (_mods_match?(event.modifiers)))
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
|
385
|
+
private
|
386
|
+
|
387
|
+
# True if every modifier in @mods matches a modifier in
|
388
|
+
# evmods. :alt, :ctrl, :meta, and :shift match either
|
389
|
+
# the left or right versions (e.g. :left_alt, :right_alt).
|
390
|
+
# All other symbols match themselves.
|
391
|
+
#
|
392
|
+
def _mods_match?( evmods ) # :nodoc:
|
393
|
+
@mods.all? { |mod|
|
394
|
+
case mod
|
395
|
+
when :alt, :ctrl, :meta, :shift
|
396
|
+
evmods.include?("left_#{mod}".intern) or
|
397
|
+
evmods.include?("right_#{mod}".intern)
|
398
|
+
else
|
399
|
+
evmods.include?(mod)
|
400
|
+
end
|
401
|
+
}
|
402
|
+
end
|
403
|
+
|
404
|
+
end
|
405
|
+
|
406
|
+
|
407
|
+
|
408
|
+
#
|
409
|
+
# KeyReleaseTrigger is an event trigger which fires when
|
410
|
+
# a key on the keyboard is released (i.e. KeyReleased).
|
411
|
+
#
|
412
|
+
# NOTE: This trigger is identical to KeyPressTrigger, except that
|
413
|
+
# it fires for KeyReleased instead of KeyPressed. Please
|
414
|
+
# see the documentation for KeyPressTrigger for info about
|
415
|
+
# the parameters and behavior of the trigger.
|
416
|
+
#
|
417
|
+
# NOTE: This trigger only works with the new-style KeyReleased
|
418
|
+
# event class, not with the older KeyUpEvent.
|
419
|
+
# See EventQueue#enable_new_style_events
|
420
|
+
#
|
421
|
+
class KeyReleaseTrigger
|
422
|
+
|
423
|
+
# Initialize a new instance of KeyReleaseTrigger with the
|
424
|
+
# given key and modifier keys.
|
425
|
+
#
|
426
|
+
# See KeyPressTrigger#new for more information and examples.
|
427
|
+
#
|
428
|
+
def initialize( key=:any, mods=:any )
|
429
|
+
@key = key
|
430
|
+
@mods = mods
|
431
|
+
end
|
432
|
+
|
433
|
+
# Returns true if the event is a KeyReleased event and the event's
|
434
|
+
# key and mods BOTH match the trigger's expectations.
|
435
|
+
#
|
436
|
+
# See KeyPressTrigger#match? for more information.
|
437
|
+
#
|
438
|
+
def match?( event )
|
439
|
+
if event.kind_of?( Events::KeyReleased )
|
440
|
+
((@key == :any) or (event.key == @key)) and \
|
441
|
+
((@mods == :any) or (@mods == :none and event.modifiers == [])\
|
442
|
+
or (_mods_match?(event.modifiers)))
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
|
447
|
+
private
|
448
|
+
|
449
|
+
# True if every modifier in @mods matches a modifier in
|
450
|
+
# evmods. :alt, :ctrl, :meta, and :shift match either
|
451
|
+
# the left or right versions (e.g. :left_alt, :right_alt).
|
452
|
+
# All other symbols match themselves.
|
453
|
+
#
|
454
|
+
def _mods_match?( evmods ) # :nodoc:
|
455
|
+
@mods.all? { |mod|
|
456
|
+
case mod
|
457
|
+
when :alt, :ctrl, :meta, :shift
|
458
|
+
evmods.include?("left_#{mod}".intern) or
|
459
|
+
evmods.include?("right_#{mod}".intern)
|
460
|
+
else
|
461
|
+
evmods.include?(mod)
|
462
|
+
end
|
463
|
+
}
|
464
|
+
end
|
465
|
+
|
466
|
+
|
467
|
+
end
|
468
|
+
|
469
|
+
|
470
|
+
|
471
|
+
#
|
472
|
+
# KindOfTrigger is an event trigger which fires when
|
473
|
+
# the event is kind of the given class or module.
|
474
|
+
# (In other words, when event.kind_of?( kind ) is
|
475
|
+
# true.)
|
476
|
+
#
|
477
|
+
# Contrast with InstanceOfTrigger.
|
478
|
+
#
|
479
|
+
class KindOfTrigger
|
480
|
+
|
481
|
+
# Initialize a new instance of KindOfTrigger with the
|
482
|
+
# given class or module.
|
483
|
+
#
|
484
|
+
# kind:: The class/module to check for.
|
485
|
+
# (Class or Module, required)
|
486
|
+
#
|
487
|
+
def initialize( kind )
|
488
|
+
@kind = kind
|
489
|
+
end
|
490
|
+
|
491
|
+
# Returns true if the event is kind of the class/module.
|
492
|
+
#
|
493
|
+
def match?( event )
|
494
|
+
event.kind_of?( @kind )
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
|
499
|
+
|
500
|
+
#
|
501
|
+
# MousePressTrigger is an event trigger which fires when
|
502
|
+
# a mouse button is pressed down (i.e. MousePressed).
|
503
|
+
#
|
504
|
+
# By default, this trigger fires for any mouse press, but
|
505
|
+
# it can be configured to fire for only a specific mouse
|
506
|
+
# button by passing a button symbol to #new.
|
507
|
+
#
|
508
|
+
# See also MousReleaseTrigger.
|
509
|
+
#
|
510
|
+
class MousePressTrigger
|
511
|
+
|
512
|
+
|
513
|
+
# Initialize a new instance of MousePressTrigger with
|
514
|
+
# the given mouse button.
|
515
|
+
#
|
516
|
+
# button:: The mouse button symbol to detect, or :any
|
517
|
+
# to detect any button press.
|
518
|
+
#
|
519
|
+
# Valid mouse button symbols are: :mouse_left,
|
520
|
+
# :mouse_middle, :mouse_right, :mouse_wheel_up,
|
521
|
+
# and :mouse_wheel_down.
|
522
|
+
#
|
523
|
+
def initialize( button=:any )
|
524
|
+
@button = button
|
525
|
+
end
|
526
|
+
|
527
|
+
# Returns true if the event is a MousePressed event and
|
528
|
+
# the event's button is the same as the trigger's button
|
529
|
+
# (or the trigger's button is :any).
|
530
|
+
#
|
531
|
+
def match?( event )
|
532
|
+
if event.kind_of?( Events::MousePressed )
|
533
|
+
((@button == :any) or (event.button == @button))
|
534
|
+
else
|
535
|
+
false
|
536
|
+
end
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
|
541
|
+
|
542
|
+
#
|
543
|
+
# MouseMoveTrigger is an event trigger which fires when the
|
544
|
+
# mouse cursor is moved (MouseMoved). If buttons are given,
|
545
|
+
# it only matches events with those buttons. See #new for details.
|
546
|
+
#
|
547
|
+
class MouseMoveTrigger
|
548
|
+
|
549
|
+
#
|
550
|
+
# Create a new instance of MouseMoveTrigger.
|
551
|
+
#
|
552
|
+
# The buttons parameter determines which mouse buttons can
|
553
|
+
# be held down and still match this trigger. It can be one of:
|
554
|
+
#
|
555
|
+
# 1. +:any+. Matches if zero or more buttons are held.
|
556
|
+
# 2. +:none+. Matches when zero buttons are being held.
|
557
|
+
# 3. +:mouse_left+, etc. Matches when at least the given
|
558
|
+
# button is being held.
|
559
|
+
# 4. An array of +:mouse_*+ symbols. Matches when exactly all
|
560
|
+
# buttons in the Array are being held, and nothing else.
|
561
|
+
#
|
562
|
+
#
|
563
|
+
# Example:
|
564
|
+
#
|
565
|
+
# # Matches all MouseMoved events, regardless of buttons:
|
566
|
+
# MouseMoveTrigger.new()
|
567
|
+
# MouseMoveTrigger.new( :any )
|
568
|
+
#
|
569
|
+
#
|
570
|
+
# # Matches only if no buttons pressed:
|
571
|
+
# MouseMoveTrigger.new( :none )
|
572
|
+
# MouseMoveTrigger.new( [] )
|
573
|
+
#
|
574
|
+
#
|
575
|
+
# # Matches if left mouse is held down, maybe with others:
|
576
|
+
# MouseMoveTrigger.new( :mouse_left )
|
577
|
+
#
|
578
|
+
#
|
579
|
+
# # Matches if ONLY left mouse held down, nothing else:
|
580
|
+
# MouseMoveTrigger.new( [:mouse_left] )
|
581
|
+
#
|
582
|
+
#
|
583
|
+
# # Matches if BOTH left AND right mouse are held down, nothing else:
|
584
|
+
# MouseMoveTrigger.new( [:mouse_left, :mouse_right] )
|
585
|
+
#
|
586
|
+
#
|
587
|
+
# # Matches if EITHER left OR right mouse are held down:
|
588
|
+
# OrTrigger.new( MouseMoveTrigger.new(:mouse_left),
|
589
|
+
# MouseMoveTrigger.new(:mouse_right) )
|
590
|
+
#
|
591
|
+
#
|
592
|
+
def initialize( buttons=:any )
|
593
|
+
@buttons = buttons
|
594
|
+
end
|
595
|
+
|
596
|
+
#
|
597
|
+
# Returns true if the given event matches this trigger.
|
598
|
+
# See #new for information about how events match.
|
599
|
+
#
|
600
|
+
def match?( event )
|
601
|
+
if event.kind_of?( Events::MouseMoved )
|
602
|
+
((@buttons == :any) or
|
603
|
+
(@buttons == :none and event.buttons == []) or
|
604
|
+
(_buttons_match?(event.buttons)) or
|
605
|
+
(event.buttons.include?(@buttons)))
|
606
|
+
else
|
607
|
+
false
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
private
|
612
|
+
|
613
|
+
# Returns true if evbuttons is the same as @buttons,
|
614
|
+
# ignoring the order of the symbols.
|
615
|
+
#
|
616
|
+
def _buttons_match?( evbuttons )
|
617
|
+
if( @buttons.kind_of? Symbol )
|
618
|
+
return false
|
619
|
+
end
|
620
|
+
|
621
|
+
e = evbuttons.sort_by { |button| button.to_s }
|
622
|
+
t = @buttons.sort_by { |button| button.to_s }
|
623
|
+
return (e == t)
|
624
|
+
end
|
625
|
+
|
626
|
+
end
|
627
|
+
|
628
|
+
|
629
|
+
|
630
|
+
#
|
631
|
+
# MouseReleaseTrigger is an event trigger which fires when
|
632
|
+
# a mouse button is released (i.e. MouseReleased).
|
633
|
+
#
|
634
|
+
# By default, this trigger fires for any mouse release, but
|
635
|
+
# it can be configured to fire for only a specific mouse
|
636
|
+
# button by passing a button symbol to #new.
|
637
|
+
#
|
638
|
+
# See also MousePressTrigger.
|
639
|
+
#
|
640
|
+
class MouseReleaseTrigger
|
641
|
+
|
642
|
+
# Initialize a new instance of MouseReleaseTrigger with
|
643
|
+
# the given mouse button.
|
644
|
+
#
|
645
|
+
# button:: The mouse button symbol to detect, or :any
|
646
|
+
# to detect any button press.
|
647
|
+
#
|
648
|
+
# Valid mouse button symbols are: :mouse_left,
|
649
|
+
# :mouse_middle, :mouse_right, :mouse_wheel_up,
|
650
|
+
# and :mouse_wheel_down.
|
651
|
+
#
|
652
|
+
def initialize( button=:any )
|
653
|
+
@button = button
|
654
|
+
end
|
655
|
+
|
656
|
+
# Returns true if the event is a MouseReleased event and
|
657
|
+
# the event's button is the same as the trigger's button
|
658
|
+
# (or the trigger's button is :any).
|
659
|
+
#
|
660
|
+
def match?( event )
|
661
|
+
if event.kind_of?( Events::MouseReleased )
|
662
|
+
((@button == :any) or (event.button == @button))
|
663
|
+
else
|
664
|
+
false
|
665
|
+
end
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
|
670
|
+
|
671
|
+
# class TickTrigger
|
672
|
+
# def match?( event )
|
673
|
+
# event.kind_of?( Events::ClockTicked )
|
674
|
+
# end
|
675
|
+
# end
|
676
|
+
|
677
|
+
|
678
|
+
|
679
|
+
#
|
680
|
+
# YesTrigger is an event trigger which will fire
|
681
|
+
# when any event occurs, regardless of the event
|
682
|
+
# type or details.
|
683
|
+
#
|
684
|
+
class YesTrigger
|
685
|
+
|
686
|
+
# Returns true every time.
|
687
|
+
def match?( event )
|
688
|
+
true
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
end
|