module SketchRunner

Runs a sketch and reloads it when related files change

Runs a sketch and reloads it when related files change

Runs a sketch and reloads it when related files change

Runs a sketch and reloads it when related files change

Constants

APPDATA_CHECK_FILE
APPDATA_ROOT
BIT_SIZE
CONFIG_MTIME
EXAMPLES_DEST_DIR
EXAMPLES_SRC_DIR
JRUBY_FILE
JRUBY_URL
LOAD_PATH
PACKAGE_ROOT
PLATFORM
PROCESSING_CORE_PATH
PROCESSING_DIR
PROCESSING_LIBS_PATH
PROCESSING_URL
PROCESSING_ZIP_DIR
PROCESSING_ZIP_FILE
SKETCH_FILE
SKETCH_LIBS_DIR
SKETCH_NAME
STARTUP_FILE
VERSION
WATCH_INTERVAL

Public Class Methods

sketch_instances() click to toggle source
# File lib/sketch_runner/runner.rb, line 11
def sketch_instances
  @sketch_instances ||= []
end
system_requests() click to toggle source
# File lib/sketch_runner/runner.rb, line 7
def system_requests
  @system_requests ||= []
end

Private Class Methods

download(url, file, proxy) click to toggle source
# File lib/sketch_runner/setup.rb, line 42
def self.download(url, file, proxy)
  print "download #{File.basename(url)} ... "

  FileUtils.mkdir_p(File.dirname(file))

  open(file, 'wb') do |output|
    begin
      open(
        url,
        proxy: proxy,
        allow_redirections: :safe,
        ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE
      ) do |data|
        output.write(data.read)
      end
    rescue StandardError
      puts "\nunable to download file -- #{url}"
      exit false
    end
  end

  puts 'done'
end
launch() click to toggle source
# File lib/sketch_runner/launch.rb, line 3
def self.launch
  jruby_opts = "-I#{LOAD_PATH}"
  jruby_args = "#{STARTUP_FILE} #{$PROGRAM_NAME} #{ARGV.join(' ')}"
  exec("java -jar #{JRUBY_FILE} #{jruby_opts} #{jruby_args}")
end
respond_to_request(request) click to toggle source
# File lib/sketch_runner/runner.rb, line 66
def self.respond_to_request(request)
  case request[:command]
  when :topmost
    sketch = request[:sketch]
    sketch.frame.set_always_on_top(true)

    return sketch.frame.is_always_on_top
  when :pos
    sketch = request[:sketch]
    pos_x, pos_y = request[:pos]
    sketch.frame.set_location(pos_x, pos_y)

    cur_pos = sketch.frame.get_location
    return cur_pos.x == pos_x && cur_pos.y == pos_y
  when :reload
    throw :break_loop
  end
end
restore_environment(initial_constants, initial_features) click to toggle source
# File lib/sketch_runner/runner.rb, line 86
def self.restore_environment(initial_constants, initial_features)
  sketch_instances.each do |sketch|
    sketch.frame.dispose
    sketch.dispose
  end

  sketch_instances.clear
  system_requests.clear

  added_constants = Object.constants - initial_constants
  added_constants.each do |constant|
    Object.class_eval { remove_const constant }
  end

  added_features = $LOADED_FEATURES - initial_features
  added_features.each { |feature| $LOADED_FEATURES.delete(feature) }

  java.lang.System.gc
end
run_sketch() click to toggle source
# File lib/sketch_runner/runner.rb, line 35
def self.run_sketch
  Thread.new do
    begin
      Object::TOPLEVEL_BINDING.eval(File.read(SKETCH_FILE), SKETCH_FILE)
    rescue Exception => e
      puts e
    end
  end
end
setup() click to toggle source
# File lib/sketch_runner/setup.rb, line 8
def self.setup
  puts "Processing.rb #{VERSION}"

  return if File.exist?(APPDATA_CHECK_FILE) &&
            File.stat(APPDATA_CHECK_FILE).mtime > CONFIG_MTIME

  FileUtils.remove_dir(APPDATA_ROOT, true)

  puts 'JRuby and Processing will be downloaded just one time.'
  puts 'Please input a proxy if necessary, otherwise just press Enter.'
  print '(e.g. http://proxy.hostname:port): '
  proxy = $stdin.gets.chomp
  proxy = nil if proxy == ''

  download(JRUBY_URL, JRUBY_FILE, proxy)

  download(PROCESSING_URL, PROCESSING_ZIP_FILE, proxy)
  unzip(PROCESSING_ZIP_FILE, PROCESSING_ZIP_DIR)

  FileUtils.mkdir_p(PROCESSING_DIR)
  processing_core_dir = File.join(PROCESSING_ZIP_DIR, PROCESSING_CORE_PATH)
  FileUtils.cp_r(processing_core_dir, PROCESSING_DIR)

  processing_libs_dir = File.join(PROCESSING_ZIP_DIR, PROCESSING_LIBS_PATH)
  Dir.glob(File.join(processing_libs_dir, '*')).each do |dir|
    FileUtils.cp_r(dir, PROCESSING_DIR)
  end

  FileUtils.remove_dir(PROCESSING_ZIP_DIR, true)

  FileUtils.touch(APPDATA_CHECK_FILE)
end
start() click to toggle source
# File lib/sketch_runner/runner.rb, line 16
def self.start
  $PROGRAM_NAME = ARGV.shift

  jars = File.join(PROCESSING_DIR, 'core/library/*.jar')
  Dir.glob(jars).each { |jar| require jar }

  initial_constants = Object.constants
  initial_features = $LOADED_FEATURES.dup

  loop do
    puts '****** START SKETCH ******'

    run_sketch
    watch_file_changes
    restore_environment(initial_constants, initial_features)
  end
end
unzip(file, dest_dir) click to toggle source
# File lib/sketch_runner/setup.rb, line 67
def self.unzip(file, dest_dir)
  print "unzip #{File.basename(file)} ... "

  Zip::File.open(file) do |zip|
    zip.each do |entry|
      dest_file = File.join(dest_dir, entry.name)

      unless File.basename(dest_file).start_with?('._')
        entry.extract(dest_file)
      end
    end
  end

  puts 'done'
end
watch_file_changes() click to toggle source
# File lib/sketch_runner/runner.rb, line 46
def self.watch_file_changes
  execute_time = Time.now

  catch :break_loop do
    loop do
      system_requests.each do |request|
        system_requests.delete(request) if respond_to_request(request)
      end

      Find.find(SKETCH_DIR) do |file|
        is_ruby = FileTest.file?(file) && File.extname(file) == '.rb'
        throw :break_loop if is_ruby && File.mtime(file) > execute_time
      end

      sleep(WATCH_INTERVAL)
    end
  end
end