Class: Processing::App

Inherits:
PApplet
  • Object
show all
Includes:
Math
Defined in:
lib/ruby-processing/app.rb

Overview

This is the main Ruby-Processing class, and is what you’ll inherit from when you create a sketch. This class can call all of the methods available in Processing, and has two mandatory methods, ‘setup’ and ‘draw’, both of which you should define in your sketch. ‘setup’ will be called one time when the sketch is first loaded, and ‘draw’ will be called constantly, for every frame.

Constant Summary collapse

METHODS_TO_WATCH_FOR =

Watch the definition of these methods, to make sure that Processing is able to call them during events.

{
  :mouse_pressed  => :mousePressed,
  :mouse_dragged  => :mouseDragged,
  :mouse_clicked  => :mouseClicked,
  :mouse_moved    => :mouseMoved,
  :mouse_released => :mouseReleased,
  :key_pressed    => :keyPressed,
  :key_released   => :keyReleased,
  :key_typed      => :keyTyped
}
@@loaded_libraries =

Detect if a library has been loaded (for conditional loading)

Hash.new(false)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ App

When you make a new sketch, you pass in (optionally), a width, height, x, y, title, and whether or not you want to run in full-screen.

This is a little different than Processing where height and width are declared inside the setup method instead.



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/ruby-processing/app.rb', line 167

def initialize(options={})
  super()
  $app = self
  proxy_java_fields
  set_sketch_path unless Processing.online?
  # make_accessible_to_the_browser if Processing.online?
  default_title = File.basename(SKETCH_PATH).sub(/(\.rb|\.pde)$/, '').titleize
  @width        = options[:width]
  @height       = options[:height]
  @frame_x      = options[:x]     || 0
  @frame_y      = options[:y]     || 0
  @title        = options[:title] ||  default_title
  @render_mode                    ||= JAVA2D
  @@full_screen                   ||= options[:full_screen]
  self.init
  determine_how_to_display
end

Instance Attribute Details

#frameObject

Alias some methods for familiarity for Shoes coders.



29
30
31
# File 'lib/ruby-processing/app.rb', line 29

def frame
  @frame
end

#titleObject

Alias some methods for familiarity for Shoes coders.



29
30
31
# File 'lib/ruby-processing/app.rb', line 29

def title
  @title
end

Class Method Details

.full_screenObject



72
# File 'lib/ruby-processing/app.rb', line 72

def self.full_screen;   @@full_screen = true; end

.has_slider(*args) ⇒ Object

:nodoc:



156
157
158
# File 'lib/ruby-processing/app.rb', line 156

def self.has_slider(*args) #:nodoc:
  raise "has_slider has been replaced with a nicer control_panel library. Check it out."
end

.inherited(subclass) ⇒ Object

Keep track of what inherits from the Processing::App, because we’re going to want to instantiate one.



78
79
80
81
# File 'lib/ruby-processing/app.rb', line 78

def self.inherited(subclass)
  super(subclass)
  @sketch_class = subclass
end

.library_loaded?(folder) ⇒ Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/ruby-processing/app.rb', line 86

def self.library_loaded?(folder)
  @@loaded_libraries[folder.to_sym]
end

.load_java_library(dir) ⇒ Object

For pure java libraries, such as the ones that are available on this page: processing.org/reference/libraries/index.html

P.S. – Loading libraries which include native code needs to hack the Java ClassLoader, so that you don’t have to futz with your PATH. But it’s probably bad juju.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/ruby-processing/app.rb', line 133

def self.load_java_library(dir)
  dir = dir.to_sym
  return true if @@loaded_libraries[dir]
  return @@loaded_libraries[dir] = !!(JRUBY_APPLET.get_parameter("archive").match(%r(#{dir}))) if Processing.online?
  local_path = "#{SKETCH_ROOT}/library/#{dir}"
  gem_path = "#{RP5_ROOT}/library/#{dir}"
  path = File.exists?(local_path) ? local_path : gem_path
  jars = Dir["#{path}/**/*.jar"]
  return false if jars.empty?
  jars.each {|jar| require jar }
  # Here goes...
  library_path = java.lang.System.getProperty("java.library.path")
  new_library_path = [path, "#{path}/library", library_path].join(java.io.File.pathSeparator)
  java.lang.System.setProperty("java.library.path", new_library_path)
  field = java.lang.Class.for_name("java.lang.ClassLoader").get_declared_field("sys_paths")
  if field
    field.accessible = true
    field.set(java.lang.Class.for_name("java.lang.System").get_class_loader, nil)
  end
  return @@loaded_libraries[dir] = true
end

.load_libraries(*args) ⇒ Object

Load a list of Ruby or Java libraries (in that order) Usage: load_libraries :opengl, :boids

If a library is put into a ‘library’ folder next to the sketch it will be used instead of the library that ships with Ruby-Processing.



97
98
99
100
101
102
# File 'lib/ruby-processing/app.rb', line 97

def self.load_libraries(*args)
  args.each do |lib|
    loaded = load_ruby_library(lib) || load_java_library(lib)
    raise LoadError.new "no such file to load -- #{lib}" if !loaded
  end
end

.load_library(*args) ⇒ Object



103
# File 'lib/ruby-processing/app.rb', line 103

def self.load_library(*args); self.load_libraries(*args); end

.load_ruby_library(dir) ⇒ Object

For pure ruby libraries. The library should have an initialization ruby file of the same name as the library folder.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/ruby-processing/app.rb', line 109

def self.load_ruby_library(dir)
  dir = dir.to_sym
  return true if @@loaded_libraries[dir]
  if Processing.online?
    begin
      return @@loaded_libraries[dir] = (require "library/#{dir}/#{dir}")
    rescue LoadError => e
      return false
    end
  end
  local_path = "#{SKETCH_ROOT}/library/#{dir}"
  gem_path = "#{RP5_ROOT}/library/#{dir}"
  path = File.exists?(local_path) ? local_path : gem_path
  return false unless (File.exists?("#{path}/#{dir}.rb"))
  return @@loaded_libraries[dir] = (require "#{path}/#{dir}")
end

.method_added(method_name) ⇒ Object

When certain special methods get added to the sketch, we need to let Processing call them by their expected Java names.



51
52
53
54
55
# File 'lib/ruby-processing/app.rb', line 51

def self.method_added(method_name) #:nodoc:
  if METHODS_TO_WATCH_FOR.keys.include?(method_name)
    alias_method METHODS_TO_WATCH_FOR[method_name], method_name
  end
end

.sketch_classObject

Handy getters and setters on the class go here:



71
# File 'lib/ruby-processing/app.rb', line 71

def self.sketch_class;  @sketch_class;        end

Instance Method Details

#buffer(buf_width = width, buf_height = height, renderer = @render_mode) {|buf| ... } ⇒ Object

Nice block method to draw to a buffer. You can optionally pass it a width, a height, and a renderer. Takes care of starting and ending the draw for you.

Yields:

  • (buf)


238
239
240
241
242
243
244
# File 'lib/ruby-processing/app.rb', line 238

def buffer(buf_width=width, buf_height=height, renderer=@render_mode)
  buf = create_graphics(buf_width, buf_height, renderer)
  buf.begin_draw
  yield buf
  buf.end_draw
  buf
end

#closeObject

Cleanly close and shutter a running sketch.



352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/ruby-processing/app.rb', line 352

def close
  $app = nil
  if Processing.online?
    JRUBY_APPLET.remove(self)
    self.destroy
  else
    control_panel.remove if respond_to?(:control_panel)
    @frame.remove(self) if @frame
    self.destroy
    @frame.dispose if @frame
  end
end

#default_size?Boolean

Is the sketch still displaying with the default size?

Returns:

  • (Boolean)


321
322
323
# File 'lib/ruby-processing/app.rb', line 321

def default_size?
  @declared_fields['defaultSize'].value(java_self)
end

#find_method(method_name) ⇒ Object

There’s just so many functions in Processing, Here’s a convenient way to look for them.



229
230
231
232
# File 'lib/ruby-processing/app.rb', line 229

def find_method(method_name)
  reg = Regexp.new("#{method_name}", true)
  self.methods.sort.select {|meth| reg.match(meth)}
end

#finished?Boolean

Is the sketch finished?

Returns:

  • (Boolean)


327
328
329
# File 'lib/ruby-processing/app.rb', line 327

def finished?
  @declared_fields['finished'].value(java_self)
end

#frame_countObject



295
# File 'lib/ruby-processing/app.rb', line 295

def frame_count;  frameCount;   end

#frame_rate(fps = nil) ⇒ Object

frame_rate needs to support reading and writing



314
315
316
317
# File 'lib/ruby-processing/app.rb', line 314

def frame_rate(fps = nil)
  return @declared_fields['frameRate'].value(java_self) unless fps
  super(fps)
end

#full_screen?Boolean

Returns:

  • (Boolean)


73
# File 'lib/ruby-processing/app.rb', line 73

def full_screen?;       @@full_screen;        end

#grid(cols, rows, col_size = 1, row_size = 1) ⇒ Object

A nice method to run a given block for a grid. Lifted from action_coding/Nodebox.



249
250
251
252
253
254
255
# File 'lib/ruby-processing/app.rb', line 249

def grid(cols, rows, col_size=1, row_size=1)
  (0...cols*rows).map do |i|
    x = col_size * (i % cols)
    y = row_size * i.div(cols)
    yield x, y
  end
end

#hex(value) ⇒ Object

From ROP. Turns a color hash-string into hexadecimal, for Processing.



285
286
287
# File 'lib/ruby-processing/app.rb', line 285

def hex(value)
  value[1..-1].hex + 0xff000000
end

#inspectObject

Provide a loggable string to represent this sketch.



195
196
197
# File 'lib/ruby-processing/app.rb', line 195

def inspect
  "#<Processing::App:#{self.class}:#{@title}>"
end

#java_selfObject

Provide a convenient handle for the Java-space version of self.



265
266
267
# File 'lib/ruby-processing/app.rb', line 265

def java_self
  @java_self ||= Java.ruby_to_java self
end

#keyObject

Fix java conversion problems getting the last key If it’s ASCII, return the character, otherwise the integer



272
273
274
275
# File 'lib/ruby-processing/app.rb', line 272

def key
  int = @declared_fields['key'].value(java_self)
  int < 256 ? int.chr : int
end

#key_codeObject



297
# File 'lib/ruby-processing/app.rb', line 297

def key_code;     keyCode;      end

#key_pressed?Boolean

Is a key pressed for this frame?

Returns:

  • (Boolean)


339
340
341
# File 'lib/ruby-processing/app.rb', line 339

def key_pressed?
  Java.java_to_primitive(java_class.field("keyPressed").value(java_object))
end

#lerp_color(*args) ⇒ Object

lerp_color takes three or four arguments, in Java that’s two different methods, one regular and one static, so:



346
347
348
# File 'lib/ruby-processing/app.rb', line 346

def lerp_color(*args)
  args.length > 3 ? self.class.lerp_color(*args) : super(*args)
end

#library_loaded?(folder) ⇒ Boolean

Returns:

  • (Boolean)


89
# File 'lib/ruby-processing/app.rb', line 89

def library_loaded?(folder); self.class.library_loaded?(folder); end

#load_strings(file_or_url) ⇒ Object

Ensure that load_strings returns a real Ruby array



301
302
303
# File 'lib/ruby-processing/app.rb', line 301

def load_strings(file_or_url)
  loadStrings(file_or_url).to_a
end

#mouse_buttonObject



296
# File 'lib/ruby-processing/app.rb', line 296

def mouse_button; mouseButton;  end

#mouse_pressed?Boolean

Is the mouse pressed for this frame?

Returns:

  • (Boolean)


333
334
335
# File 'lib/ruby-processing/app.rb', line 333

def mouse_pressed?
  Java.java_to_primitive(java_class.field("mousePressed").value(java_object))
end

#mouse_xObject

Fields that should be made accessible as under_scored.



291
# File 'lib/ruby-processing/app.rb', line 291

def mouse_x;      mouseX;       end

#mouse_yObject



292
# File 'lib/ruby-processing/app.rb', line 292

def mouse_y;      mouseY;       end

#pmouse_xObject



293
# File 'lib/ruby-processing/app.rb', line 293

def pmouse_x;     pmouseX;      end

#pmouse_yObject



294
# File 'lib/ruby-processing/app.rb', line 294

def pmouse_y;     pmouseY;      end

#render_mode(mode_const) ⇒ Object

Specify what rendering Processing should use, without needing to pass size.



221
222
223
224
# File 'lib/ruby-processing/app.rb', line 221

def render_mode(mode_const)
  @render_mode = mode_const
  size(@width, @height, @render_mode)
end

#save_strings(filename, strings) ⇒ Object

Writes an array of strings to a file, one line per string. This file is saved to the sketch’s data folder



308
309
310
# File 'lib/ruby-processing/app.rb', line 308

def save_strings(filename, strings)
  saveStrings(filename, [strings].flatten.to_java(:String))
end

#set_sketch_path(path = nil) ⇒ Object

By default, your sketch path is the folder that your sketch is in. If you’d like to do something fancy, feel free.



202
203
204
205
# File 'lib/ruby-processing/app.rb', line 202

def set_sketch_path(path=nil)
  field = @declared_fields['sketchPath']
  field.set_value(java_self, path || SKETCH_ROOT)
end

#shape(*mode) ⇒ Object

Shortcut for begin_shape/end_shape pair



258
259
260
261
262
# File 'lib/ruby-processing/app.rb', line 258

def shape(*mode)
  begin_shape *mode
  yield
  end_shape
end

#size(*args) ⇒ Object

We override size to support setting full_screen and to keep our internal @width and @height in line.



210
211
212
213
214
215
216
217
# File 'lib/ruby-processing/app.rb', line 210

def size(*args)
  args[0], args[1] = *full_screen_dimensions if @@full_screen && !args.empty?
  w, h, mode       = *args
  @width           = w     || @width
  @height          = h     || @height
  @render_mode     = mode  || @render_mode
  super(*args)
end

#sketch_pathObject

Get the sketch path



279
280
281
# File 'lib/ruby-processing/app.rb', line 279

def sketch_path
  @declared_fields['sketchPath'].value(java_self)
end

#startObject

Make sure we set the size if we set it before we start the animation thread.



187
188
189
190
191
# File 'lib/ruby-processing/app.rb', line 187

def start
  self.size(@width, @height) if @width && @height
  mix_proxy_into_inner_classes
  super()
end