metro-ld26 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +14 -0
- data/Guardfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +177 -0
- data/Rakefile +18 -0
- data/bin/metro +16 -0
- data/changelog.md +153 -0
- data/lib/assets/menu-movement.wav +0 -0
- data/lib/assets/menu-selection.wav +0 -0
- data/lib/assets/missing.ogg +0 -0
- data/lib/assets/missing.png +0 -0
- data/lib/assets/missing.wav +0 -0
- data/lib/assets/missing_animation.png +0 -0
- data/lib/commands/generate_game.rb +13 -0
- data/lib/commands/generate_model.rb +25 -0
- data/lib/commands/generate_scene.rb +36 -0
- data/lib/commands/generate_view.rb +21 -0
- data/lib/commands/thor.rb +83 -0
- data/lib/core_ext/class.rb +14 -0
- data/lib/core_ext/numeric.rb +59 -0
- data/lib/gosu_ext/color.rb +62 -0
- data/lib/gosu_ext/gosu_constants.rb +53 -0
- data/lib/locale/en.yml +35 -0
- data/lib/locale/locale.rb +1 -0
- data/lib/metro.rb +144 -0
- data/lib/metro/animation.rb +135 -0
- data/lib/metro/animation/after_interval_factory.rb +12 -0
- data/lib/metro/animation/animation_factory.rb +15 -0
- data/lib/metro/animation/easing/ease_in.rb +15 -0
- data/lib/metro/animation/easing/easing.rb +51 -0
- data/lib/metro/animation/easing/linear.rb +15 -0
- data/lib/metro/animation/has_animations.rb +70 -0
- data/lib/metro/animation/implicit_animation.rb +100 -0
- data/lib/metro/animation/on_update_operation.rb +96 -0
- data/lib/metro/animation/scene_animation.rb +16 -0
- data/lib/metro/asset_path.rb +97 -0
- data/lib/metro/events/control_definition.rb +11 -0
- data/lib/metro/events/controls.rb +42 -0
- data/lib/metro/events/event_data.rb +60 -0
- data/lib/metro/events/event_dictionary.rb +52 -0
- data/lib/metro/events/event_factory.rb +17 -0
- data/lib/metro/events/event_relay.rb +342 -0
- data/lib/metro/events/event_state_manager.rb +70 -0
- data/lib/metro/events/events.rb +3 -0
- data/lib/metro/events/has_events.rb +108 -0
- data/lib/metro/events/hit_list.rb +75 -0
- data/lib/metro/events/unknown_sender.rb +5 -0
- data/lib/metro/font.rb +69 -0
- data/lib/metro/game.rb +102 -0
- data/lib/metro/game/dsl.rb +68 -0
- data/lib/metro/image.rb +75 -0
- data/lib/metro/logging.rb +33 -0
- data/lib/metro/missing_scene.rb +21 -0
- data/lib/metro/models/audio/song.rb +33 -0
- data/lib/metro/models/draws.rb +86 -0
- data/lib/metro/models/key_value_coding.rb +38 -0
- data/lib/metro/models/model.rb +246 -0
- data/lib/metro/models/model_factory.rb +32 -0
- data/lib/metro/models/models.rb +62 -0
- data/lib/metro/models/properties/animation_property.rb +115 -0
- data/lib/metro/models/properties/array_property.rb +24 -0
- data/lib/metro/models/properties/boolean_property.rb +27 -0
- data/lib/metro/models/properties/color_property.rb +116 -0
- data/lib/metro/models/properties/dimensions_property.rb +84 -0
- data/lib/metro/models/properties/font_property.rb +130 -0
- data/lib/metro/models/properties/image_property.rb +96 -0
- data/lib/metro/models/properties/model_property.rb +84 -0
- data/lib/metro/models/properties/numeric_property.rb +29 -0
- data/lib/metro/models/properties/options_property/no_option.rb +29 -0
- data/lib/metro/models/properties/options_property/options.rb +98 -0
- data/lib/metro/models/properties/options_property/options_property.rb +125 -0
- data/lib/metro/models/properties/position_property.rb +90 -0
- data/lib/metro/models/properties/property.rb +221 -0
- data/lib/metro/models/properties/property_owner.rb +137 -0
- data/lib/metro/models/properties/sample_property.rb +84 -0
- data/lib/metro/models/properties/scale_property.rb +80 -0
- data/lib/metro/models/properties/song_property.rb +89 -0
- data/lib/metro/models/properties/text_property.rb +75 -0
- data/lib/metro/models/ui/animated_sprite.rb +85 -0
- data/lib/metro/models/ui/border.rb +95 -0
- data/lib/metro/models/ui/fps.rb +54 -0
- data/lib/metro/models/ui/generic.rb +66 -0
- data/lib/metro/models/ui/grid_drawer.rb +74 -0
- data/lib/metro/models/ui/image.rb +87 -0
- data/lib/metro/models/ui/label.rb +175 -0
- data/lib/metro/models/ui/menu.rb +214 -0
- data/lib/metro/models/ui/model_label.rb +65 -0
- data/lib/metro/models/ui/model_labeler.rb +79 -0
- data/lib/metro/models/ui/rectangle.rb +59 -0
- data/lib/metro/models/ui/sprite.rb +79 -0
- data/lib/metro/models/ui/tile_map.rb +132 -0
- data/lib/metro/models/ui/tmx/isometric_position.rb +43 -0
- data/lib/metro/models/ui/tmx/orthogonal_position.rb +15 -0
- data/lib/metro/models/ui/tmx/tile_layer.rb +78 -0
- data/lib/metro/models/ui/ui.rb +13 -0
- data/lib/metro/parameters/command_line_args_parser.rb +68 -0
- data/lib/metro/parameters/options.rb +25 -0
- data/lib/metro/parameters/parameters.rb +2 -0
- data/lib/metro/sample.rb +40 -0
- data/lib/metro/scene.rb +478 -0
- data/lib/metro/scenes.rb +154 -0
- data/lib/metro/song.rb +56 -0
- data/lib/metro/template_message.rb +60 -0
- data/lib/metro/transitions/edit_transition_scene.rb +100 -0
- data/lib/metro/transitions/fade_transition_scene.rb +66 -0
- data/lib/metro/transitions/scene_transitions.rb +44 -0
- data/lib/metro/transitions/transition_scene.rb +19 -0
- data/lib/metro/units/bounds.rb +8 -0
- data/lib/metro/units/calculation_validations.rb +74 -0
- data/lib/metro/units/dimensions.rb +60 -0
- data/lib/metro/units/point.rb +51 -0
- data/lib/metro/units/rectangle_bounds.rb +148 -0
- data/lib/metro/units/scale.rb +46 -0
- data/lib/metro/units/units.rb +6 -0
- data/lib/metro/version.rb +32 -0
- data/lib/metro/views/json_view.rb +60 -0
- data/lib/metro/views/no_view.rb +34 -0
- data/lib/metro/views/parsers.rb +42 -0
- data/lib/metro/views/scene_view.rb +107 -0
- data/lib/metro/views/view.rb +133 -0
- data/lib/metro/views/writers.rb +43 -0
- data/lib/metro/views/yaml_view.rb +94 -0
- data/lib/metro/window.rb +95 -0
- data/lib/setup_handlers/exit_if_dry_run.rb +26 -0
- data/lib/setup_handlers/game_execution.rb +65 -0
- data/lib/setup_handlers/load_game_configuration.rb +65 -0
- data/lib/setup_handlers/load_game_files.rb +101 -0
- data/lib/setup_handlers/move_to_game_directory.rb +25 -0
- data/lib/setup_handlers/reload_game_on_game_file_changes.rb +79 -0
- data/lib/templates/game/README.md.tt +43 -0
- data/lib/templates/game/assets/brand.jpg +0 -0
- data/lib/templates/game/assets/hero.png +0 -0
- data/lib/templates/game/lib/custom_easing.rb +32 -0
- data/lib/templates/game/metro.tt +63 -0
- data/lib/templates/game/models/hero.rb +62 -0
- data/lib/templates/game/scenes/brand_scene.rb +19 -0
- data/lib/templates/game/scenes/brand_to_title_scene.rb +13 -0
- data/lib/templates/game/scenes/first_scene.rb +28 -0
- data/lib/templates/game/scenes/game_scene.rb +43 -0
- data/lib/templates/game/scenes/title_scene.rb +15 -0
- data/lib/templates/game/views/brand.yaml +4 -0
- data/lib/templates/game/views/brand_to_title.yaml +8 -0
- data/lib/templates/game/views/first.yaml +26 -0
- data/lib/templates/game/views/title.yaml +11 -0
- data/lib/templates/message.erb +23 -0
- data/lib/templates/model.rb.tt +111 -0
- data/lib/templates/scene.rb.tt +140 -0
- data/lib/templates/view.yaml.tt +11 -0
- data/lib/tmx_ext/object.rb +26 -0
- data/lib/tmx_ext/tile_set.rb +41 -0
- data/metro.gemspec +57 -0
- data/metro.png +0 -0
- data/spec/core_ext/numeric_spec.rb +78 -0
- data/spec/core_ext/string_spec.rb +33 -0
- data/spec/gosu_ext/color_spec.rb +80 -0
- data/spec/metro/image_spec.rb +33 -0
- data/spec/metro/models/key_value_coding_spec.rb +61 -0
- data/spec/metro/models/properties/array_property_spec.rb +60 -0
- data/spec/metro/models/properties/color_property_spec.rb +85 -0
- data/spec/metro/models/properties/dimensions_spec.rb +29 -0
- data/spec/metro/models/properties/font_property_spec.rb +127 -0
- data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
- data/spec/metro/models/properties/options_property/no_option_spec.rb +25 -0
- data/spec/metro/models/properties/options_property/options_property_spec.rb +133 -0
- data/spec/metro/models/properties/options_property/options_spec.rb +125 -0
- data/spec/metro/models/properties/position_property_spec.rb +90 -0
- data/spec/metro/models/ui/label_spec.rb +259 -0
- data/spec/metro/parameters/command_line_args_parser_spec.rb +42 -0
- data/spec/metro/scene_spec.rb +15 -0
- data/spec/metro/scene_views/json_view_spec.rb +27 -0
- data/spec/metro/scene_views/yaml_view_spec.rb +38 -0
- data/spec/metro/scenes_spec.rb +77 -0
- data/spec/metro/units/point_spec.rb +132 -0
- data/spec/metro/units/rectangle_bounds_spec.rb +56 -0
- data/spec/metro/views/view_spec.rb +53 -0
- data/spec/setup_handlers/exit_if_dry_run_spec.rb +27 -0
- data/spec/setup_handlers/reload_game_on_game_file_changes_spec.rb +68 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/tmx_ext/object_spec.rb +96 -0
- data/spec/tmx_ext/tile_set_spec.rb +24 -0
- metadata +379 -0
@@ -0,0 +1,130 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
#
|
5
|
+
# A font property maintains a Gosu::Font.
|
6
|
+
#
|
7
|
+
# A font property also defines a `font_size` property and a `font_name` property which allows a
|
8
|
+
# more direct interface. Changing these values will update the font the next time that it is drawn.
|
9
|
+
#
|
10
|
+
# A font is stored in the properties as a hash representation and is converted into
|
11
|
+
# a Gosu::Font when it is retrieved within the system. When retrieving a font the Font
|
12
|
+
# Property will attempt to use a font that already exists that meets that criteria.
|
13
|
+
#
|
14
|
+
# The fonts are cached within the font property to help performance by reducing the unncessary
|
15
|
+
# creation of similar fonts.
|
16
|
+
#
|
17
|
+
# @example Defining a font property
|
18
|
+
#
|
19
|
+
# class Scoreboard < Metro::Model
|
20
|
+
# property :font
|
21
|
+
#
|
22
|
+
# def draw
|
23
|
+
# font.draw text, x, y, z_order, x_factor, y_factor, color
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @example Defining a font property providing a default
|
29
|
+
#
|
30
|
+
# class Hero < Metro::Model
|
31
|
+
# property :font, default: { name: 'Comic Sans', size: 80 }
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# @example Using the `font_size` and `font_name` properties
|
35
|
+
#
|
36
|
+
# class Hero < Metro::Model
|
37
|
+
# property :font, default: { name: 'Comic Sans', size: 80 }
|
38
|
+
# property :color, default: "rgba(255,0,0,1.0)"
|
39
|
+
#
|
40
|
+
# def dignified
|
41
|
+
# self.font_size = 45
|
42
|
+
# self.font_name = 'Helvetica'
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# @example Using a font property with a different property name
|
47
|
+
#
|
48
|
+
# class Hero < Metro::Model
|
49
|
+
# property :alt_font, type: :font, default: { name: 'Helvetica', size: 80 }
|
50
|
+
#
|
51
|
+
# def draw
|
52
|
+
# puts "Font: #{alt_font_name}:#{alt_font_size}"
|
53
|
+
# alt_font.draw text, x, y, z_order, x_factor, y_factor, color
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
class FontProperty < Property
|
58
|
+
|
59
|
+
# Define a paired property which allows the setting of the font size
|
60
|
+
define_property :size, prefix: true
|
61
|
+
# Define a paired property which allows the setting of the font name
|
62
|
+
define_property :name, type: :text, prefix: true
|
63
|
+
|
64
|
+
# Return the default font when the value is not supported.
|
65
|
+
get do
|
66
|
+
default_font
|
67
|
+
end
|
68
|
+
|
69
|
+
# Create a font from the specified hash of data.
|
70
|
+
#
|
71
|
+
# @example Format of Hash
|
72
|
+
#
|
73
|
+
# { name: 'Times New Roman', size: 33 }
|
74
|
+
#
|
75
|
+
get Hash do |value|
|
76
|
+
self.class.font_for value.merge(window: model.window)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Save a hash of the default font when the value is not supported.
|
80
|
+
set do
|
81
|
+
{ name: default_font_name, size: default_font_size }
|
82
|
+
end
|
83
|
+
|
84
|
+
# Save a hash representation of the font when given a font
|
85
|
+
set Metro::Font do |font|
|
86
|
+
{ name: font.name, size: font.height }
|
87
|
+
end
|
88
|
+
|
89
|
+
# Save the hash provided. It is assumed to contain the correct font data.
|
90
|
+
set Hash, HashWithIndifferentAccess do |hash|
|
91
|
+
hash.to_hash
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# @return the default font to use when a value has not been provided.
|
96
|
+
#
|
97
|
+
def default_font
|
98
|
+
self.class.font_for name: default_font_name,
|
99
|
+
size: default_font_size,
|
100
|
+
window: model.window
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Use the specified default font size or fall back to 40.
|
105
|
+
#
|
106
|
+
def default_font_size
|
107
|
+
(options[:default] and options[:default][:size]) ? options[:default][:size] : 40
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Use the specified default font name or fall back to Gosu's default font name.
|
112
|
+
#
|
113
|
+
def default_font_name
|
114
|
+
(options[:default] and options[:default][:name]) ? options[:default][:name] : Gosu::default_font_name
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Return a font that matches the specified criteria. Usig the name, size, and window a font will be
|
119
|
+
# generated or retrieved from the cache.
|
120
|
+
#
|
121
|
+
# @param [Hash] value the hash that contains the `name`, `size` and `window` that describe the font.
|
122
|
+
#
|
123
|
+
def self.font_for(value)
|
124
|
+
Font.find_or_create(value)
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
#
|
5
|
+
# A image property maintains a Gosu::Image.
|
6
|
+
#
|
7
|
+
# An image is stored in the properties as a string to the specified image path and is converted into
|
8
|
+
# a Gosu::Image when it is retrieved within the system. When retrieving an image the Image
|
9
|
+
# Property will attempt to use a image at that path that already meets that criteria if it has been
|
10
|
+
# loaded.
|
11
|
+
#
|
12
|
+
# @example Defining a image property
|
13
|
+
#
|
14
|
+
# class Player < Metro::Model
|
15
|
+
# property :image
|
16
|
+
#
|
17
|
+
# def draw
|
18
|
+
# image.draw x, y, z_order, x_factor, y_factor, color, :add)
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# @example Defining an image property providing a path
|
24
|
+
#
|
25
|
+
# class Player < Metro::Model
|
26
|
+
# property :image, path: "player.png"
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# @example Using an image property with a different property name
|
30
|
+
#
|
31
|
+
# class Player < Metro::Model
|
32
|
+
# property :disconnected_image, type: :image, path: "disconnected_player.png"
|
33
|
+
#
|
34
|
+
# def draw
|
35
|
+
# disconnected_image.draw x, y, z_order, x_factor, y_factor, color, :add)
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
class ImageProperty < Property
|
40
|
+
|
41
|
+
# By default, getting will use the the default image.
|
42
|
+
get do
|
43
|
+
default_image
|
44
|
+
end
|
45
|
+
|
46
|
+
# Return the image at the specified path.
|
47
|
+
get String do |path|
|
48
|
+
self.class.image_for path: path, window: model.window
|
49
|
+
end
|
50
|
+
|
51
|
+
# By default, setting will use the path of the default image.
|
52
|
+
set do
|
53
|
+
default_image.path
|
54
|
+
end
|
55
|
+
|
56
|
+
# Set the image with the specified path.
|
57
|
+
set String do |path|
|
58
|
+
path
|
59
|
+
end
|
60
|
+
|
61
|
+
# Set the image with the given image. A Gosu::Image does not normally
|
62
|
+
# store it's path, however, this functionality has been monkey-patched.
|
63
|
+
set Metro::Image do |image|
|
64
|
+
image.path
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# @return the default image based on the default image path specified.
|
69
|
+
#
|
70
|
+
def default_image
|
71
|
+
self.class.image_for path: default_image_path, window: model.window
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# @return the path provided as the default or if one has not been specified
|
76
|
+
# the default "missing.png"
|
77
|
+
#
|
78
|
+
def default_image_path
|
79
|
+
options[:path] or "missing.png"
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Return an image for the specified path. On first request it will be loaded from
|
84
|
+
# the file-system. On subsequent requests it will be pulled from the cache.
|
85
|
+
#
|
86
|
+
# @param [Hash] options the relative `path` to the image and the window for which it
|
87
|
+
# will be displayed.
|
88
|
+
#
|
89
|
+
def self.image_for(options)
|
90
|
+
Metro::Image.find_or_create(options)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
#
|
5
|
+
# A model property maintains a reference to another model. This property
|
6
|
+
# allows for an existing model to be more easily composed with other models.
|
7
|
+
#
|
8
|
+
# The model is stored as a hash which describes the model.
|
9
|
+
#
|
10
|
+
# @example Defining a model property with a block
|
11
|
+
#
|
12
|
+
# class ScoreBoard < Metro::Model
|
13
|
+
# property :position
|
14
|
+
# property :score
|
15
|
+
# property :label, type: :model do
|
16
|
+
# create "metro::ui::label", text: "", position: position
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @example Defining a model property with a hash
|
21
|
+
#
|
22
|
+
# class ScoreBoard < Metro::Model
|
23
|
+
# property :position
|
24
|
+
# property :score
|
25
|
+
# property :label, type: :model, default: { model: "metro::ui::label",
|
26
|
+
# text: "", position: position }
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
class ModelProperty < Property
|
31
|
+
|
32
|
+
# When retrieving a model and the type is unsupported generate the
|
33
|
+
# model instance from the default.
|
34
|
+
get do
|
35
|
+
default_model
|
36
|
+
end
|
37
|
+
|
38
|
+
# When retrieving a hash representation of the model, convert it into
|
39
|
+
# a Metro::Model instance.
|
40
|
+
get Hash do |params|
|
41
|
+
create_model params
|
42
|
+
end
|
43
|
+
|
44
|
+
# When setting the property with an unsupported type, simply save an
|
45
|
+
# empty hash. Which later, if retrieved, it will generate a generic
|
46
|
+
# model.
|
47
|
+
set do
|
48
|
+
{}
|
49
|
+
end
|
50
|
+
|
51
|
+
# When setting the property with a hash, assume that the hash is a
|
52
|
+
# valid description of a Metro::Model.
|
53
|
+
set Hash, HashWithIndifferentAccess do |hash|
|
54
|
+
hash
|
55
|
+
end
|
56
|
+
|
57
|
+
# When setting the property with a Metro::Model, convert the model into
|
58
|
+
# a hash.
|
59
|
+
set Metro::Model do |model|
|
60
|
+
model.to_hash
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# Allow for a model property to be defined with a block initialization or
|
65
|
+
# a default hash.
|
66
|
+
#
|
67
|
+
def default_model
|
68
|
+
if block
|
69
|
+
model.instance_eval(&block)
|
70
|
+
else
|
71
|
+
create_model options[:default]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Metro::Model] return a model created by the current model that
|
76
|
+
# owns the property.
|
77
|
+
def create_model
|
78
|
+
model.create params[:model], params.except(:model)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
#
|
5
|
+
# The numeric property will simply convert any input into a floating
|
6
|
+
# point value. This is the same both on getting and setting.
|
7
|
+
#
|
8
|
+
class NumericProperty < Property
|
9
|
+
|
10
|
+
# For all cases the value is converted to floating point when it can
|
11
|
+
# otherwise the default number is used.
|
12
|
+
get_or_set do |value|
|
13
|
+
if value.is_a?(NilClass)
|
14
|
+
default_number
|
15
|
+
elsif value.respond_to?(:to_f)
|
16
|
+
value.to_f
|
17
|
+
else
|
18
|
+
default_number
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_number
|
23
|
+
options[:default].to_f
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
class OptionsProperty
|
4
|
+
|
5
|
+
#
|
6
|
+
# When the options cannot find a selected menu option then this no option
|
7
|
+
# is returned instead of a nil value. This allows for a warning to be generated
|
8
|
+
# if any methods target this item.
|
9
|
+
#
|
10
|
+
# Also if the option will send a 'missing_menu_action' if the options were to
|
11
|
+
# ask for the selected action.
|
12
|
+
#
|
13
|
+
class NoOption
|
14
|
+
def method_missing(name,*args,&block)
|
15
|
+
log.warn warning_message
|
16
|
+
end
|
17
|
+
|
18
|
+
def warning_message
|
19
|
+
"No valid options were found in the menu"
|
20
|
+
end
|
21
|
+
|
22
|
+
def properties
|
23
|
+
{ action: :missing_menu_action }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
class OptionsProperty
|
4
|
+
|
5
|
+
#
|
6
|
+
# Options maintains the list of menu options that would be displayed in a menu.
|
7
|
+
# Each option is a component that can be rendered during the draw phase.
|
8
|
+
#
|
9
|
+
# Also, options maintains the currently selected item and has the ability to manage
|
10
|
+
# the changes from the previous.
|
11
|
+
#
|
12
|
+
class Options < SimpleDelegator
|
13
|
+
|
14
|
+
#
|
15
|
+
# Generate an empty set of options.
|
16
|
+
#
|
17
|
+
def self.empty
|
18
|
+
new []
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Create options with the provided array of options.
|
23
|
+
#
|
24
|
+
# @param [Array] options the array of options that this object will maintain
|
25
|
+
# as it's list of options.
|
26
|
+
#
|
27
|
+
def initialize(options)
|
28
|
+
super(options)
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# @return [Fixnum] the index of the current selected option.
|
33
|
+
#
|
34
|
+
def current_selected_index
|
35
|
+
@current_selected_index ||= 0
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Set the index of the currently selected item. Values that exceed the possible
|
40
|
+
# count of options will reset to the beginning of the list of options.
|
41
|
+
# Values that proceed the start of of the list of options will fallback to the last option.
|
42
|
+
#
|
43
|
+
# @param [Fixnum,Object] value is the integer position within the menu
|
44
|
+
# to select or the item in the options to select.
|
45
|
+
#
|
46
|
+
def current_selected_index=(value)
|
47
|
+
value = index(value) unless value.is_a?(Fixnum)
|
48
|
+
@current_selected_index = value || 0
|
49
|
+
@current_selected_index = 0 if @current_selected_index >= count
|
50
|
+
@current_selected_index = count - 1 if @current_selected_index <= -1
|
51
|
+
@current_selected_index
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# @return [Array] a list of all the options that are currently not selected.
|
56
|
+
#
|
57
|
+
def unselected
|
58
|
+
self - [ selected ]
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# @return [Object] the currently selected option.
|
63
|
+
#
|
64
|
+
def selected
|
65
|
+
at(current_selected_index) || NoOption.new
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# @return [Symbol] the action name of the currently selected option. If no
|
70
|
+
# option is currently selected then the NoOption 'missing_menu_action' will be
|
71
|
+
# returned.
|
72
|
+
#
|
73
|
+
def selected_action
|
74
|
+
if selected.respond_to?(:properties) && selected.properties[:action]
|
75
|
+
selected.properties[:action]
|
76
|
+
else
|
77
|
+
selected.to_sym
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Move the current selected item to the next item
|
83
|
+
#
|
84
|
+
def next!
|
85
|
+
self.current_selected_index += 1
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Move the current selected item to the previous item
|
90
|
+
#
|
91
|
+
def previous!
|
92
|
+
self.current_selected_index -= 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|