propane 0.3.0.pre-java

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 (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