jruby_art 0.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +39 -0
  3. data/README.md +88 -0
  4. data/Rakefile +93 -0
  5. data/bin/k9 +10 -0
  6. data/lib/core.jar +0 -0
  7. data/lib/export.txt +10 -0
  8. data/lib/gluegen-rt-natives-linux-amd64.jar +0 -0
  9. data/lib/gluegen-rt-natives-linux-armv6hf.jar +0 -0
  10. data/lib/gluegen-rt-natives-linux-i586.jar +0 -0
  11. data/lib/gluegen-rt-natives-macosx-universal.jar +0 -0
  12. data/lib/gluegen-rt-natives-windows-amd64.jar +0 -0
  13. data/lib/gluegen-rt-natives-windows-i586.jar +0 -0
  14. data/lib/gluegen-rt.jar +0 -0
  15. data/lib/jogl-all-natives-linux-amd64.jar +0 -0
  16. data/lib/jogl-all-natives-linux-armv6hf.jar +0 -0
  17. data/lib/jogl-all-natives-linux-i586.jar +0 -0
  18. data/lib/jogl-all-natives-macosx-universal.jar +0 -0
  19. data/lib/jogl-all-natives-windows-amd64.jar +0 -0
  20. data/lib/jogl-all-natives-windows-i586.jar +0 -0
  21. data/lib/jogl-all.jar +0 -0
  22. data/lib/jruby_art.rb +27 -0
  23. data/lib/jruby_art/app.rb +153 -0
  24. data/lib/jruby_art/config.rb +18 -0
  25. data/lib/jruby_art/creator.rb +100 -0
  26. data/lib/jruby_art/helper_methods.rb +220 -0
  27. data/lib/jruby_art/helpers/camel_string.rb +18 -0
  28. data/lib/jruby_art/helpers/numeric.rb +9 -0
  29. data/lib/jruby_art/helpers/range.rb +11 -0
  30. data/lib/jruby_art/helpers/string_extra.rb +33 -0
  31. data/lib/jruby_art/parse.rb +60 -0
  32. data/lib/jruby_art/runner.rb +142 -0
  33. data/lib/jruby_art/version.rb +3 -0
  34. data/lib/jruby_art/writer.rb +40 -0
  35. data/lib/rpextras.jar +0 -0
  36. data/spec/app_spec.rb +208 -0
  37. data/spec/deglut_spec.rb +25 -0
  38. data/spec/spec_helper.rb +96 -0
  39. data/spec/vecmath_spec.rb +277 -0
  40. data/vendors/Rakefile +95 -0
  41. metadata +116 -0
@@ -0,0 +1,18 @@
1
+ require 'psych'
2
+
3
+ module Processing
4
+
5
+ unless defined? RP_CONFIG
6
+ begin
7
+ CONFIG_FILE_PATH = File.expand_path('~/.jruby_art/config.yml')
8
+ File.open(CONFIG_FILE_PATH, 'r') do |yaml|
9
+ RP_CONFIG = Psych.load(yaml)
10
+ end
11
+ rescue
12
+ warn('WARNING: you need to set PROCESSING_ROOT in ~/.jruby_art/config.yml')
13
+ end
14
+ end
15
+ end
16
+
17
+
18
+
@@ -0,0 +1,100 @@
1
+ CLASS_BASIC = <<-CODE
2
+ require 'jruby_art'
3
+
4
+ class %s < Processing::App
5
+ def setup
6
+ size %s, %s
7
+ end
8
+
9
+ def draw
10
+
11
+ end
12
+ end
13
+
14
+ %s.new(title: '%s')
15
+ CODE
16
+
17
+ CLASS_MODE = <<-CODE
18
+ require 'jruby_art'
19
+
20
+ class %s < Processing::AppGL
21
+ def setup
22
+ size %s, %s, %s
23
+ end
24
+
25
+ def draw
26
+
27
+ end
28
+ end
29
+
30
+ %s.new(title: '%s')
31
+ CODE
32
+
33
+ module Processing
34
+ require_relative '../jruby_art/helpers/string_extra'
35
+ require_relative '../jruby_art/helpers/camel_string'
36
+ # Write file to disk
37
+ class SketchWriter
38
+ attr_reader :file
39
+ def initialize(path)
40
+ underscore = StringExtra.new(path).underscore
41
+ @file = "#{File.dirname(path)}/#{underscore}.rb"
42
+ end
43
+
44
+ def save(template)
45
+ File.open(file, 'w+') do |f|
46
+ f.write(template)
47
+ end
48
+ end
49
+ end
50
+
51
+ # An abstract class providing common methods for real creators
52
+ class Creator
53
+ ALL_DIGITS = /\A\d+\Z/
54
+
55
+ def already_exist(path)
56
+ underscore = StringExtra.new(path).underscore
57
+ new_file = "#{File.dirname(path)}/#{underscore}.rb"
58
+ return if !File.exist?(path) && !File.exist?(new_file)
59
+ puts 'That file already exists!'
60
+ exit
61
+ end
62
+
63
+ # Show the help/usage message for create.
64
+ def usage
65
+ puts <<-USAGE
66
+
67
+ Usage: k9 create <sketch_to_generate> <width> <height>
68
+ Examples: k9 create my_app 800 600
69
+ k9 create my_app 800 600 p3d
70
+
71
+ USAGE
72
+ end
73
+ end
74
+
75
+ # This class creates class wrapped sketches, with an optional render mode
76
+ class ClassSketch < Creator
77
+ def class_template
78
+ format(CLASS_BASIC, @name, @width, @height, @name, @title)
79
+ end
80
+
81
+ def class_template_mode
82
+ format(CLASS_MODE, @name, @width, @height, @mode, @name, @title)
83
+ end
84
+
85
+ # Create a bare blank sketch, given a path.
86
+ def create!(path, args)
87
+ return usage if /\?/ =~ path || /--help/ =~ path
88
+ main_file = File.basename(path, '.rb') # allow uneeded extension input
89
+ # Check to make sure that the main file doesn't exist already
90
+ already_exist(path)
91
+ @name = CamelString.new(main_file).camelize
92
+ writer = SketchWriter.new(main_file)
93
+ @title = StringExtra.new(main_file).titleize
94
+ @width, @height = args[0], args[1]
95
+ @mode = args[2].upcase unless args[2].nil?
96
+ template = @mode.nil? ? class_template : class_template_mode
97
+ writer.save(template)
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,220 @@
1
+ module Processing
2
+ module HelperMethods
3
+ # processings epsilon may not be defined yet
4
+ EPSILON ||= 1.0e-04
5
+ # Nice block method to draw to a buffer.
6
+ # You can optionally pass it a width, a height, and a renderer.
7
+ # Takes care of starting and ending the draw for you.
8
+ def buffer(buf_width = width, buf_height = height, renderer = @render_mode)
9
+ buf = create_graphics(buf_width, buf_height, renderer)
10
+ buf.begin_draw
11
+ yield buf
12
+ buf.end_draw
13
+ buf
14
+ end
15
+
16
+ # A nice method to run a given block for a grid.
17
+ # Lifted from action_coding/Nodebox.
18
+ def grid(cols, rows, col_size = 1, row_size = 1)
19
+ (0...cols * rows).map do |i|
20
+ x = col_size * (i % cols)
21
+ y = row_size * i.div(cols)
22
+ yield x, y
23
+ end
24
+ end
25
+
26
+ # lerp_color takes three or four arguments, in Java that's two
27
+ # different methods, one regular and one static, so:
28
+ def lerp_color(*args)
29
+ args.length > 3 ? self.class.lerp_color(*args) : super(*args)
30
+ end
31
+
32
+ def color(*args)
33
+ a = args[0]
34
+ # convert to signed int
35
+ if args.length == 1
36
+ if a.is_a?(Fixnum) && a >= 2**31
37
+ args = [a - 2**32]
38
+ elsif a.is_a?(String) && a[0].eql?('#')
39
+ h = a[1..-1].rjust(6, '0').prepend('ff')
40
+ return color(h.hex)
41
+ end
42
+ end
43
+ super(*args)
44
+ end
45
+
46
+ # Overrides Processing convenience function thread, which takes a String
47
+ # arg (for a function) to more rubylike version, takes a block...
48
+ def thread(&block)
49
+ if block_given?
50
+ Thread.new(&block)
51
+ else
52
+ fail ArgumentError, 'thread must be called with a block', caller
53
+ end
54
+ end
55
+
56
+ # Explicitly provides 'processing.org' map instance method, in which
57
+ # value is mapped from range 1, to range 2 (NB: values are not clamped to
58
+ # range 1). It may be better to explicitly write your own interpolate
59
+ # function
60
+ # @param [float] value input
61
+ # @param [range] start1, stop1
62
+ # @param [range] start1, stop2
63
+ # @return [float] mapped value
64
+ def map(value, start1, stop1, start2, stop2)
65
+ start2 + (stop2 - start2) * ((value - start1).to_f / (stop1 - start1))
66
+ end
67
+
68
+ # ruby alternative implementation of map using range parameters
69
+ # (begin..end) and excluded end (begin...end) produce the same result
70
+ def map1d(val, r_in, r_out)
71
+ r_out.begin + (r_out.end - r_out.begin) *
72
+ ((val - r_in.begin).to_f / (r_in.end - r_in.begin))
73
+ end
74
+
75
+ # explicitly provide 'processing.org' norm instance method
76
+ def norm(value, start, stop)
77
+ (value - start).to_f / (stop - start)
78
+ end
79
+
80
+ # explicitly provide 'processing.org' lerp instance method
81
+ def lerp(start, stop, amt)
82
+ start + (stop - start) * amt
83
+ end
84
+
85
+ # explicitly provide 'processing.org' min instance method
86
+ # to return a float:- a, b and c need to be floats
87
+
88
+ def min(*args)
89
+ args.min # { |a,b| a <=> b } optional block not reqd
90
+ end
91
+
92
+ # explicitly provide 'processing.org' max instance method
93
+ # to return a float:- a, b and c need to be floats
94
+
95
+ def max(*args)
96
+ args.max # { |a, b| a <=> b } optional block not reqd
97
+ end
98
+
99
+ # explicitly provide 'processing.org' dist instance method
100
+ def dist(*args)
101
+ len = args.length
102
+ if len == 4
103
+ dx = args[0] - args[2]
104
+ dy = args[1] - args[3]
105
+ return 0 if dx.abs < EPSILON && dy.abs < EPSILON
106
+ return Math.hypot(dx, dy)
107
+ end
108
+ fail ArgumentError, 'takes 4 parameters'
109
+ end
110
+
111
+ # dist_squared only makes sense with 3D distance
112
+ def dist_squared(*args)
113
+ len = args.length
114
+ if len == 6
115
+ dx = args[0] - args[3]
116
+ dy = args[1] - args[4]
117
+ dz = args[2] - args[5]
118
+ return 0 if dx.abs < EPSILON && dy.abs < EPSILON && dz.abs < EPSILON
119
+ return dx * dx + dy * dy + dz * dz
120
+ end
121
+ fail ArgumentError, 'takes 6 parameters'
122
+ end
123
+
124
+ # explicitly provide 'processing.org' constrain instance method
125
+ # to return a float:- amt, low and high need to be floats
126
+ def constrain(amt, low, high)
127
+ (low..high).clip(amt)
128
+ end
129
+
130
+ # Uses PImage class method under hood
131
+ def blend_color(c1, c2, mode)
132
+ Java::ProcessingCore::PImage::blendColor(c1, c2, mode)
133
+ end
134
+
135
+ # There's just so many functions in Processing,
136
+ # Here's a convenient way to look for them.
137
+ def find_method(method_name)
138
+ reg = Regexp.new("#{method_name}", true)
139
+ methods.sort.select { |meth| reg.match(meth) }
140
+ end
141
+
142
+ # Proxy over a list of Java declared fields that have the same name as
143
+ # some methods. Add to this list as needed.
144
+ def proxy_java_fields
145
+ fields = %w(sketchPath key frameRate frame mousePressed keyPressed)
146
+ methods = fields.map { |field| java_class.declared_field(field) }
147
+ @declared_fields = Hash[fields.zip(methods)]
148
+ end
149
+
150
+ # By default, your sketch path is the folder that your sketch is in.
151
+ # If you'd like to do something fancy, feel free.
152
+ def set_sketch_path(spath = nil)
153
+ field = @declared_fields['sketchPath']
154
+ field.set_value(java_self, spath || SKETCH_ROOT)
155
+ end
156
+
157
+ # Fix java conversion problems getting the last key
158
+ # If it's ASCII, return the character, otherwise the integer
159
+ def key
160
+ int = @declared_fields['key'].value(java_self)
161
+ int < 256 ? int.chr : int
162
+ end
163
+
164
+ # Provide a convenient handle for the Java-space version of self.
165
+ def java_self
166
+ @java_self ||= to_java(Java::ProcessingCore::PApplet)
167
+ end
168
+
169
+ # Get the sketch path
170
+ def sketch_path
171
+ @declared_fields['sketchPath'].value(java_self)
172
+ end
173
+
174
+ # Fields that should be made accessible as under_scored.
175
+ define_method(:mouse_x) { mouseX }
176
+
177
+ define_method(:mouse_y) { mouseY }
178
+
179
+ define_method(:pmouse_x) { pmouseX }
180
+
181
+ define_method(:pmouse_y) { pmouseY }
182
+
183
+ define_method(:frame_count) { frameCount }
184
+
185
+ define_method(:mouse_button) { mouseButton }
186
+
187
+ define_method(:key_code) { keyCode }
188
+
189
+ define_method(:display_height) { displayHeight }
190
+
191
+ define_method(:display_width) { displayWidth }
192
+
193
+ # Ensure that load_strings returns a real Ruby array
194
+ def load_strings(file_or_url)
195
+ loadStrings(file_or_url).to_a
196
+ end
197
+
198
+ # Writes an array of strings to a file, one line per string.
199
+ # This file is saved to the sketch's data folder
200
+ def save_strings(filename, strings)
201
+ saveStrings(filename, [strings].flatten.to_java(:String))
202
+ end
203
+
204
+ # frame_rate needs to support reading and writing
205
+ def frame_rate(fps = nil)
206
+ return @declared_fields['frameRate'].value(java_self) unless fps
207
+ super(fps)
208
+ end
209
+
210
+ # Is the mouse pressed for this frame?
211
+ def mouse_pressed?
212
+ @declared_fields['mousePressed'].value(java_self)
213
+ end
214
+
215
+ # Is a key pressed for this frame?
216
+ def key_pressed?
217
+ @declared_fields['keyPressed'].value(java_self)
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,18 @@
1
+ require 'forwardable'
2
+
3
+ # Avoid the monkey patching of String for camelize
4
+ class CamelString
5
+ extend Forwardable
6
+ def_delegators(:@string, *String.public_instance_methods(false))
7
+ def initialize(str = 'no_name')
8
+ @string = (str.length > 60) ? 'long_name' : str
9
+ end
10
+
11
+ def camelize(first_letter_in_uppercase = true)
12
+ if first_letter_in_uppercase
13
+ @string.gsub(/\/(.?)/) { '::' + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
14
+ else
15
+ @string[0] + camelize[1..-1]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ class Numeric #:nodoc:
2
+ def degrees
3
+ self * 180 / Math::PI
4
+ end
5
+
6
+ def radians
7
+ self * Math::PI / 180
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ class Range #:nodoc:
2
+ def clip(n)
3
+ if cover?(n)
4
+ n
5
+ elsif n < min
6
+ min
7
+ else
8
+ max
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,33 @@
1
+ require 'forwardable'
2
+
3
+ # Avoid the monkey patching of String for underscore/titleize/humanize
4
+ class StringExtra
5
+ extend Forwardable
6
+ def_delegators(:@string, *String.public_instance_methods(false))
7
+ def initialize(str = 'no_name')
8
+ @string = (str.length > 60) ? 'long_name' : str
9
+ end
10
+
11
+ def titleize
12
+ gsub(/::/, '/')
13
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
14
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
15
+ .tr('-', '_')
16
+ .downcase
17
+ .gsub(/_id$/, '')
18
+ .gsub(/_/, ' ').capitalize
19
+ .gsub(/\b([a-z])/) { $1.capitalize }
20
+ end
21
+
22
+ def humanize
23
+ gsub(/_id$/, '').gsub(/_/, ' ').capitalize
24
+ end
25
+
26
+ def underscore
27
+ gsub(/::/, '/')
28
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
29
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
30
+ .tr('-', '_')
31
+ .downcase
32
+ end
33
+ end
@@ -0,0 +1,60 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ SKETCH_PATH ||= ARGV.shift
4
+ SKETCH_ROOT ||= File.dirname(SKETCH_PATH)
5
+
6
+ require_relative '../jruby_art'
7
+ require_relative '../jruby_art/'
8
+ require_relative '../jruby_art/helpers/string_extra'
9
+
10
+ module Processing
11
+ # For use with "bare" sketches that don't want to define a class or methods
12
+ BARE_TEMPLATE = <<-EOS
13
+ require 'jruby_art'
14
+
15
+ class Sketch < %s
16
+ %s
17
+ end
18
+
19
+ Sketch.new(title: '%s')
20
+ EOS
21
+
22
+ NAKED_TEMPLATE = <<-EOS
23
+ require 'jruby_art'
24
+
25
+ class Sketch < Processing::App
26
+
27
+ def setup
28
+ %s
29
+ no_loop
30
+ end
31
+ end
32
+
33
+ Sketch.new(title: '%s')
34
+ EOS
35
+
36
+ # This method is the common entry point to run a sketch, bare or complete.
37
+ def self.load_and_run_sketch
38
+ source = read_sketch_source
39
+ has_sketch = !source.match(/^[^#]*< Processing::App/).nil?
40
+ has_methods = !source.match(/^[^#]*(def\s+setup|def\s+draw)/).nil?
41
+ return load File.join(SKETCH_ROOT, SKETCH_PATH) if has_sketch
42
+ title = StringExtra.new(File.basename(SKETCH_PATH).sub(/(\.rb)$/, '')).titleize
43
+ if has_methods
44
+ default = source.match(/P(2|3)D/)
45
+ mode = default ? 'Processing::App' : 'Processing::AppGL'
46
+ code = format(BARE_TEMPLATE, mode, source, title)
47
+ else
48
+ code = format(NAKED_TEMPLATE, source, title)
49
+ end
50
+ Object.class_eval code, SKETCH_PATH, -1
51
+ end
52
+
53
+ # Read in the sketch source code. Needs to work both online and offline.
54
+ def self.read_sketch_source
55
+ File.read(SKETCH_PATH)
56
+ end
57
+ end
58
+
59
+ Processing.load_and_run_sketch
60
+