gamebox 0.4.0.rc5 → 0.4.0.rc11

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.
Files changed (93) hide show
  1. data/README.md +205 -127
  2. data/bin/gamebox +49 -3
  3. data/bin/gb +87 -0
  4. data/gamebox.gemspec +4 -3
  5. data/lib/gamebox.rb +1 -1
  6. data/lib/gamebox/actors/collidable_debugger.rb +4 -4
  7. data/lib/gamebox/actors/icon.rb +7 -0
  8. data/lib/gamebox/actors/label.rb +41 -42
  9. data/lib/gamebox/behaviors/animated.rb +6 -0
  10. data/lib/gamebox/behaviors/audible.rb +1 -2
  11. data/lib/gamebox/behaviors/collidable.rb +1 -1
  12. data/lib/gamebox/behaviors/graphical.rb +8 -4
  13. data/lib/gamebox/behaviors/physical.rb +6 -1
  14. data/lib/gamebox/behaviors/positioned.rb +4 -11
  15. data/lib/gamebox/behaviors/projectile.rb +8 -0
  16. data/lib/gamebox/behaviors/visible.rb +3 -3
  17. data/lib/gamebox/core/aabb_tree.rb +1 -1
  18. data/lib/gamebox/core/actor.rb +37 -50
  19. data/lib/gamebox/core/actor_definition.rb +41 -0
  20. data/lib/gamebox/core/actor_view.rb +6 -21
  21. data/lib/gamebox/core/actor_view_definition.rb +19 -0
  22. data/lib/gamebox/core/actor_view_factory.rb +9 -3
  23. data/lib/gamebox/core/behavior.rb +8 -27
  24. data/lib/gamebox/core/behavior_definition.rb +24 -0
  25. data/lib/gamebox/core/config_manager.rb +45 -30
  26. data/lib/gamebox/core/configuration.rb +5 -0
  27. data/lib/gamebox/core/core.rb +4 -0
  28. data/lib/gamebox/core/debug_helpers.rb +46 -0
  29. data/lib/gamebox/core/director.rb +32 -5
  30. data/lib/gamebox/core/event_symbols.rb +214 -0
  31. data/lib/gamebox/core/game.rb +1 -1
  32. data/lib/gamebox/core/input_manager.rb +1 -4
  33. data/lib/gamebox/core/input_mapper.rb +85 -0
  34. data/lib/gamebox/core/physics.rb +7 -3
  35. data/lib/gamebox/core/physics_manager.rb +5 -1
  36. data/lib/gamebox/core/renderer.rb +72 -0
  37. data/lib/gamebox/core/stage.rb +25 -81
  38. data/lib/gamebox/core/stage_definition.rb +60 -0
  39. data/lib/gamebox/core/stage_factory.rb +56 -0
  40. data/lib/gamebox/core/stage_manager.rb +5 -11
  41. data/lib/gamebox/core/timer_manager.rb +6 -2
  42. data/lib/gamebox/core/viewport.rb +12 -5
  43. data/lib/gamebox/core/wrapped_screen.rb +8 -5
  44. data/lib/gamebox/gamebox_application.rb +21 -19
  45. data/lib/gamebox/lib/array_ext.rb +9 -0
  46. data/lib/gamebox/lib/observable_attributes.rb +24 -0
  47. data/lib/gamebox/lib/vector2.rb +432 -0
  48. data/lib/gamebox/post_setup_handlers/file_watcher.rb +37 -0
  49. data/lib/gamebox/post_setup_handlers/gamebox_debug_helpers.rb +13 -0
  50. data/lib/gamebox/post_setup_handlers/pry_remote_server.rb +29 -0
  51. data/lib/gamebox/spec/helper.rb +165 -17
  52. data/lib/gamebox/tasks/gamebox_tasks.rake +27 -12
  53. data/lib/gamebox/version.rb +1 -1
  54. data/lib/gamebox/views/graphical_actor_view.rb +4 -5
  55. data/script/perf_aabb.rb +13 -8
  56. data/spec/acceptance/animation_spec.rb +1 -3
  57. data/spec/acceptance/basic_actor_lifecycle_spec.rb +1 -1
  58. data/spec/acceptance/fps_actor_spec.rb +8 -12
  59. data/spec/acceptance/input_mapper_spec.rb +17 -24
  60. data/spec/acceptance/update_ordering_spec.rb +64 -0
  61. data/spec/actors/label_spec.rb +90 -5
  62. data/spec/behaviors/animated_spec.rb +1 -1
  63. data/spec/behaviors/collidable_spec.rb +7 -15
  64. data/spec/behaviors/positioned_spec.rb +12 -5
  65. data/spec/core/actor_spec.rb +31 -3
  66. data/spec/core/actor_view_spec.rb +1 -1
  67. data/spec/core/behavior_spec.rb +3 -0
  68. data/spec/core/configuration_spec.rb +49 -2
  69. data/spec/core/input_mapper_spec.rb +7 -0
  70. data/spec/core/renderer_spec.rb +89 -0
  71. data/spec/core/stage_definition_spec.rb +41 -0
  72. data/spec/core/stage_manager_spec.rb +11 -11
  73. data/spec/core/stage_spec.rb +38 -78
  74. data/spec/core/viewport_spec.rb +5 -2
  75. data/spec/core/wrapped_screen_spec.rb +18 -12
  76. data/spec/views/graphical_actor_view_spec.rb +33 -62
  77. data/templates/actor_template.erb +11 -0
  78. data/templates/app/README.md +1 -0
  79. data/templates/app/src/actors/{player.rb → player_actor.rb} +3 -1
  80. data/templates/app/src/behaviors/.gitkeep +0 -0
  81. data/templates/app/src/stages/demo_stage.rb +14 -0
  82. data/templates/behavior_template.erb +13 -0
  83. data/templates/stage_template.erb +13 -0
  84. metadata +60 -21
  85. data/component_generators/actor_generator.rb +0 -17
  86. data/lib/gamebox/actors/emitter.rb +0 -12
  87. data/lib/gamebox/behaviors/emitting.rb +0 -48
  88. data/lib/gamebox/behaviors/input_mapper.rb +0 -11
  89. data/lib/gamebox/lib/ftor.rb +0 -372
  90. data/spec/actors/emitter_spec.rb +0 -5
  91. data/templates/app/NEXT_STEPS.txt +0 -1
  92. data/templates/app/README.rdoc +0 -24
  93. data/templates/app/src/demo_stage.rb +0 -7
@@ -0,0 +1,41 @@
1
+ class ActorDefinition
2
+ attr_accessor :behaviors, :attributes, :view_blk, :behavior_blk, :source
3
+ def initialize
4
+ @behaviors = []
5
+ @attributes = []
6
+ end
7
+
8
+ def has_behaviors(*behaviors, &blk)
9
+ if block_given?
10
+ collector = MethodMissingCollector.new
11
+ collector.instance_eval &blk
12
+ collector.calls.each do |name, args|
13
+ if args.empty?
14
+ @behaviors << name
15
+ else
16
+ @behaviors << {name => args.first}
17
+ end
18
+ end
19
+ end
20
+ behaviors.each do |beh|
21
+ @behaviors << beh
22
+ end
23
+ end
24
+ alias has_behavior has_behaviors
25
+
26
+ def has_attributes(*attributes)
27
+ attributes.each do |att|
28
+ @attributes << att
29
+ end
30
+ end
31
+ alias has_attribute has_attributes
32
+
33
+ def view(&blk)
34
+ @view_blk = blk
35
+ end
36
+
37
+ def behavior(&blk)
38
+ @behavior_blk = blk
39
+ end
40
+ end
41
+
@@ -1,6 +1,7 @@
1
1
  class ActorView
2
- construct_with :stage, :wrapped_screen, :resource_manager, :actor
3
- public :stage, :wrapped_screen, :resource_manager, :actor
2
+ # TODO remove stage
3
+ construct_with :renderer, :wrapped_screen, :resource_manager, :actor, :stage
4
+ public :wrapped_screen, :resource_manager, :actor, :stage
4
5
 
5
6
  attr_accessor :layer, :parallax
6
7
  def initialize
@@ -15,11 +16,11 @@ class ActorView
15
16
  end
16
17
 
17
18
  def register
18
- stage.register_drawable self
19
+ renderer.register_drawable self
19
20
  end
20
21
 
21
22
  def unregister
22
- stage.unregister_drawable self
23
+ renderer.unregister_drawable self
23
24
  end
24
25
 
25
26
  def screen_width
@@ -34,6 +35,7 @@ class ActorView
34
35
  def define(actor_view_type, &blk)
35
36
  @definitions ||= {}
36
37
  definition = ActorViewDefinition.new
38
+ definition.source = caller.detect{|c|!c.match /core/}
37
39
  definition.instance_eval &blk if block_given?
38
40
  @definitions[actor_view_type] = definition
39
41
  end
@@ -43,21 +45,4 @@ class ActorView
43
45
  end
44
46
  end
45
47
 
46
- # TODO can these defs be unified?
47
- class ActorViewDefinition
48
- attr_accessor :draw_block, :configure_block, :required_injections
49
- def requires(*injections_needed)
50
- @required_injections = injections_needed
51
- end
52
-
53
- def configure(&configure_block)
54
- @configure_block = configure_block
55
- end
56
-
57
- def draw(&draw_block)
58
- @draw_block = draw_block
59
- end
60
- end
61
-
62
-
63
48
  end
@@ -0,0 +1,19 @@
1
+ class ActorViewDefinition
2
+ attr_accessor :draw_block, :setup_block, :required_injections, :helpers_block, :source
3
+ def requires(*injections_needed)
4
+ @required_injections = injections_needed
5
+ end
6
+
7
+ def setup(&setup_block)
8
+ @setup_block = setup_block
9
+ end
10
+
11
+ def draw(&draw_block)
12
+ @draw_block = draw_block
13
+ end
14
+
15
+ def helpers(&helper_block)
16
+ @helpers_block = helper_block
17
+ end
18
+ end
19
+
@@ -27,9 +27,15 @@ class ActorViewFactory
27
27
  end
28
28
 
29
29
  view.define_singleton_method :draw, &view_definition.draw_block if view_definition.draw_block
30
- if view_definition.configure_block
31
- view.define_singleton_method :configure, &view_definition.configure_block
32
- view.configure
30
+ if view_definition.setup_block
31
+ view.define_singleton_method :setup, &view_definition.setup_block
32
+ view.setup
33
+ end
34
+
35
+ helpers = view_definition.helpers_block
36
+ if helpers
37
+ helpers_module = Module.new &helpers
38
+ view.extend helpers_module
33
39
  end
34
40
 
35
41
  behavior_factory.add_behavior(actor, :visible, view: view)
@@ -13,13 +13,14 @@ class Behavior
13
13
  end
14
14
 
15
15
  def reacts_with(*messages_with_methods)
16
+ # TODO do a merge here..
16
17
  @message_handlers = messages_with_methods
17
18
  end
18
19
 
19
- def react_to(message_type, *opts)
20
+ def react_to(message_type, *opts, &blk)
20
21
  # TODO perf analysis, should I use a hash here?
21
22
  if @message_handlers && @message_handlers.include?(message_type)
22
- send message_type, *opts
23
+ send message_type, *opts, &blk
23
24
  end
24
25
  end
25
26
 
@@ -27,11 +28,16 @@ class Behavior
27
28
  behavior_factory.add_behavior actor, behavior_name, opts
28
29
  end
29
30
 
31
+ def remove_behavior(behavior_name)
32
+ actor.remove_behavior(behavior_name)
33
+ end
34
+
30
35
  class << self
31
36
 
32
37
  def define(behavior_type, &blk)
33
38
  @definitions ||= {}
34
39
  definition = BehaviorDefinition.new
40
+ definition.source = caller.detect{|c|!c.match /core/}
35
41
  definition.instance_eval &blk if block_given?
36
42
  @definitions[behavior_type] = definition
37
43
  end
@@ -40,29 +46,4 @@ class Behavior
40
46
  @definitions ||= {}
41
47
  end
42
48
  end
43
-
44
- class BehaviorDefinition
45
- attr_accessor :setup_block, :required_injections, :react_to_block, :required_behaviors,
46
- :helpers_block
47
-
48
- def requires(*injections_needed)
49
- @required_injections = injections_needed
50
- end
51
-
52
- def requires_behaviors(*behaviors_needed)
53
- @required_behaviors = behaviors_needed
54
- end
55
-
56
- def setup(&setup_block)
57
- @setup_block = setup_block
58
- end
59
-
60
- def react_to(&react_to_block)
61
- @react_to_block = react_to_block
62
- end
63
-
64
- def helpers(&helpers_block)
65
- @helpers_block = helpers_block
66
- end
67
- end
68
49
  end
@@ -0,0 +1,24 @@
1
+ class BehaviorDefinition
2
+ attr_accessor :setup_block, :required_injections, :react_to_block, :required_behaviors,
3
+ :helpers_block, :source
4
+
5
+ def requires(*injections_needed)
6
+ @required_injections = injections_needed
7
+ end
8
+
9
+ def requires_behaviors(*behaviors_needed)
10
+ @required_behaviors = behaviors_needed
11
+ end
12
+
13
+ def setup(&setup_block)
14
+ @setup_block = setup_block
15
+ end
16
+
17
+ def react_to(&react_to_block)
18
+ @react_to_block = react_to_block
19
+ end
20
+
21
+ def helpers(&helpers_block)
22
+ @helpers_block = helpers_block
23
+ end
24
+ end
@@ -1,42 +1,57 @@
1
1
  class ConfigManager
2
2
 
3
- attr_accessor :settings
4
- GAME_SETTINGS_FILE = "game"
3
+ def settings
4
+ @settings ||= base_configuration.merge(user_configuration)
5
+ end
5
6
 
6
- def initialize
7
- @settings = load_config(GAME_SETTINGS_FILE)
7
+ def [](key)
8
+ settings[key]
8
9
  end
9
10
 
10
- def save
11
- save_settings(GAME_SETTINGS_FILE, @settings)
11
+ def []=(key,val)
12
+ settings[key] = val
12
13
  end
13
14
 
14
- def [](key)
15
- @settings[key]
15
+
16
+ def game_settings_file
17
+ "game.yml"
16
18
  end
17
19
 
18
- def []=(key,val)
19
- @settings[key] = val
20
- end
21
-
22
- # TODO make this path include that app name?
23
- def load_config(name)
24
- conf = YAML::load_file("#{Gamebox.configuration.config_path}#{name}.yml")
25
- user_file = "#{ENV['HOME']}/.gamebox/#{name}.yml"
26
- if File.exist? user_file
27
- user_conf = YAML::load_file user_file
28
- conf = conf.merge user_conf
29
- end
30
- conf
31
- end
32
-
33
- def save_settings(name, settings)
34
- user_gamebox_dir = "#{ENV['HOME']}/.gamebox"
35
- FileUtils.mkdir_p user_gamebox_dir
36
- user_file = "#{ENV['HOME']}/.gamebox/#{name}.yml"
37
- File.open user_file, "w" do |f|
38
- f.write settings.to_yaml
39
- end
20
+ def user_configuration_directory
21
+ File.join(ENV['HOME'], ".gamebox")
22
+ end
23
+
24
+ def base_configuration_directory
25
+ Gamebox.configuration.config_path
26
+ end
27
+
28
+ def user_configuration_filepath
29
+ File.join(user_configuration_directory, game_settings_file)
30
+ end
31
+
32
+ def base_configuration_filepath
33
+ File.join(base_configuration_directory, game_settings_file)
34
+ end
35
+
36
+ def base_configuration
37
+ load base_configuration_filepath
38
+ end
39
+
40
+ def user_configuration
41
+ load user_configuration_filepath
42
+ end
43
+
44
+ def load(configuration_filepath)
45
+ File.exist?(configuration_filepath) ? YAML::load_file(configuration_filepath) : {}
46
+ end
47
+
48
+ def save
49
+ save_to_file(user_configuration_filepath,settings.to_yaml)
50
+ end
51
+
52
+ def save_to_file(filepath,settings)
53
+ FileUtils.mkdir_p File.dirname(filepath)
54
+ File.write(filepath,settings)
40
55
  end
41
56
 
42
57
  end
@@ -28,9 +28,14 @@ module Gamebox
28
28
  add_setting :gb_fonts_path
29
29
 
30
30
  add_setting :game_name, default: "Untitled Game"
31
+ add_setting :needs_cursor, default: false
31
32
 
32
33
  add_setting :stages, default: [:demo]
33
34
 
35
+ add_setting :default_font_size, default: 30
36
+ add_setting :default_font_name, default: "Asimov.ttf"
37
+ add_setting :default_font_color, default: [250,250,250,255]
38
+
34
39
  def settings
35
40
  @settings ||= {}
36
41
  end
@@ -9,6 +9,10 @@ module Gamebox
9
9
  yield configuration if block_given?
10
10
  end
11
11
 
12
+ def define_stage(name, &blk)
13
+ Stage.define name, &blk
14
+ end
15
+
12
16
  def define_behavior(name, &blk)
13
17
  Behavior.define name, &blk
14
18
  end
@@ -0,0 +1,46 @@
1
+ module DebugHelpers
2
+ def actors(type=nil)
3
+ matching_actors = []
4
+ ObjectSpace.each_object do |obj|
5
+ if obj.class == Actor
6
+ if type.nil? || obj.actor_type == type
7
+ matching_actors << obj
8
+ end
9
+ end
10
+ end
11
+ log "found #{matching_actors.size} actors"
12
+ matching_actors
13
+ end
14
+
15
+ def current_stage
16
+ game.stage_manager.current_stage
17
+ end
18
+
19
+ def reload_behavior(behavior_name)
20
+ behavior = behavior_name.to_sym
21
+ log "reloading behavior: [#{behavior}]"
22
+ load "behaviors/#{behavior}.rb"
23
+
24
+ actors.each do |act|
25
+
26
+ if act.has_behavior?(behavior)
27
+ behaviors = act.instance_variable_get('@behaviors')
28
+ beh_opts = behaviors[behavior].opts
29
+
30
+ factory = act.this_object_context[:behavior_factory]
31
+ act.remove_behavior behavior
32
+
33
+ factory.add_behavior(act, behavior, beh_opts)
34
+ end
35
+ end
36
+ end
37
+
38
+ def load_actor(actor_type)
39
+ type = actor_type.to_sym
40
+ log "loading actor: [#{type}]"
41
+ load "actors/#{type}.rb"
42
+ end
43
+
44
+ module_function :reload_behavior, :actors, :load_actor
45
+
46
+ end
@@ -1,12 +1,19 @@
1
1
  # Directors manage actors.
2
2
  class Director
3
- extend Publisher
4
- can_fire_anything
5
- attr_accessor :actors
3
+ attr_accessor :actors, :update_slots
4
+
5
+ def initialize
6
+ @update_slots = [ :pre_update, :update, :post_update ]
7
+ clear_subscriptions
8
+ end
9
+
10
+ def clear_subscriptions
11
+ @subscriptions = Hash[@update_slots.map { |slot| [slot, []] }]
12
+ end
6
13
 
7
14
  def pause
8
15
  @paused_subscriptions = @subscriptions
9
- @subscriptions = {}
16
+ clear_subscriptions
10
17
  end
11
18
 
12
19
  def unpause
@@ -16,8 +23,28 @@ class Director
16
23
  end
17
24
  end
18
25
 
26
+ def when(event=:update, &callback)
27
+ @subscriptions[event] ||= []
28
+ @subscriptions[event] << callback
29
+ end
30
+
19
31
  def update(time)
20
32
  time_in_seconds = time / 1000.to_f
21
- fire :update, time, time_in_seconds
33
+ @update_slots.each do |slot|
34
+ @subscriptions[slot].each do |callback|
35
+ callback.call time, time_in_seconds
36
+ end
37
+ end
22
38
  end
39
+
40
+ def unsubscribe_all(listener)
41
+ if @subscriptions
42
+ for slot in @subscriptions.keys
43
+ @subscriptions[slot].delete_if do |block|
44
+ eval('self',block.binding).equal?(listener)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
23
50
  end
@@ -0,0 +1,214 @@
1
+ KbRangeBegin = 0 unless defined?(KbRangeBegin)
2
+ KbRangeEnd = 0xffff unless defined?(KbRangeEnd)
3
+ MsRangeBegin = MsLeft unless defined?(MsRangeBegin)
4
+ MsRangeEnd = MsWheelDown unless defined?(MsRangeEnd)
5
+ GpRangeBegin = GpLeft unless defined?(GpRangeBegin)
6
+ GpRangeEnd = Gp3Button15 unless defined?(GpRangeEnd)
7
+
8
+ BUTTON_ID_TO_SYM = {
9
+ KbRangeBegin => :keyboard_begin,
10
+ KbEscape => :escape,
11
+ KbF1 => :f1,
12
+ KbF2 => :f2,
13
+ KbF3 => :f3,
14
+ KbF4 => :f4,
15
+ KbF5 => :f5,
16
+ KbF6 => :f6,
17
+ KbF7 => :f7,
18
+ KbF8 => :f8,
19
+ KbF9 => :f9,
20
+ KbF10 => :f10,
21
+ KbF11 => :f11,
22
+ KbF12 => :f12,
23
+ Kb1 => :one,
24
+ Kb2 => :two,
25
+ Kb3 => :three,
26
+ Kb4 => :four,
27
+ Kb5 => :five,
28
+ Kb6 => :six,
29
+ Kb7 => :seven,
30
+ Kb8 => :eight,
31
+ Kb9 => :nine,
32
+ Kb0 => :zero,
33
+ KbA => :a,
34
+ KbB => :b,
35
+ KbC => :c,
36
+ KbD => :d,
37
+ KbE => :e,
38
+ KbF => :f,
39
+ KbG => :g,
40
+ KbH => :h,
41
+ KbI => :i,
42
+ KbJ => :j,
43
+ KbK => :k,
44
+ KbL => :l,
45
+ KbM => :m,
46
+ KbN => :n,
47
+ KbO => :o,
48
+ KbP => :p,
49
+ KbQ => :q,
50
+ KbR => :r,
51
+ KbS => :s,
52
+ KbT => :t,
53
+ KbU => :u,
54
+ KbV => :v,
55
+ KbW => :w,
56
+ KbX => :x,
57
+ KbY => :y,
58
+ KbZ => :z,
59
+ KbTab => :tab,
60
+ KbReturn => :return,
61
+ KbSpace => :space,
62
+ KbLeftShift => :left_shift,
63
+ KbRightShift => :right_shift,
64
+ KbLeftControl => :left_control,
65
+ KbRightControl => :right_control,
66
+ KbLeftAlt => :left_alt,
67
+ KbRightAlt => :right_alt,
68
+ KbLeftMeta => :left_meta,
69
+ KbRightMeta => :right_meta,
70
+ KbBackspace => :backspace,
71
+ KbLeft => :left,
72
+ KbRight => :right,
73
+ KbUp => :up,
74
+ KbDown => :down,
75
+ KbHome => :home,
76
+ KbEnd => :end,
77
+ KbInsert => :insert,
78
+ KbDelete => :delete,
79
+ KbPageUp => :page_up,
80
+ KbPageDown => :page_down,
81
+ KbEnter => :enter,
82
+ KbNumpad1 => :numpad_1,
83
+ KbNumpad2 => :numpad_2,
84
+ KbNumpad3 => :numpad_3,
85
+ KbNumpad4 => :numpad_4,
86
+ KbNumpad5 => :numpad_5,
87
+ KbNumpad6 => :numpad_6,
88
+ KbNumpad7 => :numpad_7,
89
+ KbNumpad8 => :numpad_8,
90
+ KbNumpad9 => :numpad_9,
91
+ KbNumpad0 => :numpad_0,
92
+ KbNumpadAdd => :numpad_add,
93
+ KbNumpadSubtract => :numpad_subtract,
94
+ KbNumpadMultiply => :numpad_multiply,
95
+ KbNumpadDivide => :numpad_divide,
96
+ KbRangeEnd => :keyboard_end,
97
+ MsRangeBegin => :mouse_begin,
98
+ MsLeft => :mouse_left,
99
+ MsRight => :mouse_right,
100
+ MsMiddle => :mouse_middle,
101
+ MsWheelUp => :mouse_wheel_up,
102
+ MsWheelDown => :mouse_wheel_down,
103
+ MsRangeEnd => :mouse_end,
104
+ GpRangeBegin => :gp_begin,
105
+ GpLeft => :gp_left,
106
+ GpRight => :gp_right,
107
+ GpUp => :gp_up,
108
+ GpDown => :gp_down,
109
+ GpButton0 => :gp_button_0,
110
+ GpButton1 => :gp_button_1,
111
+ GpButton2 => :gp_button_2,
112
+ GpButton3 => :gp_button_3,
113
+ GpButton4 => :gp_button_4,
114
+ GpButton5 => :gp_button_5,
115
+ GpButton6 => :gp_button_6,
116
+ GpButton7 => :gp_button_7,
117
+ GpButton8 => :gp_button_8,
118
+ GpButton9 => :gp_button_9,
119
+ GpButton10 => :gp_button_10,
120
+ GpButton11 => :gp_button_11,
121
+ GpButton12 => :gp_button_12,
122
+ GpButton13 => :gp_button_13,
123
+ GpButton14 => :gp_button_14,
124
+ GpButton15 => :gp_button_15,
125
+ GpRangeEnd => :gp_end,
126
+ }
127
+
128
+ BUTTON_ID_TO_SYM.merge!({
129
+ Gp0Left => :gp0_left,
130
+ Gp0Right => :gp0_right,
131
+ Gp0Up => :gp0_up,
132
+ Gp0Down => :gp0_down,
133
+ Gp0Button0 => :gp0_button_0,
134
+ Gp0Button1 => :gp0_button_1,
135
+ Gp0Button2 => :gp0_button_2,
136
+ Gp0Button3 => :gp0_button_3,
137
+ Gp0Button4 => :gp0_button_4,
138
+ Gp0Button5 => :gp0_button_5,
139
+ Gp0Button6 => :gp0_button_6,
140
+ Gp0Button7 => :gp0_button_7,
141
+ Gp0Button8 => :gp0_button_8,
142
+ Gp0Button9 => :gp0_button_9,
143
+ Gp0Button10 => :gp0_button_10,
144
+ Gp0Button11 => :gp0_button_11,
145
+ Gp0Button12 => :gp0_button_12,
146
+ Gp0Button13 => :gp0_button_13,
147
+ Gp0Button14 => :gp0_button_14,
148
+ Gp0Button15 => :gp0_button_15,
149
+
150
+ Gp1Left => :gp1_left,
151
+ Gp1Right => :gp1_right,
152
+ Gp1Up => :gp1_up,
153
+ Gp1Down => :gp1_down,
154
+ Gp1Button0 => :gp1_button_0,
155
+ Gp1Button1 => :gp1_button_1,
156
+ Gp1Button2 => :gp1_button_2,
157
+ Gp1Button3 => :gp1_button_3,
158
+ Gp1Button4 => :gp1_button_4,
159
+ Gp1Button5 => :gp1_button_5,
160
+ Gp1Button6 => :gp1_button_6,
161
+ Gp1Button7 => :gp1_button_7,
162
+ Gp1Button8 => :gp1_button_8,
163
+ Gp1Button9 => :gp1_button_9,
164
+ Gp1Button10 => :gp1_button_10,
165
+ Gp1Button11 => :gp1_button_11,
166
+ Gp1Button12 => :gp1_button_12,
167
+ Gp1Button13 => :gp1_button_13,
168
+ Gp1Button14 => :gp1_button_14,
169
+ Gp1Button15 => :gp1_button_15,
170
+
171
+ Gp2Left => :gp2_left,
172
+ Gp2Right => :gp2_right,
173
+ Gp2Up => :gp2_up,
174
+ Gp2Down => :gp2_down,
175
+ Gp2Button0 => :gp2_button_0,
176
+ Gp2Button1 => :gp2_button_1,
177
+ Gp2Button2 => :gp2_button_2,
178
+ Gp2Button3 => :gp2_button_3,
179
+ Gp2Button4 => :gp2_button_4,
180
+ Gp2Button5 => :gp2_button_5,
181
+ Gp2Button6 => :gp2_button_6,
182
+ Gp2Button7 => :gp2_button_7,
183
+ Gp2Button8 => :gp2_button_8,
184
+ Gp2Button9 => :gp2_button_9,
185
+ Gp2Button10 => :gp2_button_10,
186
+ Gp2Button11 => :gp2_button_11,
187
+ Gp2Button12 => :gp2_button_12,
188
+ Gp2Button13 => :gp2_button_13,
189
+ Gp2Button14 => :gp2_button_14,
190
+ Gp2Button15 => :gp2_button_15,
191
+
192
+ Gp3Left => :gp3_left,
193
+ Gp3Right => :gp3_right,
194
+ Gp3Up => :gp3_up,
195
+ Gp3Down => :gp3_down,
196
+ Gp3Button0 => :gp3_button_0,
197
+ Gp3Button1 => :gp3_button_1,
198
+ Gp3Button2 => :gp3_button_2,
199
+ Gp3Button3 => :gp3_button_3,
200
+ Gp3Button4 => :gp3_button_4,
201
+ Gp3Button5 => :gp3_button_5,
202
+ Gp3Button6 => :gp3_button_6,
203
+ Gp3Button7 => :gp3_button_7,
204
+ Gp3Button8 => :gp3_button_8,
205
+ Gp3Button9 => :gp3_button_9,
206
+ Gp3Button10 => :gp3_button_10,
207
+ Gp3Button11 => :gp3_button_11,
208
+ Gp3Button12 => :gp3_button_12,
209
+ Gp3Button13 => :gp3_button_13,
210
+ Gp3Button14 => :gp3_button_14,
211
+ Gp3Button15 => :gp3_button_15,
212
+ }) if defined?(Gp0Left) # if multi gp support
213
+
214
+ BUTTON_SYM_TO_ID = BUTTON_ID_TO_SYM.invert