1
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
4
Part of the Processing project - http://processing.org
6
Copyright (c) 2004-09 Ben Fry and Casey Reas
7
Copyright (c) 2001-04 Massachusetts Institute of Technology
9
This library is free software; you can redistribute it and/or
10
modify it under the terms of the GNU Lesser General Public
11
License as published by the Free Software Foundation, version 2.1.
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.
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
24
package processing.core;
28
import java.awt.event.*;
29
import java.awt.image.*;
31
import java.lang.reflect.*;
35
import java.util.regex.*;
36
import java.util.zip.*;
38
import javax.imageio.ImageIO;
39
import javax.swing.JFileChooser;
40
import javax.swing.SwingUtilities;
44
* Base class for all sketches that use processing.core.
46
* Note that you should not use AWT or Swing components inside a Processing
47
* applet. The surface is made to automatically update itself, and will cause
48
* problems with redraw of components drawn above it. If you'd like to
49
* integrate other Java components, see below.
51
* As of release 0145, Processing uses active mode rendering in all cases.
52
* All animation tasks happen on the "Processing Animation Thread". The
53
* setup() and draw() methods are handled by that thread, and events (like
54
* mouse movement and key presses, which are fired by the event dispatch
55
* thread or EDT) are queued to be (safely) handled at the end of draw().
56
* For code that needs to run on the EDT, use SwingUtilities.invokeLater().
57
* When doing so, be careful to synchronize between that code (since
58
* invokeLater() will make your code run from the EDT) and the Processing
59
* animation thread. Use of a callback function or the registerXxx() methods
60
* in PApplet can help ensure that your code doesn't do something naughty.
62
* As of release 0136 of Processing, we have discontinued support for versions
63
* of Java prior to 1.5. We don't have enough people to support it, and for a
64
* project of our size, we should be focusing on the future, rather than
65
* working around legacy Java code. In addition, Java 1.5 gives us access to
66
* better timing facilities which will improve the steadiness of animation.
68
* This class extends Applet instead of JApplet because 1) historically,
69
* we supported Java 1.1, which does not include Swing (without an
70
* additional, sizable, download), and 2) Swing is a bloated piece of crap.
71
* A Processing applet is a heavyweight AWT component, and can be used the
72
* same as any other AWT component, with or without Swing.
74
* Similarly, Processing runs in a Frame and not a JFrame. However, there's
75
* nothing to prevent you from embedding a PApplet into a JFrame, it's just
76
* that the base version uses a regular AWT frame because there's simply
77
* no need for swing in that context. If people want to use Swing, they can
78
* embed themselves as they wish.
80
* It is possible to use PApplet, along with core.jar in other projects.
81
* In addition to enabling you to use Java 1.5+ features with your sketch,
82
* this also allows you to embed a Processing drawing area into another Java
83
* application. This means you can use standard GUI controls with a Processing
84
* sketch. Because AWT and Swing GUI components cannot be used on top of a
85
* PApplet, you can instead embed the PApplet inside another GUI the way you
86
* would any other Component.
88
* It is also possible to resize the Processing window by including
89
* <tt>frame.setResizable(true)</tt> inside your <tt>setup()</tt> method.
90
* Note that the Java method <tt>frame.setSize()</tt> will not work unless
91
* you first set the frame to be resizable.
93
* Because the default animation thread will run at 60 frames per second,
94
* an embedded PApplet can make the parent sluggish. You can use frameRate()
95
* to make it update less often, or you can use noLoop() and loop() to disable
96
* and then re-enable looping. If you want to only update the sketch
97
* intermittently, use noLoop() inside setup(), and redraw() whenever
98
* the screen needs to be updated once (or loop() to re-enable the animation
99
* thread). The following example embeds a sketch and also uses the noLoop()
100
* and redraw() methods. You need not use noLoop() and redraw() when embedding
101
* if you want your application to animate continuously.
103
* public class ExampleFrame extends Frame {
105
* public ExampleFrame() {
106
* super("Embedded PApplet");
108
* setLayout(new BorderLayout());
109
* PApplet embed = new Embedded();
110
* add(embed, BorderLayout.CENTER);
112
* // important to call this whenever embedding a PApplet.
113
* // It ensures that the animation thread is started and
114
* // that other internal variables are properly set.
119
* public class Embedded extends PApplet {
121
* public void setup() {
122
* // original setup code here ...
125
* // prevent thread from starving everything else
129
* public void draw() {
130
* // drawing code goes here
133
* public void mousePressed() {
134
* // do something based on mouse movement
136
* // update the screen (run draw once)
142
* <H2>Processing on multiple displays</H2>
143
* <P>I was asked about Processing with multiple displays, and for lack of a
144
* better place to document it, things will go here.</P>
145
* <P>You can address both screens by making a window the width of both,
146
* and the height of the maximum of both screens. In this case, do not use
147
* present mode, because that's exclusive to one screen. Basically it'll
148
* give you a PApplet that spans both screens. If using one half to control
149
* and the other half for graphics, you'd just have to put the 'live' stuff
150
* on one half of the canvas, the control stuff on the other. This works
151
* better in windows because on the mac we can't get rid of the menu bar
152
* unless it's running in present mode.</P>
153
* <P>For more control, you need to write straight java code that uses p5.
154
* You can create two windows, that are shown on two separate screens,
155
* that have their own PApplet. this is just one of the tradeoffs of one of
156
* the things that we don't support in p5 from within the environment
157
* itself (we must draw the line somewhere), because of how messy it would
158
* get to start talking about multiple screens. It's also not that tough to
159
* do by hand w/ some Java code.</P>
161
public class PApplet extends Applet
162
implements PConstants, Runnable,
163
MouseListener, MouseMotionListener, KeyListener, FocusListener
166
* Full name of the Java version (i.e. 1.5.0_11).
167
* Prior to 0125, this was only the first three digits.
169
public static final String javaVersionName =
170
System.getProperty("java.version");
173
* Version of Java that's in use, whether 1.1 or 1.3 or whatever,
176
* Note that because this is stored as a float, the values may
177
* not be <EM>exactly</EM> 1.3 or 1.4. Instead, make sure you're
178
* comparing against 1.3f or 1.4f, which will have the same amount
179
* of error (i.e. 1.40000001). This could just be a double, but
180
* since Processing only uses floats, it's safer for this to be a float
181
* because there's no good way to specify a double with the preproc.
183
public static final float javaVersion =
184
new Float(javaVersionName.substring(0, 3)).floatValue();
187
* Current platform in use.
189
* Equivalent to System.getProperty("os.name"), just used internally.
193
* Current platform in use, one of the
194
* PConstants WINDOWS, MACOSX, MACOS9, LINUX or OTHER.
196
static public int platform;
199
* Name associated with the current 'platform' (see PConstants.platformNames)
201
//static public String platformName;
204
String osname = System.getProperty("os.name");
206
if (osname.indexOf("Mac") != -1) {
209
} else if (osname.indexOf("Windows") != -1) {
212
} else if (osname.equals("Linux")) { // true for the ibm vm
221
* Modifier flags for the shortcut key used to trigger menus.
222
* (Cmd on Mac OS X, Ctrl on Linux and Windows)
224
static public final int MENU_SHORTCUT =
225
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
227
/** The PGraphics renderer associated with this PApplet */
230
//protected Object glock = new Object(); // for sync
232
/** The frame containing this applet (if any) */
236
* The screen size when the applet was started.
238
* Access this via screen.width and screen.height. To make an applet
239
* run at full screen, use size(screen.width, screen.height).
241
* If you have multiple displays, this will be the size of the main
242
* display. Running full screen across multiple displays isn't
243
* particularly supported, and requires more monkeying with the values.
244
* This probably can't/won't be fixed until/unless I get a dual head
247
* Note that this won't update if you change the resolution
248
* of your screen once the the applet is running.
250
* This variable is not static, because future releases need to be better
251
* at handling multiple displays.
253
public Dimension screen =
254
Toolkit.getDefaultToolkit().getScreenSize();
257
* A leech graphics object that is echoing all events.
259
public PGraphics recorder;
262
* Command line options passed in from main().
264
* This does not include the arguments passed in to PApplet itself.
266
public String args[];
268
/** Path to sketch folder */
269
public String sketchPath; //folder;
271
/** When debugging headaches */
272
static final boolean THREAD_DEBUG = false;
274
/** Default width and height for applet when not specified */
275
static public final int DEFAULT_WIDTH = 100;
276
static public final int DEFAULT_HEIGHT = 100;
279
* Minimum dimensions for the window holding an applet.
280
* This varies between platforms, Mac OS X 10.3 can do any height
281
* but requires at least 128 pixels width. Windows XP has another
282
* set of limitations. And for all I know, Linux probably lets you
283
* make windows with negative sizes.
285
static public final int MIN_WINDOW_WIDTH = 128;
286
static public final int MIN_WINDOW_HEIGHT = 128;
289
* Exception thrown when size() is called the first time.
291
* This is used internally so that setup() is forced to run twice
292
* when the renderer is changed. This is the only way for us to handle
293
* invoking the new renderer while also in the midst of rendering.
295
static public class RendererChangeException extends RuntimeException { }
298
* true if no size() command has been executed. This is used to wait until
299
* a size has been set before placing in the window and showing it.
301
public boolean defaultSize;
303
volatile boolean resizeRequest;
304
volatile int resizeWidth;
305
volatile int resizeHeight;
308
* Pixel buffer from this applet's PGraphics.
310
* When used with OpenGL or Java2D, this value will
311
* be null until loadPixels() has been called.
315
/** width of this applet's associated PGraphics */
318
/** height of this applet's associated PGraphics */
321
/** current x position of the mouse */
324
/** current y position of the mouse */
328
* Previous x/y position of the mouse. This will be a different value
329
* when inside a mouse handler (like the mouseMoved() method) versus
330
* when inside draw(). Inside draw(), pmouseX is updated once each
331
* frame, but inside mousePressed() and friends, it's updated each time
332
* an event comes through. Be sure to use only one or the other type of
333
* means for tracking pmouseX and pmouseY within your sketch, otherwise
334
* you're gonna run into trouble.
336
public int pmouseX, pmouseY;
339
* previous mouseX/Y for the draw loop, separated out because this is
340
* separate from the pmouseX/Y when inside the mouse event handlers.
342
protected int dmouseX, dmouseY;
345
* pmouseX/Y for the event handlers (mousePressed(), mouseDragged() etc)
346
* these are different because mouse events are queued to the end of
347
* draw, so the previous position has to be updated on each event,
348
* as opposed to the pmouseX/Y that's used inside draw, which is expected
349
* to be updated once per trip through draw().
351
protected int emouseX, emouseY;
354
* Used to set pmouseX/Y to mouseX/Y the first time mouseX/Y are used,
355
* otherwise pmouseX/Y are always zero, causing a nasty jump.
357
* Just using (frameCount == 0) won't work since mouseXxxxx()
358
* may not be called until a couple frames into things.
360
public boolean firstMouse;
363
* Last mouse button pressed, one of LEFT, CENTER, or RIGHT.
365
* If running on Mac OS, a ctrl-click will be interpreted as
366
* the righthand mouse button (unlike Java, which reports it as
369
public int mouseButton;
371
public boolean mousePressed;
372
public MouseEvent mouseEvent;
377
* If it's a coded key, i.e. UP/DOWN/CTRL/SHIFT/ALT,
378
* this will be set to CODED (0xffff or 65535).
383
* When "key" is set to CODED, this will contain a Java key code.
385
* For the arrow keys, keyCode will be one of UP, DOWN, LEFT and RIGHT.
386
* Also available are ALT, CONTROL and SHIFT. A full set of constants
387
* can be obtained from java.awt.event.KeyEvent, from the VK_XXXX variables.
392
* true if the mouse is currently pressed.
394
public boolean keyPressed;
397
* the last KeyEvent object passed into a mouse function.
399
public KeyEvent keyEvent;
402
* Gets set to true/false as the applet gains/loses focus.
404
public boolean focused = false;
407
* true if the applet is online.
409
* This can be used to test how the applet should behave
410
* since online situations are different (no file writing, etc).
412
public boolean online = false;
415
* Time in milliseconds when the applet was started.
417
* Used by the millis() function.
422
* The current value of frames per second.
424
* The initial value will be 10 fps, and will be updated with each
425
* frame thereafter. The value is not instantaneous (since that
426
* wouldn't be very useful since it would jump around so much),
427
* but is instead averaged (integrated) over several frames.
428
* As such, this value won't be valid until after 5-10 frames.
430
public float frameRate = 10;
431
/** Last time in nanoseconds that frameRate was checked */
432
protected long frameRateLastNanos = 0;
434
/** As of release 0116, frameRate(60) is called as a default */
435
protected float frameRateTarget = 60;
436
protected long frameRatePeriod = 1000000000L / 60L;
438
protected boolean looping;
440
/** flag set to true when a redraw is asked for by the user */
441
protected boolean redraw;
444
* How many frames have been displayed since the applet started.
446
* This value is read-only <EM>do not</EM> attempt to set it,
447
* otherwise bad things will happen.
449
* Inside setup(), frameCount is 0.
450
* For the first iteration of draw(), frameCount will equal 1.
452
public int frameCount;
455
* true if this applet has had it.
457
public boolean finished;
460
* true if exit() has been called so that things shut down
461
* once the main thread kicks off.
463
protected boolean exitCalled;
467
protected RegisteredMethods sizeMethods;
468
protected RegisteredMethods preMethods, drawMethods, postMethods;
469
protected RegisteredMethods mouseEventMethods, keyEventMethods;
470
protected RegisteredMethods disposeMethods;
472
// messages to send if attached as an external vm
475
* Position of the upper-lefthand corner of the editor window
476
* that launched this applet.
478
static public final String ARGS_EDITOR_LOCATION = "--editor-location";
481
* Location for where to position the applet window on screen.
483
* This is used by the editor to when saving the previous applet
484
* location, or could be used by other classes to launch at a
485
* specific position on-screen.
487
static public final String ARGS_EXTERNAL = "--external";
489
static public final String ARGS_LOCATION = "--location";
491
static public final String ARGS_DISPLAY = "--display";
493
static public final String ARGS_BGCOLOR = "--bgcolor";
495
static public final String ARGS_PRESENT = "--present";
497
static public final String ARGS_EXCLUSIVE = "--exclusive";
499
static public final String ARGS_STOP_COLOR = "--stop-color";
501
static public final String ARGS_HIDE_STOP = "--hide-stop";
504
* Allows the user or PdeEditor to set a specific sketch folder path.
506
* Used by PdeEditor to pass in the location where saveFrame()
507
* and all that stuff should write things.
509
static public final String ARGS_SKETCH_FOLDER = "--sketch-path";
512
* When run externally to a PdeEditor,
513
* this is sent by the applet when it quits.
515
//static public final String EXTERNAL_QUIT = "__QUIT__";
516
static public final String EXTERNAL_STOP = "__STOP__";
519
* When run externally to a PDE Editor, this is sent by the applet
520
* whenever the window is moved.
522
* This is used so that the editor can re-open the sketch window
523
* in the same position as the user last left it.
525
static public final String EXTERNAL_MOVE = "__MOVE__";
527
/** true if this sketch is being run by the PDE */
528
boolean external = false;
531
static final String ERROR_MIN_MAX =
532
"Cannot use min() or max() on an empty array.";
535
// during rev 0100 dev cycle, working on new threading model,
536
// but need to disable and go conservative with changes in order
537
// to get pdf and audio working properly first.
538
// for 0116, the CRUSTY_THREADS are being disabled to fix lots of bugs.
539
//static final boolean CRUSTY_THREADS = false; //true;
543
// println("Calling init()");
545
// send tab keys through to the PApplet
546
setFocusTraversalKeysEnabled(false);
548
millisOffset = System.currentTimeMillis();
550
finished = false; // just for clarity
552
// this will be cleared by draw() if it is not overridden
554
redraw = true; // draw this guy once
557
// these need to be inited before setup
558
sizeMethods = new RegisteredMethods();
559
preMethods = new RegisteredMethods();
560
drawMethods = new RegisteredMethods();
561
postMethods = new RegisteredMethods();
562
mouseEventMethods = new RegisteredMethods();
563
keyEventMethods = new RegisteredMethods();
564
disposeMethods = new RegisteredMethods();
569
} catch (NullPointerException e) {
574
if (sketchPath == null) {
575
sketchPath = System.getProperty("user.dir");
577
} catch (Exception e) { } // may be a security problem
579
Dimension size = getSize();
580
if ((size.width != 0) && (size.height != 0)) {
581
// When this PApplet is embedded inside a Java application with other
582
// Component objects, its size() may already be set externally (perhaps
583
// by a LayoutManager). In this case, honor that size as the default.
584
// Size of the component is set, just create a renderer.
585
g = makeGraphics(size.width, size.height, getSketchRenderer(), null, true);
586
// This doesn't call setSize() or setPreferredSize() because the fact
587
// that a size was already set means that someone is already doing it.
590
// Set the default size, until the user specifies otherwise
591
this.defaultSize = true;
592
int w = getSketchWidth();
593
int h = getSketchHeight();
594
g = makeGraphics(w, h, getSketchRenderer(), null, true);
595
// Fire component resize event
597
setPreferredSize(new Dimension(w, h));
604
// this is automatically called in applets
605
// though it's here for applications anyway
610
public int getSketchWidth() {
611
return DEFAULT_WIDTH;
615
public int getSketchHeight() {
616
return DEFAULT_HEIGHT;
620
public String getSketchRenderer() {
626
* Called by the browser or applet viewer to inform this applet that it
627
* should start its execution. It is called after the init method and
628
* each time the applet is revisited in a Web page.
630
* Called explicitly via the first call to PApplet.paint(), because
631
* PAppletGL needs to have a usable screen before getting things rolling.
633
public void start() {
634
// When running inside a browser, start() will be called when someone
635
// returns to a page containing this applet.
636
// http://dev.processing.org/bugs/show_bug.cgi?id=581
639
if (thread != null) return;
640
thread = new Thread(this, "Animation Thread");
646
* Called by the browser or applet viewer to inform
647
* this applet that it should stop its execution.
649
* Unfortunately, there are no guarantees from the Java spec
650
* when or if stop() will be called (i.e. on browser quit,
651
* or when moving between web pages), and it's not always called.
654
// bringing this back for 0111, hoping it'll help opengl shutdown
655
finished = true; // why did i comment this out?
657
// don't run stop and disposers twice
658
if (thread == null) return;
661
// call to shut down renderer, in case it needs it (pdf does)
662
if (g != null) g.dispose();
664
// maybe this should be done earlier? might help ensure it gets called
665
// before the vm just craps out since 1.5 craps out so aggressively.
666
disposeMethods.handle();
671
* Called by the browser or applet viewer to inform this applet
672
* that it is being reclaimed and that it should destroy
673
* any resources that it has allocated.
675
* This also attempts to call PApplet.stop(), in case there
676
* was an inadvertent override of the stop() function by a user.
678
* destroy() supposedly gets called as the applet viewer
679
* is shutting down the applet. stop() is called
680
* first, and then destroy() to really get rid of things.
681
* no guarantees on when they're run (on browser quit, or
682
* when moving between pages), though.
684
public void destroy() {
685
((PApplet)this).stop();
690
* This returns the last width and height specified by the user
691
* via the size() command.
693
// public Dimension getPreferredSize() {
694
// return new Dimension(width, height);
698
// public void addNotify() {
699
// super.addNotify();
700
// println("addNotify()");
705
//////////////////////////////////////////////////////////////
708
public class RegisteredMethods {
714
// convenience version for no args
715
public void handle() {
716
handle(new Object[] { });
719
public void handle(Object oargs[]) {
720
for (int i = 0; i < count; i++) {
722
//System.out.println(objects[i] + " " + args);
723
methods[i].invoke(objects[i], oargs);
724
} catch (Exception e) {
730
public void add(Object object, Method method) {
731
if (objects == null) {
732
objects = new Object[5];
733
methods = new Method[5];
735
if (count == objects.length) {
736
objects = (Object[]) PApplet.expand(objects);
737
methods = (Method[]) PApplet.expand(methods);
738
// Object otemp[] = new Object[count << 1];
739
// System.arraycopy(objects, 0, otemp, 0, count);
741
// Method mtemp[] = new Method[count << 1];
742
// System.arraycopy(methods, 0, mtemp, 0, count);
745
objects[count] = object;
746
methods[count] = method;
752
* Removes first object/method pair matched (and only the first,
753
* must be called multiple times if object is registered multiple times).
754
* Does not shrink array afterwards, silently returns if method not found.
756
public void remove(Object object, Method method) {
757
int index = findIndex(object, method);
759
// shift remaining methods by one to preserve ordering
761
for (int i = index; i < count; i++) {
762
objects[i] = objects[i+1];
763
methods[i] = methods[i+1];
765
// clean things out for the gc's sake
766
objects[count] = null;
767
methods[count] = null;
771
protected int findIndex(Object object, Method method) {
772
for (int i = 0; i < count; i++) {
773
if (objects[i] == object && methods[i].equals(method)) {
774
//objects[i].equals() might be overridden, so use == for safety
775
// since here we do care about actual object identity
776
//methods[i]==method is never true even for same method, so must use
777
// equals(), this should be safe because of object identity
786
public void registerSize(Object o) {
787
Class<?> methodArgs[] = new Class[] { Integer.TYPE, Integer.TYPE };
788
registerWithArgs(sizeMethods, "size", o, methodArgs);
791
public void registerPre(Object o) {
792
registerNoArgs(preMethods, "pre", o);
795
public void registerDraw(Object o) {
796
registerNoArgs(drawMethods, "draw", o);
799
public void registerPost(Object o) {
800
registerNoArgs(postMethods, "post", o);
803
public void registerMouseEvent(Object o) {
804
Class<?> methodArgs[] = new Class[] { MouseEvent.class };
805
registerWithArgs(mouseEventMethods, "mouseEvent", o, methodArgs);
809
public void registerKeyEvent(Object o) {
810
Class<?> methodArgs[] = new Class[] { KeyEvent.class };
811
registerWithArgs(keyEventMethods, "keyEvent", o, methodArgs);
814
public void registerDispose(Object o) {
815
registerNoArgs(disposeMethods, "dispose", o);
819
protected void registerNoArgs(RegisteredMethods meth,
820
String name, Object o) {
821
Class<?> c = o.getClass();
823
Method method = c.getMethod(name, new Class[] {});
826
} catch (NoSuchMethodException nsme) {
827
die("There is no public " + name + "() method in the class " +
828
o.getClass().getName());
830
} catch (Exception e) {
831
die("Could not register " + name + " + () for " + o, e);
836
protected void registerWithArgs(RegisteredMethods meth,
837
String name, Object o, Class<?> cargs[]) {
838
Class<?> c = o.getClass();
840
Method method = c.getMethod(name, cargs);
843
} catch (NoSuchMethodException nsme) {
844
die("There is no public " + name + "() method in the class " +
845
o.getClass().getName());
847
} catch (Exception e) {
848
die("Could not register " + name + " + () for " + o, e);
853
public void unregisterSize(Object o) {
854
Class<?> methodArgs[] = new Class[] { Integer.TYPE, Integer.TYPE };
855
unregisterWithArgs(sizeMethods, "size", o, methodArgs);
858
public void unregisterPre(Object o) {
859
unregisterNoArgs(preMethods, "pre", o);
862
public void unregisterDraw(Object o) {
863
unregisterNoArgs(drawMethods, "draw", o);
866
public void unregisterPost(Object o) {
867
unregisterNoArgs(postMethods, "post", o);
870
public void unregisterMouseEvent(Object o) {
871
Class<?> methodArgs[] = new Class[] { MouseEvent.class };
872
unregisterWithArgs(mouseEventMethods, "mouseEvent", o, methodArgs);
875
public void unregisterKeyEvent(Object o) {
876
Class<?> methodArgs[] = new Class[] { KeyEvent.class };
877
unregisterWithArgs(keyEventMethods, "keyEvent", o, methodArgs);
880
public void unregisterDispose(Object o) {
881
unregisterNoArgs(disposeMethods, "dispose", o);
885
protected void unregisterNoArgs(RegisteredMethods meth,
886
String name, Object o) {
887
Class<?> c = o.getClass();
889
Method method = c.getMethod(name, new Class[] {});
890
meth.remove(o, method);
891
} catch (Exception e) {
892
die("Could not unregister " + name + "() for " + o, e);
897
protected void unregisterWithArgs(RegisteredMethods meth,
898
String name, Object o, Class<?> cargs[]) {
899
Class<?> c = o.getClass();
901
Method method = c.getMethod(name, cargs);
902
meth.remove(o, method);
903
} catch (Exception e) {
904
die("Could not unregister " + name + "() for " + o, e);
909
//////////////////////////////////////////////////////////////
912
public void setup() {
917
// if no draw method, then shut things down
918
//System.out.println("no draw method, goodbye");
923
//////////////////////////////////////////////////////////////
926
protected void resizeRenderer(int iwidth, int iheight) {
927
// println("resizeRenderer request for " + iwidth + " " + iheight);
928
if (width != iwidth || height != iheight) {
929
// println(" former size was " + width + " " + height);
930
g.setSize(iwidth, iheight);
938
* Starts up and creates a two-dimensional drawing surface,
939
* or resizes the current drawing surface.
941
* This should be the first thing called inside of setup().
943
* If using Java 1.3 or later, this will default to using
944
* PGraphics2, the Java2D-based renderer. If using Java 1.1,
945
* or if PGraphics2 is not available, then PGraphics will be used.
946
* To set your own renderer, use the other version of the size()
947
* method that takes a renderer as its last parameter.
949
* If called once a renderer has already been set, this will
950
* use the previous renderer and simply resize it.
952
public void size(int iwidth, int iheight) {
953
size(iwidth, iheight, JAVA2D, null);
957
public void size(int iwidth, int iheight, String irenderer) {
958
size(iwidth, iheight, irenderer, null);
963
* Creates a new PGraphics object and sets it to the specified size.
965
* Note that you cannot change the renderer once outside of setup().
966
* In most cases, you can call size() to give it a new size,
967
* but you need to always ask for the same renderer, otherwise
968
* you're gonna run into trouble.
970
* The size() method should *only* be called from inside the setup() or
971
* draw() methods, so that it is properly run on the main animation thread.
972
* To change the size of a PApplet externally, use setSize(), which will
973
* update the component size, and queue a resize of the renderer as well.
975
public void size(final int iwidth, final int iheight,
976
String irenderer, String ipath) {
977
// Run this from the EDT, just cuz it's AWT stuff (or maybe later Swing)
978
SwingUtilities.invokeLater(new Runnable() {
980
// Set the preferred size so that the layout managers can handle it
981
setPreferredSize(new Dimension(iwidth, iheight));
982
setSize(iwidth, iheight);
986
// ensure that this is an absolute path
987
if (ipath != null) ipath = savePath(ipath);
989
String currentRenderer = g.getClass().getName();
990
if (currentRenderer.equals(irenderer)) {
991
// Avoid infinite loop of throwing exception to reset renderer
992
resizeRenderer(iwidth, iheight);
993
//redraw(); // will only be called insize draw()
995
} else { // renderer is being changed
996
// otherwise ok to fall through and create renderer below
997
// the renderer is changing, so need to create a new object
998
g = makeGraphics(iwidth, iheight, irenderer, ipath, true);
1002
// fire resize event to make sure the applet is the proper size
1003
// setSize(iwidth, iheight);
1004
// this is the function that will run if the user does their own
1005
// size() command inside setup, so set defaultSize to false.
1006
defaultSize = false;
1008
// throw an exception so that setup() is called again
1009
// but with a properly sized render
1010
// this is for opengl, which needs a valid, properly sized
1011
// display before calling anything inside setup().
1012
throw new RendererChangeException();
1018
* Create an offscreen PGraphics object for drawing. This can be used
1019
* for bitmap or vector images drawing or rendering.
1021
* <LI>Do not use "new PGraphicsXxxx()", use this method. This method
1022
* ensures that internal variables are set up properly that tie the
1023
* new graphics context back to its parent PApplet.
1024
* <LI>The basic way to create bitmap images is to use the <A
1025
* HREF="http://processing.org/reference/saveFrame_.html">saveFrame()</A>
1027
* <LI>If you want to create a really large scene and write that,
1028
* first make sure that you've allocated a lot of memory in the Preferences.
1029
* <LI>If you want to create images that are larger than the screen,
1030
* you should create your own PGraphics object, draw to that, and use
1031
* <A HREF="http://processing.org/reference/save_.html">save()</A>.
1032
* For now, it's best to use <A HREF="http://dev.processing.org/reference/everything/javadoc/processing/core/PGraphics3D.html">P3D</A> in this scenario.
1033
* P2D is currently disabled, and the JAVA2D default will give mixed
1034
* results. An example of using P3D:
1040
* big = createGraphics(3000, 3000, P3D);
1043
* big.background(128);
1044
* big.line(20, 1800, 1800, 900);
1048
* // make sure the file is written to the sketch folder
1049
* big.save("big.tif");
1053
* <LI>It's important to always wrap drawing to createGraphics() with
1054
* beginDraw() and endDraw() (beginFrame() and endFrame() prior to
1055
* revision 0115). The reason is that the renderer needs to know when
1056
* drawing has stopped, so that it can update itself internally.
1057
* This also handles calling the defaults() method, for people familiar
1059
* <LI>It's not possible to use createGraphics() with the OPENGL renderer,
1060
* because it doesn't allow offscreen use.
1061
* <LI>With Processing 0115 and later, it's possible to write images in
1062
* formats other than the default .tga and .tiff. The exact formats and
1063
* background information can be found in the developer's reference for
1064
* <A HREF="http://dev.processing.org/reference/core/javadoc/processing/core/PImage.html#save(java.lang.String)">PImage.save()</A>.
1067
public PGraphics createGraphics(int iwidth, int iheight,
1069
PGraphics pg = makeGraphics(iwidth, iheight, irenderer, null, false);
1070
//pg.parent = this; // make save() work
1076
* Create an offscreen graphics surface for drawing, in this case
1077
* for a renderer that writes to a file (such as PDF or DXF).
1078
* @param ipath can be an absolute or relative path
1080
public PGraphics createGraphics(int iwidth, int iheight,
1081
String irenderer, String ipath) {
1082
if (ipath != null) {
1083
ipath = savePath(ipath);
1085
PGraphics pg = makeGraphics(iwidth, iheight, irenderer, ipath, false);
1086
pg.parent = this; // make save() work
1092
* Version of createGraphics() used internally.
1094
* @param ipath must be an absolute path, usually set via savePath()
1095
* @oaram applet the parent applet object, this should only be non-null
1096
* in cases where this is the main drawing surface object.
1098
protected PGraphics makeGraphics(int iwidth, int iheight,
1099
String irenderer, String ipath,
1101
if (irenderer.equals(OPENGL)) {
1102
if (PApplet.platform == WINDOWS) {
1103
String s = System.getProperty("java.version");
1105
if (s.equals("1.5.0_10")) {
1106
System.err.println("OpenGL support is broken with Java 1.5.0_10");
1107
System.err.println("See http://dev.processing.org" +
1108
"/bugs/show_bug.cgi?id=513 for more info.");
1109
throw new RuntimeException("Please update your Java " +
1110
"installation (see bug #513)");
1116
// if (irenderer.equals(P2D)) {
1117
// throw new RuntimeException("The P2D renderer is currently disabled, " +
1118
// "please use P3D or JAVA2D.");
1121
String openglError =
1122
"Before using OpenGL, first select " +
1123
"Import Library > opengl from the Sketch menu.";
1127
Class<?> rendererClass = Class.forName(irenderer);
1129
Class<?> constructorParams[] = null;
1130
Object constructorValues[] = null;
1132
if (ipath == null) {
1133
constructorParams = new Class[] {
1134
Integer.TYPE, Integer.TYPE, PApplet.class
1136
constructorValues = new Object[] {
1137
new Integer(iwidth), new Integer(iheight), this
1140
constructorParams = new Class[] {
1141
Integer.TYPE, Integer.TYPE, PApplet.class, String.class
1143
constructorValues = new Object[] {
1144
new Integer(iwidth), new Integer(iheight), this, ipath
1148
Constructor<?> constructor =
1149
rendererClass.getConstructor(constructorParams);
1150
PGraphics pg = (PGraphics) constructor.newInstance(constructorValues);
1153
Class<?> rendererClass =
1154
Thread.currentThread().getContextClassLoader().loadClass(irenderer);
1156
//Class<?> params[] = null;
1157
//PApplet.println(rendererClass.getConstructors());
1158
Constructor<?> constructor = rendererClass.getConstructor(new Class[] { });
1159
PGraphics pg = (PGraphics) constructor.newInstance();
1162
pg.setPrimary(iprimary);
1163
if (ipath != null) pg.setPath(ipath);
1164
pg.setSize(iwidth, iheight);
1166
// everything worked, return it
1169
} catch (InvocationTargetException ite) {
1170
String msg = ite.getTargetException().getMessage();
1171
if ((msg != null) &&
1172
(msg.indexOf("no jogl in java.library.path") != -1)) {
1173
throw new RuntimeException(openglError +
1174
" (The native library is missing.)");
1177
ite.getTargetException().printStackTrace();
1178
Throwable target = ite.getTargetException();
1179
if (platform == MACOSX) target.printStackTrace(System.out); // bug
1180
// neither of these help, or work
1181
//target.printStackTrace(System.err);
1182
//System.err.flush();
1183
//System.out.println(System.err); // and the object isn't null
1184
throw new RuntimeException(target.getMessage());
1187
} catch (ClassNotFoundException cnfe) {
1188
if (cnfe.getMessage().indexOf("processing.opengl.PGraphicsGL") != -1) {
1189
throw new RuntimeException(openglError +
1190
" (The library .jar file is missing.)");
1192
throw new RuntimeException("You need to use \"Import Library\" " +
1193
"to add " + irenderer + " to your sketch.");
1196
} catch (Exception e) {
1197
//System.out.println("ex3");
1198
if ((e instanceof IllegalArgumentException) ||
1199
(e instanceof NoSuchMethodException) ||
1200
(e instanceof IllegalAccessException)) {
1201
e.printStackTrace();
1203
String msg = "public " +
1204
irenderer.substring(irenderer.lastIndexOf('.') + 1) +
1205
"(int width, int height, PApplet parent" +
1206
((ipath == null) ? "" : ", String filename") +
1207
") does not exist.";
1209
String msg = irenderer + " needs to be updated " +
1210
"for the current release of Processing.";
1211
throw new RuntimeException(msg);
1214
if (platform == MACOSX) e.printStackTrace(System.out);
1215
throw new RuntimeException(e.getMessage());
1222
* Preferred method of creating new PImage objects, ensures that a
1223
* reference to the parent PApplet is included, which makes save() work
1224
* without needing an absolute path.
1226
public PImage createImage(int wide, int high, int format) {
1227
PImage image = new PImage(wide, high, format);
1228
image.parent = this; // make save() work
1233
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1236
public void update(Graphics screen) {
1241
//synchronized public void paint(Graphics screen) { // shutting off for 0146
1242
public void paint(Graphics screen) {
1243
// ignore the very first call to paint, since it's coming
1244
// from the o.s., and the applet will soon update itself anyway.
1245
if (frameCount == 0) {
1246
// println("Skipping frame");
1247
// paint() may be called more than once before things
1248
// are finally painted to the screen and the thread gets going
1252
// without ignoring the first call, the first several frames
1253
// are confused because paint() gets called in the midst of
1254
// the initial nextFrame() call, so there are multiple
1255
// updates fighting with one another.
1257
// g.image is synchronized so that draw/loop and paint don't
1258
// try to fight over it. this was causing a randomized slowdown
1259
// that would cut the frameRate into a third on macosx,
1260
// and is probably related to the windows sluggishness bug too
1262
// make sure the screen is visible and usable
1263
// (also prevents over-drawing when using PGraphicsOpenGL)
1264
if ((g != null) && (g.image != null)) {
1265
// println("inside paint(), screen.drawImage()");
1266
screen.drawImage(g.image, 0, 0, null);
1271
// active paint method
1272
protected void paint() {
1274
Graphics screen = this.getGraphics();
1275
if (screen != null) {
1276
if ((g != null) && (g.image != null)) {
1277
screen.drawImage(g.image, 0, 0, null);
1279
Toolkit.getDefaultToolkit().sync();
1281
} catch (Exception e) {
1282
// Seen on applet destroy, maybe can ignore?
1283
e.printStackTrace();
1293
//////////////////////////////////////////////////////////////
1297
* Main method for the primary animation thread.
1299
* <A HREF="http://java.sun.com/products/jfc/tsc/articles/painting/">Painting in AWT and Swing</A>
1301
public void run() { // not good to make this synchronized, locks things up
1302
long beforeTime = System.nanoTime();
1303
long overSleepTime = 0L;
1306
// Number of frames with a delay of 0 ms before the
1307
// animation thread yields to other running threads.
1308
final int NO_DELAYS_PER_YIELD = 15;
1311
// this has to be called after the exception is thrown,
1312
// otherwise the supporting libs won't have a valid context to draw to
1313
Object methodArgs[] =
1314
new Object[] { new Integer(width), new Integer(height) };
1315
sizeMethods.handle(methodArgs);
1318
while ((Thread.currentThread() == thread) && !finished) {
1319
// Don't resize the renderer from the EDT (i.e. from a ComponentEvent),
1320
// otherwise it may attempt a resize mid-render.
1321
if (resizeRequest) {
1322
resizeRenderer(resizeWidth, resizeHeight);
1323
resizeRequest = false;
1326
// render a single frame
1329
if (frameCount == 1) {
1330
// Call the request focus event once the image is sure to be on
1331
// screen and the component is valid. The OpenGL renderer will
1332
// request focus for its canvas inside beginDraw().
1333
// http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/FocusSpec.html
1334
//println("requesting focus");
1338
// wait for update & paint to happen before drawing next frame
1339
// this is necessary since the drawing is sometimes in a
1340
// separate thread, meaning that the next frame will start
1341
// before the update/paint is completed
1343
long afterTime = System.nanoTime();
1344
long timeDiff = afterTime - beforeTime;
1345
//System.out.println("time diff is " + timeDiff);
1346
long sleepTime = (frameRatePeriod - timeDiff) - overSleepTime;
1348
if (sleepTime > 0) { // some time left in this cycle
1350
// Thread.sleep(sleepTime / 1000000L); // nanoseconds -> milliseconds
1351
Thread.sleep(sleepTime / 1000000L, (int) (sleepTime % 1000000L));
1352
noDelays = 0; // Got some sleep, not delaying anymore
1353
} catch (InterruptedException ex) { }
1355
overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
1356
//System.out.println(" oversleep is " + overSleepTime);
1358
} else { // sleepTime <= 0; the frame took longer than the period
1359
// excess -= sleepTime; // store excess time value
1362
if (noDelays > NO_DELAYS_PER_YIELD) {
1363
Thread.yield(); // give another thread a chance to run
1368
beforeTime = System.nanoTime();
1371
stop(); // call to shutdown libs?
1373
// If the user called the exit() function, the window should close,
1374
// rather than the sketch just halting.
1381
//synchronized public void handleDisplay() {
1382
public void handleDraw() {
1383
if (g != null && (looping || redraw)) {
1385
// Don't draw if the renderer is not yet ready.
1386
// (e.g. OpenGL has to wait for a peer to be on screen)
1390
//System.out.println("handleDraw() " + frameCount);
1393
if (recorder != null) {
1394
recorder.beginDraw();
1397
long now = System.nanoTime();
1399
if (frameCount == 0) {
1401
//println("Calling setup()");
1403
//println("Done with setup()");
1405
} catch (RendererChangeException e) {
1406
// Give up, instead set the new renderer and re-attempt setup()
1409
this.defaultSize = false;
1411
} else { // frameCount > 0, meaning an actual draw()
1412
// update the current frameRate
1413
double rate = 1000000.0 / ((now - frameRateLastNanos) / 1000000.0);
1414
float instantaneousRate = (float) rate / 1000.0f;
1415
frameRate = (frameRate * 0.9f) + (instantaneousRate * 0.1f);
1417
preMethods.handle();
1419
// use dmouseX/Y as previous mouse pos, since this is the
1420
// last position the mouse was in during the previous draw.
1424
//println("Calling draw()");
1426
//println("Done calling draw()");
1428
// dmouseX/Y is updated only once per frame (unlike emouseX/Y)
1432
// these are called *after* loop so that valid
1433
// drawing commands can be run inside them. it can't
1434
// be before, since a call to background() would wipe
1435
// out anything that had been drawn so far.
1436
dequeueMouseEvents();
1439
drawMethods.handle();
1441
redraw = false; // unset 'redraw' flag in case it was set
1442
// (only do this once draw() has run, not just setup())
1447
if (recorder != null) {
1451
frameRateLastNanos = now;
1454
// Actively render the screen
1458
// getToolkit().sync(); // force repaint now (proper method)
1460
postMethods.handle();
1465
//////////////////////////////////////////////////////////////
1469
synchronized public void redraw() {
1472
// if (thread != null) {
1473
// // wake from sleep (necessary otherwise it'll be
1474
// // up to 10 seconds before update)
1475
// if (CRUSTY_THREADS) {
1476
// thread.interrupt();
1478
// synchronized (blocker) {
1479
// blocker.notifyAll();
1487
synchronized public void loop() {
1494
synchronized public void noLoop() {
1501
//////////////////////////////////////////////////////////////
1504
public void addListeners() {
1505
addMouseListener(this);
1506
addMouseMotionListener(this);
1507
addKeyListener(this);
1508
addFocusListener(this);
1510
addComponentListener(new ComponentAdapter() {
1511
public void componentResized(ComponentEvent e) {
1512
Component c = e.getComponent();
1513
//System.out.println("componentResized() " + c);
1514
Rectangle bounds = c.getBounds();
1515
resizeRequest = true;
1516
resizeWidth = bounds.width;
1517
resizeHeight = bounds.height;
1523
//////////////////////////////////////////////////////////////
1526
MouseEvent mouseEventQueue[] = new MouseEvent[10];
1527
int mouseEventCount;
1529
protected void enqueueMouseEvent(MouseEvent e) {
1530
synchronized (mouseEventQueue) {
1531
if (mouseEventCount == mouseEventQueue.length) {
1532
MouseEvent temp[] = new MouseEvent[mouseEventCount << 1];
1533
System.arraycopy(mouseEventQueue, 0, temp, 0, mouseEventCount);
1534
mouseEventQueue = temp;
1536
mouseEventQueue[mouseEventCount++] = e;
1540
protected void dequeueMouseEvents() {
1541
synchronized (mouseEventQueue) {
1542
for (int i = 0; i < mouseEventCount; i++) {
1543
mouseEvent = mouseEventQueue[i];
1544
handleMouseEvent(mouseEvent);
1546
mouseEventCount = 0;
1552
* Actually take action based on a mouse event.
1553
* Internally updates mouseX, mouseY, mousePressed, and mouseEvent.
1554
* Then it calls the event type with no params,
1555
* i.e. mousePressed() or mouseReleased() that the user may have
1556
* overloaded to do something more useful.
1558
protected void handleMouseEvent(MouseEvent event) {
1559
int id = event.getID();
1561
// http://dev.processing.org/bugs/show_bug.cgi?id=170
1562
// also prevents mouseExited() on the mac from hosing the mouse
1563
// position, because x/y are bizarre values on the exit event.
1564
// see also the id check below.. both of these go together
1565
if ((id == MouseEvent.MOUSE_DRAGGED) ||
1566
(id == MouseEvent.MOUSE_MOVED)) {
1569
mouseX = event.getX();
1570
mouseY = event.getY();
1575
int modifiers = event.getModifiers();
1576
if ((modifiers & InputEvent.BUTTON1_MASK) != 0) {
1578
} else if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
1579
mouseButton = CENTER;
1580
} else if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
1581
mouseButton = RIGHT;
1583
// if running on macos, allow ctrl-click as right mouse
1584
if (platform == MACOSX) {
1585
if (mouseEvent.isPopupTrigger()) {
1586
mouseButton = RIGHT;
1590
mouseEventMethods.handle(new Object[] { event });
1592
// this used to only be called on mouseMoved and mouseDragged
1593
// change it back if people run into trouble
1605
case MouseEvent.MOUSE_PRESSED:
1606
mousePressed = true;
1609
case MouseEvent.MOUSE_RELEASED:
1610
mousePressed = false;
1613
case MouseEvent.MOUSE_CLICKED:
1616
case MouseEvent.MOUSE_DRAGGED:
1619
case MouseEvent.MOUSE_MOVED:
1624
if ((id == MouseEvent.MOUSE_DRAGGED) ||
1625
(id == MouseEvent.MOUSE_MOVED)) {
1633
* Figure out how to process a mouse event. When loop() has been
1634
* called, the events will be queued up until drawing is complete.
1635
* If noLoop() has been called, then events will happen immediately.
1637
protected void checkMouseEvent(MouseEvent event) {
1639
enqueueMouseEvent(event);
1641
handleMouseEvent(event);
1647
* If you override this or any function that takes a "MouseEvent e"
1648
* without calling its super.mouseXxxx() then mouseX, mouseY,
1649
* mousePressed, and mouseEvent will no longer be set.
1651
public void mousePressed(MouseEvent e) {
1655
public void mouseReleased(MouseEvent e) {
1659
public void mouseClicked(MouseEvent e) {
1663
public void mouseEntered(MouseEvent e) {
1667
public void mouseExited(MouseEvent e) {
1671
public void mouseDragged(MouseEvent e) {
1675
public void mouseMoved(MouseEvent e) {
1681
* Mouse has been pressed, and should be considered "down"
1682
* until mouseReleased() is called. If you must, use
1683
* int button = mouseEvent.getButton();
1684
* to figure out which button was clicked. It will be one of:
1685
* MouseEvent.BUTTON1, MouseEvent.BUTTON2, MouseEvent.BUTTON3
1686
* Note, however, that this is completely inconsistent across
1689
public void mousePressed() { }
1692
* Mouse button has been released.
1694
public void mouseReleased() { }
1697
* When the mouse is clicked, mousePressed() will be called,
1698
* then mouseReleased(), then mouseClicked(). Note that
1699
* mousePressed is already false inside of mouseClicked().
1701
public void mouseClicked() { }
1704
* Mouse button is pressed and the mouse has been dragged.
1706
public void mouseDragged() { }
1709
* Mouse button is not pressed but the mouse has changed locations.
1711
public void mouseMoved() { }
1714
//////////////////////////////////////////////////////////////
1717
KeyEvent keyEventQueue[] = new KeyEvent[10];
1720
protected void enqueueKeyEvent(KeyEvent e) {
1721
synchronized (keyEventQueue) {
1722
if (keyEventCount == keyEventQueue.length) {
1723
KeyEvent temp[] = new KeyEvent[keyEventCount << 1];
1724
System.arraycopy(keyEventQueue, 0, temp, 0, keyEventCount);
1725
keyEventQueue = temp;
1727
keyEventQueue[keyEventCount++] = e;
1731
protected void dequeueKeyEvents() {
1732
synchronized (keyEventQueue) {
1733
for (int i = 0; i < keyEventCount; i++) {
1734
keyEvent = keyEventQueue[i];
1735
handleKeyEvent(keyEvent);
1742
protected void handleKeyEvent(KeyEvent event) {
1744
key = event.getKeyChar();
1745
keyCode = event.getKeyCode();
1747
keyEventMethods.handle(new Object[] { event });
1749
switch (event.getID()) {
1750
case KeyEvent.KEY_PRESSED:
1754
case KeyEvent.KEY_RELEASED:
1758
case KeyEvent.KEY_TYPED:
1763
// if someone else wants to intercept the key, they should
1764
// set key to zero (or something besides the ESC).
1765
if (event.getID() == KeyEvent.KEY_PRESSED) {
1766
if (key == KeyEvent.VK_ESCAPE) {
1769
// When running tethered to the Processing application, respond to
1770
// Ctrl-W (or Cmd-W) events by closing the sketch. Disable this behavior
1771
// when running independently, because this sketch may be one component
1772
// embedded inside an application that has its own close behavior.
1774
event.getModifiers() == MENU_SHORTCUT &&
1775
event.getKeyCode() == 'W') {
1782
protected void checkKeyEvent(KeyEvent event) {
1784
enqueueKeyEvent(event);
1786
handleKeyEvent(event);
1792
* Overriding keyXxxxx(KeyEvent e) functions will cause the 'key',
1793
* 'keyCode', and 'keyEvent' variables to no longer work;
1794
* key events will no longer be queued until the end of draw();
1795
* and the keyPressed(), keyReleased() and keyTyped() methods
1796
* will no longer be called.
1798
public void keyPressed(KeyEvent e) { checkKeyEvent(e); }
1799
public void keyReleased(KeyEvent e) { checkKeyEvent(e); }
1800
public void keyTyped(KeyEvent e) { checkKeyEvent(e); }
1804
* Called each time a single key on the keyboard is pressed.
1805
* Because of how operating systems handle key repeats, holding
1806
* down a key will cause multiple calls to keyPressed(), because
1807
* the OS repeat takes over.
1809
* Examples for key handling:
1810
* (Tested on Windows XP, please notify if different on other
1811
* platforms, I have a feeling Mac OS and Linux may do otherwise)
1813
* 1. Pressing 'a' on the keyboard:
1814
* keyPressed with key == 'a' and keyCode == 'A'
1815
* keyTyped with key == 'a' and keyCode == 0
1816
* keyReleased with key == 'a' and keyCode == 'A'
1818
* 2. Pressing 'A' on the keyboard:
1819
* keyPressed with key == 'A' and keyCode == 'A'
1820
* keyTyped with key == 'A' and keyCode == 0
1821
* keyReleased with key == 'A' and keyCode == 'A'
1823
* 3. Pressing 'shift', then 'a' on the keyboard (caps lock is off):
1824
* keyPressed with key == CODED and keyCode == SHIFT
1825
* keyPressed with key == 'A' and keyCode == 'A'
1826
* keyTyped with key == 'A' and keyCode == 0
1827
* keyReleased with key == 'A' and keyCode == 'A'
1828
* keyReleased with key == CODED and keyCode == SHIFT
1830
* 4. Holding down the 'a' key.
1831
* The following will happen several times,
1832
* depending on your machine's "key repeat rate" settings:
1833
* keyPressed with key == 'a' and keyCode == 'A'
1834
* keyTyped with key == 'a' and keyCode == 0
1835
* When you finally let go, you'll get:
1836
* keyReleased with key == 'a' and keyCode == 'A'
1838
* 5. Pressing and releasing the 'shift' key
1839
* keyPressed with key == CODED and keyCode == SHIFT
1840
* keyReleased with key == CODED and keyCode == SHIFT
1841
* (note there is no keyTyped)
1843
* 6. Pressing the tab key in an applet with Java 1.4 will
1844
* normally do nothing, but PApplet dynamically shuts
1845
* this behavior off if Java 1.4 is in use (tested 1.4.2_05 Windows).
1846
* Java 1.1 (Microsoft VM) passes the TAB key through normally.
1847
* Not tested on other platforms or for 1.3.
1850
public void keyPressed() { }
1856
public void keyReleased() { }
1860
* Only called for "regular" keys like letters,
1861
* see keyPressed() for full documentation.
1863
public void keyTyped() { }
1866
//////////////////////////////////////////////////////////////
1868
// i am focused man, and i'm not afraid of death.
1869
// and i'm going all out. i circle the vultures in a van
1870
// and i run the block.
1873
public void focusGained() { }
1875
public void focusGained(FocusEvent e) {
1881
public void focusLost() { }
1883
public void focusLost(FocusEvent e) {
1889
//////////////////////////////////////////////////////////////
1895
* Get the number of milliseconds since the applet started.
1897
* This is a function, rather than a variable, because it may
1898
* change multiple times per frame.
1900
public int millis() {
1901
return (int) (System.currentTimeMillis() - millisOffset);
1904
/** Seconds position of the current time. */
1905
static public int second() {
1906
return Calendar.getInstance().get(Calendar.SECOND);
1909
/** Minutes position of the current time. */
1910
static public int minute() {
1911
return Calendar.getInstance().get(Calendar.MINUTE);
1915
* Hour position of the current time in international format (0-23).
1917
* To convert this value to American time: <BR>
1918
* <PRE>int yankeeHour = (hour() % 12);
1919
* if (yankeeHour == 0) yankeeHour = 12;</PRE>
1921
static public int hour() {
1922
return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
1926
* Get the current day of the month (1 through 31).
1928
* If you're looking for the day of the week (M-F or whatever)
1929
* or day of the year (1..365) then use java's Calendar.get()
1931
static public int day() {
1932
return Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
1936
* Get the current month in range 1 through 12.
1938
static public int month() {
1939
// months are number 0..11 so change to colloquial 1..12
1940
return Calendar.getInstance().get(Calendar.MONTH) + 1;
1944
* Get the current year.
1946
static public int year() {
1947
return Calendar.getInstance().get(Calendar.YEAR);
1951
//////////////////////////////////////////////////////////////
1953
// controlling time (playing god)
1957
* The delay() function causes the program to halt for a specified time.
1958
* Delay times are specified in thousandths of a second. For example,
1959
* running delay(3000) will stop the program for three seconds and
1960
* delay(500) will stop the program for a half-second. Remember: the
1961
* display window is updated only at the end of draw(), so putting more
1962
* than one delay() inside draw() will simply add them together and the new
1963
* frame will be drawn when the total delay is over.
1965
* I'm not sure if this is even helpful anymore, as the screen isn't
1966
* updated before or after the delay, meaning which means it just
1967
* makes the app lock up temporarily.
1969
public void delay(int napTime) {
1970
if (frameCount != 0) {
1973
Thread.sleep(napTime);
1974
} catch (InterruptedException e) { }
1981
* Set a target frameRate. This will cause delay() to be called
1982
* after each frame so that the sketch synchronizes to a particular speed.
1983
* Note that this only sets the maximum frame rate, it cannot be used to
1984
* make a slow sketch go faster. Sketches have no default frame rate
1985
* setting, and will attempt to use maximum processor power to achieve
1988
public void frameRate(float newRateTarget) {
1989
frameRateTarget = newRateTarget;
1990
frameRatePeriod = (long) (1000000000.0 / frameRateTarget);
1994
//////////////////////////////////////////////////////////////
1998
* Get a param from the web page, or (eventually)
1999
* from a properties file.
2001
public String param(String what) {
2003
return getParameter(what);
2006
System.err.println("param() only works inside a web browser");
2013
* Show status in the status bar of a web browser, or in the
2014
* System.out console. Eventually this might show status in the
2015
* p5 environment itself, rather than relying on the console.
2017
public void status(String what) {
2022
System.out.println(what); // something more interesting?
2027
public void link(String here) {
2033
* Link to an external page without all the muss.
2035
* When run with an applet, uses the browser to open the url,
2036
* for applications, attempts to launch a browser with the url.
2038
* Works on Mac OS X and Windows. For Linux, use:
2039
* <PRE>open(new String[] { "firefox", url });</PRE>
2040
* or whatever you want as your browser, since Linux doesn't
2041
* yet have a standard method for launching URLs.
2043
public void link(String url, String frameTitle) {
2046
if (frameTitle == null) {
2047
getAppletContext().showDocument(new URL(url));
2049
getAppletContext().showDocument(new URL(url), frameTitle);
2051
} catch (Exception e) {
2052
e.printStackTrace();
2053
throw new RuntimeException("Could not open " + url);
2057
if (platform == WINDOWS) {
2058
// the following uses a shell execute to launch the .html file
2059
// note that under cygwin, the .html files have to be chmodded +x
2060
// after they're unpacked from the zip file. i don't know why,
2061
// and don't understand what this does in terms of windows
2062
// permissions. without the chmod, the command prompt says
2063
// "Access is denied" in both cygwin and the "dos" prompt.
2064
//Runtime.getRuntime().exec("cmd /c " + currentDir + "\\reference\\" +
2065
// referenceFile + ".html");
2067
// replace ampersands with control sequence for DOS.
2068
// solution contributed by toxi on the bugs board.
2069
url = url.replaceAll("&","^&");
2071
// open dos prompt, give it 'start' command, which will
2072
// open the url properly. start by itself won't work since
2073
// it appears to need cmd
2074
Runtime.getRuntime().exec("cmd /c start " + url);
2076
} else if (platform == MACOSX) {
2077
//com.apple.mrj.MRJFileUtils.openURL(url);
2079
Class<?> mrjFileUtils = Class.forName("com.apple.mrj.MRJFileUtils");
2081
mrjFileUtils.getMethod("openURL", new Class[] { String.class });
2082
openMethod.invoke(null, new Object[] { url });
2083
} catch (Exception e) {
2084
e.printStackTrace();
2087
//throw new RuntimeException("Can't open URLs for this platform");
2088
// Just pass it off to open() and hope for the best
2091
} catch (IOException e) {
2092
e.printStackTrace();
2093
throw new RuntimeException("Could not open " + url);
2100
* Attempt to open a file using the platform's shell.
2102
static public void open(String filename) {
2103
open(new String[] { filename });
2107
static String openLauncher;
2110
* Launch a process using a platforms shell. This version uses an array
2111
* to make it easier to deal with spaces in the individual elements.
2112
* (This avoids the situation of trying to put single or double quotes
2113
* around different bits).
2115
static public Process open(String argv[]) {
2116
String[] params = null;
2118
if (platform == WINDOWS) {
2119
// just launching the .html file via the shell works
2120
// but make sure to chmod +x the .html files first
2121
// also place quotes around it in case there's a space
2122
// in the user.dir part of the url
2123
params = new String[] { "cmd", "/c" };
2125
} else if (platform == MACOSX) {
2126
params = new String[] { "open" };
2128
} else if (platform == LINUX) {
2129
if (openLauncher == null) {
2130
// Attempt to use gnome-open
2132
Process p = Runtime.getRuntime().exec(new String[] { "gnome-open" });
2133
/*int result =*/ p.waitFor();
2134
// Not installed will throw an IOException (JDK 1.4.2, Ubuntu 7.04)
2135
openLauncher = "gnome-open";
2136
} catch (Exception e) { }
2138
if (openLauncher == null) {
2139
// Attempt with kde-open
2141
Process p = Runtime.getRuntime().exec(new String[] { "kde-open" });
2142
/*int result =*/ p.waitFor();
2143
openLauncher = "kde-open";
2144
} catch (Exception e) { }
2146
if (openLauncher == null) {
2147
System.err.println("Could not find gnome-open or kde-open, " +
2148
"the open() command may not work.");
2150
if (openLauncher != null) {
2151
params = new String[] { openLauncher };
2153
//} else { // give up and just pass it to Runtime.exec()
2154
//open(new String[] { filename });
2155
//params = new String[] { filename };
2157
if (params != null) {
2158
// If the 'open', 'gnome-open' or 'cmd' are already included
2159
if (params[0].equals(argv[0])) {
2160
// then don't prepend those params again
2163
params = concat(params, argv);
2164
return exec(params);
2172
static public Process exec(String[] argv) {
2174
return Runtime.getRuntime().exec(argv);
2175
} catch (Exception e) {
2176
e.printStackTrace();
2177
throw new RuntimeException("Could not open " + join(argv, ' '));
2182
//////////////////////////////////////////////////////////////
2186
* Function for an applet/application to kill itself and
2187
* display an error. Mostly this is here to be improved later.
2189
public void die(String what) {
2191
throw new RuntimeException(what);
2196
* Same as above but with an exception. Also needs work.
2198
public void die(String what, Exception e) {
2199
if (e != null) e.printStackTrace();
2205
* Call to safely exit the sketch when finished. For instance,
2206
* to render a single frame, save it, and quit.
2208
public void exit() {
2209
if (thread == null) {
2210
// exit immediately, stop() has already been called,
2211
// meaning that the main thread has long since exited
2214
} else if (looping) {
2215
// stop() will be called as the thread exits
2217
// tell the code to call exit2() to do a System.exit()
2218
// once the next draw() has completed
2221
} else if (!looping) {
2222
// if not looping, need to call stop explicitly,
2223
// because the main thread will be sleeping
2235
} catch (SecurityException e) {
2236
// don't care about applet security exceptions
2242
//////////////////////////////////////////////////////////////
2245
public void method(String name) {
2246
// final Object o = this;
2247
// final Class<?> c = getClass();
2249
Method method = getClass().getMethod(name, new Class[] {});
2250
method.invoke(this, new Object[] { });
2252
} catch (IllegalArgumentException e) {
2253
e.printStackTrace();
2254
} catch (IllegalAccessException e) {
2255
e.printStackTrace();
2256
} catch (InvocationTargetException e) {
2257
e.getTargetException().printStackTrace();
2258
} catch (NoSuchMethodException nsme) {
2259
System.err.println("There is no public " + name + "() method " +
2260
"in the class " + getClass().getName());
2261
} catch (Exception e) {
2262
e.printStackTrace();
2267
public void thread(final String name) {
2268
Thread later = new Thread() {
2278
public void thread(String name) {
2279
final Object o = this;
2280
final Class<?> c = getClass();
2282
final Method method = c.getMethod(name, new Class[] {});
2283
Thread later = new Thread() {
2286
method.invoke(o, new Object[] { });
2288
} catch (IllegalArgumentException e) {
2289
e.printStackTrace();
2290
} catch (IllegalAccessException e) {
2291
e.printStackTrace();
2292
} catch (InvocationTargetException e) {
2293
e.getTargetException().printStackTrace();
2299
} catch (NoSuchMethodException nsme) {
2300
System.err.println("There is no " + name + "() method " +
2301
"in the class " + getClass().getName());
2303
} catch (Exception e) {
2304
e.printStackTrace();
2311
//////////////////////////////////////////////////////////////
2317
* Intercepts any relative paths to make them absolute (relative
2318
* to the sketch folder) before passing to save() in PImage.
2321
public void save(String filename) {
2322
g.save(savePath(filename));
2327
* Grab an image of what's currently in the drawing area and save it
2328
* as a .tif or .tga file.
2330
* Best used just before endDraw() at the end of your draw().
2331
* This can only create .tif or .tga images, so if neither extension
2332
* is specified it defaults to writing a tiff and adds a .tif suffix.
2334
public void saveFrame() {
2336
g.save(savePath("screen-" + nf(frameCount, 4) + ".tif"));
2337
} catch (SecurityException se) {
2338
System.err.println("Can't use saveFrame() when running in a browser, " +
2339
"unless using a signed applet.");
2345
* Save the current frame as a .tif or .tga image.
2347
* The String passed in can contain a series of # signs
2348
* that will be replaced with the screengrab number.
2350
* i.e. saveFrame("blah-####.tif");
2351
* // saves a numbered tiff image, replacing the
2352
* // #### signs with zeros and the frame number </PRE>
2354
public void saveFrame(String what) {
2356
g.save(savePath(insertFrame(what)));
2357
} catch (SecurityException se) {
2358
System.err.println("Can't use saveFrame() when running in a browser, " +
2359
"unless using a signed applet.");
2365
* Check a string for #### signs to see if the frame number should be
2366
* inserted. Used for functions like saveFrame() and beginRecord() to
2367
* replace the # marks with the frame number. If only one # is used,
2368
* it will be ignored, under the assumption that it's probably not
2369
* intended to be the frame number.
2371
protected String insertFrame(String what) {
2372
int first = what.indexOf('#');
2373
int last = what.lastIndexOf('#');
2375
if ((first != -1) && (last - first > 0)) {
2376
String prefix = what.substring(0, first);
2377
int count = last - first + 1;
2378
String suffix = what.substring(last + 1);
2379
return prefix + nf(frameCount, count) + suffix;
2381
return what; // no change
2386
//////////////////////////////////////////////////////////////
2393
int cursorType = ARROW; // cursor type
2394
boolean cursorVisible = true; // cursor visibility flag
2395
PImage invisibleCursor;
2399
* Set the cursor type
2401
public void cursor(int cursorType) {
2402
setCursor(Cursor.getPredefinedCursor(cursorType));
2403
cursorVisible = true;
2404
this.cursorType = cursorType;
2409
* Replace the cursor with the specified PImage. The x- and y-
2410
* coordinate of the center will be the center of the image.
2412
public void cursor(PImage image) {
2413
cursor(image, image.width/2, image.height/2);
2418
* Set a custom cursor to an image with a specific hotspot.
2419
* Only works with JDK 1.2 and later.
2420
* Currently seems to be broken on Java 1.4 for Mac OS X
2422
* Based on code contributed by Amit Pitaru, plus additional
2423
* code to handle Java versions via reflection by Jonathan Feinberg.
2424
* Reflection removed for release 0128 and later.
2426
public void cursor(PImage image, int hotspotX, int hotspotY) {
2427
// don't set this as cursor type, instead use cursor_type
2428
// to save the last cursor used in case cursor() is called
2429
//cursor_type = Cursor.CUSTOM_CURSOR;
2431
createImage(new MemoryImageSource(image.width, image.height,
2432
image.pixels, 0, image.width));
2433
Point hotspot = new Point(hotspotX, hotspotY);
2434
Toolkit tk = Toolkit.getDefaultToolkit();
2435
Cursor cursor = tk.createCustomCursor(jimage, hotspot, "Custom Cursor");
2437
cursorVisible = true;
2442
* Show the cursor after noCursor() was called.
2443
* Notice that the program remembers the last set cursor type
2445
public void cursor() {
2446
// maybe should always set here? seems dangerous, since
2447
// it's likely that java will set the cursor to something
2448
// else on its own, and the applet will be stuck b/c bagel
2449
// thinks that the cursor is set to one particular thing
2450
if (!cursorVisible) {
2451
cursorVisible = true;
2452
setCursor(Cursor.getPredefinedCursor(cursorType));
2458
* Hide the cursor by creating a transparent image
2459
* and using it as a custom cursor.
2461
public void noCursor() {
2462
if (!cursorVisible) return; // don't hide if already hidden.
2464
if (invisibleCursor == null) {
2465
invisibleCursor = new PImage(16, 16, ARGB);
2467
// was formerly 16x16, but the 0x0 was added by jdf as a fix
2468
// for macosx, which wasn't honoring the invisible cursor
2469
cursor(invisibleCursor, 8, 8);
2470
cursorVisible = false;
2474
//////////////////////////////////////////////////////////////
2477
static public void print(byte what) {
2478
System.out.print(what);
2482
static public void print(boolean what) {
2483
System.out.print(what);
2487
static public void print(char what) {
2488
System.out.print(what);
2492
static public void print(int what) {
2493
System.out.print(what);
2497
static public void print(float what) {
2498
System.out.print(what);
2502
static public void print(String what) {
2503
System.out.print(what);
2507
static public void print(Object what) {
2509
// special case since this does fuggly things on > 1.1
2510
System.out.print("null");
2512
System.out.println(what.toString());
2518
static public void println() {
2519
System.out.println();
2524
static public void println(byte what) {
2525
print(what); System.out.println();
2528
static public void println(boolean what) {
2529
print(what); System.out.println();
2532
static public void println(char what) {
2533
print(what); System.out.println();
2536
static public void println(int what) {
2537
print(what); System.out.println();
2540
static public void println(float what) {
2541
print(what); System.out.println();
2544
static public void println(String what) {
2545
print(what); System.out.println();
2548
static public void println(Object what) {
2550
// special case since this does fuggly things on > 1.1
2551
System.out.println("null");
2554
String name = what.getClass().getName();
2555
if (name.charAt(0) == '[') {
2556
switch (name.charAt(1)) {
2558
// don't even mess with multi-dimensional arrays (case '[')
2559
// or anything else that's not int, float, boolean, char
2560
System.out.println(what);
2564
// print a 1D array of objects as individual elements
2565
Object poo[] = (Object[]) what;
2566
for (int i = 0; i < poo.length; i++) {
2567
if (poo[i] instanceof String) {
2568
System.out.println("[" + i + "] \"" + poo[i] + "\"");
2570
System.out.println("[" + i + "] " + poo[i]);
2575
case 'Z': // boolean
2576
boolean zz[] = (boolean[]) what;
2577
for (int i = 0; i < zz.length; i++) {
2578
System.out.println("[" + i + "] " + zz[i]);
2583
byte bb[] = (byte[]) what;
2584
for (int i = 0; i < bb.length; i++) {
2585
System.out.println("[" + i + "] " + bb[i]);
2590
char cc[] = (char[]) what;
2591
for (int i = 0; i < cc.length; i++) {
2592
System.out.println("[" + i + "] '" + cc[i] + "'");
2597
int ii[] = (int[]) what;
2598
for (int i = 0; i < ii.length; i++) {
2599
System.out.println("[" + i + "] " + ii[i]);
2604
float ff[] = (float[]) what;
2605
for (int i = 0; i < ff.length; i++) {
2606
System.out.println("[" + i + "] " + ff[i]);
2612
double dd[] = (double[]) what;
2613
for (int i = 0; i < dd.length; i++) {
2614
System.out.println("[" + i + "] " + dd[i]);
2620
System.out.println(what);
2622
} else { // not an array
2623
System.out.println(what);
2631
// not very useful, because it only works for public (and protected?)
2632
// fields of a class, not local variables to methods
2633
public void printvar(String name) {
2635
Field field = getClass().getDeclaredField(name);
2636
println(name + " = " + field.get(this));
2637
} catch (Exception e) {
2638
e.printStackTrace();
2644
//////////////////////////////////////////////////////////////
2648
// lots of convenience methods for math with floats.
2649
// doubles are overkill for processing applets, and casting
2650
// things all the time is annoying, thus the functions below.
2653
static public final float abs(float n) {
2654
return (n < 0) ? -n : n;
2657
static public final int abs(int n) {
2658
return (n < 0) ? -n : n;
2661
static public final float sq(float a) {
2665
static public final float sqrt(float a) {
2666
return (float)Math.sqrt(a);
2669
static public final float log(float a) {
2670
return (float)Math.log(a);
2673
static public final float exp(float a) {
2674
return (float)Math.exp(a);
2677
static public final float pow(float a, float b) {
2678
return (float)Math.pow(a, b);
2682
static public final int max(int a, int b) {
2683
return (a > b) ? a : b;
2686
static public final float max(float a, float b) {
2687
return (a > b) ? a : b;
2691
static public final double max(double a, double b) {
2692
return (a > b) ? a : b;
2697
static public final int max(int a, int b, int c) {
2698
return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
2701
static public final float max(float a, float b, float c) {
2702
return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
2707
* Find the maximum value in an array.
2708
* Throws an ArrayIndexOutOfBoundsException if the array is length 0.
2709
* @param list the source array
2710
* @return The maximum value
2712
static public final int max(int[] list) {
2713
if (list.length == 0) {
2714
throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX);
2717
for (int i = 1; i < list.length; i++) {
2718
if (list[i] > max) max = list[i];
2724
* Find the maximum value in an array.
2725
* Throws an ArrayIndexOutOfBoundsException if the array is length 0.
2726
* @param list the source array
2727
* @return The maximum value
2729
static public final float max(float[] list) {
2730
if (list.length == 0) {
2731
throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX);
2733
float max = list[0];
2734
for (int i = 1; i < list.length; i++) {
2735
if (list[i] > max) max = list[i];
2742
* Find the maximum value in an array.
2743
* Throws an ArrayIndexOutOfBoundsException if the array is length 0.
2744
* @param list the source array
2745
* @return The maximum value
2748
static public final double max(double[] list) {
2749
if (list.length == 0) {
2750
throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX);
2752
double max = list[0];
2753
for (int i = 1; i < list.length; i++) {
2754
if (list[i] > max) max = list[i];
2761
static public final int min(int a, int b) {
2762
return (a < b) ? a : b;
2765
static public final float min(float a, float b) {
2766
return (a < b) ? a : b;
2770
static public final double min(double a, double b) {
2771
return (a < b) ? a : b;
2776
static public final int min(int a, int b, int c) {
2777
return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
2780
static public final float min(float a, float b, float c) {
2781
return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
2785
static public final double min(double a, double b, double c) {
2786
return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
2792
* Find the minimum value in an array.
2793
* Throws an ArrayIndexOutOfBoundsException if the array is length 0.
2794
* @param list the source array
2795
* @return The minimum value
2797
static public final int min(int[] list) {
2798
if (list.length == 0) {
2799
throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX);
2802
for (int i = 1; i < list.length; i++) {
2803
if (list[i] < min) min = list[i];
2810
* Find the minimum value in an array.
2811
* Throws an ArrayIndexOutOfBoundsException if the array is length 0.
2812
* @param list the source array
2813
* @return The minimum value
2815
static public final float min(float[] list) {
2816
if (list.length == 0) {
2817
throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX);
2819
float min = list[0];
2820
for (int i = 1; i < list.length; i++) {
2821
if (list[i] < min) min = list[i];
2828
* Find the minimum value in an array.
2829
* Throws an ArrayIndexOutOfBoundsException if the array is length 0.
2830
* @param list the source array
2831
* @return The minimum value
2834
static public final double min(double[] list) {
2835
if (list.length == 0) {
2836
throw new ArrayIndexOutOfBoundsException(ERROR_MIN_MAX);
2838
double min = list[0];
2839
for (int i = 1; i < list.length; i++) {
2840
if (list[i] < min) min = list[i];
2846
static public final int constrain(int amt, int low, int high) {
2847
return (amt < low) ? low : ((amt > high) ? high : amt);
2850
static public final float constrain(float amt, float low, float high) {
2851
return (amt < low) ? low : ((amt > high) ? high : amt);
2855
static public final float sin(float angle) {
2856
return (float)Math.sin(angle);
2859
static public final float cos(float angle) {
2860
return (float)Math.cos(angle);
2863
static public final float tan(float angle) {
2864
return (float)Math.tan(angle);
2868
static public final float asin(float value) {
2869
return (float)Math.asin(value);
2872
static public final float acos(float value) {
2873
return (float)Math.acos(value);
2876
static public final float atan(float value) {
2877
return (float)Math.atan(value);
2880
static public final float atan2(float a, float b) {
2881
return (float)Math.atan2(a, b);
2885
static public final float degrees(float radians) {
2886
return radians * RAD_TO_DEG;
2889
static public final float radians(float degrees) {
2890
return degrees * DEG_TO_RAD;
2894
static public final int ceil(float what) {
2895
return (int) Math.ceil(what);
2898
static public final int floor(float what) {
2899
return (int) Math.floor(what);
2902
static public final int round(float what) {
2903
return (int) Math.round(what);
2907
static public final float mag(float a, float b) {
2908
return (float)Math.sqrt(a*a + b*b);
2911
static public final float mag(float a, float b, float c) {
2912
return (float)Math.sqrt(a*a + b*b + c*c);
2916
static public final float dist(float x1, float y1, float x2, float y2) {
2917
return sqrt(sq(x2-x1) + sq(y2-y1));
2920
static public final float dist(float x1, float y1, float z1,
2921
float x2, float y2, float z2) {
2922
return sqrt(sq(x2-x1) + sq(y2-y1) + sq(z2-z1));
2926
static public final float lerp(float start, float stop, float amt) {
2927
return start + (stop-start) * amt;
2931
* Normalize a value to exist between 0 and 1 (inclusive).
2932
* Mathematically the opposite of lerp(), figures out what proportion
2933
* a particular value is relative to start and stop coordinates.
2935
static public final float norm(float value, float start, float stop) {
2936
return (value - start) / (stop - start);
2940
* Convenience function to map a variable from one coordinate space
2941
* to another. Equivalent to unlerp() followed by lerp().
2943
static public final float map(float value,
2944
float istart, float istop,
2945
float ostart, float ostop) {
2946
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
2951
static public final double map(double value,
2952
double istart, double istop,
2953
double ostart, double ostop) {
2954
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
2960
//////////////////////////////////////////////////////////////
2965
Random internalRandom;
2968
* Return a random number in the range [0, howbig).
2970
* The number returned will range from zero up to
2971
* (but not including) 'howbig'.
2973
public final float random(float howbig) {
2974
// for some reason (rounding error?) Math.random() * 3
2975
// can sometimes return '3' (once in ~30 million tries)
2976
// so a check was added to avoid the inclusion of 'howbig'
2978
// avoid an infinite loop
2979
if (howbig == 0) return 0;
2981
// internal random number object
2982
if (internalRandom == null) internalRandom = new Random();
2986
//value = (float)Math.random() * howbig;
2987
value = internalRandom.nextFloat() * howbig;
2988
} while (value == howbig);
2994
* Return a random number in the range [howsmall, howbig).
2996
* The number returned will range from 'howsmall' up to
2997
* (but not including 'howbig'.
2999
* If howsmall is >= howbig, howsmall will be returned,
3000
* meaning that random(5, 5) will return 5 (useful)
3001
* and random(7, 4) will return 7 (not useful.. better idea?)
3003
public final float random(float howsmall, float howbig) {
3004
if (howsmall >= howbig) return howsmall;
3005
float diff = howbig - howsmall;
3006
return random(diff) + howsmall;
3010
public final void randomSeed(long what) {
3011
// internal random number object
3012
if (internalRandom == null) internalRandom = new Random();
3013
internalRandom.setSeed(what);
3018
//////////////////////////////////////////////////////////////
3023
// octaves and amplitude amount per octave are now user controlled
3024
// via the noiseDetail() function.
3027
// cleaned up code and now using bagel's cosine table to speed up
3030
// implementation by the german demo group farbrausch
3031
// as used in their demo "art": http://www.farb-rausch.de/fr010src.zip
3033
static final int PERLIN_YWRAPB = 4;
3034
static final int PERLIN_YWRAP = 1<<PERLIN_YWRAPB;
3035
static final int PERLIN_ZWRAPB = 8;
3036
static final int PERLIN_ZWRAP = 1<<PERLIN_ZWRAPB;
3037
static final int PERLIN_SIZE = 4095;
3039
int perlin_octaves = 4; // default to medium smooth
3040
float perlin_amp_falloff = 0.5f; // 50% reduction/octave
3043
// new vars needed due to recent change of cos table in PGraphics
3044
int perlin_TWOPI, perlin_PI;
3045
float[] perlin_cosTable;
3048
Random perlinRandom;
3052
* Computes the Perlin noise function value at point x.
3054
public float noise(float x) {
3055
// is this legit? it's a dumb way to do it (but repair it later)
3056
return noise(x, 0f, 0f);
3060
* Computes the Perlin noise function value at the point x, y.
3062
public float noise(float x, float y) {
3063
return noise(x, y, 0f);
3067
* Computes the Perlin noise function value at x, y, z.
3069
public float noise(float x, float y, float z) {
3070
if (perlin == null) {
3071
if (perlinRandom == null) {
3072
perlinRandom = new Random();
3074
perlin = new float[PERLIN_SIZE + 1];
3075
for (int i = 0; i < PERLIN_SIZE + 1; i++) {
3076
perlin[i] = perlinRandom.nextFloat(); //(float)Math.random();
3079
// noise broke due to recent change of cos table in PGraphics
3080
// this will take care of it
3081
perlin_cosTable = PGraphics.cosLUT;
3082
perlin_TWOPI = perlin_PI = PGraphics.SINCOS_LENGTH;
3090
int xi=(int)x, yi=(int)y, zi=(int)z;
3091
float xf = (float)(x-xi);
3092
float yf = (float)(y-yi);
3093
float zf = (float)(z-zi);
3101
for (int i=0; i<perlin_octaves; i++) {
3102
int of=xi+(yi<<PERLIN_YWRAPB)+(zi<<PERLIN_ZWRAPB);
3107
n1 = perlin[of&PERLIN_SIZE];
3108
n1 += rxf*(perlin[(of+1)&PERLIN_SIZE]-n1);
3109
n2 = perlin[(of+PERLIN_YWRAP)&PERLIN_SIZE];
3110
n2 += rxf*(perlin[(of+PERLIN_YWRAP+1)&PERLIN_SIZE]-n2);
3114
n2 = perlin[of&PERLIN_SIZE];
3115
n2 += rxf*(perlin[(of+1)&PERLIN_SIZE]-n2);
3116
n3 = perlin[(of+PERLIN_YWRAP)&PERLIN_SIZE];
3117
n3 += rxf*(perlin[(of+PERLIN_YWRAP+1)&PERLIN_SIZE]-n3);
3120
n1 += noise_fsc(zf)*(n2-n1);
3123
ampl *= perlin_amp_falloff;
3128
if (xf>=1.0f) { xi++; xf--; }
3129
if (yf>=1.0f) { yi++; yf--; }
3130
if (zf>=1.0f) { zi++; zf--; }
3136
// now adjusts to the size of the cosLUT used via
3137
// the new variables, defined above
3138
private float noise_fsc(float i) {
3139
// using bagel's cosine table instead
3140
return 0.5f*(1.0f-perlin_cosTable[(int)(i*perlin_PI)%perlin_TWOPI]);
3144
// make perlin noise quality user controlled to allow
3145
// for different levels of detail. lower values will produce
3146
// smoother results as higher octaves are surpressed
3148
public void noiseDetail(int lod) {
3149
if (lod>0) perlin_octaves=lod;
3152
public void noiseDetail(int lod, float falloff) {
3153
if (lod>0) perlin_octaves=lod;
3154
if (falloff>0) perlin_amp_falloff=falloff;
3157
public void noiseSeed(long what) {
3158
if (perlinRandom == null) perlinRandom = new Random();
3159
perlinRandom.setSeed(what);
3160
// force table reset after changing the random number seed [0122]
3166
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3169
protected String[] loadImageFormats;
3173
* Load an image from the data folder or a local directory.
3174
* Supports .gif (including transparency), .tga, and .jpg images.
3175
* In Java 1.3 or later, .png images are
3176
* <A HREF="http://java.sun.com/j2se/1.3/docs/guide/2d/new_features.html">
3177
* also supported</A>.
3179
* Generally, loadImage() should only be used during setup, because
3180
* re-loading images inside draw() is likely to cause a significant
3181
* delay while memory is allocated and the thread blocks while waiting
3182
* for the image to load because loading is not asynchronous.
3184
* To load several images asynchronously, see more information in the
3185
* FAQ about writing your own threaded image loading method.
3187
* As of 0096, returns null if no image of that name is found,
3188
* rather than an error.
3190
* Release 0115 also provides support for reading TIFF and RLE-encoded
3191
* Targa (.tga) files written by Processing via save() and saveFrame().
3192
* Other TIFF and Targa files will probably not load, use a different
3193
* format (gif, jpg and png are safest bets) when creating images with
3194
* another application to use with Processing.
3196
* Also in release 0115, more image formats (BMP and others) can
3197
* be read when using Java 1.4 and later. Because many people still
3198
* use Java 1.1 and 1.3, these formats are not recommended for
3199
* work that will be posted on the web. To get a list of possible
3200
* image formats for use with Java 1.4 and later, use the following:
3201
* <TT>println(javax.imageio.ImageIO.getReaderFormatNames())</TT>
3203
* Images are loaded via a byte array that is passed to
3204
* Toolkit.createImage(). Unfortunately, we cannot use Applet.getImage()
3205
* because it takes a URL argument, which would be a pain in the a--
3206
* to make work consistently for online and local sketches.
3207
* Sometimes this causes problems, resulting in issues like
3208
* <A HREF="http://dev.processing.org/bugs/show_bug.cgi?id=279">Bug 279</A>
3210
* <A HREF="http://dev.processing.org/bugs/show_bug.cgi?id=305">Bug 305</A>.
3211
* In release 0115, everything was instead run through javax.imageio,
3212
* but that turned out to be very slow, see
3213
* <A HREF="http://dev.processing.org/bugs/show_bug.cgi?id=392">Bug 392</A>.
3214
* As a result, starting with 0116, the following happens:
3216
* <LI>TGA and TIFF images are loaded using the internal load methods.
3217
* <LI>JPG, GIF, and PNG images are loaded via loadBytes().
3218
* <LI>If the image still isn't loaded, it's passed to javax.imageio.
3220
* For releases 0116 and later, if you have problems such as those seen
3221
* in Bugs 279 and 305, use Applet.getImage() instead. You'll be stuck
3222
* with the limitations of getImage() (the headache of dealing with
3223
* online/offline use). Set up your own MediaTracker, and pass the resulting
3224
* java.awt.Image to the PImage constructor that takes an AWT image.
3226
public PImage loadImage(String filename) {
3227
return loadImage(filename, null);
3232
* Identical to loadImage, but allows you to specify the type of
3233
* image by its extension. Especially useful when downloading from
3236
* Use 'unknown' as the extension to pass off to the default
3237
* image loader that handles gif, jpg, and png.
3239
public PImage loadImage(String filename, String extension) {
3240
if (extension == null) {
3241
String lower = filename.toLowerCase();
3242
int dot = filename.lastIndexOf('.');
3244
extension = "unknown"; // no extension found
3246
extension = lower.substring(dot + 1);
3248
// check for, and strip any parameters on the url, i.e.
3249
// filename.jpg?blah=blah&something=that
3250
int question = extension.indexOf('?');
3251
if (question != -1) {
3252
extension = extension.substring(0, question);
3256
// just in case. them users will try anything!
3257
extension = extension.toLowerCase();
3259
if (extension.equals("tga")) {
3261
return loadImageTGA(filename);
3262
} catch (IOException e) {
3263
e.printStackTrace();
3268
if (extension.equals("tif") || extension.equals("tiff")) {
3269
byte bytes[] = loadBytes(filename);
3270
return (bytes == null) ? null : PImage.loadTIFF(bytes);
3273
// For jpeg, gif, and png, load them using createImage(),
3274
// because the javax.imageio code was found to be much slower, see
3275
// <A HREF="http://dev.processing.org/bugs/show_bug.cgi?id=392">Bug 392</A>.
3277
if (extension.equals("jpg") || extension.equals("jpeg") ||
3278
extension.equals("gif") || extension.equals("png") ||
3279
extension.equals("unknown")) {
3280
byte bytes[] = loadBytes(filename);
3281
if (bytes == null) {
3284
Image awtImage = Toolkit.getDefaultToolkit().createImage(bytes);
3285
PImage image = loadImageMT(awtImage);
3286
if (image.width == -1) {
3287
System.err.println("The file " + filename +
3288
" contains bad image data, or may not be an image.");
3290
// if it's a .gif image, test to see if it has transparency
3291
if (extension.equals("gif") || extension.equals("png")) {
3297
} catch (Exception e) {
3298
// show error, but move on to the stuff below, see if it'll work
3299
e.printStackTrace();
3302
if (loadImageFormats == null) {
3303
loadImageFormats = ImageIO.getReaderFormatNames();
3305
if (loadImageFormats != null) {
3306
for (int i = 0; i < loadImageFormats.length; i++) {
3307
if (extension.equals(loadImageFormats[i])) {
3308
return loadImageIO(filename);
3313
// failed, could not load image after all those attempts
3314
System.err.println("Could not find a method to load " + filename);
3319
public PImage requestImage(String filename) {
3320
return requestImage(filename, null);
3324
public PImage requestImage(String filename, String extension) {
3325
PImage vessel = createImage(0, 0, ARGB);
3326
AsyncImageLoader ail =
3327
new AsyncImageLoader(filename, extension, vessel);
3334
* By trial and error, four image loading threads seem to work best when
3335
* loading images from online. This is consistent with the number of open
3336
* connections that web browsers will maintain. The variable is made public
3337
* (however no accessor has been added since it's esoteric) if you really
3338
* want to have control over the value used. For instance, when loading local
3339
* files, it might be better to only have a single thread (or two) loading
3340
* images so that you're disk isn't simply jumping around.
3342
public int requestImageMax = 4;
3343
volatile int requestImageCount;
3345
class AsyncImageLoader extends Thread {
3350
public AsyncImageLoader(String filename, String extension, PImage vessel) {
3351
this.filename = filename;
3352
this.extension = extension;
3353
this.vessel = vessel;
3357
while (requestImageCount == requestImageMax) {
3360
} catch (InterruptedException e) { }
3362
requestImageCount++;
3364
PImage actual = loadImage(filename, extension);
3366
// An error message should have already printed
3367
if (actual == null) {
3372
vessel.width = actual.width;
3373
vessel.height = actual.height;
3374
vessel.format = actual.format;
3375
vessel.pixels = actual.pixels;
3377
requestImageCount--;
3383
* Load an AWT image synchronously by setting up a MediaTracker for
3384
* a single image, and blocking until it has loaded.
3386
protected PImage loadImageMT(Image awtImage) {
3387
MediaTracker tracker = new MediaTracker(this);
3388
tracker.addImage(awtImage, 0);
3390
tracker.waitForAll();
3391
} catch (InterruptedException e) {
3392
//e.printStackTrace(); // non-fatal, right?
3395
PImage image = new PImage(awtImage);
3396
image.parent = this;
3402
* Use Java 1.4 ImageIO methods to load an image.
3404
protected PImage loadImageIO(String filename) {
3405
InputStream stream = createInput(filename);
3406
if (stream == null) {
3407
System.err.println("The image " + filename + " could not be found.");
3412
BufferedImage bi = ImageIO.read(stream);
3413
PImage outgoing = new PImage(bi.getWidth(), bi.getHeight());
3414
outgoing.parent = this;
3416
bi.getRGB(0, 0, outgoing.width, outgoing.height,
3417
outgoing.pixels, 0, outgoing.width);
3419
// check the alpha for this image
3420
// was gonna call getType() on the image to see if RGB or ARGB,
3421
// but it's not actually useful, since gif images will come through
3422
// as TYPE_BYTE_INDEXED, which means it'll still have to check for
3423
// the transparency. also, would have to iterate through all the other
3424
// types and guess whether alpha was in there, so.. just gonna stick
3425
// with the old method.
3426
outgoing.checkAlpha();
3431
} catch (Exception e) {
3432
e.printStackTrace();
3439
* Targa image loader for RLE-compressed TGA files.
3441
* Rewritten for 0115 to read/write RLE-encoded targa images.
3442
* For 0125, non-RLE encoded images are now supported, along with
3443
* images whose y-order is reversed (which is standard for TGA files).
3445
protected PImage loadImageTGA(String filename) throws IOException {
3446
InputStream is = createInput(filename);
3447
if (is == null) return null;
3449
byte header[] = new byte[18];
3452
int count = is.read(header, offset, header.length - offset);
3453
if (count == -1) return null;
3455
} while (offset < 18);
3458
header[2] image type code
3459
2 (0x02) - Uncompressed, RGB images.
3460
3 (0x03) - Uncompressed, black and white images.
3461
10 (0x0A) - Runlength encoded RGB images.
3462
11 (0x0B) - Compressed, black and white images. (grayscale?)
3464
header[16] is the bit depth (8, 24, 32)
3466
header[17] image descriptor (packed bits)
3467
0x20 is 32 = origin upper-left
3468
0x28 is 32 + 8 = origin upper-left + 32 bits
3471
128 64 32 16 8 4 2 1
3476
if (((header[2] == 3) || (header[2] == 11)) && // B&W, plus RLE or not
3477
(header[16] == 8) && // 8 bits
3478
((header[17] == 0x8) || (header[17] == 0x28))) { // origin, 32 bit
3481
} else if (((header[2] == 2) || (header[2] == 10)) && // RGB, RLE or not
3482
(header[16] == 24) && // 24 bits
3483
((header[17] == 0x20) || (header[17] == 0))) { // origin
3486
} else if (((header[2] == 2) || (header[2] == 10)) &&
3487
(header[16] == 32) &&
3488
((header[17] == 0x8) || (header[17] == 0x28))) { // origin, 32
3493
System.err.println("Unknown .tga file format for " + filename);
3494
//" (" + header[2] + " " +
3495
//(header[16] & 0xff) + " " +
3496
//hex(header[17], 2) + ")");
3500
int w = ((header[13] & 0xff) << 8) + (header[12] & 0xff);
3501
int h = ((header[15] & 0xff) << 8) + (header[14] & 0xff);
3502
PImage outgoing = createImage(w, h, format);
3504
// where "reversed" means upper-left corner (normal for most of
3505
// the modernized world, but "reversed" for the tga spec)
3506
boolean reversed = (header[17] & 0x20) != 0;
3508
if ((header[2] == 2) || (header[2] == 3)) { // not RLE encoded
3510
int index = (h-1) * w;
3513
for (int y = h-1; y >= 0; y--) {
3514
for (int x = 0; x < w; x++) {
3515
outgoing.pixels[index + x] = is.read();
3521
for (int y = h-1; y >= 0; y--) {
3522
for (int x = 0; x < w; x++) {
3523
outgoing.pixels[index + x] =
3524
is.read() | (is.read() << 8) | (is.read() << 16) |
3531
for (int y = h-1; y >= 0; y--) {
3532
for (int x = 0; x < w; x++) {
3533
outgoing.pixels[index + x] =
3534
is.read() | (is.read() << 8) | (is.read() << 16) |
3540
} else { // not reversed
3544
for (int i = 0; i < count; i++) {
3545
outgoing.pixels[i] = is.read();
3549
for (int i = 0; i < count; i++) {
3550
outgoing.pixels[i] =
3551
is.read() | (is.read() << 8) | (is.read() << 16) |
3556
for (int i = 0; i < count; i++) {
3557
outgoing.pixels[i] =
3558
is.read() | (is.read() << 8) | (is.read() << 16) |
3565
} else { // header[2] is 10 or 11
3567
int px[] = outgoing.pixels;
3569
while (index < px.length) {
3570
int num = is.read();
3571
boolean isRLE = (num & 0x80) != 0;
3573
num -= 127; // (num & 0x7F) + 1
3580
pixel = 0xFF000000 |
3581
is.read() | (is.read() << 8) | (is.read() << 16);
3582
//(is.read() << 16) | (is.read() << 8) | is.read();
3586
(is.read() << 8) | (is.read() << 16) | (is.read() << 24);
3589
for (int i = 0; i < num; i++) {
3590
px[index++] = pixel;
3591
if (index == px.length) break;
3593
} else { // write up to 127 bytes as uncompressed
3597
for (int i = 0; i < num; i++) {
3598
px[index++] = is.read();
3602
for (int i = 0; i < num; i++) {
3603
px[index++] = 0xFF000000 |
3604
is.read() | (is.read() << 8) | (is.read() << 16);
3605
//(is.read() << 16) | (is.read() << 8) | is.read();
3609
for (int i = 0; i < num; i++) {
3610
px[index++] = is.read() | //(is.read() << 24) |
3611
(is.read() << 8) | (is.read() << 16) | (is.read() << 24);
3612
//(is.read() << 16) | (is.read() << 8) | is.read();
3620
int[] temp = new int[w];
3621
for (int y = 0; y < h/2; y++) {
3623
System.arraycopy(px, y*w, temp, 0, w);
3624
System.arraycopy(px, z*w, px, y*w, w);
3625
System.arraycopy(temp, 0, px, z*w, w);
3635
//////////////////////////////////////////////////////////////
3641
* Load a geometry from a file as a PShape. Currently only supports SVG data.
3643
public PShape loadShape(String filename) {
3644
if (filename.toLowerCase().endsWith(".svg")) {
3645
return new PShapeSVG(this, filename);
3652
//////////////////////////////////////////////////////////////
3657
public PFont loadFont(String filename) {
3659
InputStream input = createInput(filename);
3660
return new PFont(input);
3662
} catch (Exception e) {
3663
die("Could not load font " + filename + ". " +
3664
"Make sure that the font has been copied " +
3665
"to the data folder of your sketch.", e);
3671
public PFont createFont(String name, float size) {
3672
return createFont(name, size, true, PFont.DEFAULT_CHARSET);
3676
public PFont createFont(String name, float size, boolean smooth) {
3677
return createFont(name, size, smooth, PFont.DEFAULT_CHARSET);
3682
* Create a .vlw font on the fly from either a font name that's
3683
* installed on the system, or from a .ttf or .otf that's inside
3684
* the data folder of this sketch.
3686
* Only works with Java 1.3 or later. Many .otf fonts don't seem
3687
* to be supported by Java, perhaps because they're CFF based?
3689
* Font names are inconsistent across platforms and Java versions.
3690
* On Mac OS X, Java 1.3 uses the font menu name of the font,
3691
* whereas Java 1.4 uses the PostScript name of the font. Java 1.4
3692
* on OS X will also accept the font menu name as well. On Windows,
3693
* it appears that only the menu names are used, no matter what
3694
* Java version is in use. Naming system unknown/untested for 1.5.
3696
* Use 'null' for the charset if you want to use any of the 65,536
3697
* unicode characters that exist in the font. Note that this can
3698
* produce an enormous file or may cause an OutOfMemoryError.
3700
public PFont createFont(String name, float size,
3701
boolean smooth, char charset[]) {
3702
String lowerName = name.toLowerCase();
3703
Font baseFont = null;
3706
if (lowerName.endsWith(".otf") || lowerName.endsWith(".ttf")) {
3707
InputStream stream = createInput(name);
3708
if (stream == null) {
3709
System.err.println("The font \"" + name + "\" " +
3710
"is missing or inaccessible, make sure " +
3711
"the URL is valid or that the file has been " +
3712
"added to your sketch and is readable.");
3715
baseFont = Font.createFont(Font.TRUETYPE_FONT, createInput(name));
3718
//baseFont = new Font(name, Font.PLAIN, 1);
3719
baseFont = PFont.findFont(name);
3721
} catch (Exception e) {
3722
System.err.println("Problem using createFont() with " + name);
3723
e.printStackTrace();
3725
return new PFont(baseFont.deriveFont(size), smooth, charset);
3730
//////////////////////////////////////////////////////////////
3732
// FILE/FOLDER SELECTION
3735
public File selectedFile;
3736
protected Frame parentFrame;
3739
protected void checkParentFrame() {
3740
if (parentFrame == null) {
3741
Component comp = getParent();
3742
while (comp != null) {
3743
if (comp instanceof Frame) {
3744
parentFrame = (Frame) comp;
3747
comp = comp.getParent();
3749
// Who you callin' a hack?
3750
if (parentFrame == null) {
3751
parentFrame = new Frame();
3758
* Open a platform-specific file chooser dialog to select a file for input.
3759
* @return full path to the selected file, or null if no selection.
3761
public String selectInput() {
3762
return selectInput("Select a file...");
3767
* Open a platform-specific file chooser dialog to select a file for input.
3768
* @param prompt Mesage to show the user when prompting for a file.
3769
* @return full path to the selected file, or null if canceled.
3771
public String selectInput(String prompt) {
3772
return selectFileImpl(prompt, FileDialog.LOAD);
3777
* Open a platform-specific file save dialog to select a file for output.
3778
* @return full path to the file entered, or null if canceled.
3780
public String selectOutput() {
3781
return selectOutput("Save as...");
3786
* Open a platform-specific file save dialog to select a file for output.
3787
* @param prompt Mesage to show the user when prompting for a file.
3788
* @return full path to the file entered, or null if canceled.
3790
public String selectOutput(String prompt) {
3791
return selectFileImpl(prompt, FileDialog.SAVE);
3795
protected String selectFileImpl(final String prompt, final int mode) {
3799
SwingUtilities.invokeAndWait(new Runnable() {
3801
FileDialog fileDialog =
3802
new FileDialog(parentFrame, prompt, mode);
3803
fileDialog.setVisible(true);
3804
String directory = fileDialog.getDirectory();
3805
String filename = fileDialog.getFile();
3807
(filename == null) ? null : new File(directory, filename);
3810
return (selectedFile == null) ? null : selectedFile.getAbsolutePath();
3812
} catch (Exception e) {
3813
e.printStackTrace();
3820
* Open a platform-specific folder chooser dialog.
3821
* @return full path to the selected folder, or null if no selection.
3823
public String selectFolder() {
3824
return selectFolder("Select a folder...");
3829
* Open a platform-specific folder chooser dialog.
3830
* @param prompt Mesage to show the user when prompting for a file.
3831
* @return full path to the selected folder, or null if no selection.
3833
public String selectFolder(final String prompt) {
3837
SwingUtilities.invokeAndWait(new Runnable() {
3839
if (platform == MACOSX) {
3840
FileDialog fileDialog =
3841
new FileDialog(parentFrame, prompt, FileDialog.LOAD);
3842
System.setProperty("apple.awt.fileDialogForDirectories", "true");
3843
fileDialog.setVisible(true);
3844
System.setProperty("apple.awt.fileDialogForDirectories", "false");
3845
String filename = fileDialog.getFile();
3846
selectedFile = (filename == null) ? null :
3847
new File(fileDialog.getDirectory(), fileDialog.getFile());
3849
JFileChooser fileChooser = new JFileChooser();
3850
fileChooser.setDialogTitle(prompt);
3851
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
3853
int returned = fileChooser.showOpenDialog(parentFrame);
3854
System.out.println(returned);
3855
if (returned == JFileChooser.CANCEL_OPTION) {
3856
selectedFile = null;
3858
selectedFile = fileChooser.getSelectedFile();
3863
return (selectedFile == null) ? null : selectedFile.getAbsolutePath();
3865
} catch (Exception e) {
3866
e.printStackTrace();
3873
//////////////////////////////////////////////////////////////
3875
// READERS AND WRITERS
3879
* I want to read lines from a file. I have RSI from typing these
3880
* eight lines of code so many times.
3882
public BufferedReader createReader(String filename) {
3884
InputStream is = createInput(filename);
3886
System.err.println(filename + " does not exist or could not be read");
3889
return createReader(is);
3891
} catch (Exception e) {
3892
if (filename == null) {
3893
System.err.println("Filename passed to reader() was null");
3895
System.err.println("Couldn't create a reader for " + filename);
3903
* I want to read lines from a file. And I'm still annoyed.
3905
static public BufferedReader createReader(File file) {
3907
InputStream is = new FileInputStream(file);
3908
if (file.getName().toLowerCase().endsWith(".gz")) {
3909
is = new GZIPInputStream(is);
3911
return createReader(is);
3913
} catch (Exception e) {
3915
throw new RuntimeException("File passed to createReader() was null");
3917
e.printStackTrace();
3918
throw new RuntimeException("Couldn't create a reader for " +
3919
file.getAbsolutePath());
3927
* I want to read lines from a stream. If I have to type the
3928
* following lines any more I'm gonna send Sun my medical bills.
3930
static public BufferedReader createReader(InputStream input) {
3931
InputStreamReader isr = null;
3933
isr = new InputStreamReader(input, "UTF-8");
3934
} catch (UnsupportedEncodingException e) { } // not gonna happen
3935
return new BufferedReader(isr);
3940
* I want to print lines to a file. Why can't I?
3942
public PrintWriter createWriter(String filename) {
3943
return createWriter(saveFile(filename));
3948
* I want to print lines to a file. I have RSI from typing these
3949
* eight lines of code so many times.
3951
static public PrintWriter createWriter(File file) {
3953
createPath(file); // make sure in-between folders exist
3954
OutputStream output = new FileOutputStream(file);
3955
if (file.getName().toLowerCase().endsWith(".gz")) {
3956
output = new GZIPOutputStream(output);
3958
return createWriter(output);
3960
} catch (Exception e) {
3962
throw new RuntimeException("File passed to createWriter() was null");
3964
e.printStackTrace();
3965
throw new RuntimeException("Couldn't create a writer for " +
3966
file.getAbsolutePath());
3974
* I want to print lines to a file. Why am I always explaining myself?
3975
* It's the JavaSoft API engineers who need to explain themselves.
3977
static public PrintWriter createWriter(OutputStream output) {
3979
OutputStreamWriter osw = new OutputStreamWriter(output, "UTF-8");
3980
return new PrintWriter(osw);
3981
} catch (UnsupportedEncodingException e) { } // not gonna happen
3986
//////////////////////////////////////////////////////////////
3992
* @deprecated As of release 0136, use createInput() instead.
3994
public InputStream openStream(String filename) {
3995
return createInput(filename);
4000
* Simplified method to open a Java InputStream.
4002
* This method is useful if you want to use the facilities provided
4003
* by PApplet to easily open things from the data folder or from a URL,
4004
* but want an InputStream object so that you can use other Java
4005
* methods to take more control of how the stream is read.
4007
* If the requested item doesn't exist, null is returned.
4008
* (Prior to 0096, die() would be called, killing the applet)
4010
* For 0096+, the "data" folder is exported intact with subfolders,
4011
* and openStream() properly handles subdirectories from the data folder
4013
* If not online, this will also check to see if the user is asking
4014
* for a file whose name isn't properly capitalized. This helps prevent
4015
* issues when a sketch is exported to the web, where case sensitivity
4016
* matters, as opposed to Windows and the Mac OS default where
4017
* case sensitivity is preserved but ignored.
4019
* It is strongly recommended that libraries use this method to open
4020
* data files, so that the loading sequence is handled in the same way
4021
* as functions like loadBytes(), loadImage(), etc.
4023
* The filename passed in can be:
4025
* <LI>A URL, for instance openStream("http://processing.org/");
4026
* <LI>A file in the sketch's data folder
4027
* <LI>Another file to be opened locally (when running as an application)
4030
public InputStream createInput(String filename) {
4031
InputStream input = createInputRaw(filename);
4032
if ((input != null) && filename.toLowerCase().endsWith(".gz")) {
4034
return new GZIPInputStream(input);
4035
} catch (IOException e) {
4036
e.printStackTrace();
4045
* Call openStream() without automatic gzip decompression.
4047
public InputStream createInputRaw(String filename) {
4048
InputStream stream = null;
4050
if (filename == null) return null;
4052
if (filename.length() == 0) {
4053
// an error will be called by the parent function
4054
//System.err.println("The filename passed to openStream() was empty.");
4058
// safe to check for this as a url first. this will prevent online
4059
// access logs from being spammed with GET /sketchfolder/http://blahblah
4061
URL url = new URL(filename);
4062
stream = url.openStream();
4065
} catch (MalformedURLException mfue) {
4066
// not a url, that's fine
4068
} catch (FileNotFoundException fnfe) {
4069
// Java 1.5 likes to throw this when URL not available. (fix for 0119)
4070
// http://dev.processing.org/bugs/show_bug.cgi?id=403
4072
} catch (IOException e) {
4073
// changed for 0117, shouldn't be throwing exception
4074
e.printStackTrace();
4075
//System.err.println("Error downloading from URL " + filename);
4077
//throw new RuntimeException("Error downloading from URL " + filename);
4080
// Moved this earlier than the getResourceAsStream() checks, because
4081
// calling getResourceAsStream() on a directory lists its contents.
4082
// http://dev.processing.org/bugs/show_bug.cgi?id=716
4084
// First see if it's in a data folder. This may fail by throwing
4085
// a SecurityException. If so, this whole block will be skipped.
4086
File file = new File(dataPath(filename));
4087
if (!file.exists()) {
4088
// next see if it's just in the sketch folder
4089
file = new File(sketchPath, filename);
4091
if (file.isDirectory()) {
4094
if (file.exists()) {
4096
// handle case sensitivity check
4097
String filePath = file.getCanonicalPath();
4098
String filenameActual = new File(filePath).getName();
4099
// make sure there isn't a subfolder prepended to the name
4100
String filenameShort = new File(filename).getName();
4101
// if the actual filename is the same, but capitalized
4102
// differently, warn the user.
4103
//if (filenameActual.equalsIgnoreCase(filenameShort) &&
4104
//!filenameActual.equals(filenameShort)) {
4105
if (!filenameActual.equals(filenameShort)) {
4106
throw new RuntimeException("This file is named " +
4107
filenameActual + " not " +
4108
filename + ". Rename the file " +
4109
"or change your code.");
4111
} catch (IOException e) { }
4114
// if this file is ok, may as well just load it
4115
stream = new FileInputStream(file);
4116
if (stream != null) return stream;
4118
// have to break these out because a general Exception might
4119
// catch the RuntimeException being thrown above
4120
} catch (IOException ioe) {
4121
} catch (SecurityException se) { }
4123
// Using getClassLoader() prevents java from converting dots
4124
// to slashes or requiring a slash at the beginning.
4125
// (a slash as a prefix means that it'll load from the root of
4126
// the jar, rather than trying to dig into the package location)
4127
ClassLoader cl = getClass().getClassLoader();
4129
// by default, data files are exported to the root path of the jar.
4130
// (not the data folder) so check there first.
4131
stream = cl.getResourceAsStream("data/" + filename);
4132
if (stream != null) {
4133
String cn = stream.getClass().getName();
4134
// this is an irritation of sun's java plug-in, which will return
4135
// a non-null stream for an object that doesn't exist. like all good
4136
// things, this is probably introduced in java 1.5. awesome!
4137
// http://dev.processing.org/bugs/show_bug.cgi?id=359
4138
if (!cn.equals("sun.plugin.cache.EmptyInputStream")) {
4143
// When used with an online script, also need to check without the
4144
// data folder, in case it's not in a subfolder called 'data'.
4145
// http://dev.processing.org/bugs/show_bug.cgi?id=389
4146
stream = cl.getResourceAsStream(filename);
4147
if (stream != null) {
4148
String cn = stream.getClass().getName();
4149
if (!cn.equals("sun.plugin.cache.EmptyInputStream")) {
4155
// attempt to load from a local file, used when running as
4156
// an application, or as a signed applet
4157
try { // first try to catch any security exceptions
4159
stream = new FileInputStream(dataPath(filename));
4160
if (stream != null) return stream;
4161
} catch (IOException e2) { }
4164
stream = new FileInputStream(sketchPath(filename));
4165
if (stream != null) return stream;
4166
} catch (Exception e) { } // ignored
4169
stream = new FileInputStream(filename);
4170
if (stream != null) return stream;
4171
} catch (IOException e1) { }
4173
} catch (SecurityException se) { } // online, whups
4175
} catch (Exception e) {
4176
//die(e.getMessage(), e);
4177
e.printStackTrace();
4183
static public InputStream createInput(File file) {
4185
InputStream input = new FileInputStream(file);
4186
if (file.getName().toLowerCase().endsWith(".gz")) {
4187
return new GZIPInputStream(input);
4191
} catch (IOException e) {
4193
throw new RuntimeException("File passed to openStream() was null");
4196
e.printStackTrace();
4197
throw new RuntimeException("Couldn't openStream() for " +
4198
file.getAbsolutePath());
4204
public byte[] loadBytes(String filename) {
4205
InputStream is = createInput(filename);
4206
if (is != null) return loadBytes(is);
4208
System.err.println("The file \"" + filename + "\" " +
4209
"is missing or inaccessible, make sure " +
4210
"the URL is valid or that the file has been " +
4211
"added to your sketch and is readable.");
4216
static public byte[] loadBytes(InputStream input) {
4218
BufferedInputStream bis = new BufferedInputStream(input);
4219
ByteArrayOutputStream out = new ByteArrayOutputStream();
4226
return out.toByteArray();
4228
} catch (IOException e) {
4229
e.printStackTrace();
4230
//throw new RuntimeException("Couldn't load bytes from stream");
4236
static public byte[] loadBytes(File file) {
4237
InputStream is = createInput(file);
4238
return loadBytes(is);
4242
static public String[] loadStrings(File file) {
4243
InputStream is = createInput(file);
4244
if (is != null) return loadStrings(is);
4250
* Load data from a file and shove it into a String array.
4252
* Exceptions are handled internally, when an error, occurs, an
4253
* exception is printed to the console and 'null' is returned,
4254
* but the program continues running. This is a tradeoff between
4255
* 1) showing the user that there was a problem but 2) not requiring
4256
* that all i/o code is contained in try/catch blocks, for the sake
4257
* of new users (or people who are just trying to get things done
4258
* in a "scripting" fashion. If you want to handle exceptions,
4259
* use Java methods for I/O.
4261
public String[] loadStrings(String filename) {
4262
InputStream is = createInput(filename);
4263
if (is != null) return loadStrings(is);
4265
System.err.println("The file \"" + filename + "\" " +
4266
"is missing or inaccessible, make sure " +
4267
"the URL is valid or that the file has been " +
4268
"added to your sketch and is readable.");
4273
static public String[] loadStrings(InputStream input) {
4275
BufferedReader reader =
4276
new BufferedReader(new InputStreamReader(input, "UTF-8"));
4278
String lines[] = new String[100];
4281
while ((line = reader.readLine()) != null) {
4282
if (lineCount == lines.length) {
4283
String temp[] = new String[lineCount << 1];
4284
System.arraycopy(lines, 0, temp, 0, lineCount);
4287
lines[lineCount++] = line;
4291
if (lineCount == lines.length) {
4295
// resize array to appropriate amount for these lines
4296
String output[] = new String[lineCount];
4297
System.arraycopy(lines, 0, output, 0, lineCount);
4300
} catch (IOException e) {
4301
e.printStackTrace();
4302
//throw new RuntimeException("Error inside loadStrings()");
4309
//////////////////////////////////////////////////////////////
4315
* Similar to createInput() (formerly openStream), this creates a Java
4316
* OutputStream for a given filename or path. The file will be created in
4317
* the sketch folder, or in the same folder as an exported application.
4319
* If the path does not exist, intermediate folders will be created. If an
4320
* exception occurs, it will be printed to the console, and null will be
4323
* Future releases may also add support for handling HTTP POST via this
4324
* method (for better symmetry with createInput), however that's maybe a
4325
* little too clever (and then we'd have to add the same features to the
4326
* other file functions like createWriter). Who you callin' bloated?
4328
public OutputStream createOutput(String filename) {
4329
return createOutput(saveFile(filename));
4333
static public OutputStream createOutput(File file) {
4335
createPath(file); // make sure the path exists
4336
FileOutputStream fos = new FileOutputStream(file);
4337
if (file.getName().toLowerCase().endsWith(".gz")) {
4338
return new GZIPOutputStream(fos);
4342
} catch (IOException e) {
4343
e.printStackTrace();
4350
* Save the contents of a stream to a file in the sketch folder.
4351
* This is basically saveBytes(blah, loadBytes()), but done
4352
* more efficiently (and with less confusing syntax).
4354
public void saveStream(String targetFilename, String sourceLocation) {
4355
saveStream(saveFile(targetFilename), sourceLocation);
4360
* Identical to the other saveStream(), but writes to a File
4361
* object, for greater control over the file location.
4362
* Note that unlike other api methods, this will not automatically
4363
* compress or uncompress gzip files.
4365
public void saveStream(File targetFile, String sourceLocation) {
4366
saveStream(targetFile, createInputRaw(sourceLocation));
4370
static public void saveStream(File targetFile, InputStream sourceStream) {
4371
File tempFile = null;
4373
File parentDir = targetFile.getParentFile();
4374
tempFile = File.createTempFile(targetFile.getName(), null, parentDir);
4376
BufferedInputStream bis = new BufferedInputStream(sourceStream, 16384);
4377
FileOutputStream fos = new FileOutputStream(tempFile);
4378
BufferedOutputStream bos = new BufferedOutputStream(fos);
4380
byte[] buffer = new byte[8192];
4382
while ((bytesRead = bis.read(buffer)) != -1) {
4383
bos.write(buffer, 0, bytesRead);
4390
if (!tempFile.renameTo(targetFile)) {
4391
System.err.println("Could not rename temporary file " +
4392
tempFile.getAbsolutePath());
4394
} catch (IOException e) {
4395
if (tempFile != null) {
4398
e.printStackTrace();
4404
* Saves bytes to a file to inside the sketch folder.
4405
* The filename can be a relative path, i.e. "poo/bytefun.txt"
4406
* would save to a file named "bytefun.txt" to a subfolder
4407
* called 'poo' inside the sketch folder. If the in-between
4408
* subfolders don't exist, they'll be created.
4410
public void saveBytes(String filename, byte buffer[]) {
4411
saveBytes(saveFile(filename), buffer);
4416
* Saves bytes to a specific File location specified by the user.
4418
static public void saveBytes(File file, byte buffer[]) {
4419
File tempFile = null;
4421
File parentDir = file.getParentFile();
4422
tempFile = File.createTempFile(file.getName(), null, parentDir);
4425
String filename = file.getAbsolutePath();
4426
createPath(filename);
4427
OutputStream output = new FileOutputStream(file);
4428
if (file.getName().toLowerCase().endsWith(".gz")) {
4429
output = new GZIPOutputStream(output);
4432
OutputStream output = createOutput(tempFile);
4433
saveBytes(output, buffer);
4437
if (!tempFile.renameTo(file)) {
4438
System.err.println("Could not rename temporary file " +
4439
tempFile.getAbsolutePath());
4442
} catch (IOException e) {
4443
System.err.println("error saving bytes to " + file);
4444
if (tempFile != null) {
4447
e.printStackTrace();
4453
* Spews a buffer of bytes to an OutputStream.
4455
static public void saveBytes(OutputStream output, byte buffer[]) {
4457
output.write(buffer);
4460
} catch (IOException e) {
4461
e.printStackTrace();
4467
public void saveStrings(String filename, String strings[]) {
4468
saveStrings(saveFile(filename), strings);
4472
static public void saveStrings(File file, String strings[]) {
4473
saveStrings(createOutput(file), strings);
4476
String location = file.getAbsolutePath();
4477
createPath(location);
4478
OutputStream output = new FileOutputStream(location);
4479
if (file.getName().toLowerCase().endsWith(".gz")) {
4480
output = new GZIPOutputStream(output);
4482
saveStrings(output, strings);
4485
} catch (IOException e) {
4486
e.printStackTrace();
4492
static public void saveStrings(OutputStream output, String strings[]) {
4493
PrintWriter writer = createWriter(output);
4494
for (int i = 0; i < strings.length; i++) {
4495
writer.println(strings[i]);
4502
//////////////////////////////////////////////////////////////
4506
* Prepend the sketch folder path to the filename (or path) that is
4507
* passed in. External libraries should use this function to save to
4508
* the sketch folder.
4510
* Note that when running as an applet inside a web browser,
4511
* the sketchPath will be set to null, because security restrictions
4512
* prevent applets from accessing that information.
4514
* This will also cause an error if the sketch is not inited properly,
4515
* meaning that init() was never called on the PApplet when hosted
4516
* my some other main() or by other code. For proper use of init(),
4517
* see the examples in the main description text for PApplet.
4519
public String sketchPath(String where) {
4520
if (sketchPath == null) {
4522
// throw new RuntimeException("The applet was not inited properly, " +
4523
// "or security restrictions prevented " +
4524
// "it from determining its path.");
4526
// isAbsolute() could throw an access exception, but so will writing
4527
// to the local disk using the sketch path, so this is safe here.
4528
// for 0120, added a try/catch anyways.
4530
if (new File(where).isAbsolute()) return where;
4531
} catch (Exception e) { }
4533
return sketchPath + File.separator + where;
4537
public File sketchFile(String where) {
4538
return new File(sketchPath(where));
4543
* Returns a path inside the applet folder to save to. Like sketchPath(),
4544
* but creates any in-between folders so that things save properly.
4546
* All saveXxxx() functions use the path to the sketch folder, rather than
4547
* its data folder. Once exported, the data folder will be found inside the
4548
* jar file of the exported application or applet. In this case, it's not
4549
* possible to save data into the jar file, because it will often be running
4550
* from a server, or marked in-use if running from a local file system.
4551
* With this in mind, saving to the data path doesn't make sense anyway.
4552
* If you know you're running locally, and want to save to the data folder,
4553
* use <TT>saveXxxx("data/blah.dat")</TT>.
4555
public String savePath(String where) {
4556
if (where == null) return null;
4557
String filename = sketchPath(where);
4558
createPath(filename);
4564
* Identical to savePath(), but returns a File object.
4566
public File saveFile(String where) {
4567
return new File(savePath(where));
4572
* Return a full path to an item in the data folder.
4574
* In this method, the data path is defined not as the applet's actual
4575
* data path, but a folder titled "data" in the sketch's working
4576
* directory. When running inside the PDE, this will be the sketch's
4577
* "data" folder. However, when exported (as application or applet),
4578
* sketch's data folder is exported as part of the applications jar file,
4579
* and it's not possible to read/write from the jar file in a generic way.
4580
* If you need to read data from the jar file, you should use other methods
4581
* such as createInput(), createReader(), or loadStrings().
4583
public String dataPath(String where) {
4584
// isAbsolute() could throw an access exception, but so will writing
4585
// to the local disk using the sketch path, so this is safe here.
4586
if (new File(where).isAbsolute()) return where;
4588
return sketchPath + File.separator + "data" + File.separator + where;
4593
* Return a full path to an item in the data folder as a File object.
4594
* See the dataPath() method for more information.
4596
public File dataFile(String where) {
4597
return new File(dataPath(where));
4602
* Takes a path and creates any in-between folders if they don't
4603
* already exist. Useful when trying to save to a subfolder that
4604
* may not actually exist.
4606
static public void createPath(String path) {
4607
createPath(new File(path));
4611
static public void createPath(File file) {
4613
String parent = file.getParent();
4614
if (parent != null) {
4615
File unit = new File(parent);
4616
if (!unit.exists()) unit.mkdirs();
4618
} catch (SecurityException se) {
4619
System.err.println("You don't have permissions to create " +
4620
file.getAbsolutePath());
4626
//////////////////////////////////////////////////////////////
4631
static public byte[] sort(byte what[]) {
4632
return sort(what, what.length);
4636
static public byte[] sort(byte[] what, int count) {
4637
byte[] outgoing = new byte[what.length];
4638
System.arraycopy(what, 0, outgoing, 0, what.length);
4639
Arrays.sort(outgoing, 0, count);
4644
static public char[] sort(char what[]) {
4645
return sort(what, what.length);
4649
static public char[] sort(char[] what, int count) {
4650
char[] outgoing = new char[what.length];
4651
System.arraycopy(what, 0, outgoing, 0, what.length);
4652
Arrays.sort(outgoing, 0, count);
4657
static public int[] sort(int what[]) {
4658
return sort(what, what.length);
4662
static public int[] sort(int[] what, int count) {
4663
int[] outgoing = new int[what.length];
4664
System.arraycopy(what, 0, outgoing, 0, what.length);
4665
Arrays.sort(outgoing, 0, count);
4670
static public float[] sort(float what[]) {
4671
return sort(what, what.length);
4675
static public float[] sort(float[] what, int count) {
4676
float[] outgoing = new float[what.length];
4677
System.arraycopy(what, 0, outgoing, 0, what.length);
4678
Arrays.sort(outgoing, 0, count);
4683
static public String[] sort(String what[]) {
4684
return sort(what, what.length);
4688
static public String[] sort(String[] what, int count) {
4689
String[] outgoing = new String[what.length];
4690
System.arraycopy(what, 0, outgoing, 0, what.length);
4691
Arrays.sort(outgoing, 0, count);
4697
//////////////////////////////////////////////////////////////
4703
* Calls System.arraycopy(), included here so that we can
4704
* avoid people needing to learn about the System object
4705
* before they can just copy an array.
4707
static public void arrayCopy(Object src, int srcPosition,
4708
Object dst, int dstPosition,
4710
System.arraycopy(src, srcPosition, dst, dstPosition, length);
4715
* Convenience method for arraycopy().
4716
* Identical to <CODE>arraycopy(src, 0, dst, 0, length);</CODE>
4718
static public void arrayCopy(Object src, Object dst, int length) {
4719
System.arraycopy(src, 0, dst, 0, length);
4724
* Shortcut to copy the entire contents of
4725
* the source into the destination array.
4726
* Identical to <CODE>arraycopy(src, 0, dst, 0, src.length);</CODE>
4728
static public void arrayCopy(Object src, Object dst) {
4729
System.arraycopy(src, 0, dst, 0, Array.getLength(src));
4735
* @deprecated Use arrayCopy() instead.
4737
static public void arraycopy(Object src, int srcPosition,
4738
Object dst, int dstPosition,
4740
System.arraycopy(src, srcPosition, dst, dstPosition, length);
4744
* @deprecated Use arrayCopy() instead.
4746
static public void arraycopy(Object src, Object dst, int length) {
4747
System.arraycopy(src, 0, dst, 0, length);
4751
* @deprecated Use arrayCopy() instead.
4753
static public void arraycopy(Object src, Object dst) {
4754
System.arraycopy(src, 0, dst, 0, Array.getLength(src));
4759
static public boolean[] expand(boolean list[]) {
4760
return expand(list, list.length << 1);
4763
static public boolean[] expand(boolean list[], int newSize) {
4764
boolean temp[] = new boolean[newSize];
4765
System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length));
4770
static public byte[] expand(byte list[]) {
4771
return expand(list, list.length << 1);
4774
static public byte[] expand(byte list[], int newSize) {
4775
byte temp[] = new byte[newSize];
4776
System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length));
4781
static public char[] expand(char list[]) {
4782
return expand(list, list.length << 1);
4785
static public char[] expand(char list[], int newSize) {
4786
char temp[] = new char[newSize];
4787
System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length));
4792
static public int[] expand(int list[]) {
4793
return expand(list, list.length << 1);
4796
static public int[] expand(int list[], int newSize) {
4797
int temp[] = new int[newSize];
4798
System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length));
4803
static public float[] expand(float list[]) {
4804
return expand(list, list.length << 1);
4807
static public float[] expand(float list[], int newSize) {
4808
float temp[] = new float[newSize];
4809
System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length));
4814
static public String[] expand(String list[]) {
4815
return expand(list, list.length << 1);
4818
static public String[] expand(String list[], int newSize) {
4819
String temp[] = new String[newSize];
4820
// in case the new size is smaller than list.length
4821
System.arraycopy(list, 0, temp, 0, Math.min(newSize, list.length));
4826
static public Object expand(Object array) {
4827
return expand(array, Array.getLength(array) << 1);
4830
static public Object expand(Object list, int newSize) {
4831
Class<?> type = list.getClass().getComponentType();
4832
Object temp = Array.newInstance(type, newSize);
4833
System.arraycopy(list, 0, temp, 0,
4834
Math.min(Array.getLength(list), newSize));
4840
// contract() has been removed in revision 0124, use subset() instead.
4841
// (expand() is also functionally equivalent)
4845
static public byte[] append(byte b[], byte value) {
4846
b = expand(b, b.length + 1);
4847
b[b.length-1] = value;
4851
static public char[] append(char b[], char value) {
4852
b = expand(b, b.length + 1);
4853
b[b.length-1] = value;
4857
static public int[] append(int b[], int value) {
4858
b = expand(b, b.length + 1);
4859
b[b.length-1] = value;
4863
static public float[] append(float b[], float value) {
4864
b = expand(b, b.length + 1);
4865
b[b.length-1] = value;
4869
static public String[] append(String b[], String value) {
4870
b = expand(b, b.length + 1);
4871
b[b.length-1] = value;
4875
static public Object append(Object b, Object value) {
4876
int length = Array.getLength(b);
4877
b = expand(b, length + 1);
4878
Array.set(b, length, value);
4884
static public boolean[] shorten(boolean list[]) {
4885
return subset(list, 0, list.length-1);
4888
static public byte[] shorten(byte list[]) {
4889
return subset(list, 0, list.length-1);
4892
static public char[] shorten(char list[]) {
4893
return subset(list, 0, list.length-1);
4896
static public int[] shorten(int list[]) {
4897
return subset(list, 0, list.length-1);
4900
static public float[] shorten(float list[]) {
4901
return subset(list, 0, list.length-1);
4904
static public String[] shorten(String list[]) {
4905
return subset(list, 0, list.length-1);
4908
static public Object shorten(Object list) {
4909
int length = Array.getLength(list);
4910
return subset(list, 0, length - 1);
4915
static final public boolean[] splice(boolean list[],
4916
boolean v, int index) {
4917
boolean outgoing[] = new boolean[list.length + 1];
4918
System.arraycopy(list, 0, outgoing, 0, index);
4919
outgoing[index] = v;
4920
System.arraycopy(list, index, outgoing, index + 1,
4921
list.length - index);
4925
static final public boolean[] splice(boolean list[],
4926
boolean v[], int index) {
4927
boolean outgoing[] = new boolean[list.length + v.length];
4928
System.arraycopy(list, 0, outgoing, 0, index);
4929
System.arraycopy(v, 0, outgoing, index, v.length);
4930
System.arraycopy(list, index, outgoing, index + v.length,
4931
list.length - index);
4936
static final public byte[] splice(byte list[],
4937
byte v, int index) {
4938
byte outgoing[] = new byte[list.length + 1];
4939
System.arraycopy(list, 0, outgoing, 0, index);
4940
outgoing[index] = v;
4941
System.arraycopy(list, index, outgoing, index + 1,
4942
list.length - index);
4946
static final public byte[] splice(byte list[],
4947
byte v[], int index) {
4948
byte outgoing[] = new byte[list.length + v.length];
4949
System.arraycopy(list, 0, outgoing, 0, index);
4950
System.arraycopy(v, 0, outgoing, index, v.length);
4951
System.arraycopy(list, index, outgoing, index + v.length,
4952
list.length - index);
4957
static final public char[] splice(char list[],
4958
char v, int index) {
4959
char outgoing[] = new char[list.length + 1];
4960
System.arraycopy(list, 0, outgoing, 0, index);
4961
outgoing[index] = v;
4962
System.arraycopy(list, index, outgoing, index + 1,
4963
list.length - index);
4967
static final public char[] splice(char list[],
4968
char v[], int index) {
4969
char outgoing[] = new char[list.length + v.length];
4970
System.arraycopy(list, 0, outgoing, 0, index);
4971
System.arraycopy(v, 0, outgoing, index, v.length);
4972
System.arraycopy(list, index, outgoing, index + v.length,
4973
list.length - index);
4978
static final public int[] splice(int list[],
4980
int outgoing[] = new int[list.length + 1];
4981
System.arraycopy(list, 0, outgoing, 0, index);
4982
outgoing[index] = v;
4983
System.arraycopy(list, index, outgoing, index + 1,
4984
list.length - index);
4988
static final public int[] splice(int list[],
4989
int v[], int index) {
4990
int outgoing[] = new int[list.length + v.length];
4991
System.arraycopy(list, 0, outgoing, 0, index);
4992
System.arraycopy(v, 0, outgoing, index, v.length);
4993
System.arraycopy(list, index, outgoing, index + v.length,
4994
list.length - index);
4999
static final public float[] splice(float list[],
5000
float v, int index) {
5001
float outgoing[] = new float[list.length + 1];
5002
System.arraycopy(list, 0, outgoing, 0, index);
5003
outgoing[index] = v;
5004
System.arraycopy(list, index, outgoing, index + 1,
5005
list.length - index);
5009
static final public float[] splice(float list[],
5010
float v[], int index) {
5011
float outgoing[] = new float[list.length + v.length];
5012
System.arraycopy(list, 0, outgoing, 0, index);
5013
System.arraycopy(v, 0, outgoing, index, v.length);
5014
System.arraycopy(list, index, outgoing, index + v.length,
5015
list.length - index);
5020
static final public String[] splice(String list[],
5021
String v, int index) {
5022
String outgoing[] = new String[list.length + 1];
5023
System.arraycopy(list, 0, outgoing, 0, index);
5024
outgoing[index] = v;
5025
System.arraycopy(list, index, outgoing, index + 1,
5026
list.length - index);
5030
static final public String[] splice(String list[],
5031
String v[], int index) {
5032
String outgoing[] = new String[list.length + v.length];
5033
System.arraycopy(list, 0, outgoing, 0, index);
5034
System.arraycopy(v, 0, outgoing, index, v.length);
5035
System.arraycopy(list, index, outgoing, index + v.length,
5036
list.length - index);
5041
static final public Object splice(Object list, Object v, int index) {
5042
Object[] outgoing = null;
5043
int length = Array.getLength(list);
5045
// check whether item being spliced in is an array
5046
if (v.getClass().getName().charAt(0) == '[') {
5047
int vlength = Array.getLength(v);
5048
outgoing = new Object[length + vlength];
5049
System.arraycopy(list, 0, outgoing, 0, index);
5050
System.arraycopy(v, 0, outgoing, index, vlength);
5051
System.arraycopy(list, index, outgoing, index + vlength, length - index);
5054
outgoing = new Object[length + 1];
5055
System.arraycopy(list, 0, outgoing, 0, index);
5056
Array.set(outgoing, index, v);
5057
System.arraycopy(list, index, outgoing, index + 1, length - index);
5064
static public boolean[] subset(boolean list[], int start) {
5065
return subset(list, start, list.length - start);
5068
static public boolean[] subset(boolean list[], int start, int count) {
5069
boolean output[] = new boolean[count];
5070
System.arraycopy(list, start, output, 0, count);
5075
static public byte[] subset(byte list[], int start) {
5076
return subset(list, start, list.length - start);
5079
static public byte[] subset(byte list[], int start, int count) {
5080
byte output[] = new byte[count];
5081
System.arraycopy(list, start, output, 0, count);
5086
static public char[] subset(char list[], int start) {
5087
return subset(list, start, list.length - start);
5090
static public char[] subset(char list[], int start, int count) {
5091
char output[] = new char[count];
5092
System.arraycopy(list, start, output, 0, count);
5097
static public int[] subset(int list[], int start) {
5098
return subset(list, start, list.length - start);
5101
static public int[] subset(int list[], int start, int count) {
5102
int output[] = new int[count];
5103
System.arraycopy(list, start, output, 0, count);
5108
static public float[] subset(float list[], int start) {
5109
return subset(list, start, list.length - start);
5112
static public float[] subset(float list[], int start, int count) {
5113
float output[] = new float[count];
5114
System.arraycopy(list, start, output, 0, count);
5119
static public String[] subset(String list[], int start) {
5120
return subset(list, start, list.length - start);
5123
static public String[] subset(String list[], int start, int count) {
5124
String output[] = new String[count];
5125
System.arraycopy(list, start, output, 0, count);
5130
static public Object subset(Object list, int start) {
5131
int length = Array.getLength(list);
5132
return subset(list, start, length - start);
5135
static public Object subset(Object list, int start, int count) {
5136
Class<?> type = list.getClass().getComponentType();
5137
Object outgoing = Array.newInstance(type, count);
5138
System.arraycopy(list, start, outgoing, 0, count);
5144
static public boolean[] concat(boolean a[], boolean b[]) {
5145
boolean c[] = new boolean[a.length + b.length];
5146
System.arraycopy(a, 0, c, 0, a.length);
5147
System.arraycopy(b, 0, c, a.length, b.length);
5151
static public byte[] concat(byte a[], byte b[]) {
5152
byte c[] = new byte[a.length + b.length];
5153
System.arraycopy(a, 0, c, 0, a.length);
5154
System.arraycopy(b, 0, c, a.length, b.length);
5158
static public char[] concat(char a[], char b[]) {
5159
char c[] = new char[a.length + b.length];
5160
System.arraycopy(a, 0, c, 0, a.length);
5161
System.arraycopy(b, 0, c, a.length, b.length);
5165
static public int[] concat(int a[], int b[]) {
5166
int c[] = new int[a.length + b.length];
5167
System.arraycopy(a, 0, c, 0, a.length);
5168
System.arraycopy(b, 0, c, a.length, b.length);
5172
static public float[] concat(float a[], float b[]) {
5173
float c[] = new float[a.length + b.length];
5174
System.arraycopy(a, 0, c, 0, a.length);
5175
System.arraycopy(b, 0, c, a.length, b.length);
5179
static public String[] concat(String a[], String b[]) {
5180
String c[] = new String[a.length + b.length];
5181
System.arraycopy(a, 0, c, 0, a.length);
5182
System.arraycopy(b, 0, c, a.length, b.length);
5186
static public Object concat(Object a, Object b) {
5187
Class<?> type = a.getClass().getComponentType();
5188
int alength = Array.getLength(a);
5189
int blength = Array.getLength(b);
5190
Object outgoing = Array.newInstance(type, alength + blength);
5191
System.arraycopy(a, 0, outgoing, 0, alength);
5192
System.arraycopy(b, 0, outgoing, alength, blength);
5198
static public boolean[] reverse(boolean list[]) {
5199
boolean outgoing[] = new boolean[list.length];
5200
int length1 = list.length - 1;
5201
for (int i = 0; i < list.length; i++) {
5202
outgoing[i] = list[length1 - i];
5207
static public byte[] reverse(byte list[]) {
5208
byte outgoing[] = new byte[list.length];
5209
int length1 = list.length - 1;
5210
for (int i = 0; i < list.length; i++) {
5211
outgoing[i] = list[length1 - i];
5216
static public char[] reverse(char list[]) {
5217
char outgoing[] = new char[list.length];
5218
int length1 = list.length - 1;
5219
for (int i = 0; i < list.length; i++) {
5220
outgoing[i] = list[length1 - i];
5225
static public int[] reverse(int list[]) {
5226
int outgoing[] = new int[list.length];
5227
int length1 = list.length - 1;
5228
for (int i = 0; i < list.length; i++) {
5229
outgoing[i] = list[length1 - i];
5234
static public float[] reverse(float list[]) {
5235
float outgoing[] = new float[list.length];
5236
int length1 = list.length - 1;
5237
for (int i = 0; i < list.length; i++) {
5238
outgoing[i] = list[length1 - i];
5243
static public String[] reverse(String list[]) {
5244
String outgoing[] = new String[list.length];
5245
int length1 = list.length - 1;
5246
for (int i = 0; i < list.length; i++) {
5247
outgoing[i] = list[length1 - i];
5252
static public Object reverse(Object list) {
5253
Class<?> type = list.getClass().getComponentType();
5254
int length = Array.getLength(list);
5255
Object outgoing = Array.newInstance(type, length);
5256
for (int i = 0; i < length; i++) {
5257
Array.set(outgoing, i, Array.get(list, (length - 1) - i));
5264
//////////////////////////////////////////////////////////////
5270
* Remove whitespace characters from the beginning and ending
5271
* of a String. Works like String.trim() but includes the
5272
* unicode nbsp character as well.
5274
static public String trim(String str) {
5275
return str.replace('\u00A0', ' ').trim();
5280
* Trim the whitespace from a String array. This returns a new
5281
* array and does not affect the passed-in array.
5283
static public String[] trim(String[] array) {
5284
String[] outgoing = new String[array.length];
5285
for (int i = 0; i < array.length; i++) {
5286
outgoing[i] = array[i].replace('\u00A0', ' ').trim();
5293
* Join an array of Strings together as a single String,
5294
* separated by the whatever's passed in for the separator.
5296
static public String join(String str[], char separator) {
5297
return join(str, String.valueOf(separator));
5302
* Join an array of Strings together as a single String,
5303
* separated by the whatever's passed in for the separator.
5305
* To use this on numbers, first pass the array to nf() or nfs()
5306
* to get a list of String objects, then use join on that.
5308
* e.g. String stuff[] = { "apple", "bear", "cat" };
5309
* String list = join(stuff, ", ");
5310
* // list is now "apple, bear, cat"</PRE>
5312
static public String join(String str[], String separator) {
5313
StringBuffer buffer = new StringBuffer();
5314
for (int i = 0; i < str.length; i++) {
5315
if (i != 0) buffer.append(separator);
5316
buffer.append(str[i]);
5318
return buffer.toString();
5323
* Split the provided String at wherever whitespace occurs.
5324
* Multiple whitespace (extra spaces or tabs or whatever)
5325
* between items will count as a single break.
5327
* The whitespace characters are "\t\n\r\f", which are the defaults
5328
* for java.util.StringTokenizer, plus the unicode non-breaking space
5329
* character, which is found commonly on files created by or used
5330
* in conjunction with Mac OS X (character 160, or 0x00A0 in hex).
5332
* i.e. splitTokens("a b") -> { "a", "b" }
5333
* splitTokens("a b") -> { "a", "b" }
5334
* splitTokens("a\tb") -> { "a", "b" }
5335
* splitTokens("a \t b ") -> { "a", "b" }</PRE>
5337
static public String[] splitTokens(String what) {
5338
return splitTokens(what, WHITESPACE);
5343
* Splits a string into pieces, using any of the chars in the
5344
* String 'delim' as separator characters. For instance,
5345
* in addition to white space, you might want to treat commas
5346
* as a separator. The delimeter characters won't appear in
5347
* the returned String array.
5349
* i.e. splitTokens("a, b", " ,") -> { "a", "b" }
5351
* To include all the whitespace possibilities, use the variable
5352
* WHITESPACE, found in PConstants:
5354
* i.e. splitTokens("a | b", WHITESPACE + "|"); -> { "a", "b" }</PRE>
5356
static public String[] splitTokens(String what, String delim) {
5357
StringTokenizer toker = new StringTokenizer(what, delim);
5358
String pieces[] = new String[toker.countTokens()];
5361
while (toker.hasMoreTokens()) {
5362
pieces[index++] = toker.nextToken();
5369
* Split a string into pieces along a specific character.
5370
* Most commonly used to break up a String along a space or a tab
5373
* This operates differently than the others, where the
5374
* single delimeter is the only breaking point, and consecutive
5375
* delimeters will produce an empty string (""). This way,
5376
* one can split on tab characters, but maintain the column
5377
* alignments (of say an excel file) where there are empty columns.
5379
static public String[] split(String what, char delim) {
5380
// do this so that the exception occurs inside the user's
5381
// program, rather than appearing to be a bug inside split()
5382
if (what == null) return null;
5383
//return split(what, String.valueOf(delim)); // huh
5385
char chars[] = what.toCharArray();
5386
int splitCount = 0; //1;
5387
for (int i = 0; i < chars.length; i++) {
5388
if (chars[i] == delim) splitCount++;
5390
// make sure that there is something in the input string
5391
//if (chars.length > 0) {
5392
// if the last char is a delimeter, get rid of it..
5393
//if (chars[chars.length-1] == delim) splitCount--;
5394
// on second thought, i don't agree with this, will disable
5396
if (splitCount == 0) {
5397
String splits[] = new String[1];
5398
splits[0] = new String(what);
5401
//int pieceCount = splitCount + 1;
5402
String splits[] = new String[splitCount + 1];
5405
for (int i = 0; i < chars.length; i++) {
5406
if (chars[i] == delim) {
5407
splits[splitIndex++] =
5408
new String(chars, startIndex, i-startIndex);
5412
//if (startIndex != chars.length) {
5413
splits[splitIndex] =
5414
new String(chars, startIndex, chars.length-startIndex);
5421
* Split a String on a specific delimiter. Unlike Java's String.split()
5422
* method, this does not parse the delimiter as a regexp because it's more
5423
* confusing than necessary, and String.split() is always available for
5424
* those who want regexp.
5426
static public String[] split(String what, String delim) {
5427
ArrayList<String> items = new ArrayList<String>();
5430
while ((index = what.indexOf(delim, offset)) != -1) {
5431
items.add(what.substring(offset, index));
5432
offset = index + delim.length();
5434
items.add(what.substring(offset));
5435
String[] outgoing = new String[items.size()];
5436
items.toArray(outgoing);
5442
* Match a string with a regular expression, and returns the match as an
5443
* array. The first index is the matching expression, and array elements
5444
* [1] and higher represent each of the groups (sequences found in parens).
5446
* This uses multiline matching (Pattern.MULTILINE) and dotall mode
5447
* (Pattern.DOTALL) by default, so that ^ and $ match the beginning and
5448
* end of any lines found in the source, and the . operator will also
5449
* pick up newline characters.
5451
static public String[] match(String what, String regexp) {
5452
Pattern p = Pattern.compile(regexp, Pattern.MULTILINE | Pattern.DOTALL);
5453
Matcher m = p.matcher(what);
5455
int count = m.groupCount() + 1;
5456
String[] groups = new String[count];
5457
for (int i = 0; i < count; i++) {
5458
groups[i] = m.group(i);
5467
* Identical to match(), except that it returns an array of all matches in
5468
* the specified String, rather than just the first.
5470
static public String[][] matchAll(String what, String regexp) {
5471
Pattern p = Pattern.compile(regexp, Pattern.MULTILINE | Pattern.DOTALL);
5472
Matcher m = p.matcher(what);
5473
ArrayList<String[]> results = new ArrayList<String[]>();
5474
int count = m.groupCount() + 1;
5476
String[] groups = new String[count];
5477
for (int i = 0; i < count; i++) {
5478
groups[i] = m.group(i);
5480
results.add(groups);
5482
if (results.isEmpty()) {
5485
String[][] matches = new String[results.size()][count];
5486
for (int i = 0; i < matches.length; i++) {
5487
matches[i] = (String[]) results.get(i);
5494
//////////////////////////////////////////////////////////////
5496
// CASTING FUNCTIONS, INSERTED BY PREPROC
5500
* Convert a char to a boolean. 'T', 't', and '1' will become the
5501
* boolean value true, while 'F', 'f', or '0' will become false.
5504
static final public boolean parseBoolean(char what) {
5505
return ((what == 't') || (what == 'T') || (what == '1'));
5510
* <p>Convert an integer to a boolean. Because of how Java handles upgrading
5511
* numbers, this will also cover byte and char (as they will upgrade to
5512
* an int without any sort of explicit cast).</p>
5513
* <p>The preprocessor will convert boolean(what) to parseBoolean(what).</p>
5514
* @return false if 0, true if any other number
5516
static final public boolean parseBoolean(int what) {
5521
// removed because this makes no useful sense
5522
static final public boolean parseBoolean(float what) {
5528
* Convert the string "true" or "false" to a boolean.
5529
* @return true if 'what' is "true" or "TRUE", false otherwise
5531
static final public boolean parseBoolean(String what) {
5532
return new Boolean(what).booleanValue();
5535
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5538
// removed, no need to introduce strange syntax from other languages
5539
static final public boolean[] parseBoolean(char what[]) {
5540
boolean outgoing[] = new boolean[what.length];
5541
for (int i = 0; i < what.length; i++) {
5543
((what[i] == 't') || (what[i] == 'T') || (what[i] == '1'));
5550
* Convert a byte array to a boolean array. Each element will be
5551
* evaluated identical to the integer case, where a byte equal
5552
* to zero will return false, and any other value will return true.
5553
* @return array of boolean elements
5555
static final public boolean[] parseBoolean(byte what[]) {
5556
boolean outgoing[] = new boolean[what.length];
5557
for (int i = 0; i < what.length; i++) {
5558
outgoing[i] = (what[i] != 0);
5564
* Convert an int array to a boolean array. An int equal
5565
* to zero will return false, and any other value will return true.
5566
* @return array of boolean elements
5568
static final public boolean[] parseBoolean(int what[]) {
5569
boolean outgoing[] = new boolean[what.length];
5570
for (int i = 0; i < what.length; i++) {
5571
outgoing[i] = (what[i] != 0);
5577
// removed, not necessary... if necessary, convert to int array first
5578
static final public boolean[] parseBoolean(float what[]) {
5579
boolean outgoing[] = new boolean[what.length];
5580
for (int i = 0; i < what.length; i++) {
5581
outgoing[i] = (what[i] != 0);
5587
static final public boolean[] parseBoolean(String what[]) {
5588
boolean outgoing[] = new boolean[what.length];
5589
for (int i = 0; i < what.length; i++) {
5590
outgoing[i] = new Boolean(what[i]).booleanValue();
5595
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5597
static final public byte parseByte(boolean what) {
5598
return what ? (byte)1 : 0;
5601
static final public byte parseByte(char what) {
5605
static final public byte parseByte(int what) {
5609
static final public byte parseByte(float what) {
5614
// nixed, no precedent
5615
static final public byte[] parseByte(String what) { // note: array[]
5616
return what.getBytes();
5620
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5622
static final public byte[] parseByte(boolean what[]) {
5623
byte outgoing[] = new byte[what.length];
5624
for (int i = 0; i < what.length; i++) {
5625
outgoing[i] = what[i] ? (byte)1 : 0;
5630
static final public byte[] parseByte(char what[]) {
5631
byte outgoing[] = new byte[what.length];
5632
for (int i = 0; i < what.length; i++) {
5633
outgoing[i] = (byte) what[i];
5638
static final public byte[] parseByte(int what[]) {
5639
byte outgoing[] = new byte[what.length];
5640
for (int i = 0; i < what.length; i++) {
5641
outgoing[i] = (byte) what[i];
5646
static final public byte[] parseByte(float what[]) {
5647
byte outgoing[] = new byte[what.length];
5648
for (int i = 0; i < what.length; i++) {
5649
outgoing[i] = (byte) what[i];
5655
static final public byte[][] parseByte(String what[]) { // note: array[][]
5656
byte outgoing[][] = new byte[what.length][];
5657
for (int i = 0; i < what.length; i++) {
5658
outgoing[i] = what[i].getBytes();
5664
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5667
static final public char parseChar(boolean what) { // 0/1 or T/F ?
5668
return what ? 't' : 'f';
5672
static final public char parseChar(byte what) {
5673
return (char) (what & 0xff);
5676
static final public char parseChar(int what) {
5681
static final public char parseChar(float what) { // nonsensical
5685
static final public char[] parseChar(String what) { // note: array[]
5686
return what.toCharArray();
5690
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5693
static final public char[] parseChar(boolean what[]) { // 0/1 or T/F ?
5694
char outgoing[] = new char[what.length];
5695
for (int i = 0; i < what.length; i++) {
5696
outgoing[i] = what[i] ? 't' : 'f';
5702
static final public char[] parseChar(byte what[]) {
5703
char outgoing[] = new char[what.length];
5704
for (int i = 0; i < what.length; i++) {
5705
outgoing[i] = (char) (what[i] & 0xff);
5710
static final public char[] parseChar(int what[]) {
5711
char outgoing[] = new char[what.length];
5712
for (int i = 0; i < what.length; i++) {
5713
outgoing[i] = (char) what[i];
5719
static final public char[] parseChar(float what[]) { // nonsensical
5720
char outgoing[] = new char[what.length];
5721
for (int i = 0; i < what.length; i++) {
5722
outgoing[i] = (char) what[i];
5727
static final public char[][] parseChar(String what[]) { // note: array[][]
5728
char outgoing[][] = new char[what.length][];
5729
for (int i = 0; i < what.length; i++) {
5730
outgoing[i] = what[i].toCharArray();
5736
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5738
static final public int parseInt(boolean what) {
5739
return what ? 1 : 0;
5743
* Note that parseInt() will un-sign a signed byte value.
5745
static final public int parseInt(byte what) {
5750
* Note that parseInt('5') is unlike String in the sense that it
5751
* won't return 5, but the ascii value. This is because ((int) someChar)
5752
* returns the ascii value, and parseInt() is just longhand for the cast.
5754
static final public int parseInt(char what) {
5759
* Same as floor(), or an (int) cast.
5761
static final public int parseInt(float what) {
5766
* Parse a String into an int value. Returns 0 if the value is bad.
5768
static final public int parseInt(String what) {
5769
return parseInt(what, 0);
5773
* Parse a String to an int, and provide an alternate value that
5774
* should be used when the number is invalid.
5776
static final public int parseInt(String what, int otherwise) {
5778
int offset = what.indexOf('.');
5780
return Integer.parseInt(what);
5782
return Integer.parseInt(what.substring(0, offset));
5784
} catch (NumberFormatException e) { }
5788
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5790
static final public int[] parseInt(boolean what[]) {
5791
int list[] = new int[what.length];
5792
for (int i = 0; i < what.length; i++) {
5793
list[i] = what[i] ? 1 : 0;
5798
static final public int[] parseInt(byte what[]) { // note this unsigns
5799
int list[] = new int[what.length];
5800
for (int i = 0; i < what.length; i++) {
5801
list[i] = (what[i] & 0xff);
5806
static final public int[] parseInt(char what[]) {
5807
int list[] = new int[what.length];
5808
for (int i = 0; i < what.length; i++) {
5814
static public int[] parseInt(float what[]) {
5815
int inties[] = new int[what.length];
5816
for (int i = 0; i < what.length; i++) {
5817
inties[i] = (int)what[i];
5823
* Make an array of int elements from an array of String objects.
5824
* If the String can't be parsed as a number, it will be set to zero.
5826
* String s[] = { "1", "300", "44" };
5827
* int numbers[] = parseInt(s);
5829
* numbers will contain { 1, 300, 44 }
5831
static public int[] parseInt(String what[]) {
5832
return parseInt(what, 0);
5836
* Make an array of int elements from an array of String objects.
5837
* If the String can't be parsed as a number, its entry in the
5838
* array will be set to the value of the "missing" parameter.
5840
* String s[] = { "1", "300", "apple", "44" };
5841
* int numbers[] = parseInt(s, 9999);
5843
* numbers will contain { 1, 300, 9999, 44 }
5845
static public int[] parseInt(String what[], int missing) {
5846
int output[] = new int[what.length];
5847
for (int i = 0; i < what.length; i++) {
5849
output[i] = Integer.parseInt(what[i]);
5850
} catch (NumberFormatException e) {
5851
output[i] = missing;
5857
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5860
static final public float parseFloat(boolean what) {
5861
return what ? 1 : 0;
5866
* Convert an int to a float value. Also handles bytes because of
5867
* Java's rules for upgrading values.
5869
static final public float parseFloat(int what) { // also handles byte
5873
static final public float parseFloat(String what) {
5874
return parseFloat(what, Float.NaN);
5877
static final public float parseFloat(String what, float otherwise) {
5879
return new Float(what).floatValue();
5880
} catch (NumberFormatException e) { }
5885
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5888
static final public float[] parseFloat(boolean what[]) {
5889
float floaties[] = new float[what.length];
5890
for (int i = 0; i < what.length; i++) {
5891
floaties[i] = what[i] ? 1 : 0;
5896
static final public float[] parseFloat(char what[]) {
5897
float floaties[] = new float[what.length];
5898
for (int i = 0; i < what.length; i++) {
5899
floaties[i] = (char) what[i];
5905
static final public float[] parseByte(byte what[]) {
5906
float floaties[] = new float[what.length];
5907
for (int i = 0; i < what.length; i++) {
5908
floaties[i] = what[i];
5913
static final public float[] parseFloat(int what[]) {
5914
float floaties[] = new float[what.length];
5915
for (int i = 0; i < what.length; i++) {
5916
floaties[i] = what[i];
5921
static final public float[] parseFloat(String what[]) {
5922
return parseFloat(what, Float.NaN);
5925
static final public float[] parseFloat(String what[], float missing) {
5926
float output[] = new float[what.length];
5927
for (int i = 0; i < what.length; i++) {
5929
output[i] = new Float(what[i]).floatValue();
5930
} catch (NumberFormatException e) {
5931
output[i] = missing;
5937
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5939
static final public String str(boolean x) {
5940
return String.valueOf(x);
5943
static final public String str(byte x) {
5944
return String.valueOf(x);
5947
static final public String str(char x) {
5948
return String.valueOf(x);
5951
static final public String str(int x) {
5952
return String.valueOf(x);
5955
static final public String str(float x) {
5956
return String.valueOf(x);
5959
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5961
static final public String[] str(boolean x[]) {
5962
String s[] = new String[x.length];
5963
for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]);
5967
static final public String[] str(byte x[]) {
5968
String s[] = new String[x.length];
5969
for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]);
5973
static final public String[] str(char x[]) {
5974
String s[] = new String[x.length];
5975
for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]);
5979
static final public String[] str(int x[]) {
5980
String s[] = new String[x.length];
5981
for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]);
5985
static final public String[] str(float x[]) {
5986
String s[] = new String[x.length];
5987
for (int i = 0; i < x.length; i++) s[i] = String.valueOf(x[i]);
5992
//////////////////////////////////////////////////////////////
5994
// INT NUMBER FORMATTING
5998
* Integer number formatter.
6000
static private NumberFormat int_nf;
6001
static private int int_nf_digits;
6002
static private boolean int_nf_commas;
6005
static public String[] nf(int num[], int digits) {
6006
String formatted[] = new String[num.length];
6007
for (int i = 0; i < formatted.length; i++) {
6008
formatted[i] = nf(num[i], digits);
6014
static public String nf(int num, int digits) {
6015
if ((int_nf != null) &&
6016
(int_nf_digits == digits) &&
6018
return int_nf.format(num);
6021
int_nf = NumberFormat.getInstance();
6022
int_nf.setGroupingUsed(false); // no commas
6023
int_nf_commas = false;
6024
int_nf.setMinimumIntegerDigits(digits);
6025
int_nf_digits = digits;
6026
return int_nf.format(num);
6030
static public String[] nfc(int num[]) {
6031
String formatted[] = new String[num.length];
6032
for (int i = 0; i < formatted.length; i++) {
6033
formatted[i] = nfc(num[i]);
6039
static public String nfc(int num) {
6040
if ((int_nf != null) &&
6041
(int_nf_digits == 0) &&
6043
return int_nf.format(num);
6046
int_nf = NumberFormat.getInstance();
6047
int_nf.setGroupingUsed(true);
6048
int_nf_commas = true;
6049
int_nf.setMinimumIntegerDigits(0);
6051
return int_nf.format(num);
6056
* number format signed (or space)
6057
* Formats a number but leaves a blank space in the front
6058
* when it's positive so that it can be properly aligned with
6059
* numbers that have a negative sign in front of them.
6061
static public String nfs(int num, int digits) {
6062
return (num < 0) ? nf(num, digits) : (' ' + nf(num, digits));
6065
static public String[] nfs(int num[], int digits) {
6066
String formatted[] = new String[num.length];
6067
for (int i = 0; i < formatted.length; i++) {
6068
formatted[i] = nfs(num[i], digits);
6076
* number format positive (or plus)
6077
* Formats a number, always placing a - or + sign
6078
* in the front when it's negative or positive.
6080
static public String nfp(int num, int digits) {
6081
return (num < 0) ? nf(num, digits) : ('+' + nf(num, digits));
6084
static public String[] nfp(int num[], int digits) {
6085
String formatted[] = new String[num.length];
6086
for (int i = 0; i < formatted.length; i++) {
6087
formatted[i] = nfp(num[i], digits);
6094
//////////////////////////////////////////////////////////////
6096
// FLOAT NUMBER FORMATTING
6099
static private NumberFormat float_nf;
6100
static private int float_nf_left, float_nf_right;
6101
static private boolean float_nf_commas;
6104
static public String[] nf(float num[], int left, int right) {
6105
String formatted[] = new String[num.length];
6106
for (int i = 0; i < formatted.length; i++) {
6107
formatted[i] = nf(num[i], left, right);
6113
static public String nf(float num, int left, int right) {
6114
if ((float_nf != null) &&
6115
(float_nf_left == left) &&
6116
(float_nf_right == right) &&
6118
return float_nf.format(num);
6121
float_nf = NumberFormat.getInstance();
6122
float_nf.setGroupingUsed(false);
6123
float_nf_commas = false;
6125
if (left != 0) float_nf.setMinimumIntegerDigits(left);
6127
float_nf.setMinimumFractionDigits(right);
6128
float_nf.setMaximumFractionDigits(right);
6130
float_nf_left = left;
6131
float_nf_right = right;
6132
return float_nf.format(num);
6136
static public String[] nfc(float num[], int right) {
6137
String formatted[] = new String[num.length];
6138
for (int i = 0; i < formatted.length; i++) {
6139
formatted[i] = nfc(num[i], right);
6145
static public String nfc(float num, int right) {
6146
if ((float_nf != null) &&
6147
(float_nf_left == 0) &&
6148
(float_nf_right == right) &&
6150
return float_nf.format(num);
6153
float_nf = NumberFormat.getInstance();
6154
float_nf.setGroupingUsed(true);
6155
float_nf_commas = true;
6158
float_nf.setMinimumFractionDigits(right);
6159
float_nf.setMaximumFractionDigits(right);
6162
float_nf_right = right;
6163
return float_nf.format(num);
6168
* Number formatter that takes into account whether the number
6169
* has a sign (positive, negative, etc) in front of it.
6171
static public String[] nfs(float num[], int left, int right) {
6172
String formatted[] = new String[num.length];
6173
for (int i = 0; i < formatted.length; i++) {
6174
formatted[i] = nfs(num[i], left, right);
6179
static public String nfs(float num, int left, int right) {
6180
return (num < 0) ? nf(num, left, right) : (' ' + nf(num, left, right));
6184
static public String[] nfp(float num[], int left, int right) {
6185
String formatted[] = new String[num.length];
6186
for (int i = 0; i < formatted.length; i++) {
6187
formatted[i] = nfp(num[i], left, right);
6192
static public String nfp(float num, int left, int right) {
6193
return (num < 0) ? nf(num, left, right) : ('+' + nf(num, left, right));
6198
//////////////////////////////////////////////////////////////
6200
// HEX/BINARY CONVERSION
6203
static final public String hex(byte what) {
6204
return hex(what, 2);
6207
static final public String hex(char what) {
6208
return hex(what, 4);
6211
static final public String hex(int what) {
6212
return hex(what, 8);
6215
static final public String hex(int what, int digits) {
6216
String stuff = Integer.toHexString(what).toUpperCase();
6218
int length = stuff.length();
6219
if (length > digits) {
6220
return stuff.substring(length - digits);
6222
} else if (length < digits) {
6223
return "00000000".substring(8 - (digits-length)) + stuff;
6228
static final public int unhex(String what) {
6229
// has to parse as a Long so that it'll work for numbers bigger than 2^31
6230
return (int) (Long.parseLong(what, 16));
6236
* Returns a String that contains the binary value of a byte.
6237
* The returned value will always have 8 digits.
6239
static final public String binary(byte what) {
6240
return binary(what, 8);
6244
* Returns a String that contains the binary value of a char.
6245
* The returned value will always have 16 digits because chars
6246
* are two bytes long.
6248
static final public String binary(char what) {
6249
return binary(what, 16);
6253
* Returns a String that contains the binary value of an int.
6254
* The length depends on the size of the number itself.
6255
* An int can be up to 32 binary digits, but that seems like
6256
* overkill for almost any situation, so this function just
6257
* auto-size. If you want a specific number of digits (like all 32)
6258
* use binary(int what, int digits) to specify how many digits.
6260
static final public String binary(int what) {
6261
return Integer.toBinaryString(what);
6262
//return binary(what, 32);
6266
* Returns a String that contains the binary value of an int.
6267
* The digits parameter determines how many digits will be used.
6269
static final public String binary(int what, int digits) {
6270
String stuff = Integer.toBinaryString(what);
6272
int length = stuff.length();
6273
if (length > digits) {
6274
return stuff.substring(length - digits);
6276
} else if (length < digits) {
6277
int offset = 32 - (digits-length);
6278
return "00000000000000000000000000000000".substring(offset) + stuff;
6285
* Unpack a binary String into an int.
6286
* i.e. unbinary("00001000") would return 8.
6288
static final public int unbinary(String what) {
6289
return Integer.parseInt(what, 2);
6294
//////////////////////////////////////////////////////////////
6298
// moved here so that they can work without
6299
// the graphics actually being instantiated (outside setup)
6302
public final int color(int gray) {
6304
if (gray > 255) gray = 255; else if (gray < 0) gray = 0;
6305
return 0xff000000 | (gray << 16) | (gray << 8) | gray;
6307
return g.color(gray);
6311
public final int color(float fgray) {
6313
int gray = (int) fgray;
6314
if (gray > 255) gray = 255; else if (gray < 0) gray = 0;
6315
return 0xff000000 | (gray << 16) | (gray << 8) | gray;
6317
return g.color(fgray);
6322
* As of 0116 this also takes color(#FF8800, alpha)
6324
public final int color(int gray, int alpha) {
6326
if (alpha > 255) alpha = 255; else if (alpha < 0) alpha = 0;
6328
// then assume this is actually a #FF8800
6329
return (alpha << 24) | (gray & 0xFFFFFF);
6331
//if (gray > 255) gray = 255; else if (gray < 0) gray = 0;
6332
return (alpha << 24) | (gray << 16) | (gray << 8) | gray;
6335
return g.color(gray, alpha);
6339
public final int color(float fgray, float falpha) {
6341
int gray = (int) fgray;
6342
int alpha = (int) falpha;
6343
if (gray > 255) gray = 255; else if (gray < 0) gray = 0;
6344
if (alpha > 255) alpha = 255; else if (alpha < 0) alpha = 0;
6345
return 0xff000000 | (gray << 16) | (gray << 8) | gray;
6347
return g.color(fgray, falpha);
6351
public final int color(int x, int y, int z) {
6353
if (x > 255) x = 255; else if (x < 0) x = 0;
6354
if (y > 255) y = 255; else if (y < 0) y = 0;
6355
if (z > 255) z = 255; else if (z < 0) z = 0;
6357
return 0xff000000 | (x << 16) | (y << 8) | z;
6359
return g.color(x, y, z);
6363
public final int color(float x, float y, float z) {
6365
if (x > 255) x = 255; else if (x < 0) x = 0;
6366
if (y > 255) y = 255; else if (y < 0) y = 0;
6367
if (z > 255) z = 255; else if (z < 0) z = 0;
6369
return 0xff000000 | ((int)x << 16) | ((int)y << 8) | (int)z;
6371
return g.color(x, y, z);
6375
public final int color(int x, int y, int z, int a) {
6377
if (a > 255) a = 255; else if (a < 0) a = 0;
6378
if (x > 255) x = 255; else if (x < 0) x = 0;
6379
if (y > 255) y = 255; else if (y < 0) y = 0;
6380
if (z > 255) z = 255; else if (z < 0) z = 0;
6382
return (a << 24) | (x << 16) | (y << 8) | z;
6384
return g.color(x, y, z, a);
6388
public final int color(float x, float y, float z, float a) {
6390
if (a > 255) a = 255; else if (a < 0) a = 0;
6391
if (x > 255) x = 255; else if (x < 0) x = 0;
6392
if (y > 255) y = 255; else if (y < 0) y = 0;
6393
if (z > 255) z = 255; else if (z < 0) z = 0;
6395
return ((int)a << 24) | ((int)x << 16) | ((int)y << 8) | (int)z;
6397
return g.color(x, y, z, a);
6402
//////////////////////////////////////////////////////////////
6408
* Set this sketch to communicate its state back to the PDE.
6410
* This uses the stderr stream to write positions of the window
6411
* (so that it will be saved by the PDE for the next run) and
6412
* notify on quit. See more notes in the Worker class.
6414
public void setupExternalMessages() {
6416
frame.addComponentListener(new ComponentAdapter() {
6417
public void componentMoved(ComponentEvent e) {
6418
Point where = ((Frame) e.getSource()).getLocation();
6419
System.err.println(PApplet.EXTERNAL_MOVE + " " +
6420
where.x + " " + where.y);
6421
System.err.flush(); // doesn't seem to help or hurt
6425
frame.addWindowListener(new WindowAdapter() {
6426
public void windowClosing(WindowEvent e) {
6427
// System.err.println(PApplet.EXTERNAL_QUIT);
6428
// System.err.flush(); // important
6430
exit(); // don't quit, need to just shut everything down (0133)
6437
* Set up a listener that will fire proper component resize events
6438
* in cases where frame.setResizable(true) is called.
6440
public void setupFrameResizeListener() {
6441
frame.addComponentListener(new ComponentAdapter() {
6443
public void componentResized(ComponentEvent e) {
6444
// Ignore bad resize events fired during setup to fix
6445
// http://dev.processing.org/bugs/show_bug.cgi?id=341
6446
// This should also fix the blank screen on Linux bug
6447
// http://dev.processing.org/bugs/show_bug.cgi?id=282
6448
if (frame.isResizable()) {
6449
// might be multiple resize calls before visible (i.e. first
6450
// when pack() is called, then when it's resized for use).
6451
// ignore them because it's not the user resizing things.
6452
Frame farm = (Frame) e.getComponent();
6453
if (farm.isVisible()) {
6454
Insets insets = farm.getInsets();
6455
Dimension windowSize = farm.getSize();
6456
int usableW = windowSize.width - insets.left - insets.right;
6457
int usableH = windowSize.height - insets.top - insets.bottom;
6459
// the ComponentListener in PApplet will handle calling size()
6460
setBounds(insets.left, insets.top, usableW, usableH);
6469
* GIF image of the Processing logo.
6471
static public final byte[] ICON_IMAGE = {
6472
71, 73, 70, 56, 57, 97, 16, 0, 16, 0, -77, 0, 0, 0, 0, 0, -1, -1, -1, 12,
6473
12, 13, -15, -15, -14, 45, 57, 74, 54, 80, 111, 47, 71, 97, 62, 88, 117,
6474
1, 14, 27, 7, 41, 73, 15, 52, 85, 2, 31, 55, 4, 54, 94, 18, 69, 109, 37,
6475
87, 126, -1, -1, -1, 33, -7, 4, 1, 0, 0, 15, 0, 44, 0, 0, 0, 0, 16, 0, 16,
6476
0, 0, 4, 122, -16, -107, 114, -86, -67, 83, 30, -42, 26, -17, -100, -45,
6477
56, -57, -108, 48, 40, 122, -90, 104, 67, -91, -51, 32, -53, 77, -78, -100,
6478
47, -86, 12, 76, -110, -20, -74, -101, 97, -93, 27, 40, 20, -65, 65, 48,
6479
-111, 99, -20, -112, -117, -123, -47, -105, 24, 114, -112, 74, 69, 84, 25,
6480
93, 88, -75, 9, 46, 2, 49, 88, -116, -67, 7, -19, -83, 60, 38, 3, -34, 2,
6481
66, -95, 27, -98, 13, 4, -17, 55, 33, 109, 11, 11, -2, -128, 121, 123, 62,
6482
91, 120, -128, 127, 122, 115, 102, 2, 119, 0, -116, -113, -119, 6, 102,
6483
121, -108, -126, 5, 18, 6, 4, -102, -101, -100, 114, 15, 17, 0, 59
6488
* main() method for running this class from the command line.
6490
* <B>The options shown here are not yet finalized and will be
6491
* changing over the next several releases.</B>
6493
* The simplest way to turn and applet into an application is to
6494
* add the following code to your program:
6495
* <PRE>static public void main(String args[]) {
6496
* PApplet.main(new String[] { "YourSketchName" });
6498
* This will properly launch your applet from a double-clickable
6499
* .jar or from the command line.
6501
* Parameters useful for launching or also used by the PDE:
6503
* --location=x,y upper-lefthand corner of where the applet
6504
* should appear on screen. if not used,
6505
* the default is to center on the main screen.
6507
* --present put the applet into full screen presentation
6508
* mode. requires java 1.4 or later.
6510
* --exclusive use full screen exclusive mode when presenting.
6511
* disables new windows or interaction with other
6512
* monitors, this is like a "game" mode.
6514
* --hide-stop use to hide the stop button in situations where
6515
* you don't want to allow users to exit. also
6516
* see the FAQ on information for capturing the ESC
6517
* key when running in presentation mode.
6519
* --stop-color=#xxxxxx color of the 'stop' text used to quit an
6520
* sketch when it's in present mode.
6522
* --bgcolor=#xxxxxx background color of the window.
6524
* --sketch-path location of where to save files from functions
6525
* like saveStrings() or saveFrame(). defaults to
6526
* the folder that the java application was
6527
* launched from, which means if this isn't set by
6528
* the pde, everything goes into the same folder
6529
* as processing.exe.
6531
* --display=n set what display should be used by this applet.
6532
* displays are numbered starting from 1.
6534
* Parameters used by Processing when running via the PDE
6536
* --external set when the applet is being used by the PDE
6538
* --editor-location=x,y position of the upper-lefthand corner of the
6539
* editor window, for placement of applet window
6542
static public void main(String args[]) {
6543
// Disable abyssmally slow Sun renderer on OS X 10.5.
6544
if (platform == MACOSX) {
6545
// Only run this on OS X otherwise it can cause a permissions error.
6546
// http://dev.processing.org/bugs/show_bug.cgi?id=976
6547
System.setProperty("apple.awt.graphics.UseQuartz", "true");
6550
// This doesn't do anything.
6551
// if (platform == WINDOWS) {
6552
// // For now, disable the D3D renderer on Java 6u10 because
6553
// // it causes problems with Present mode.
6554
// // http://dev.processing.org/bugs/show_bug.cgi?id=1009
6555
// System.setProperty("sun.java2d.d3d", "false");
6558
if (args.length < 1) {
6559
System.err.println("Usage: PApplet <appletname>");
6560
System.err.println("For additional options, " +
6561
"see the Javadoc for PApplet");
6565
boolean external = false;
6566
int[] location = null;
6567
int[] editorLocation = null;
6570
boolean present = false;
6571
boolean exclusive = false;
6572
Color backgroundColor = Color.BLACK;
6573
Color stopColor = Color.GRAY;
6574
GraphicsDevice displayDevice = null;
6575
boolean hideStop = false;
6577
String param = null, value = null;
6579
// try to get the user folder. if running under java web start,
6580
// this may cause a security exception if the code is not signed.
6581
// http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Integrate;action=display;num=1159386274
6582
String folder = null;
6584
folder = System.getProperty("user.dir");
6585
} catch (Exception e) { }
6588
while (argIndex < args.length) {
6589
int equals = args[argIndex].indexOf('=');
6591
param = args[argIndex].substring(0, equals);
6592
value = args[argIndex].substring(equals + 1);
6594
if (param.equals(ARGS_EDITOR_LOCATION)) {
6596
editorLocation = parseInt(split(value, ','));
6598
} else if (param.equals(ARGS_DISPLAY)) {
6599
int deviceIndex = Integer.parseInt(value) - 1;
6601
//DisplayMode dm = device.getDisplayMode();
6602
//if ((dm.getWidth() == 1024) && (dm.getHeight() == 768)) {
6604
GraphicsEnvironment environment =
6605
GraphicsEnvironment.getLocalGraphicsEnvironment();
6606
GraphicsDevice devices[] = environment.getScreenDevices();
6607
if ((deviceIndex >= 0) && (deviceIndex < devices.length)) {
6608
displayDevice = devices[deviceIndex];
6610
System.err.println("Display " + value + " does not exist, " +
6611
"using the default display instead.");
6614
} else if (param.equals(ARGS_BGCOLOR)) {
6615
if (value.charAt(0) == '#') value = value.substring(1);
6616
backgroundColor = new Color(Integer.parseInt(value, 16));
6618
} else if (param.equals(ARGS_STOP_COLOR)) {
6619
if (value.charAt(0) == '#') value = value.substring(1);
6620
stopColor = new Color(Integer.parseInt(value, 16));
6622
} else if (param.equals(ARGS_SKETCH_FOLDER)) {
6625
} else if (param.equals(ARGS_LOCATION)) {
6626
location = parseInt(split(value, ','));
6630
if (args[argIndex].equals(ARGS_PRESENT)) {
6633
} else if (args[argIndex].equals(ARGS_EXCLUSIVE)) {
6636
} else if (args[argIndex].equals(ARGS_HIDE_STOP)) {
6639
} else if (args[argIndex].equals(ARGS_EXTERNAL)) {
6643
name = args[argIndex];
6650
// Set this property before getting into any GUI init code
6651
//System.setProperty("com.apple.mrj.application.apple.menu.about.name", name);
6652
// This )*)(*@#$ Apple crap don't work no matter where you put it
6653
// (static method of the class, at the top of main, wherever)
6655
if (displayDevice == null) {
6656
GraphicsEnvironment environment =
6657
GraphicsEnvironment.getLocalGraphicsEnvironment();
6658
displayDevice = environment.getDefaultScreenDevice();
6661
Frame frame = new Frame(displayDevice.getDefaultConfiguration());
6664
if (displayDevice != null) {
6665
frame = new Frame(displayDevice.getDefaultConfiguration());
6667
frame = new Frame();
6670
//Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
6672
// remove the grow box by default
6673
// users who want it back can call frame.setResizable(true)
6674
frame.setResizable(false);
6676
// Set the trimmings around the image
6677
Image image = Toolkit.getDefaultToolkit().createImage(ICON_IMAGE);
6678
frame.setIconImage(image);
6679
frame.setTitle(name);
6681
final PApplet applet;
6683
Class<?> c = Thread.currentThread().getContextClassLoader().loadClass(name);
6684
applet = (PApplet) c.newInstance();
6685
} catch (Exception e) {
6686
throw new RuntimeException(e);
6689
// these are needed before init/start
6690
applet.frame = frame;
6691
applet.sketchPath = folder;
6692
applet.args = PApplet.subset(args, 1);
6693
applet.external = external;
6695
// Need to save the window bounds at full screen,
6696
// because pack() will cause the bounds to go to zero.
6697
// http://dev.processing.org/bugs/show_bug.cgi?id=923
6698
Rectangle fullScreenRect = null;
6700
// For 0149, moving this code (up to the pack() method) before init().
6701
// For OpenGL (and perhaps other renderers in the future), a peer is
6702
// needed before a GLDrawable can be created. So pack() needs to be
6703
// called on the Frame before applet.init(), which itself calls size(),
6704
// and launches the Thread that will kick off setup().
6705
// http://dev.processing.org/bugs/show_bug.cgi?id=891
6706
// http://dev.processing.org/bugs/show_bug.cgi?id=908
6708
frame.setUndecorated(true);
6709
frame.setBackground(backgroundColor);
6711
displayDevice.setFullScreenWindow(frame);
6712
fullScreenRect = frame.getBounds();
6714
DisplayMode mode = displayDevice.getDisplayMode();
6715
fullScreenRect = new Rectangle(0, 0, mode.getWidth(), mode.getHeight());
6716
frame.setBounds(fullScreenRect);
6717
frame.setVisible(true);
6720
frame.setLayout(null);
6727
// insufficient, places the 100x100 sketches offset strangely
6732
// Wait until the applet has figured out its width.
6733
// In a static mode app, this will be after setup() has completed,
6734
// and the empty draw() has set "finished" to true.
6735
// TODO make sure this won't hang if the applet has an exception.
6736
while (applet.defaultSize && !applet.finished) {
6737
//System.out.println("default size");
6741
} catch (InterruptedException e) {
6742
//System.out.println("interrupt");
6745
//println("not default size " + applet.width + " " + applet.height);
6746
//println(" (g width/height is " + applet.g.width + "x" + applet.g.height + ")");
6749
// After the pack(), the screen bounds are gonna be 0s
6750
frame.setBounds(fullScreenRect);
6751
applet.setBounds((fullScreenRect.width - applet.width) / 2,
6752
(fullScreenRect.height - applet.height) / 2,
6753
applet.width, applet.height);
6756
Label label = new Label("stop");
6757
label.setForeground(stopColor);
6758
label.addMouseListener(new MouseAdapter() {
6759
public void mousePressed(MouseEvent e) {
6765
Dimension labelSize = label.getPreferredSize();
6766
// sometimes shows up truncated on mac
6767
//System.out.println("label width is " + labelSize.width);
6768
labelSize = new Dimension(100, labelSize.height);
6769
label.setSize(labelSize);
6770
label.setLocation(20, fullScreenRect.height - labelSize.height - 20);
6773
// not always running externally when in present mode
6775
applet.setupExternalMessages();
6778
} else { // if not presenting
6779
// can't do pack earlier cuz present mode don't like it
6780
// (can't go full screen with a frame after calling pack)
6781
// frame.pack(); // get insets. get more.
6782
Insets insets = frame.getInsets();
6784
int windowW = Math.max(applet.width, MIN_WINDOW_WIDTH) +
6785
insets.left + insets.right;
6786
int windowH = Math.max(applet.height, MIN_WINDOW_HEIGHT) +
6787
insets.top + insets.bottom;
6789
frame.setSize(windowW, windowH);
6791
if (location != null) {
6792
// a specific location was received from PdeRuntime
6793
// (applet has been run more than once, user placed window)
6794
frame.setLocation(location[0], location[1]);
6796
} else if (external) {
6797
int locationX = editorLocation[0] - 20;
6798
int locationY = editorLocation[1];
6800
if (locationX - windowW > 10) {
6801
// if it fits to the left of the window
6802
frame.setLocation(locationX - windowW, locationY);
6804
} else { // doesn't fit
6805
// if it fits inside the editor window,
6806
// offset slightly from upper lefthand corner
6807
// so that it's plunked inside the text area
6808
locationX = editorLocation[0] + 66;
6809
locationY = editorLocation[1] + 66;
6811
if ((locationX + windowW > applet.screen.width - 33) ||
6812
(locationY + windowH > applet.screen.height - 33)) {
6813
// otherwise center on screen
6814
locationX = (applet.screen.width - windowW) / 2;
6815
locationY = (applet.screen.height - windowH) / 2;
6817
frame.setLocation(locationX, locationY);
6819
} else { // just center on screen
6820
frame.setLocation((applet.screen.width - applet.width) / 2,
6821
(applet.screen.height - applet.height) / 2);
6824
if (backgroundColor == Color.black) { //BLACK) {
6825
// this means no bg color unless specified
6826
backgroundColor = SystemColor.control;
6828
frame.setBackground(backgroundColor);
6830
int usableWindowH = windowH - insets.top - insets.bottom;
6831
applet.setBounds((windowW - applet.width)/2,
6832
insets.top + (usableWindowH - applet.height)/2,
6833
applet.width, applet.height);
6836
applet.setupExternalMessages();
6838
} else { // !external
6839
frame.addWindowListener(new WindowAdapter() {
6840
public void windowClosing(WindowEvent e) {
6846
// handle frame resizing events
6847
applet.setupFrameResizeListener();
6849
// all set for rockin
6850
if (applet.displayable()) {
6851
frame.setVisible(true);
6855
applet.requestFocus(); // ask for keydowns
6856
//System.out.println("exiting main()");
6860
//////////////////////////////////////////////////////////////
6864
* Begin recording to a new renderer of the specified type, using the width
6865
* and height of the main drawing surface.
6867
public PGraphics beginRecord(String renderer, String filename) {
6868
filename = insertFrame(filename);
6869
PGraphics rec = createGraphics(width, height, renderer, filename);
6876
* Begin recording (echoing) commands to the specified PGraphics object.
6878
public void beginRecord(PGraphics recorder) {
6879
this.recorder = recorder;
6880
recorder.beginDraw();
6884
public void endRecord() {
6885
if (recorder != null) {
6894
* Begin recording raw shape data to a renderer of the specified type,
6895
* using the width and height of the main drawing surface.
6897
* If hashmarks (###) are found in the filename, they'll be replaced
6898
* by the current frame number (frameCount).
6900
public PGraphics beginRaw(String renderer, String filename) {
6901
filename = insertFrame(filename);
6902
PGraphics rec = createGraphics(width, height, renderer, filename);
6909
* Begin recording raw shape data to the specified renderer.
6911
* This simply echoes to g.beginRaw(), but since is placed here (rather than
6912
* generated by preproc.pl) for clarity and so that it doesn't echo the
6913
* command should beginRecord() be in use.
6915
public void beginRaw(PGraphics rawGraphics) {
6916
g.beginRaw(rawGraphics);
6921
* Stop recording raw shape data to the specified renderer.
6923
* This simply echoes to g.beginRaw(), but since is placed here (rather than
6924
* generated by preproc.pl) for clarity and so that it doesn't echo the
6925
* command should beginRecord() be in use.
6927
public void endRaw() {
6932
//////////////////////////////////////////////////////////////
6936
* Override the g.pixels[] function to set the pixels[] array
6937
* that's part of the PApplet object. Allows the use of
6938
* pixels[] in the code, rather than g.pixels[].
6940
public void loadPixels() {
6946
public void updatePixels() {
6951
public void updatePixels(int x1, int y1, int x2, int y2) {
6952
g.updatePixels(x1, y1, x2, y2);
6956
//////////////////////////////////////////////////////////////
6958
// everything below this line is automatically generated. no touch.
6959
// public functions for processing.core
6962
public void flush() {
6963
if (recorder != null) recorder.flush();
6968
public void hint(int which) {
6969
if (recorder != null) recorder.hint(which);
6974
public void beginShape() {
6975
if (recorder != null) recorder.beginShape();
6980
public void beginShape(int kind) {
6981
if (recorder != null) recorder.beginShape(kind);
6986
public void edge(boolean edge) {
6987
if (recorder != null) recorder.edge(edge);
6992
public void normal(float nx, float ny, float nz) {
6993
if (recorder != null) recorder.normal(nx, ny, nz);
6994
g.normal(nx, ny, nz);
6998
public void textureMode(int mode) {
6999
if (recorder != null) recorder.textureMode(mode);
7000
g.textureMode(mode);
7004
public void texture(PImage image) {
7005
if (recorder != null) recorder.texture(image);
7010
public void vertex(float x, float y) {
7011
if (recorder != null) recorder.vertex(x, y);
7016
public void vertex(float x, float y, float z) {
7017
if (recorder != null) recorder.vertex(x, y, z);
7022
public void vertex(float[] v) {
7023
if (recorder != null) recorder.vertex(v);
7028
public void vertex(float x, float y, float u, float v) {
7029
if (recorder != null) recorder.vertex(x, y, u, v);
7030
g.vertex(x, y, u, v);
7034
public void vertex(float x, float y, float z, float u, float v) {
7035
if (recorder != null) recorder.vertex(x, y, z, u, v);
7036
g.vertex(x, y, z, u, v);
7040
public void breakShape() {
7041
if (recorder != null) recorder.breakShape();
7046
public void endShape() {
7047
if (recorder != null) recorder.endShape();
7052
public void endShape(int mode) {
7053
if (recorder != null) recorder.endShape(mode);
7058
public void bezierVertex(float x2, float y2,
7060
float x4, float y4) {
7061
if (recorder != null) recorder.bezierVertex(x2, y2, x3, y3, x4, y4);
7062
g.bezierVertex(x2, y2, x3, y3, x4, y4);
7066
public void bezierVertex(float x2, float y2, float z2,
7067
float x3, float y3, float z3,
7068
float x4, float y4, float z4) {
7069
if (recorder != null) recorder.bezierVertex(x2, y2, z2, x3, y3, z3, x4, y4, z4);
7070
g.bezierVertex(x2, y2, z2, x3, y3, z3, x4, y4, z4);
7074
public void curveVertex(float x, float y) {
7075
if (recorder != null) recorder.curveVertex(x, y);
7076
g.curveVertex(x, y);
7080
public void curveVertex(float x, float y, float z) {
7081
if (recorder != null) recorder.curveVertex(x, y, z);
7082
g.curveVertex(x, y, z);
7086
public void point(float x, float y) {
7087
if (recorder != null) recorder.point(x, y);
7092
public void point(float x, float y, float z) {
7093
if (recorder != null) recorder.point(x, y, z);
7098
public void line(float x1, float y1, float x2, float y2) {
7099
if (recorder != null) recorder.line(x1, y1, x2, y2);
7100
g.line(x1, y1, x2, y2);
7104
public void line(float x1, float y1, float z1,
7105
float x2, float y2, float z2) {
7106
if (recorder != null) recorder.line(x1, y1, z1, x2, y2, z2);
7107
g.line(x1, y1, z1, x2, y2, z2);
7111
public void triangle(float x1, float y1, float x2, float y2,
7112
float x3, float y3) {
7113
if (recorder != null) recorder.triangle(x1, y1, x2, y2, x3, y3);
7114
g.triangle(x1, y1, x2, y2, x3, y3);
7118
public void quad(float x1, float y1, float x2, float y2,
7119
float x3, float y3, float x4, float y4) {
7120
if (recorder != null) recorder.quad(x1, y1, x2, y2, x3, y3, x4, y4);
7121
g.quad(x1, y1, x2, y2, x3, y3, x4, y4);
7125
public void rectMode(int mode) {
7126
if (recorder != null) recorder.rectMode(mode);
7131
public void rect(float a, float b, float c, float d) {
7132
if (recorder != null) recorder.rect(a, b, c, d);
7137
public void ellipseMode(int mode) {
7138
if (recorder != null) recorder.ellipseMode(mode);
7139
g.ellipseMode(mode);
7143
public void ellipse(float a, float b, float c, float d) {
7144
if (recorder != null) recorder.ellipse(a, b, c, d);
7145
g.ellipse(a, b, c, d);
7149
public void arc(float a, float b, float c, float d,
7150
float start, float stop) {
7151
if (recorder != null) recorder.arc(a, b, c, d, start, stop);
7152
g.arc(a, b, c, d, start, stop);
7156
public void box(float size) {
7157
if (recorder != null) recorder.box(size);
7162
public void box(float w, float h, float d) {
7163
if (recorder != null) recorder.box(w, h, d);
7168
public void sphereDetail(int res) {
7169
if (recorder != null) recorder.sphereDetail(res);
7170
g.sphereDetail(res);
7174
public void sphereDetail(int ures, int vres) {
7175
if (recorder != null) recorder.sphereDetail(ures, vres);
7176
g.sphereDetail(ures, vres);
7180
public void sphere(float r) {
7181
if (recorder != null) recorder.sphere(r);
7186
public float bezierPoint(float a, float b, float c, float d, float t) {
7187
return g.bezierPoint(a, b, c, d, t);
7191
public float bezierTangent(float a, float b, float c, float d, float t) {
7192
return g.bezierTangent(a, b, c, d, t);
7196
public void bezierDetail(int detail) {
7197
if (recorder != null) recorder.bezierDetail(detail);
7198
g.bezierDetail(detail);
7202
public void bezier(float x1, float y1,
7205
float x4, float y4) {
7206
if (recorder != null) recorder.bezier(x1, y1, x2, y2, x3, y3, x4, y4);
7207
g.bezier(x1, y1, x2, y2, x3, y3, x4, y4);
7211
public void bezier(float x1, float y1, float z1,
7212
float x2, float y2, float z2,
7213
float x3, float y3, float z3,
7214
float x4, float y4, float z4) {
7215
if (recorder != null) recorder.bezier(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4);
7216
g.bezier(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4);
7220
public float curvePoint(float a, float b, float c, float d, float t) {
7221
return g.curvePoint(a, b, c, d, t);
7225
public float curveTangent(float a, float b, float c, float d, float t) {
7226
return g.curveTangent(a, b, c, d, t);
7230
public void curveDetail(int detail) {
7231
if (recorder != null) recorder.curveDetail(detail);
7232
g.curveDetail(detail);
7236
public void curveTightness(float tightness) {
7237
if (recorder != null) recorder.curveTightness(tightness);
7238
g.curveTightness(tightness);
7242
public void curve(float x1, float y1,
7245
float x4, float y4) {
7246
if (recorder != null) recorder.curve(x1, y1, x2, y2, x3, y3, x4, y4);
7247
g.curve(x1, y1, x2, y2, x3, y3, x4, y4);
7251
public void curve(float x1, float y1, float z1,
7252
float x2, float y2, float z2,
7253
float x3, float y3, float z3,
7254
float x4, float y4, float z4) {
7255
if (recorder != null) recorder.curve(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4);
7256
g.curve(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4);
7260
public void smooth() {
7261
if (recorder != null) recorder.smooth();
7266
public void noSmooth() {
7267
if (recorder != null) recorder.noSmooth();
7272
public void imageMode(int mode) {
7273
if (recorder != null) recorder.imageMode(mode);
7278
public void image(PImage image, float x, float y) {
7279
if (recorder != null) recorder.image(image, x, y);
7280
g.image(image, x, y);
7284
public void image(PImage image, float x, float y, float c, float d) {
7285
if (recorder != null) recorder.image(image, x, y, c, d);
7286
g.image(image, x, y, c, d);
7290
public void image(PImage image,
7291
float a, float b, float c, float d,
7292
int u1, int v1, int u2, int v2) {
7293
if (recorder != null) recorder.image(image, a, b, c, d, u1, v1, u2, v2);
7294
g.image(image, a, b, c, d, u1, v1, u2, v2);
7298
public void shapeMode(int mode) {
7299
if (recorder != null) recorder.shapeMode(mode);
7304
public void shape(PShape shape) {
7305
if (recorder != null) recorder.shape(shape);
7310
public void shape(PShape shape, float x, float y) {
7311
if (recorder != null) recorder.shape(shape, x, y);
7312
g.shape(shape, x, y);
7316
public void shape(PShape shape, float x, float y, float c, float d) {
7317
if (recorder != null) recorder.shape(shape, x, y, c, d);
7318
g.shape(shape, x, y, c, d);
7322
public void textAlign(int align) {
7323
if (recorder != null) recorder.textAlign(align);
7328
public void textAlign(int alignX, int alignY) {
7329
if (recorder != null) recorder.textAlign(alignX, alignY);
7330
g.textAlign(alignX, alignY);
7334
public float textAscent() {
7335
return g.textAscent();
7339
public float textDescent() {
7340
return g.textDescent();
7344
public void textFont(PFont which) {
7345
if (recorder != null) recorder.textFont(which);
7350
public void textFont(PFont which, float size) {
7351
if (recorder != null) recorder.textFont(which, size);
7352
g.textFont(which, size);
7356
public void textLeading(float leading) {
7357
if (recorder != null) recorder.textLeading(leading);
7358
g.textLeading(leading);
7362
public void textMode(int mode) {
7363
if (recorder != null) recorder.textMode(mode);
7368
public void textSize(float size) {
7369
if (recorder != null) recorder.textSize(size);
7374
public float textWidth(char c) {
7375
return g.textWidth(c);
7379
public float textWidth(String str) {
7380
return g.textWidth(str);
7384
public float textWidth(char[] chars, int start, int length) {
7385
return g.textWidth(chars, start, length);
7389
public void text(char c) {
7390
if (recorder != null) recorder.text(c);
7395
public void text(char c, float x, float y) {
7396
if (recorder != null) recorder.text(c, x, y);
7401
public void text(char c, float x, float y, float z) {
7402
if (recorder != null) recorder.text(c, x, y, z);
7407
public void text(String str) {
7408
if (recorder != null) recorder.text(str);
7413
public void text(String str, float x, float y) {
7414
if (recorder != null) recorder.text(str, x, y);
7419
public void text(char[] chars, int start, int stop, float x, float y) {
7420
if (recorder != null) recorder.text(chars, start, stop, x, y);
7421
g.text(chars, start, stop, x, y);
7425
public void text(String str, float x, float y, float z) {
7426
if (recorder != null) recorder.text(str, x, y, z);
7427
g.text(str, x, y, z);
7431
public void text(char[] chars, int start, int stop,
7432
float x, float y, float z) {
7433
if (recorder != null) recorder.text(chars, start, stop, x, y, z);
7434
g.text(chars, start, stop, x, y, z);
7438
public void text(String str, float x1, float y1, float x2, float y2) {
7439
if (recorder != null) recorder.text(str, x1, y1, x2, y2);
7440
g.text(str, x1, y1, x2, y2);
7444
public void text(String s, float x1, float y1, float x2, float y2, float z) {
7445
if (recorder != null) recorder.text(s, x1, y1, x2, y2, z);
7446
g.text(s, x1, y1, x2, y2, z);
7450
public void text(int num, float x, float y) {
7451
if (recorder != null) recorder.text(num, x, y);
7456
public void text(int num, float x, float y, float z) {
7457
if (recorder != null) recorder.text(num, x, y, z);
7458
g.text(num, x, y, z);
7462
public void text(float num, float x, float y) {
7463
if (recorder != null) recorder.text(num, x, y);
7468
public void text(float num, float x, float y, float z) {
7469
if (recorder != null) recorder.text(num, x, y, z);
7470
g.text(num, x, y, z);
7474
public void pushMatrix() {
7475
if (recorder != null) recorder.pushMatrix();
7480
public void popMatrix() {
7481
if (recorder != null) recorder.popMatrix();
7486
public void translate(float tx, float ty) {
7487
if (recorder != null) recorder.translate(tx, ty);
7488
g.translate(tx, ty);
7492
public void translate(float tx, float ty, float tz) {
7493
if (recorder != null) recorder.translate(tx, ty, tz);
7494
g.translate(tx, ty, tz);
7498
public void rotate(float angle) {
7499
if (recorder != null) recorder.rotate(angle);
7504
public void rotateX(float angle) {
7505
if (recorder != null) recorder.rotateX(angle);
7510
public void rotateY(float angle) {
7511
if (recorder != null) recorder.rotateY(angle);
7516
public void rotateZ(float angle) {
7517
if (recorder != null) recorder.rotateZ(angle);
7522
public void rotate(float angle, float vx, float vy, float vz) {
7523
if (recorder != null) recorder.rotate(angle, vx, vy, vz);
7524
g.rotate(angle, vx, vy, vz);
7528
public void scale(float s) {
7529
if (recorder != null) recorder.scale(s);
7534
public void scale(float sx, float sy) {
7535
if (recorder != null) recorder.scale(sx, sy);
7540
public void scale(float x, float y, float z) {
7541
if (recorder != null) recorder.scale(x, y, z);
7546
public void resetMatrix() {
7547
if (recorder != null) recorder.resetMatrix();
7552
public void applyMatrix(PMatrix source) {
7553
if (recorder != null) recorder.applyMatrix(source);
7554
g.applyMatrix(source);
7558
public void applyMatrix(PMatrix2D source) {
7559
if (recorder != null) recorder.applyMatrix(source);
7560
g.applyMatrix(source);
7564
public void applyMatrix(float n00, float n01, float n02,
7565
float n10, float n11, float n12) {
7566
if (recorder != null) recorder.applyMatrix(n00, n01, n02, n10, n11, n12);
7567
g.applyMatrix(n00, n01, n02, n10, n11, n12);
7571
public void applyMatrix(PMatrix3D source) {
7572
if (recorder != null) recorder.applyMatrix(source);
7573
g.applyMatrix(source);
7577
public void applyMatrix(float n00, float n01, float n02, float n03,
7578
float n10, float n11, float n12, float n13,
7579
float n20, float n21, float n22, float n23,
7580
float n30, float n31, float n32, float n33) {
7581
if (recorder != null) recorder.applyMatrix(n00, n01, n02, n03, n10, n11, n12, n13, n20, n21, n22, n23, n30, n31, n32, n33);
7582
g.applyMatrix(n00, n01, n02, n03, n10, n11, n12, n13, n20, n21, n22, n23, n30, n31, n32, n33);
7586
public PMatrix getMatrix() {
7587
return g.getMatrix();
7591
public PMatrix2D getMatrix(PMatrix2D target) {
7592
return g.getMatrix(target);
7596
public PMatrix3D getMatrix(PMatrix3D target) {
7597
return g.getMatrix(target);
7601
public void setMatrix(PMatrix source) {
7602
if (recorder != null) recorder.setMatrix(source);
7603
g.setMatrix(source);
7607
public void setMatrix(PMatrix2D source) {
7608
if (recorder != null) recorder.setMatrix(source);
7609
g.setMatrix(source);
7613
public void setMatrix(PMatrix3D source) {
7614
if (recorder != null) recorder.setMatrix(source);
7615
g.setMatrix(source);
7619
public void printMatrix() {
7620
if (recorder != null) recorder.printMatrix();
7625
public void beginCamera() {
7626
if (recorder != null) recorder.beginCamera();
7631
public void endCamera() {
7632
if (recorder != null) recorder.endCamera();
7637
public void camera() {
7638
if (recorder != null) recorder.camera();
7643
public void camera(float eyeX, float eyeY, float eyeZ,
7644
float centerX, float centerY, float centerZ,
7645
float upX, float upY, float upZ) {
7646
if (recorder != null) recorder.camera(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
7647
g.camera(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
7651
public void printCamera() {
7652
if (recorder != null) recorder.printCamera();
7657
public void ortho() {
7658
if (recorder != null) recorder.ortho();
7663
public void ortho(float left, float right,
7664
float bottom, float top,
7665
float near, float far) {
7666
if (recorder != null) recorder.ortho(left, right, bottom, top, near, far);
7667
g.ortho(left, right, bottom, top, near, far);
7671
public void perspective() {
7672
if (recorder != null) recorder.perspective();
7677
public void perspective(float fovy, float aspect, float zNear, float zFar) {
7678
if (recorder != null) recorder.perspective(fovy, aspect, zNear, zFar);
7679
g.perspective(fovy, aspect, zNear, zFar);
7683
public void frustum(float left, float right,
7684
float bottom, float top,
7685
float near, float far) {
7686
if (recorder != null) recorder.frustum(left, right, bottom, top, near, far);
7687
g.frustum(left, right, bottom, top, near, far);
7691
public void printProjection() {
7692
if (recorder != null) recorder.printProjection();
7693
g.printProjection();
7697
public float screenX(float x, float y) {
7698
return g.screenX(x, y);
7702
public float screenY(float x, float y) {
7703
return g.screenY(x, y);
7707
public float screenX(float x, float y, float z) {
7708
return g.screenX(x, y, z);
7712
public float screenY(float x, float y, float z) {
7713
return g.screenY(x, y, z);
7717
public float screenZ(float x, float y, float z) {
7718
return g.screenZ(x, y, z);
7722
public float modelX(float x, float y, float z) {
7723
return g.modelX(x, y, z);
7727
public float modelY(float x, float y, float z) {
7728
return g.modelY(x, y, z);
7732
public float modelZ(float x, float y, float z) {
7733
return g.modelZ(x, y, z);
7737
public void pushStyle() {
7738
if (recorder != null) recorder.pushStyle();
7743
public void popStyle() {
7744
if (recorder != null) recorder.popStyle();
7749
public void style(PStyle s) {
7750
if (recorder != null) recorder.style(s);
7755
public void strokeWeight(float weight) {
7756
if (recorder != null) recorder.strokeWeight(weight);
7757
g.strokeWeight(weight);
7761
public void strokeJoin(int join) {
7762
if (recorder != null) recorder.strokeJoin(join);
7767
public void strokeCap(int cap) {
7768
if (recorder != null) recorder.strokeCap(cap);
7773
public void noStroke() {
7774
if (recorder != null) recorder.noStroke();
7779
public void stroke(int rgb) {
7780
if (recorder != null) recorder.stroke(rgb);
7785
public void stroke(int rgb, float alpha) {
7786
if (recorder != null) recorder.stroke(rgb, alpha);
7787
g.stroke(rgb, alpha);
7791
public void stroke(float gray) {
7792
if (recorder != null) recorder.stroke(gray);
7797
public void stroke(float gray, float alpha) {
7798
if (recorder != null) recorder.stroke(gray, alpha);
7799
g.stroke(gray, alpha);
7803
public void stroke(float x, float y, float z) {
7804
if (recorder != null) recorder.stroke(x, y, z);
7809
public void stroke(float x, float y, float z, float a) {
7810
if (recorder != null) recorder.stroke(x, y, z, a);
7811
g.stroke(x, y, z, a);
7815
public void noTint() {
7816
if (recorder != null) recorder.noTint();
7821
public void tint(int rgb) {
7822
if (recorder != null) recorder.tint(rgb);
7827
public void tint(int rgb, float alpha) {
7828
if (recorder != null) recorder.tint(rgb, alpha);
7833
public void tint(float gray) {
7834
if (recorder != null) recorder.tint(gray);
7839
public void tint(float gray, float alpha) {
7840
if (recorder != null) recorder.tint(gray, alpha);
7841
g.tint(gray, alpha);
7845
public void tint(float x, float y, float z) {
7846
if (recorder != null) recorder.tint(x, y, z);
7851
public void tint(float x, float y, float z, float a) {
7852
if (recorder != null) recorder.tint(x, y, z, a);
7857
public void noFill() {
7858
if (recorder != null) recorder.noFill();
7863
public void fill(int rgb) {
7864
if (recorder != null) recorder.fill(rgb);
7869
public void fill(int rgb, float alpha) {
7870
if (recorder != null) recorder.fill(rgb, alpha);
7875
public void fill(float gray) {
7876
if (recorder != null) recorder.fill(gray);
7881
public void fill(float gray, float alpha) {
7882
if (recorder != null) recorder.fill(gray, alpha);
7883
g.fill(gray, alpha);
7887
public void fill(float x, float y, float z) {
7888
if (recorder != null) recorder.fill(x, y, z);
7893
public void fill(float x, float y, float z, float a) {
7894
if (recorder != null) recorder.fill(x, y, z, a);
7899
public void ambient(int rgb) {
7900
if (recorder != null) recorder.ambient(rgb);
7905
public void ambient(float gray) {
7906
if (recorder != null) recorder.ambient(gray);
7911
public void ambient(float x, float y, float z) {
7912
if (recorder != null) recorder.ambient(x, y, z);
7917
public void specular(int rgb) {
7918
if (recorder != null) recorder.specular(rgb);
7923
public void specular(float gray) {
7924
if (recorder != null) recorder.specular(gray);
7929
public void specular(float x, float y, float z) {
7930
if (recorder != null) recorder.specular(x, y, z);
7931
g.specular(x, y, z);
7935
public void shininess(float shine) {
7936
if (recorder != null) recorder.shininess(shine);
7941
public void emissive(int rgb) {
7942
if (recorder != null) recorder.emissive(rgb);
7947
public void emissive(float gray) {
7948
if (recorder != null) recorder.emissive(gray);
7953
public void emissive(float x, float y, float z) {
7954
if (recorder != null) recorder.emissive(x, y, z);
7955
g.emissive(x, y, z);
7959
public void lights() {
7960
if (recorder != null) recorder.lights();
7965
public void noLights() {
7966
if (recorder != null) recorder.noLights();
7971
public void ambientLight(float red, float green, float blue) {
7972
if (recorder != null) recorder.ambientLight(red, green, blue);
7973
g.ambientLight(red, green, blue);
7977
public void ambientLight(float red, float green, float blue,
7978
float x, float y, float z) {
7979
if (recorder != null) recorder.ambientLight(red, green, blue, x, y, z);
7980
g.ambientLight(red, green, blue, x, y, z);
7984
public void directionalLight(float red, float green, float blue,
7985
float nx, float ny, float nz) {
7986
if (recorder != null) recorder.directionalLight(red, green, blue, nx, ny, nz);
7987
g.directionalLight(red, green, blue, nx, ny, nz);
7991
public void pointLight(float red, float green, float blue,
7992
float x, float y, float z) {
7993
if (recorder != null) recorder.pointLight(red, green, blue, x, y, z);
7994
g.pointLight(red, green, blue, x, y, z);
7998
public void spotLight(float red, float green, float blue,
7999
float x, float y, float z,
8000
float nx, float ny, float nz,
8001
float angle, float concentration) {
8002
if (recorder != null) recorder.spotLight(red, green, blue, x, y, z, nx, ny, nz, angle, concentration);
8003
g.spotLight(red, green, blue, x, y, z, nx, ny, nz, angle, concentration);
8007
public void lightFalloff(float constant, float linear, float quadratic) {
8008
if (recorder != null) recorder.lightFalloff(constant, linear, quadratic);
8009
g.lightFalloff(constant, linear, quadratic);
8013
public void lightSpecular(float x, float y, float z) {
8014
if (recorder != null) recorder.lightSpecular(x, y, z);
8015
g.lightSpecular(x, y, z);
8019
public void background(int rgb) {
8020
if (recorder != null) recorder.background(rgb);
8025
public void background(int rgb, float alpha) {
8026
if (recorder != null) recorder.background(rgb, alpha);
8027
g.background(rgb, alpha);
8031
public void background(float gray) {
8032
if (recorder != null) recorder.background(gray);
8037
public void background(float gray, float alpha) {
8038
if (recorder != null) recorder.background(gray, alpha);
8039
g.background(gray, alpha);
8043
public void background(float x, float y, float z) {
8044
if (recorder != null) recorder.background(x, y, z);
8045
g.background(x, y, z);
8049
public void background(float x, float y, float z, float a) {
8050
if (recorder != null) recorder.background(x, y, z, a);
8051
g.background(x, y, z, a);
8055
public void background(PImage image) {
8056
if (recorder != null) recorder.background(image);
8057
g.background(image);
8061
public void colorMode(int mode) {
8062
if (recorder != null) recorder.colorMode(mode);
8067
public void colorMode(int mode, float max) {
8068
if (recorder != null) recorder.colorMode(mode, max);
8069
g.colorMode(mode, max);
8073
public void colorMode(int mode, float maxX, float maxY, float maxZ) {
8074
if (recorder != null) recorder.colorMode(mode, maxX, maxY, maxZ);
8075
g.colorMode(mode, maxX, maxY, maxZ);
8079
public void colorMode(int mode,
8080
float maxX, float maxY, float maxZ, float maxA) {
8081
if (recorder != null) recorder.colorMode(mode, maxX, maxY, maxZ, maxA);
8082
g.colorMode(mode, maxX, maxY, maxZ, maxA);
8086
public final float alpha(int what) {
8087
return g.alpha(what);
8091
public final float red(int what) {
8096
public final float green(int what) {
8097
return g.green(what);
8101
public final float blue(int what) {
8102
return g.blue(what);
8106
public final float hue(int what) {
8111
public final float saturation(int what) {
8112
return g.saturation(what);
8116
public final float brightness(int what) {
8117
return g.brightness(what);
8121
public int lerpColor(int c1, int c2, float amt) {
8122
return g.lerpColor(c1, c2, amt);
8126
static public int lerpColor(int c1, int c2, float amt, int mode) {
8127
return PGraphics.lerpColor(c1, c2, amt, mode);
8131
public boolean displayable() {
8132
return g.displayable();
8136
public void setCache(Object parent, Object storage) {
8137
if (recorder != null) recorder.setCache(parent, storage);
8138
g.setCache(parent, storage);
8142
public Object getCache(Object parent) {
8143
return g.getCache(parent);
8147
public void removeCache(Object parent) {
8148
if (recorder != null) recorder.removeCache(parent);
8149
g.removeCache(parent);
8153
public int get(int x, int y) {
8158
public PImage get(int x, int y, int w, int h) {
8159
return g.get(x, y, w, h);
8163
public PImage get() {
8168
public void set(int x, int y, int c) {
8169
if (recorder != null) recorder.set(x, y, c);
8174
public void set(int x, int y, PImage src) {
8175
if (recorder != null) recorder.set(x, y, src);
8180
public void mask(int alpha[]) {
8181
if (recorder != null) recorder.mask(alpha);
8186
public void mask(PImage alpha) {
8187
if (recorder != null) recorder.mask(alpha);
8192
public void filter(int kind) {
8193
if (recorder != null) recorder.filter(kind);
8198
public void filter(int kind, float param) {
8199
if (recorder != null) recorder.filter(kind, param);
8200
g.filter(kind, param);
8204
public void copy(int sx, int sy, int sw, int sh,
8205
int dx, int dy, int dw, int dh) {
8206
if (recorder != null) recorder.copy(sx, sy, sw, sh, dx, dy, dw, dh);
8207
g.copy(sx, sy, sw, sh, dx, dy, dw, dh);
8211
public void copy(PImage src,
8212
int sx, int sy, int sw, int sh,
8213
int dx, int dy, int dw, int dh) {
8214
if (recorder != null) recorder.copy(src, sx, sy, sw, sh, dx, dy, dw, dh);
8215
g.copy(src, sx, sy, sw, sh, dx, dy, dw, dh);
8219
static public int blendColor(int c1, int c2, int mode) {
8220
return PGraphics.blendColor(c1, c2, mode);
8224
public void blend(int sx, int sy, int sw, int sh,
8225
int dx, int dy, int dw, int dh, int mode) {
8226
if (recorder != null) recorder.blend(sx, sy, sw, sh, dx, dy, dw, dh, mode);
8227
g.blend(sx, sy, sw, sh, dx, dy, dw, dh, mode);
8231
public void blend(PImage src,
8232
int sx, int sy, int sw, int sh,
8233
int dx, int dy, int dw, int dh, int mode) {
8234
if (recorder != null) recorder.blend(src, sx, sy, sw, sh, dx, dy, dw, dh, mode);
8235
g.blend(src, sx, sy, sw, sh, dx, dy, dw, dh, mode);