propane 0.3.0.pre-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +21 -0
 - data/.mvn/extensions.xml +8 -0
 - data/.mvn/wrapper/maven-wrapper.properties +1 -0
 - data/.travis.yml +9 -0
 - data/Gemfile +4 -0
 - data/LICENSE.txt +22 -0
 - data/README.md +69 -0
 - data/Rakefile +59 -0
 - data/VERSION.txt +4 -0
 - data/bin/propane +8 -0
 - data/examples/complete/Rakefile +32 -0
 - data/examples/complete/data/Texture01.jpg +0 -0
 - data/examples/complete/data/Texture02.jpg +0 -0
 - data/examples/complete/data/Univers45.vlw +0 -0
 - data/examples/complete/data/displaceFrag.glsl +8 -0
 - data/examples/complete/data/displaceVert.glsl +201 -0
 - data/examples/complete/glsl_heightmap_noise.rb +121 -0
 - data/examples/complete/kinetic_type.rb +79 -0
 - data/examples/regular/Rakefile +30 -0
 - data/examples/regular/arcball_box.rb +36 -0
 - data/examples/regular/creating_colors.rb +57 -0
 - data/examples/regular/elegant_ball.rb +159 -0
 - data/examples/regular/flight_patterns.rb +63 -0
 - data/examples/regular/grey_circles.rb +28 -0
 - data/examples/regular/jwishy.rb +100 -0
 - data/examples/regular/letters.rb +42 -0
 - data/examples/regular/lib/boundary.rb +38 -0
 - data/examples/regular/lib/particle.rb +77 -0
 - data/examples/regular/lib/particle_system.rb +111 -0
 - data/examples/regular/liquidy.rb +40 -0
 - data/examples/regular/mouse_button_demo.rb +34 -0
 - data/examples/regular/polyhedrons.rb +248 -0
 - data/examples/regular/ribbon_doodle.rb +89 -0
 - data/examples/regular/vector_math.rb +36 -0
 - data/examples/regular/words.rb +41 -0
 - data/lib/PROCESSING_LICENSE.txt +456 -0
 - data/lib/export.txt +10 -0
 - data/lib/propane.rb +12 -0
 - data/lib/propane/app.rb +197 -0
 - data/lib/propane/helper_methods.rb +177 -0
 - data/lib/propane/helpers/numeric.rb +9 -0
 - data/lib/propane/library_loader.rb +117 -0
 - data/lib/propane/runner.rb +88 -0
 - data/lib/propane/underscorer.rb +19 -0
 - data/lib/propane/version.rb +5 -0
 - data/library/boids/boids.rb +201 -0
 - data/library/control_panel/control_panel.rb +172 -0
 - data/pom.rb +113 -0
 - data/pom.xml +198 -0
 - data/propane.gemspec +28 -0
 - data/src/monkstone/ColorUtil.java +67 -0
 - data/src/monkstone/MathTool.java +195 -0
 - data/src/monkstone/PropaneLibrary.java +47 -0
 - data/src/monkstone/core/AbstractLibrary.java +102 -0
 - data/src/monkstone/fastmath/Deglut.java +115 -0
 - data/src/monkstone/vecmath/AppRender.java +87 -0
 - data/src/monkstone/vecmath/JRender.java +56 -0
 - data/src/monkstone/vecmath/ShapeRender.java +87 -0
 - data/src/monkstone/vecmath/vec2/Vec2.java +670 -0
 - data/src/monkstone/vecmath/vec3/Vec3.java +708 -0
 - data/test/respond_to_test.rb +208 -0
 - data/vendors/Rakefile +48 -0
 - metadata +130 -0
 
| 
         @@ -0,0 +1,88 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: false
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "#{PROPANE_ROOT}/lib/propane"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "#{PROPANE_ROOT}/lib/propane/app"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module Propane
         
     | 
| 
      
 8 
     | 
    
         
            +
              # Utility class to handle the different commands that the 'rp5' command
         
     | 
| 
      
 9 
     | 
    
         
            +
              # offers. Able to run, watch, live, create, app, and unpack
         
     | 
| 
      
 10 
     | 
    
         
            +
              class Runner
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_reader :options, :name
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @options = {}
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                # Start running a propane sketch from the passed-in arguments
         
     | 
| 
      
 18 
     | 
    
         
            +
                def self.execute
         
     | 
| 
      
 19 
     | 
    
         
            +
                  runner = new
         
     | 
| 
      
 20 
     | 
    
         
            +
                  runner.parse_options(ARGV)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  runner.execute!
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                # Dispatch central.
         
     | 
| 
      
 25 
     | 
    
         
            +
                def execute!
         
     | 
| 
      
 26 
     | 
    
         
            +
                  show_help if options.empty?
         
     | 
| 
      
 27 
     | 
    
         
            +
                  show_version if options[:version]
         
     | 
| 
      
 28 
     | 
    
         
            +
                  run_sketch if options[:run]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  install if options[:install]
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                # Parse the command-line options. Keep it simple.
         
     | 
| 
      
 33 
     | 
    
         
            +
                def parse_options(args)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  opt_parser = OptionParser.new do |opts|
         
     | 
| 
      
 35 
     | 
    
         
            +
                    # Set a banner, displayed at the top
         
     | 
| 
      
 36 
     | 
    
         
            +
                    # of the help screen.
         
     | 
| 
      
 37 
     | 
    
         
            +
                    opts.banner = 'Usage: propane [options] sketch.rb'
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    # Define the options, and what they do
         
     | 
| 
      
 40 
     | 
    
         
            +
                    options[:version] = false
         
     | 
| 
      
 41 
     | 
    
         
            +
                    opts.on('-v', '--version', 'Propane Version') do
         
     | 
| 
      
 42 
     | 
    
         
            +
                      options[:version] = true
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    options[:install] = false
         
     | 
| 
      
 46 
     | 
    
         
            +
                    opts.on('-i', '--install', 'Installs jruby-complete') do
         
     | 
| 
      
 47 
     | 
    
         
            +
                      options[:install] = true
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    options[:run] = false
         
     | 
| 
      
 51 
     | 
    
         
            +
                    opts.on('-r', '--run', 'Run the sketch using jruby-complete') do
         
     | 
| 
      
 52 
     | 
    
         
            +
                      options[:run] = true
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    # This displays the help screen, all programs are
         
     | 
| 
      
 56 
     | 
    
         
            +
                    # assumed to have this option.
         
     | 
| 
      
 57 
     | 
    
         
            +
                    opts.on('-h', '--help', 'Display this screen') do
         
     | 
| 
      
 58 
     | 
    
         
            +
                      puts opts
         
     | 
| 
      
 59 
     | 
    
         
            +
                      exit
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @name = opt_parser.parse(args)
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def run_sketch
         
     | 
| 
      
 66 
     | 
    
         
            +
                  root = File.absolute_path(File.dirname(ARGV.shift))
         
     | 
| 
      
 67 
     | 
    
         
            +
                  sketch = File.join(root, name)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  warn_format = 'File %s does not not Exist!'
         
     | 
| 
      
 69 
     | 
    
         
            +
                  return warn(format(warn_format, sketch)) unless File.exist?(sketch)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  command = [
         
     | 
| 
      
 71 
     | 
    
         
            +
                    'java',
         
     | 
| 
      
 72 
     | 
    
         
            +
                    '-cp',
         
     | 
| 
      
 73 
     | 
    
         
            +
                    "#{PROPANE_ROOT}/lib/ruby/jruby-complete.jar",
         
     | 
| 
      
 74 
     | 
    
         
            +
                    'org.jruby.Main',
         
     | 
| 
      
 75 
     | 
    
         
            +
                    sketch.to_s
         
     | 
| 
      
 76 
     | 
    
         
            +
                  ].flatten
         
     | 
| 
      
 77 
     | 
    
         
            +
                  exec(*command)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def show_version
         
     | 
| 
      
 81 
     | 
    
         
            +
                  puts format('Propane version %s', Propane::VERSION)
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                def install
         
     | 
| 
      
 85 
     | 
    
         
            +
                  system "cd #{PROPANE_ROOT}/vendors && rake"
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
              end # class Runner
         
     | 
| 
      
 88 
     | 
    
         
            +
            end # module Propane
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: false
         
     | 
| 
      
 3 
     | 
    
         
            +
            module Propane
         
     | 
| 
      
 4 
     | 
    
         
            +
              # This class defines a single method that converts a method name
         
     | 
| 
      
 5 
     | 
    
         
            +
              # from camel or mixed case to snake case.
         
     | 
| 
      
 6 
     | 
    
         
            +
              #
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Underscorer
         
     | 
| 
      
 8 
     | 
    
         
            +
                # Underscorer.("CamelCase") => "camel_case"
         
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
      
 10 
     | 
    
         
            +
                def self.call(input)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  string = input.to_s
         
     | 
| 
      
 12 
     | 
    
         
            +
                  string.gsub(/::/, '/')
         
     | 
| 
      
 13 
     | 
    
         
            +
                        .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
         
     | 
| 
      
 14 
     | 
    
         
            +
                        .gsub(/([a-z\d])([A-Z])/, '\1_\2')
         
     | 
| 
      
 15 
     | 
    
         
            +
                        .tr('-', '_')
         
     | 
| 
      
 16 
     | 
    
         
            +
                        .downcase
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,201 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Boids -- after Tom de Smedt.
         
     | 
| 
      
 2 
     | 
    
         
            +
            # See his Python version: http://nodebox.net/code/index.php/Boids
         
     | 
| 
      
 3 
     | 
    
         
            +
            # This is an example of how a pure-Ruby library can work. Original for
         
     | 
| 
      
 4 
     | 
    
         
            +
            # ruby-processing Jeremy Ashkenas. Reworked, re-factored for JRubyArt 0.9+
         
     | 
| 
      
 5 
     | 
    
         
            +
            # by Martin Prout, features forwardable, keyword args, Vec3D and Vec2D.
         
     | 
| 
      
 6 
     | 
    
         
            +
            class Boid
         
     | 
| 
      
 7 
     | 
    
         
            +
              attr_accessor :boids, :pos, :vel, :is_perching, :perch_time
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def initialize(boids, pos)
         
     | 
| 
      
 10 
     | 
    
         
            +
                @boids, @flock = boids, boids
         
     | 
| 
      
 11 
     | 
    
         
            +
                @pos = pos
         
     | 
| 
      
 12 
     | 
    
         
            +
                @vel = Vec3D.new
         
     | 
| 
      
 13 
     | 
    
         
            +
                @is_perching = false
         
     | 
| 
      
 14 
     | 
    
         
            +
                @perch_time = 0.0
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def cohesion(d:)
         
     | 
| 
      
 18 
     | 
    
         
            +
                # Boids gravitate towards the center of the flock,
         
     | 
| 
      
 19 
     | 
    
         
            +
                # Which is the averaged position of the rest of the boids.
         
     | 
| 
      
 20 
     | 
    
         
            +
                vect = Vec3D.new
         
     | 
| 
      
 21 
     | 
    
         
            +
                @boids.each do |boid|
         
     | 
| 
      
 22 
     | 
    
         
            +
                  vect += boid.pos unless boid == self
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
                count = @boids.length - 1.0
         
     | 
| 
      
 25 
     | 
    
         
            +
                vect /= count
         
     | 
| 
      
 26 
     | 
    
         
            +
                (vect - pos) / d
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              def separation(radius:)
         
     | 
| 
      
 30 
     | 
    
         
            +
                # Boids don't like to cuddle.
         
     | 
| 
      
 31 
     | 
    
         
            +
                vect = Vec3D.new
         
     | 
| 
      
 32 
     | 
    
         
            +
                @boids.each do |boid|
         
     | 
| 
      
 33 
     | 
    
         
            +
                  if boid != self
         
     | 
| 
      
 34 
     | 
    
         
            +
                    dv = pos - boid.pos
         
     | 
| 
      
 35 
     | 
    
         
            +
                    vect += dv if dv.mag < radius
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
                vect
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              def alignment(d:)
         
     | 
| 
      
 42 
     | 
    
         
            +
                # Boids like to fly at the speed of traffic.
         
     | 
| 
      
 43 
     | 
    
         
            +
                vect = Vec3D.new
         
     | 
| 
      
 44 
     | 
    
         
            +
                @boids.each do |boid|
         
     | 
| 
      
 45 
     | 
    
         
            +
                  vect += boid.vel if boid != self
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
                count = @boids.length - 1.0
         
     | 
| 
      
 48 
     | 
    
         
            +
                vect /= count
         
     | 
| 
      
 49 
     | 
    
         
            +
                (vect - vel) / d
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              def limit(max:)
         
     | 
| 
      
 53 
     | 
    
         
            +
                # Tweet, Tweet! The boid police will bust you for breaking the speed limit.
         
     | 
| 
      
 54 
     | 
    
         
            +
                most = [vel.x.abs, vel.y.abs, vel.z.abs].max
         
     | 
| 
      
 55 
     | 
    
         
            +
                return if most < max
         
     | 
| 
      
 56 
     | 
    
         
            +
                scale = max / most.to_f
         
     | 
| 
      
 57 
     | 
    
         
            +
                @vel *= scale
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              def angle
         
     | 
| 
      
 61 
     | 
    
         
            +
                Vec2D.new(vel.x, vel.y).heading
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              def goal(target, d = 50.0)
         
     | 
| 
      
 65 
     | 
    
         
            +
                # Them boids is hungry.
         
     | 
| 
      
 66 
     | 
    
         
            +
                (target - pos) / d
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
            end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            require 'forwardable'
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            # The Boids class
         
     | 
| 
      
 73 
     | 
    
         
            +
            class Boids
         
     | 
| 
      
 74 
     | 
    
         
            +
              include Enumerable
         
     | 
| 
      
 75 
     | 
    
         
            +
              extend Forwardable
         
     | 
| 
      
 76 
     | 
    
         
            +
              def_delegators(:@boids, :reject, :<<, :each, :shuffle!, :length, :next)
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              attr_reader :has_goal, :perch, :perch_tm, :perch_y
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 81 
     | 
    
         
            +
                @boids = []
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
              def self.flock(n:, x:, y:, w:, h:)
         
     | 
| 
      
 85 
     | 
    
         
            +
                flock = Boids.new.setup(n, x, y, w, h)
         
     | 
| 
      
 86 
     | 
    
         
            +
                flock.goal(target: Vec3D.new(w / 2, h / 2, 0))
         
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
              def setup(n, x, y, w, h)
         
     | 
| 
      
 90 
     | 
    
         
            +
                n.times do
         
     | 
| 
      
 91 
     | 
    
         
            +
                  dx, dy = rand(w), rand(h)
         
     | 
| 
      
 92 
     | 
    
         
            +
                  z = rand(200.0)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  self << Boid.new(self, Vec3D.new(x + dx, y + dy, z))
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
                @x, @y, @w, @h = x, y, w, h
         
     | 
| 
      
 96 
     | 
    
         
            +
                @scattered = false
         
     | 
| 
      
 97 
     | 
    
         
            +
                @scatter = 0.005
         
     | 
| 
      
 98 
     | 
    
         
            +
                @scatter_time = 50.0
         
     | 
| 
      
 99 
     | 
    
         
            +
                @scatter_i = 0.0
         
     | 
| 
      
 100 
     | 
    
         
            +
                @perch = 1.0 # Lower this number to divebomb.
         
     | 
| 
      
 101 
     | 
    
         
            +
                @perch_y = h
         
     | 
| 
      
 102 
     | 
    
         
            +
                @perch_tm = -> { 25.0 + rand(50.0) }
         
     | 
| 
      
 103 
     | 
    
         
            +
                @has_goal = false
         
     | 
| 
      
 104 
     | 
    
         
            +
                @flee = false
         
     | 
| 
      
 105 
     | 
    
         
            +
                @goal = Vec3D.new
         
     | 
| 
      
 106 
     | 
    
         
            +
                self
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
              def scatter(chance = 0.005, frames = 50.0)
         
     | 
| 
      
 110 
     | 
    
         
            +
                @scatter = chance
         
     | 
| 
      
 111 
     | 
    
         
            +
                @scatter_time = frames
         
     | 
| 
      
 112 
     | 
    
         
            +
              end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
              def no_scatter
         
     | 
| 
      
 115 
     | 
    
         
            +
                @scatter = 0.0
         
     | 
| 
      
 116 
     | 
    
         
            +
              end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
              def perch(ground = nil, chance = 1.0, frames = nil)
         
     | 
| 
      
 119 
     | 
    
         
            +
                @perch_tm = frames.nil? ? -> { 25.0 + rand(50.0) } : frames
         
     | 
| 
      
 120 
     | 
    
         
            +
                @perch_y = ground.nil? ? @h : ground
         
     | 
| 
      
 121 
     | 
    
         
            +
                @perch = chance
         
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
              def no_perch
         
     | 
| 
      
 125 
     | 
    
         
            +
                @perch = 0.0
         
     | 
| 
      
 126 
     | 
    
         
            +
              end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
              def goal(target:, flee: false)
         
     | 
| 
      
 129 
     | 
    
         
            +
                @has_goal = true
         
     | 
| 
      
 130 
     | 
    
         
            +
                @flee = flee
         
     | 
| 
      
 131 
     | 
    
         
            +
                @goal = target
         
     | 
| 
      
 132 
     | 
    
         
            +
                self
         
     | 
| 
      
 133 
     | 
    
         
            +
              end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
              def no_goal
         
     | 
| 
      
 136 
     | 
    
         
            +
                @has_goal = false
         
     | 
| 
      
 137 
     | 
    
         
            +
              end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
              def constrain
         
     | 
| 
      
 140 
     | 
    
         
            +
                # Put them boids in a cage.
         
     | 
| 
      
 141 
     | 
    
         
            +
                dx, dy = @w * 0.1, @h * 0.1
         
     | 
| 
      
 142 
     | 
    
         
            +
                each do |b|
         
     | 
| 
      
 143 
     | 
    
         
            +
                  b.vel.x += rand(dx) if b.pos.x < @x - dx
         
     | 
| 
      
 144 
     | 
    
         
            +
                  b.vel.x += rand(dy) if b.pos.y < @y - dy
         
     | 
| 
      
 145 
     | 
    
         
            +
                  b.vel.x -= rand(dx) if b.pos.x > @x + @w + dx
         
     | 
| 
      
 146 
     | 
    
         
            +
                  b.vel.y -= rand(dy) if b.pos.y > @y + @h + dy
         
     | 
| 
      
 147 
     | 
    
         
            +
                  b.vel.z += 10.0 if b.pos.z < 0.0
         
     | 
| 
      
 148 
     | 
    
         
            +
                  b.vel.z -= 10.0 if b.pos.z > 100.0
         
     | 
| 
      
 149 
     | 
    
         
            +
                  next unless b.pos.y > perch_y && rand < perch
         
     | 
| 
      
 150 
     | 
    
         
            +
                  b.pos.y = perch_y
         
     | 
| 
      
 151 
     | 
    
         
            +
                  b.vel.y = -(b.vel.y.abs) * 0.2
         
     | 
| 
      
 152 
     | 
    
         
            +
                  b.is_perching = true
         
     | 
| 
      
 153 
     | 
    
         
            +
                  b.perch_time = perch_tm.respond_to?(:call) ? perch_tm.call : perch_tm
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
              end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
              def update(goal: 20.0, limit: 30.0, **args)
         
     | 
| 
      
 158 
     | 
    
         
            +
                shuffled = args.fetch(:shuffled, true)
         
     | 
| 
      
 159 
     | 
    
         
            +
                cohesion = args.fetch(:cohesion, 100)
         
     | 
| 
      
 160 
     | 
    
         
            +
                separation = args.fetch(:separation, 10)
         
     | 
| 
      
 161 
     | 
    
         
            +
                alignment = args.fetch(:alignment, 5.0)
         
     | 
| 
      
 162 
     | 
    
         
            +
                # Just flutter, little boids ... just flutter away.
         
     | 
| 
      
 163 
     | 
    
         
            +
                # Shuffling keeps things flowing smooth.
         
     | 
| 
      
 164 
     | 
    
         
            +
                shuffle! if shuffled
         
     | 
| 
      
 165 
     | 
    
         
            +
                m1 = 1.0 # cohesion
         
     | 
| 
      
 166 
     | 
    
         
            +
                m2 = 1.0 # separation
         
     | 
| 
      
 167 
     | 
    
         
            +
                m3 = 1.0 # alignment
         
     | 
| 
      
 168 
     | 
    
         
            +
                m4 = 1.0 # goal
         
     | 
| 
      
 169 
     | 
    
         
            +
                @scattered = true if !(@scattered) && rand < @scatter
         
     | 
| 
      
 170 
     | 
    
         
            +
                if @scattered
         
     | 
| 
      
 171 
     | 
    
         
            +
                  m1 = -m1
         
     | 
| 
      
 172 
     | 
    
         
            +
                  m3 *= 0.25
         
     | 
| 
      
 173 
     | 
    
         
            +
                  @scatter_i += 1.0
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
                if @scatter_i >= @scatter_time
         
     | 
| 
      
 176 
     | 
    
         
            +
                  @scattered = false
         
     | 
| 
      
 177 
     | 
    
         
            +
                  @scatter_i = 0.0
         
     | 
| 
      
 178 
     | 
    
         
            +
                end
         
     | 
| 
      
 179 
     | 
    
         
            +
                m4 = 0.0 unless has_goal
         
     | 
| 
      
 180 
     | 
    
         
            +
                m4 = -m4 if @flee
         
     | 
| 
      
 181 
     | 
    
         
            +
                each do |b|
         
     | 
| 
      
 182 
     | 
    
         
            +
                  if b.is_perching
         
     | 
| 
      
 183 
     | 
    
         
            +
                    if b.perch_time > 0.0
         
     | 
| 
      
 184 
     | 
    
         
            +
                      b.perch_time -= 1.0
         
     | 
| 
      
 185 
     | 
    
         
            +
                      next
         
     | 
| 
      
 186 
     | 
    
         
            +
                    else
         
     | 
| 
      
 187 
     | 
    
         
            +
                      b.is_perching = false
         
     | 
| 
      
 188 
     | 
    
         
            +
                    end
         
     | 
| 
      
 189 
     | 
    
         
            +
                  end
         
     | 
| 
      
 190 
     | 
    
         
            +
                  v1 = b.cohesion(d: cohesion)
         
     | 
| 
      
 191 
     | 
    
         
            +
                  v2 = b.separation(radius: separation)
         
     | 
| 
      
 192 
     | 
    
         
            +
                  v3 = b.alignment(d: alignment)
         
     | 
| 
      
 193 
     | 
    
         
            +
                  v4 = b.goal(@goal, goal)
         
     | 
| 
      
 194 
     | 
    
         
            +
                  # NB: vector must precede scalar in '*' operation below
         
     | 
| 
      
 195 
     | 
    
         
            +
                  b.vel += (v1 * m1 + v2 * m2 + v3 * m3 + v4 * m4)
         
     | 
| 
      
 196 
     | 
    
         
            +
                  b.limit(max: limit)
         
     | 
| 
      
 197 
     | 
    
         
            +
                  b.pos += b.vel
         
     | 
| 
      
 198 
     | 
    
         
            +
                end
         
     | 
| 
      
 199 
     | 
    
         
            +
                constrain
         
     | 
| 
      
 200 
     | 
    
         
            +
              end
         
     | 
| 
      
 201 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,172 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Here's a little library for quickly hooking up controls to sketches.
         
     | 
| 
      
 2 
     | 
    
         
            +
            # For messing with the parameters and such.
         
     | 
| 
      
 3 
     | 
    
         
            +
            # These controls will set instance variables on the sketches.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            # You can make sliders, checkboxes, buttons, and drop-down menus.
         
     | 
| 
      
 6 
     | 
    
         
            +
            # (optionally) pass the range and default value.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module ControlPanel
         
     | 
| 
      
 9 
     | 
    
         
            +
              # class used to create slider elements for control_panel
         
     | 
| 
      
 10 
     | 
    
         
            +
              class Slider < javax.swing.JSlider
         
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(control_panel, name, range, initial_value, proc = nil)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  min = range.begin * 100
         
     | 
| 
      
 13 
     | 
    
         
            +
                  max = (
         
     | 
| 
      
 14 
     | 
    
         
            +
                    (range.exclude_end? && range.begin.respond_to?(:succ)) ?
         
     | 
| 
      
 15 
     | 
    
         
            +
                      range.max : range.end) * 100
         
     | 
| 
      
 16 
     | 
    
         
            +
                  super(min, max)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  set_minor_tick_spacing((max - min).abs / 10)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  set_paint_ticks true
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # paint_labels = true
         
     | 
| 
      
 20 
     | 
    
         
            +
                  set_preferred_size(java.awt.Dimension.new(190, 30))
         
     | 
| 
      
 21 
     | 
    
         
            +
                  label = control_panel.add_element(self, name)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  add_change_listener do
         
     | 
| 
      
 23 
     | 
    
         
            +
                    update_label(label, name, value)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    $app.instance_variable_set("@#{name}", value) unless value.nil?
         
     | 
| 
      
 25 
     | 
    
         
            +
                    proc.call(value) if proc
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  set_value(initial_value ? initial_value * 100 : min)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  fire_state_changed
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def value
         
     | 
| 
      
 32 
     | 
    
         
            +
                  get_value / 100.0
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def update_label(label, name, value)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  value = value.to_s
         
     | 
| 
      
 37 
     | 
    
         
            +
                  value << '0' if value.length < 4
         
     | 
| 
      
 38 
     | 
    
         
            +
                  label.set_text "<html><br><b>#{name}: #{value}</b></html>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              # class used to combo_box menu elements for control_panel
         
     | 
| 
      
 43 
     | 
    
         
            +
              class Menu < javax.swing.JComboBox
         
     | 
| 
      
 44 
     | 
    
         
            +
                def initialize(control_panel, name, elements, initial_value, proc = nil)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  super(elements.to_java(:String))
         
     | 
| 
      
 46 
     | 
    
         
            +
                  set_preferred_size(java.awt.Dimension.new(190, 30))
         
     | 
| 
      
 47 
     | 
    
         
            +
                  control_panel.add_element(self, name)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  add_action_listener do
         
     | 
| 
      
 49 
     | 
    
         
            +
                    $app.instance_variable_set("@#{name}", value) unless value.nil?
         
     | 
| 
      
 50 
     | 
    
         
            +
                    proc.call(value) if proc
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  set_selected_index(initial_value ? elements.index(initial_value) : 0)
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                def value
         
     | 
| 
      
 56 
     | 
    
         
            +
                  get_selected_item
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              # Creates check-box elements for control_panel
         
     | 
| 
      
 61 
     | 
    
         
            +
              class Checkbox < javax.swing.JCheckBox
         
     | 
| 
      
 62 
     | 
    
         
            +
                def initialize(control_panel, name, proc = nil)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @control_panel = control_panel
         
     | 
| 
      
 64 
     | 
    
         
            +
                  super(name.to_s)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  set_preferred_size(java.awt.Dimension.new(190, 64))
         
     | 
| 
      
 66 
     | 
    
         
            +
                  set_horizontal_alignment javax.swing.SwingConstants::CENTER
         
     | 
| 
      
 67 
     | 
    
         
            +
                  control_panel.add_element(self, name, false)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  add_action_listener do
         
     | 
| 
      
 69 
     | 
    
         
            +
                    $app.instance_variable_set("@#{name}", value) unless value.nil?
         
     | 
| 
      
 70 
     | 
    
         
            +
                    proc.call(value) if proc
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                def value
         
     | 
| 
      
 75 
     | 
    
         
            +
                  is_selected
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              # Creates button elements for control_panel
         
     | 
| 
      
 80 
     | 
    
         
            +
              class Button < javax.swing.JButton
         
     | 
| 
      
 81 
     | 
    
         
            +
                def initialize(control_panel, name, proc = nil)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  super(name.to_s)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  set_preferred_size(java.awt.Dimension.new(170, 64))
         
     | 
| 
      
 84 
     | 
    
         
            +
                  control_panel.add_element(self, name, false, true)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  add_action_listener do
         
     | 
| 
      
 86 
     | 
    
         
            +
                    $app.send(name.to_s)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    proc.call(value) if proc
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              # class used to contain control_panel elements
         
     | 
| 
      
 93 
     | 
    
         
            +
              class Panel < javax.swing.JFrame
         
     | 
| 
      
 94 
     | 
    
         
            +
                java_import javax.swing.UIManager
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                attr_accessor :elements, :panel
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 99 
     | 
    
         
            +
                  super()
         
     | 
| 
      
 100 
     | 
    
         
            +
                  @elements = []
         
     | 
| 
      
 101 
     | 
    
         
            +
                  @panel = javax.swing.JPanel.new(java.awt.FlowLayout.new(1, 0, 0))
         
     | 
| 
      
 102 
     | 
    
         
            +
                  set_feel
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                def display
         
     | 
| 
      
 106 
     | 
    
         
            +
                  add panel
         
     | 
| 
      
 107 
     | 
    
         
            +
                  set_size 200, 30 + (64 * elements.size)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  set_default_close_operation javax.swing.JFrame::HIDE_ON_CLOSE
         
     | 
| 
      
 109 
     | 
    
         
            +
                  set_resizable false
         
     | 
| 
      
 110 
     | 
    
         
            +
                  set_location($app.width + 10, 0) unless $app.width + 10 > $app.displayWidth
         
     | 
| 
      
 111 
     | 
    
         
            +
                  panel.visible = true
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                def add_element(element, name, has_label = true, _button_ = false)
         
     | 
| 
      
 115 
     | 
    
         
            +
                  if has_label
         
     | 
| 
      
 116 
     | 
    
         
            +
                    label = javax.swing.JLabel.new("<html><br><b>#{name}</b></html>")
         
     | 
| 
      
 117 
     | 
    
         
            +
                    panel.add label
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
                  elements << element
         
     | 
| 
      
 120 
     | 
    
         
            +
                  panel.add element
         
     | 
| 
      
 121 
     | 
    
         
            +
                  has_label ? label : nil
         
     | 
| 
      
 122 
     | 
    
         
            +
                end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                def remove
         
     | 
| 
      
 125 
     | 
    
         
            +
                  remove_all
         
     | 
| 
      
 126 
     | 
    
         
            +
                  dispose
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                def slider(name, range = 0..100, initial_value = nil, &block)
         
     | 
| 
      
 130 
     | 
    
         
            +
                  Slider.new(self, name, range, initial_value, block || nil)
         
     | 
| 
      
 131 
     | 
    
         
            +
                end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                def menu(name, elements, initial_value = nil, &block)
         
     | 
| 
      
 134 
     | 
    
         
            +
                  Menu.new(self, name, elements, initial_value, block || nil)
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                def checkbox(name, initial_value = nil, &block)
         
     | 
| 
      
 138 
     | 
    
         
            +
                  checkbox = Checkbox.new(self, name, block || nil)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  checkbox.do_click if initial_value == true
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                def button(name, &block)
         
     | 
| 
      
 143 
     | 
    
         
            +
                  Button.new(self, name, block || nil)
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                def look_feel(lf)
         
     | 
| 
      
 147 
     | 
    
         
            +
                  set_feel(lf)
         
     | 
| 
      
 148 
     | 
    
         
            +
                end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                private
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                def set_feel(lf = 'metal')
         
     | 
| 
      
 153 
     | 
    
         
            +
                  lafinfo = javax.swing.UIManager.getInstalledLookAndFeels
         
     | 
| 
      
 154 
     | 
    
         
            +
                  laf = lafinfo.select do |info|
         
     | 
| 
      
 155 
     | 
    
         
            +
                    info.getName.eql? lf.capitalize
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
                  javax.swing.UIManager.setLookAndFeel(laf[0].getClassName)
         
     | 
| 
      
 158 
     | 
    
         
            +
                end
         
     | 
| 
      
 159 
     | 
    
         
            +
              end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
              # instance methods module
         
     | 
| 
      
 162 
     | 
    
         
            +
              module InstanceMethods
         
     | 
| 
      
 163 
     | 
    
         
            +
                def control_panel
         
     | 
| 
      
 164 
     | 
    
         
            +
                  @control_panel ||= ControlPanel::Panel.new
         
     | 
| 
      
 165 
     | 
    
         
            +
                  return @control_panel unless block_given?
         
     | 
| 
      
 166 
     | 
    
         
            +
                  yield(@control_panel)
         
     | 
| 
      
 167 
     | 
    
         
            +
                  @control_panel.display
         
     | 
| 
      
 168 
     | 
    
         
            +
                end
         
     | 
| 
      
 169 
     | 
    
         
            +
              end
         
     | 
| 
      
 170 
     | 
    
         
            +
            end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
            Propane::App.send :include, ControlPanel::InstanceMethods
         
     |