Commit 03625a4d4288e7a5cc66b98ca8367af5dc54e974
- Diff rendering mode:
- inline
- side by side
lib/ruby/wii_remote.rb
(169 / 65)
|   | |||
| 1 | class Java::WiiremotejEvent::WRButtonEvent | ||
| 2 | |||
| 3 | def details= h | ||
| 4 | @details = h | ||
| 5 | end | ||
| 6 | |||
| 7 | def details | ||
| 8 | @details || {} | ||
| 9 | end | ||
| 10 | end | ||
| 11 | |||
| 1 | 12 | module Neurogami | |
| 13 | |||
| 2 | 14 | class Wiimote | |
| 3 | 15 | ||
| 4 | 16 | def self.attach owner, map = {} | |
| 5 | 17 | @owner = owner | |
| 6 | @map = map | ||
| 18 | |||
| 7 | 19 | warn "Finding remote .." | |
| 8 | remote = WiiRemoteJ::WiiRemoteJ.findRemote | ||
| 9 | raise "Wiimote class could not attache to Wiimote!" unless remote | ||
| 10 | listener = MbWiiRemoteListener.new(remote) | ||
| 20 | |||
| 21 | remote = nil | ||
| 22 | |||
| 23 | begin | ||
| 24 | remote = WiiRemoteJ::WiiRemoteJ.findRemote | ||
| 25 | warn "remote: #{remote.pretty_inspect}" | ||
| 26 | rescue Exception | ||
| 27 | warn "Error calling findRemote: #{$!}" | ||
| 28 | raise | ||
| 29 | end | ||
| 30 | |||
| 31 | unless remote | ||
| 32 | sleep 2 | ||
| 33 | raise "Wiimote class could not attache to Wiimote!" | ||
| 34 | end | ||
| 35 | |||
| 36 | |||
| 37 | listener = WiiRemoteListener.new(remote) | ||
| 11 | 38 | listener.event_map(owner, map ) | |
| 12 | 39 | remote.addWiiRemoteListener(listener) | |
| 13 | 40 | remote.accelerometerEnabled = true | |
| 14 | # remote.setIRSensorEnabled(true, WiiRemoteJEvent::WRIREvent.BASIC ) | ||
| 15 | remote.setIRSensorEnabled(true, WiiRemoteJEvent::WRIREvent.FULL, WiiRemoteJ::IRSensitivitySettings::WII_LEVEL_4) | ||
| 16 | remote.enableContinuous | ||
| 41 | |||
| 42 | # Need this if you want to track IR events | ||
| 43 | #remote.setIRSensorEnabled(true, WiiRemoteJEvent::WRIREvent.FULL, WiiRemoteJ::IRSensitivitySettings::WII_LEVEL_4) | ||
| 44 | # remote.enableContinuous | ||
| 45 | |||
| 46 | # This works, giving both IR and pitch, roll info | ||
| 47 | remote.setIRSensorEnabled(true, WiiRemoteJEvent::WRIREvent.BASIC, WiiRemoteJ::IRSensitivitySettings::WII_LEVEL_3) | ||
| 48 | |||
| 49 | # But this only gives IR data; pitch stuff ends up NaN or zero | ||
| 50 | #remote.setIRSensorEnabled(true, WiiRemoteJEvent::WRIREvent.FULL, WiiRemoteJ::IRSensitivitySettings::WII_LEVEL_3) | ||
| 51 | |||
| 52 | # remote.setIRSensorEnabled(true, WiiRemoteJEvent::WRIREvent.EXTENDED, WiiRemoteJ::IRSensitivitySettings::WII_LEVEL_3) | ||
| 53 | # remote.enableContinuous | ||
| 54 | remote.setLEDIlluminated(0, true); | ||
| 55 | |||
| 17 | 56 | remote | |
| 18 | 57 | end | |
| 19 | 58 | end | |
| 20 | 59 | ||
| 21 | class MbWiiRemoteListener | ||
| 60 | |||
| 61 | def add_to_mappings map | ||
| 62 | STDERR.puts( ":DEBUG #{__FILE__}:#{__LINE__}" ) if ENV['JAMES_SCA_JDEV_MACHINE'] # JGBDEBUG | ||
| 63 | listener = WiiRemoteListener.new(self) | ||
| 64 | listener.event_map(nil, map ) | ||
| 65 | self.addWiiRemoteListener(listener) | ||
| 66 | # remote.accelerometerEnabled = true | ||
| 67 | self | ||
| 68 | end | ||
| 69 | |||
| 70 | class WiiRemoteListener | ||
| 71 | @@button_masks = {} | ||
| 72 | |||
| 22 | 73 | def initialize remote | |
| 23 | 74 | @remote = remote | |
| 24 | 75 | @accelerometer_source = true #//true = wii remote, false = nunchuk | |
| 76 | warn " Created WiiRemoteListener" | ||
| 77 | STDERR.puts( ":DEBUG #{__FILE__}:#{__LINE__}" ) if ENV['JAMES_SCA_JDEV_MACHINE'] # JGBDEBUG | ||
| 25 | 78 | end | |
| 26 | 79 | ||
| 27 | 80 | def event_map owner, map={} | |
| 28 | 81 | @owner = owner | |
| 29 | @map = map | ||
| 82 | @maps ||= [] | ||
| 83 | @maps << map | ||
| 30 | 84 | end | |
| 31 | 85 | ||
| 32 | 86 | def accelerometer_source | |
| … | … | ||
| 95 | 95 | # the button value. Instead, you have to play 20 questions. | |
| 96 | 96 | # | |
| 97 | 97 | # | |
| 98 | def button_input_received evt | ||
| 98 | def button_input_received event | ||
| 99 | dispatch_on_button event | ||
| 100 | end | ||
| 99 | 101 | ||
| 100 | %w{ B | ||
| 101 | DOWN | ||
| 102 | HOME | ||
| 103 | LEFT | ||
| 104 | MINUS | ||
| 105 | ONE | ||
| 106 | PLUS | ||
| 107 | RIGHT | ||
| 108 | TWO | ||
| 109 | UP }.each do |button| | ||
| 110 | next unless @map[:"#{button.to_s.downcase}_button"] | ||
| 102 | def maps_contain key | ||
| 103 | @maps.each do |map| | ||
| 104 | return true if map[key] | ||
| 105 | end | ||
| 106 | false | ||
| 107 | end | ||
| 111 | 108 | ||
| 112 | if evt.wasPressed( eval( "WiiRemoteJEvent::WRButtonEvent::#{button}" )) | ||
| 113 | warn button.to_s | ||
| 114 | @owner.send(@map[:"#{button.to_s.downcase}_button"]) | ||
| 115 | return | ||
| 109 | def maps_handle_event event_key, event | ||
| 110 | @maps.each do |map| | ||
| 111 | map[event_key].call event | ||
| 116 | 112 | end | |
| 117 | end | ||
| 118 | 113 | end | |
| 119 | 114 | ||
| 120 | def acceleration_input_received evt | ||
| 121 | return unless @map[:acceleration_input_received] | ||
| 122 | x = evt.getXAcceleration | ||
| 123 | y = evt.getYAcceleration | ||
| 124 | z = evt.getZAcceleration | ||
| 125 | @owner.send(@map[:acceleration_input_received], x, y, z) | ||
| 115 | def acceleration_input_received event | ||
| 116 | return unless maps_contain :motion_sensing_event | ||
| 117 | maps_handle_event :motion_sensing_event, event | ||
| 126 | 118 | end | |
| 127 | 119 | ||
| 120 | # | ||
| 121 | def IRInputReceived event | ||
| 122 | return unless maps_contain :ir_sensing_event | ||
| 123 | maps_handle_event :ir_sensing_event, event | ||
| 128 | 124 | ||
| 129 | =begin | ||
| 130 | Method Summary | ||
| 131 | boolean equals(java.lang.Object other) | ||
| 132 | Returns true if this IRLight is equivalent to the given IRLight; otherwise false. | ||
| 133 | double getIntensity() | ||
| 134 | Returns the intensity of the light dot from 0 to 1 (percent). | ||
| 135 | double getSize() | ||
| 136 | Returns the size of the light dot from 0 to 1 (percent). | ||
| 137 | double getX() | ||
| 138 | Returns the X coordinate of the light dot from 0 to 1 (percent). | ||
| 139 | double getXMax() | ||
| 140 | Returns the maximum X coordinate of the light dot's bounding box from 0 to 1 (percent). | ||
| 141 | double getXMin() | ||
| 142 | Returns the minimum X coordinate of the light dot's bounding box from 0 to 1 (percent). | ||
| 143 | double getY() | ||
| 144 | Returns the Y coordinate of the light dot from 0 to 1 (percent). | ||
| 145 | double getYMax() | ||
| 146 | Returns the maximum Y coordinate of the light dot's bounding box from 0 to 1 (percent). | ||
| 147 | double getYMin() | ||
| 148 | Returns the minimum Y coordinate of the light dot's bounding box from 0 to 1 (percent). | ||
| 149 | =end | ||
| 150 | def IRInputReceived evt | ||
| 151 | evt.getIRLights.each_with_index do |light, idx| | ||
| 152 | if light | ||
| 153 | @owner.send(@map[:ir_light], idx, light) if @map[:ir_light] | ||
| 154 | # warn("IR #{idx} X: #{ light.getX() * 100}") | ||
| 155 | # warn("IR #{idx} Y: #{light.getY() * 100}") | ||
| 156 | end | ||
| 157 | end | ||
| 158 | |||
| 159 | 125 | end | |
| 160 | 126 | ||
| 127 | |||
| 161 | 128 | def method_missing m, *args | |
| 162 | # warn " MbWiiRemoteListener mm: #{m}, #{args.inspect}" | ||
| 129 | m = " WiiRemoteListener mm: #{m}, #{args.inspect}" | ||
| 130 | STDERR.puts( ":DEBUG #{__FILE__}:#{__LINE__}\n#{}" ) if ENV['JAMES_SCA_JDEV_MACHINE'] # JGBDEBUG | ||
| 163 | 131 | end | |
| 164 | 132 | ||
| 165 | def null | ||
| 166 | nil | ||
| 133 | |||
| 134 | # Here's the thing: | ||
| 135 | # A user can be doing any number of things with buttons, including | ||
| 136 | # pressing multiple buttons, holding buttons down, releasing buttons. | ||
| 137 | # | ||
| 138 | # We might want to loop over the mapping and only see if we have | ||
| 139 | # a matching event. | ||
| 140 | # For example, | ||
| 141 | # :wiimote_button_b maps to the B button pressed. | ||
| 142 | # :wiimote_button_b_wiimote_button_a would map to both A + B pressed. | ||
| 143 | # We still get lots of combos: | ||
| 144 | # :wiimote_button_b_only | ||
| 145 | # | ||
| 146 | # There's also 'is' and 'was' ... ? | ||
| 147 | # | ||
| 148 | # and 'released' | ||
| 149 | # | ||
| 150 | # :wiimote_button_b_was_released | ||
| 151 | # | ||
| 152 | # We need some formal syntax so we can create code: | ||
| 153 | # | ||
| 154 | # :wiimote_button_<x>_<action> | ||
| 155 | # | ||
| 156 | # isAnyPressed(int buttonMask) | ||
| 157 | # Returns true if any of the given buttons are pressed; otherwise false. | ||
| 158 | # boolean isOnlyPressed(int buttonMask) | ||
| 159 | # Returns true if all of the given buttons are pressed and no others are; otherwise false. | ||
| 160 | # boolean isPressed(int buttonMask) | ||
| 161 | # Returns true if all of the given buttons are pressed; otherwise false. | ||
| 162 | # boolean wasOnlyPressed(int buttonMask) | ||
| 163 | # Returns true if all of the given buttons were pressed and no others are; otherwise false. | ||
| 164 | # boolean wasPressed(int buttonMask) | ||
| 165 | # Returns true if all of the given buttons were pressed; otherwise false. | ||
| 166 | # boolean wasReleased(int buttonMask) | ||
| 167 | # Returns true if one of the given buttons wa | ||
| 168 | # | ||
| 169 | # We need to figure out, for each mapping, the button mask, and then the action to | ||
| 170 | # look for. | ||
| 171 | # Given - | ||
| 172 | # { :buttons => :two, :action => :only_pressed } => lambda {|e| exit_button_action_performed e }, | ||
| 173 | # { :buttons => [:two, :b], :action => :released } => lambda {|e| release_example e }, | ||
| 174 | # | ||
| 175 | ## | ||
| 176 | def dispatch_on_button event | ||
| 177 | |||
| 178 | @maps.each do |map| | ||
| 179 | |||
| 180 | map[:buttons].each do |m| | ||
| 181 | mask = buttons_to_mask(m[:buttons]) | ||
| 182 | action = m[:action] | ||
| 183 | # Can we do some dynaimic invokation here? | ||
| 184 | event.details = {:buttons => m[:buttons] , :action => action }; | ||
| 185 | case action | ||
| 186 | when :any_pressed | ||
| 187 | m[:handler].call(event) if event.isAnyPressed(mask) | ||
| 188 | when :is_only_pressed | ||
| 189 | m[:handler].call(event) if event.isOnlyPressed(mask) | ||
| 190 | when :pressed | ||
| 191 | m[:handler].call(event) if event.isPressed(mask) | ||
| 192 | when :was_only_pressed | ||
| 193 | m[:handler].call(event) if event.wasOnlyPressed(mask) | ||
| 194 | when :was_pressed | ||
| 195 | m[:handler].call(event) if event.wasPressed(mask) | ||
| 196 | when :was_released | ||
| 197 | m[:handler].call(event) if event.wasReleased(mask) | ||
| 198 | end | ||
| 199 | |||
| 200 | end | ||
| 201 | end | ||
| 202 | |||
| 167 | 203 | end | |
| 168 | 204 | ||
| 205 | |||
| 206 | def buttons_to_mask buttons | ||
| 207 | if buttons.is_a?(Array) | ||
| 208 | mask = 0 | ||
| 209 | buttons.each do |button| | ||
| 210 | @@button_masks[button] ||= eval "WiiRemoteJEvent::WRButtonEvent::#{button.to_s.upcase}" | ||
| 211 | mask =+ @@button_masks[button] | ||
| 212 | end | ||
| 213 | mask | ||
| 214 | else | ||
| 215 | @@button_masks[buttons] ||= eval "WiiRemoteJEvent::WRButtonEvent::#{buttons.to_s.upcase}" | ||
| 216 | @@button_masks[buttons] | ||
| 217 | end | ||
| 218 | end | ||
| 169 | 219 | end | |
| 170 | 220 | end |
lib/ruby/wiimotable.rb
(45 / 32)
|   | |||
| 1 | # http://wiki.jruby.org/wiki/Calling_Java_from_JRuby#Use_include_package_within_a_Ruby_Module_to_import_a_Java_Package | ||
| 2 | module WiiRemoteJ | ||
| 3 | include_package 'wiiremotej' | ||
| 4 | end | ||
| 1 | require 'spinner_dialog' | ||
| 5 | 2 | ||
| 6 | module WiiRemoteJEvent | ||
| 7 | include_package 'wiiremotej.event' | ||
| 8 | end | ||
| 3 | class GlobalWiimote | ||
| 9 | 4 | ||
| 5 | @@wiimote = nil | ||
| 10 | 6 | ||
| 11 | #module JavaxSoundSampled | ||
| 12 | # include_package 'javax.sound.sampled' | ||
| 13 | #end | ||
| 7 | def self.wiimote | ||
| 8 | @@wiimote | ||
| 9 | end | ||
| 14 | 10 | ||
| 15 | include WiiRemoteJ | ||
| 16 | include WiiRemoteJEvent | ||
| 17 | # include JavaxSoundSampled | ||
| 11 | def self.wiimote= wiimote | ||
| 12 | @@wiimote = wiimote | ||
| 13 | end | ||
| 18 | 14 | ||
| 19 | require 'spinner_dialog' | ||
| 15 | def self.add_to_mappings wiimote, map | ||
| 16 | listener = Neurogami::WiiRemoteListener.new(wiimote) | ||
| 17 | listener.event_map(nil, map ) | ||
| 18 | wiimote.addWiiRemoteListener(listener) | ||
| 19 | wiimote | ||
| 20 | end | ||
| 20 | 21 | ||
| 22 | end | ||
| 23 | |||
| 21 | 24 | module Neurogami | |
| 22 | 25 | ||
| 23 | 26 | module Wiimotable | |
| 24 | def wiimote_me mapping | ||
| 25 | max_attempts = 3 | ||
| 26 | attempts_so_far = 0 | ||
| 27 | begin | ||
| 28 | attempts_so_far += 1 | ||
| 29 | transfer[:attempt_number] = attempts_so_far | ||
| 30 | signal :set_discovery_mode | ||
| 31 | @remote = Wiimote.attach self, mapping | ||
| 32 | rescue Exception => e | ||
| 33 | warn "Error #{e.inspect}" | ||
| 34 | warn "Signal to end dicovery mode. Have @remote #{@remote.inspect}" | ||
| 35 | exit if e.is_a?(NameError) | ||
| 36 | signal :end_discovery_mode | ||
| 37 | if attempts_so_far < max_attempts | ||
| 38 | retry | ||
| 39 | else | ||
| 40 | raise | ||
| 27 | def wiimote_me event_map, max_attempts = nil | ||
| 28 | unless GlobalWiimote.wiimote | ||
| 29 | attempts_so_far = 0 | ||
| 30 | begin | ||
| 31 | attempts_so_far += 1 | ||
| 32 | transfer[:attempt_number] = attempts_so_far | ||
| 33 | signal :set_discovery_mode | ||
| 34 | GlobalWiimote.wiimote = Wiimote.attach self, event_map | ||
| 35 | GlobalWiimote.wiimote.setLEDIlluminated(0, true); | ||
| 36 | rescue Exception => e | ||
| 37 | signal :end_discovery_mode | ||
| 38 | if max_attempts.nil? || attempts_so_far < max_attempts | ||
| 39 | retry | ||
| 40 | else | ||
| 41 | raise e | ||
| 42 | end | ||
| 41 | 43 | end | |
| 44 | else | ||
| 45 | # GlobalWiimote.wiimote = Wiimote.attach self, event_map | ||
| 46 | GlobalWiimote.add_to_mappings GlobalWiimote.wiimote, event_map | ||
| 42 | 47 | end | |
| 43 | 48 | ensure | |
| 44 | 49 | signal :end_discovery_mode | |
| 50 | GlobalWiimote.wiimote | ||
| 45 | 51 | end | |
| 46 | 52 | ||
| 53 | def clean_up_and_exit | ||
| 54 | GlobalWiimote.wiimote.setLEDIlluminated(0, false); | ||
| 55 | GlobalWiimote.wiimote.disconnect | ||
| 56 | java.lang.System.exit(0) | ||
| 57 | end | ||
| 47 | 58 | end | |
| 48 | 59 | ||
| 60 | |||
| 61 | |||
| 49 | 62 | module WiimotableView | |
| 50 | 63 | ||
| 51 | 64 | def set_discovery_mode model, transfer | |
| … | … | ||
| 77 | 77 | @spinner.hide | |
| 78 | 78 | @spinner = nil | |
| 79 | 79 | end | |
| 80 | |||
| 81 | 80 | end | |
| 81 | |||
| 82 | 82 | end |

