ruby-processing 1.0.8 → 1.0.9

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 (32) hide show
  1. data/CHANGELOG +6 -0
  2. data/lib/core/core.jar +0 -0
  3. data/lib/core/jruby-complete.jar +0 -0
  4. data/lib/ruby-processing.rb +5 -10
  5. data/lib/ruby-processing/app.rb +139 -98
  6. data/lib/ruby-processing/exporters/applet_exporter.rb +4 -1
  7. data/lib/ruby-processing/exporters/application_exporter.rb +5 -1
  8. data/lib/ruby-processing/exporters/base_exporter.rb +3 -2
  9. data/lib/ruby-processing/runner.rb +54 -46
  10. data/lib/ruby-processing/runners/base.rb +6 -7
  11. data/lib/ruby-processing/runners/live.rb +4 -3
  12. data/lib/ruby-processing/runners/watch.rb +33 -27
  13. data/library/control_panel/control_panel.rb +24 -23
  14. data/samples/anar/data/java_args.txt +1 -0
  15. data/samples/anar/extrusion.rb +49 -0
  16. data/samples/anar/l_system.rb +86 -0
  17. data/samples/anar/library/anar/anar.jar +0 -0
  18. data/samples/anar/many_shapes.rb +98 -0
  19. data/samples/empathy.rb +73 -0
  20. data/samples/gravity.rb +113 -0
  21. data/samples/peasy_cam/data/java_args.txt +1 -0
  22. data/samples/peasy_cam/hello_peasy.rb +29 -0
  23. data/samples/peasy_cam/hilbert_fractal.rb +40 -0
  24. data/samples/peasy_cam/library/PeasyCam/PeasyCam.jar +0 -0
  25. data/samples/peasy_cam/library/hilbert/hilbert.rb +99 -0
  26. data/samples/processing_app/3D/form/brick_tower.rb +3 -3
  27. data/samples/processing_app/basics/data/characters_strings/characters_strings.rb +5 -7
  28. data/samples/processing_app/basics/form/triangle_strip.rb +11 -11
  29. data/samples/processing_app/basics/input/keyboard.rb +2 -8
  30. data/samples/processing_app/basics/input/keyboard_2.rb +4 -4
  31. data/samples/processing_app/basics/input/keyboard_functions.rb +12 -21
  32. metadata +41 -64
@@ -40,7 +40,10 @@ module Processing
40
40
  @necessary_files = [@main_file_path]
41
41
  @necessary_files += Dir["#{RP5_ROOT}/lib/{*,**}"]
42
42
  @necessary_files += @real_requires
43
- @necessary_files << "#{@main_folder}/data" if File.exists?("#{@main_folder}/data")
43
+ NECESSARY_FOLDERS.each do |folder|
44
+ resource_path = File.join(@main_folder, folder)
45
+ @necessary_files << resource_path if File.exists?(resource_path)
46
+ end
44
47
  @necessary_files += Dir["#{RP5_ROOT}/lib/templates/applet/{*,**}"]
45
48
  @necessary_files += Dir.glob("library/{#{@libraries.join(",")}}") unless @libraries.empty?
46
49
  @necessary_files.uniq!
@@ -42,7 +42,10 @@ module Processing
42
42
  @necessary_files = [@main_file_path]
43
43
  @necessary_files += Dir["#{RP5_ROOT}/lib/{*,**}"]
44
44
  @necessary_files += @real_requires
45
- @necessary_files << "#{@main_folder}/data" if File.exists?("#{@main_folder}/data")
45
+ NECESSARY_FOLDERS.each do |folder|
46
+ resource_path = File.join(@main_folder, folder)
47
+ @necessary_files << resource_path if File.exists?(resource_path)
48
+ end
46
49
  @necessary_files.uniq!
47
50
  cp_r(@necessary_files, File.join(@dest, @prefix))
48
51
  cp_r(@libraries, File.join(@dest, @prefix, "library")) unless @libraries.empty?
@@ -66,6 +69,7 @@ module Processing
66
69
  move @dest + "/run.exe", "#{runnable}.exe"
67
70
  chmod 0755, runnable
68
71
  chmod 0755, "#{runnable}.exe"
72
+ chmod 0755, File.join(@dest, 'Contents', 'MacOS', 'JavaApplicationStub')
69
73
  end
70
74
 
71
75
  def symlink_library_into_place
@@ -10,6 +10,7 @@ module Processing
10
10
 
11
11
  DEFAULT_DIMENSIONS = {'width' => '100', 'height' => '100'}
12
12
  DEFAULT_DESCRIPTION = ''
13
+ NECESSARY_FOLDERS = ['data', 'lib', 'vendor']
13
14
 
14
15
  # Returns the filepath, basename, and directory name of the sketch.
15
16
  def get_main_file(file)
@@ -42,7 +43,7 @@ module Processing
42
43
 
43
44
  # Searches the source for a title.
44
45
  def extract_title(source)
45
- match = source.match(/#{@info[:class_name]}\.new.*?:title\s=>\s["'](.+)["']/m)
46
+ match = source.match(/#{@info[:class_name]}\.new.*?:title\s=>\s["'](.+?)["']/m)
46
47
  match ? match[1] : File.basename(@file, '.rb').titleize
47
48
  end
48
49
 
@@ -89,7 +90,7 @@ module Processing
89
90
  requirements = []
90
91
  partial_paths = []
91
92
  loop do
92
- matchdata = code.match(/^.*\b(require|load)\b.*$/)
93
+ matchdata = code.match(/^.*[^::\.\w](require|load)\b.*$/)
93
94
  break unless matchdata
94
95
  line = matchdata[0].gsub('__FILE__', "'#{@main_file_path}'")
95
96
  line = line.gsub(/\b(require|load)\b/, 'partial_paths << ')
@@ -2,45 +2,45 @@ require 'ostruct'
2
2
  require 'fileutils'
3
3
 
4
4
  module Processing
5
-
5
+
6
6
  # Utility class to handle the different commands that the 'rp5' command
7
7
  # offers. Able to run, watch, live, create, app, applet, and unpack
8
8
  class Runner
9
-
9
+
10
10
  HELP_MESSAGE = <<-EOS
11
-
11
+
12
12
  Ruby-Processing is a little shim between Processing and JRuby that helps
13
13
  you create sketches of code art.
14
-
14
+
15
15
  Usage:
16
16
  rp5 [run | watch | live | create | app | applet | unpack] path/to/sketch
17
-
17
+
18
18
  Examples:
19
19
  rp5 unpack samples
20
20
  rp5 run samples/jwishy.rb
21
21
  rp5 create some_new_sketch --bare 640 480
22
22
  rp5 watch some_new_sketch.rb
23
23
  rp5 applet some_new_sketch.rb
24
-
24
+
25
25
  Everything Else:
26
- http://wiki.github.com/jashkenas/ruby-processing
27
-
26
+ http://wiki.github.com/jashkenas/ruby-processing
27
+
28
28
  EOS
29
-
29
+
30
30
  # Start running a ruby-processing sketch from the passed-in arguments
31
31
  def self.execute
32
32
  runner = new
33
33
  runner.parse_options(ARGV)
34
34
  runner.execute!
35
35
  end
36
-
36
+
37
37
  # Dispatch central.
38
38
  def execute!
39
39
  case @options.action
40
- when 'run' then run(@options.path)
41
- when 'watch' then watch(@options.path)
40
+ when 'run' then run(@options.path, @options.args)
41
+ when 'watch' then watch(@options.path, @options.args)
42
+ when 'live' then live(@options.path, @options.args)
42
43
  when 'create' then create(@options.path, @options.args, @options.bare)
43
- when 'live' then live(@options.path)
44
44
  when 'app' then app(@options.path)
45
45
  when 'applet' then applet(@options.path)
46
46
  when 'unpack' then unpack(@options.path)
@@ -50,52 +50,53 @@ module Processing
50
50
  show_help
51
51
  end
52
52
  end
53
-
53
+
54
54
  # Parse the command-line options. Keep it simple.
55
55
  def parse_options(args)
56
56
  @options = OpenStruct.new
57
57
  @options.bare = !!args.delete('--bare')
58
+ @options.jruby = !!args.delete('--jruby')
58
59
  @options.action = args[0] || nil
59
60
  @options.path = args[1] || File.basename(Dir.pwd + '.rb')
60
61
  @options.args = args[2..-1] || []
61
62
  end
62
-
63
+
63
64
  # Create a fresh Ruby-Processing sketch, with the necessary
64
65
  # boilerplate filled out.
65
66
  def create(sketch, args, bare)
66
67
  Processing::Creator.new.create!(sketch, args, bare)
67
68
  end
68
-
69
+
69
70
  # Just simply run a ruby-processing sketch.
70
- def run(sketch)
71
+ def run(sketch, args)
71
72
  ensure_exists(sketch)
72
- spin_up('run.rb', sketch)
73
+ spin_up('run.rb', sketch, args)
73
74
  end
74
-
75
+
75
76
  # Run a sketch, keeping an eye on it's file, and reloading
76
77
  # whenever it changes.
77
- def watch(sketch)
78
+ def watch(sketch, args)
78
79
  ensure_exists(sketch)
79
- spin_up('watch.rb', sketch)
80
+ spin_up('watch.rb', sketch, args)
80
81
  end
81
-
82
+
82
83
  # Run a sketch, opening its guts to IRB, letting you play with it.
83
- def live(sketch)
84
+ def live(sketch, args)
84
85
  ensure_exists(sketch)
85
- spin_up('live.rb', sketch)
86
+ spin_up('live.rb', sketch, args)
86
87
  end
87
-
88
+
88
89
  # Generate a cross-platform application of a given Ruby-Processing sketch.
89
90
  def app(sketch)
90
91
  Processing::ApplicationExporter.new.export!(sketch)
91
92
  end
92
-
93
+
93
94
  # Generate an applet and HTML page for a given sketch.
94
95
  def applet(sketch)
95
96
  Processing::AppletExporter.new.export!(sketch)
96
97
  end
97
-
98
- # Install the included samples to a given path, where you can run and
98
+
99
+ # Install the included samples to a given path, where you can run and
99
100
  # alter them to your heart's content.
100
101
  def unpack(dir)
101
102
  require 'fileutils'
@@ -103,52 +104,59 @@ module Processing
103
104
  puts usage and return unless dir.match(/\A(samples|library)\Z/)
104
105
  FileUtils.cp_r("#{RP5_ROOT}/#{dir}", "#{Dir.pwd}/#{dir}")
105
106
  end
106
-
107
+
107
108
  # Display the current version of Ruby-Processing.
108
109
  def show_version
109
- puts "Ruby-Processing version #{Processing.version}"
110
+ puts "Ruby-Processing version #{Processing::VERSION}"
110
111
  end
111
-
112
+
112
113
  # Show the standard help/usage message.
113
114
  def show_help
114
115
  puts HELP_MESSAGE
115
116
  end
116
-
117
-
117
+
118
+
118
119
  private
119
-
120
- # Trade in this Ruby instance for a JRuby instance, loading in a
120
+
121
+ # Trade in this Ruby instance for a JRuby instance, loading in a
121
122
  # starter script and passing it some arguments.
122
- def spin_up(starter_script, sketch)
123
+ # If --jruby is passed, use the installed version of jruby, instead of
124
+ # our vendored jarred one (useful for gems).
125
+ def spin_up(starter_script, sketch, args)
123
126
  runner = "#{RP5_ROOT}/lib/ruby-processing/runners/#{starter_script}"
124
127
  java_args = discover_java_args(sketch)
125
- command = "java #{java_args} -cp \"#{jruby_complete}\" #{dock_icon} org.jruby.Main \"#{runner}\" #{sketch}"
126
- exec(command)
128
+ command = @options.jruby ?
129
+ ['jruby', java_args, runner, sketch, args].flatten :
130
+ ['java', java_args, '-cp', jruby_complete, 'org.jruby.Main', runner, sketch, args].flatten
131
+ exec *command
127
132
  # exec replaces the Ruby process with the JRuby one.
128
133
  end
129
-
134
+
130
135
  # If you need to pass in arguments to Java, such as the ones on this page:
131
136
  # http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html
132
137
  # then type them into a java_args.txt in your data directory next to your sketch.
133
138
  def discover_java_args(sketch)
134
139
  arg_file = "#{File.dirname(sketch)}/data/java_args.txt"
135
- File.exists?(arg_file) ? File.read(arg_file).gsub("\n", " ") : ''
140
+ args = dock_icon
141
+ args += File.read(arg_file).split(/\s+/) if File.exists?(arg_file)
142
+ args.map! {|arg| "-J#{arg}" } if @options.jruby
143
+ args
136
144
  end
137
-
145
+
138
146
  def ensure_exists(sketch)
139
147
  puts "Couldn't find: #{sketch}" and exit unless File.exists?(sketch)
140
148
  end
141
-
149
+
142
150
  def jruby_complete
143
151
  File.join(RP5_ROOT, 'lib/core/jruby-complete.jar')
144
152
  end
145
-
153
+
146
154
  # On the Mac, we can display a fat, shiny ruby in the Dock.
147
155
  def dock_icon
148
156
  mac = RUBY_PLATFORM.match(/darwin/i) || (RUBY_PLATFORM == 'java' && ENV_JAVA['os.name'].match(/mac/i))
149
- mac ? "-Xdock:name=Ruby-Processing -Xdock:icon=#{RP5_ROOT}/lib/templates/application/Contents/Resources/sketch.icns" : ""
157
+ mac ? ["-Xdock:name=Ruby-Processing", "-Xdock:icon=#{RP5_ROOT}/lib/templates/application/Contents/Resources/sketch.icns"] : []
150
158
  end
151
-
159
+
152
160
  end # class Runner
153
-
161
+
154
162
  end # module Processing
@@ -1,5 +1,6 @@
1
1
  $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../../")
2
- SKETCH_ROOT = File.dirname(ARGV[0]) unless defined? SKETCH_ROOT
2
+ SKETCH_PATH = ARGV.shift
3
+ SKETCH_ROOT = File.dirname(SKETCH_PATH) unless defined? SKETCH_ROOT
3
4
 
4
5
  require 'ruby-processing'
5
6
  require 'ruby-processing/app'
@@ -7,8 +8,6 @@ require 'ruby-processing/app'
7
8
 
8
9
  module Processing
9
10
 
10
- SKETCH_PATH = ARGV[0]
11
-
12
11
  # For use with "bare" sketches that don't want to define a class or methods
13
12
  SKETCH_TEMPLATE = <<-EOS
14
13
  class Sketch < Processing::App
@@ -31,13 +30,13 @@ module Processing
31
30
  has_methods = !!source.match(/^[^#]*(def\s+setup|def\s+draw)/)
32
31
 
33
32
  if has_sketch
34
- load Processing::SKETCH_PATH
33
+ load SKETCH_PATH
35
34
  Processing::App.sketch_class.new if !$app
36
35
  return
37
36
  else
38
37
  require 'erb'
39
38
  code = ERB.new(SKETCH_TEMPLATE).result(binding)
40
- Object.class_eval code, Processing::SKETCH_PATH, 0
39
+ Object.class_eval code, SKETCH_PATH, 0
41
40
  Processing::App.sketch_class.new if !$app
42
41
  end
43
42
  end
@@ -48,7 +47,7 @@ module Processing
48
47
  if Processing.online?
49
48
  # Fuck the following lines. Fucking Java can go sit on broken glass.
50
49
  source = ''
51
- url = java.net.URL.new(JRUBY_APPLET.get_code_base, Processing::SKETCH_PATH)
50
+ url = java.net.URL.new(JRUBY_APPLET.get_code_base, SKETCH_PATH)
52
51
  input = java.io.BufferedReader.new(java.io.InputStreamReader.new(url.open_stream))
53
52
  while line = input.read_line do
54
53
  source << (line + "\n") if line
@@ -56,7 +55,7 @@ module Processing
56
55
  input.close
57
56
  else
58
57
  # Ahhh, much better.
59
- source = File.read(Processing::SKETCH_PATH)
58
+ source = File.read(SKETCH_PATH)
60
59
  end
61
60
  source
62
61
  end
@@ -3,9 +3,10 @@
3
3
  # or will start with your sketch.
4
4
 
5
5
  require "#{File.dirname(__FILE__)}/base.rb"
6
+ Processing.load_and_run_sketch
7
+
8
+ ARGV.clear # So that IRB doesn't try to load them as files.
6
9
 
7
10
  require 'irb'
8
- ARGV[0] = nil # To keep IRB from trying to run it multiple times.
9
11
  IRB.setup(__FILE__)
10
- Processing.load_and_run_sketch
11
- IRB.start()
12
+ IRB.start
@@ -1,25 +1,25 @@
1
1
  require "#{File.dirname(__FILE__)}/base.rb"
2
2
 
3
- module Processing
4
-
5
- # A sketch loader, observer, and reloader, to tighten
3
+ module Processing
4
+
5
+ # A sketch loader, observer, and reloader, to tighten
6
6
  # the feedback between code and effect.
7
7
  class Watcher
8
-
8
+
9
9
  # Sic a new Processing::Watcher on the sketch
10
10
  def initialize
11
- @file = Processing::SKETCH_PATH
11
+ @file = SKETCH_PATH
12
12
  @time = Time.now
13
13
  # Doesn't work well enough for now.
14
14
  # record_state_of_ruby
15
- Processing.load_and_run_sketch unless $app
16
15
  start_watching
17
16
  end
18
-
19
-
17
+
18
+
20
19
  # Kicks off a thread to watch the sketch, reloading Ruby-Processing
21
20
  # and restarting the sketch whenever it changes.
22
21
  def start_watching
22
+ @runner = Thread.start { report_errors { Processing.load_and_run_sketch } } unless $app
23
23
  thread = Thread.start do
24
24
  loop do
25
25
  file_mtime = File.stat(@file).mtime
@@ -29,22 +29,28 @@ module Processing
29
29
  # Taking it out the reset until it can be made to work more reliably
30
30
  # rewind_to_recorded_state
31
31
  GC.start
32
- begin
33
- Processing.load_and_run_sketch
34
- rescue StandardError, ScriptError
35
- print "Error in your sketch: ", $!, "\n"
36
- end
32
+ @runner = Thread.start { report_errors { Processing.load_and_run_sketch } }
37
33
  end
38
34
  sleep 0.33
39
35
  end
40
36
  end
41
37
  thread.join
42
38
  end
43
-
44
-
45
- # Used to completely remove all traces of the current sketch,
39
+
40
+ # Convenience function to report errors when loading and running a sketch,
41
+ # instead of having them eaten by the thread they are loaded in.
42
+ def report_errors
43
+ yield
44
+ rescue Exception => e
45
+ puts "Exception occured while running sketch #{File.basename SKETCH_PATH}:"
46
+ puts e.to_s
47
+ puts e.backtrace.join("\n")
48
+ end
49
+
50
+ # Used to completely remove all traces of the current sketch,
46
51
  # so that it can be loaded afresh. Go down into modules to find it, even.
47
52
  def wipe_out_current_app!
53
+ @runner.kill if @runner.alive?
48
54
  app = $app
49
55
  return unless app
50
56
  app.no_loop
@@ -54,15 +60,15 @@ module Processing
54
60
  constant_names = app.class.to_s.split(/::/)
55
61
  app_class_name = constant_names.pop
56
62
  obj = constant_names.inject(Object) {|o, name| o.send(:const_get, name) }
57
- obj.send(:remove_const, app_class_name)
63
+ obj.send(:remove_const, app_class_name)
58
64
  end
59
-
65
+
60
66
  # The following methods were intended to make the watcher clean up all code
61
67
  # loaded in from the sketch, gems, etc, and have them be reloaded properly
62
68
  # when the sketch is.... but it seems that this is neither a very good idea
63
- # or a very possible one. If you can make the scheme work, please do,
69
+ # or a very possible one. If you can make the scheme work, please do,
64
70
  # otherwise the following methods will probably be removed soonish.
65
-
71
+
66
72
  # Do the best we can to take a picture of the current Ruby interpreter.
67
73
  # For now, this means top-level constants and loaded .rb files.
68
74
  def record_state_of_ruby
@@ -71,19 +77,19 @@ module Processing
71
77
  @saved_features = $LOADED_FEATURES.dup
72
78
  @saved_globals = Kernel.global_variables.dup
73
79
  end
74
-
75
-
80
+
81
+
76
82
  # Try to go back to the recorded Ruby state.
77
83
  def rewind_to_recorded_state
78
84
  new_constants = Object.send(:constants).reject {|c| @saved_constants.include?(c) }
79
85
  new_load_paths = $LOAD_PATH.reject {|p| @saved_load_paths.include?(p) }
80
86
  new_features = $LOADED_FEATURES.reject {|f| @saved_features.include?(f) }
81
87
  new_globals = Kernel.global_variables.reject {|g| @saved_globals.include?(g) }
82
-
88
+
83
89
  Processing::App.recursively_remove_constants(Object, new_constants)
84
90
  new_load_paths.each {|p| $LOAD_PATH.delete(p) }
85
91
  new_features.each {|f| $LOADED_FEATURES.delete(f) }
86
- new_globals.each do |g|
92
+ new_globals.each do |g|
87
93
  begin
88
94
  eval("#{g} = nil") # There's no way to undef a global variable in Ruby
89
95
  rescue NameError => e
@@ -91,8 +97,8 @@ module Processing
91
97
  end
92
98
  end
93
99
  end
94
-
95
-
100
+
101
+
96
102
  # Used to clean up declared constants in code that needs to be reloaded.
97
103
  def recursively_remove_constants(base, constant_names)
98
104
  constants = constant_names.map {|name| base.const_get(name) }
@@ -104,7 +110,7 @@ module Processing
104
110
  constants.each {|c| recursively_remove_constants(c, c.constants) if c }
105
111
  constant_names.each {|name| base.send(:remove_const, name.to_sym) if name }
106
112
  end
107
-
113
+
108
114
  end
109
115
  end
110
116