jruby_art 0.2.0.pre
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.
- checksums.yaml +7 -0
- data/LICENSE.md +39 -0
- data/README.md +88 -0
- data/Rakefile +93 -0
- data/bin/k9 +10 -0
- data/lib/core.jar +0 -0
- data/lib/export.txt +10 -0
- data/lib/gluegen-rt-natives-linux-amd64.jar +0 -0
- data/lib/gluegen-rt-natives-linux-armv6hf.jar +0 -0
- data/lib/gluegen-rt-natives-linux-i586.jar +0 -0
- data/lib/gluegen-rt-natives-macosx-universal.jar +0 -0
- data/lib/gluegen-rt-natives-windows-amd64.jar +0 -0
- data/lib/gluegen-rt-natives-windows-i586.jar +0 -0
- data/lib/gluegen-rt.jar +0 -0
- data/lib/jogl-all-natives-linux-amd64.jar +0 -0
- data/lib/jogl-all-natives-linux-armv6hf.jar +0 -0
- data/lib/jogl-all-natives-linux-i586.jar +0 -0
- data/lib/jogl-all-natives-macosx-universal.jar +0 -0
- data/lib/jogl-all-natives-windows-amd64.jar +0 -0
- data/lib/jogl-all-natives-windows-i586.jar +0 -0
- data/lib/jogl-all.jar +0 -0
- data/lib/jruby_art.rb +27 -0
- data/lib/jruby_art/app.rb +153 -0
- data/lib/jruby_art/config.rb +18 -0
- data/lib/jruby_art/creator.rb +100 -0
- data/lib/jruby_art/helper_methods.rb +220 -0
- data/lib/jruby_art/helpers/camel_string.rb +18 -0
- data/lib/jruby_art/helpers/numeric.rb +9 -0
- data/lib/jruby_art/helpers/range.rb +11 -0
- data/lib/jruby_art/helpers/string_extra.rb +33 -0
- data/lib/jruby_art/parse.rb +60 -0
- data/lib/jruby_art/runner.rb +142 -0
- data/lib/jruby_art/version.rb +3 -0
- data/lib/jruby_art/writer.rb +40 -0
- data/lib/rpextras.jar +0 -0
- data/spec/app_spec.rb +208 -0
- data/spec/deglut_spec.rb +25 -0
- data/spec/spec_helper.rb +96 -0
- data/spec/vecmath_spec.rb +277 -0
- data/vendors/Rakefile +95 -0
- 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,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
|
+
|