propane 0.3.0.pre-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.mvn/extensions.xml +8 -0
  4. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  5. data/.travis.yml +9 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +69 -0
  9. data/Rakefile +59 -0
  10. data/VERSION.txt +4 -0
  11. data/bin/propane +8 -0
  12. data/examples/complete/Rakefile +32 -0
  13. data/examples/complete/data/Texture01.jpg +0 -0
  14. data/examples/complete/data/Texture02.jpg +0 -0
  15. data/examples/complete/data/Univers45.vlw +0 -0
  16. data/examples/complete/data/displaceFrag.glsl +8 -0
  17. data/examples/complete/data/displaceVert.glsl +201 -0
  18. data/examples/complete/glsl_heightmap_noise.rb +121 -0
  19. data/examples/complete/kinetic_type.rb +79 -0
  20. data/examples/regular/Rakefile +30 -0
  21. data/examples/regular/arcball_box.rb +36 -0
  22. data/examples/regular/creating_colors.rb +57 -0
  23. data/examples/regular/elegant_ball.rb +159 -0
  24. data/examples/regular/flight_patterns.rb +63 -0
  25. data/examples/regular/grey_circles.rb +28 -0
  26. data/examples/regular/jwishy.rb +100 -0
  27. data/examples/regular/letters.rb +42 -0
  28. data/examples/regular/lib/boundary.rb +38 -0
  29. data/examples/regular/lib/particle.rb +77 -0
  30. data/examples/regular/lib/particle_system.rb +111 -0
  31. data/examples/regular/liquidy.rb +40 -0
  32. data/examples/regular/mouse_button_demo.rb +34 -0
  33. data/examples/regular/polyhedrons.rb +248 -0
  34. data/examples/regular/ribbon_doodle.rb +89 -0
  35. data/examples/regular/vector_math.rb +36 -0
  36. data/examples/regular/words.rb +41 -0
  37. data/lib/PROCESSING_LICENSE.txt +456 -0
  38. data/lib/export.txt +10 -0
  39. data/lib/propane.rb +12 -0
  40. data/lib/propane/app.rb +197 -0
  41. data/lib/propane/helper_methods.rb +177 -0
  42. data/lib/propane/helpers/numeric.rb +9 -0
  43. data/lib/propane/library_loader.rb +117 -0
  44. data/lib/propane/runner.rb +88 -0
  45. data/lib/propane/underscorer.rb +19 -0
  46. data/lib/propane/version.rb +5 -0
  47. data/library/boids/boids.rb +201 -0
  48. data/library/control_panel/control_panel.rb +172 -0
  49. data/pom.rb +113 -0
  50. data/pom.xml +198 -0
  51. data/propane.gemspec +28 -0
  52. data/src/monkstone/ColorUtil.java +67 -0
  53. data/src/monkstone/MathTool.java +195 -0
  54. data/src/monkstone/PropaneLibrary.java +47 -0
  55. data/src/monkstone/core/AbstractLibrary.java +102 -0
  56. data/src/monkstone/fastmath/Deglut.java +115 -0
  57. data/src/monkstone/vecmath/AppRender.java +87 -0
  58. data/src/monkstone/vecmath/JRender.java +56 -0
  59. data/src/monkstone/vecmath/ShapeRender.java +87 -0
  60. data/src/monkstone/vecmath/vec2/Vec2.java +670 -0
  61. data/src/monkstone/vecmath/vec3/Vec3.java +708 -0
  62. data/test/respond_to_test.rb +208 -0
  63. data/vendors/Rakefile +48 -0
  64. metadata +130 -0
@@ -0,0 +1,10 @@
1
+ # If you want to support more platforms, visit jogamp.org to get the
2
+ # natives libraries for the platform in question (i.e. Solaris).
3
+
4
+ name = OpenGL
5
+
6
+ application.macosx=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-macosx-universal.jar,gluegen-rt-natives-macosx-universal.jar
7
+ application.windows32=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-windows-i586.jar,gluegen-rt-natives-windows-i586.jar
8
+ application.windows64=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-windows-amd64.jar,gluegen-rt-natives-windows-amd64.jar
9
+ application.linux32=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-linux-i586.jar,gluegen-rt-natives-linux-i586.jar
10
+ application.linux64=core.jar,jogl-all.jar,gluegen-rt.jar,jogl-all-natives-linux-amd64.jar,gluegen-rt-natives-linux-amd64.jar
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+ unless defined? PROPANE_ROOT
4
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
5
+ PROPANE_ROOT = File.expand_path(File.dirname(__FILE__) + '/../')
6
+ end
7
+ Dir["#{PROPANE_ROOT}/lib/*.jar"].each do |jar|
8
+ require jar
9
+ end
10
+ require 'propane/version'
11
+ require 'propane/app'
12
+ require 'propane/helpers/numeric'
@@ -0,0 +1,197 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+ require_relative 'underscorer'
4
+ require_relative 'helper_methods'
5
+ require_relative 'library_loader'
6
+
7
+ module Propane
8
+ include_package 'processing.core' # imports the processing jar.
9
+ # Load vecmath, fastmath and mathtool modules
10
+ Java::Monkstone::PropaneLibrary.load(JRuby.runtime)
11
+ # We may change this
12
+ module Render
13
+ java_import 'monkstone.vecmath.AppRender'
14
+ java_import 'monkstone.vecmath.ShapeRender'
15
+ end
16
+
17
+
18
+
19
+ # This class is the base class the user should inherit from when making
20
+ # their own sketch.
21
+ #
22
+ # i.e.
23
+ #
24
+ # class MySketch < Propane::App
25
+ #
26
+ # def draw
27
+ # background rand(255)
28
+ # end
29
+ #
30
+ # end
31
+ class App < PApplet
32
+ include Math
33
+ include HelperMethods
34
+ attr_reader :title, :arguments, :options
35
+ # App should be instantiated with an optional list of options
36
+ # and array of arguments.
37
+ #
38
+ # App.new(width: 500, height: 500, fullscreen: true)
39
+ #
40
+ class << self
41
+ # Handy getters and setters on the class go here:
42
+ attr_accessor :sketch_class, :library_loader
43
+
44
+ def load_libraries(*args)
45
+ library_loader ||= LibraryLoader.new
46
+ library_loader.load_library(*args)
47
+ end
48
+ alias_method :load_library, :load_libraries
49
+
50
+ def library_loaded?(library_name)
51
+ library_loader.library_loaded?(library_name)
52
+ end
53
+
54
+ def load_ruby_library(*args)
55
+ library_loader.load_ruby_library(*args)
56
+ end
57
+
58
+ def load_java_library(*args)
59
+ library_loader.load_java_library(*args)
60
+ end
61
+ end
62
+
63
+ def library_loaded?(library_name)
64
+ self.class.library_loaded?(library_name)
65
+ end
66
+
67
+
68
+ def initialize(options = {}, arguments = [])
69
+ # Guard against invalid input.
70
+ proxy_java_fields
71
+ raise TypeError unless options.is_a? Hash
72
+ raise TypeError unless arguments.is_a? Array
73
+ # Set up the sketch.
74
+ super()
75
+ $app = self
76
+ @arguments = arguments
77
+ @options = options
78
+ configure_sketch
79
+ run_sketch
80
+ end
81
+
82
+ def size(*args)
83
+ w, h, mode = *args
84
+ @width ||= w
85
+ @height ||= h
86
+ @render_mode ||= mode
87
+ import_opengl if /opengl/ =~ mode
88
+ super(*args)
89
+ end
90
+
91
+ # This method runs the processing sketch.
92
+ #
93
+ def run_sketch
94
+ PApplet.run_sketch(arguments, self)
95
+ end
96
+
97
+ # Is the mouse pressed for this frame?
98
+ def mouse_pressed?
99
+ @declared_fields['mousePressed'].value(java_self)
100
+ end
101
+
102
+ # Is a key pressed for this frame?
103
+ def key_pressed?
104
+ @declared_fields['keyPressed'].value(java_self)
105
+ end
106
+
107
+ # Fix java conversion problems getting the last key
108
+ # If it's ASCII, return the character, otherwise the integer
109
+ def key
110
+ int = @declared_fields['key'].value(java_self)
111
+ int < 256 ? int.chr : int
112
+ end
113
+
114
+ private
115
+
116
+ # Provide a convenient handle for the Java-space version of self.
117
+ def java_self
118
+ @java_self ||= to_java(Java::ProcessingCore::PApplet)
119
+ end
120
+
121
+ def import_opengl
122
+ # Include processing opengl classes that we'd like to use:
123
+ %w(FontTexture FrameBuffer LinePath LineStroker PGL
124
+ PGraphics2D PGraphics3D PGraphicsOpenGL PShader
125
+ PShapeOpenGL Texture).each do |klass|
126
+ java_import "processing.opengl.#{klass}"
127
+ end
128
+ end
129
+
130
+ # This method configures the sketch title and and presentation mode.
131
+ #
132
+ def configure_sketch
133
+ set_sketch_title
134
+ set_presentation_mode
135
+ end
136
+
137
+ # This method sets the sketch presentation mode.
138
+ #
139
+ def set_presentation_mode
140
+ arguments.concat ['--present'] if options[:fullscreen]
141
+ end
142
+
143
+ # This method sets the sketch title.
144
+ #
145
+ def set_sketch_title
146
+ title_string = options.fetch(:title, 'processing sketch')
147
+ arguments.concat [title_string]
148
+ end
149
+
150
+ %w(displayHeight displayWidth frameCount keyCode
151
+ mouseButton mouseX mouseY pmouseX pmouseY).each do |name|
152
+ sc_name = name.split(/(?![a-z])(?=[A-Z])/).map(&:downcase).join('_')
153
+ alias_method sc_name, name
154
+ end
155
+
156
+ def self.method_added(name)
157
+ name = name.to_s
158
+ if name.include?('_')
159
+ lcc_name = name.split('_').map(&:capitalize).join('')
160
+ lcc_name[0] = lcc_name[0].downcase
161
+ alias_method lcc_name, name if lcc_name != name
162
+ end
163
+ end
164
+
165
+ def method_missing(name, *args)
166
+ self.class.__send__(name, *args) if PApplet.public_methods.include?(name)
167
+ end
168
+
169
+ def proxy_java_fields
170
+ fields = %w(sketchPath key frameRate mousePressed keyPressed)
171
+ methods = fields.map { |field| java_class.declared_field(field) }
172
+ @declared_fields = Hash[fields.zip(methods)]
173
+ end
174
+
175
+ # Fix java conversion problems getting the last key
176
+ # If it's ASCII, return the character, otherwise the integer
177
+ # def self.key
178
+ # int = @declared_fields['key'].value(java_self)
179
+ # int < 256 ? int.chr : int
180
+ # end
181
+ end
182
+
183
+ # Importing PConstants to access to processing constants,
184
+ # to keep namespace clean use PConstants::TRIANGLE (for example)
185
+ # or to use bare TRIANGLE also 'include PConstants'
186
+ # Using :method_missing to mimic inner class methods
187
+ # @HACK you should consider using 'forwardable' to avoid this
188
+ # egregious hack...
189
+ module Proxy
190
+ java_import 'processing.core.PConstants'
191
+
192
+ def method_missing(name, *args)
193
+ return $app.send(name, *args) if $app && $app.respond_to?(name)
194
+ super
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,177 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+ module Propane
4
+ module HelperMethods
5
+ # processings epsilon may not be defined yet
6
+ EPSILON ||= 1.0e-04
7
+ # Nice block method to draw to a buffer.
8
+ # You can optionally pass it a width, a height, and a renderer.
9
+ # Takes care of starting and ending the draw for you.
10
+ def buffer(buf_width = width, buf_height = height, renderer = @render_mode)
11
+ buf = create_graphics(buf_width, buf_height, renderer)
12
+ buf.begin_draw
13
+ yield buf
14
+ buf.end_draw
15
+ buf
16
+ end
17
+
18
+ # A nice method to run a given block for a grid.
19
+ # Lifted from action_coding/Nodebox.
20
+ def grid(cols, rows, col_size = 1, row_size = 1)
21
+ (0...cols * rows).map do |i|
22
+ x = col_size * (i % cols)
23
+ y = row_size * i.div(cols)
24
+ yield x, y
25
+ end
26
+ end
27
+
28
+ # lerp_color takes three or four arguments, in Java that's two
29
+ # different methods, one regular and one static, so:
30
+ def lerp_color(*args)
31
+ args.length > 3 ? self.class.lerp_color(*args) : super(*args)
32
+ end
33
+
34
+ def color(*args)
35
+ return super(*args) unless args.length == 1
36
+ super(hex_color(args[0]))
37
+ end
38
+
39
+ # Overrides Processing convenience function thread, which takes a String
40
+ # arg (for a function) to more rubylike version, takes a block...
41
+ def thread(&block)
42
+ if block_given?
43
+ Thread.new(&block)
44
+ else
45
+ raise ArgumentError, 'thread must be called with a block', caller
46
+ end
47
+ end
48
+
49
+ # explicitly provide 'processing.org' min instance method
50
+ # to return a float:- a, b and c need to be floats
51
+
52
+ def min(*args)
53
+ args.min # { |a,b| a <=> b } optional block not reqd
54
+ end
55
+
56
+ # explicitly provide 'processing.org' max instance method
57
+ # to return a float:- a, b and c need to be floats
58
+
59
+ def max(*args)
60
+ args.max # { |a, b| a <=> b } optional block not reqd
61
+ end
62
+
63
+ # explicitly provide 'processing.org' dist instance method
64
+ def dist(*args)
65
+ len = args.length
66
+ return dist2d(*args) if len == 4
67
+ return dist3d(*args) if len == 6
68
+ raise ArgumentError, 'takes 4 or 6 parameters'
69
+ end
70
+
71
+ # Uses PImage class method under hood
72
+ def blend_color(c1, c2, mode)
73
+ Java::ProcessingCore::PImage.blendColor(c1, c2, mode)
74
+ end
75
+
76
+ # There's just so many functions in Processing,
77
+ # Here's a convenient way to look for them.
78
+ def find_method(method_name)
79
+ reg = Regexp.new(method_name.to_s, true)
80
+ methods.sort.select { |meth| reg.match(meth) }
81
+ end
82
+
83
+ # Proxy over a list of Java declared fields that have the same name as
84
+ # some methods. Add to this list as needed.
85
+ def proxy_java_fields
86
+ fields = %w(sketchPath key frameRate frame mousePressed keyPressed)
87
+ methods = fields.map { |field| java_class.declared_field(field) }
88
+ @declared_fields = Hash[fields.zip(methods)]
89
+ end
90
+
91
+ class VersionError < StandardError
92
+ end
93
+
94
+ # By default, your sketch path is the folder that your sketch is in.
95
+ # If you'd like to do something fancy, feel free.
96
+ def set_sketch_path(spath = nil)
97
+ field = @declared_fields['sketchPath']
98
+ begin
99
+ field.set_value(java_self, spath || SKETCH_ROOT)
100
+ rescue TypeError
101
+ raise VersionError, 'Use JRubyArt for processing-3.0'
102
+ end
103
+ end
104
+
105
+
106
+
107
+ # Provide a convenient handle for the Java-space version of self.
108
+ #def java_self
109
+ # @java_self ||= to_java(Java::ProcessingCore::PApplet)
110
+ #end
111
+
112
+ # Get the sketch path
113
+ def sketch_path
114
+ @declared_fields['sketchPath'].value(java_self)
115
+ end
116
+
117
+ # Fields that should be made accessible as under_scored.
118
+ define_method(:mouse_x) { mouseX }
119
+
120
+ define_method(:mouse_y) { mouseY }
121
+
122
+ define_method(:pmouse_x) { pmouseX }
123
+
124
+ define_method(:pmouse_y) { pmouseY }
125
+
126
+ define_method(:frame_count) { frameCount }
127
+
128
+ define_method(:mouse_button) { mouseButton }
129
+
130
+ define_method(:key_code) { keyCode }
131
+
132
+ # Ensure that load_strings returns a real Ruby array
133
+ def load_strings(file_or_url)
134
+ loadStrings(file_or_url).to_a
135
+ end
136
+
137
+ # Writes an array of strings to a file, one line per string.
138
+ # This file is saved to the sketch's data folder
139
+ def save_strings(filename, strings)
140
+ saveStrings(filename, [strings].flatten.to_java(:String))
141
+ end
142
+
143
+ # frame_rate needs to support reading and writing
144
+ def frame_rate(fps = nil)
145
+ return @declared_fields['frameRate'].value(java_self) unless fps
146
+ super(fps)
147
+ end
148
+
149
+
150
+ private
151
+
152
+ # parse single argument color int/double/String
153
+ def hex_color(a)
154
+ return Java::Monkstone::ColorUtil.colorLong(a) if a.is_a?(Fixnum)
155
+ if a.is_a?(String)
156
+ return Java::Monkstone::ColorUtil.colorString(a) if a =~ /#\h+/
157
+ raise StandardError, 'Dodgy Hexstring'
158
+ end
159
+ Java::Monkstone::ColorUtil.colorDouble(a)
160
+ end
161
+
162
+ def dist2d(*args)
163
+ dx = args[0] - args[2]
164
+ dy = args[1] - args[3]
165
+ return 0 if dx.abs < EPSILON && dy.abs < EPSILON
166
+ Math.hypot(dx, dy)
167
+ end
168
+
169
+ def dist3d(*args)
170
+ dx = args[0] - args[3]
171
+ dy = args[1] - args[4]
172
+ dz = args[2] - args[5]
173
+ return 0 if dx.abs < EPSILON && dy.abs < EPSILON && dz.abs < EPSILON
174
+ Math.sqrt(dx * dx + dy * dy + dz * dz)
175
+ end
176
+ end
177
+ 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,117 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+
4
+ require "#{PROPANE_ROOT}/lib/propane"
5
+
6
+ # The processing wrapper module
7
+ module Propane
8
+ # Encapsulate library loader functionality as a class
9
+ class LibraryLoader
10
+ def initialize
11
+ @loaded_libraries = Hash.new(false)
12
+ end
13
+
14
+ # Detect if a library has been loaded (for conditional loading)
15
+ def library_loaded?(library_name)
16
+ @loaded_libraries[library_name.to_sym]
17
+ end
18
+
19
+ # Load a list of Ruby or Java libraries (in that order)
20
+ # Usage: load_libraries :opengl, :boids
21
+ #
22
+ # If a library is put into a 'library' folder next to the sketch it will
23
+ # be used instead of the library that ships with Propane.
24
+ def load_libraries(*args)
25
+ message = 'no such file to load -- %s'
26
+ args.each do |lib|
27
+ loaded = load_ruby_library(lib) || load_java_library(lib)
28
+ fail(LoadError.new, format(message, lib)) unless loaded
29
+ end
30
+ end
31
+ alias_method :load_library, :load_libraries
32
+
33
+ # For pure ruby libraries.
34
+ # The library should have an initialization ruby file
35
+ # of the same name as the library folder.
36
+ def load_ruby_library(library_name)
37
+ library_name = library_name.to_sym
38
+ return true if @loaded_libraries.include?(library_name)
39
+ path = get_library_paths(library_name, 'rb').first
40
+ return false unless path
41
+ @loaded_libraries[library_name] = (require path)
42
+ end
43
+
44
+ # HACK: For pure java libraries, such as the ones that are available
45
+ # on this page: http://processing.org/reference/libraries/index.html
46
+ # that include native code, we mess with the 'Java ClassLoader', so that
47
+ # you don't have to futz with your PATH. But it's probably bad juju.
48
+ def load_java_library(library_name)
49
+ library_name = library_name.to_sym
50
+ return true if @loaded_libraries.include?(library_name)
51
+ jpath = get_library_directory_path(library_name, 'jar')
52
+ jars = get_library_paths(library_name, 'jar')
53
+ return false if jars.empty?
54
+ jars.each { |jar| require jar }
55
+ platform_specific_library_paths = get_platform_specific_library_paths(jpath)
56
+ platform_specific_library_paths = platform_specific_library_paths.select do |ppath|
57
+ FileTest.directory?(ppath) && !Dir.glob(File.join(ppath, '*.{so,dll,jnilib}')).empty?
58
+ end
59
+ unless platform_specific_library_paths.empty?
60
+ platform_specific_library_paths << java.lang.System.getProperty('java.library.path')
61
+ new_library_path = platform_specific_library_paths.join(java.io.File.pathSeparator)
62
+ java.lang.System.setProperty('java.library.path', new_library_path)
63
+ field = java.lang.Class.for_name('java.lang.ClassLoader').get_declared_field('sys_paths')
64
+ if field
65
+ field.accessible = true
66
+ field.set(java.lang.Class.for_name('java.lang.System').get_class_loader, nil)
67
+ end
68
+ end
69
+ @loaded_libraries[library_name] = true
70
+ end
71
+
72
+ def platform
73
+ match = %w(mac linux windows).find do |os|
74
+ java.lang.System.getProperty('os.name').downcase.index(os)
75
+ end
76
+ return 'other' unless match
77
+ return match unless match =~ /mac/
78
+ 'macosx'
79
+ end
80
+
81
+ def get_platform_specific_library_paths(basename)
82
+ # for MacOSX, but does this even work, or does Mac return '64'?
83
+ bits = 'universal'
84
+ if java.lang.System.getProperty('sun.arch.data.model') == '32' ||
85
+ java.lang.System.getProperty('java.vm.name').index('32')
86
+ bits = '32'
87
+ elsif java.lang.System.getProperty('sun.arch.data.model') == '64' ||
88
+ java.lang.System.getProperty('java.vm.name').index('64')
89
+ bits = '64' unless platform =~ /macosx/
90
+ end
91
+ [platform, platform + bits].map { |p| File.join(basename, p) }
92
+ end
93
+
94
+ def get_library_paths(library_name, extension = nil)
95
+ dir = get_library_directory_path(library_name, extension)
96
+ Dir.glob("#{dir}/*.{rb,jar}")
97
+ end
98
+
99
+ protected
100
+
101
+ def get_library_directory_path(library_name, extension = nil)
102
+ extensions = extension ? [extension] : %w(jar rb)
103
+ extensions.each do |ext|
104
+ [
105
+ "#{PROPANE_ROOT}/library/#{library_name}",
106
+ "#{PROPANE_ROOT}/library/#{library_name}/library",
107
+ "#{PROPANE_ROOT}/library/#{library_name}"
108
+ ].each do |jpath|
109
+ if File.exist?(jpath) && !Dir.glob(format('%s/*.%s', jpath, ext)).empty?
110
+ return jpath
111
+ end
112
+ end
113
+ end
114
+ nil
115
+ end
116
+ end
117
+ end