├── .yardopts ├── favicon.ico ├── src └── main │ ├── resources │ └── icon │ │ ├── icon-128.png │ │ ├── icon-16.png │ │ ├── icon-256.png │ │ ├── icon-32.png │ │ ├── icon-48.png │ │ ├── icon-512.png │ │ ├── icon-64.png │ │ └── icon-1024.png │ └── java │ ├── processing │ ├── opengl │ │ ├── cursors │ │ │ ├── arrow.png │ │ │ ├── cross.png │ │ │ ├── hand.png │ │ │ ├── move.png │ │ │ ├── text.png │ │ │ ├── wait.png │ │ │ └── license.txt │ │ ├── shaders │ │ │ ├── ColorFrag.glsl │ │ │ ├── LineFrag.glsl │ │ │ ├── PointFrag.glsl │ │ │ ├── ColorVert.glsl │ │ │ ├── LightFrag.glsl │ │ │ ├── TexFrag.glsl │ │ │ ├── TexLightFrag.glsl │ │ │ ├── TexVert.glsl │ │ │ ├── MaskFrag.glsl │ │ │ ├── PointVert.glsl │ │ │ └── LineVert.glsl │ │ └── VertexBuffer.java │ ├── javafx │ │ └── PGraphicsFX2D.java │ ├── data │ │ └── Sort.java │ ├── core │ │ ├── PStyle.java │ │ └── ThinkDifferent.java │ └── event │ │ ├── KeyEvent.java │ │ ├── TouchEvent.java │ │ ├── MouseEvent.java │ │ └── Event.java │ ├── japplemenubar │ ├── libjAppleMenuBar.jnilib │ └── JAppleMenuBar.java │ └── monkstone │ ├── fastmath │ ├── package-info.java │ ├── Deglut.java │ └── DegLutTables.java │ ├── vecmath │ ├── vec2 │ │ └── package-info.java │ ├── vec3 │ │ └── package-info.java │ ├── package-info.java │ ├── JRender.java │ ├── GfxRender.java │ └── ShapeRender.java │ ├── core │ ├── package-info.java │ └── LibraryProxy.java │ ├── arcball │ ├── package-info.java │ ├── WheelHandler.java │ ├── Constrain.java │ ├── Quaternion.java │ ├── Rarcball.java │ └── Jvector.java │ ├── videoevent │ ├── package-info.java │ ├── CaptureEvent.java │ └── MovieEvent.java │ ├── slider │ ├── Slider.java │ ├── WheelHandler.java │ ├── SliderGroup.java │ ├── SimpleSlider.java │ └── SimpleHorizontalSlider.java │ ├── filechooser │ └── Chooser.java │ ├── PropaneLibrary.java │ ├── JRLibrary.java │ ├── ColorUtil.java │ └── FastNoiseModuleJava.java ├── lib ├── jruby_art │ ├── runners │ │ ├── run.rb │ │ ├── live.rb │ │ ├── base.rb │ │ └── watch.rb │ ├── version.rb │ ├── jruby_complete.rb │ ├── helpers │ │ ├── numeric.rb │ │ └── aabb.rb │ ├── default_config.rb │ ├── java_opts.rb │ ├── processing_ide.rb │ ├── installer.rb │ ├── native_loader.rb │ ├── native_folder.rb │ ├── config.rb │ ├── library_loader.rb │ ├── launcher.rb │ ├── library.rb │ └── creators │ │ └── sketch_writer.rb └── jruby_art.rb ├── library ├── dxf │ └── dxf.rb ├── net │ └── net.rb ├── pdf │ └── pdf.rb ├── svg │ └── svg.rb ├── video_event │ └── video_event.rb ├── chooser │ └── chooser.rb ├── color_group │ └── color_group.rb ├── library_proxy │ ├── library_proxy.rb │ └── README.md ├── slider │ └── slider.rb └── vector_utils │ └── vector_utils.rb ├── .travis.yml ├── test ├── sketches │ ├── setup_ex.rb │ ├── graphics.rb │ ├── basic.rb │ ├── installed_java.rb │ ├── processing_java.rb │ ├── local_java.rb │ ├── on_top.rb │ ├── sketch_path.rb │ ├── noise.rb │ ├── fx2d.rb │ ├── p2d.rb │ └── p3d.rb ├── test_helper.rb ├── test_java_args.rb ├── README.md ├── installer_test.rb ├── deglut_spec_test.rb ├── test_command.rb ├── color_group_test.rb ├── aabb_spec_test.rb ├── native_folder.rb ├── smooth_noise_test.rb ├── fast_noise_test.rb ├── helper_methods_test.rb ├── create_test.rb ├── test_map1d.rb ├── k9_run_test.rb └── math_tool_test.rb ├── .mvn ├── wrapper │ ├── maven-wrapper.properties │ └── MavenWrapperDownloader.java └── extensions.xml ├── bin └── k9 ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE.md └── CONTRIBUTING.md ├── ACKNOWLEDGEMENTS.md ├── .gitignore ├── Rakefile ├── jruby_art.gemspec ├── pom.rb ├── CHANGELOG.md ├── README.md └── vendors └── Rakefile /.yardopts: -------------------------------------------------------------------------------- 1 | --markup markdown 2 | - 3 | CHANGELOG.md 4 | LICENSE.md 5 | README.md 6 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/favicon.ico -------------------------------------------------------------------------------- /src/main/resources/icon/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/resources/icon/icon-128.png -------------------------------------------------------------------------------- /src/main/resources/icon/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/resources/icon/icon-16.png -------------------------------------------------------------------------------- /src/main/resources/icon/icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/resources/icon/icon-256.png -------------------------------------------------------------------------------- /src/main/resources/icon/icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/resources/icon/icon-32.png -------------------------------------------------------------------------------- /src/main/resources/icon/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/resources/icon/icon-48.png -------------------------------------------------------------------------------- /src/main/resources/icon/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/resources/icon/icon-512.png -------------------------------------------------------------------------------- /src/main/resources/icon/icon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/resources/icon/icon-64.png -------------------------------------------------------------------------------- /lib/jruby_art/runners/run.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'base' 4 | 5 | Processing.load_and_run_sketch 6 | -------------------------------------------------------------------------------- /src/main/resources/icon/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/resources/icon/icon-1024.png -------------------------------------------------------------------------------- /lib/jruby_art/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # A wrapper for version 4 | module JRubyArt 5 | VERSION = '2.6.1' 6 | end 7 | -------------------------------------------------------------------------------- /library/dxf/dxf.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # @TODO usage 4 | class Processing::App 5 | java_import Java::ProcessingDxf::RawDXF 6 | end 7 | -------------------------------------------------------------------------------- /src/main/java/processing/opengl/cursors/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/java/processing/opengl/cursors/arrow.png -------------------------------------------------------------------------------- /src/main/java/processing/opengl/cursors/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/java/processing/opengl/cursors/cross.png -------------------------------------------------------------------------------- /src/main/java/processing/opengl/cursors/hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/java/processing/opengl/cursors/hand.png -------------------------------------------------------------------------------- /src/main/java/processing/opengl/cursors/move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/java/processing/opengl/cursors/move.png -------------------------------------------------------------------------------- /src/main/java/processing/opengl/cursors/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/java/processing/opengl/cursors/text.png -------------------------------------------------------------------------------- /src/main/java/processing/opengl/cursors/wait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/java/processing/opengl/cursors/wait.png -------------------------------------------------------------------------------- /src/main/java/japplemenubar/libjAppleMenuBar.jnilib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruby-processing/JRubyArt/HEAD/src/main/java/japplemenubar/libjAppleMenuBar.jnilib -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | dist: bionic 3 | 4 | rvm: 5 | - jruby-9.2.11.0 6 | jdk: 7 | - openjdk11 8 | os: 9 | - linux 10 | 11 | addons: 12 | apt: 13 | update: true 14 | -------------------------------------------------------------------------------- /library/net/net.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # @TODO usage 4 | class Processing::App 5 | java_import Java::ProcessingNet::Client 6 | java_import Java::ProcessingNet::Server 7 | end 8 | -------------------------------------------------------------------------------- /library/pdf/pdf.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # @TODO usage 4 | class Processing::App 5 | require_relative 'itextpdf-5.5.13.2.jar' 6 | java_import Java::ProcessingPdf::PGraphicsPDF 7 | end 8 | -------------------------------------------------------------------------------- /library/svg/svg.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # @TODO usage 4 | class Processing::App 5 | require_relative 'batik-all-1.14.jar' 6 | java_import Java::ProcessingSvg::PGraphicsSVG 7 | end 8 | -------------------------------------------------------------------------------- /library/video_event/video_event.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # include interfaces 4 | class Processing::App 5 | include Java::MonkstoneVideoevent::MovieEvent 6 | include Java::MonkstoneVideoevent::CaptureEvent 7 | end 8 | -------------------------------------------------------------------------------- /test/sketches/setup_ex.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def setup 4 | unknown_method 5 | rescue StandardError => e 6 | puts e 7 | exit 8 | end 9 | 10 | def draw; end 11 | 12 | def settings 13 | size(300, 300) 14 | end 15 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /test/sketches/graphics.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def setup 4 | puts Java::ProcessingOpengl::PGraphicsOpenGL.OPENGL_VERSION 5 | end 6 | 7 | def draw 8 | exit 9 | end 10 | 11 | def settings 12 | size(100, 100, P3D) 13 | end 14 | -------------------------------------------------------------------------------- /.mvn/extensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | io.takari.polyglot 5 | polyglot-ruby 6 | 0.4.8 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/monkstone/fastmath/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package monkstone.fastmath; 7 | -------------------------------------------------------------------------------- /test/sketches/basic.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def setup 4 | frame_rate(10) 5 | end 6 | 7 | def draw 8 | background 0 9 | return unless frame_count == 5 10 | 11 | puts 'ok' 12 | exit 13 | end 14 | 15 | def settings 16 | size(300, 300) 17 | end 18 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | gem 'minitest' # don't use bundled minitest 4 | require 'jruby' 5 | require 'minitest/autorun' 6 | require 'minitest/pride' 7 | require_relative '../lib/jruby_art' 8 | require "#{K9_ROOT}/lib/jruby_art-#{JRubyArt::VERSION}.jar" 9 | -------------------------------------------------------------------------------- /src/main/java/monkstone/vecmath/vec2/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package monkstone.vecmath.vec2; 7 | -------------------------------------------------------------------------------- /src/main/java/monkstone/vecmath/vec3/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package monkstone.vecmath.vec3; 7 | -------------------------------------------------------------------------------- /bin/k9: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | file = __FILE__ 5 | if test('l', file) 6 | require 'pathname' 7 | file = Pathname.new(file).realpath 8 | end 9 | 10 | require File.expand_path(File.dirname(file) + '/../lib/jruby_art') 11 | Processing::Runner.execute 12 | -------------------------------------------------------------------------------- /test/sketches/installed_java.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | load_library :hype 4 | 5 | def settings 6 | size 200, 200 7 | end 8 | 9 | def setup 10 | sketch_title 'Installed Java' 11 | puts library_loaded?(:hype) ? 'ok' : 'oops?' 12 | end 13 | 14 | def draw 15 | exit 16 | end 17 | -------------------------------------------------------------------------------- /test/sketches/processing_java.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | load_library :pdf 4 | 5 | def settings 6 | size 200, 200 7 | end 8 | 9 | def setup 10 | sketch_title 'Processing Java' 11 | puts library_loaded?(:pdf) ? 'ok' : 'oops?' 12 | end 13 | 14 | def draw 15 | exit 16 | end 17 | -------------------------------------------------------------------------------- /test/sketches/local_java.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | load_library :test_sound 4 | 5 | def settings 6 | size 200, 200 7 | end 8 | 9 | def setup 10 | sketch_title 'Local Java' 11 | puts library_loaded?(:test_sound) ? 'ok' : 'oops?' 12 | end 13 | 14 | def draw 15 | exit 16 | end 17 | -------------------------------------------------------------------------------- /test/sketches/on_top.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def setup 4 | sketch_title 'On Top' 5 | on_top 6 | frame_rate(10) 7 | end 8 | 9 | def draw 10 | background 0 11 | return unless frame_count == 5 12 | 13 | puts 'ok' 14 | exit 15 | end 16 | 17 | def settings 18 | size(300, 300) 19 | end 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ### Fixes 10 | 11 | Some Issue 12 | 13 | ### Describe Proposed Changes 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /lib/jruby_art/jruby_complete.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class JRubyComplete 4 | def self.complete 5 | rcomplete = File.join(K9_ROOT, 'lib/ruby/jruby-complete.jar') 6 | return [rcomplete] if FileTest.exist?(rcomplete) 7 | 8 | warn "#{rcomplete} does not exist\nTry running `k9 --install`" 9 | exit 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/sketches/sketch_path.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | java_alias :background_int, :background, [Java::int] 4 | 5 | def setup 6 | sketchPath(SKETCH_ROOT) 7 | frame_rate(10) 8 | puts sketchPath 9 | end 10 | 11 | def draw 12 | background_int 0 13 | exit if frame_count == 5 14 | end 15 | 16 | def settings 17 | size(300, 300) 18 | end 19 | -------------------------------------------------------------------------------- /test/sketches/noise.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def setup 4 | sketch_title('Noise sketch') 5 | color_mode(HSB, 1.0) 6 | frame_rate(10) 7 | end 8 | 9 | def draw 10 | background(noise(1, 1, 3, 0.2), 1.0, 1.0) 11 | return unless frame_count == 5 12 | 13 | puts 'ok' 14 | exit 15 | end 16 | 17 | def settings 18 | size(300, 300) 19 | end 20 | -------------------------------------------------------------------------------- /lib/jruby_art/helpers/numeric.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Re-open Numeric so that we can do simple degree and radian conversions 4 | # conversion factors are 180 / Math::PI and Math::PI / 180 5 | 6 | class Numeric #:nodoc: 7 | def degrees 8 | self * 57.29577951308232 9 | end 10 | 11 | def radians 12 | self * 0.017453292519943295 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /test/sketches/fx2d.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | java_alias :background_int, :background, [Java::int] 4 | 5 | def setup 6 | sketch_title('P2D sketch') 7 | frame_rate(10) 8 | end 9 | 10 | def draw 11 | background_int 255 12 | return unless frame_count == 5 13 | 14 | puts 'ok' 15 | exit 16 | end 17 | 18 | def settings 19 | size(300, 300, FX2D) 20 | end 21 | -------------------------------------------------------------------------------- /test/sketches/p2d.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | java_alias :background_int, :background, [Java::int] 4 | 5 | def setup 6 | sketch_title('P2D sketch') 7 | frame_rate(10) 8 | end 9 | 10 | def draw 11 | background_int 255 12 | return unless frame_count == 3 13 | 14 | puts 'ok' 15 | exit 16 | end 17 | 18 | def settings 19 | size(300, 300, P2D) 20 | end 21 | -------------------------------------------------------------------------------- /lib/jruby_art/default_config.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # default configuration 4 | class Default 5 | def self.config 6 | { 7 | 'processing_ide' => false, 8 | 'library_path' => File.join(ENV['HOME'], '.jruby_art', 'libraries'), 9 | 'MAX_WATCH' => 32, 10 | 'JRUBY' => true, 11 | 'template' => 'bare', 12 | 'java_args' => nil 13 | } 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/sketches/p3d.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | java_alias :background_float_float_float, :background, [Java::float, Java::float, Java::float] 4 | 5 | def setup 6 | frame_rate(10) 7 | end 8 | 9 | def draw 10 | background_float_float_float 39, 232, 51 11 | return unless frame_count == 5 12 | 13 | puts 'ok' 14 | exit 15 | end 16 | 17 | def settings 18 | size(300, 300, P3D) 19 | end 20 | -------------------------------------------------------------------------------- /test/test_java_args.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | require_relative '../lib/jruby_art/java_opts' 5 | 6 | JAVA = %w[-Xmx512 -Xms1G].freeze 7 | JRUBY = %w[-J-Xmx512 -J-Xms1G].freeze 8 | # Java Args Test 9 | class JavaArgsTest < Minitest::Test 10 | attr_reader :root 11 | def setup 12 | @root = './' 13 | end 14 | 15 | def test_java 16 | assert_equal JAVA, JavaOpts.new(root).opts 17 | end 18 | 19 | def test_jruby 20 | assert_equal JRUBY, JRubyOpts.new(root).opts 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/jruby_art/runners/live.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | 3 | # A pry shell for live coding. 4 | # Will start with your sketch. 5 | require_relative 'base' 6 | Processing.load_and_run_sketch 7 | 8 | # Custom Exception 9 | class PryException < StandardError 10 | MESSAGE = "You need to 'jruby -S gem install pry' for 'live' mode".freeze 11 | 12 | def initialize(msg = MESSAGE) 13 | super 14 | end 15 | end 16 | 17 | raise PryException unless Gem::Specification.find_all_by_name('pry').any? 18 | 19 | require 'pry' 20 | Processing.app.pry 21 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | Minitest 2 | ======== 3 | 4 | OK strictly the tests should directly test objects, rather than the indirect tests on io here. These test make use of minitest capture_io (this seems to require real files rather than temp files?). Also there seems to be some problem with how the built in version minitest run so I've specified gem "minitest". The graphics test is designed to fail if your graphics setup does not supports opengl 3+, this may not be fatal, but as message states is probably suboptimal. 5 | 6 | [gist]:https://gist.github.com/monkstone/6145906 7 | -------------------------------------------------------------------------------- /library/chooser/chooser.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Usage: 4 | # load_library :chooser 5 | # 6 | # def setup 7 | # java_signature 'void selectInput(String, String)' 8 | # selectInput('Select a file to process:', 'fileSelected') 9 | # end 10 | # 11 | # def fileSelected(selection) 12 | # if selection.nil? 13 | # puts 'Window was closed or the user hit cancel.' 14 | # else 15 | # puts format('User selected %s', selection.get_absolute_path) 16 | # end 17 | # end 18 | class Processing::App 19 | include Java::MonkstoneFilechooser::Chooser 20 | end 21 | -------------------------------------------------------------------------------- /test/installer_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | require_relative '../lib/jruby_art/installer' 5 | 6 | # Installer test 7 | class InstallerTest < Minitest::Test 8 | attr_reader :installer, :jruby 9 | def setup 10 | @installer = Installer.new 11 | @jruby = JRubyInstaller.new 12 | end 13 | 14 | def test_new_installer 15 | assert installer.is_a? Installer 16 | assert installer.respond_to? :install 17 | assert jruby.is_a? JRubyInstaller 18 | assert jruby.respond_to? :install 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /test/deglut_spec_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | 5 | Java::Monkstone::JRLibrary.new.load(JRuby.runtime, false) 6 | # Degree lookup table 7 | class DeglutTest < Minitest::Test 8 | attr_reader :to_radian 9 | 10 | def setup 11 | @to_radian = Math::PI / 180 12 | end 13 | 14 | def test_cos_sin 15 | (-720..720).step(1) do |deg| 16 | sine = DegLut.sin(deg) 17 | deg_sin = Math.sin(deg * to_radian) 18 | assert_in_delta(sine, deg_sin, 0.0003) 19 | cosine = DegLut.cos(deg) 20 | deg_cos = Math.cos(deg * to_radian) 21 | assert_in_delta(cosine, deg_cos, 0.0003) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/jruby_art/java_opts.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | 3 | # class to parse java_args.txt or java_args in config.yml 4 | class JavaOpts 5 | attr_reader :opts 6 | 7 | def initialize 8 | arg_file = File.join(SKETCH_ROOT, 'data/java_args.txt') 9 | @opts = [] 10 | @opts += File.read(arg_file).split(/\s+/) if FileTest.exist?(arg_file) 11 | return unless opts.empty? && Processing::RP_CONFIG.fetch('java_args', false) 12 | 13 | @opts += Processing::RP_CONFIG['java_args'].split(/\s+/) 14 | end 15 | end 16 | 17 | # wrap args to pass through to jvm from jruby 18 | class JRubyOpts < JavaOpts 19 | def opts 20 | super.map { |arg| "-J#{arg}" } 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/test_command.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | 5 | JAVA = %w[java -Xmx512 -Xms1G -cp /home/tux/JRubyArt/lib/ruby/jruby-complete.jar org.jruby.Main watch].freeze 6 | JRUBY = %w[jruby -J-Xmx512 -J-Xms1G watch].freeze 7 | 8 | # Java Args Tests 9 | class JavaArgsTest < Minitest::Test 10 | attr_reader :root 11 | def setup; end 12 | 13 | def test_java 14 | assert_equal JAVA.flatten, Processing::Command.new(executable: 'java', runner: 'watch', args: []).cmd('./') 15 | end 16 | 17 | def test_jruby 18 | assert_equal JRUBY.flatten, Processing::Command.new(executable: 'jruby', runner: 'watch', args: []).cmd('./') 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /library/color_group/color_group.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | java_import Java::Monkstone::ColorUtil 4 | 5 | # class wraps a java color array, supports shuffle!, last and ruby_string 6 | # as well as ability to initialize with an array of "web" color string 7 | class ColorGroup 8 | attr_reader :colors 9 | def initialize(p5cols) 10 | @colors = p5cols 11 | end 12 | 13 | def self.from_web_array(web) 14 | ColorGroup.new(ColorUtil.web_array(web.to_java(:string))) 15 | end 16 | 17 | def shuffle! 18 | @colors = ColorUtil.shuffle(colors) 19 | end 20 | 21 | def ruby_string 22 | ColorUtil.rubyString(colors) 23 | end 24 | 25 | def last 26 | colors[0] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /ACKNOWLEDGEMENTS.md: -------------------------------------------------------------------------------- 1 | # JRubyArt 2 | Depends on jruby, and processing, without them this project would not exist. I see this as being a development of ruby-processing and many others were involved in developing that see [github][] for a complete list of contributors. This is fresh start so for ruby-processing history see [github] logs. 3 | 4 | ## JRuby 5 | 6 | The whole @jruby team, including @headius and @enebo 7 | 8 | ## Processing 9 | 10 | The whole @ProcessingOrg team, especially @benfry, @REAS, and @codeanticode 11 | 12 | ## Ruby-processing 13 | 14 | Ruby-processing was started by @jashkenas, but there were many other contributors including @moumar, @fjennet. 15 | 16 | [github]:https://github.com/jashkenas/ruby-processing 17 | -------------------------------------------------------------------------------- /lib/jruby_art.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # JRubyArt is for Code Art. 3 | # Send suggestions, ideas, and hate-mail to mamba2928 [at] gmail.com 4 | # Also, send samples and libraries. 5 | unless defined? K9_ROOT 6 | $LOAD_PATH << File.dirname(__dir__) 7 | K9_ROOT = File.dirname(__dir__) 8 | end 9 | 10 | require "#{K9_ROOT}/lib/jruby_art/version" 11 | require "#{K9_ROOT}/lib/jruby_art/helpers/numeric" 12 | # inherited from ruby-processing, we could probably re-factor this but since 13 | # SKETCH_ROOT is used before instance of sketch is created leave it alone. 14 | SKETCH_ROOT ||= Dir.pwd 15 | 16 | # The top-level namespace, a home for all JRubyArt classes. 17 | module Processing 18 | require "#{K9_ROOT}/lib/jruby_art/runner" 19 | end 20 | -------------------------------------------------------------------------------- /library/library_proxy/library_proxy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | java_import Java::MonkstoneCore::LibraryProxy 4 | java_import Java::ProcessingEvent::KeyEvent 5 | java_import Java::ProcessingEvent::MouseEvent 6 | 7 | # classes that inherit from LibraryProxy are expected to implement 8 | # the abstract draw method of monkstone.core.LibraryProxy the other methods are 9 | # registered with PApplet instance in constructor ImplementingClass.new(app) 10 | # 11 | # def pre... NOOP can be overridden 12 | # def draw... Abstract Method should be implemented NOOP is OK 13 | # def post... NOOP can be overridden 14 | # def keyEvent(e)... NOOP can be overridden 15 | # def mouseEvent(e)... NOOP can be overridden 16 | # `app` can be called to get PApplet instance 17 | -------------------------------------------------------------------------------- /lib/jruby_art/helpers/aabb.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Axis aligned bounding box class (AABB would clash with Toxicgem) 4 | class AaBb 5 | attr_reader :center, :extent 6 | 7 | def initialize(center:, extent:) 8 | @center = center 9 | @extent = extent 10 | end 11 | 12 | def self.from_min_max(min:, max:) 13 | new(center: (min + max) * 0.5, extent: max - min) 14 | end 15 | 16 | def position(vec) 17 | return @center = vec unless block_given? 18 | 19 | @center = vec if yield 20 | end 21 | 22 | def scale(d) 23 | @extent *= d 24 | end 25 | 26 | def contains?(vec) 27 | rad = extent * 0.5 28 | return false unless (center.x - rad.x..center.x + rad.x).cover? vec.x 29 | 30 | (center.y - rad.y..center.y + rad.y).cover? vec.y 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/jruby_art/processing_ide.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # detects processing preferences.txt, extracts sketchbook_path 4 | class ProcessingIde 5 | THREE='sketchbook.path.three='.freeze 6 | FOUR='sketchbook.path.four='.freeze 7 | attr_reader :preferences 8 | def initialize 9 | @preferences = File.join(ENV['HOME'], '.processing', 'preferences.txt') 10 | end 11 | 12 | def installed? 13 | File.exist?(preferences) 14 | end 15 | 16 | def sketchbook_path 17 | File.open(preferences, 'r') do |file| 18 | file.each_line do |line| 19 | return line.tap { |sli| sli.slice!(FOUR) }.chomp if /sketchbook.path.four/.match?(line) 20 | 21 | return line.tap { |sli| sli.slice!(THREE) }.chomp if /sketchbook.path.three/.match?(line) 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | nb-configuration.xml 2 | *.gem 3 | *.rbc 4 | /.config 5 | /coverage/ 6 | /InstalledFiles 7 | /target/ 8 | /spec/reports/ 9 | /test/tmp/ 10 | /test/version_tmp/ 11 | /tmp/ 12 | *.swp 13 | *~ 14 | *.jar 15 | ## Specific to RubyMotion: 16 | .dat* 17 | .repl_history 18 | build/ 19 | MANIFEST.MF 20 | ## Documentation cache and generated files: 21 | /.yardoc/ 22 | /_yardoc/ 23 | /doc/ 24 | /rdoc/ 25 | 26 | ## Environment normalisation: 27 | /.bundle/ 28 | /vendor/bundle 29 | /lib/bundler/man/ 30 | 31 | # for a library or gem, you might want to ignore these files since the code is 32 | # intended to run in multiple environments; otherwise, check them in: 33 | # Gemfile.lock 34 | # .ruby-version 35 | # .ruby-gemset 36 | 37 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 38 | .rvmrc 39 | /nbproject/private/ 40 | -------------------------------------------------------------------------------- /test/color_group_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | require_relative '../library/color_group/color_group' 5 | 6 | Java::Monkstone::JRLibrary.load(JRuby.runtime) 7 | java_import Java::Monkstone::ColorUtil 8 | 9 | PALETTE = %w[#FFFFFF #FF0000 #0000FF].freeze 10 | COLORS = [16_777_215, 16_711_680, 255].to_java(:int) 11 | # ColorGroup Tests 12 | class ColorGroupTest < Minitest::Test 13 | def test_new 14 | group = ColorGroup.new(COLORS) 15 | assert group.is_a? ColorGroup 16 | end 17 | 18 | def test_web_array 19 | group = ColorGroup.from_web_array(PALETTE) 20 | assert group.is_a? ColorGroup 21 | end 22 | 23 | def test_ruby_string 24 | p5array = [16_777_215, 16_711_680, 255] 25 | group = ColorGroup.new(COLORS) 26 | ruby_string = "%w[#FFFFFF #FF0000 #0000FF]\n" 27 | result = group.ruby_string 28 | assert_equal(result, ruby_string) 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/jruby_art/installer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'config' 4 | require_relative 'processing_ide' 5 | 6 | class Installer 7 | attr_reader :processing_ide 8 | def initialize 9 | @processing_ide = ProcessingIde.new 10 | end 11 | 12 | def install 13 | config = if processing_ide.installed? 14 | Config.new( 15 | 'processing_ide' => true, 16 | 'library_path' => processing_ide.sketchbook_path 17 | ) 18 | else 19 | Config.new('processing_ide' => false) 20 | end 21 | config.write_to_file 22 | end 23 | end 24 | 25 | # Examples Installer 26 | class UnpackSamples 27 | def install 28 | system "cd #{K9_ROOT}/vendors && rake unpack_samples" 29 | end 30 | end 31 | 32 | # JRuby-Complete installer 33 | class JRubyCompleteInstall 34 | def install 35 | system "cd #{K9_ROOT}/vendors && rake" 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/aabb_spec_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | require_relative '../lib/jruby_art/helpers/aabb' 5 | 6 | Java::Monkstone::JRLibrary.new.load(JRuby.runtime, false) 7 | 8 | # AaBb test 9 | class AaBbTest < Minitest::Test 10 | def test_aabb_new 11 | x = 1.0000001 12 | y = 1.01 13 | a = Vec2D.new(x, y) 14 | assert AaBb.new(center: Vec2D.new, extent: a).is_a? AaBb 15 | x0 = -4 16 | y0 = -4 17 | a = Vec2D.new(x0, y0) 18 | b = a *= -1 19 | assert AaBb.from_min_max(min: a, max: b).is_a? AaBb 20 | x = 1.0000001 21 | y = 1.01 22 | a = AaBb.new(center: Vec2D.new, extent: Vec2D.new(x, y)) 23 | a.position(Vec2D.new(4, 6)) 24 | assert a.center == Vec2D.new(4, 6) 25 | x = 1.0000001 26 | y = 1.01 27 | a = AaBb.new(center: Vec2D.new, extent: Vec2D.new(x, y)) 28 | a.position(Vec2D.new(4, 6)) { false } 29 | assert a.center == Vec2D.new 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /src/main/java/monkstone/core/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.core; 21 | -------------------------------------------------------------------------------- /src/main/java/monkstone/vecmath/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.vecmath; 21 | -------------------------------------------------------------------------------- /src/main/java/monkstone/arcball/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | package monkstone.arcball; 22 | -------------------------------------------------------------------------------- /src/main/java/monkstone/videoevent/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.videoevent; 21 | -------------------------------------------------------------------------------- /lib/jruby_art/native_loader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This class knows how to dynamically set the 'java' native library path 4 | # It might not work with java 9? 5 | class NativeLoader 6 | attr_reader :separator, :current_path 7 | 8 | module JC 9 | java_import 'java.lang.Class' 10 | java_import 'java.lang.System' 11 | java_import 'java.io.File' 12 | end 13 | 14 | def initialize 15 | @separator = JC::File.pathSeparatorChar 16 | @current_path = JC::System.getProperty('java.library.path') 17 | end 18 | 19 | def add_native_path(pth) 20 | current_path << separator << pth 21 | JC::System.setProperty('java.library.path', current_path) 22 | field = JC::Class.for_name('java.lang.ClassLoader') 23 | .get_declared_field('sys_paths') 24 | return unless field 25 | 26 | field.accessible = true # some jruby magic 27 | field.set(JC::Class.for_name('java.lang.System').get_class_loader, nil) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /src/main/java/monkstone/slider/Slider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package monkstone.slider; 7 | 8 | /** 9 | * 10 | * @author tux 11 | */ 12 | public interface Slider { 13 | 14 | void dispose(); 15 | 16 | void draw(); 17 | 18 | /** 19 | * 20 | */ 21 | void hideBackground(); 22 | 23 | /** 24 | * 25 | */ 26 | void hideLabel(); 27 | 28 | /** 29 | * 30 | */ 31 | void hideNumbers(); 32 | 33 | /** 34 | * 35 | * @param s 36 | */ 37 | void labelSize(int s); 38 | 39 | /** 40 | * 41 | * @return 42 | */ 43 | float readValue(); 44 | 45 | /** 46 | * 47 | * @param value 48 | */ 49 | void setValue(float value); 50 | 51 | /** 52 | * 53 | */ 54 | void showLabel(); 55 | 56 | /** 57 | * 58 | */ 59 | void showNumbers(); 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/processing/javafx/PGraphicsFX2D.java: -------------------------------------------------------------------------------- 1 | /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Part of the Processing project - http://processing.org 5 | 6 | Copyright (c) 2015 The Processing Foundation 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.javafx; 24 | 25 | 26 | 27 | import processing.core.*; 28 | 29 | 30 | public class PGraphicsFX2D extends PGraphics { 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/processing/data/Sort.java: -------------------------------------------------------------------------------- 1 | package processing.data; 2 | 3 | 4 | /** 5 | * Internal sorter used by several data classes. 6 | * Advanced users only, not official API. 7 | */ 8 | public abstract class Sort implements Runnable { 9 | 10 | public Sort() { } 11 | 12 | 13 | public void run() { 14 | int c = size(); 15 | if (c > 1) { 16 | sort(0, c - 1); 17 | } 18 | } 19 | 20 | 21 | protected void sort(int i, int j) { 22 | int pivotIndex = (i+j)/2; 23 | swap(pivotIndex, j); 24 | int k = partition(i-1, j); 25 | swap(k, j); 26 | if ((k-i) > 1) sort(i, k-1); 27 | if ((j-k) > 1) sort(k+1, j); 28 | } 29 | 30 | 31 | protected int partition(int left, int right) { 32 | int pivot = right; 33 | do { 34 | while (compare(++left, pivot) < 0) { } 35 | while ((right != 0) && (compare(--right, pivot) > 0)) { } 36 | swap(left, right); 37 | } while (left < right); 38 | swap(left, right); 39 | return left; 40 | } 41 | 42 | 43 | abstract public int size(); 44 | abstract public int compare(int a, int b); 45 | abstract public void swap(int a, int b); 46 | } -------------------------------------------------------------------------------- /src/main/java/monkstone/videoevent/CaptureEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | package monkstone.videoevent; 22 | import processing.video.Capture; 23 | 24 | @FunctionalInterface 25 | public interface CaptureEvent{ 26 | void captureEvent(Capture capture); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/ColorFrag.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifdef GL_ES 24 | precision mediump float; 25 | precision mediump int; 26 | #endif 27 | 28 | varying vec4 vertColor; 29 | 30 | void main() { 31 | gl_FragColor = vertColor; 32 | } -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/LineFrag.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifdef GL_ES 24 | precision mediump float; 25 | precision mediump int; 26 | #endif 27 | 28 | varying vec4 vertColor; 29 | 30 | void main() { 31 | gl_FragColor = vertColor; 32 | } -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/PointFrag.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifdef GL_ES 24 | precision mediump float; 25 | precision mediump int; 26 | #endif 27 | 28 | varying vec4 vertColor; 29 | 30 | void main() { 31 | gl_FragColor = vertColor; 32 | } -------------------------------------------------------------------------------- /lib/jruby_art/native_folder.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'rbconfig' 4 | 5 | # Utility to load native binaries on Java CLASSPATH 6 | # HACK until jruby returns a more specific 'host_os' than 'linux' 7 | class NativeFolder 8 | attr_reader :os, :bit 9 | 10 | LINUX_FORMAT = 'linux%d' 11 | # ARM64 = '-aarch64' 12 | WIN_FORMAT = 'windows%d' 13 | WIN_PATTERNS = [ 14 | /bccwin/i, 15 | /cygwin/i, 16 | /djgpp/i, 17 | /ming/i, 18 | /mswin/i, 19 | /wince/i 20 | ].freeze 21 | 22 | def initialize 23 | @os = RbConfig::CONFIG['host_os'].downcase 24 | @bit = /64/.match?(java.lang.System.get_property('os.arch')) ? 64 : 32 25 | end 26 | 27 | def name 28 | return macos if /darwin|mac/.match?(os) 29 | 30 | return format(LINUX_FORMAT, bit: bit) if /linux/.match?(os) 31 | 32 | unless WIN_PATTERNS.any? { |pat| pat.match?(os) } 33 | raise StandardError, 'Unsupported Architecture' 34 | end 35 | 36 | format(WIN_FORMAT, bit: bit) 37 | end 38 | 39 | def extension 40 | return '*.so' if /linux/.match?(os) 41 | 42 | return '*.dll' if WIN_PATTERNS.any? { |pat| pat.match?(os) } 43 | 44 | '*.dylib' # MacOS 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /src/main/java/monkstone/vecmath/JRender.java: -------------------------------------------------------------------------------- 1 | package monkstone.vecmath; 2 | 3 | /** 4 | * 5 | * @author Martin Prout 6 | */ 7 | public interface JRender { 8 | 9 | /** 10 | * 11 | * @param x double 12 | * @param y double 13 | */ 14 | void vertex(double x, double y); 15 | 16 | /** 17 | * 18 | * @param x double 19 | * @param y double 20 | */ 21 | void curveVertex(double x, double y); 22 | 23 | /** 24 | * 25 | * @param x double 26 | * @param y double 27 | * @param z double 28 | */ 29 | void vertex(double x, double y, double z); 30 | 31 | /** 32 | * 33 | * @param x double 34 | * @param y double 35 | * @param z double 36 | * @param u double 37 | * @param v double 38 | */ 39 | void vertex(double x, double y, double z, double u, double v); 40 | 41 | /** 42 | * 43 | * @param x double 44 | * @param y double 45 | * @param z double 46 | */ 47 | void curveVertex(double x, double y, double z); 48 | 49 | /** 50 | * 51 | * @param x double 52 | * @param y double 53 | * @param z double 54 | */ 55 | void normal(double x, double y, double z); 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/ColorVert.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | uniform mat4 transformMatrix; 24 | 25 | attribute vec4 position; 26 | attribute vec4 color; 27 | 28 | varying vec4 vertColor; 29 | 30 | void main() { 31 | gl_Position = transformMatrix * position; 32 | 33 | vertColor = color; 34 | } -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/LightFrag.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifdef GL_ES 24 | precision mediump float; 25 | precision mediump int; 26 | #endif 27 | 28 | varying vec4 vertColor; 29 | varying vec4 backVertColor; 30 | 31 | void main() { 32 | gl_FragColor = gl_FrontFacing ? vertColor : backVertColor; 33 | } -------------------------------------------------------------------------------- /src/main/java/monkstone/videoevent/MovieEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | package monkstone.videoevent; 22 | import processing.video.Movie; 23 | 24 | /** 25 | * This interface makes it easier/possible to use the reflection methods 26 | * from Movie and Capture classes in Processing::App in JRubyArt 27 | * @author Martin Prout 28 | */ 29 | @FunctionalInterface 30 | public interface MovieEvent { 31 | void movieEvent(Movie movie); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/TexFrag.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifdef GL_ES 24 | precision mediump float; 25 | precision mediump int; 26 | #endif 27 | 28 | uniform sampler2D texture; 29 | 30 | uniform vec2 texOffset; 31 | 32 | varying vec4 vertColor; 33 | varying vec4 vertTexCoord; 34 | 35 | void main() { 36 | gl_FragColor = texture2D(texture, vertTexCoord.st) * vertColor; 37 | } -------------------------------------------------------------------------------- /library/slider/slider.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Here's a little library for quickly hooking up in sketch sliders. 4 | # Copyright (c) 2015-20 Martin Prout. 5 | 6 | java_import 'monkstone.slider.CustomHorizontalSlider' 7 | java_import 'monkstone.slider.CustomVerticalSlider' 8 | 9 | module Slider 10 | def self.slider(app:, x:, y:, name:, **opts) 11 | options = default.merge opts 12 | slider = if options[:vertical] 13 | CustomVerticalSlider.new( 14 | app, 15 | x, 16 | y, 17 | options[:length], 18 | options[:range].first, 19 | options[:range].last, 20 | name 21 | ) 22 | else 23 | CustomHorizontalSlider.new( 24 | app, 25 | x, 26 | y, 27 | options[:length], 28 | options[:range].first, 29 | options[:range].last, 30 | name 31 | ) 32 | end 33 | unless opts.empty? 34 | slider.bar_width(opts.fetch(:bar_width, 10)) 35 | slider.set_value(opts.fetch(:initial_value, 0)) 36 | end 37 | slider 38 | end 39 | 40 | def self.default 41 | { length: 100, range: (0..100) } 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/native_folder.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | require_relative '../lib/jruby_art/native_folder' 5 | # Mock class 6 | class WindowsNativeFolder < NativeFolder 7 | def initialize 8 | @os = 'mswin' 9 | @bit = 64 10 | end 11 | end 12 | 13 | # Mock Mac 14 | class MacNativeFolder < NativeFolder 15 | def initialize 16 | @os = 'mac' 17 | @bit = 64 18 | end 19 | end 20 | 21 | # Test class 22 | class NativeFolderTest < Minitest::Test 23 | def test_windows_native_folder 24 | obj = WindowsNativeFolder.new 25 | assert_kind_of NativeFolder, obj, 'Constructor Failed' 26 | assert(/windows/.match?(obj.name)) 27 | assert(/\*.dll/.match?(obj.extension)) 28 | end 29 | 30 | class NativeFolderTest < Minitest::Test 31 | def test_windows_native_folder 32 | obj = MacNativeFolder.new 33 | assert_kind_of NativeFolder, obj, 'Constructor Failed' 34 | assert(/macos/.match?(obj.name)) 35 | assert(/\*.dylib/.match?(obj.extension)) 36 | end 37 | end 38 | 39 | if /linux/.match?(RbConfig::CONFIG['host_os'].downcase) 40 | def test_native_folder 41 | obj = NativeFolder.new 42 | assert_instance_of NativeFolder, obj, 'Constructor Failed' 43 | assert(/linux/.match?(obj.name)) 44 | assert(/\*.so/.match?(obj.extension)) 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /src/main/java/monkstone/slider/WheelHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.slider; 21 | 22 | /** 23 | * @author Martin Prout from a borrowed pattern seen in Jonathan Feinbergs 24 | * Peasycam when I was struggling with non functioning browser applet, probably 25 | * superfluous here. 26 | */ 27 | @FunctionalInterface 28 | public interface WheelHandler { 29 | 30 | /** 31 | * 32 | * @param amount int 33 | */ 34 | void handleWheel(final short amount); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/monkstone/arcball/WheelHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | package monkstone.arcball; 22 | 23 | /** 24 | * @author Martin Prout 25 | * from a borrowed pattern seen in Jonathan Feinbergs Peasycam 26 | * when I was struggling with non functioning browser applet, 27 | * probably superfluous here. 28 | */ 29 | public interface WheelHandler { 30 | /** 31 | * 32 | * @param amount int 33 | */ 34 | 35 | void handleWheel(final int amount); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/TexLightFrag.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | #ifdef GL_ES 23 | precision mediump float; 24 | precision mediump int; 25 | #endif 26 | 27 | uniform sampler2D texture; 28 | 29 | uniform vec2 texOffset; 30 | 31 | varying vec4 vertColor; 32 | varying vec4 backVertColor; 33 | varying vec4 vertTexCoord; 34 | 35 | void main() { 36 | gl_FragColor = texture2D(texture, vertTexCoord.st) * (gl_FrontFacing ? vertColor : backVertColor); 37 | } -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/TexVert.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | uniform mat4 transformMatrix; 24 | uniform mat4 texMatrix; 25 | 26 | attribute vec4 position; 27 | attribute vec4 color; 28 | attribute vec2 texCoord; 29 | 30 | varying vec4 vertColor; 31 | varying vec4 vertTexCoord; 32 | 33 | void main() { 34 | gl_Position = transformMatrix * position; 35 | 36 | vertColor = color; 37 | vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); 38 | } -------------------------------------------------------------------------------- /src/main/java/processing/opengl/cursors/license.txt: -------------------------------------------------------------------------------- 1 | These files are based on the DMZ Cursors package, 2 | used with permission from Jakub Steiner 3 | 11 September 2015 4 | 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2006 Jakub Steiner 9 | Copyright (c) 2006 Novell, Inc. 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in 19 | all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | THE SOFTWARE. 28 | -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/MaskFrag.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #ifdef GL_ES 24 | precision mediump float; 25 | precision mediump int; 26 | #endif 27 | 28 | #define PROCESSING_TEXTURE_SHADER 29 | 30 | uniform sampler2D texture; 31 | uniform sampler2D mask; 32 | 33 | varying vec4 vertTexCoord; 34 | 35 | void main() { 36 | vec3 texColor = texture2D(texture, vertTexCoord.st).rgb; 37 | vec3 maskColor = texture2D(mask, vertTexCoord.st).rgb; 38 | float luminance = dot(maskColor, vec3(0.2126, 0.7152, 0.0722)); 39 | gl_FragColor = vec4(texColor, luminance); 40 | } -------------------------------------------------------------------------------- /test/smooth_noise_test.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | Java::Monkstone::JRLibrary.new.load(JRuby.runtime, false) 4 | # method tests 5 | class NoiseTest < Minitest::Test 6 | 7 | VALS = [0.4, 0.5, 4, 5].freeze 8 | 9 | def test_noise2d 10 | result = VALS.map { |x| SmoothNoise.noise(x, Math.sin(x)) } 11 | assert result.all? { |x| (-1.0..1.0).include?(x) } 12 | assert VALS.length == result.uniq.length 13 | end 14 | 15 | def test_noise3d 16 | result = VALS.map { |x| SmoothNoise.noise(x, Math.sin(x), Math.cos(x)) } 17 | assert result.all? { |x| (-1.0..1.0).include?(x) } 18 | assert VALS.length == result.uniq.length 19 | end 20 | 21 | def test_noise4d 22 | result = VALS.map { |x| SmoothNoise.noise(x, rand, Math.sin(x), Math.cos(x)) } 23 | assert result.all? { |x| (-1.0..1.0).include?(x) } 24 | assert VALS.length == result.uniq.length 25 | end 26 | 27 | def test_tnoise2d 28 | result = VALS.map { |x| SmoothNoise.tnoise(x, Math.sin(x)) } 29 | assert result.all? { |x| (-1.0..1.0).include?(x) } 30 | assert VALS.length == result.uniq.length 31 | end 32 | 33 | def test_tnoise3d 34 | result = VALS.map { |x| SmoothNoise.tnoise(x, Math.sin(x), Math.cos(x)) } 35 | assert result.all? { |x| (-1.0..1.0).include?(x) } 36 | assert VALS.length == result.uniq.length 37 | end 38 | 39 | def test_tnoise4d 40 | result = VALS.map { |x| SmoothNoise.tnoise(x, rand, Math.sin(x), Math.cos(x)) } 41 | assert result.all? { |x| (-1.0..1.0).include?(x) } 42 | assert VALS.length == result.uniq.length 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /src/main/java/monkstone/filechooser/Chooser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.filechooser; 21 | 22 | import java.io.File; 23 | 24 | /** 25 | * This interface makes it easier/possible to use the reflection methods 26 | * selectInput def setup java_signature 'void selectInput(String, String)' 27 | * selectInput('Select a file to process:', 'fileSelected') end 28 | * 29 | * def file_selected(selection) if selection.nil? puts 'Window was closed or the 30 | * user hit cancel.' else puts format('User selected %s', 31 | * selection.get_absolute_path) end end 32 | * 33 | * @author Martin Prout 34 | */ 35 | @FunctionalInterface 36 | public interface Chooser { 37 | 38 | void file_selected(File selection); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/monkstone/PropaneLibrary.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The purpose of this class is to load the MathTool into ruby-processing runtime 3 | * Copyright (C) 2015-20 Martin Prout. This code is free software; you can 4 | * redistribute it and/or modify it under the terms of the GNU Lesser General 5 | * Public License as published by the Free Software Foundation; either version 6 | * 2.1 of the License, or (at your option) any later version. 7 | * 8 | * Obtain a copy of the license at http://www.gnu.org/licenses/lgpl-2.1.html 9 | */ 10 | package monkstone; 11 | 12 | import java.io.IOException; 13 | import monkstone.fastmath.Deglut; 14 | import monkstone.vecmath.vec2.Vec2; 15 | import monkstone.vecmath.vec3.Vec3; 16 | import org.jruby.Ruby; 17 | import org.jruby.runtime.load.Library; 18 | 19 | /** 20 | * 21 | * @author Martin Prout 22 | */ 23 | public class PropaneLibrary implements Library { 24 | 25 | /** 26 | * 27 | * @param runtime 28 | */ 29 | public static void load(final Ruby runtime) { 30 | MathToolModule.createMathToolModule(runtime); 31 | FastNoiseModuleJava.createNoiseModule(runtime); 32 | SmoothNoiseModuleJava.createNoiseModule(runtime); 33 | Deglut.createDeglut(runtime); 34 | Vec2.createVec2(runtime); 35 | Vec3.createVec3(runtime); 36 | } 37 | 38 | /** 39 | * 40 | * @param runtime 41 | * @param wrap 42 | * @throws java.io.IOException 43 | */ 44 | @Override 45 | public void load(final Ruby runtime, boolean wrap) throws IOException { 46 | PropaneLibrary.load(runtime); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/jruby_art/config.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'yaml' 4 | require_relative 'default_config' 5 | require_relative 'version' 6 | HOME = ENV['HOME'] 7 | # Configuration class 8 | class Config 9 | attr_reader :config 10 | def initialize(conf = {}) 11 | @config = Default.config.merge(conf) 12 | end 13 | 14 | def write_to_file 15 | directory = File.join(HOME, '.jruby_art') 16 | Dir.mkdir(directory) unless Dir.exist? directory 17 | File.write(File.join(HOME, '.jruby_art', 'config.yml'), config.to_yaml) 18 | end 19 | 20 | def load_config 21 | config_path = File.join(File.join(HOME, '.jruby_art', 'config.yml')) 22 | if File.exist? config_path 23 | loaded = YAML.safe_load(File.read(config_path)) 24 | @config = Default.config.merge(loaded) 25 | return self unless loaded.key? 'PROCESSING_ROOT' 26 | 27 | warn '*********** Move Old Config File ***************' 28 | end 29 | @config = Default.config 30 | warn '*********** Default Config Loaded ***************' 31 | self 32 | end 33 | 34 | def check 35 | load_config 36 | puts "JRubyArt version #{JRubyArt::VERSION}" 37 | puts 'Approximates to Processing-4.0' 38 | puts "processing ide = #{config.fetch('processing_ide', false)}" 39 | puts "library_path = #{config.fetch('library_path', File.join(HOME, '.jruby_art'))}" 40 | puts "template = #{config.fetch('template', 'bare')}" 41 | puts "java_args = #{config.fetch('java_args', '')}" 42 | puts "MAX_WATCH = #{config.fetch('MAX_WATCH', 32)}" 43 | puts "JRUBY = #{config.fetch('JRUBY', true)}" 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Before you file an issue 2 | 3 | Please check your configuration `~/jruby_art/config.yml`, if you get the following error (_or similar_) 4 | ```bash 5 | LoadError: load error: C:/jruby-9.1.15.0/lib/ruby/gems/shared/gems/jruby_art-1.4.6/lib/jruby_art/app --java.lang.NoClassDefFoundError: processing/core/PApplet 6 | ``` 7 | It means the program can't find the processing root and you should make sure that 8 | ```bash 9 | PROCESSING_ROOT: /home/tux/processing-3.4 10 | ``` 11 | matches your system (_typical linux shown above for user tux_) for windows it may be safer to use quoted string, especially if you have spaces in your path. 12 | 13 | 14 | 21 | 22 | ### Environment 23 | 24 | Ensure that you are using the recommended versions of processing(`k9 setup check`), jruby (`jruby -v`) and java (`java -version`) 25 | Provide JRubyArt version that you are using (`k9 --version`) 26 | Provide your operating system and platform (e.g. `uname -a`, and/or `java -version` output if relevant) 27 | 28 | ### Expected Behavior 29 | 30 | Describe your expectation of how JRubyArt sketch should behave. 31 | Provide a `problematic` JRubyArt sketch or a link to an example repository. 32 | 33 | ### Actual Behavior 34 | 35 | Describe or show the actual behavior. 36 | Provide text or screen capture showing the behavior. 37 | 38 | ### Other 39 | 40 | eg installation issue (just use this header and explain the problem as best you can) 41 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | In the spirit of [free software][free-sw], **everyone** is encouraged to help improve this project. 3 | 4 | Here are some ways *you* can contribute: 5 | 6 | * by reporting bugs 7 | * by suggesting/implementing new features ( _running sketches from the atom editor would be cool_ ) 8 | * by writing or editing documentation ( _expert Windows users could help write install instructions_ ) 9 | * by contributing examples ( _show your creativity, or translate someone elses masterpiece_ ) 10 | * by refactoring examples to be more rubyfied 11 | * by closing [issues][] 12 | * by proselytizing JRubyArt (ruby-processing), we need more champions 13 | * by supporting [Processing.org][], nothing to do with us but we rely on them 14 | * by figuring out if we could replace swing with javafx for control_panel etc 15 | 16 | ## Submitting an Issue 17 | We use the [GitHub issue tracker][issues] to track bugs and features. Before 18 | submitting a bug report or feature request, check to make sure it hasn't 19 | already been submitted. When submitting a bug report, ideally include a [Gist][] 20 | that includes a stack trace and any details that may be necessary to reproduce 21 | the bug, including your gem version, Ruby version, and operating system. 22 | 23 | 24 | ## Submitting a Pull Request 25 | 1. [Fork the repository.][fork] 26 | 2. [Submit a pull request.][pr] 27 | 28 | [free-sw]: http://www.fsf.org/licensing/essays/free-sw.html 29 | [issues]: https://github.com/ruby-processing/JRubyArt/issues 30 | [gist]: https://gist.github.com/ 31 | [fork]: http://help.github.com/fork-a-repo/ 32 | [pr]: http://help.github.com/send-pull-requests/ 33 | [processing.org]: http://processing.org/foundation/ 34 | -------------------------------------------------------------------------------- /lib/jruby_art/runners/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | SKETCH_PATH ||= ARGV.shift 4 | SKETCH_ROOT ||= File.absolute_path(File.dirname(SKETCH_PATH)) 5 | 6 | # we can safely require app.rb as we are using a jruby runtime 7 | require_relative '../app' 8 | 9 | # More processing module 10 | module Processing 11 | # For use with "bare" sketches that don't want to define a class or methods 12 | BARE_WRAP = <<-BARE 13 | class Sketch < Processing::App 14 | %s 15 | end 16 | BARE 17 | 18 | NAKED_WRAP = <<-NAKED 19 | class Sketch < Processing::App 20 | def setup 21 | sketch_title '%s' 22 | %s 23 | no_loop 24 | end 25 | 26 | def settings 27 | size(%d, %d) 28 | end 29 | end 30 | NAKED 31 | 32 | # This method is the common entry point to run a sketch, bare or complete. 33 | def self.load_and_run_sketch 34 | source = read_sketch_source 35 | wrapped = !source.match(/^[^#]*< Processing::App/).nil? 36 | no_methods = source.match(/^[^#]*(def\s+setup|def\s+draw)/).nil? 37 | if wrapped 38 | load SKETCH_PATH 39 | Processing::App.sketch_class.new unless Processing.app 40 | return 41 | end 42 | name = RP_CONFIG.fetch('sketch_title', 'Naked Sketch') 43 | width = RP_CONFIG.fetch('width', 200) 44 | height = RP_CONFIG.fetch('height', 200) 45 | code = no_methods ? format(NAKED_WRAP, name, source, width, height) : format(BARE_WRAP, source) 46 | Object.class_eval code, SKETCH_PATH, -1 47 | Processing::App.sketch_class.new unless Processing.app 48 | end 49 | 50 | # Read in the sketch source code. Needs to work both online and offline. 51 | def self.read_sketch_source 52 | File.read(SKETCH_PATH) 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /src/main/java/monkstone/JRLibrary.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The purpose of this class is to load the MathTool etc. into JRuby runtime 3 | * Copyright (c) 2015-20 Martin Prout. This code is free software; you can 4 | * redistribute it and/or modify it under the terms of the GNU Lesser General 5 | * Public License as published by the Free Software Foundation; either version 6 | * 2.1 of the License, or (at your option) any later version. 7 | * 8 | * Obtain a copy of the license at http://www.gnu.org/licenses/lgpl-2.1.html 9 | */ 10 | 11 | package monkstone; 12 | 13 | import java.io.IOException; 14 | import monkstone.arcball.Rarcball; 15 | import monkstone.fastmath.Deglut; 16 | import monkstone.vecmath.vec2.Vec2; 17 | import monkstone.vecmath.vec3.Vec3; 18 | import org.jruby.Ruby; 19 | import org.jruby.runtime.load.Library; 20 | 21 | /** 22 | * 23 | * @author Martin Prout 24 | */ 25 | public class JRLibrary implements Library{ 26 | 27 | /** 28 | * Loads the extension classes into Ruby runtime 29 | * @param runtime Ruby 30 | */ 31 | public static void load(final Ruby runtime) { 32 | FastNoiseModuleJava.createNoiseModule(runtime); 33 | SmoothNoiseModuleJava.createNoiseModule(runtime); 34 | MathToolModule.createMathToolModule(runtime); 35 | Deglut.createDeglut(runtime); 36 | Rarcball.createArcBall(runtime); 37 | Vec2.createVec2(runtime); 38 | Vec3.createVec3(runtime); 39 | } 40 | 41 | /** 42 | * 43 | * @param runtime Ruby 44 | * @param wrap boolean 45 | * @throws java.io.IOException 46 | */ 47 | @Override 48 | public void load(final Ruby runtime, boolean wrap) throws IOException { 49 | load(runtime); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/fast_noise_test.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | Java::Monkstone::JRLibrary.new.load(JRuby.runtime, false) 4 | # method tests 5 | class NoiseTest < Minitest::Test 6 | include FastNoise 7 | 8 | VALS = [0.4, 0.5, 4, 5].freeze 9 | 10 | def test_noise1d 11 | assert self.respond_to? :noise 12 | result = VALS.map { |x| noise(x) } 13 | assert result.all? { |x| (-1.0..1.0).include?(x) } 14 | assert VALS.length == result.uniq.length 15 | end 16 | 17 | def test_noise2d 18 | result = VALS.map { |x| noise(x, Math.sin(x)) } 19 | assert result.all? { |x| (-1.0..1.0).include?(x) } 20 | assert VALS.length == result.uniq.length 21 | end 22 | 23 | def test_noise3d 24 | result = VALS.map { |x| noise(x, Math.sin(x), Math.cos(x)) } 25 | assert result.all? { |x| (-1.0..1.0).include?(x) } 26 | assert VALS.length == result.uniq.length 27 | end 28 | 29 | def test_noise4d 30 | result = VALS.map { |x| noise(x, rand, Math.sin(x), Math.cos(x)) } 31 | assert result.all? { |x| (-1.0..1.0).include?(x) } 32 | assert VALS.length == result.uniq.length 33 | end 34 | 35 | def test_tnoise2d 36 | result = VALS.map { |x| tnoise(x, Math.sin(x)) } 37 | assert result.all? { |x| (-1.0..1.0).include?(x) } 38 | assert VALS.length == result.uniq.length 39 | end 40 | 41 | def test_tnoise3d 42 | result = VALS.map { |x| tnoise(x, Math.sin(x), Math.cos(x)) } 43 | assert result.all? { |x| (-1.0..1.0).include?(x) } 44 | assert VALS.length == result.uniq.length 45 | end 46 | 47 | def test_tnoise4d 48 | result = VALS.map { |x| tnoise(x, rand, Math.sin(x), Math.cos(x)) } 49 | assert result.all? { |x| (-1.0..1.0).include?(x) } 50 | assert VALS.length == result.uniq.length 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/jruby_art/library_loader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | 3 | # The processing wrapper module 4 | module Processing 5 | require_relative 'library' 6 | 7 | # Encapsulate library loader functionality as a class 8 | class LibraryLoader 9 | attr_reader :library 10 | 11 | def initialize 12 | @loaded_libraries = Hash.new(false) 13 | end 14 | 15 | # Detect if a library has been loaded (for conditional loading) 16 | def library_loaded?(library_name) 17 | @loaded_libraries[library_name.to_sym] 18 | end 19 | 20 | # Load a list of Ruby or Java libraries (in that order) 21 | # Usage: load_libraries :video, :video_event 22 | # 23 | # If a library is put into a 'library' folder next to the sketch it will be used 24 | # instead of the library that ships with vanilla processing (or ide installed), or JRubyArt. 25 | def load_libraries(*args) 26 | message = 'no such file to load -- %s' 27 | args.each do |lib| 28 | loaded = loader(lib) 29 | raise(LoadError.new, format(message, lib)) unless loaded 30 | end 31 | end 32 | alias load_library load_libraries 33 | 34 | def loader(name) 35 | return true if @loaded_libraries.include?(name) 36 | 37 | fname = name.to_s 38 | library = Library.new(fname) 39 | library.locate 40 | return require_library(library, name) if library.ruby? 41 | 42 | warn("Not found library: #{fname}") unless library.exist? 43 | load_jars(library, name) 44 | end 45 | 46 | def load_jars(lib, name) 47 | lib.load_jars 48 | @loaded_libraries[name] = true 49 | end 50 | 51 | def require_library(lib, name) 52 | @loaded_libraries[name] = require lib.path 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /src/main/java/monkstone/arcball/Constrain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | package monkstone.arcball; 22 | 23 | /** 24 | * 25 | * @author Martin Prout 26 | */ 27 | public enum Constrain { 28 | 29 | /** 30 | * Used to constrain arc-ball rotation about X axis 31 | */ 32 | 33 | XAXIS(0), 34 | /** 35 | * Used to constrain arc-ball rotation about Y axis 36 | */ 37 | YAXIS(1), 38 | /** 39 | * Used to constrain arc-ball rotation about Z axis 40 | */ 41 | ZAXIS(2), 42 | /** 43 | * Used for default no constrain arc-ball about any axis 44 | */ 45 | FREE(-1); 46 | private final int index; 47 | 48 | Constrain(int idx) { 49 | this.index = idx; 50 | } 51 | 52 | /** 53 | * Numeric value of constrained axis 54 | * @return axis int 55 | */ 56 | public int index() { 57 | return index; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/monkstone/slider/SliderGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.slider; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | import processing.core.PApplet; 25 | 26 | public class SliderGroup { 27 | 28 | int count = 0; 29 | List sliders; 30 | PApplet applet; 31 | boolean vertical; 32 | 33 | public SliderGroup(final PApplet outer) { 34 | applet = outer; 35 | sliders = new ArrayList<>(); 36 | vertical = false; 37 | } 38 | 39 | public void vertical() { 40 | vertical = true; 41 | } 42 | 43 | public void addSlider(float beginRange, float endRange, float initial) { 44 | if (vertical) { 45 | sliders.add(new SimpleVerticalSlider(applet, beginRange, endRange, initial, count)); 46 | } else { 47 | sliders.add(new SimpleHorizontalSlider(applet, beginRange, endRange, initial, count)); 48 | } 49 | count = sliders.size(); 50 | } 51 | 52 | public float readValue(int count) { 53 | return sliders.get(count).readValue(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/monkstone/vecmath/GfxRender.java: -------------------------------------------------------------------------------- 1 | package monkstone.vecmath; 2 | 3 | import processing.core.PGraphics; 4 | 5 | /** 6 | * 7 | * @author Martin Prout 8 | */ 9 | public class GfxRender implements JRender { 10 | 11 | final PGraphics graphics; 12 | 13 | /** 14 | * 15 | * @param graphics PGraphics 16 | */ 17 | public GfxRender(final PGraphics graphics) { 18 | this.graphics = graphics; 19 | } 20 | 21 | /** 22 | * 23 | * @param x double 24 | * @param y double 25 | */ 26 | @Override 27 | public void vertex(double x, double y) { 28 | graphics.vertex((float) x, (float) y); 29 | } 30 | 31 | /** 32 | * 33 | * @param x double 34 | * @param y double 35 | */ 36 | @Override 37 | public void curveVertex(double x, double y) { 38 | graphics.curveVertex((float) x, (float) y); 39 | } 40 | 41 | /** 42 | * 43 | * @param x double 44 | * @param y double 45 | * @param z double 46 | */ 47 | @Override 48 | public void vertex(double x, double y, double z) { 49 | graphics.vertex((float) x, (float) y, (float) z); 50 | } 51 | 52 | /** 53 | * 54 | * @param x double 55 | * @param y double 56 | * @param z double 57 | */ 58 | @Override 59 | public void normal(double x, double y, double z) { 60 | graphics.normal((float) x, (float) y, (float) z); 61 | } 62 | 63 | /** 64 | * 65 | * @param x double 66 | * @param y double 67 | * @param z double 68 | * @param u double 69 | * @param v double 70 | */ 71 | @Override 72 | public void vertex(double x, double y, double z, double u, double v) { 73 | graphics.vertex((float) x, (float) y, (float) z, (float) u, (float) v); 74 | } 75 | 76 | /** 77 | * 78 | * @param x double 79 | * @param y double 80 | * @param z double 81 | */ 82 | @Override 83 | public void curveVertex(double x, double y, double z) { 84 | graphics.curveVertex((float) x, (float) y, (float) z); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/processing/core/PStyle.java: -------------------------------------------------------------------------------- 1 | /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Part of the Processing project - http://processing.org 5 | 6 | Copyright (c) 2008 Ben Fry and Casey Reas 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This library is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General 19 | Public License along with this library; if not, write to the 20 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 21 | Boston, MA 02111-1307 USA 22 | */ 23 | 24 | package processing.core; 25 | 26 | 27 | public class PStyle implements PConstants { 28 | public int imageMode; 29 | public int rectMode; 30 | public int ellipseMode; 31 | public int shapeMode; 32 | 33 | public int blendMode; 34 | 35 | public int colorMode; 36 | public float colorModeX; 37 | public float colorModeY; 38 | public float colorModeZ; 39 | public float colorModeA; 40 | 41 | public boolean tint; 42 | public int tintColor; 43 | public boolean fill; 44 | public int fillColor; 45 | public boolean stroke; 46 | public int strokeColor; 47 | public float strokeWeight; 48 | public int strokeCap; 49 | public int strokeJoin; 50 | 51 | // TODO these fellas are inconsistent, and may need to go elsewhere 52 | public float ambientR, ambientG, ambientB; 53 | public float specularR, specularG, specularB; 54 | public float emissiveR, emissiveG, emissiveB; 55 | public float shininess; 56 | 57 | public PFont textFont; 58 | public int textAlign; 59 | public int textAlignY; 60 | public int textMode; 61 | public float textSize; 62 | public float textLeading; 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/monkstone/vecmath/ShapeRender.java: -------------------------------------------------------------------------------- 1 | package monkstone.vecmath; 2 | 3 | import processing.core.PShape; 4 | 5 | /** 6 | * 7 | * @author Martin Prout 8 | */ 9 | public class ShapeRender implements JRender { 10 | 11 | final PShape shape; 12 | 13 | /** 14 | * 15 | * @param shape PShape 16 | */ 17 | public ShapeRender(final PShape shape) { 18 | this.shape = shape; 19 | 20 | } 21 | 22 | /** 23 | * 24 | * @param x double 25 | * @param y double 26 | */ 27 | @Override 28 | public void vertex(double x, double y) { 29 | shape.vertex((float) x, (float) y); 30 | } 31 | 32 | /** 33 | * 34 | * @param x double 35 | * @param y double 36 | */ 37 | @Override 38 | public void curveVertex(double x, double y) { 39 | throw new UnsupportedOperationException("Not implemented for this renderer"); 40 | } 41 | 42 | /** 43 | * 44 | * @param x double 45 | * @param y double 46 | * @param z double 47 | */ 48 | @Override 49 | public void vertex(double x, double y, double z) { 50 | shape.vertex((float) x, (float) y, (float) z); 51 | } 52 | 53 | /** 54 | * 55 | * @param x double 56 | * @param y double 57 | * @param z double 58 | */ 59 | @Override 60 | public void normal(double x, double y, double z) { 61 | shape.normal((float) x, (float) y, (float) z); 62 | } 63 | 64 | /** 65 | * 66 | * @param x double 67 | * @param y double 68 | * @param z double 69 | * @param u double 70 | * @param v double 71 | */ 72 | @Override 73 | public void vertex(double x, double y, double z, double u, double v) { 74 | shape.vertex((float) x, (float) y, (float) z, (float) u, (float) v); 75 | } 76 | 77 | /** 78 | * 79 | * @param x double 80 | * @param y double 81 | * @param z double 82 | */ 83 | @Override 84 | public void curveVertex(double x, double y, double z) { 85 | throw new UnsupportedOperationException("Not implemented for this renderer"); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/processing/event/KeyEvent.java: -------------------------------------------------------------------------------- 1 | /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Part of the Processing project - http://processing.org 5 | 6 | Copyright (c) 2012 The Processing Foundation 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.event; 24 | 25 | 26 | public class KeyEvent extends Event { 27 | static public final int PRESS = 1; 28 | static public final int RELEASE = 2; 29 | static public final int TYPE = 3; 30 | 31 | char key; 32 | int keyCode; 33 | 34 | boolean isAutoRepeat; 35 | 36 | 37 | public KeyEvent(Object nativeObject, 38 | long millis, int action, int modifiers, 39 | char key, int keyCode) { 40 | super(nativeObject, millis, action, modifiers); 41 | this.flavor = KEY; 42 | this.key = key; 43 | this.keyCode = keyCode; 44 | } 45 | 46 | public KeyEvent(Object nativeObject, 47 | long millis, int action, int modifiers, 48 | char key, int keyCode, boolean isAutoRepeat) { 49 | super(nativeObject, millis, action, modifiers); 50 | this.flavor = KEY; 51 | this.key = key; 52 | this.keyCode = keyCode; 53 | this.isAutoRepeat = isAutoRepeat; 54 | } 55 | 56 | 57 | public char getKey() { 58 | return key; 59 | } 60 | 61 | 62 | public int getKeyCode() { 63 | return keyCode; 64 | } 65 | 66 | 67 | public boolean isAutoRepeat() { 68 | return isAutoRepeat; 69 | } 70 | } -------------------------------------------------------------------------------- /src/main/java/processing/event/TouchEvent.java: -------------------------------------------------------------------------------- 1 | /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Part of the Processing project - http://processing.org 5 | 6 | Copyright (c) 2012 The Processing Foundation 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.event; 24 | 25 | 26 | // PLACEHOLDER CLASS: DO NOT USE. IT HAS NOT EVEN DECIDED WHETHER 27 | // THIS WILL BE CALLED TOUCHEVENT ONCE IT'S FINISHED. 28 | 29 | /* 30 | http://developer.android.com/guide/topics/ui/ui-events.html 31 | http://developer.android.com/reference/android/view/MotionEvent.html 32 | http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/TouchEventClassReference/TouchEvent/TouchEvent.html 33 | http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIGestureRecognizer_Class/Reference/Reference.html#//apple_ref/occ/cl/UIGestureRecognizer 34 | 35 | Apple's high-level gesture names: 36 | tap 37 | pinch 38 | rotate 39 | swipe 40 | pan 41 | longpress 42 | 43 | W3C touch events 44 | http://www.w3.org/TR/touch-events/ 45 | http://www.w3.org/TR/2011/WD-touch-events-20110913/ 46 | 47 | Pointer and gesture events (Windows) 48 | http://msdn.microsoft.com/en-US/library/ie/hh673557.aspx 49 | 50 | */ 51 | public class TouchEvent extends Event { 52 | 53 | public TouchEvent(Object nativeObject, long millis, int action, int modifiers) { 54 | super(nativeObject, millis, action, modifiers); 55 | this.flavor = TOUCH; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'lib/jruby_art/version' 4 | require 'erb' 5 | 6 | MVN = Gem.win_platform? ? File.expand_path('mvnw.cmd') : File.expand_path('mvnw') 7 | 8 | task default: %i[compile init gem test] 9 | 10 | # depends on installed processing, with processing on path 11 | desc 'Copy Jars' 12 | task :init do 13 | jogl24 = File.join(ENV['HOME'], 'jogl24') 14 | opengl = Dir.entries(jogl24).grep(/amd64|universal|arm64/).select { |jar| jar =~ /linux|windows|macosx|ios|/ } 15 | opengl.concat %w[jogl-all.jar gluegen-rt.jar] 16 | opengl.each do |gl| 17 | FileUtils.cp(File.join(jogl24, gl), File.join('.', 'lib')) 18 | end 19 | end 20 | 21 | desc 'Build gem' 22 | task :gem do 23 | system 'jgem build jruby_art.gemspec' 24 | end 25 | 26 | desc 'Compile' 27 | task :compile do 28 | system "#{MVN} package" 29 | FileUtils.mv "target/jruby_art-#{JRubyArt::VERSION}.jar", 'lib' 30 | system "#{MVN} dependency:copy" 31 | end 32 | 33 | desc 'pmd' 34 | task :pmd do 35 | sh './mvnw pmd:pmd' 36 | end 37 | 38 | desc 'Test' 39 | task :test do 40 | system 'jruby --dev test/deglut_spec_test.rb' 41 | system 'jruby --dev test/vecmath_spec_test.rb' 42 | system 'jruby --dev test/math_tool_test.rb' 43 | system 'jruby --dev test/helper_methods_test.rb' 44 | system 'jruby --dev test/aabb_spec_test.rb' 45 | system 'jruby --dev test/create_test.rb' 46 | system 'jruby --dev test/color_group_test.rb' 47 | system 'jruby --dev test/fast_noise_test.rb' 48 | system 'jruby --dev test/smooth_noise_test.rb' 49 | home = File.expand_path('~') 50 | FLF = '%s/.jruby_art/config.yml' 51 | config = File.exist?(format(FLF, home: home)) 52 | if config 53 | system 'jruby test/k9_run_test.rb' 54 | else 55 | WNF = 'Create a config %s/.jruby_art/config.yml to run sketch tests' 56 | warn format(WNF, home: home) 57 | end 58 | end 59 | 60 | desc 'JDeps Tool' 61 | task :jdeps do 62 | system "#{MVN} jdeps:jdkinternals" 63 | end 64 | 65 | desc 'clean' 66 | task :clean do 67 | Dir['./**/*.{jar,gem}'].each do |path| 68 | puts "Deleting #{path} ..." 69 | File.delete(path) 70 | end 71 | FileUtils.rm_rf('./target') 72 | end 73 | -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/PointVert.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | uniform mat4 projectionMatrix; 24 | uniform mat4 modelviewMatrix; 25 | 26 | uniform vec4 viewport; 27 | uniform int perspective; 28 | 29 | attribute vec4 position; 30 | attribute vec4 color; 31 | attribute vec2 offset; 32 | 33 | varying vec4 vertColor; 34 | 35 | void main() { 36 | vec4 pos = modelviewMatrix * position; 37 | vec4 clip = projectionMatrix * pos; 38 | 39 | // Perspective --- 40 | // convert from world to clip by multiplying with projection scaling factor 41 | // invert Y, projections in Processing invert Y 42 | vec2 perspScale = (projectionMatrix * vec4(1, -1, 0, 0)).xy; 43 | 44 | // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) 45 | // screen_p = (p.xy/p.w + <1,1>) * 0.5 * viewport.zw 46 | 47 | // No Perspective --- 48 | // multiply by W (to cancel out division by W later in the pipeline) and 49 | // convert from screen to clip (derived from clip to screen above) 50 | vec2 noPerspScale = clip.w / (0.5 * viewport.zw); 51 | 52 | gl_Position.xy = clip.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0)); 53 | gl_Position.zw = clip.zw; 54 | 55 | vertColor = color; 56 | } 57 | -------------------------------------------------------------------------------- /lib/jruby_art/launcher.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../jruby_art/jruby_complete' 4 | require_relative '../jruby_art/java_opts' 5 | module Processing 6 | # The command class check for configuration and options, before creating and 7 | # executing the jruby (or java) command to run the sketch 8 | class Launcher 9 | attr_reader :command 10 | def initialize(runner:, args:, filename:) 11 | @command = if Processing::RP_CONFIG.fetch('JRUBY', true) 12 | JRubyCommand.new(runner, filename, args) 13 | else 14 | JavaCommand.new(runner, filename, args) 15 | end 16 | end 17 | 18 | # Trade in this Ruby instance for a JRuby instance, loading in a starter 19 | # script and passing it some arguments. Unless you set JRUBY: false in 20 | # ~/.jruby_art/config.yml, an installed version of jruby is used instead 21 | # of our vendored one. Note the use of jruby-complete might make using 22 | # other gems in your sketches hard (but not impossible).... 23 | def cmd 24 | cmda = command.cmd 25 | begin 26 | exec(*cmda) 27 | # exec replaces the Ruby process with the JRuby one. 28 | rescue Java::JavaLang::ClassNotFoundException 29 | end 30 | end 31 | end 32 | end 33 | 34 | # Wrap creation of java command string as a class 35 | class JavaCommand 36 | MAIN = 'org.jruby.Main' 37 | attr_reader :runner, :args, :filename, :opts, :complete 38 | def initialize(runner, args, filename) 39 | @runner = runner 40 | @args = args 41 | @filename = filename 42 | @complete = JRubyComplete.complete 43 | @opts = JavaOpts.new.opts 44 | end 45 | 46 | def cmd 47 | ['java', opts, '-cp', complete, MAIN, runner, filename, args].flatten 48 | end 49 | end 50 | 51 | # Wrap creation of jruby command string as a class 52 | class JRubyCommand 53 | attr_reader :runner, :args, :filename, :opts 54 | def initialize(runner, args, filename) 55 | @runner = runner 56 | @args = args 57 | @filename = filename 58 | @opts = JRubyOpts.new.opts 59 | end 60 | 61 | def cmd 62 | ['jruby', opts, runner, filename, args].flatten 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /library/vector_utils/vector_utils.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | PHI ||= (1 + Math.sqrt(5)) / 2 # golden ratio 4 | GA = PHI * 2 * Math::PI # golden angle 5 | 6 | # Useful Vector Utiliies 7 | module VectorUtil 8 | def self.rotate_vec2d(vectors: [], angle: 0) 9 | vectors.map { |vector| vector.rotate(angle) } 10 | end 11 | 12 | def self.vogel_layout(number:, node_size:) 13 | (0..number).map do |i| 14 | r = Math.sqrt(i) 15 | theta = i * ((2 * Math::PI) / (PHI * PHI)) 16 | x = Math.cos(theta) * r * node_size 17 | y = Math.sin(theta) * r * node_size 18 | Vec2D.new(x, y) 19 | end 20 | end 21 | 22 | def self.fibonacci_sphere(number:, radius:) 23 | (0..number).map do |i| 24 | lon = GA * i 25 | lon /= 2 * Math::PI 26 | lon -= lon.floor 27 | lon *= 2 * Math::PI 28 | lon -= 2 * Math::PI if lon > Math::PI 29 | lat = Math.asin(-1 + 2 * i / number.to_f) 30 | x = radius * Math.cos(lat) * Math.cos(lon) 31 | y = radius * Math.cos(lat) * Math.sin(lon) 32 | z = radius * Math.sin(lat) 33 | Vec3D.new(x, y, z) 34 | end 35 | end 36 | 37 | def self.spiral_layout(number:, radius:, resolution:, spacing:, inc:) 38 | n = 0 39 | angle = nil 40 | (0..number).map do 41 | angle = n * resolution 42 | n += inc 43 | radius -= angle * spacing 44 | x = Math.cos(angle) * radius 45 | y = Math.sin(angle) * radius 46 | Vec2D.new(x, y) 47 | end 48 | end 49 | 50 | def self.cartesian_to_polar(vec:) 51 | res = Vec3D.new(vec.mag, 0, 0) 52 | return Vec3D.new unless res.x.positive? 53 | 54 | res.y = -Math.atan2(vec.z, vec.x) 55 | res.z = Math.asin(vec.y / res.x) 56 | res 57 | end 58 | 59 | def self.to_cartesian(lat:, long:, radius:) 60 | latitude = lat 61 | longitude = long 62 | x = radius * Math.cos(latitude) * Math.cos(longitude) 63 | y = radius * Math.cos(latitude) * Math.sin(longitude) 64 | z = radius * Math.sin(latitude) 65 | Vec3D.new(x, y, z) 66 | end 67 | 68 | def self.polar_to_cartesian(vec:) 69 | return Vec3D.new if vec.mag <= 0 70 | 71 | Vec3D.new(Math.asin(vec.y / vec.mag), vec.mag, -Math.atan2(vec.z, vec.x)) 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /jruby_art.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'jruby_art/version' 6 | require 'rake' 7 | 8 | Gem::Specification.new do |spec| 9 | spec.name = 'jruby_art' 10 | spec.version = JRubyArt::VERSION 11 | spec.author = 'Martin Prout' 12 | spec.email = 'mamba2928@yahoo.co.uk' 13 | spec.description = <<-DESCRIPTION 14 | JRubyArt-2.5.0+ is a ruby implementation of the processing art framework, with enhanced 15 | functionality. Processing libraries and ruby gems can be used in your sketches. 16 | Features create/run/watch/live modes. 17 | DESCRIPTION 18 | spec.summary = 'Code as Art, Art as Code. Processing and Ruby are meant for each other.' 19 | spec.homepage = 'https://ruby-processing.github.io/JRubyArt/' 20 | spec.post_install_message = "Use 'k9 --install' to install jruby-complete, and 'k9 --check' to check config." 21 | spec.licenses = %w[GPL-3.0 LGPL-2.0] 22 | spec.files = FileList['bin/**/*', 'lib/**/*', 'library/**/*', 'samples/**/*', 'vendors/Rakefile'].exclude(/jar/).to_a 23 | spec.files << "lib/jruby_art-#{JRubyArt::VERSION}.jar" 24 | spec.files << 'lib/gluegen-rt.jar' 25 | spec.files << 'lib/jogl-all.jar' 26 | spec.files << 'lib/gluegen-rt-natives-linux-amd64.jar' 27 | spec.files << 'lib/gluegen-rt-natives-macosx-universal.jar' 28 | # spec.files << 'lib/gluegen-rt-natives-ios-arm64.jar' 29 | spec.files << 'lib/gluegen-rt-natives-windows-amd64.jar' 30 | spec.files << 'lib/jogl-all-natives-linux-amd64.jar' 31 | spec.files << 'lib/jogl-all-natives-macosx-universal.jar' 32 | # spec.files << 'lib/jogl-all-natives-ios-arm64.jar' 33 | spec.files << 'lib/jogl-all-natives-windows-amd64.jar' 34 | spec.files << 'library/pdf/itextpdf-5.5.13.2.jar' 35 | spec.files << 'library/svg/batik-all-1.14.jar' 36 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 37 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 38 | spec.require_paths = ['lib'] 39 | spec.required_ruby_version = '>= 2.5' 40 | spec.add_development_dependency 'minitest', '~> 5.15' 41 | spec.add_runtime_dependency 'rake', '~> 13.0' 42 | spec.requirements << 'A decent graphics card' 43 | spec.requirements << 'java runtime >= 17.0.1+' 44 | end 45 | -------------------------------------------------------------------------------- /lib/jruby_art/library.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'native_folder' 4 | require_relative 'native_loader' 5 | 6 | require 'pathname' 7 | 8 | # This class knows where to find JRubyArt libraries 9 | class Library 10 | require_relative '../jruby_art' 11 | require_relative './config' 12 | attr_reader :name, :path, :dir, :ppath 13 | 14 | def initialize(name) 15 | @name = name 16 | @ruby = true 17 | end 18 | 19 | def locate 20 | return if (@path = Pathname.new( 21 | File.join(SKETCH_ROOT, 'library', name, "#{name}.rb") 22 | )).exist? 23 | return if (@path = Pathname.new( 24 | File.join(K9_ROOT, 'library', name, "#{name}.rb") 25 | )).exist? 26 | 27 | locate_java 28 | end 29 | 30 | def locate_java 31 | @dir = Pathname.new( 32 | File.join(SKETCH_ROOT, 'library', name) 33 | ) 34 | return @path = dir.join(Pathname.new("#{name}.jar")) if dir.directory? 35 | 36 | locate_installed_java 37 | end 38 | 39 | def locate_installed_java 40 | return if dir.directory? 41 | 42 | if Processing::RP_CONFIG.fetch('processing_ide', false) 43 | prefix = library_path 44 | @dir = Pathname.new(File.join(prefix, 'libraries', name, 'library')) 45 | @path = dir.join(Pathname.new("#{name}.jar")) 46 | else 47 | @dir = Pathname.new( 48 | File.join(ENV['HOME'], '.jruby_art', 'libraries', name, 'library') 49 | ) 50 | end 51 | @path = dir.join(Pathname.new("#{name}.jar")) 52 | end 53 | 54 | def library_path 55 | Processing::RP_CONFIG.fetch('library_path', "#{ENV['HOME']}/.jruby_art") 56 | end 57 | 58 | def ruby? 59 | path.extname == '.rb' 60 | end 61 | 62 | def exist? 63 | path.exist? 64 | end 65 | 66 | def load_jars 67 | Dir.glob("#{dir}/*.jar").sort.each do |jar| 68 | require jar 69 | end 70 | return unless native_binaries? 71 | 72 | add_binaries_to_classpath 73 | end 74 | 75 | def native_binaries? 76 | native_folder = NativeFolder.new 77 | native = native_folder.name 78 | @ppath = File.join(dir, native) 79 | File.directory?(ppath) && 80 | !Dir.glob(File.join(ppath, native_folder.extension)).empty? 81 | end 82 | 83 | def add_binaries_to_classpath 84 | native_loader = NativeLoader.new 85 | native_loader.add_native_path(ppath) 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /test/helper_methods_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | require_relative '../lib/jruby_art/helper_methods' 5 | 6 | Java::Monkstone::JRLibrary.new.load(JRuby.runtime, false) 7 | 8 | # Helper Methods Test 9 | class HelperMethodsTest < Minitest::Test 10 | include Processing::HelperMethods 11 | include MathTool 12 | ARRAY = %w[albatross dog horse].freeze 13 | def test_hex_color 14 | col_double = 0.5 15 | hexcolor = 0xFFCC6600 16 | dodgy_hexstring = '*56666' 17 | hexstring = '#CC6600' 18 | assert hex_color(col_double) == 0.5, 'double as a color' 19 | assert hex_color(hexcolor) == -3_381_760, 'hexadecimal fixnum color' 20 | assert hex_color(hexstring) == -3_381_760, 'hexadecimal string color' 21 | assert_raises(StandardError, 'Dodgy Hexstring') do 22 | hex_color(dodgy_hexstring) 23 | end 24 | assert_raises(StandardError, 'Dodgy Color Conversion') do 25 | hex_color([]) 26 | end 27 | end 28 | 29 | def test_dist 30 | ax = 0 31 | ay = 0 32 | bx = 1.0 33 | by = 1.0 34 | assert_in_epsilon(dist(ax, ay, bx, by), Math.sqrt(2), 0.0001, '2D distance') 35 | by = 0.0 36 | assert_in_epsilon(dist(ax, ay, bx, by), 1.0, 0.0001, 'when y dimension is zero') 37 | ax = 0 38 | ay = 0 39 | bx = 0.0 40 | by = 0.0 41 | assert_in_epsilon(dist(ax, ay, bx, by), 0.0, 0.0001, 'when x and y dimension are zero') 42 | ax = 1 43 | ay = 1 44 | bx = -2.0 45 | by = -3.0 46 | assert_in_epsilon(dist(ax, ay, bx, by), 5.0, 0.0001, 'classic triangle dimensions') 47 | ax = -1 48 | ay = -1 49 | bx = 100 50 | by = 2.0 51 | cx = 3.0 52 | cy = 100 53 | assert_in_epsilon(dist(ax, ay, bx, by, cx, cy), 5.0, 0.0001, 'classic triangle dimensions') 54 | ax = 0 55 | ay = 0 56 | bx = -1.0 57 | by = -1.0 58 | cx = 0 59 | cy = 0 60 | assert_in_epsilon(dist(ax, ay, bx, by, cx, cy), Math.sqrt(2), 0.0001, '2D distance') 61 | ax = 0 62 | ay = 0 63 | bx = 0.0 64 | by = 0.0 65 | cx = 0 66 | cy = 0 67 | assert_in_epsilon(dist(ax, ay, bx, by, cx, cy), 0.0) 68 | ax = 0 69 | ay = 0 70 | bx = 1.0 71 | by = 0.0 72 | cx = 0 73 | cy = 0 74 | assert_in_epsilon(dist(ax, ay, bx, by, cx, cy), 1.0, 0.0001, 'when x and z dimension are zero') 75 | end 76 | 77 | def test_min 78 | assert_equal(min(*ARRAY), 'albatross') 79 | end 80 | 81 | def test_max 82 | assert_equal(max(*ARRAY), 'horse') 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /test/create_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | require_relative '../lib/jruby_art/creators/sketch_writer' 5 | 6 | EMACS = <<~CODE 7 | # frozen_string_literal: true 8 | 9 | require 'jruby_art' 10 | require 'jruby_art/app' 11 | 12 | Processing::App::SKETCH_PATH = __FILE__.freeze 13 | 14 | class FredSketch < Processing::App 15 | def settings 16 | size 200, 200, P2D 17 | end 18 | 19 | def setup 20 | sketch_title 'Fred Sketch' 21 | end 22 | 23 | def draw 24 | 25 | end 26 | end 27 | 28 | FredSketch.new if Processing.app.nil? 29 | 30 | CODE 31 | 32 | CLASS_SKETCH = <<~CODE 33 | # frozen_string_literal: true 34 | 35 | class FredSketch < Processing::App 36 | def settings 37 | size 200, 200, P2D 38 | end 39 | 40 | def setup 41 | sketch_title 'Fred Sketch' 42 | end 43 | 44 | def draw 45 | 46 | end 47 | end 48 | 49 | CODE 50 | 51 | BARE = <<~CODE 52 | def settings 53 | size 200, 200, P2D 54 | end 55 | 56 | def setup 57 | sketch_title 'Fred Sketch' 58 | end 59 | 60 | def draw 61 | 62 | end 63 | 64 | 65 | 66 | CODE 67 | 68 | class SketchWriterTest < Minitest::Test 69 | ParamMethods = Struct.new(:name, :class_name, :sketch_title, :sketch_size) 70 | 71 | def setup 72 | @param = ParamMethods.new( 73 | 'fred_sketch', 74 | 'FredSketch', 75 | "sketch_title 'Fred Sketch'", 76 | 'size 200, 200, P2D' 77 | ) 78 | end 79 | 80 | def test_parameter_new 81 | param = SketchParameters.new(name: 'fred_sketch', args: %w[200 200 p2d]) 82 | assert_equal "sketch_title 'Fred Sketch'", param.sketch_title 83 | assert_equal 'size 200, 200, P2D', param.sketch_size 84 | assert_equal 'FredSketch', param.class_name 85 | end 86 | 87 | def test_bare 88 | result = BARE.split(/\n/, -1) 89 | sketch = BareSketch.new(@param).code 90 | sketch.each_with_index do |line, i| 91 | assert_equal result[i], line 92 | end 93 | end 94 | 95 | def test_class 96 | result = CLASS_SKETCH.split(/\n/, -1) 97 | sketch = ClassSketch.new(@param).code 98 | sketch.each_with_index do |line, i| 99 | assert_equal result[i], line 100 | end 101 | end 102 | 103 | def test_emacs 104 | result = EMACS.split(/\n/, -1) 105 | sketch = EmacsSketch.new(@param).code 106 | sketch.each_with_index do |line, i| 107 | assert_equal result[i], line 108 | end 109 | end 110 | end 111 | -------------------------------------------------------------------------------- /lib/jruby_art/runners/watch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | 3 | require_relative 'base' 4 | require_relative '../config' 5 | 6 | module Processing 7 | class WatchException < StandardError 8 | end 9 | 10 | # A sketch loader, observer, and reloader, to tighten 11 | # the feedback between code and effect. 12 | class Watcher 13 | # Sic a new Processing::Watcher on the sketch 14 | WATCH_MESSAGE ||= <<-EOS.freeze 15 | Warning: 16 | To protect you from running watch mode in a top level 17 | directory with lots of nested ruby files we 18 | limit the number of files to watch to %d. 19 | If you really want to watch %d files you should 20 | increase MAX_WATCH in ~/.jruby_art/config.yml 21 | 22 | EOS 23 | SLEEP_TIME = 0.2 24 | def initialize 25 | count = Dir['**.*rb'].length 26 | max_watch = RP_CONFIG.fetch('MAX_WATCH', 20) 27 | abort format(WATCH_MESSAGE, max_watch, count) if count > max_watch.to_i 28 | 29 | reload_files_to_watch 30 | @time = Time.now 31 | start_watching 32 | end 33 | 34 | # Kicks off a thread to watch the sketch, reloading JRubyArt 35 | # and restarting the sketch whenever it changes. 36 | def start_watching 37 | start_original 38 | Kernel.loop do 39 | if @files.find { |file| FileTest.exist?(file) && File.stat(file).mtime > @time } 40 | puts 'reloading sketch...' 41 | Processing.app&.close 42 | java.lang.System.gc 43 | @time = Time.now 44 | start_runner 45 | reload_files_to_watch 46 | end 47 | sleep SLEEP_TIME 48 | end 49 | end 50 | 51 | # Convenience function to report errors when loading and running a sketch, 52 | # instead of having them eaten by the thread they are loaded in. 53 | def report_errors 54 | yield 55 | rescue Exception => e 56 | wformat = 'Exception occured while running sketch %s...' 57 | tformat = "Backtrace:\n\t%s" 58 | warn format(wformat, File.basename(SKETCH_PATH)) 59 | puts format(tformat, e.backtrace.join("\n\t")) 60 | end 61 | 62 | def start_original 63 | @runner = Thread.start do 64 | report_errors do 65 | Processing.load_and_run_sketch 66 | end 67 | end 68 | end 69 | 70 | def start_runner 71 | @runner.kill if @runner&.alive? 72 | @runner.join 73 | @runner = nil 74 | start_original 75 | end 76 | 77 | def reload_files_to_watch 78 | @files = Dir.glob(File.join(SKETCH_ROOT, '**/*.{rb,glsl}')) 79 | end 80 | end 81 | end 82 | 83 | Processing::Watcher.new 84 | -------------------------------------------------------------------------------- /src/main/java/monkstone/fastmath/Deglut.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-21 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.fastmath; 21 | 22 | import org.jruby.Ruby; 23 | import org.jruby.RubyNumeric; 24 | import org.jruby.RubyModule; 25 | import org.jruby.anno.JRubyModule; 26 | import org.jruby.anno.JRubyMethod; 27 | import org.jruby.runtime.ThreadContext; 28 | import org.jruby.runtime.builtin.IRubyObject; 29 | 30 | /** 31 | * 32 | * @author Martin Prout 33 | */ 34 | @JRubyModule(name = "DegLut") 35 | public class Deglut { 36 | 37 | /** 38 | * 39 | * @param runtime Ruby 40 | */ 41 | public static void createDeglut(final Ruby runtime) { 42 | RubyModule deglutModule = runtime.defineModule("DegLut"); 43 | deglutModule.defineAnnotatedMethods(Deglut.class); 44 | } 45 | 46 | /** 47 | * 48 | * @param context ThreadContext 49 | * @param recv IRubyObject 50 | * @param other IRubyObject degrees 51 | * @return sin IRubyObject 52 | */ 53 | @JRubyMethod(name = "sin", module = true) 54 | public static IRubyObject sin(ThreadContext context, IRubyObject recv, IRubyObject other) { 55 | float thet = (float) ((RubyNumeric) other).getLongValue(); 56 | return context.runtime.newFloat(DegLutTables.sinDeg(thet)); 57 | } 58 | 59 | /** 60 | * 61 | * @param context ThreadContext 62 | * @param recv IRubyObject 63 | * @param other IRubyObject degrees 64 | * @return cos IRubyObject 65 | */ 66 | @JRubyMethod(name = "cos", module = true) 67 | public static IRubyObject cos(ThreadContext context, IRubyObject recv, IRubyObject other) { 68 | float thet = (float) ((RubyNumeric) other).getLongValue(); 69 | return context.runtime.newFloat(DegLutTables.cosDeg(thet)); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /test/test_map1d.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | require_relative '../lib/jruby_art/helper_methods' 5 | 6 | Java::Monkstone::JRLibrary.new.load(JRuby.runtime, false) 7 | # method tests 8 | class Rp5Test < Minitest::Test 9 | include Processing::HelperMethods 10 | include Processing::MathTool 11 | def setup; end 12 | 13 | def test_map1d 14 | x = [0, 5, 7.5, 10] 15 | range1 = (0..10) 16 | range2 = (100..1) 17 | range3 = (0..10) 18 | range4 = (5..105) 19 | assert_in_epsilon(map1d(x[0], range1, range2), 100, 'map to first') 20 | assert_in_epsilon(map1d(x[1], range1, range2), 50.5, 'map to reversed intermediate') 21 | assert_in_epsilon(map1d(x[2], range3, range4), 80.0, 'map to intermediate') 22 | assert_in_epsilon(map1d(x[3], range1, range2), 1, 'map to last') 23 | end 24 | 25 | def test_p5map # as map1d except not using range input 26 | x = [0, 5, 7.5, 10] 27 | range1 = (0..10) 28 | range2 = (100..1) 29 | range3 = (0..10) 30 | range4 = (5..105) 31 | assert_in_epsilon(p5map(x[0], range1.first, range1.last, range2.first, range2.last), 100) 32 | assert_in_epsilon(p5map(x[1], range1.first, range1.last, range2.first, range2.last), 50.5) 33 | assert_in_epsilon(p5map(x[2], range3.first, range3.last, range4.first, range4.last), 80.0) 34 | assert_in_epsilon(p5map(x[3], range1.first, range1.last, range2.first, range2.last), 1) 35 | end 36 | 37 | def test_norm 38 | x = [10, 140, 210] 39 | start0 = 30 40 | last0 = 200 41 | start1 = 0 42 | last1 = 200 43 | assert_in_epsilon(norm(x[0], start0, last0), -0.11764705882352941, 'unclamped map') 44 | assert_in_epsilon(norm(x[1], start1, last1), 0.7, 'map to intermediate') 45 | assert_in_epsilon(norm(x[2], start1, last1), 1.05, 'unclamped map') 46 | end 47 | 48 | def test_norm_strict 49 | x = [10, 140, 210] 50 | start0 = 30 51 | last0 = 200 52 | assert_in_epsilon(norm_strict(x[0], start0, last0), 0, 'clamped map to 0..1.0') 53 | end 54 | 55 | def test_lerp # behaviour is deliberately different to processing which is unclamped 56 | x = [0.5, 0.8, 2.0] 57 | start0 = 300 58 | last0 = 200 59 | start1 = 0 60 | last1 = 200 61 | assert_in_epsilon(lerp(start0, last0, x[0]), 250, 'produces a intermediate value of a reversed range') 62 | assert_in_epsilon(lerp(start1, last1, x[1]), 160, 'lerps tp an intermediate value') 63 | assert_in_epsilon(lerp(start1, last1, x[2]), 200, 'lerps to the last value of a range') 64 | end 65 | 66 | def test_constrain 67 | x = [15, 2_500, -2_500] 68 | start1 = 0 69 | last1 = 200 70 | assert_in_epsilon(constrain(x[0], start1, last1), 15) 71 | assert_in_epsilon(constrain(x[1], start1, last1), 200) 72 | assert_in_epsilon(constrain(x[2], start1, last1), 0) 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /src/main/java/japplemenubar/JAppleMenuBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2011-12 hansi raber, released under LGPL under agreement 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation, version 2.1. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General 16 | Public License along with this library; if not, write to the 17 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 | Boston, MA 02111-1307 USA 19 | */ 20 | package japplemenubar; 21 | 22 | import java.io.*; 23 | 24 | import processing.core.PApplet; 25 | 26 | 27 | /** 28 | * Starting point for the application. General initialization should be done 29 | * inside the ApplicationController's init() method. If certain kinds of 30 | * non-Swing initialization takes too long, it should happen in a new Thread 31 | * and off the Swing event dispatch thread (EDT). 32 | * 33 | * @author hansi 34 | */ 35 | public class JAppleMenuBar { 36 | static JAppleMenuBar instance; 37 | static final String FILENAME = "libjAppleMenuBar.jnilib"; 38 | 39 | static { 40 | try { 41 | File temp = File.createTempFile("processing", "menubar"); 42 | temp.delete(); // remove the file itself 43 | temp.mkdirs(); // create a directory out of it 44 | temp.deleteOnExit(); 45 | 46 | File jnilibFile = new File(temp, FILENAME); 47 | InputStream input = JAppleMenuBar.class.getResourceAsStream(FILENAME); 48 | if (input != null) { 49 | if (PApplet.saveStream(jnilibFile, input)) { 50 | System.load(jnilibFile.getAbsolutePath()); 51 | instance = new JAppleMenuBar(); 52 | 53 | } else { 54 | sadness("Problem saving " + FILENAME + " for full screen use."); 55 | } 56 | } else { 57 | sadness("Could not load " + FILENAME + " from core.jar"); 58 | } 59 | } catch (IOException e) { 60 | sadness("Unknown error, here's the stack trace."); 61 | e.printStackTrace(); 62 | } 63 | } 64 | 65 | 66 | static void sadness(String msg) { 67 | System.err.println("Full screen mode disabled. " + msg); 68 | } 69 | 70 | 71 | // static public void show() { 72 | // instance.setVisible(true); 73 | // } 74 | 75 | 76 | static public void hide() { 77 | instance.setVisible(false, false); 78 | } 79 | 80 | 81 | public native void setVisible(boolean visibility, boolean kioskMode); 82 | 83 | 84 | // public void setVisible(boolean visibility) { 85 | // // Keep original API in-tact. Default kiosk-mode to off. 86 | // setVisible(visibility, false); 87 | // } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/processing/opengl/VertexBuffer.java: -------------------------------------------------------------------------------- 1 | /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Part of the Processing project - http://processing.org 5 | 6 | Copyright (c) 2012-15 The Processing Foundation 7 | Copyright (c) 2004-12 Ben Fry and Casey Reas 8 | Copyright (c) 2001-04 Massachusetts Institute of Technology 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation, version 2.1. 13 | 14 | This library is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General 20 | Public License along with this library; if not, write to the 21 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 22 | Boston, MA 02111-1307 USA 23 | */ 24 | 25 | package processing.opengl; 26 | 27 | import processing.opengl.PGraphicsOpenGL.GLResourceVertexBuffer; 28 | 29 | // TODO: need to combine with PGraphicsOpenGL.VertexAttribute 30 | public class VertexBuffer { 31 | static protected final int INIT_VERTEX_BUFFER_SIZE = 256; 32 | static protected final int INIT_INDEX_BUFFER_SIZE = 512; 33 | 34 | public int glId; 35 | int target; 36 | int elementSize; 37 | int ncoords; 38 | boolean index; 39 | 40 | protected PGL pgl; // The interface between Processing and OpenGL. 41 | protected int context; // The context that created this texture. 42 | private GLResourceVertexBuffer glres; 43 | 44 | VertexBuffer(PGraphicsOpenGL pg, int target, int ncoords, int esize) { 45 | this(pg, target, ncoords, esize, false); 46 | } 47 | 48 | VertexBuffer(PGraphicsOpenGL pg, int target, int ncoords, int esize, boolean index) { 49 | pgl = pg.pgl; 50 | context = pgl.createEmptyContext(); 51 | 52 | this.target = target; 53 | this.ncoords = ncoords; 54 | this.elementSize = esize; 55 | this.index = index; 56 | create(); 57 | init(); 58 | } 59 | 60 | protected final void create() { 61 | context = pgl.getCurrentContext(); 62 | glres = new GLResourceVertexBuffer(this); 63 | } 64 | 65 | protected final void init() { 66 | int size = index ? ncoords * INIT_INDEX_BUFFER_SIZE * elementSize : 67 | ncoords * INIT_VERTEX_BUFFER_SIZE * elementSize; 68 | pgl.bindBuffer(target, glId); 69 | pgl.bufferData(target, size, null, PGL.STATIC_DRAW); 70 | } 71 | 72 | protected void dispose() { 73 | if (glres != null) { 74 | glres.dispose(); 75 | glId = 0; 76 | glres = null; 77 | } 78 | } 79 | 80 | protected boolean contextIsOutdated() { 81 | boolean outdated = !pgl.contextIsCurrent(context); 82 | if (outdated) { 83 | dispose(); 84 | } 85 | return outdated; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /test/k9_run_test.rb: -------------------------------------------------------------------------------- 1 | require_relative 'test_helper' 2 | 3 | Dir.chdir(File.dirname(__FILE__)) 4 | 5 | # Sketch tests 6 | class Rp5Test < Minitest::Test 7 | def test_normal 8 | out, _err_ = capture_io do 9 | Kernel.open('|../bin/k9 -r sketches/basic.rb', 'r') do |io| 10 | while (l = io.gets) 11 | puts(l.chop) 12 | end 13 | end 14 | end 15 | assert_match(/ok/, out, 'Failed Basic Sketch') 16 | end 17 | 18 | def test_sketch_path 19 | out, _err_ = capture_io do 20 | Kernel.open('|../bin/k9 -r sketches/sketch_path.rb', 'r') do |io| 21 | while (l = io.gets) 22 | puts(l.chop) 23 | end 24 | end 25 | end 26 | assert_match('/home/tux/JRubyArt', out, 'Failed Sketch Path Sketch') 27 | end 28 | 29 | def test_on_top 30 | out, _err_ = capture_io do 31 | Kernel.open('|../bin/k9 -r sketches/on_top.rb', 'r') do |io| 32 | while (l = io.gets) 33 | puts(l.chop) 34 | end 35 | end 36 | end 37 | assert_match(/ok/, out, 'Failed On Top Sketch') 38 | end 39 | 40 | def test_p2d 41 | out, _err_ = capture_io do 42 | Kernel.open('|../bin/k9 -r sketches/p2d.rb', 'r') do |io| 43 | while (l = io.gets) 44 | puts(l.chop) 45 | end 46 | end 47 | end 48 | assert_match(/ok/, out, 'Failed P2D sketch') 49 | end 50 | 51 | def test_proc_root 52 | skip 'TODO: create a test for library configuration' 53 | require 'psych' 54 | path = File.expand_path('~/.jruby_art/config.yml') 55 | config = FileTest.exist?(path) ? Psych.load_file(path) : {} 56 | library = config.empty? ? '' : config['library_path'] 57 | assert /librar/.match?(library), 'You need to set your library_path in .jruby_art/config.yml' 58 | end 59 | 60 | def test_fx2d 61 | skip 'Currently FX2D not implemented' 62 | out, _err = capture_io do 63 | Kernel.open('|../bin/k9 -r sketches/fx2d.rb', 'r') do |io| 64 | while (l = io.gets) 65 | puts(l.chop) 66 | end 67 | end 68 | end 69 | end 70 | 71 | def test_p3d 72 | out, _err_ = capture_io do 73 | Kernel.open('|../bin/k9 -r sketches/p3d.rb', 'r') do |io| 74 | while (l = io.gets) 75 | puts(l.chop) 76 | end 77 | end 78 | end 79 | assert_match(/ok/, out, 'Failed P3D sketch') 80 | end 81 | 82 | def test_graphics 83 | out, _err_ = capture_io do 84 | Kernel.open('|../bin/k9 -r sketches/graphics.rb', 'r') do |io| 85 | while (l = io.gets) 86 | puts(l.chop) 87 | end 88 | end 89 | end 90 | assert out[0].to_i >= 3, "Graphics capability #{out} may be sub-optimal" 91 | end 92 | 93 | def test_setup_exception 94 | out, _err_ = capture_io do 95 | Kernel.open('|../bin/k9 -r sketches/setup_ex.rb', 'r') do |io| 96 | while (l = io.gets) 97 | puts(l.chop) 98 | end 99 | end 100 | end 101 | assert out.index('undefined local variable or method `unknown_method'), 'Failed to raise exception?' 102 | end 103 | end 104 | -------------------------------------------------------------------------------- /library/library_proxy/README.md: -------------------------------------------------------------------------------- 1 | ### Using the LibraryProxy in your sketches 2 | LibraryProxy is a [abstract java class](https://github.com/ruby-processing/JRubyArt/blob/master/src/monkstone/core/LibraryProxy.java) so that you can acccess vanilla processing library reflection methods in your sketches using ruby. 3 | 4 | In the sketch you should `load_library :library_proxy` and your library class should inherit 5 | from LibraryProxy and implement pre(), draw() and post() methods (can be empty method if not 6 | required). For simplicity initialize your `processing library` in the sketch `setup`. 7 | 8 | ### Example library 9 | 10 | ```ruby 11 | require 'forwardable' 12 | 13 | # A custom Array created using forwardable (that can also access the PApplet pre, 14 | # post and draw loops by extending our new LibraryProxy class. Also has access 15 | # to custom background(int), fill(int) and stroke(int) methods. 16 | class CustomArray < LibraryProxy 17 | extend Forwardable 18 | def_delegators(:@objs, :each, :<<) 19 | include Enumerable 20 | 21 | attr_reader :app 22 | 23 | # We must initialize class with the PApplet instance 24 | def initialize(app) 25 | @app = app 26 | @objs = [] 27 | end 28 | 29 | def add_object(mx, my, x, y, speed) 30 | self << Particle.new(x.to_i, y.to_i, mx, my, Sketch::UNIT, speed, 1, 1) 31 | end 32 | 33 | # Access the processing post loop (gets called after draw) 34 | def post 35 | each do |obj| 36 | update_x obj 37 | next unless obj.y >= Sketch::UNIT || obj.x <= 0 38 | obj.ydir *= -1 39 | obj.y += obj.ydir 40 | end 41 | end 42 | 43 | def update_x(obj) 44 | obj.x += obj.speed * obj.xdir 45 | return if (0..Sketch::UNIT).cover? obj.x 46 | obj.xdir *= -1 47 | obj.x += obj.xdir 48 | obj.y += obj.ydir 49 | end 50 | 51 | # We need this to fulfill the contract of implementing abstract methods of 52 | # LibraryProxy which is an alias for Java::ProcessingCore::AbstractLibrary 53 | def pre 54 | end 55 | 56 | # Access the processing draw loop here, using our custom background and fill 57 | # note: use of 'app' to access ellipse functionality as would otherwise be 58 | # required for background and fill 59 | def draw 60 | background(0) 61 | fill(255) 62 | each do |obj| 63 | app.ellipse(obj.mx + obj.x, obj.my + obj.y, 6, 6) 64 | end 65 | end 66 | end 67 | 68 | # The Particle object 69 | 70 | Particle = Struct.new(:x, :y, :mx, :my, :size, :speed, :xdir, :ydir) 71 | ``` 72 | ### Example sketch 73 | 74 | ```ruby 75 | # A minimalist sketch that demonstrates a possible approach to creating a custom 76 | # array of objects using forwardable. Also demonstrates how to use LibraryProxy. 77 | 78 | load_library :library_proxy # loads the JRubyArt LibraryProxy abstract class 79 | require_relative 'custom_array' # loads our custom 'library' class 80 | 81 | UNIT = 40 82 | 83 | def setup 84 | size 640, 360 85 | wide_count = width / UNIT 86 | height_count = height / UNIT 87 | custom_array = CustomArray.new(self) 88 | height_count.times do |i| 89 | wide_count.times do |j| 90 | custom_array.add_object(j * UNIT, i * UNIT, UNIT / 2, UNIT / 2, rand(0.05..0.8)) 91 | end 92 | end 93 | no_stroke 94 | end 95 | 96 | # does nothing here see custom_array.rb 97 | def draw 98 | end 99 | ``` 100 | -------------------------------------------------------------------------------- /src/main/java/monkstone/arcball/Quaternion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | package monkstone.arcball; 22 | 23 | /** 24 | * Based on a original sketch by Ariel Malka 25 | * Arcball quaternion idea by Ken Shoemake 26 | * http://dl.acm.org/citation.cfm?id=325242 27 | * A google of the quaternions term will find a 28 | * freely down-loadable article by Ken Shoemake. 29 | * @author Martin Prout 30 | */ 31 | public final class Quaternion { 32 | 33 | private double w, x, y, z; 34 | 35 | /** 36 | * 37 | */ 38 | public Quaternion() { 39 | reset(); 40 | } 41 | 42 | /** 43 | * 44 | * @param w double 45 | * @param x double 46 | * @param y double 47 | * @param z double 48 | */ 49 | public Quaternion(double w, double x, double y, double z) { 50 | this.w = w; 51 | this.x = x; 52 | this.y = y; 53 | this.z = z; 54 | } 55 | 56 | /** 57 | * 58 | */ 59 | public void reset() { 60 | w = 1.0f; 61 | x = 0.0f; 62 | y = 0.0f; 63 | z = 0.0f; 64 | } 65 | 66 | /** 67 | * 68 | * @param w scalar double 69 | * @param v custom Vector class 70 | */ 71 | public void set(double w, Jvector v) { 72 | this.w = w; 73 | x = v.x; 74 | y = v.y; 75 | z = v.z; 76 | } 77 | 78 | /** 79 | * 80 | * @param q Quaternion 81 | */ 82 | public void set(Quaternion q) { 83 | w = q.w; 84 | x = q.x; 85 | y = q.y; 86 | z = q.z; 87 | } 88 | 89 | /** 90 | * 91 | * @param q1 Quaternion 92 | * @param q2 Quaternion 93 | * @return new Quaternion 94 | */ 95 | public static Quaternion mult(Quaternion q1, Quaternion q2) { 96 | double w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; 97 | double x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; 98 | double y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z; 99 | double z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x; 100 | return new Quaternion(w, x, y, z); 101 | } 102 | 103 | /** 104 | * Transform this Quaternion into an angle (radians) and an axis vector, about 105 | * which to rotate (avoids NaN by setting sa to 1.0F when sa < epsilon) 106 | * @return a new double[] where a0 = angle and a1 .. a3 are axis vector 107 | */ 108 | 109 | public double[] getValue() { 110 | double sa = Math.sqrt(1.0 - w * w); 111 | if (sa < processing.core.PConstants.EPSILON) { 112 | sa = 1.0f; 113 | } 114 | return new double[]{ Math.acos(w) * 2.0f, x / sa, y / sa, z / sa}; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/processing/event/MouseEvent.java: -------------------------------------------------------------------------------- 1 | /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Part of the Processing project - http://processing.org 5 | 6 | Copyright (c) 2012 The Processing Foundation 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.event; 24 | 25 | //import processing.core.PConstants; 26 | 27 | 28 | public class MouseEvent extends Event { 29 | static public final int PRESS = 1; 30 | static public final int RELEASE = 2; 31 | static public final int CLICK = 3; 32 | static public final int DRAG = 4; 33 | static public final int MOVE = 5; 34 | static public final int ENTER = 6; 35 | static public final int EXIT = 7; 36 | static public final int WHEEL = 8; 37 | 38 | protected int x, y; 39 | protected int button; 40 | protected int count; 41 | 42 | 43 | public MouseEvent(Object nativeObject, 44 | long millis, int action, int modifiers, 45 | int x, int y, int button, int count) { 46 | super(nativeObject, millis, action, modifiers); 47 | this.flavor = MOUSE; 48 | this.x = x; 49 | this.y = y; 50 | this.button = button; 51 | this.count = count; 52 | } 53 | 54 | 55 | public int getX() { 56 | return x; 57 | } 58 | 59 | 60 | public int getY() { 61 | return y; 62 | } 63 | 64 | 65 | /** Which button was pressed, either LEFT, CENTER, or RIGHT. 66 | * @return */ 67 | public int getButton() { 68 | return button; 69 | } 70 | 71 | 72 | /** 73 | * Number of clicks for mouse button events, or the number of steps (positive 74 | * or negative depending on direction) for a mouse wheel event.Wheel events follow Java (see here), so 75 | getAmount() will return "negative values if the mouse wheel was rotated 76 | up or away from the user" and positive values in the other direction. 77 | * On Mac OS X, this will be reversed when "natural" scrolling is enabled 78 | in System Preferences &rarr Mouse. 79 | * @return 80 | */ 81 | public int getCount() { 82 | return count; 83 | } 84 | 85 | 86 | private String actionString() { 87 | switch (action) { 88 | default: 89 | return "UNKNOWN"; 90 | case CLICK: 91 | return "CLICK"; 92 | case DRAG: 93 | return "DRAG"; 94 | case ENTER: 95 | return "ENTER"; 96 | case EXIT: 97 | return "EXIT"; 98 | case MOVE: 99 | return "MOVE"; 100 | case PRESS: 101 | return "PRESS"; 102 | case RELEASE: 103 | return "RELEASE"; 104 | case WHEEL: 105 | return "WHEEL"; 106 | } 107 | } 108 | 109 | @Override 110 | public String toString() { 111 | return String.format("", 112 | actionString(), x, y, count, button); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/processing/event/Event.java: -------------------------------------------------------------------------------- 1 | /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Part of the Processing project - http://processing.org 5 | 6 | Copyright (c) 2012 The Processing Foundation 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.event; 24 | 25 | 26 | public class Event { 27 | protected Object nativeObject; 28 | 29 | protected long millis; 30 | protected int action; 31 | 32 | // These correspond to the java.awt.Event modifiers (not to be confused with 33 | // the newer getModifiersEx), though they're not guaranteed to in the future. 34 | static public final int SHIFT = 1 << 0; 35 | static public final int CTRL = 1 << 1; 36 | static public final int META = 1 << 2; 37 | static public final int ALT = 1 << 3; 38 | protected int modifiers; 39 | 40 | // Types of events. As with all constants in Processing, brevity's preferred. 41 | static public final int KEY = 1; 42 | static public final int MOUSE = 2; 43 | static public final int TOUCH = 3; 44 | protected int flavor; 45 | 46 | 47 | public Event(Object nativeObject, long millis, int action, int modifiers) { 48 | this.nativeObject = nativeObject; 49 | this.millis = millis; 50 | this.action = action; 51 | this.modifiers = modifiers; 52 | } 53 | 54 | 55 | public int getFlavor() { 56 | return flavor; 57 | } 58 | 59 | 60 | /** 61 | * Get the platform-native event object. This might be the java.awt event 62 | * on the desktop, though if you're using OpenGL on the desktop it'll be a 63 | * NEWT event that JOGL uses. Android events are something else altogether. 64 | * Bottom line, use this only if you know what you're doing, and don't make 65 | * assumptions about the class type. 66 | */ 67 | public Object getNative() { 68 | return nativeObject; 69 | } 70 | 71 | 72 | // public void setNative(Object nativeObject) { 73 | // this.nativeObject = nativeObject; 74 | // } 75 | 76 | 77 | public long getMillis() { 78 | return millis; 79 | } 80 | 81 | 82 | // public void setMillis(long millis) { 83 | // this.millis = millis; 84 | // } 85 | 86 | 87 | public int getAction() { 88 | return action; 89 | } 90 | 91 | 92 | // public void setAction(int action) { 93 | // this.action = action; 94 | // } 95 | 96 | 97 | public int getModifiers() { 98 | return modifiers; 99 | } 100 | 101 | 102 | // public void setModifiers(int modifiers) { 103 | // this.modifiers = modifiers; 104 | // } 105 | 106 | 107 | public boolean isShiftDown() { 108 | return (modifiers & SHIFT) != 0; 109 | } 110 | 111 | 112 | public boolean isControlDown() { 113 | return (modifiers & CTRL) != 0; 114 | } 115 | 116 | 117 | public boolean isMetaDown() { 118 | return (modifiers & META) != 0; 119 | } 120 | 121 | 122 | public boolean isAltDown() { 123 | return (modifiers & ALT) != 0; 124 | } 125 | } -------------------------------------------------------------------------------- /pom.rb: -------------------------------------------------------------------------------- 1 | project 'jruby_art', 'https://github.com/ruby-processing/JRubyArt' do 2 | 3 | model_version '4.0.0' 4 | id 'ruby-processing:jruby_art:2.6.1' 5 | packaging 'jar' 6 | 7 | description 'Jar for JRubyArt' 8 | 9 | { 10 | 'monkstone' => 'Martin Prout', 'sampottinger' => 'Sam Pottinger', 11 | 'benfry' => 'Ben Fry', 'REAS' => 'Casey Reas', 'codeanticode' => 'Andres Colubri' 12 | }.each do |key, value| 13 | developer key do 14 | name value 15 | roles 'developer' 16 | end 17 | end 18 | 19 | issue_management 'https://github.com/ruby-processing/JRubyArt/issues', 'Github' 20 | 21 | source_control( :url => 'https://github.com/ruby-processing/JRubyArt', 22 | :connection => 'scm:git:git://github.com/ruby-processing/JRubyArt.git', 23 | :developer_connection => 'scm:git:git@github.com/ruby-processing/JRubyArt.git' ) 24 | 25 | properties( 'jruby_art.basedir' => '${project.basedir}', 26 | 'processing.api' => 'http://processing.github.io/processing-javadocs/core/', 27 | 'source.directory' => 'src', 28 | 'polyglot.dump.pom' => 'pom.xml', 29 | 'project.build.sourceEncoding' => 'UTF-8', 30 | 'jogl.version' => '2.3.2', 31 | 'jruby.version' => '9.3.3.0', 32 | 'itextpdf.version' => '5.5.13.2', 33 | 'batik.version' => '1.14', 34 | 'jruby.api' => 'http://jruby.org/apidocs/' ) 35 | 36 | jar 'org.jruby:jruby-base:${jruby.version}' 37 | jar 'org.jogamp.jogl:jogl-all:${jogl.version}' 38 | jar 'org.jogamp.gluegen:gluegen-rt-main:${jogl.version}' 39 | jar 'org.processing:video:3.0.2' 40 | jar 'org.apache.xmlgraphics:batik-all:${batik.version}' 41 | jar 'com.itextpdf:itextpdf:${itextpdf.version}' 42 | 43 | overrides do 44 | plugin :resources, '3.2.0' 45 | plugin :dependency, '3.2.0' do 46 | execute_goals( :id => 'default-cli', 47 | 'artifactItems' => [ { 'groupId' => 'com.itextpdf', 48 | 'artifactId' => 'itextpdf', 49 | 'version' => '${itextpdf.version}', 50 | 'type' => 'jar', 51 | 'outputDirectory' => '${jruby_art.basedir}/library/pdf' }, 52 | { 'groupId' => 'org.apache.xmlgraphics', 53 | 'artifactId' => 'batik-all', 54 | 'version' => '${batik.version}', 55 | 'type' => 'jar', 56 | 'outputDirectory' => '${jruby_art.basedir}/library/svg' } ] ) 57 | end 58 | 59 | plugin( :compiler, '3.9.0', 60 | 'release' => '17' ) 61 | plugin( :javadoc, '3.3.1', 62 | 'detectOfflineLinks' => 'false', 63 | 'links' => [ '${processing.api}', 64 | '${jruby.api}' ] ) 65 | plugin( :jar, '3.2.2', 66 | 'archive' => { 67 | 'manifestEntries' => { 68 | 'Automatic-Module-Name' => 'processing.core' 69 | } 70 | } ) 71 | plugin :pmd, '3.15.0' 72 | plugin :jdeps, '3.1.2' do 73 | execute_goals 'jdkinternals', 'test-jdkinternals' 74 | end 75 | end 76 | 77 | build do 78 | resource do 79 | directory '${source.directory}/main/java' 80 | excludes '**/**/*.java' 81 | end 82 | resource do 83 | directory '${source.directory}/main/resources' 84 | includes '**/*.png', '**/*.txt', '**/*.glsl' 85 | end 86 | end 87 | 88 | reporting do 89 | plugin 'org.apache.maven.plugins:mavan-jxr-plugin:2.3' 90 | end 91 | 92 | end 93 | -------------------------------------------------------------------------------- /src/main/java/monkstone/fastmath/DegLutTables.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.fastmath; 21 | 22 | public final class DegLutTables { 23 | 24 | /** 25 | * 26 | */ 27 | static public float PI = 3.1415927f; 28 | 29 | /** 30 | * 31 | */ 32 | public static final float PI2 = PI * 2; 33 | static private final int SIN_BITS = 15; // 16KB. Adjust for accuracy. 34 | static private final int SIN_MASK = ~(-1 << SIN_BITS); 35 | static private final int SIN_COUNT = SIN_MASK + 1; 36 | 37 | private static final float RAD_FULL = PI * 2; 38 | private static final float DEG_FULL = 360; 39 | private static final float RAD_TO_INDEX = SIN_COUNT / RAD_FULL; 40 | private static final float DEG_TO_INDEX = SIN_COUNT / DEG_FULL; 41 | 42 | /** 43 | * multiply by this to convert from radians to degrees 44 | */ 45 | public static final float RADIANS_TO_DEGREES = 180f / PI; 46 | 47 | /** 48 | * 49 | */ 50 | public static final float RAD_DEG = RADIANS_TO_DEGREES; 51 | /** 52 | * multiply by this to convert from degrees to radians 53 | */ 54 | public static final float DEGREES_TO_RADIANS = PI / 180; 55 | 56 | /** 57 | * 58 | */ 59 | public static final float DEG_RAD = DEGREES_TO_RADIANS; 60 | 61 | static private class Sin { 62 | 63 | static float[] table = new float[SIN_COUNT]; 64 | 65 | static { 66 | for (int i = 0; i < SIN_COUNT; i++) { 67 | table[i] = (float) Math.sin((i + 0.5f) / SIN_COUNT * RAD_FULL); 68 | } 69 | for (int i = 0; i < 360; i += 90) { 70 | table[(int) (i * DEG_TO_INDEX) & SIN_MASK] = (float) Math.sin(i * DEGREES_TO_RADIANS); 71 | } 72 | } 73 | } 74 | 75 | /** 76 | * Returns the sine in radians from a lookup table. 77 | * @param radians 78 | * @return 79 | */ 80 | static public float sin(float radians) { 81 | return Sin.table[(int) (radians * RAD_TO_INDEX) & SIN_MASK]; 82 | } 83 | 84 | /** 85 | * Returns the cosine in radians from a lookup table. 86 | * @param radians 87 | * @return 88 | */ 89 | static public float cos(float radians) { 90 | return Sin.table[(int) ((radians + PI / 2) * RAD_TO_INDEX) & SIN_MASK]; 91 | } 92 | 93 | /** 94 | * Returns the sine in radians from a lookup table. 95 | * @param degrees 96 | * @return 97 | */ 98 | static public float sinDeg(float degrees) { 99 | return Sin.table[(int) (degrees * DEG_TO_INDEX) & SIN_MASK]; 100 | } 101 | 102 | /** 103 | * Returns the cosine in radians from a lookup table. 104 | * @param degrees 105 | * @return 106 | */ 107 | static public float cosDeg(float degrees) { 108 | return Sin.table[(int) ((degrees + 90) * DEG_TO_INDEX) & SIN_MASK]; 109 | } 110 | } 111 | 112 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | **v2.6.1** Recommend JRuby-9.3.2.0 use, make rake runtime dependency. Update to jdk17, deprecate Vec2D cross product in favor of wedge product, update SimplexNoise. 2 | 3 | **v2.6.0** Recommend JRuby-9.3.1.0 use, move non-java files to resources (simplifies path). Use `field` not `declared_field` to access java_class fields. 4 | 5 | **v2.5.1** Recommend JRuby-9.2.19.0 use. 6 | 7 | **v2.5.0** Refactor noise to delegate pattern and make OpenSimplex2 noise default noise, implement pdf and svg export libraries. 8 | Recommend JRuby-9.2.16.0 use 9 | 10 | **v2.4.2** Update to use jruby-complete-9.2.14.0, regularise video/sound downloadswhen no processing ide. 11 | 12 | **v2.4.1** Update to use jruby-complete-9.2.13.0 13 | 14 | **v2.4.1** Update to use jruby-complete-9.2.12.0 15 | 16 | **v2.4.0** Update to use jruby-complete-9.2.11.1 recommended java version AdoptOpenJDK-13+ or Openj9-14+ 17 | 18 | **v2.3.0** Update to use jruby-complete-9.2.11.0 recommended java version AdoptOpenJDK-13+ 19 | 20 | **v2.2.2** Fix for Native library bug on Windows by Jay Scott. Added minim examples. Bump processing-version in build. 21 | 22 | **v2.2.1** Added --force option for use with --install option to remove old configuration. Added support for installing video and sound libraries, without vanilla processing. Added dxf export library, re-branded app with a red wavy triangle icon. 23 | 24 | **v2.2.0** A standalone ruby version of processing which runs with jdk12 and essentially uses a development version of processing core (by Sam Pottinger). Use version 1.7.0 if you are using jdk8. 25 | 26 | **v2.1.0** JRubyArt is no longer dependent on an installed version of vanilla processing, but needs at least jdk11 to run. Anyone wanting to use jdk8 should install JRubyArt-1.7.0 and probably use bundler to freeze version. 27 | **v2.0.0** Update to jdk11, removing many bashisms on the way. We compile our own processing code, and include with jogl gems in gem. Requires a new `config.yml` file to use libraries. Revert to processing-3.3.7 versions of PShapeOpenGL and PGraphicsOpenGL to fix diwi examples and possibly others. 28 | 29 | **v1.7.0** Update to jruby-complete-9.2.8.0. NB: breaking change AppRender(applet) changed to GfxRender(graphics) please update samples. 30 | 31 | **v1.6.4** Fix glitch on loading jruby-complete, warn if not using JDK8 improved ColorGroup 32 | 33 | **v1.6.3** Update to jruby-complete-9.2.6.0 and processing-3.5.3 34 | 35 | **v1.6.2** Update to jruby-complete-9.2.4.0. 36 | 37 | **v1.6.1** Update to jruby-complete-9.2.2.0. 38 | 39 | **v1.6.0** Update to expect processing-3.4 and to jruby-complete-9.2.1.0. Add color_group library, remove web_array helper method 40 | 41 | **v1.5.2** JRuby downloads have moved 42 | 43 | **v1.5.1** Revert changes to windows OS detection 44 | 45 | **v1.5.0** Update to jruby-complete-9.2.0.0, make native loader work with raspberrypi. 46 | 47 | **v1.4.9** Update to jruby-complete-9.1.17.0. 48 | 49 | **v1.4.8** Re-factor `control_panel` to avoid calling protected method on slider, also reduces boilerplate code requires in `control_panel` sketches. 50 | 51 | **v1.4.7** Bump up to processing-3.3.7, make watch fail early if too many ruby files to watch 52 | 53 | **v1.4.6** Bump up to JRubyComplete-9.1.16.0 54 | 55 | **v1.4.5** Vec2D and Vec3D now support `copy` constructor where the original can be a duck-type. Further the only requirement is that the duck-type responds to `:x`, and `:y` by returning a `float` or `fixnum` thus Vec2D can be promoted to Vec3D (where `z = 0`), or more usually some other Vector or Point class can be used as the original. A `vector_utils` library has been implemented, see examples for usage. 56 | 57 | **v1.4.4** Bump up to JRubyComplete-9.1.15.0 58 | 59 | **v1.4.3** Features example sketches using the PixelFlow library by Thomas Diewald 60 | 61 | **v1.4.2** Fix for windows `library_loader` thanks to Thomas Diewald 62 | 63 | **v1.0.3** Initial version 64 | -------------------------------------------------------------------------------- /lib/jruby_art/creators/sketch_writer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: false 2 | 3 | # The SketchParameters class knows how to format, size, title & class name 4 | class SketchParameters 5 | attr_reader :name, :args 6 | def initialize(name:, args:) 7 | @name = name 8 | @args = args 9 | end 10 | 11 | def class_name 12 | name.split('_').collect(&:capitalize).join 13 | end 14 | 15 | def sketch_title 16 | human = name.split('_').collect(&:capitalize).join(' ') 17 | format("sketch_title '%s'", title: human) 18 | end 19 | 20 | def sketch_size 21 | mode = args.length == 3 ? format(', %<mode>s', mode: args[2].upcase) : '' 22 | return 'size 200, 200' if args.empty? 23 | 24 | format( 25 | 'size %<width>d, %<height>d%<mode>s', 26 | width: args[0].to_i, 27 | height: args[1].to_i, 28 | mode: mode 29 | ) 30 | end 31 | end 32 | 33 | # The file writer can write a sketch when given instance of Sketch type 34 | class SketchWriter 35 | attr_reader :file, :param 36 | 37 | def initialize(path, args) 38 | @param = SketchParameters.new(name: path, args: args) 39 | @file = format( 40 | '%<dir>s/%<file>s.rb', dir: File.dirname(path), file: path 41 | ) 42 | end 43 | 44 | def write 45 | sketch = SketchFactory.create(param) 46 | File.open(file, 'w+') { |f| f.write sketch.join("\n") } 47 | end 48 | end 49 | 50 | # Implements methods and class_methods omits blank line after draw 51 | # uses private method_lines to format method lines 52 | class Sketch 53 | attr_reader :param 54 | 55 | def initialize(param) 56 | @param = param 57 | end 58 | 59 | BLANK ||= ''.freeze 60 | INDENT ||= ' '.freeze 61 | 62 | def methods(indent) 63 | lines = [] 64 | lines.concat method_lines('settings', param.sketch_size, indent) 65 | lines.concat method_lines('setup', param.sketch_title, indent) 66 | lines.concat method_lines('draw', BLANK, indent) 67 | end 68 | 69 | def class_methods 70 | lines = [format('class %<name>s < Processing::App', name: param.class_name)] 71 | lines.concat methods(INDENT) 72 | lines << 'end' 73 | end 74 | 75 | private 76 | 77 | def content(content, indent) 78 | return BLANK if content.empty? 79 | 80 | format(' %<indent>s%<content>s', indent: indent, content: content) 81 | end 82 | 83 | def method_lines(name, content, indent) 84 | one = format('%<indent>sdef %<name>s', indent: indent, name: name) 85 | two = content(content, indent) 86 | three = format('%<indent>send', indent: indent) 87 | return [one, two, three] if /draw/.match?(name) 88 | 89 | [one, two, three, BLANK] 90 | end 91 | end 92 | 93 | # Switch templates on config 94 | class SketchFactory 95 | def self.create(param) 96 | case Processing::RP_CONFIG.fetch('template', 'bare') 97 | when /bare/ 98 | BareSketch 99 | when /class/ 100 | ClassSketch 101 | when /emacs/ 102 | EmacsSketch 103 | end.new(param).code 104 | end 105 | end 106 | 107 | # The sketch class creates an array of formatted sketch lines 108 | class BareSketch < Sketch 109 | def code 110 | methods(BLANK) 111 | end 112 | end 113 | 114 | # A simple class wrapped sketch 115 | class ClassSketch < Sketch 116 | def code 117 | lines = ['# frozen_string_literal: true', BLANK] 118 | lines.concat class_methods 119 | end 120 | end 121 | 122 | # A sketch that will run with jruby, for emacs etc 123 | class EmacsSketch < Sketch 124 | def code 125 | lines = [ 126 | '# frozen_string_literal: true', 127 | BLANK, 128 | "require 'jruby_art'", 129 | "require 'jruby_art/app'", 130 | BLANK, 131 | 'Processing::App::SKETCH_PATH = __FILE__.freeze', 132 | BLANK 133 | ] 134 | lines.concat class_methods 135 | lines << BLANK 136 | lines << format( 137 | '%<name>s.new if Processing.app.nil?', name: param.class_name 138 | ) 139 | end 140 | end 141 | -------------------------------------------------------------------------------- /test/math_tool_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | 5 | Java::Monkstone::JRLibrary.new.load(JRuby.runtime, false) 6 | 7 | # Processing Map test 8 | class MapTest < Minitest::Test 9 | include MathTool 10 | # map input from input_range to output range (unclamped) 11 | def test_map1d 12 | x = [0, 5, 7.5, 10] 13 | range1 = (0..10) 14 | range2 = (100..1) 15 | range3 = (0..10) 16 | range4 = (5..105) 17 | assert_in_delta(map1d(x[0], range1, range2), 100, 0.00001, 'map to first') 18 | assert_in_delta(map1d(x[1], range1, range2), 50.5, 0.00001, 'map to reversed intermediate') 19 | assert_in_delta(map1d(x[2], range3, range4), 80.0, 0.00001, 'map to intermediate') 20 | assert_in_delta(map1d(x[3], range1, range2), 1, 0.00001, 'map to last') 21 | end 22 | 23 | # as map1d except not using range input 24 | def test_p5map 25 | x = [0, 5, 7.5, 10] 26 | range1 = (0..10) 27 | range2 = (100..1) 28 | range3 = (0..10) 29 | range4 = (5..105) 30 | assert_in_delta(p5map(x[0], range1.first, range1.last, range2.first, range2.last), 100, 0.00001) 31 | assert_in_delta(p5map(x[1], range1.first, range1.last, range2.first, range2.last), 50.5, 0.00001) 32 | assert_in_delta(p5map(x[2], range3.first, range3.last, range4.first, range4.last), 80.0, 0.00001) 33 | assert_in_delta(p5map(x[3], range1.first, range1.last, range2.first, range2.last), 1, 0.00001) 34 | end 35 | 36 | def test_norm 37 | x = [10, 140, 210] 38 | start0 = 30 39 | last0 = 200 40 | start_int = 0 41 | last_int = 200 42 | assert_in_delta(norm(x[0], start0, last0), -0.11764705882352941, 0.00001, 'unclamped map') 43 | assert_in_delta(norm(x[1], start_int, last_int), 0.7, 0.00001, 'map to intermediate') 44 | assert_in_delta(norm(x[2], start_int, last_int), 1.05, 0.00001, 'unclamped map') 45 | end 46 | 47 | def test_norm_strict 48 | x = [10, 140, 210] 49 | assert_in_delta(norm_strict(x[2], x[0], x[1]), 1.0, 0.00001, 'clamped map to 0..1.0') 50 | assert_in_delta(norm_strict(x[2], x[1], x[0]), 0.0, 0.00001, 'clamped map to 0..1.0') 51 | assert_in_delta(norm_strict(x[1], x[0], x[2]), 0.65, 0.00001, 'clamped map to 0..1.0') 52 | end 53 | 54 | # behaviour is deliberately different to processing which is unclamped 55 | def test_lerp 56 | x = [0.5, 0.8, 2.0] 57 | start0 = 300 58 | last0 = 200 59 | start_int = 0 60 | last_int = 200 61 | assert_in_delta(lerp(start0, last0, x[0]), 250, 0.00001, 'produces a intermediate value of a reversed range') 62 | assert_in_delta(lerp(start_int, last_int, x[1]), 160, 0.00001, 'lerps to an intermediate value') 63 | assert_in_delta(lerp(start_int, last_int, x[2]), 200, 0.00001, 'lerps to the last value of a range') 64 | end 65 | 66 | def test_constrain 67 | x_int = [15, 2_500, -2_500] 68 | start_int = 0 69 | last_int = 200 70 | assert_in_delta(constrain(x_int[0], start_int, last_int), 15, 0.00001) 71 | assert_in_delta(constrain(x_int[1], start_int, last_int), 200, 0.00001) 72 | assert_in_delta(constrain(x_int[2], start_int, last_int), 0, 0.00001) 73 | xf = [15.0, 2_500.0, -2_500.0] 74 | startf = 0 75 | lastf = 200.0 76 | assert_in_delta(constrain(xf[0], startf, lastf), 15.0, 0.00001, 'constrain to 0..200') 77 | assert_in_delta(constrain(xf[1], startf, lastf), 200.0, 0.00001, 'constrain to 0..200') 78 | assert_in_delta(constrain(xf[2], startf, lastf), 0.0, 0.00001, 'constrain to 0..200') 79 | end 80 | 81 | def test_grid_one 82 | array = [] 83 | grid(100, 100) { |x, y| array << [x, y] } 84 | assert array[0].include?(0) 85 | assert array[98].include?(0) 86 | assert_equal array.length, 10_000 87 | assert array[50].include?(50) 88 | end 89 | 90 | def test_grid_ten 91 | array = [] 92 | grid(100, 100, 10, 10) { |x, y| array << [x, y] } 93 | assert array[0].include?(0) 94 | assert array[9].include?(90) 95 | assert_equal array.length, 100 96 | assert array[5].include?(50) 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /src/main/java/monkstone/core/LibraryProxy.java: -------------------------------------------------------------------------------- 1 | package monkstone.core; 2 | 3 | import processing.core.PApplet; 4 | import static processing.core.PConstants.*; 5 | import processing.event.MouseEvent; 6 | import processing.event.KeyEvent; 7 | 8 | /** 9 | * The purpose of this class is to enable access to processing pre, draw and 10 | * post loops in ruby-processing as a regular java library class. Also included 11 | * background, fill and stroke methods. PConstants should also be available from 12 | * static import 13 | * 14 | * @author Martin Prout 15 | */ 16 | public abstract class LibraryProxy { 17 | 18 | private final PApplet app; 19 | 20 | /** 21 | * Useful accessors 22 | */ 23 | public int width, height; 24 | 25 | /** 26 | * 27 | * @param app PApplet 28 | */ 29 | public LibraryProxy(PApplet app) { 30 | this.app = app; 31 | this.width = app.width; 32 | this.height = app.height; 33 | setActive(true); 34 | } 35 | 36 | /** 37 | * Extending classes can override this, gives access to, by reflection, 38 | * processing PApplet pre loop (called before draw) 39 | */ 40 | public void pre() { 41 | } 42 | 43 | /** 44 | * Extending classes must implement this gives access to processing PApplet 45 | * draw loop 46 | */ 47 | public abstract void draw(); 48 | 49 | /** 50 | * Extending classes can override this, gives access to, by reflection, 51 | * processing PApplet post loop (called after draw) 52 | */ 53 | public void post() { 54 | } 55 | 56 | /** 57 | * Extending classes can override this, gives access to, by reflection, 58 | * processing PApplet post loop (called after draw) 59 | * @param e 60 | */ 61 | public void keyEvent(KeyEvent e) { 62 | } 63 | 64 | /** 65 | * Extending classes can override this, gives access to, by reflection, 66 | * processing PApplet post loop (called after draw) 67 | * @param e 68 | */ 69 | public void mouseEvent(MouseEvent e) { 70 | } 71 | 72 | /** 73 | * Register or unregister reflection methods 74 | * 75 | * @param active 76 | */ 77 | final void setActive(boolean active) { 78 | if (active) { 79 | this.app.registerMethod("pre", this); 80 | this.app.registerMethod("draw", this); 81 | this.app.registerMethod("post", this); 82 | this.app.registerMethod("mouseEvent", this); 83 | this.app.registerMethod("keyEvent", this); 84 | this.app.registerMethod("dispose", this); 85 | } else { 86 | this.app.unregisterMethod("pre", this); 87 | this.app.unregisterMethod("draw", this); 88 | this.app.unregisterMethod("post", this); 89 | this.app.unregisterMethod("mouseEvent", this); 90 | this.app.unregisterMethod("keyEvent", this); 91 | } 92 | } 93 | 94 | /** 95 | * Simple signature for background hides need to call app 96 | * 97 | * @param col int 98 | */ 99 | public void background(int col) { 100 | this.app.background(col); 101 | } 102 | 103 | /** 104 | * Simple signature for fill hides need to call app 105 | * 106 | * @param col int 107 | */ 108 | public void fill(int col) { 109 | this.app.fill(col); 110 | } 111 | 112 | /** 113 | * Simple signature for stroke hides need to call app 114 | * 115 | * @param col int 116 | */ 117 | public void stroke(int col) { 118 | this.app.stroke(col); 119 | } 120 | 121 | /** 122 | * Access applet if we must 123 | * 124 | * @return applet PApplet 125 | */ 126 | public PApplet app() { 127 | return this.app; 128 | } 129 | 130 | /** 131 | * required for processing 132 | */ 133 | public void dispose() { 134 | setActive(false); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/processing/core/ThinkDifferent.java: -------------------------------------------------------------------------------- 1 | /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 | 3 | /* 4 | Part of the Processing project - http://processing.org 5 | 6 | Copyright (c) 2012-2014 The Processing Foundation 7 | Copyright (c) 2007-2012 Ben Fry and Casey Reas 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | version 2, as published by the Free Software Foundation. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software Foundation, 20 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | */ 22 | 23 | package processing.core; 24 | 25 | import java.awt.Desktop; 26 | import java.awt.Image; 27 | import java.awt.Taskbar; 28 | 29 | 30 | /** 31 | * Deal with issues related to macOS application behavior. 32 | * 33 | * We have to register a quit handler to safely shut down the sketch, 34 | * otherwise OS X will just kill the sketch when a user hits Cmd-Q. 35 | * In addition, we have a method to set the dock icon image so we look more 36 | * like a native application. 37 | * 38 | * This is a stripped-down version of what's in processing.app.platform to fix 39 | * <a href="https://github.com/processing/processing/issues/3301">3301</a>. 40 | */ 41 | public class ThinkDifferent { 42 | static private Desktop desktop; 43 | static private Taskbar taskbar; 44 | 45 | // True if user has tried to quit once. Prevents us from canceling the quit 46 | // call if the sketch is held up for some reason, like an exception that's 47 | // managed to put the sketch in a bad state. 48 | static boolean attemptedQuit; 49 | 50 | 51 | /** 52 | * Initialize the sketch with the quit handler. 53 | * 54 | * Initialize the sketch with the quit handler such that, if there is no known 55 | * crash, the application will not exit on its own if this is the first quit 56 | * attempt. 57 | * 58 | * @param sketch The sketch whose quit handler callback should be set. 59 | */ 60 | static public void init(final PApplet sketch) { 61 | getDesktop().setQuitHandler((event, quitResponse) -> { 62 | sketch.exit(); 63 | 64 | boolean noKnownCrash = PApplet.uncaughtThrowable == null; 65 | 66 | if (noKnownCrash && !attemptedQuit) { // haven't tried yet 67 | quitResponse.cancelQuit(); // tell OS X we'll handle this 68 | attemptedQuit = true; 69 | } else { 70 | quitResponse.performQuit(); // just force it this time 71 | } 72 | }); 73 | } 74 | 75 | 76 | /** 77 | * Remove the quit handler. 78 | */ 79 | static public void cleanup() { 80 | getDesktop().setQuitHandler(null); 81 | } 82 | 83 | 84 | /** 85 | * Called via reflection from PSurfaceAWT and others, set the dock icon image. 86 | * @param image The image to provide for Processing icon. 87 | */ 88 | static public void setIconImage(Image image) { 89 | getTaskbar().setIconImage(image); 90 | } 91 | 92 | 93 | /** 94 | * Get the taskbar where OS visual settings can be provided. 95 | * @return Cached taskbar singleton instance. 96 | */ 97 | static private Taskbar getTaskbar() { 98 | if (taskbar == null) { 99 | taskbar = Taskbar.getTaskbar(); 100 | } 101 | return taskbar; 102 | } 103 | 104 | 105 | /** 106 | * Get the desktop where OS behavior can be provided. 107 | * @return Cached desktop singleton instance. 108 | */ 109 | static private Desktop getDesktop() { 110 | if (desktop == null) { 111 | desktop = Desktop.getDesktop(); 112 | } 113 | return desktop; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JRubyArt 2 | 3 | [![Gem Version](https://badge.fury.io/rb/jruby_art.svg)](https://badge.fury.io/rb/jruby_art) ![Travis CI](https://travis-ci.org/ruby-processing/JRubyArt.svg) 4 | 5 | A new version for jdk17+ and JRuby-9.3.2.0 use, does not require an installed `vanilla processing`, however if installed you can use processing-ide to download libraries. Configuration file is incompatible with that of previous version of JRubyArt (and you should move or rename old `config.yml` to keep it). This version will run with a default configuration file but you won't be able to use processing libraries, until you match configuration to your setup. Illegal reflective access warning should be fixed for this release (by using JOGL-2.4.0-rc jars), though you may need to define `JAVA_HOME` for JRuby warnings to be suppressed. 6 | 7 | ## Requirements 8 | 9 | A clean start for `jruby_art` with custom processing core included, built for [jruby-9.3.2.0](http://jruby.org/download) see [wiki](https://github.com/ruby-processing/JRubyArt/wiki/Building-latest-gem) for building gem from this repo. 10 | 11 | ## Requirements 12 | 13 | A suitable version of ruby (MRI `ruby 2.6+` or `jruby-9.3.2.0`) to download gem. NB: avoid ruby 2.7, it is guaranteed to give you problems (you've been warned) 14 | Tested and working OpenJDK 17, if you have any issues with opengl sketches with distro installed JDK use a JDK from AdoptOpenJDK. 15 | 16 | 17 | ## Configuration 18 | 19 | You can if you wish leave configuration to the `new` autoconfig tool (delete or rename existing config to do this). The config file is `config.yml` in the `~/.jruby_art folder`, the autoconfig gets run on `k9 --install` expected to just work. 20 | 21 | **config.yml on linux** 22 | 23 | ```yaml 24 | --- 25 | processing_ide: true 26 | library_path: "/home/tux/sketchbook" 27 | MAX_WATCH: 32 28 | JRUBY: true 29 | template: bare 30 | java_args: 31 | # Global java_args can be used to suppress reflective access warn 32 | ``` 33 | 34 | ## Install Steps (assumes you have requirements above) 35 | 36 | ```bash 37 | gem install jruby_art 38 | k9 --install # installs jruby-complete-9.2.13.0 and downloads and installs samples to ~/k9_samples 39 | cd ~/k9_samples/contributed 40 | k9 --run jwishy.rb # if you have jruby-9.2.13.0 installed or config `JRUBY: false` 41 | # to use jruby-complete set `JRUBY: false` in config 42 | ``` 43 | 44 | ## Create sketches from built in templates 45 | 46 | ```bash 47 | k9 --create fred 200 200 # basic sketch fred.rb 48 | k9 --create fred 200 200 p2d # basic P2D sketch fred.rb 49 | ``` 50 | 51 | To create either a `class` wrapped sketch or `emacs` sketch set `template: class` or `template: emacs` in config.yml 52 | 53 | ## Simple Sketch 54 | 55 | ```ruby 56 | 57 | def setup 58 | sketch_title 'My Sketch' 59 | end 60 | 61 | def draw 62 | background 0 63 | fill 200 64 | ellipse width / 2, height / 2, 300, 200 65 | end 66 | 67 | def settings 68 | size 400, 300 69 | end 70 | ``` 71 | 72 | ## Run Sketch 73 | 74 | See above be prepared to `KILL` the odd java process (ie when sketch does not exit cleanly) 75 | 76 | ## Watch sketches 77 | 78 | ```bash 79 | k9 --watch sketch.rb # NB: doesn't work with FX2D render mode 80 | ``` 81 | 82 | ## Open pry console on sketch 83 | 84 | ```bash 85 | k9 --live sketch.rb # pry is bound to Processing.app # needs `jruby -S gem install pry` 86 | ``` 87 | 88 | ## Example sketches 89 | 90 | [Worked Examples](https://github.com/ruby-processing/JRubyArt-examples) and, [The-Nature-of-Code-Examples-for-JRubyArt](https://github.com/ruby-processing/The-Nature-of-Code-for-JRubyArt) feel free to add your own, especially ruby-2.6+ syntax now we can. These can now be downloaded using `k9 --install` please move existing `k9_samples` if you wish to keep them. 91 | 92 | [adopt]: https://adoptopenjdk.net/ 93 | [pi]: http://ruby-processing.github.io/JRubyArt/raspberrypi_started/ 94 | [rubuto-processing3]: https://github.com/hoshi-sano/ruboto-processing3 95 | [testing]: http://ruby-processing.github.io/testing/testing/ 96 | [warnings]: https://monkstone.github.io/jruby_art/update/2019/09/10/Reflective_Access.html 97 | -------------------------------------------------------------------------------- /src/main/java/monkstone/ColorUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This utility allows JRubyArt users to use the processing.org color method 3 | * in their sketches. Includes a method to efficiently convert an array of web 4 | * strings to an array of color int, and another to convert an array of color 5 | * int to a string that can be used in ruby code (to generate web color array). 6 | * Copyright (c) 2015-20 Martin Prout. 7 | * This utility is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation; either version 2.1 of the License, or (at 10 | * your option) any later version. 11 | * 12 | * Obtain a copy of the license at http://www.gnu.org/licenses/lgpl-2.1.html 13 | */ 14 | package monkstone; 15 | 16 | import java.util.Random; 17 | 18 | /** 19 | * 20 | * @author Martin Prout 21 | */ 22 | public class ColorUtil { 23 | 24 | /** 25 | * Returns hex long as a positive int unless greater than Integer.MAX_VALUE 26 | * else return the complement as a negative integer or something like that 27 | * 28 | * @param hexlong long 29 | * @return rgb int 30 | */ 31 | static final int hexLong(long hexlong) { 32 | long SPLIT = Integer.MAX_VALUE + 1; 33 | return hexlong < SPLIT ? (int) hexlong : (int) (hexlong - SPLIT * 2L); 34 | } 35 | 36 | /** 37 | * @param hexstring String 38 | * @return rgb int 39 | */ 40 | static public int colorString(String hexstring) { 41 | return java.awt.Color.decode(hexstring).getRGB(); 42 | } 43 | 44 | /** 45 | * 46 | * @param web Array of web (hex) String 47 | * @return array of color int according to java 48 | */ 49 | static public int[] webArray(String[] web) { 50 | int[] result = new int[web.length]; 51 | for (int i = 0; i < web.length; i++) { 52 | result[i] = java.awt.Color.decode(web[i]).getRGB(); 53 | } 54 | return result; 55 | } 56 | 57 | /** 58 | * Return a ruby string of the form "%w(a b c)" where a, b, c are raw web 59 | * strings. This string can be used in ruby code. 60 | * 61 | * @param hex int array 62 | * @return String for use in ruby 63 | */ 64 | static public String rubyString(int[] hex) { 65 | StringBuilder result = new StringBuilder("%w["); 66 | for (int i = 0; i < hex.length; i++) { 67 | result.append(String.format("#%06X", 0xFFFFFF & hex[i])); 68 | if (i < hex.length - 1) { 69 | result.append(' '); 70 | } 71 | } 72 | result.append("]\n"); 73 | return result.toString(); 74 | } 75 | 76 | /** 77 | * 78 | * @param hex double 79 | * @return hex float 80 | */ 81 | static public float colorLong(double hex) { 82 | return (float) hex; 83 | } 84 | 85 | /** 86 | * 87 | * @param hexlong long 88 | * @return hexlong int 89 | */ 90 | static public int colorLong(long hexlong) { 91 | return hexLong(hexlong); 92 | } 93 | 94 | /** 95 | * 96 | * @param hex double 97 | * @return hex float 98 | */ 99 | static public float colorDouble(double hex) { 100 | return (float) hex; 101 | } 102 | 103 | static public int[] shuffle(int[] cols) { 104 | Random rgen = new Random(); // Random number generator 105 | for (int i = 0; i < cols.length; i++) { 106 | int randomPosition = rgen.nextInt(cols.length); 107 | int temp = cols[i]; 108 | cols[i] = cols[randomPosition]; 109 | cols[randomPosition] = temp; 110 | } 111 | return cols; 112 | } 113 | 114 | /** 115 | * 116 | * @param hue 117 | * @param sat 118 | * @param brightness 119 | * @return 120 | */ 121 | static public int hsbToRgB(double hue, double sat, double brightness) { 122 | return java.awt.Color.HSBtoRGB((float) hue, (float) sat, (float) brightness); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/monkstone/slider/SimpleSlider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package monkstone.slider; 7 | 8 | import processing.core.PApplet; 9 | 10 | /** 11 | * 12 | * @author tux 13 | */ 14 | public abstract class SimpleSlider implements Slider {//implements Slider { 15 | 16 | int MIN_BAR_WIDTH = 10; 17 | int MAX_BAR_WIDTH = 30; 18 | int sliderBack = 0xff909090; 19 | int sliderFill = 0xff696969; 20 | int borderColor = 0; 21 | int numbersColor = 0; 22 | int labelColor = 0; 23 | int externalBorder = 0; 24 | boolean backgroundVisible = true; 25 | int labelSize = 18; 26 | int numberSize = 14; 27 | boolean displayLabel = false; 28 | boolean displayValue = true; 29 | int pX; 30 | int pY; 31 | int pW; 32 | int pH; 33 | float pScaled = 0; 34 | float pValue = 0; 35 | String ID; 36 | boolean pressOnlyOnce = true; 37 | int deb = 0; 38 | short wheelCount = 0; 39 | float vMin = 0; 40 | float vMax = 15; 41 | PApplet applet; 42 | 43 | abstract void displayText(); 44 | 45 | abstract void drawGui(); 46 | 47 | @Override 48 | public void draw() { 49 | applet.pushStyle(); 50 | applet.noStroke(); 51 | drawGui(); 52 | displayText(); 53 | applet.popStyle(); 54 | change(); 55 | } 56 | 57 | /** 58 | * 59 | */ 60 | @Override 61 | public void showLabel() { 62 | displayLabel = true; 63 | } 64 | 65 | /** 66 | * 67 | */ 68 | @Override 69 | public void hideLabel() { 70 | displayLabel = false; 71 | } 72 | 73 | /** 74 | * 75 | */ 76 | @Override 77 | public void showNumbers() { 78 | displayValue = true; 79 | } 80 | 81 | /** 82 | * 83 | */ 84 | @Override 85 | public void hideNumbers() { 86 | displayValue = false; 87 | } 88 | 89 | void change() { 90 | checkKeyboard(); 91 | } 92 | 93 | /** 94 | * 95 | */ 96 | @Override 97 | public void hideBackground() { 98 | backgroundVisible = false; 99 | } 100 | 101 | /** 102 | * 103 | * @return 104 | */ 105 | @Override 106 | public float readValue() { 107 | return pValue; 108 | } 109 | 110 | abstract boolean mouseOver(); 111 | 112 | protected float map(float val, float begIn, float endIn, float beginOut, float endOut) { 113 | return beginOut + (endOut - beginOut) * ((val - begIn) / (endIn - begIn)); 114 | } 115 | 116 | final void limits(float iv, float fv) { 117 | vMin = iv; 118 | vMax = fv; 119 | setValue(iv); 120 | } 121 | 122 | /** 123 | * 124 | * @param s 125 | */ 126 | @Override 127 | public void labelSize(int s) { 128 | labelSize = s < 4 ? 4 : s; 129 | } 130 | 131 | void deBounce(int n) { 132 | if (!pressOnlyOnce && deb++ > n) { 133 | deb = 0; 134 | pressOnlyOnce = true; 135 | } 136 | } 137 | 138 | abstract void checkKeyboard(); 139 | 140 | protected int constrainMap(double val, double begIn, double endIn, double beginOut, double endOut) { 141 | double max = Math.max(begIn, endIn); 142 | double min = Math.min(begIn, endIn); 143 | if (val < min) { 144 | val = min; 145 | } 146 | if (val > max) { 147 | val = max; 148 | } 149 | return (int) ((beginOut + (endOut - beginOut) * ((val - begIn) / (endIn - begIn)))); 150 | } 151 | 152 | private void setActive(boolean active) { 153 | if (active) { 154 | applet.registerMethod("dispose", this); 155 | applet.registerMethod("draw", this); 156 | } else { 157 | applet.unregisterMethod("draw", this); 158 | } 159 | } 160 | 161 | @Override 162 | public void dispose() { 163 | setActive(false); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/processing/opengl/shaders/LineVert.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Processing project - http://processing.org 3 | 4 | Copyright (c) 2012-15 The Processing Foundation 5 | Copyright (c) 2004-12 Ben Fry and Casey Reas 6 | Copyright (c) 2001-04 Massachusetts Institute of Technology 7 | 8 | This library is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation, version 2.1. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General 18 | Public License along with this library; if not, write to the 19 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20 | Boston, MA 02111-1307 USA 21 | */ 22 | 23 | #define PROCESSING_LINE_SHADER 24 | 25 | uniform mat4 modelviewMatrix; 26 | uniform mat4 projectionMatrix; 27 | 28 | uniform vec4 viewport; 29 | uniform int perspective; 30 | uniform vec3 scale; 31 | 32 | attribute vec4 position; 33 | attribute vec4 color; 34 | attribute vec4 direction; 35 | 36 | varying vec4 vertColor; 37 | 38 | void main() { 39 | vec4 posp = modelviewMatrix * position; 40 | vec4 posq = modelviewMatrix * (position + vec4(direction.xyz, 0)); 41 | 42 | // Moving vertices slightly toward the camera 43 | // to avoid depth-fighting with the fill triangles. 44 | // Discussed here: 45 | // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848 46 | posp.xyz = posp.xyz * scale; 47 | posq.xyz = posq.xyz * scale; 48 | 49 | vec4 p = projectionMatrix * posp; 50 | vec4 q = projectionMatrix * posq; 51 | 52 | // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height]) 53 | // screen_p = (p.xy/p.w + <1,1>) * 0.5 * viewport.zw 54 | 55 | // prevent division by W by transforming the tangent formula (div by 0 causes 56 | // the line to disappear, see https://github.com/processing/processing/issues/5183) 57 | // t = screen_q - screen_p 58 | // 59 | // tangent is normalized and we don't care which direction it points to (+-) 60 | // t = +- normalize( screen_q - screen_p ) 61 | // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*viewport.zw - (p.xy/p.w+<1,1>)*0.5*viewport.zw ) 62 | // 63 | // extract common factor, <1,1> - <1,1> cancels out 64 | // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * viewport.zw ) 65 | // 66 | // convert to common divisor 67 | // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * viewport.zw ) 68 | // 69 | // remove the common scalar divisor/factor, not needed due to normalize and +- 70 | // (keep viewport - can't remove because it has different components for x and y 71 | // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181) 72 | // t = +- normalize( (q.xy*p.w - p.xy*q.w) * viewport.zw ) 73 | 74 | vec2 tangent = (q.xy*p.w - p.xy*q.w) * viewport.zw; 75 | 76 | // don't normalize zero vector (line join triangles and lines perpendicular to the eye plane) 77 | tangent = length(tangent) == 0.0 ? vec2(0.0, 0.0) : normalize(tangent); 78 | 79 | // flip tangent to normal (it's already normalized) 80 | vec2 normal = vec2(-tangent.y, tangent.x); 81 | 82 | float thickness = direction.w; 83 | vec2 offset = normal * thickness; 84 | 85 | // Perspective --- 86 | // convert from world to clip by multiplying with projection scaling factor 87 | // to get the right thickness (see https://github.com/processing/processing/issues/5182) 88 | // invert Y, projections in Processing invert Y 89 | vec2 perspScale = (projectionMatrix * vec4(1, -1, 0, 0)).xy; 90 | 91 | // No Perspective --- 92 | // multiply by W (to cancel out division by W later in the pipeline) and 93 | // convert from screen to clip (derived from clip to screen above) 94 | vec2 noPerspScale = p.w / (0.5 * viewport.zw); 95 | 96 | gl_Position.xy = p.xy + offset.xy * mix(noPerspScale, perspScale, float(perspective > 0)); 97 | gl_Position.zw = p.zw; 98 | 99 | vertColor = color; 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/monkstone/slider/SimpleHorizontalSlider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.slider; 21 | 22 | import processing.core.PApplet; 23 | import processing.core.PConstants; 24 | 25 | public class SimpleHorizontalSlider extends SimpleSlider { 26 | 27 | final int SPACING = 20; 28 | final int LEFT_SPC = SPACING * 2; 29 | final int RIGHT_SPC = SPACING * 4; 30 | 31 | /** 32 | * 33 | * @param outer 34 | * @param beginRange start range 35 | * @param endRange end range 36 | * @param initial 37 | * @param count 38 | */ 39 | public SimpleHorizontalSlider(final PApplet outer, float beginRange, float endRange, float initial, int count) { 40 | this.applet = outer; 41 | setActive(true); 42 | pX = LEFT_SPC; 43 | pY = outer.height - SPACING - (count * SPACING); 44 | pW = outer.width - RIGHT_SPC; 45 | pH = 10; 46 | ID = Integer.toString(count + 1); 47 | limits(beginRange, endRange); 48 | setValue(initial); 49 | } 50 | 51 | @Override 52 | boolean mouseOver() { 53 | return applet.mouseX >= pX && applet.mouseX <= pX + pW && applet.mouseY >= pY && applet.mouseY <= pY + pH; 54 | } 55 | 56 | private void setActive(boolean active) { 57 | if (active) { 58 | applet.registerMethod("dispose", this); 59 | applet.registerMethod("draw", this); 60 | } else { 61 | applet.unregisterMethod("draw", this); 62 | } 63 | } 64 | 65 | @Override 66 | void displayText() { 67 | String lFormat = "%d"; 68 | if (displayLabel) { 69 | applet.fill(labelColor); 70 | applet.textSize(labelSize); 71 | applet.textAlign(PConstants.BOTTOM); 72 | applet.text(Integer.toString((int) pValue), pX + pW / 2, pY + pH); 73 | } 74 | if (displayValue) { 75 | applet.textSize(numberSize); 76 | applet.fill(numbersColor); 77 | applet.textAlign(PConstants.LEFT); 78 | applet.text(String.format(lFormat, (int) vMin), pX, pY); 79 | applet.textAlign(PConstants.RIGHT); 80 | applet.text(String.format(lFormat, (int) vMax), pX + pW, pY); 81 | } 82 | } 83 | 84 | @Override 85 | void drawGui() { 86 | if (backgroundVisible) { 87 | applet.stroke(sliderBack); 88 | applet.line(pX, pY + pH / 2, pX + pW, pY + pH / 2); 89 | } 90 | applet.noStroke(); 91 | applet.fill(255); 92 | applet.ellipse(pX + pScaled, pY + pH / 2, 10, 10); 93 | } 94 | 95 | /** 96 | * 97 | * @param value 98 | */ 99 | @Override 100 | public final void setValue(float value) { 101 | if (value > vMax) { 102 | value = vMax; 103 | } 104 | if (value < vMin) { 105 | value = vMin; 106 | } 107 | pValue = value; 108 | pScaled = map(pValue, vMin, vMax, 0, pW); 109 | } 110 | 111 | @Override 112 | void checkKeyboard() { 113 | if (mouseOver()) { 114 | if (applet.mousePressed && applet.mouseButton == PConstants.LEFT) { 115 | pValue = constrainMap(applet.mouseX - pX, 0, pW, vMin, vMax); 116 | } 117 | if (applet.keyPressed && pressOnlyOnce) { 118 | if (applet.keyCode == PConstants.LEFT || applet.keyCode == PConstants.DOWN) { 119 | pValue--; 120 | } 121 | if (applet.keyCode == PConstants.RIGHT || applet.keyCode == PConstants.UP) { 122 | pValue++; 123 | } 124 | if (pValue > vMax) { 125 | pValue = vMax; 126 | } else { 127 | pValue = pValue < vMin ? vMin : pValue; 128 | } 129 | pressOnlyOnce = false; 130 | } 131 | deBounce(5); 132 | pScaled = map(pValue, vMin, vMax, 0, pW); 133 | } 134 | } 135 | 136 | /** 137 | * 138 | * @return 139 | */ 140 | @Override 141 | public String toString() { 142 | String geomF = "SimpleHSliderBar.new(%d, %d, %d, %.2f, %.2f, \"%s\")"; 143 | return String.format(geomF, pX, pY, pW, vMin, vMax, ID); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/monkstone/arcball/Rarcball.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | package monkstone.arcball; 22 | 23 | import org.jruby.Ruby; 24 | import org.jruby.RubyClass; 25 | import org.jruby.RubyFloat; 26 | import org.jruby.RubyFixnum; 27 | import org.jruby.RubyModule; 28 | import org.jruby.RubyObject; 29 | import org.jruby.RubySymbol; 30 | import org.jruby.anno.JRubyClass; 31 | import org.jruby.anno.JRubyMethod; 32 | import org.jruby.runtime.Arity; 33 | import org.jruby.runtime.ThreadContext; 34 | import org.jruby.runtime.builtin.IRubyObject; 35 | import processing.core.PApplet; 36 | 37 | /** 38 | * 39 | * @author Martin Prout 40 | */ 41 | @JRubyClass(name = "ArcBall") 42 | public class Rarcball extends RubyObject { 43 | 44 | private static final long serialVersionUID = -8164248008668234947L; 45 | 46 | /** 47 | * 48 | * @param runtime Ruby 49 | */ 50 | public static void createArcBall(final Ruby runtime) { 51 | RubyModule processing = runtime.defineModule("Processing"); 52 | RubyModule arcBallModule = processing.defineModuleUnder("ArcBall"); 53 | arcBallModule.defineAnnotatedMethods(Rarcball.class); 54 | } 55 | 56 | /** 57 | * 58 | * @param runtime Ruby 59 | * @param metaClass RubyClass 60 | */ 61 | public Rarcball(Ruby runtime, RubyClass metaClass) { 62 | super(runtime, metaClass); 63 | } 64 | 65 | /** 66 | * Initialize a new instance of Arcball (without Constrain) 67 | * @param context ThreadContext 68 | * @param self IRubyObject 69 | * @param args optional (no args jx = 0, jy = 0) 70 | */ 71 | @JRubyMethod(name = "init", meta = true, rest = true, required = 1, optional = 3) 72 | 73 | public static void init(ThreadContext context, IRubyObject self, IRubyObject args[]) { 74 | int count = Arity.checkArgumentCount(context.runtime, args, 1, 4); 75 | if (count == 4) { 76 | PApplet parent = (PApplet) args[0].toJava(PApplet.class); 77 | double cx = args[1] instanceof RubyFloat 78 | ? ((RubyFloat) args[1]).getValue() : ((RubyFixnum) args[1]).getDoubleValue(); 79 | double cy = args[2] instanceof RubyFloat 80 | ? ((RubyFloat) args[2]).getValue() : ((RubyFixnum) args[2]).getDoubleValue(); 81 | double radius = args[3] instanceof RubyFloat 82 | ? ((RubyFloat) args[3]).getValue() : ((RubyFixnum) args[3]).getDoubleValue(); 83 | new Arcball(parent, cx, cy, radius).setActive(true); 84 | } 85 | if (count == 3) { 86 | PApplet parent = (PApplet) args[0].toJava(PApplet.class); 87 | double cx = args[1] instanceof RubyFloat 88 | ? ((RubyFloat) args[1]).getValue() : ((RubyFixnum) args[1]).getDoubleValue(); 89 | double cy = args[2] instanceof RubyFloat 90 | ? ((RubyFloat) args[2]).getValue() : ((RubyFixnum) args[2]).getDoubleValue(); 91 | new Arcball(parent, cx, cy, parent.width * 0.8f).setActive(true); 92 | } 93 | if (count == 1) { 94 | PApplet parent = (PApplet) args[0].toJava(PApplet.class); 95 | new Arcball(parent).setActive(true); 96 | } 97 | } 98 | 99 | /** 100 | * 101 | * @param context 102 | * @param self 103 | * @param args optional (no args jx = 0, jy = 0) 104 | */ 105 | @JRubyMethod(name = "constrain", meta = true, rest = true, required = 1, optional = 1) 106 | 107 | public static void constrain(ThreadContext context, IRubyObject self, IRubyObject args[]) { 108 | int count = Arity.checkArgumentCount(context.runtime, args, 1, 2); 109 | RubySymbol zaxis = RubySymbol.newSymbol(context.runtime, "zaxis"); 110 | RubySymbol xaxis = RubySymbol.newSymbol(context.runtime, "xaxis"); 111 | PApplet parent = (PApplet) args[0].toJava(PApplet.class); 112 | if (count == 2) { 113 | if (xaxis == args[1]) { 114 | new Arcball(parent, Constrain.XAXIS).setActive(true); 115 | } 116 | if (zaxis == args[1]) { 117 | new Arcball(parent, Constrain.ZAXIS).setActive(true); 118 | } 119 | } else { 120 | new Arcball(parent, Constrain.YAXIS).setActive(true); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /vendors/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'fileutils' 4 | require 'rake/clean' 5 | 6 | WARNING = <<~WARN 7 | WARNING: you may not have wget installed, you could just download 8 | the correct version of jruby-complete to the vendors folder, and 9 | re-run k9 setup install instead of installing wget. Some systems 10 | may also require 'sudo' access to install, NB: this is untested.... 11 | 12 | WARN 13 | 14 | JRUBYC_VERSION = '9.3.3.0' 15 | SOUND = 'sound.zip' 16 | SOUND_VERSION = 'v2.2.3' 17 | VIDEO = 'video.zip' 18 | VIDEO_VERSION = 'v2.0' 19 | EXAMPLES = '4.2' 20 | HOME_DIR = ENV['HOME'] 21 | MAC_OR_LINUX = /linux|mac|darwin/.match?(RbConfig::CONFIG['host_os']) 22 | DOWNLOAD = 'releases/download/latest' 23 | CLOBBER << "jruby-complete-#{JRUBYC_VERSION}.jar" 24 | CLOBBER << "jruby-complete-#{JRUBYC_VERSION}.jar.sha256" 25 | 26 | desc 'dependency check' 27 | task :wget_check do 28 | WGET ||= `which wget`.freeze 29 | warn WARNING unless WGET 30 | end 31 | 32 | file "jruby-complete-#{JRUBYC_VERSION}.jar.sha256" do 33 | system "wget https://repo1.maven.org/maven2/org/jruby/jruby-complete/#{JRUBYC_VERSION}/jruby-complete-#{JRUBYC_VERSION}.jar.sha256" 34 | end 35 | 36 | file "jruby-complete-#{JRUBYC_VERSION}.jar" do 37 | begin 38 | system "wget https://repo1.maven.org/maven2/org/jruby/jruby-complete/#{JRUBYC_VERSION}/jruby-complete-#{JRUBYC_VERSION}.jar" 39 | rescue NameError 40 | warn(WARNING) 41 | end 42 | value = File.read("jruby-complete-#{JRUBYC_VERSION}.jar.sha256") 43 | check_sha256("jruby-complete-#{JRUBYC_VERSION}.jar", value) 44 | end 45 | 46 | desc 'get sha256' 47 | task get_sha256: ['wget_check', "jruby-complete-#{JRUBYC_VERSION}.jar.sha256"] 48 | 49 | desc 'download, and copy to jruby_art' 50 | task default: %i[wget_check download copy_ruby install_samples] 51 | 52 | desc 'download JRuby upstream sources' 53 | task download: ['get_sha256', "jruby-complete-#{JRUBYC_VERSION}.jar"] 54 | 55 | directory '../lib/ruby' 56 | 57 | desc 'copy jruby-complete' 58 | task copy_ruby: ['../lib/ruby'] do 59 | FileUtils.cp( 60 | "jruby-complete-#{JRUBYC_VERSION}.jar", '../lib/ruby/jruby-complete.jar' 61 | ) 62 | end 63 | 64 | def check_sha256(filename, expected_hash) 65 | require 'digest' 66 | sha256 = Digest::SHA256.new 67 | File.open(filename, 'r') do |f| 68 | while (buf = f.read(4096)) 69 | sha256.update(buf) 70 | end 71 | end 72 | return if sha256.hexdigest == expected_hash 73 | 74 | raise "bad sha256 checksum for #{filename} (expected #{expected_hash} got #{sha256.hexdigest})" 75 | end 76 | 77 | desc 'initialize ~/.jruby_art directories' 78 | task :init_dir do 79 | unless File.exist? "#{HOME_DIR}/.jruby_art/libraries" 80 | FileUtils.mkdir_p "#{HOME_DIR}/.jruby_art/libraries" 81 | end 82 | end 83 | 84 | desc 'download and copy sound library to ~/.jruby_art' 85 | task install_sound: %i[wget_check init_dir download_sound copy_sound clobber] 86 | 87 | desc 'download and copy video library to ~/.jruby_art' 88 | task install_video: %i[wget_check init_dir download_video copy_video clobber] 89 | 90 | desc 'download sound library' 91 | task :download_sound do 92 | wget_base = 'wget https://github.com/processing/processing-sound' 93 | wget_string = [wget_base, DOWNLOAD, SOUND].join('/') 94 | puts wget_string 95 | system wget_string 96 | end 97 | 98 | desc 'download video library' 99 | task :download_video do 100 | wget_base = 'wget https://github.com/processing/processing-video' 101 | wget_string = [wget_base, DOWNLOAD, VIDEO].join('/') 102 | system wget_string 103 | end 104 | 105 | desc 'copy sound library' 106 | task :copy_sound do 107 | system "unzip #{SOUND}" 108 | if File.exist? "#{HOME_DIR}/.jruby_art/libraries/sound" 109 | FileUtils.rm_r "#{HOME_DIR}/.picrate/libraries/sound" 110 | end 111 | FileUtils.cp_r 'sound', "#{HOME_DIR}/.jruby_art/libraries" 112 | FileUtils.rm_r 'sound' 113 | end 114 | 115 | desc 'copy video library' 116 | task :copy_video do 117 | system "unzip #{VIDEO}" 118 | if File.exist? "#{HOME_DIR}/.jruby_art/libraries/video" 119 | FileUtils.rm_r "#{HOME_DIR}/.picrate/libraries/video" 120 | end 121 | FileUtils.cp_r 'video', "#{HOME_DIR}/.jruby_art/libraries/video" 122 | FileUtils.rm_r 'video' 123 | end 124 | 125 | desc 'download, and copy to jruby_art' 126 | task install_samples: %i[download_examples copy_examples] 127 | 128 | desc 'download and copy examples to user home' 129 | task :download_examples 130 | file_name = MAC_OR_LINUX.nil? ? "#{EXAMPLES}.zip" : "#{EXAMPLES}.tar.gz" 131 | file file_name do 132 | if MAC_OR_LINUX.nil? 133 | system "wget https://github.com/ruby-processing/JRubyArt-examples/archive/#{EXAMPLES}.zip" 134 | else 135 | system "wget https://github.com/ruby-processing/JRubyArt-examples/archive/#{EXAMPLES}.tar.gz" 136 | end 137 | end 138 | 139 | desc 'copy examples' 140 | task copy_examples: file_name do 141 | if MAC_OR_LINUX.nil? 142 | system "unzip #{EXAMPLES}.zip" 143 | else 144 | system "tar xzvf #{EXAMPLES}.tar.gz" 145 | end 146 | if File.exist? "#{HOME_DIR}/k9_samples" 147 | FileUtils.rm_r("#{HOME_DIR}/k9_samples") 148 | end 149 | FileUtils.cp_r("JRubyArt-examples-#{EXAMPLES}", "#{HOME_DIR}/k9_samples") 150 | FileUtils.rm_r("JRubyArt-examples-#{EXAMPLES}") 151 | end 152 | -------------------------------------------------------------------------------- /src/main/java/monkstone/arcball/Jvector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-20 Martin Prout 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * http://creativecommons.org/licenses/LGPL/2.1/ 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | package monkstone.arcball; 21 | 22 | /** 23 | * 24 | * @author Martin Prout 25 | */ 26 | public final class Jvector { 27 | 28 | static final double EPSILON = 9.999999747378752E-5f; 29 | 30 | /** 31 | * 32 | */ 33 | public double x; 34 | 35 | /** 36 | * 37 | */ 38 | public double y; 39 | 40 | /** 41 | * 42 | */ 43 | public double z; 44 | 45 | /** 46 | * 47 | * @param x double 48 | * @param y double 49 | * @param z double 50 | */ 51 | public Jvector(double x, double y, double z) { 52 | this.x = x; 53 | this.y = y; 54 | this.z = z; 55 | } 56 | 57 | /** 58 | * 59 | */ 60 | public Jvector() { 61 | this(0.0f, 0.0f, 0.0f); 62 | } 63 | 64 | /** 65 | * 66 | * @param vect Jvector 67 | */ 68 | public Jvector(Jvector vect) { 69 | this(vect.x, vect.y, vect.z); 70 | } 71 | 72 | /** 73 | * 74 | * @param other Jvector 75 | * @return result new Jvector 76 | */ 77 | public Jvector sub(Jvector other) { 78 | return new Jvector(this.x - other.x, this.y - other.y, this.z - other.z); 79 | } 80 | 81 | /** 82 | * 83 | * @param scalar double 84 | * @return result new Jvector 85 | */ 86 | public Jvector mult(double scalar) { 87 | return new Jvector(this.x * scalar, this.y * scalar, this.z * scalar); 88 | } 89 | 90 | /** 91 | * 92 | * @return mag double 93 | */ 94 | public double mag() { 95 | return Math.sqrt(x * x + y * y + z * z); 96 | } 97 | 98 | /** 99 | * The usual normalize 100 | * 101 | * @return this Jvector normalized 102 | */ 103 | public Jvector normalize() { 104 | double mag = Math.sqrt(x * x + y * y + z * z); 105 | this.x /= mag; 106 | this.y /= mag; 107 | this.z /= mag; 108 | return this; 109 | } 110 | 111 | /** 112 | * 113 | * @param other Jvector 114 | * @return product double 115 | */ 116 | public double dot(Jvector other) { 117 | return x * other.x + y * other.y + z * other.z; 118 | } 119 | 120 | /** 121 | * 122 | * @param other Jvector 123 | * @return cross product Jvector 124 | */ 125 | public Jvector cross(Jvector other) { 126 | double xc = y * other.z - z * other.y; 127 | double yc = z * other.x - x * other.z; 128 | double zc = x * other.y - y * other.x; 129 | return new Jvector(xc, yc, zc); 130 | } 131 | 132 | /** 133 | * 134 | * @param other Jvector 135 | * @return equals boolean 136 | */ 137 | public boolean equals(Jvector other) { 138 | if (other instanceof Jvector) { 139 | 140 | if (Math.abs(this.x - other.x) > EPSILON) { 141 | return false; 142 | } 143 | if (Math.abs(this.y - other.y) > EPSILON) { 144 | return false; 145 | } 146 | return Math.abs(this.z - other.z) > EPSILON; 147 | } 148 | return false; 149 | 150 | } 151 | 152 | /** 153 | * 154 | * @param obj Object 155 | * @return equals boolean 156 | */ 157 | @Override 158 | public boolean equals(Object obj) { 159 | if (obj == null) { 160 | return false; 161 | } 162 | if (getClass() != obj.getClass()) { 163 | return false; 164 | } 165 | final Jvector other = (Jvector) obj; 166 | if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x)) { 167 | return false; 168 | } 169 | if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y)) { 170 | return false; 171 | } 172 | return Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z); 173 | } 174 | 175 | /** 176 | * 177 | * @return hash int 178 | */ 179 | @Override 180 | public int hashCode() { 181 | int hash = 7; 182 | hash = 97 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); 183 | hash = 97 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); 184 | hash = 97 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); 185 | return hash; 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/main/java/monkstone/FastNoiseModuleJava.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020-2022 Martin Prout 3 | */ 4 | package monkstone; 5 | 6 | import monkstone.noise.OpenSimplex2; 7 | import org.jruby.Ruby; 8 | import org.jruby.RubyFixnum; 9 | import org.jruby.RubyFloat; 10 | import org.jruby.RubyModule; 11 | import org.jruby.anno.JRubyMethod; 12 | import org.jruby.anno.JRubyModule; 13 | import org.jruby.runtime.ThreadContext; 14 | import org.jruby.runtime.builtin.IRubyObject; 15 | 16 | /** 17 | * 18 | * @author Martin Prout 19 | */ 20 | @JRubyModule(name = "FastNoise") 21 | public class FastNoiseModuleJava { 22 | 23 | static OpenSimplex2 ng = new OpenSimplex2(); 24 | static long seed = System.currentTimeMillis(); 25 | /** 26 | * 27 | * @param runtime Ruby 28 | */ 29 | public static void createNoiseModule(Ruby runtime) { 30 | RubyModule noiseModule = runtime.defineModule("FastNoise"); 31 | noiseModule.defineAnnotatedMethods(FastNoiseModuleJava.class); 32 | } 33 | 34 | 35 | /** 36 | * Utility method 37 | * 38 | * @param obj 39 | * @return parse float value of object or zero 40 | */ 41 | private static double jvalue(IRubyObject obj) { 42 | if (obj instanceof RubyFloat rubyFloat) { 43 | return rubyFloat.getValue(); 44 | } 45 | if (obj instanceof RubyFixnum rubyFixnum) { 46 | return rubyFixnum.getDoubleValue(); 47 | } 48 | return 0; 49 | } 50 | 51 | /** 52 | * 53 | * @param context ThreadContext 54 | * @param recv IRubyObject 55 | * @param args array of numeric values 56 | * @return mapped value RubyFloat 57 | */ 58 | @JRubyMethod(name = "tnoise", rest = true, module = true) 59 | public static IRubyObject terrainNoiseImpl(ThreadContext context, IRubyObject recv, IRubyObject[] args) { 60 | double one; 61 | double two; 62 | double three; 63 | double four; 64 | double result = switch (args.length) { 65 | case 2 -> { 66 | two = jvalue(args[1]); 67 | one = jvalue(args[0]); 68 | //yield ng.noise2_XBeforeY(one, two); 69 | yield ng.noise2(seed, one, two); 70 | } 71 | case 3 -> { 72 | three = jvalue(args[2]); 73 | two = jvalue(args[1]); 74 | one = jvalue(args[0]); 75 | yield ng.noise3_ImproveXY(seed, one, two, three); 76 | } 77 | case 4 -> { 78 | four = jvalue(args[3]); 79 | three = jvalue(args[2]); 80 | two = jvalue(args[1]); 81 | one = jvalue(args[0]); 82 | yield ng.noise4_ImproveXYZ_ImproveXY(seed, one, two, three, four); 83 | } 84 | default -> { yield 2; } // yield an invalid value for noise 85 | }; 86 | if (result != 2) { 87 | return RubyFloat.newFloat(context.runtime, result); 88 | } else { 89 | throw new RuntimeException("Min 2D Max 4D Noise"); 90 | } 91 | } 92 | 93 | /** 94 | * 95 | * @param context ThreadContext 96 | * @param recv IRubyObject 97 | * @param args array of numeric values 98 | * @return mapped value RubyFloat 99 | */ 100 | @JRubyMethod(name = "noise", rest = true, module = true) 101 | public static IRubyObject noiseImpl(ThreadContext context, IRubyObject recv, IRubyObject[] args) { 102 | double one; 103 | double two; 104 | double three; 105 | double four; 106 | double result = switch (args.length) { 107 | case 1 -> { 108 | one = jvalue(args[0]); 109 | yield ng.noise2(seed, one, 0); 110 | } 111 | case 2 -> { 112 | two = jvalue(args[1]); 113 | one = jvalue(args[0]); 114 | yield ng.noise2(seed, one, two); 115 | } 116 | case 3 -> { 117 | three = jvalue(args[2]); 118 | two = jvalue(args[1]); 119 | one = jvalue(args[0]); 120 | yield ng.noise3_ImproveXY(seed, one, two, three); 121 | } 122 | case 4 -> { 123 | four = jvalue(args[3]); 124 | three = jvalue(args[2]); 125 | two = jvalue(args[1]); 126 | one = jvalue(args[0]); 127 | yield ng.noise4_ImproveXY_ImproveZW(seed, one, two, three, four); 128 | } 129 | default -> { yield 2; } // yield an invalid value for noise 130 | }; 131 | if (result != 2) { 132 | return RubyFloat.newFloat(context.runtime, result); 133 | } else { 134 | throw new RuntimeException("Min 2D Max 4D Noise"); 135 | } 136 | } 137 | } 138 | 139 | // @JRubyMethod(name = "noise_seed", rest = true, module = true) 140 | // public static IRubyObject noiseSeedImpl(ThreadContext context, IRubyObject recv, IRubyObject arg) { 141 | // long seed; 142 | // if (arg instanceof RubyNumeric) { 143 | // seed = ((RubyNumeric) arg).getLongValue(); 144 | // ng = new OpenSimplex2(seed); 145 | // return RubyBoolean.newBoolean(context.runtime, true); 146 | // } 147 | // return RubyBoolean.newBoolean(context.runtime, false); 148 | // } 149 | //} 150 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.6"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | --------------------------------------------------------------------------------