metro-ld25 0.3.3

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 (177) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +12 -0
  6. data/Guardfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +189 -0
  9. data/Rakefile +18 -0
  10. data/bin/metro +16 -0
  11. data/changelog.md +157 -0
  12. data/lib/assets/menu-movement.wav +0 -0
  13. data/lib/assets/menu-selection.wav +0 -0
  14. data/lib/assets/missing.ogg +0 -0
  15. data/lib/assets/missing.png +0 -0
  16. data/lib/assets/missing.wav +0 -0
  17. data/lib/assets/missing_animation.png +0 -0
  18. data/lib/commands/generate_game.rb +13 -0
  19. data/lib/commands/generate_model.rb +25 -0
  20. data/lib/commands/generate_scene.rb +36 -0
  21. data/lib/commands/generate_view.rb +21 -0
  22. data/lib/commands/thor.rb +83 -0
  23. data/lib/core_ext/class.rb +14 -0
  24. data/lib/core_ext/numeric.rb +59 -0
  25. data/lib/gosu_ext/color.rb +62 -0
  26. data/lib/gosu_ext/gosu_constants.rb +53 -0
  27. data/lib/locale/en.yml +35 -0
  28. data/lib/locale/locale.rb +1 -0
  29. data/lib/metro.rb +140 -0
  30. data/lib/metro/animation.rb +135 -0
  31. data/lib/metro/animation/after_interval_factory.rb +12 -0
  32. data/lib/metro/animation/animation_factory.rb +15 -0
  33. data/lib/metro/animation/easing/ease_in.rb +15 -0
  34. data/lib/metro/animation/easing/easing.rb +51 -0
  35. data/lib/metro/animation/easing/linear.rb +15 -0
  36. data/lib/metro/animation/has_animations.rb +70 -0
  37. data/lib/metro/animation/implicit_animation.rb +100 -0
  38. data/lib/metro/animation/on_update_operation.rb +96 -0
  39. data/lib/metro/animation/scene_animation.rb +16 -0
  40. data/lib/metro/asset_path.rb +97 -0
  41. data/lib/metro/events/control_definition.rb +11 -0
  42. data/lib/metro/events/controls.rb +42 -0
  43. data/lib/metro/events/event_data.rb +60 -0
  44. data/lib/metro/events/event_dictionary.rb +52 -0
  45. data/lib/metro/events/event_factory.rb +17 -0
  46. data/lib/metro/events/event_relay.rb +300 -0
  47. data/lib/metro/events/event_state_manager.rb +63 -0
  48. data/lib/metro/events/events.rb +3 -0
  49. data/lib/metro/events/has_events.rb +108 -0
  50. data/lib/metro/events/hit_list.rb +75 -0
  51. data/lib/metro/events/unknown_sender.rb +5 -0
  52. data/lib/metro/font.rb +69 -0
  53. data/lib/metro/game.rb +102 -0
  54. data/lib/metro/game/dsl.rb +68 -0
  55. data/lib/metro/image.rb +68 -0
  56. data/lib/metro/logging.rb +33 -0
  57. data/lib/metro/missing_scene.rb +21 -0
  58. data/lib/metro/models/audio/song.rb +33 -0
  59. data/lib/metro/models/draws.rb +86 -0
  60. data/lib/metro/models/key_value_coding.rb +38 -0
  61. data/lib/metro/models/model.rb +236 -0
  62. data/lib/metro/models/model_factory.rb +32 -0
  63. data/lib/metro/models/models.rb +62 -0
  64. data/lib/metro/models/properties/animation_property.rb +115 -0
  65. data/lib/metro/models/properties/array_property.rb +24 -0
  66. data/lib/metro/models/properties/boolean_property.rb +27 -0
  67. data/lib/metro/models/properties/color_property.rb +116 -0
  68. data/lib/metro/models/properties/dimensions_property.rb +84 -0
  69. data/lib/metro/models/properties/font_property.rb +130 -0
  70. data/lib/metro/models/properties/image_property.rb +96 -0
  71. data/lib/metro/models/properties/model_property.rb +84 -0
  72. data/lib/metro/models/properties/numeric_property.rb +29 -0
  73. data/lib/metro/models/properties/options_property/no_option.rb +29 -0
  74. data/lib/metro/models/properties/options_property/options.rb +94 -0
  75. data/lib/metro/models/properties/options_property/options_property.rb +125 -0
  76. data/lib/metro/models/properties/position_property.rb +90 -0
  77. data/lib/metro/models/properties/property.rb +221 -0
  78. data/lib/metro/models/properties/property_owner.rb +137 -0
  79. data/lib/metro/models/properties/sample_property.rb +84 -0
  80. data/lib/metro/models/properties/scale_property.rb +80 -0
  81. data/lib/metro/models/properties/song_property.rb +89 -0
  82. data/lib/metro/models/properties/text_property.rb +75 -0
  83. data/lib/metro/models/ui/animated_sprite.rb +85 -0
  84. data/lib/metro/models/ui/border.rb +95 -0
  85. data/lib/metro/models/ui/fps.rb +54 -0
  86. data/lib/metro/models/ui/generic.rb +66 -0
  87. data/lib/metro/models/ui/grid_drawer.rb +74 -0
  88. data/lib/metro/models/ui/image.rb +87 -0
  89. data/lib/metro/models/ui/label.rb +175 -0
  90. data/lib/metro/models/ui/menu.rb +214 -0
  91. data/lib/metro/models/ui/model_label.rb +65 -0
  92. data/lib/metro/models/ui/model_labeler.rb +79 -0
  93. data/lib/metro/models/ui/rectangle.rb +59 -0
  94. data/lib/metro/models/ui/sprite.rb +79 -0
  95. data/lib/metro/models/ui/tile_map.rb +162 -0
  96. data/lib/metro/models/ui/ui.rb +13 -0
  97. data/lib/metro/parameters/command_line_args_parser.rb +68 -0
  98. data/lib/metro/parameters/options.rb +25 -0
  99. data/lib/metro/parameters/parameters.rb +2 -0
  100. data/lib/metro/sample.rb +40 -0
  101. data/lib/metro/scene.rb +477 -0
  102. data/lib/metro/scenes.rb +154 -0
  103. data/lib/metro/song.rb +56 -0
  104. data/lib/metro/template_message.rb +60 -0
  105. data/lib/metro/transitions/edit_transition_scene.rb +100 -0
  106. data/lib/metro/transitions/fade_transition_scene.rb +66 -0
  107. data/lib/metro/transitions/scene_transitions.rb +44 -0
  108. data/lib/metro/transitions/transition_scene.rb +19 -0
  109. data/lib/metro/units/bounds.rb +8 -0
  110. data/lib/metro/units/calculation_validations.rb +74 -0
  111. data/lib/metro/units/dimensions.rb +60 -0
  112. data/lib/metro/units/point.rb +51 -0
  113. data/lib/metro/units/rectangle_bounds.rb +85 -0
  114. data/lib/metro/units/scale.rb +46 -0
  115. data/lib/metro/units/units.rb +6 -0
  116. data/lib/metro/version.rb +32 -0
  117. data/lib/metro/views/json_view.rb +60 -0
  118. data/lib/metro/views/no_view.rb +34 -0
  119. data/lib/metro/views/parsers.rb +42 -0
  120. data/lib/metro/views/scene_view.rb +107 -0
  121. data/lib/metro/views/view.rb +133 -0
  122. data/lib/metro/views/writers.rb +43 -0
  123. data/lib/metro/views/yaml_view.rb +94 -0
  124. data/lib/metro/window.rb +94 -0
  125. data/lib/setup_handlers/exit_if_dry_run.rb +26 -0
  126. data/lib/setup_handlers/game_execution.rb +65 -0
  127. data/lib/setup_handlers/load_game_configuration.rb +65 -0
  128. data/lib/setup_handlers/load_game_files.rb +101 -0
  129. data/lib/setup_handlers/move_to_game_directory.rb +25 -0
  130. data/lib/setup_handlers/reload_game_on_game_file_changes.rb +79 -0
  131. data/lib/templates/game/README.md.tt +52 -0
  132. data/lib/templates/game/assets/brand.jpg +0 -0
  133. data/lib/templates/game/assets/hero.png +0 -0
  134. data/lib/templates/game/lib/custom_easing.rb +32 -0
  135. data/lib/templates/game/metro.tt +63 -0
  136. data/lib/templates/game/models/hero.rb +62 -0
  137. data/lib/templates/game/scenes/brand_scene.rb +19 -0
  138. data/lib/templates/game/scenes/brand_to_title_scene.rb +13 -0
  139. data/lib/templates/game/scenes/first_scene.rb +28 -0
  140. data/lib/templates/game/scenes/game_scene.rb +43 -0
  141. data/lib/templates/game/scenes/title_scene.rb +15 -0
  142. data/lib/templates/game/views/brand.yaml +4 -0
  143. data/lib/templates/game/views/brand_to_title.yaml +8 -0
  144. data/lib/templates/game/views/first.yaml +26 -0
  145. data/lib/templates/game/views/title.yaml +11 -0
  146. data/lib/templates/message.erb +23 -0
  147. data/lib/templates/model.rb.tt +111 -0
  148. data/lib/templates/scene.rb.tt +140 -0
  149. data/lib/templates/view.yaml.tt +11 -0
  150. data/lib/tmxed_ext/tile_set.rb +34 -0
  151. data/metro.gemspec +56 -0
  152. data/spec/core_ext/numeric_spec.rb +78 -0
  153. data/spec/core_ext/string_spec.rb +33 -0
  154. data/spec/gosu_ext/color_spec.rb +80 -0
  155. data/spec/metro/events/event_state_manager_spec.rb +5 -0
  156. data/spec/metro/models/key_value_coding_spec.rb +61 -0
  157. data/spec/metro/models/properties/array_property_spec.rb +60 -0
  158. data/spec/metro/models/properties/color_property_spec.rb +85 -0
  159. data/spec/metro/models/properties/dimensions_spec.rb +29 -0
  160. data/spec/metro/models/properties/font_property_spec.rb +127 -0
  161. data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
  162. data/spec/metro/models/properties/options_property/no_option_spec.rb +25 -0
  163. data/spec/metro/models/properties/options_property/options_property_spec.rb +133 -0
  164. data/spec/metro/models/properties/options_property/options_spec.rb +125 -0
  165. data/spec/metro/models/properties/position_property_spec.rb +90 -0
  166. data/spec/metro/models/ui/label_spec.rb +259 -0
  167. data/spec/metro/parameters/command_line_args_parser_spec.rb +42 -0
  168. data/spec/metro/scene_spec.rb +15 -0
  169. data/spec/metro/scene_views/json_view_spec.rb +27 -0
  170. data/spec/metro/scene_views/yaml_view_spec.rb +38 -0
  171. data/spec/metro/scenes_spec.rb +77 -0
  172. data/spec/metro/units/point_spec.rb +132 -0
  173. data/spec/metro/views/view_spec.rb +53 -0
  174. data/spec/setup_handlers/exit_if_dry_run_spec.rb +27 -0
  175. data/spec/setup_handlers/reload_game_on_game_file_changes_spec.rb +68 -0
  176. data/spec/spec_helper.rb +20 -0
  177. metadata +374 -0
@@ -0,0 +1,68 @@
1
+ module Metro
2
+
3
+ #
4
+ # Image is a wrapper class for a Gosu Image. This allows for additional data
5
+ # to be stored without relying on monkey-patching on functionality.
6
+ #
7
+ class Image < SimpleDelegator
8
+
9
+ def initialize(gosu_image,path,tileable)
10
+ super(gosu_image)
11
+ @path = path
12
+ @tileable = tileable
13
+ end
14
+
15
+ # The relative path of the image
16
+ attr_reader :path
17
+
18
+ # The tileability of the image
19
+ attr_reader :tileable
20
+
21
+ def dimensions
22
+ Metro::Units::Dimensions.of width, height
23
+ end
24
+
25
+ #
26
+ # Finds an existing image or creates a new image given the window, path,
27
+ # and tileablilty.
28
+ #
29
+ # @example Finding or creating an Image
30
+ #
31
+ # Metro::Image.find_or_create window: model.window,
32
+ # path: "asset_path", tileable: tileable
33
+ #
34
+ def self.find_or_create(options)
35
+ path = AssetPath.with(options[:path])
36
+ images[path.to_s] or (images[path.to_s] = create(options))
37
+ end
38
+
39
+ #
40
+ # Create an image given the window, path, and tileability.
41
+ #
42
+ # @example Creating an Image
43
+ #
44
+ # Metro::Image.create window: model.window,
45
+ # path: "asset_path", tileable: tileable
46
+ #
47
+ def self.create(options)
48
+ window, asset_path, tileable = create_params(options)
49
+ gosu_image = Gosu::Image.new(window,asset_path.filepath,tileable)
50
+ new gosu_image, asset_path.path, tileable
51
+ end
52
+
53
+ private
54
+
55
+ def self.create_params(options)
56
+ options.symbolize_keys!
57
+ asset_path = AssetPath.with(options[:path])
58
+ window = options[:window]
59
+ tileable = !!options[:tileable]
60
+ [ window, asset_path, tileable ]
61
+ end
62
+
63
+ def self.images
64
+ @images ||= {}
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,33 @@
1
+
2
+ #
3
+ # Generates a default logger to standard out that can be used within Metro or the game.
4
+ #
5
+ # @example Outputting information at the debug level
6
+ #
7
+ # log.debug "The the screen resolution is #{Game.width},#{Game.height}"
8
+ #
9
+ def log
10
+ @log ||= begin
11
+ logger = Logger.new(STDOUT)
12
+ logger.level = Logger::DEBUG
13
+ logger
14
+ end
15
+ end
16
+
17
+ #
18
+ # Display an error message defined within the localization file. A game error displays
19
+ # a error title, message, and actions that can be taken to possibly address this issue.
20
+ #
21
+ # @param [String] message the I18n string found in the locale file.
22
+ # @param [Hash] details contains all the possible key-value pairs that might be needed
23
+ # for the localized error messages.
24
+ #
25
+ def error!(messages, details = {})
26
+ details = { show: true, exit: true }.merge details
27
+
28
+ message = TemplateMessage.new messages: messages, details: details,
29
+ website: Game.website, contact: Game.contact
30
+
31
+ warn message if details[:show]
32
+ exit 1 if details[:exit]
33
+ end
@@ -0,0 +1,21 @@
1
+ module Metro
2
+ class MissingScene < Scene
3
+ scene_name :missing_scene
4
+
5
+ class << self
6
+ attr_accessor :missing_scene
7
+ end
8
+
9
+ draw :title, text: "Missing Scene!",
10
+ position: "20,20,1",
11
+ color: "rgb(255,0,0)",
12
+ font: {size: 80},
13
+ model: "metro::ui::label"
14
+
15
+ draw :message, text: 'The scene `#{self.class.missing_scene}` was requested, but is missing!',
16
+ position: "20,100,1",
17
+ color: "rgb(255,255,255)",
18
+ model: "metro::ui::label"
19
+
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ module Metro
2
+ module Audio
3
+
4
+ #
5
+ # A song represents an audio representation.
6
+ #
7
+ class Song < Metro::Model
8
+
9
+ property :song
10
+ property :volume, default: 1.0
11
+ property :state, type: :text, default: 'play'
12
+
13
+ def show
14
+ song.volume = self.volume
15
+ play if state == "play"
16
+ end
17
+
18
+ def stop
19
+ song.stop
20
+ end
21
+
22
+ def play
23
+ song.play if not song.playing? and not song.paused?
24
+ end
25
+
26
+ def pause
27
+ song.playing? ? song.pause : song.play
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,86 @@
1
+ require_relative 'model_factory'
2
+
3
+ module Metro
4
+ module Draws
5
+
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ #
13
+ # Define an actor with the given name and options.
14
+ #
15
+ # As a convenience the draw method will define `getter` and `setter`
16
+ # methods for the specified actor.
17
+ #
18
+ # @example Defining a title label within a scene
19
+ #
20
+ # class ExampleScene
21
+ # draw :title, text: 'Title Screen',
22
+ # model: 'metro::ui::label'
23
+ # position: '20,20,0',
24
+ # scale: '3,3',
25
+ # color: 'rgba(255,255,255,1.0)'
26
+ #
27
+ # def show
28
+ # puts "Where is my title? #{title.x},#{title.y}"
29
+ # end
30
+ # end
31
+ #
32
+ def draw(actor_name,options = {})
33
+
34
+ view_content_for_actor = view.content[actor_name.to_s]
35
+
36
+ actor_data = view_content_for_actor.merge(options)
37
+ actor_data[:name] = actor_name
38
+
39
+ scene_actor = ModelFactory.new actor_name, actor_data
40
+
41
+ define_method actor_name do
42
+ instance_variable_get("@#{actor_name}")
43
+ end
44
+
45
+ define_method "#{actor_name}=" do |value|
46
+ instance_variable_set("@#{actor_name}",value)
47
+ end
48
+
49
+ drawings.push scene_actor
50
+ end
51
+
52
+ #
53
+ # Define a sound actor with the given anem and options.
54
+ #
55
+ # @see #draw
56
+ #
57
+ def play(song_name,options={})
58
+ draw song_name, options.merge(model: "metro::audio::song")
59
+ end
60
+
61
+ #
62
+ # Define several actors to be drawn.
63
+ #
64
+ def draws(*actor_names)
65
+ actor_names = actor_names.flatten.compact
66
+
67
+ actor_names.each do |actor_name|
68
+ draw actor_name
69
+ end
70
+
71
+ drawings
72
+ end
73
+
74
+ #
75
+ # All of the model factories that have been defined.
76
+ #
77
+ def drawings
78
+ @drawings ||= []
79
+ end
80
+
81
+ alias_method :actors, :drawings
82
+
83
+ end
84
+
85
+ end
86
+ end
@@ -0,0 +1,38 @@
1
+ module Metro
2
+
3
+ #
4
+ # Key-Value coding emulates the functionality found in Objective-C, which allows
5
+ # for an object to be sent a message which contains the method to return. This is
6
+ # the same as Ruby. However, Objective-C also supports the use of the dot notation
7
+ # within the keys to acces the sub-values.
8
+ #
9
+ # @example Setting the red value of the color on a Model.
10
+ #
11
+ # class Elf
12
+ # include KeyValueCoding
13
+ #
14
+ # attr_accessor :color
15
+ # end
16
+ #
17
+ # elf = Elf.new
18
+ # elf.color = Gosu::Color.new "rgb(0,0,0)"
19
+ #
20
+ # elf.get("color.red") # => 0
21
+ # elf.set("color.red",255)
22
+ # elf.get("color.red") # => 255
23
+ #
24
+ module KeyValueCoding
25
+
26
+ def set(name,value)
27
+ keys = name.to_s.split('.')
28
+ key_to_set = keys[0..-2].inject(self) {|target,method| target.send(method) }
29
+ key_to_set.send("#{keys.last}=",value)
30
+ end
31
+
32
+ def get(name)
33
+ keys = name.to_s.split('.')
34
+ keys.inject(self) {|target,method| target.send(method) }
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,236 @@
1
+ require_relative 'key_value_coding'
2
+ require_relative 'properties/property'
3
+ require_relative 'models'
4
+
5
+ module Metro
6
+
7
+ #
8
+ # The Model is a basic, generic representation of a game object
9
+ # that has a visual representation within the scene's window.
10
+ #
11
+ # Model is designed to be an abstract class, to be subclassed by
12
+ # other models.
13
+ #
14
+ # @see Models::Generic
15
+ #
16
+ class Model
17
+ include PropertyOwner
18
+ include Units
19
+
20
+ #
21
+ # This is an entry point for customization. As the model's {#initialize}
22
+ # method performs may perform some initialization that may be necessary.
23
+ #
24
+ # At this point the model has been created. However, the window and scene
25
+ # of the model will not have been defined and defined properties rely on
26
+ # the window or scene will return nil values. Other properties also will
27
+ # likely not be set.
28
+ #
29
+ # @note This method should be implemented in the Model subclass.
30
+ #
31
+ def after_initialize ; end
32
+
33
+ #
34
+ # This is an entry point for customization. After the model's properties
35
+ # have been set and the model has been assigned to the window and scene
36
+ # this method is called. Here is where customization of properties or
37
+ # final positioning can be performed.
38
+ #
39
+ # @note This method may be implemented in the Model subclass.
40
+ #
41
+ def show ; end
42
+
43
+ #
44
+ # This is called every update interval while the actor is in the scene
45
+ #
46
+ # @note This method should be implemented in the Model subclass
47
+ #
48
+ def update ; end
49
+
50
+ #
51
+ # This is called after an update. A model normally is not removed after
52
+ # an update, however if the model responds true to #completed? then it
53
+ # will be removed.
54
+ #
55
+ # @note This method should be implemented in the Model sublclass if you
56
+ # are interested in having the model be removed from the scene.
57
+ #
58
+ def completed? ; false ; end
59
+
60
+ #
61
+ # This is called after every {#update} and when the OS wants the window to
62
+ # repaint itself.
63
+ #
64
+ # @note This method should be implemented in the Model subclass.
65
+ #
66
+ def draw ; end
67
+
68
+ def self.model_name(model_name=nil)
69
+ @model_name ||= to_s.underscore
70
+ model_name ? @model_name = model_name.to_s : @model_name
71
+ end
72
+
73
+ #
74
+ # @return [String] the name of the model class.
75
+ #
76
+ property :model, type: :text
77
+
78
+ #
79
+ # @return [String] the name of model as it is used within the view or the scene.
80
+ # This is the common name, the key within the view file, or the name symbol
81
+ # name specified in the scene.
82
+ #
83
+ property :name, type: :text
84
+
85
+ #
86
+ # @return [TrueClass,FalseClass] true if the model should be saved to the
87
+ # view file, false when the model should not be savedable to the view file.
88
+ #
89
+ property :saveable_to_view, type: :boolean, default: true
90
+
91
+ #
92
+ # The window that this model that this window is currently being
93
+ # displayed.
94
+ #
95
+ # The current value of window is managed by the scene
96
+ # as this is set when the Scene is added to the window. All the
97
+ # models gain access to the window.
98
+ #
99
+ # @see Window
100
+ #
101
+ attr_accessor :window
102
+
103
+ #
104
+ # The scene that this model is currently being displayed.
105
+ #
106
+ # The current value of scene is managed by the scene as this
107
+ # is set when the scene is created.
108
+ #
109
+ # @see Scene
110
+ attr_accessor :scene
111
+
112
+ include KeyValueCoding
113
+
114
+ #
115
+ # Generate a custom notification event with the given name.
116
+ #
117
+ # @param [Symbol] event the name of the notification to generate.
118
+ #
119
+ def notification(event)
120
+ scene.notification(event.to_sym,self)
121
+ end
122
+
123
+ #
124
+ # Allows for the definition of events within the scene.
125
+ #
126
+ include HasEvents
127
+
128
+ #
129
+ # A helper method that allows the current model to generate another model. This
130
+ # is useful as it allows for the current model to pass window and scene state
131
+ # to the created model.
132
+ #
133
+ # @param [String] model_name the name of the model to be created.
134
+ # @return [Metro::Model] the metro model instance
135
+ #
136
+ def create(model_name,options={})
137
+ # @TODO: this is another path that parallels the ModelFactory
138
+ model_class = Metro::Models.find(model_name)
139
+ mc = model_class.new options
140
+ mc.scene = scene
141
+ mc.window = window
142
+ mc
143
+ end
144
+
145
+ #
146
+ # By default a model has no bounds. Each subclass of model will have to
147
+ # define how their bounds are defined.
148
+ #
149
+ def bounds
150
+ Bounds.none
151
+ end
152
+
153
+ #
154
+ # Create an instance of a model.
155
+ #
156
+ # @note Overridding initialize method should be avoided, using the {#aftter_initialize)
157
+ # method or done with care to ensure that functionality is preserved.
158
+ #
159
+ def initialize(options = {})
160
+ _load(options)
161
+ after_initialize
162
+ end
163
+
164
+ #
165
+ # Loads a hash of content into the model. This process will convert the hash
166
+ # of content into setter and getter methods with appropriate ruby style names.
167
+ #
168
+ # This is used internally when the model is created for the Scene. It is loaded
169
+ # with the contents of the view.
170
+ #
171
+ def _load(options = {})
172
+ # Clean up and symbolize all the keys then merge that with the existing properties
173
+ options.keys.each do |key|
174
+ property_name = key.to_s.underscore.to_sym
175
+ if respond_to? "#{property_name}="
176
+ send("#{property_name}=",options.delete(key))
177
+ else
178
+ options[property_name] = options.delete(key)
179
+ end
180
+ end
181
+
182
+ properties.merge! options
183
+ end
184
+
185
+ #
186
+ # Generate a hash export of all the fields that were previously stored within
187
+ # the model.
188
+ #
189
+ # This is used internally within the scene to transfer the data from one model
190
+ # to another model.
191
+ #
192
+ def _save
193
+ properties
194
+ end
195
+
196
+ #
197
+ # Generate a hash representation of the model.
198
+ #
199
+ def to_hash
200
+ { name => properties.except(:name) }
201
+ end
202
+
203
+ #
204
+ # @return a common name that can be used through the system as a common identifier.
205
+ #
206
+ def self.metro_name
207
+ name.underscore
208
+ end
209
+
210
+ #
211
+ # @return an array of all ancestor models by name
212
+ #
213
+ def self.hierarchy
214
+ ancestors.find_all {|a| a.respond_to? :metro_name }.map(&:metro_name)
215
+ end
216
+
217
+ #
218
+ # Captures all classes that subclass Model.
219
+ #
220
+ def self.inherited(base)
221
+ models << base.to_s
222
+ Models.add(base)
223
+ end
224
+
225
+ #
226
+ # All subclasses of Model, this should be all the defined
227
+ #
228
+ def self.models
229
+ @models ||= []
230
+ end
231
+
232
+ end
233
+ end
234
+
235
+ require_relative 'ui/ui'
236
+ require_relative 'audio/song'