metro 0.2.1 → 0.2.2
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/README.md +2 -0
- data/changelog.md +10 -0
- data/lib/assets/missing.mp3 +0 -0
- data/lib/assets/missing.wav +0 -0
- data/lib/gosu_ext/image.rb +4 -0
- data/lib/gosu_ext/sample.rb +18 -0
- data/lib/gosu_ext/song.rb +18 -0
- data/lib/metro.rb +2 -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 +17 -0
- data/lib/metro/animation/implicit_animation.rb +5 -24
- data/lib/metro/models/draws.rb +10 -1
- data/lib/metro/models/model.rb +117 -89
- data/lib/metro/models/models/image.rb +8 -9
- data/lib/metro/models/models/label.rb +4 -8
- data/lib/metro/models/models/menu.rb +7 -9
- data/lib/metro/models/models/rectangle.rb +7 -12
- data/lib/metro/models/models/song.rb +33 -0
- data/lib/metro/models/properties/dimensions_property.rb +18 -1
- data/lib/metro/models/properties/image_property.rb +2 -2
- data/lib/metro/models/properties/position_property.rb +6 -0
- data/lib/metro/models/properties/property.rb +129 -23
- data/lib/metro/models/properties/sample_property.rb +97 -0
- data/lib/metro/models/properties/song_property.rb +113 -0
- data/lib/metro/scene.rb +2 -11
- data/lib/metro/scenes.rb +14 -7
- data/lib/metro/transitions/fade_transition_scene.rb +8 -1
- data/lib/metro/units/bounds.rb +8 -0
- data/lib/metro/units/dimensions.rb +23 -5
- data/lib/metro/units/point.rb +26 -1
- data/lib/metro/units/rectangle_bounds.rb +52 -0
- data/lib/metro/units/scale.rb +16 -0
- data/lib/metro/units/units.rb +3 -1
- data/lib/metro/version.rb +1 -1
- data/lib/metro/window.rb +7 -0
- data/lib/templates/game/README.md.tt +20 -1
- data/spec/metro/models/models/label_spec.rb +4 -4
- data/spec/metro/models/properties/dimensions_spec.rb +29 -0
- data/spec/metro/models/properties/position_property_spec.rb +5 -5
- data/spec/spec_helper.rb +3 -1
- metadata +22 -9
- data/lib/metro/animation/easing.rb +0 -31
- data/lib/metro/models/rectangle_bounds.rb +0 -28
data/README.md
CHANGED
@@ -12,6 +12,8 @@ Metro is a framework built around [gosu](https://github.com/jlnr/gosu) (the 2D g
|
|
12
12
|
|
13
13
|
> NOTE: This project is very early in development and at this point mostly a prototype to explore more of theses concepts to gain an understanding of core tools necessary to make games.
|
14
14
|
|
15
|
+
[](https://codeclimate.com/github/burtlo/metro)
|
16
|
+
|
15
17
|
## Installation
|
16
18
|
|
17
19
|
$ gem install metro
|
data/changelog.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Metro
|
2
2
|
|
3
|
+
## 0.2.2 / 2012-11-10
|
4
|
+
|
5
|
+
* Song support added (scene methods and model properties)
|
6
|
+
* Sample support added (model properties)
|
7
|
+
* Added a missing sample/song
|
8
|
+
* Implicit Animation easings can now be more easily created and registered.
|
9
|
+
* Properties can now be defined with a block
|
10
|
+
* FIX Dimensions parse creation called wrong method
|
11
|
+
* Removed support for specifying a color in animation
|
12
|
+
|
3
13
|
## 0.2.1 / 2012-11-08
|
4
14
|
|
5
15
|
* FIX Scene fade transition color changing and implicit animations
|
Binary file
|
Binary file
|
data/lib/gosu_ext/image.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Metro
|
2
|
+
|
3
|
+
#
|
4
|
+
# Sample is a wrapper class for a Gosu Sample. This allows for additional data to be stored
|
5
|
+
# without relying on monkey-patching on functionality.
|
6
|
+
#
|
7
|
+
class Sample < SimpleDelegator
|
8
|
+
|
9
|
+
attr_accessor :sample, :path
|
10
|
+
|
11
|
+
def initialize(sample,path)
|
12
|
+
super(sample)
|
13
|
+
@sample = sample
|
14
|
+
@path = path
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Metro
|
2
|
+
|
3
|
+
#
|
4
|
+
# Song is a wrapper class for a Gosu Song. This allows for additional data to be stored
|
5
|
+
# without relying on monkey-patching on functionality.
|
6
|
+
#
|
7
|
+
class Song < SimpleDelegator
|
8
|
+
|
9
|
+
attr_accessor :song, :path
|
10
|
+
|
11
|
+
def initialize(song,path)
|
12
|
+
super(song)
|
13
|
+
@song = song
|
14
|
+
@path = path
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/lib/metro.rb
CHANGED
@@ -13,6 +13,8 @@ require 'active_support/hash_with_indifferent_access'
|
|
13
13
|
require 'gosu_ext/color'
|
14
14
|
require 'gosu_ext/image'
|
15
15
|
require 'gosu_ext/animation'
|
16
|
+
require 'gosu_ext/song'
|
17
|
+
require 'gosu_ext/sample'
|
16
18
|
require 'gosu_ext/gosu_constants'
|
17
19
|
require 'core_ext/numeric'
|
18
20
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Metro
|
2
|
+
class Easing
|
3
|
+
|
4
|
+
#
|
5
|
+
# Perform a ease-in motion between the start position and the final position.
|
6
|
+
#
|
7
|
+
class EaseIn < Easing
|
8
|
+
def self.calculation(moment,start,change,interval)
|
9
|
+
change * (moment = moment / interval) * moment + start
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
register :ease_in, EaseIn
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Metro
|
2
|
+
|
3
|
+
#
|
4
|
+
# An easing is a means to calculate the steps between the start and the final
|
5
|
+
# over an interval.
|
6
|
+
#
|
7
|
+
class Easing
|
8
|
+
|
9
|
+
#
|
10
|
+
# The calculate method is called within the ImplicitAnimation and will create
|
11
|
+
# an array of all the states between the start and the final value.
|
12
|
+
#
|
13
|
+
def self.calculate(start,final,interval)
|
14
|
+
change = final - start
|
15
|
+
(1..interval).map { |time| calculation(time.to_f,start,change,interval) }
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# The calculation method is to be overriden in the Easing subclasses.
|
20
|
+
# This calculation figures out the value at the current moemnt.
|
21
|
+
#
|
22
|
+
def self.calculation(moment,start,change,interval) ; 0 ; end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Register an easing within the game system.
|
26
|
+
#
|
27
|
+
def self.register(name,easing_class)
|
28
|
+
easings[name] = easing_class.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# @return the easing class based on the specified easing name.
|
33
|
+
#
|
34
|
+
def self.easing_for(easing)
|
35
|
+
easing_classname = easings[easing]
|
36
|
+
easing_classname.constantize
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# A hash of all the supported easings within metro or game.
|
41
|
+
#
|
42
|
+
def self.easings
|
43
|
+
@easings_hash ||= HashWithIndifferentAccess.new("Metro::Easing::Linear")
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
require_relative 'linear'
|
51
|
+
require_relative 'ease_in'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Metro
|
2
|
+
class Easing
|
3
|
+
|
4
|
+
#
|
5
|
+
# Perform a linear motion between the start position and the final position.
|
6
|
+
#
|
7
|
+
class Linear < Easing
|
8
|
+
def self.calculation(moment,start,change,interval)
|
9
|
+
change * moment / interval + start
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
register :linear, Linear
|
14
|
+
end
|
15
|
+
end
|
@@ -7,6 +7,20 @@ module Metro
|
|
7
7
|
base.extend ClassMethods
|
8
8
|
end
|
9
9
|
|
10
|
+
#
|
11
|
+
# A simplier syntax to enqueue an animation. At the moment this animation is going
|
12
|
+
# to be an implicit animation.
|
13
|
+
#
|
14
|
+
def animate(actor_or_actor_name,options,&block)
|
15
|
+
options[:actor] = actor(actor_or_actor_name)
|
16
|
+
options[:context] = self
|
17
|
+
animation_group = SceneAnimation.build options, &block
|
18
|
+
enqueue animation_group
|
19
|
+
end
|
20
|
+
|
21
|
+
# An alternative to stating `animate` syntax.
|
22
|
+
alias_method :change, :animate
|
23
|
+
|
10
24
|
module ClassMethods
|
11
25
|
|
12
26
|
#
|
@@ -24,6 +38,9 @@ module Metro
|
|
24
38
|
animations.push scene_animation
|
25
39
|
end
|
26
40
|
|
41
|
+
# Provide an alternative to the `animate` syntax.
|
42
|
+
alias_method :change, :animate
|
43
|
+
|
27
44
|
#
|
28
45
|
# All the animations that are defined for the scene to be run the scene starts.
|
29
46
|
#
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative 'easing'
|
1
|
+
require_relative 'easing/easing'
|
2
2
|
|
3
3
|
module Metro
|
4
4
|
|
@@ -52,21 +52,7 @@ module Metro
|
|
52
52
|
def after_initialize
|
53
53
|
to.each do |attribute,final|
|
54
54
|
start = actor.send(attribute)
|
55
|
-
|
56
|
-
if attribute == :color
|
57
|
-
final = Gosu::Color.new final
|
58
|
-
|
59
|
-
# @TODO: This is not going to work when the color uses a non-standard
|
60
|
-
# name for the color property.
|
61
|
-
|
62
|
-
animations.push build_animation_step(:red,start.red,final.red)
|
63
|
-
animations.push build_animation_step(:green,start.green,final.green)
|
64
|
-
animations.push build_animation_step(:blue,start.blue,final.blue)
|
65
|
-
animations.push build_animation_step(:alpha,start.alpha,final.alpha)
|
66
|
-
else
|
67
|
-
animations.push build_animation_step(attribute,start,final)
|
68
|
-
end
|
69
|
-
|
55
|
+
animations.push build_animation_step(attribute,start,final)
|
70
56
|
end
|
71
57
|
end
|
72
58
|
|
@@ -74,7 +60,7 @@ module Metro
|
|
74
60
|
step = AnimationStep.new
|
75
61
|
step.actor = actor
|
76
62
|
step.attribute = attribute
|
77
|
-
step.deltas =
|
63
|
+
step.deltas = easing_for(easing).calculate(start.to_f,final.to_f,interval.to_f)
|
78
64
|
step
|
79
65
|
end
|
80
66
|
|
@@ -90,13 +76,8 @@ module Metro
|
|
90
76
|
# @return the correct easing based on the specified name. When the name
|
91
77
|
# provided does not match anything then default to linear easing.
|
92
78
|
#
|
93
|
-
def
|
94
|
-
|
95
|
-
hash = HashWithIndifferentAccess.new("Metro::Easing::Linear")
|
96
|
-
hash.merge! linear: "Metro::Easing::Linear",
|
97
|
-
ease_in: "Metro::Easing::EaseIn"
|
98
|
-
end
|
99
|
-
@steppings[stepping].constantize
|
79
|
+
def easing_for(name)
|
80
|
+
Metro::Easing.easing_for(name)
|
100
81
|
end
|
101
82
|
|
102
83
|
#
|
data/lib/metro/models/draws.rb
CHANGED
@@ -12,7 +12,7 @@ module Metro
|
|
12
12
|
#
|
13
13
|
# Define an actor with the given name and options.
|
14
14
|
#
|
15
|
-
# As a
|
15
|
+
# As a convenience the draw method will define `getter` and `setter`
|
16
16
|
# methods for the specified actor.
|
17
17
|
#
|
18
18
|
# @example Defining a title label within a scene
|
@@ -48,6 +48,15 @@ module Metro
|
|
48
48
|
drawings.push scene_actor
|
49
49
|
end
|
50
50
|
|
51
|
+
#
|
52
|
+
# Define a sound actor with the given anem and options.
|
53
|
+
#
|
54
|
+
# @see #draw
|
55
|
+
#
|
56
|
+
def play(song_name,options={})
|
57
|
+
draw song_name, options.merge(model: "metro::models::song")
|
58
|
+
end
|
59
|
+
|
51
60
|
#
|
52
61
|
# Define several actors to be drawn.
|
53
62
|
#
|
data/lib/metro/models/model.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require_relative 'key_value_coding'
|
2
|
-
require_relative 'rectangle_bounds'
|
3
2
|
require_relative 'properties/property'
|
4
3
|
|
5
4
|
module Metro
|
@@ -16,6 +15,31 @@ module Metro
|
|
16
15
|
class Model
|
17
16
|
include Units
|
18
17
|
|
18
|
+
#
|
19
|
+
# This is an entry point for customization. As the model's {#initialize}
|
20
|
+
# method performs may perform some initialization that may be necessary.
|
21
|
+
#
|
22
|
+
# At this point the model has been created. However, the window and scene
|
23
|
+
# of the model will not have been defined and defined properties rely on
|
24
|
+
# the window or scene will return nil values. Other properties also will
|
25
|
+
# likely not be set.
|
26
|
+
#
|
27
|
+
# @note This method should be implemented in the Model subclass.
|
28
|
+
#
|
29
|
+
def after_initialize ; end
|
30
|
+
|
31
|
+
|
32
|
+
#
|
33
|
+
# This is an entry point for customization. After the model's properties
|
34
|
+
# have been set and the model has been assigned to the window and scene
|
35
|
+
# this method is called. Here is where customization of properties or
|
36
|
+
# final positioning can be performed.
|
37
|
+
#
|
38
|
+
# @note This method may be implemented in the Model subclass.
|
39
|
+
#
|
40
|
+
def show ; end
|
41
|
+
|
42
|
+
|
19
43
|
#
|
20
44
|
# This is called every update interval while the actor is in the scene
|
21
45
|
#
|
@@ -23,6 +47,7 @@ module Metro
|
|
23
47
|
#
|
24
48
|
def update ; end
|
25
49
|
|
50
|
+
|
26
51
|
#
|
27
52
|
# This is called after an update. A model normally is not removed after
|
28
53
|
# an update, however if the model responds true to #completed? then it
|
@@ -34,7 +59,41 @@ module Metro
|
|
34
59
|
def completed? ; false ; end
|
35
60
|
|
36
61
|
|
37
|
-
|
62
|
+
#
|
63
|
+
# This is called after every {#update} and when the OS wants the window to
|
64
|
+
# repaint itself.
|
65
|
+
#
|
66
|
+
# @note This method should be implemented in the Model subclass.
|
67
|
+
#
|
68
|
+
def draw ; end
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
#
|
73
|
+
# Define a property for the model. A property has a name and then can optionally specify
|
74
|
+
# a property type which will receive additional options.
|
75
|
+
#
|
76
|
+
# @example Defining various propertys for a model
|
77
|
+
#
|
78
|
+
# class Player
|
79
|
+
# property :position
|
80
|
+
# property :angle, default: 0.0
|
81
|
+
# property :turn_amount, default: 4.5
|
82
|
+
# property :image, path: "player.png"
|
83
|
+
# property :motto, type: :text, default: 'Hometown Heroes!'
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# When the property name matches a property definition with that name they will be used. This is what
|
87
|
+
# happens for the 'position' and 'image' properties defined above. Both of those map to respective
|
88
|
+
# properties with matching names.
|
89
|
+
#
|
90
|
+
# Properties by default are assumed to be numeric properties so the types does not have to be stated.
|
91
|
+
# This is the case for 'angle' and 'turn_amount' properties.
|
92
|
+
#
|
93
|
+
# You may use any particular name for your properties as long as you specify the type. This is the case
|
94
|
+
# for the 'motto' property.
|
95
|
+
#
|
96
|
+
def self.property(name,options={},&block)
|
38
97
|
|
39
98
|
# Use the name as the property type if one has not been provided.
|
40
99
|
|
@@ -42,6 +101,18 @@ module Metro
|
|
42
101
|
|
43
102
|
property_class = Property.property(property_type)
|
44
103
|
|
104
|
+
define_method name do
|
105
|
+
raw_value = properties[name]
|
106
|
+
property_class.new(self,options,&block).get raw_value
|
107
|
+
end
|
108
|
+
|
109
|
+
define_method "#{name}=" do |value|
|
110
|
+
prepared_value = property_class.new(self,options).set(value)
|
111
|
+
properties[name] = prepared_value
|
112
|
+
end
|
113
|
+
|
114
|
+
# Define any sub-properties defined on this property
|
115
|
+
|
45
116
|
# When the name does not match the property type then we want to force
|
46
117
|
# the prefixing to be on for our sub-properties. This is to make sure
|
47
118
|
# that when people define multiple fonts and colors that they do not
|
@@ -49,72 +120,60 @@ module Metro
|
|
49
120
|
|
50
121
|
override_prefix = !(name == property_type)
|
51
122
|
|
52
|
-
# Define any properties defined on this property
|
53
|
-
|
54
123
|
property_class.defined_properties.each do |subproperty|
|
55
124
|
sub_options = { prefix: override_prefix }.merge(subproperty.options)
|
56
125
|
sub_options = sub_options.merge(parents: (Array(sub_options[:parents]) + [name]))
|
57
|
-
|
58
|
-
property subproperty.name, sub_options
|
126
|
+
_sub_property subproperty.name, sub_options
|
59
127
|
end
|
60
128
|
|
61
|
-
|
62
|
-
# parent property for which they are dependent on we will need
|
63
|
-
# to know this information because we need to behave appropriately
|
64
|
-
# within the getter and setter blocks below.
|
65
|
-
|
66
|
-
is_a_dependency = true if options[:parents]
|
67
|
-
|
68
|
-
if is_a_dependency
|
129
|
+
end
|
69
130
|
|
70
|
-
|
131
|
+
#
|
132
|
+
# Defines the sub-properties defined within the property. This is to be used internally
|
133
|
+
# by the #property method.
|
134
|
+
#
|
135
|
+
def self._sub_property(name,options={},&block)
|
71
136
|
|
72
|
-
|
137
|
+
# Use the name as the property type if one has not been provided.
|
73
138
|
|
74
|
-
|
75
|
-
method_name = (parents + [name]).join("_")
|
76
|
-
end
|
139
|
+
property_type = options[:type] || name
|
77
140
|
|
78
|
-
|
79
|
-
# parent properties, finally returning the filtered value
|
141
|
+
property_class = Property.property(property_type)
|
80
142
|
|
81
|
-
|
82
|
-
raw_value = (parents + [name]).inject(self) {|current,method| current.send(method) }
|
83
|
-
property_class.new(self,options).get raw_value
|
84
|
-
end
|
143
|
+
parents = Array(options[:parents])
|
85
144
|
|
86
|
-
|
87
|
-
# value and set itself on that with the filtered value. The parent
|
88
|
-
# is then set.
|
89
|
-
#
|
90
|
-
# @TODO: If getters return dups and not instances of the original object then a very
|
91
|
-
# deep setter will not be valid.
|
92
|
-
#
|
93
|
-
define_method "#{method_name}=" do |value|
|
94
|
-
parent_value = parents.inject(self) {|current,method| current.send(method) }
|
145
|
+
method_name = name
|
95
146
|
|
96
|
-
|
97
|
-
|
147
|
+
if options[:prefix]
|
148
|
+
method_name = (parents + [name]).join("_")
|
149
|
+
end
|
98
150
|
|
99
|
-
|
100
|
-
|
151
|
+
# Define a getter for the sub-property that will traverse the
|
152
|
+
# parent properties, finally returning the filtered value
|
101
153
|
|
102
|
-
|
154
|
+
define_method method_name do
|
155
|
+
raw_value = (parents + [name]).inject(self) {|current,method| current.send(method) }
|
156
|
+
property_class.new(self,options).get raw_value
|
157
|
+
end
|
103
158
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
159
|
+
# Define a setter for the sub-property that will find the parent
|
160
|
+
# value and set itself on that with the filtered value. The parent
|
161
|
+
# is then set.
|
162
|
+
#
|
163
|
+
# @TODO: If getters return dups and not instances of the original object then a very
|
164
|
+
# deep setter will not be valid.
|
165
|
+
#
|
166
|
+
define_method "#{method_name}=" do |value|
|
167
|
+
parent_value = parents.inject(self) {|current,method| current.send(method) }
|
108
168
|
|
109
|
-
|
110
|
-
|
111
|
-
properties[name] = prepared_value
|
112
|
-
end
|
169
|
+
prepared_value = property_class.new(self,options,&block).set(value)
|
170
|
+
parent_value.send("#{name}=",prepared_value)
|
113
171
|
|
172
|
+
send("#{parents.last}=",parent_value)
|
114
173
|
end
|
115
|
-
|
116
174
|
end
|
117
175
|
|
176
|
+
|
118
177
|
def properties
|
119
178
|
@properties ||= {}
|
120
179
|
end
|
@@ -122,14 +181,6 @@ module Metro
|
|
122
181
|
property :model, type: :text
|
123
182
|
property :name, type: :text
|
124
183
|
|
125
|
-
#
|
126
|
-
# This is called after every {#update} and when the OS wants the window to
|
127
|
-
# repaint itself.
|
128
|
-
#
|
129
|
-
# @note This method should be implemented in the Model subclass.
|
130
|
-
#
|
131
|
-
def draw ; end
|
132
|
-
|
133
184
|
#
|
134
185
|
# The window that this model that this window is currently being
|
135
186
|
# displayed.
|
@@ -153,14 +204,6 @@ module Metro
|
|
153
204
|
|
154
205
|
include KeyValueCoding
|
155
206
|
|
156
|
-
#
|
157
|
-
# This is an entry point for customization. As the model's {#initialize}
|
158
|
-
# method performs may perform some initialization that may be necessary.
|
159
|
-
#
|
160
|
-
# @note This method should be implemented in the Model subclass.
|
161
|
-
#
|
162
|
-
def after_initialize ; end
|
163
|
-
|
164
207
|
#
|
165
208
|
# Generate a custom notification event with the given name.
|
166
209
|
#
|
@@ -253,19 +296,12 @@ module Metro
|
|
253
296
|
#
|
254
297
|
# Captures all classes that subclass Model.
|
255
298
|
#
|
256
|
-
# @see #self.
|
299
|
+
# @see #self.models_hash
|
257
300
|
#
|
258
|
-
def self.inherited(
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
#
|
263
|
-
# All subclasses of Model, this should be all the defined model within the game.
|
264
|
-
#
|
265
|
-
# @return an Array of Scene subclasses
|
266
|
-
#
|
267
|
-
def self.models
|
268
|
-
@models ||= []
|
301
|
+
def self.inherited(model)
|
302
|
+
models_hash[model.to_s] = model.to_s
|
303
|
+
models_hash[model.to_s.downcase] = model.to_s
|
304
|
+
models_hash[model.to_s.underscore] = model.to_s
|
269
305
|
end
|
270
306
|
|
271
307
|
#
|
@@ -273,20 +309,11 @@ module Metro
|
|
273
309
|
#
|
274
310
|
# @return the Model class given the specified model name.
|
275
311
|
def self.model(name)
|
276
|
-
|
277
|
-
|
278
|
-
hash = HashWithIndifferentAccess.new("Metro::Models::Generic")
|
279
|
-
|
280
|
-
models.each do |model|
|
281
|
-
hash[model.to_s] = model
|
282
|
-
hash[model.downcase] = model
|
283
|
-
hash[model.to_s.underscore] = model
|
284
|
-
end
|
285
|
-
|
286
|
-
hash
|
287
|
-
end
|
312
|
+
models_hash[name]
|
313
|
+
end
|
288
314
|
|
289
|
-
|
315
|
+
def self.models_hash
|
316
|
+
@models_hash ||= HashWithIndifferentAccess.new("Metro::Models::Generic")
|
290
317
|
end
|
291
318
|
|
292
319
|
end
|
@@ -298,3 +325,4 @@ require_relative 'models/menu'
|
|
298
325
|
require_relative 'models/image'
|
299
326
|
require_relative 'models/rectangle'
|
300
327
|
require_relative 'models/grid_drawer'
|
328
|
+
require_relative 'models/song'
|