shattered 0.4.0.1 → 0.5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/lib/game_loader.rb +89 -8
  2. data/lib/rails_generator.rb +1 -1
  3. data/lib/rails_generator/base.rb +3 -3
  4. data/lib/rails_generator/commands.rb +91 -17
  5. data/lib/rails_generator/generators/applications/shattered_app/shattered_app_generator.rb +12 -12
  6. data/lib/rails_generator/generators/components/state/templates/state.rb +17 -0
  7. data/lib/rails_generator/generators/components/view/templates/view.rb +5 -2
  8. data/lib/rails_generator/lookup.rb +18 -17
  9. data/lib/rails_generator/manifest.rb +1 -1
  10. data/lib/rails_generator/options.rb +18 -10
  11. data/lib/rails_generator/scripts.rb +4 -4
  12. data/lib/rails_generator/simple_logger.rb +2 -2
  13. data/lib/rails_generator/spec.rb +1 -1
  14. data/lib/shatter.rb +1 -1
  15. data/lib/tasks/documentation.rake +46 -0
  16. data/lib/tasks/framework.rake +84 -0
  17. data/lib/tasks/log.rake +9 -0
  18. data/lib/tasks/misc.rake +4 -0
  19. data/lib/tasks/pre_namespace_aliases.rake +28 -0
  20. data/lib/tasks/shattered.rb +6 -0
  21. data/lib/tasks/statistics.rake +17 -0
  22. data/lib/tasks/testing.rake +102 -0
  23. data/lib/templates/Rakefile +4 -8
  24. data/lib/templates/configs/ogre_plugins.windows.cfg +14 -0
  25. data/lib/templates/environments/environment.rb +5 -2
  26. metadata +44 -53
  27. data/lib/templates/configs/Mac/shattered.app/Contents/Info.plist +0 -22
  28. data/lib/templates/configs/Mac/shattered.app/Contents/MacOS/shattered_mac +0 -0
  29. data/lib/templates/configs/Mac/shattered.app/Contents/PkgInfo +0 -1
  30. data/lib/templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/InfoPlist.strings +0 -0
  31. data/lib/templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/classes.nib +0 -4
  32. data/lib/templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/info.nib +0 -20
  33. data/lib/templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/objects.nib +0 -0
  34. data/lib/templates/configs/Mac/shattered.app/Contents/Resources/rb_main.rb +0 -3
  35. data/lib/templates/configs/Mac/shattered.app/Contents/pbdevelopment.plist +0 -8
  36. data/lib/templates/configs/Mac/shattered.app/OgreLeaks.log +0 -144
  37. data/lib/templates/configs/Mac/shattered.app/OgreMemory.log +0 -29
  38. data/lib/templates/configs/ogre_plugins.rcfg +0 -16
@@ -10,6 +10,8 @@ module Shatter #:nodoc:all
10
10
  class GameLoader
11
11
  include Singleton
12
12
  attr_writer :environment
13
+ attr_reader :media_paths, :render_window, :input_manager, :key_manager, :key_converter
14
+ attr_accessor :current_state
13
15
 
14
16
  # This will recourse into the app/** directories and load all ruby files
15
17
  # inside those directories.
@@ -18,20 +20,99 @@ class GameLoader
18
20
  require(file)
19
21
  end
20
22
  end
23
+
24
+ # start the game
21
25
  def run
22
- load_environment
23
26
  load_all_sources(SHATTERED_ROOT)
27
+ load_environment
24
28
 
25
- eval("#{@environment[:start_state].to_s.camelize}State").new
29
+ # Create our initial state, as defined by the environment.
30
+ create_state(@environment[:start_state])
26
31
 
27
- @control.start_game(@environment)
32
+ start_game
33
+ end
34
+
35
+ # Create a state from the given name
36
+ # :sample creates a new SampleState object
37
+ def create_state(state_name)
38
+ state_class = eval("#{state_name.to_s.camelize}State")
39
+ raise Error, "#{state_class} is not a class" unless state_class.is_a? Class
40
+ state = state_class.new
41
+ unless state.is_a? ShatteredState::Base
42
+ raise Error, "#{state_class} is an invalid State object (not of ShatteredState::Base)"
43
+ end
44
+ return state
28
45
  end
46
+
29
47
  def load_environment
30
- view = ShatteredView::Runner.new @environment
31
- view.add_to_environment @environment
32
- @control = ShatteredState::Runner.new(@environment)
33
- ShatteredPack::Configuration.environment=@environment
34
- return @environment
48
+ #Setup Ogre and the scene for the state
49
+ raise Error, "Ogre failed to initialize" if !setup_ogre
50
+ setup_input
51
+
52
+ load_resources(@environment[:media])
53
+ end
54
+
55
+ # Given ['app/media', 'media'], searches those directories, recursively, for OGRE media
56
+ def load_resources(paths)
57
+ @media_paths = paths
58
+ # setup our resource paths specified in environment.rb
59
+ Resources.instance.add_resource_paths(*paths)
60
+ Resources.instance.setup
61
+ end
62
+
63
+ #Load the root, setup the render window
64
+ #TODO: allow for the user to specify whether the window dialogue pops up
65
+ #further TODO: allow the user to skin the render window dialogue
66
+ def setup_ogre
67
+ # TODO: create platform loader for other platforms
68
+ plugins = SHATTERED_ROOT + "/config/ogre_plugins.windows.cfg"
69
+ config_save=SHATTERED_ROOT + "/config/ogrerb_defaults.save"
70
+ log=SHATTERED_ROOT + "/log/ogrerb.log"
71
+ @root = ShatteredOgre.create_root(plugins, config_save, log)
72
+ return false if !@root.show_config_dialog
73
+ # TODO: allow application name to be set.
74
+ @render_window = @root.initialise(true)
75
+
76
+ return true
77
+ end
78
+
79
+ #Every time this exits, a game dies.
80
+ def start_game
81
+ each_frame do |time_elapsed|
82
+ current_state.update_timers(time_elapsed)
83
+ @keyboard.capture
84
+ #@@environment[:input].flush
85
+ end
86
+ end
87
+
88
+ # Main game loop
89
+ def each_frame
90
+ timer = Ogre::Timer.new
91
+ while !@environment[:quit] && Ogre::Root::instance.render_one_frame
92
+ seconds = timer.get_microseconds / 1000000.0
93
+ yield seconds
94
+ timer.reset
95
+ end
96
+ end
97
+
98
+ # Leave the game
99
+ def quit!
100
+ @environment[:quit]=true
101
+ end
102
+
103
+ # load the input manager, the key manager, etc
104
+ # TODO: Consider how to make input non-exclusive, as well as mouse, etc.
105
+ # TODO: Investigate any use cases for non-buffered input
106
+ def setup_input
107
+ windowHnd = render_window.get_custom_attribute_unsigned_long("WINDOW")
108
+ @input_manager = OIS::InputManager.create_input_system(
109
+ { "WINDOW" => "#{windowHnd}",
110
+ "w32_mouse" => ["DISCL_FOREGROUND", "DISCL_NONEXCLUSIVE"],
111
+ "w32_keyboard" => ["DISCL_FOREGROUND", "DISCL_NONEXCLUSIVE"]
112
+ })
113
+ @keyboard = @input_manager.create_input_object(OIS::OISKeyboard, true)
114
+ @key_manager = OIS::KeyManager.new(@keyboard)
115
+ @key_converter = ShatteredPack::KeyConverter.new(@key_manager)
35
116
  end
36
117
  end
37
118
  end
@@ -25,7 +25,7 @@ $:.unshift(File.dirname(__FILE__))
25
25
  $:.unshift(File.dirname(__FILE__) + "/../../shattered_support/lib")
26
26
 
27
27
  begin
28
- require 'shattered_support'
28
+ require 'shattered_support'
29
29
  rescue LoadError
30
30
  require 'rubygems'
31
31
  require_gem 'shattered_support'
@@ -14,7 +14,7 @@ require File.dirname(__FILE__) + '/spec'
14
14
  # generator and just replaces the code templates with its own.
15
15
  #
16
16
  # Now go forth and multiply^Wgenerate.
17
- module Rails #:nodoc:all
17
+ module Rails
18
18
  module Generator
19
19
  class GeneratorError < StandardError; end
20
20
  class UsageError < GeneratorError; end
@@ -144,10 +144,9 @@ module Rails #:nodoc:all
144
144
  #
145
145
  # See Rails::Generator::Base for a discussion of Manifests and Commands.
146
146
  class NamedBase < Base
147
- attr_reader :name, :class_name, :singular_name, :plural_name
147
+ attr_reader :name, :class_name, :singular_name, :plural_name, :table_name
148
148
  attr_reader :class_path, :file_path, :class_nesting, :class_nesting_depth
149
149
  alias_method :file_name, :singular_name
150
- alias_method :table_name, :plural_name
151
150
  alias_method :actions, :args
152
151
 
153
152
  def initialize(runtime_args, runtime_options = {})
@@ -172,6 +171,7 @@ module Rails #:nodoc:all
172
171
  @name = name
173
172
  base_name, @class_path, @file_path, @class_nesting, @class_nesting_depth = extract_modules(@name)
174
173
  @class_name_without_nesting, @singular_name, @plural_name = inflect_names(base_name)
174
+ @table_name = singular_name
175
175
  if @class_nesting.empty?
176
176
  @class_name = @class_name_without_nesting
177
177
  else
@@ -3,7 +3,7 @@ require 'optparse'
3
3
  require 'fileutils'
4
4
  require 'erb'
5
5
 
6
- module Rails #:nodoc:all
6
+ module Rails
7
7
  module Generator
8
8
  module Commands
9
9
  # Here's a convenient way to get a handle on generator commands.
@@ -16,7 +16,7 @@ module Rails #:nodoc:all
16
16
  # Even more convenient access to commands. Include Commands in
17
17
  # the generator Base class to get a nice #command instance method
18
18
  # which returns a delegate for the requested command.
19
- def self.append_features(base)
19
+ def self.included(base)
20
20
  base.send(:define_method, :command) do |command|
21
21
  Commands.instance(command, self)
22
22
  end
@@ -55,6 +55,34 @@ module Rails #:nodoc:all
55
55
  def readme(*args)
56
56
  end
57
57
 
58
+ protected
59
+ def migration_directory(relative_path)
60
+ directory(@migration_directory = relative_path)
61
+ end
62
+
63
+ def existing_migrations(file_name)
64
+ Dir.glob("#{@migration_directory}/[0-9]*_*.rb").grep(/[0-9]+_#{file_name}.rb$/)
65
+ end
66
+
67
+ def migration_exists?(file_name)
68
+ not existing_migrations(file_name).empty?
69
+ end
70
+
71
+ def current_migration_number
72
+ Dir.glob("#{@migration_directory}/[0-9]*.rb").inject(0) do |max, file_path|
73
+ n = File.basename(file_path).split('_', 2).first.to_i
74
+ if n > max then n else max end
75
+ end
76
+ end
77
+
78
+ def next_migration_number
79
+ current_migration_number + 1
80
+ end
81
+
82
+ def next_migration_string(padding = 3)
83
+ "%.#{padding}d" % next_migration_number
84
+ end
85
+
58
86
  private
59
87
  # Ask the user interactively whether to force collision.
60
88
  def force_file_collision?(destination)
@@ -84,10 +112,10 @@ module Rails #:nodoc:all
84
112
  begin_mark = template_part_mark(template_options[:begin_mark], template_options[:mark_id])
85
113
  end_mark = template_part_mark(template_options[:end_mark], template_options[:mark_id])
86
114
  begin_mark + rendered_part + end_mark
87
- end
115
+ end
88
116
 
89
- def template_part_mark(name, id)
90
- "<!--[#{name}:#{id}]-->\n"
117
+ def template_part_mark(name, id)
118
+ "<!--[#{name}:#{id}]-->\n"
91
119
  end
92
120
  end
93
121
 
@@ -135,26 +163,34 @@ module Rails #:nodoc:all
135
163
 
136
164
  # Copy a file from source to destination with collision checking.
137
165
  #
138
- # The file_options hash accepts :chmod and :shebang options.
166
+ # The file_options hash accepts :chmod and :shebang and :collision options.
139
167
  # :chmod sets the permissions of the destination file:
140
168
  # file 'config/empty.log', 'log/test.log', :chmod => 0664
141
169
  # :shebang sets the #!/usr/bin/ruby line for scripts
142
170
  # file 'bin/generate.rb', 'script/generate', :chmod => 0755, :shebang => '/usr/bin/env ruby'
171
+ # :collision sets the collision option only for the destination file:
172
+ # file 'settings/server.yml', 'config/server.yml', :collision => :skip
143
173
  #
144
174
  # Collisions are handled by checking whether the destination file
145
175
  # exists and either skipping the file, forcing overwrite, or asking
146
176
  # the user what to do.
147
- def file(relative_source, relative_destination, file_options = {})
177
+ def file(relative_source, relative_destination, file_options = {}, &block)
148
178
  # Determine full paths for source and destination files.
149
- source = source_path(relative_source)
150
- destination = destination_path(relative_destination)
179
+ source = source_path(relative_source)
180
+ destination = destination_path(relative_destination)
181
+ destination_exists = File.exists?(destination)
182
+
183
+ # If source and destination are identical then we're done.
184
+ if destination_exists and identical?(source, destination, &block)
185
+ return logger.identical(relative_destination)
186
+ end
151
187
 
152
188
  # Check for and resolve file collisions.
153
- if File.exists?(destination)
189
+ if destination_exists
154
190
 
155
191
  # Make a choice whether to overwrite the file. :force and
156
192
  # :skip already have their mind made up, but give :ask a shot.
157
- choice = case options[:collision].to_sym #|| :ask
193
+ choice = case (file_options[:collision] || options[:collision]).to_sym #|| :ask
158
194
  when :ask then force_file_collision?(relative_destination)
159
195
  when :force then :force
160
196
  when :skip then :skip
@@ -181,17 +217,16 @@ module Rails #:nodoc:all
181
217
  # if block given so templaters may render the source file. If a
182
218
  # shebang is requested, replace the existing shebang or insert a
183
219
  # new one.
184
- File.open(destination, 'w') do |df|
185
- File.open(source) do |sf|
220
+ File.open(destination, 'wb') do |df|
221
+ File.open(source, 'rb') do |sf|
186
222
  if block_given?
187
223
  df.write(yield(sf))
188
224
  else
189
- line = sf.gets
190
225
  if file_options[:shebang]
191
226
  df.puts("#!#{file_options[:shebang]}")
192
- df.puts(line) if line !~ /^#!/
193
- else
194
- df.puts(line)
227
+ if line = sf.gets
228
+ df.puts(line) if line !~ /^#!/
229
+ end
195
230
  end
196
231
  df.write(sf.read)
197
232
  end
@@ -207,6 +242,16 @@ module Rails #:nodoc:all
207
242
  system("svn add #{destination}") if options[:svn]
208
243
  end
209
244
 
245
+ # Checks if the source and the destination file are identical. If
246
+ # passed a block then the source file is a template that needs to first
247
+ # be evaluated before being compared to the destination.
248
+ def identical?(source, destination, &block)
249
+ return false if File.directory? destination
250
+ source = block_given? ? File.open(source) {|sf| yield(sf)} : IO.read(source)
251
+ destination = IO.read(destination)
252
+ source == destination
253
+ end
254
+
210
255
  # Generate a file for a Rails application using an ERuby template.
211
256
  # Looks up and evalutes a template by name and writes the result.
212
257
  #
@@ -263,6 +308,14 @@ module Rails #:nodoc:all
263
308
  end
264
309
  end
265
310
 
311
+ # When creating a migration, it knows to find the first available file in db/migrate and use the migration.rb template.
312
+ def migration_template(relative_source, relative_destination, template_options = {})
313
+ migration_directory relative_destination
314
+ migration_file_name = template_options[:migration_file_name] || file_name
315
+ raise "Another migration is already named #{migration_file_name}: #{existing_migrations(migration_file_name).first}" if migration_exists?(migration_file_name)
316
+ template(relative_source, "#{relative_destination}/#{next_migration_string}_#{migration_file_name}.rb", template_options)
317
+ end
318
+
266
319
  private
267
320
  # Raise a usage error with an informative WordNet suggestion.
268
321
  # Thanks to Florian Gross (flgr).
@@ -369,6 +422,22 @@ end_message
369
422
  def complex_template(*args)
370
423
  # nothing should be done here
371
424
  end
425
+
426
+ # When deleting a migration, it knows to delete every file named "[0-9]*_#{file_name}".
427
+ def migration_template(relative_source, relative_destination, template_options = {})
428
+ migration_directory relative_destination
429
+
430
+ migration_file_name = template_options[:migration_file_name] || file_name
431
+ unless migration_exists?(migration_file_name)
432
+ puts "There is no migration named #{migration_file_name}"
433
+ return
434
+ end
435
+
436
+
437
+ existing_migrations(migration_file_name).each do |file_path|
438
+ file(relative_source, file_path, template_options)
439
+ end
440
+ end
372
441
  end
373
442
 
374
443
 
@@ -401,6 +470,11 @@ end_message
401
470
  def readme(*args)
402
471
  logger.readme args.join(', ')
403
472
  end
473
+
474
+ def migration_template(relative_source, relative_destination, options = {})
475
+ migration_directory relative_destination
476
+ logger.migration_template file_name
477
+ end
404
478
  end
405
479
 
406
480
  # Update generator's action manifest.
@@ -26,7 +26,7 @@ class ShatteredAppGenerator < Rails::Generator::Base #:nodoc:all
26
26
  m.file "templates/README", "README"
27
27
 
28
28
  # ogre plugins and configuration
29
- m.file "templates/configs/ogre_plugins.rcfg", "config/ogre_plugins.rcfg"
29
+ m.file "templates/configs/ogre_plugins.windows.cfg", "config/ogre_plugins.windows.cfg"
30
30
  m.template "templates/configs/ogre.cfg", "config/ogre.cfg"
31
31
  m.template "templates/configs/boot.rb", "config/boot.rb"
32
32
 
@@ -37,15 +37,16 @@ class ShatteredAppGenerator < Rails::Generator::Base #:nodoc:all
37
37
  m.file "templates/test/test_helper.rb", "test/test_helper.rb"
38
38
 
39
39
  # Mac OSX
40
- m.file "templates/configs/Mac/shattered.app/Contents/Info.plist", "config/Mac/shattered.app/Contents/Info.plist"
41
- m.file "templates/configs/Mac/shattered.app/Contents/MacOS/shattered_mac", "config/Mac/shattered.app/Contents/MacOS/shattered_mac"
42
- m.file "templates/configs/Mac/shattered.app/Contents/pbdevelopment.plist", "config/Mac/shattered.app/Contents/pbdevelopment.plist"
43
- m.file "templates/configs/Mac/shattered.app/Contents/PkgInfo", "config/Mac/shattered.app/Contents/PkgInfo"
44
- m.file "templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/InfoPlist.strings", "config/Mac/shattered.app/Contents/Resources/English.lproj/InfoPlist.strings"
45
- m.file "templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/classes.nib", "config/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/classes.nib"
46
- m.file "templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/info.nib", "config/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/info.nib"
47
- m.file "templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/objects.nib", "config/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/objects.nib"
48
- m.file "templates/configs/Mac/shattered.app/Contents/Resources/rb_main.rb", "config/Mac/shattered.app/Contents/Resources/rb_main.rb"
40
+ # TODO: OSX support needs to be revisited.
41
+ #m.file "templates/configs/Mac/shattered.app/Contents/Info.plist", "config/Mac/shattered.app/Contents/Info.plist"
42
+ #m.file "templates/configs/Mac/shattered.app/Contents/MacOS/shattered_mac", "config/Mac/shattered.app/Contents/MacOS/shattered_mac"
43
+ #m.file "templates/configs/Mac/shattered.app/Contents/pbdevelopment.plist", "config/Mac/shattered.app/Contents/pbdevelopment.plist"
44
+ #m.file "templates/configs/Mac/shattered.app/Contents/PkgInfo", "config/Mac/shattered.app/Contents/PkgInfo"
45
+ #m.file "templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/InfoPlist.strings", "config/Mac/shattered.app/Contents/Resources/English.lproj/InfoPlist.strings"
46
+ #m.file "templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/classes.nib", "config/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/classes.nib"
47
+ #m.file "templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/info.nib", "config/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/info.nib"
48
+ #m.file "templates/configs/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/objects.nib", "config/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib/objects.nib"
49
+ #m.file "templates/configs/Mac/shattered.app/Contents/Resources/rb_main.rb", "config/Mac/shattered.app/Contents/Resources/rb_main.rb"
49
50
 
50
51
  # Scripts
51
52
  %w( generate runner console destroy ).each do |file|
@@ -91,9 +92,8 @@ class ShatteredAppGenerator < Rails::Generator::Base #:nodoc:all
91
92
  app/views
92
93
  app/media/common/programs
93
94
  app/media/common/templates
94
- config/Mac/shattered.app/Contents/MacOS
95
- config/Mac/shattered.app/Contents/Resources/English.lproj/MainMenu.nib
96
95
  doc
96
+ config
97
97
  log
98
98
  script
99
99
  test/unit
@@ -1,3 +1,20 @@
1
1
  class <%= class_name %>State < ShatteredState::Base
2
2
  key :pressed => :escape, :action => :quit
3
+
4
+ def initialize
5
+ # The different types of scene managers provided by Ogre are:
6
+ # :general
7
+ # :terrain
8
+ # :nature
9
+ # :paging
10
+ # :indoor
11
+ scene_manager = create_scene_manager :general
12
+
13
+ camera = scene_manager.create_camera("camera")
14
+ camera.position = v(0,0,-200)
15
+ camera.look_at v(0,0,0)
16
+
17
+ viewport = create_viewport(camera)
18
+ viewport.set_background_colour Ogre::ColourValue.new(0.8, 0.5, 0.5)
19
+ end
3
20
  end
@@ -1,4 +1,7 @@
1
1
  class <%= class_name %>View < ShatteredView::Base
2
- material "<%= file_name %>_material", :template => "basic", :texture => "<%= file_name %>.png"
3
- mesh "<%= file_name %>", :material => :<%= file_name %>_material
2
+ # View works by executing after any model event
3
+ # This initialize will work after the model's initialize
4
+ def initialize
5
+ mesh = create(:mesh, "<%= class_name %>")
6
+ end
4
7
  end
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/spec'
2
2
 
3
- class Object #:nodoc:all
3
+ class Object
4
4
  class << self
5
5
  # Lookup missing generators using const_missing. This allows any
6
6
  # generator to reference another without having to know its location:
@@ -21,23 +21,21 @@ class Object #:nodoc:all
21
21
  end
22
22
  end
23
23
 
24
- class Dir #:nodoc:all
25
- # User home directory lookup adapted from RubyGems.
26
- def self.user_home
27
- if ENV['HOME']
28
- ENV['HOME']
29
- elsif ENV['USERPROFILE']
30
- ENV['USERPROFILE']
31
- elsif ENV['HOMEDRIVE'] and ENV['HOMEPATH']
32
- "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
33
- else
34
- File.expand_path '~'
35
- end
24
+ # User home directory lookup adapted from RubyGems.
25
+ def Dir.user_home
26
+ if ENV['HOME']
27
+ ENV['HOME']
28
+ elsif ENV['USERPROFILE']
29
+ ENV['USERPROFILE']
30
+ elsif ENV['HOMEDRIVE'] and ENV['HOMEPATH']
31
+ "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
32
+ else
33
+ File.expand_path '~'
36
34
  end
37
35
  end
38
36
 
39
37
 
40
- module Rails #:nodoc:all
38
+ module Rails
41
39
  module Generator
42
40
 
43
41
  # Generator lookup is managed by a list of sources which return specs
@@ -50,8 +48,7 @@ module Rails #:nodoc:all
50
48
  # the generator and how to create it. A source is anything that
51
49
  # yields generators from #each. PathSource and GemSource are provided.
52
50
  module Lookup
53
- def self.append_features(base)
54
- super
51
+ def self.included(base)
55
52
  base.extend(ClassMethods)
56
53
  base.use_component_sources!
57
54
  end
@@ -100,7 +97,11 @@ module Rails #:nodoc:all
100
97
  # 4. Builtins. Model, controller, mailer, scaffold.
101
98
  def use_component_sources!
102
99
  reset_sources
103
- sources << PathSource.new(:app, "#{::SHATTERED_ROOT}/generators") if defined? ::SHATTERED_ROOT
100
+ if defined? ::SHATTERED_ROOT
101
+ sources << PathSource.new(:lib, "#{::SHATTERED_ROOT}/lib/generators")
102
+ sources << PathSource.new(:vendor, "#{::SHATTERED_ROOT}/vendor/generators")
103
+ sources << PathSource.new(:plugins, "#{::SHATTERED_ROOT}/vendor/plugins/**/generators")
104
+ end
104
105
  sources << PathSource.new(:user, "#{Dir.user_home}/.rails/generators")
105
106
  sources << GemSource.new if Object.const_defined?(:Gem)
106
107
  sources << PathSource.new(:builtin, "#{File.dirname(__FILE__)}/generators/components")