metro 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/lib/metro/event_relay.rb +197 -28
- data/lib/metro/game/dsl.rb +5 -1
- data/lib/metro/game.rb +4 -0
- data/lib/metro/scene.rb +137 -84
- data/lib/metro/scene_view/drawers/artists_block.rb +17 -0
- data/lib/metro/scene_view/drawers/composite_drawer.rb +81 -0
- data/lib/metro/scene_view/drawers/drawer.rb +115 -0
- data/lib/metro/scene_view/drawers/image.rb +30 -0
- data/lib/metro/scene_view/{components → drawers}/label.rb +5 -0
- data/lib/metro/scene_view/{components → drawers}/select.rb +10 -2
- data/lib/metro/scene_view/json_view.rb +21 -1
- data/lib/metro/scene_view/no_view.rb +12 -1
- data/lib/metro/scene_view/scene_view.rb +34 -4
- data/lib/metro/scene_view/yaml_view.rb +18 -1
- data/lib/metro/scenes.rb +53 -11
- data/lib/metro/version.rb +1 -1
- data/lib/metro/window.rb +35 -8
- data/lib/metro.rb +21 -3
- metadata +8 -6
- data/lib/metro/scene_view/components/drawer.rb +0 -44
- data/lib/metro/scene_view/components/unsupported_component.rb +0 -9
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# metro
|
2
2
|
|
3
|
-
Metro is a framework built around [gosu](https://github.com/jlnr/gosu) the 2D game development library in Ruby. The goal of Metro is to enforce common conceptual structures and conventions making it easier to quickly generate a game.
|
3
|
+
Metro is a framework built around [gosu](https://github.com/jlnr/gosu) (the 2D game development library in Ruby). The goal of Metro is to enforce common conceptual structures and conventions making it easier to quickly generate a game.
|
4
4
|
|
5
5
|
> 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.
|
6
6
|
|
data/lib/metro/event_relay.rb
CHANGED
@@ -1,56 +1,225 @@
|
|
1
1
|
module Metro
|
2
|
-
class EventRelay
|
3
|
-
|
4
|
-
attr_reader :target, :window
|
5
2
|
|
6
|
-
|
3
|
+
#
|
4
|
+
# An EventRelay represents a target's willingness to respond to events
|
5
|
+
# generate from the window. An event relay is generate for every scene
|
6
|
+
# but additional relays can be generated to also listen for events.
|
7
|
+
#
|
8
|
+
# An event relay can register a target to listen for the following window
|
9
|
+
# events: 'button_down'; 'button_up'; and 'button_held'.
|
10
|
+
#
|
11
|
+
# @note registering for 'button_held' events require that the window be
|
12
|
+
# speicfied. As that is the only way to ask if the button is currently
|
13
|
+
# pressed.
|
14
|
+
#
|
15
|
+
# @see #on_up
|
16
|
+
# @see #on_down
|
17
|
+
# @see #on_hold
|
18
|
+
#
|
19
|
+
# A target can also receive events when 'button_up' and 'button_down' events
|
20
|
+
# have been fired but did not map to any specified actions. This is similar to
|
21
|
+
# Ruby's {#method_missing}.
|
22
|
+
#
|
23
|
+
# To receive unampped 'button_up' events define a method
|
24
|
+
# named `up_action_missing(id)` within your target.
|
25
|
+
#
|
26
|
+
# To receive unampped 'button_down' events define a method
|
27
|
+
# named `down_action_missing(id)` within your target.
|
28
|
+
#
|
29
|
+
# @example Scene that receives all the 'button_up' and 'button_down' events that
|
30
|
+
# are not mapped to actions.
|
31
|
+
#
|
32
|
+
# class ExampleScene
|
33
|
+
# def up_action_missing(id)
|
34
|
+
# puts "No up action found for #{id}"
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# def down_action_missing(id)
|
38
|
+
# puts "No down action found for #{id}"
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
class EventRelay
|
7
43
|
|
8
|
-
|
44
|
+
#
|
45
|
+
# An event relay is created a with a target and optionally a window.
|
46
|
+
#
|
47
|
+
# @param [Object] target the object that will execute the code when
|
48
|
+
# the button events have fired have been triggered.
|
49
|
+
# @param [Window] window the window of the game. This parameter is
|
50
|
+
# optional and only required if the events are interested in buttons
|
51
|
+
# being held.
|
52
|
+
#
|
53
|
+
def initialize(target,window = nil)
|
9
54
|
@target = target
|
10
55
|
@window = window
|
11
|
-
@up_actions ||=
|
12
|
-
@down_actions ||=
|
13
|
-
@held_actions ||=
|
56
|
+
@up_actions ||= {}
|
57
|
+
@down_actions ||= {}
|
58
|
+
@held_actions ||= {}
|
14
59
|
end
|
15
60
|
|
16
|
-
|
17
|
-
options = (args.last.is_a?(Hash) ? args.pop : {})
|
61
|
+
attr_reader :target, :window
|
18
62
|
|
19
|
-
|
20
|
-
|
21
|
-
|
63
|
+
#
|
64
|
+
# Register for a button_down event. These events are fired when
|
65
|
+
# the button is pressed down. This event only fires once when the
|
66
|
+
# button moves from the not pressed to the down state.
|
67
|
+
#
|
68
|
+
# @example Registering for a button down event to call a method named 'previous_option'
|
69
|
+
#
|
70
|
+
# class ExampleScene
|
71
|
+
# def events(e)
|
72
|
+
# e.on_down Gosu::GpLeft, Gosu::GpUp, do: :previous_option
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# def previous_option
|
76
|
+
# @selected_index = @selected_index - 1
|
77
|
+
# @selected_index = options.length - 1 if @selected_index <= -1
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# Here in this scene if the GpLeft or GpUp buttons are pressed down the method
|
82
|
+
# `previous_options` will be executed.
|
83
|
+
#
|
84
|
+
#
|
85
|
+
# @example Registering for a button down event with a block of code to execute
|
86
|
+
#
|
87
|
+
# class ExampleScene
|
88
|
+
# def events(e)
|
89
|
+
# e.on_down Gosu::GpLeft, Gosu::GpUp do
|
90
|
+
# @selected_index = @selected_index - 1
|
91
|
+
# @selected_index = options.length - 1 if @selected_index <= -1
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# This example uses a block instead of a method name but it is absolultey the same
|
97
|
+
# as the last example.
|
98
|
+
#
|
99
|
+
def on_down(*args,&block)
|
100
|
+
_on(@down_actions,args,block)
|
22
101
|
end
|
23
102
|
|
103
|
+
#
|
104
|
+
# Register for a button_up event. These events are fired when
|
105
|
+
# the button is released (from being pressed down). This event only fires
|
106
|
+
# once when the button moves from the pressed state to the up state.
|
107
|
+
#
|
108
|
+
# @example Registering for a button down event to call a method named 'next_option'
|
109
|
+
#
|
110
|
+
# class ExampleScene
|
111
|
+
# def events(e)
|
112
|
+
# e.on_up Gosu::KbEscape, do: :leave_scene
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# def leave_scene
|
116
|
+
# transition_to :title
|
117
|
+
# end
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# Here in this scene if the Escape Key is pressed and released the example scene
|
121
|
+
# will transition to the title scene.
|
122
|
+
#
|
123
|
+
# @example Registering for a button up event with a block of code to execute
|
124
|
+
#
|
125
|
+
# class ExampleScene
|
126
|
+
# def events(e)
|
127
|
+
# e.on_up Gosu::KbEscape do
|
128
|
+
# transition_to :title
|
129
|
+
# end
|
130
|
+
# end
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# This example uses a block instead of a method name but it is absolultey the same
|
134
|
+
# as the last example.
|
135
|
+
#
|
24
136
|
def on_up(*args,&block)
|
25
|
-
|
137
|
+
_on(@up_actions,args,block)
|
26
138
|
end
|
27
139
|
|
28
|
-
|
29
|
-
|
140
|
+
#
|
141
|
+
# Register for a button_held event. These events are fired when
|
142
|
+
# the button is currently in the downstate. This event continues to fire at the
|
143
|
+
# beginning of every update of a scene until the button is released.
|
144
|
+
#
|
145
|
+
# @note button_held events require that the window be specified during initialization.
|
146
|
+
#
|
147
|
+
# @example Registering for button held events
|
148
|
+
#
|
149
|
+
# class ExampleScene
|
150
|
+
# def events(e)
|
151
|
+
# e.on_hold Gosu::KbLeft, Gosu::GpLeft do
|
152
|
+
# player.turn_left
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
# e.on_hold Gosu::KbRight, Gosu::GpRight do
|
156
|
+
# player.turn_right
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# e.on_hold Gosu::KbUp, Gosu::GpButton0, do: :calculate_accleration
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
# def calculate_acceleration
|
163
|
+
# long_complicated_calculated_result = 0
|
164
|
+
# # ... multi-line calculations to determine the player acceleration ...
|
165
|
+
# player.accelerate = long_complicated_calculated_result
|
166
|
+
# end
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
def on_hold(*args,&block)
|
170
|
+
log.warn "Registering for a on_hold event requires that a window be provided." unless window
|
171
|
+
_on(@held_actions,args,block)
|
30
172
|
end
|
31
173
|
|
32
|
-
|
33
|
-
|
174
|
+
attr_reader :up_actions, :down_actions, :held_actions
|
175
|
+
|
176
|
+
def _on(hash,args,block)
|
177
|
+
options = (args.last.is_a?(Hash) ? args.pop : {})
|
178
|
+
|
179
|
+
args.each do |keystroke|
|
180
|
+
hash[keystroke] = block || lambda { |instance| send(options[:do]) }
|
181
|
+
end
|
34
182
|
end
|
35
183
|
|
184
|
+
#
|
185
|
+
# This is called by external or parent source of events, usually a Scene, when a button up event
|
186
|
+
# has been triggered.
|
187
|
+
#
|
36
188
|
def button_up(id)
|
37
|
-
|
38
|
-
|
189
|
+
target.instance_eval( &up_action(id) )
|
190
|
+
end
|
191
|
+
|
192
|
+
#
|
193
|
+
# This is called by external or parent source of events, usually a Scene, when a button down
|
194
|
+
# event has been triggered.
|
195
|
+
#
|
196
|
+
def button_down(id)
|
197
|
+
target.instance_eval( &down_action(id) )
|
39
198
|
end
|
40
199
|
|
41
|
-
|
200
|
+
#
|
201
|
+
# Fire the events mapped to the held buttons within the context
|
202
|
+
# of the specified target. This method is differently formatted because held buttons are not
|
203
|
+
# events but polling to see if the button is still being held.
|
204
|
+
#
|
205
|
+
def fire_events_for_held_buttons
|
42
206
|
held_actions.each do |key,action|
|
43
|
-
target.instance_eval(&action) if window.button_down?(key)
|
207
|
+
target.instance_eval(&action) if window and window.button_down?(key)
|
44
208
|
end
|
45
209
|
end
|
46
210
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
211
|
+
# @return a block of code that is mapped for the 'button_up' id or a block that will attempt to call out
|
212
|
+
# to the action missing method.
|
213
|
+
def up_action(id)
|
214
|
+
up_actions[id] || lambda {|instance| send(:up_action_missing,id) if respond_to?(:up_action_missing) }
|
53
215
|
end
|
54
216
|
|
217
|
+
# @return a block of code that is mapped for the 'button_down' id or a block that will attempt to call out
|
218
|
+
# to the action missing method.
|
219
|
+
def down_action(id)
|
220
|
+
down_actions[id] || lambda {|instance| send(:down_action_missing,id) if respond_to?(:down_action_missing) }
|
221
|
+
end
|
222
|
+
|
223
|
+
|
55
224
|
end
|
56
225
|
end
|
data/lib/metro/game/dsl.rb
CHANGED
@@ -9,7 +9,7 @@ module Metro
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def first_scene(scene_name = nil)
|
12
|
-
scene_name ? @first_scene =
|
12
|
+
scene_name ? @first_scene = scene_name : @first_scene
|
13
13
|
end
|
14
14
|
|
15
15
|
def width(game_width = nil)
|
@@ -24,6 +24,10 @@ module Metro
|
|
24
24
|
[ width(w), height(h) ]
|
25
25
|
end
|
26
26
|
|
27
|
+
def fullscreen(set_fullscreen = nil)
|
28
|
+
set_fullscreen.nil? ? @fullscreen : @fullscreen = set_fullscreen
|
29
|
+
end
|
30
|
+
|
27
31
|
end
|
28
32
|
end
|
29
33
|
end
|
data/lib/metro/game.rb
CHANGED
data/lib/metro/scene.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require_relative 'scene_view/scene_view'
|
2
|
-
require_relative 'scene_view/components/drawer'
|
3
2
|
require_relative 'event_relay'
|
4
3
|
|
5
4
|
module Metro
|
@@ -21,133 +20,148 @@ module Metro
|
|
21
20
|
class Scene
|
22
21
|
|
23
22
|
#
|
24
|
-
# The
|
25
|
-
#
|
26
|
-
# obfuscating.
|
23
|
+
# The events method is where a scene has access to configure the events that it
|
24
|
+
# would like to listen for during the scene.
|
27
25
|
#
|
28
|
-
# @
|
29
|
-
# @see Gosu::Window
|
26
|
+
# @note This method should be implemented in the Scene subclass.
|
30
27
|
#
|
31
|
-
|
28
|
+
# @param [EventRelay] e is the EventRelay that you can register for button up,
|
29
|
+
# button down, or button held events.
|
30
|
+
#
|
31
|
+
# @see EventRelay
|
32
|
+
#
|
33
|
+
def events(e) ; end
|
32
34
|
|
33
35
|
#
|
34
|
-
#
|
35
|
-
# all the gamepad and keyboard events defined.
|
36
|
+
# This method is called right after the scene has been adopted by the window
|
36
37
|
#
|
37
|
-
# @
|
38
|
+
# @note This method should be implemented in the Scene subclass.
|
38
39
|
#
|
39
|
-
|
40
|
+
def show ; end
|
40
41
|
|
41
42
|
#
|
42
|
-
#
|
43
|
-
# view_drawer.
|
43
|
+
# This is called every update interval while the window is being shown.
|
44
44
|
#
|
45
|
-
# @
|
45
|
+
# @note This method should be implemented in the Scene subclass.
|
46
46
|
#
|
47
|
-
|
47
|
+
def update ; end
|
48
48
|
|
49
49
|
#
|
50
|
-
#
|
50
|
+
# This is called after every {#update} and when the OS wants the window to
|
51
|
+
# repaint itself.
|
51
52
|
#
|
52
|
-
|
53
|
-
|
54
|
-
end
|
53
|
+
# @note This method should be implemented in the Scene subclass.
|
54
|
+
#
|
55
|
+
def draw ; end
|
55
56
|
|
56
57
|
#
|
57
|
-
#
|
58
|
-
#
|
58
|
+
# Before a scene is transisitioned away from to a new scene, this method is called
|
59
|
+
# to allow for the scene to complete any taskss, stop any actions, or pass any
|
60
|
+
# information from the existing scene to the scene that is about to replace it.
|
59
61
|
#
|
60
|
-
# @
|
62
|
+
# @note This method should be implemented in the Scene subclass.
|
61
63
|
#
|
62
|
-
|
63
|
-
|
64
|
-
|
64
|
+
# @param [Scene] new_scene this is the instance of the scene that is about to replace
|
65
|
+
# the current scene.
|
66
|
+
#
|
67
|
+
def prepare_transition(new_scene) ; end
|
65
68
|
|
66
|
-
#
|
67
|
-
|
69
|
+
#
|
70
|
+
# The window is the main instance of the game. Using window can access a lot of
|
71
|
+
# underlying Metro::Window, a subclass of Gosu::Window, that the Scene class is
|
72
|
+
# obfuscating.
|
73
|
+
#
|
74
|
+
# @see Metro::Window
|
75
|
+
# @see Gosu::Window
|
76
|
+
#
|
77
|
+
attr_reader :window
|
68
78
|
|
69
79
|
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
# that allow for the subclasses of Scene to be setup correctly.
|
80
|
+
# Setting the window places the scene within in the specified window. Which
|
81
|
+
# will cause a number of variables and settings to be set up. The {#show}
|
82
|
+
# method is called after the window has been set.
|
74
83
|
#
|
75
|
-
def
|
84
|
+
def window=(window)
|
76
85
|
@window = window
|
77
86
|
|
78
|
-
@event_relays
|
87
|
+
@event_relays = []
|
79
88
|
|
80
89
|
@scene_events = EventRelay.new(self,window)
|
81
90
|
events(@scene_events)
|
82
91
|
|
83
92
|
@event_relays << @scene_events
|
84
93
|
|
85
|
-
@view_drawer = SceneView::Drawer.new(self)
|
86
|
-
|
87
94
|
show
|
88
95
|
end
|
89
96
|
|
90
97
|
#
|
91
|
-
#
|
98
|
+
# Allows you to set or retrieve the scene name for the Scene.
|
92
99
|
#
|
93
|
-
# @
|
100
|
+
# @example Retrieving the default scene name
|
94
101
|
#
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
end
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
102
|
+
# class ExampleScene
|
103
|
+
# def show
|
104
|
+
# puts "Showing Scene: #{self.class.scene_name}"
|
105
|
+
# end
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# ExampleScene.scene_name
|
109
|
+
#
|
110
|
+
# @example Setting a custom name for the Scene
|
111
|
+
#
|
112
|
+
# class RollingCreditsScene
|
113
|
+
# scene_name "credits"
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# @param [String] scene_name when specified it will set the scene name for the class
|
117
|
+
# to the value specified.
|
118
|
+
#
|
119
|
+
# @return the String name of the scene which it can be used as a reference for transitioning
|
120
|
+
# or for generating the appropriate view information.
|
121
|
+
#
|
122
|
+
def self.scene_name(scene_name=nil)
|
123
|
+
@scene_name ||= to_s[/^(.+)Scene$/,1].downcase
|
124
|
+
scene_name ? @scene_name = scene_name.to_s : @scene_name
|
111
125
|
end
|
112
126
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
127
|
+
#
|
128
|
+
# @return the string representation of a scene, this is used for debugging.
|
129
|
+
#
|
130
|
+
def to_s
|
131
|
+
"[SCENE: #{self.class.scene_name}(#{self.class})]"
|
117
132
|
end
|
118
133
|
|
119
134
|
#
|
120
|
-
#
|
121
|
-
# for button up and button down
|
135
|
+
# Captures all classes that subclass Scene.
|
122
136
|
#
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
137
|
+
# @see #self.scenes
|
138
|
+
#
|
139
|
+
def self.inherited(base)
|
140
|
+
scenes << base
|
141
|
+
end
|
127
142
|
|
128
143
|
#
|
129
|
-
#
|
144
|
+
# All subclasses of Scene, this should be all the defined scenes within the game.
|
130
145
|
#
|
131
|
-
# @
|
146
|
+
# @return an Array of Scene subclasses
|
132
147
|
#
|
133
|
-
def
|
148
|
+
def self.scenes
|
149
|
+
@scenes ||= []
|
150
|
+
end
|
134
151
|
|
135
152
|
#
|
136
|
-
# The `
|
153
|
+
# The `base_draw` method is called by the Game Window. This is allow for any special
|
137
154
|
# drawing needs to be handled before calling the traditional `draw` method defined
|
138
|
-
# in the subclassed
|
155
|
+
# in the subclassed Scene.
|
139
156
|
#
|
140
|
-
def
|
141
|
-
view_drawer.draw(view)
|
157
|
+
def base_draw
|
142
158
|
draw
|
143
159
|
end
|
144
160
|
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
|
149
|
-
#
|
150
|
-
def draw ; end
|
161
|
+
# This provides the functionality for view handling.
|
162
|
+
# @note the inclusion of view functionality redefines {#base_draw} so it must proceed
|
163
|
+
# the declaration of that method.
|
164
|
+
include SceneView
|
151
165
|
|
152
166
|
#
|
153
167
|
# `transition_to` performs the work of transitioning this scene
|
@@ -157,7 +171,7 @@ module Metro
|
|
157
171
|
# the class or a string/symbol representation of the shortened scene name.
|
158
172
|
#
|
159
173
|
def transition_to(scene_name)
|
160
|
-
new_scene = Scenes.
|
174
|
+
new_scene = Scenes.generate(scene_name)
|
161
175
|
_prepare_transition(new_scene)
|
162
176
|
window.scene = new_scene
|
163
177
|
end
|
@@ -177,16 +191,55 @@ module Metro
|
|
177
191
|
end
|
178
192
|
|
179
193
|
#
|
180
|
-
#
|
181
|
-
#
|
182
|
-
#
|
194
|
+
# The events object that is configured through the {#events} method, which stores
|
195
|
+
# all the gamepad and keyboard events defined. By default a scene has an event
|
196
|
+
# relay defined. Additional relays can be defined based on the components added.
|
183
197
|
#
|
184
|
-
# @
|
198
|
+
# @see Events
|
199
|
+
# @see #add_event_relay
|
185
200
|
#
|
186
|
-
|
187
|
-
|
201
|
+
attr_reader :event_relays
|
202
|
+
|
188
203
|
#
|
189
|
-
|
204
|
+
# Add an additional event relay to the list of event relays. It is appended
|
205
|
+
# to the end of the list of relays.
|
206
|
+
#
|
207
|
+
# @param [EventRelay] event_relay an event relay instance that will now
|
208
|
+
# receive events generated from this scene.
|
209
|
+
#
|
210
|
+
def add_event_relay(event_relay)
|
211
|
+
@event_relays << event_relay
|
212
|
+
end
|
213
|
+
|
214
|
+
#
|
215
|
+
# This method is called during a scene update and will fire all the events
|
216
|
+
# that have been defined for all held buttons for all defined event relays.
|
217
|
+
#
|
218
|
+
def fire_events_for_held_buttons
|
219
|
+
event_relays.each do |relay|
|
220
|
+
relay.fire_events_for_held_buttons
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
#
|
225
|
+
# This method is called before a scene update and passes the button up events
|
226
|
+
# to each of the defined event relays.
|
227
|
+
#
|
228
|
+
def button_up(id)
|
229
|
+
event_relays.each do |relay|
|
230
|
+
relay.button_up(id)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
#
|
235
|
+
# This method is called before a scene update and passes the button down events
|
236
|
+
# to each of the defined event relays.
|
237
|
+
#
|
238
|
+
def button_down(id)
|
239
|
+
event_relays.each do |relay|
|
240
|
+
relay.button_down(id)
|
241
|
+
end
|
242
|
+
end
|
190
243
|
|
191
244
|
end
|
192
245
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Metro
|
2
|
+
module SceneView
|
3
|
+
|
4
|
+
#
|
5
|
+
# This Drawer draws nothing. This is a nod to the age old struggle that
|
6
|
+
# as artists we struggle with the impetus and ability to convey a message
|
7
|
+
# but simply lack the message.
|
8
|
+
#
|
9
|
+
# It is the fallback drawer when no suitable drawer can be found.
|
10
|
+
#
|
11
|
+
class ArtistsBlock < Drawer
|
12
|
+
def self.draw(view)
|
13
|
+
# log.warn "The component #{view['type']} does not have a supported drawer."
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|