diff --git a/processing/app/KjcApplet.java b/processing/app/KjcApplet.java new file mode 100644 index 000000000..fe6a30fb4 --- /dev/null +++ b/processing/app/KjcApplet.java @@ -0,0 +1,96 @@ +// special subclass only used inside the pde environment +// while the kjc engine is in use. takes care of error handling. + +public class KjcApplet extends BApplet { + KjcEngine engine; + + public void setEngine(KjcEngine engine) { + this.engine = engine; + } + + public void run() { + try { + super.run(); + } catch (Exception e) { + //System.out.println("ex found in run"); + //e.printStackTrace(); + //engine.error(e); + engine.newMessage = true; + e.printStackTrace(engine.leechErr); + } + } +} + + +/* + +public class BAppletViewer implements Runnable { + BApplet applet; + Thread killer; + //int portnum; + //Socket umbilical; + //OutputStream umbilicalOut; + //InputStream umbilicalIn; + + + static public void main(String args[]) { + try { + //portnum = Integer.parseInt(args[1]); + //umbilical = new Socket("localhost", portnum); + + new BAppletViewer(args[0], + Integer.parseInt(args[1]), + Integer.parseInt(args[2])); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + public BAppletViewer(String name, int x1, int y1) throws Exception { + Class c = Class.forName(name); + applet = (BApplet) c.newInstance(); + applet.init(); + applet.start(); + + Window window = new Window(new Frame()); + window.setBounds(x1 - applet.width, y1, applet.width, applet.height); + window.add(applet); + applet.setBounds(0, 0, applet.width, applet.height); + window.show(); + applet.requestFocus(); // necessary for key events + + //umbilical = new Socket("localhost", portnum); + //umbilicalOut = umbilical.getOutputStream(); + //umbilicalIn = umbilical.getInputStream(); + + killer = new Thread(this); + killer.start(); + } + + + File deathNotice = new File("die"); + + public void run() { + //while (Thread.currentThread() == killer) { + while (true) { + if (deathNotice.exists()) { + deathNotice.delete(); + System.exit(0); + } + //try { + //System.out.println("testing"); + //umbilicalOut.write(100); + //umbilicalIn.read(); + //} catch (Exception e) { + //e.printStackTrace(); + //System.exit(0); + //} + try { + Thread.sleep(100); + } catch (InterruptedException e) { } + } + } +} + +*/ diff --git a/processing/app/KjcEngine.java b/processing/app/KjcEngine.java new file mode 100644 index 000000000..f3f8ebdc3 --- /dev/null +++ b/processing/app/KjcEngine.java @@ -0,0 +1,1128 @@ +import java.awt.*; // for window, temporary +import java.awt.event.*; // also for window +import java.io.*; + +import java.net.*; // the start of a bad joke + +import at.dms.kjc.*; +import com.oroinc.text.regex.*; +//import at.dms.compiler.PositionedError; + + +// always compile to lib directory +// always make .java in current directory +// can copy over (and delete) later for export +// fix line number offset so that public class can be on a new line +// re-enable system err catching (after lib fixes) + +// doesn't really need to extend kjc.Main anymore, +// since reportTrouble doesn't actually do any good + +public class KjcEngine extends at.dms.kjc.Main implements PdeEngine { + static String TEMP_CLASS = "Temporary"; + static final String EXTENDS = "extends BApplet "; + static final String EXTENDS_KJC = "extends KjcApplet "; + + static final int COMPILING = 1; + static final int RUNNING = 2; + int messageMode; + + static final String imports[] = { + "java.applet", "java.awt", "java.awt.image", "java.awt.event", + "java.io", "java.net", "java.text", "java.util", "java.util.zip" + }; + + String tempClass; + String tempFilename; + //File tempDir; // for .java file + String tempClassFilename; + //File tempClassDir; // for .class file + PdeException exception; + + //PrintStream systemErr; + PrintStream leechErr; + KjcMessageStream messageStream; + + String program; + //PdeEnvironment env; + PdeEditor editor; + String buildPath; + + boolean running; + KjcApplet applet; + Window window; + + Process process; + static int portnum = 8192; + ServerSocket umbilical; + boolean usingExternal; + + + public KjcEngine(String program, String buildPath, + String dataPath, PdeEditor editor) { + this.program = program; + this.buildPath = buildPath; + //this.buildPath = "lib" + File.separator + "build"; + this.editor = editor; + + // only run cleanup if using the applications temp dir + //if (buildPath.endsWith("build")) cleanup(); + + File buildDir = new File(buildPath); + if (dataPath != null) { + File dataDir = new File(dataPath); + if (dataDir.exists()) { + String files[] = dataDir.list(); + for (int i = 0; i < files.length; i++) { + File sourceFile = new File(dataDir, files[i]); + if (sourceFile.isDirectory()) continue; // may fix in future + File targetFile = new File(buildDir, files[i]); + //System.err.println("source is " + sourceFile + + // " target is " + targetFile); + PdeEditor.copyFile(sourceFile, targetFile); + } + } + } + + usingExternal = PdeBase.getBoolean("play.external", false); + + /* + // what are the chances of this working on the mac? + // one in ninety nine? one in a 667 megahertz? + File dir = new File("."); + String list[] = dir.list(); + for (int i = 0; i < list.length; i++) { + if (list[i].indexOf(TEMP_CLASS) == 0) { + //System.out.println("culprit1: " + list[i]); + File deadMan = new File(dir, list[i]); + deadMan.delete(); + } + } + dir = new File("lib"); + list = dir.list(); + for (int i = 0; i < list.length; i++) { + if (list[i].indexOf(TEMP_CLASS) == 0) { + //System.out.println("culprit2: " + list[i]); + File deadMan = new File(dir, list[i]); + deadMan.delete(); + } + } + */ + //dir = new File(buildPath); + } + + + static final int BEGINNER = 0; + static final int INTERMEDIATE = 1; + static final int ADVANCED = 2; + + // writes .java file into buildPath + public String writeJava(String name, boolean kjc) { + //System.out.println("writing java"); + try { + int programType = BEGINNER; + + // remove (encode) comments temporarily + program = commentsCodec(program /*, true*/); + + // insert 'f' for all floats + if (PdeBase.getBoolean("compiler.substitute_f", true)) { + // allow 3. to work (also allows x.x too) + program = substipoot(program, "(\\d+\\.\\d*)(\\D)", "$1f$2"); + program = substipoot(program, "(\\d+\\.\\d*)ff", "$1f"); + + // allow .3 to work (also allows x.x) + program = substipoot(program, "(\\d*\\.\\d+)(\\D)", "$1f$2"); + program = substipoot(program, "(\\d*\\.\\d+)ff", "$1f"); + + /* + PatternMatcher matcher = new Perl5Matcher(); + PatternCompiler compiler = new Perl5Compiler(); + Pattern pattern = null; + + try { + pattern = compiler.compile("(\\d+\\.\\d+)([\\D^f])"); + //pattern = compiler.compile("(\\.\\d+)([^f])"); + //String $1f + + } catch (MalformedPatternException e){ + System.err.println("Bad pattern."); + System.err.println(e.getMessage()); + System.exit(1); + } + + Perl5Substitution subst = + new Perl5Substitution("$1f$2", Perl5Substitution.INTERPOLATE_ALL); + program = Util.substitute(matcher, pattern, subst, program, + Util.SUBSTITUTE_ALL); + */ + //System.out.println(program); + } + + // allow int(3.75) instead of just (int)3.75 + if (PdeBase.getBoolean("compiler.enhanced_casting", true)) { + program = substipoot(program, "([^A-Za-z0-9_])byte\\((.*)\\)", "$1(byte)($2)"); + program = substipoot(program, "([^A-Za-z0-9_])char\\((.*)\\)", "$1(char)($2)"); + program = substipoot(program, "([^A-Za-z0-9_])int\\((.*)\\)", "$1(int)($2)"); + program = substipoot(program, "([^A-Za-z0-9_])float\\((.*)\\)", "$1(float)($2)"); + + //program = substipoot(program, "(\\W)float\\((.*)\\)", "$1(float)($2)"); + //program = substipoot(program, "(\\W)int\\((.*)\\)", "$1(int)($2)"); + //System.out.println(program); + /* + PatternMatcher matcher = new Perl5Matcher(); + PatternCompiler compiler = new Perl5Compiler(); + Pattern pattern = null; + Perl5Substitution subst; + + try { + pattern = compiler.compile("\\sfloat\\((.*)\\)"); + + } catch (MalformedPatternException e){ + System.err.println("Bad pattern."); + System.err.println(e.getMessage()); + System.exit(1); + } + + subst = new Perl5Substitution(" (float)$1", + Perl5Substitution.INTERPOLATE_ALL); + program = Util.substitute(matcher, pattern, subst, program, + Util.SUBSTITUTE_ALL); + + try { + pattern = compiler.compile("\\sint\\((.*)\\)"); + + } catch (MalformedPatternException e){ + System.err.println("Bad pattern."); + System.err.println(e.getMessage()); + System.exit(1); + } + + subst = new Perl5Substitution(" (int)$1", + Perl5Substitution.INTERPOLATE_ALL); + program = Util.substitute(matcher, pattern, subst, program, + Util.SUBSTITUTE_ALL); + */ + } + + if (PdeBase.getBoolean("compiler.color_datatype", true)) { + // so that regexp works correctly in this strange edge case + if (program.indexOf("color") == 0) program = " " + program; + program = substipoot(program, + "([^A-Za-z0-9_])color([^A-Za-z0-9_\\(])", "$1int$2"); + //program = substipoot(program, "([^A-Za-z0-9_])color\\((.*)\\)", "$1(int)($2)"); + } + + if (PdeBase.getBoolean("compiler.inline_web_colors", true)) { + // convert "= #cc9988" into "= 0xffcc9988" + program = substipoot(program, "(=\\s*)\\#([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])", "$1 0xff$2$3$4"); + } + + if ((program.indexOf("void setup()") != -1) || + (program.indexOf("void loop()") != -1) || + (program.indexOf("void draw()") != -1)) { + programType = INTERMEDIATE; + } + + int index = program.indexOf("public class"); + if (index != -1) { + programType = ADVANCED; + // kjc will get pissed off if i call the .java file + // something besides the name of the class.. so here goes + String s = program.substring(index + "public class".length()).trim(); + index = s.indexOf(' '); + name = s.substring(0, index); + tempClass = name; + + // and we're running inside + if (kjc) { // if running inside processing... + index = program.indexOf(EXTENDS); // ...and extends BApplet + if (index != -1) { // just extends object + String left = program.substring(0, index); + String right = program.substring(index + EXTENDS.length()); + // replace with 'extends KjcApplet' + program = left + ((usingExternal) ? EXTENDS : EXTENDS_KJC) + right; + } + } + } + tempFilename = name + ".java"; + tempClassFilename = name + ".class"; + + PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(buildPath + File.separator + tempFilename)))); + + //String eol = System.getProperties().getProperty("line.separator"); + + if (programType < ADVANCED) { + // spew out a bunch of java imports + for (int i = 0; i < imports.length; i++) { + writer.print("import " + imports[i] + ".*; "); + if (!kjc) writer.println(); + } + if (!kjc) writer.println(); + + writer.print("public class " + name + " extends " + + ((kjc && !usingExternal) ? "KjcApplet" : "BApplet") + " {"); + } + if (programType == BEGINNER) { + if (!kjc) writer.println(); + + // first determine the size of the program + PatternMatcher matcher = new Perl5Matcher(); + PatternCompiler compiler = new Perl5Compiler(); + Pattern pattern = null; + + // hack so that the regexp below works + if (program.indexOf("size(") == 0) program = " " + program; + + try { + //pattern = compiler.compile("\ssize\(\d+),\s*(\d+)\)\;"); + //pattern = compiler.compile("^[^A-Za-z0-9_]+size\\(\\s*(\\d+),\\s*(\\d+)\\s*\\);"); + pattern = + compiler.compile("^([^A-Za-z0-9_]+)(size\\(\\s*\\d+,\\s*\\d+\\s*\\);)"); + + } catch (MalformedPatternException e){ + System.err.println("Bad pattern."); + System.err.println(e.getMessage()); + System.exit(1); + } + + //PatternMatcher matcher = new Perl5Matcher(); + String sizeInfo = ""; + PatternMatcherInput input = + new PatternMatcherInput(program); + if (matcher.contains(input, pattern)) { + MatchResult result = matcher.getMatch(); + //int wide = Integer.parseInt(result.group(1).toString()); + //int high = Integer.parseInt(result.group(2).toString()); + sizeInfo = "void setup() { " + result.group(0) + " } "; + + } else { + // no size() defined, make it 100x100 + } + + // remove references to size() + // this winds up removing every reference to size() + // not really intended, but will help things work + Perl5Substitution subst = + new Perl5Substitution("$1", Perl5Substitution.INTERPOLATE_ALL); + program = Util.substitute(matcher, pattern, subst, program, + Util.SUBSTITUTE_ALL); + //System.out.println(program); + + writer.print(sizeInfo); + writer.print("void draw() {"); + } + + // decode comments to bring them back + program = commentsCodec(program /*, false*/); + + // spew the actual program + // this should really add extra indents, + // especially when not in kjc mode (!kjc == export) + + // things will be one line off if there's an error in the code + if (!kjc) writer.println(); + + writer.println(program); + //System.out.println(program); + + if (programType == BEGINNER) { + writer.println("}"); + } + if (programType < ADVANCED) { + writer.print("}"); + } + + writer.flush(); + writer.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + return name; + } + + //static char encodeTable[] = new char[127]; + //static char decodeTable[] = new char[127]; + static char rotateTable[] = new char[127]; + static { + int rot = (123 - 65) / 2; + for (int i = 65; i < 123; i++) { + rotateTable[i] = (char) (((i - 65 + rot) % (rot*2)) + 65); // : (char)i; + } + + //for (int i = 33; i < 127; i++) { + //rotateTable[i] = //Character.isAlpha((char)i) ? + //(char) (((i - 33 + rot) % 94) + 33) : (char)i; + + //encodeTable[i] = (char) (i+1); + //decodeTable[i] = (char) (i-1); + //encodeTable[i] = (char) (((i - 33 + rot) % 94) + 33); + //decodeTable[i] = encodeTable[i]; + //encodeTable[i] = (char) (((i - 33 + rot) % 94) + 33); + //decodeTable[i] = (char) (((i + 33 + rot) % 94) + 33); + //System.out.println((int) decodeTable[i]); + //} + } + + protected String commentsCodec(String program /*, boolean encode*/) { + // need to preprocess class to remove comments + // so tthat they don't fool this crappy parsing below + char p[] = program.toCharArray(); + boolean insideComment = false; + boolean eolComment = false; + boolean slash = false; + for (int i = 0; i < p.length; i++) { + if (insideComment) { + if (eolComment && + ((p[i] == '\r') || (p[i] == '\n'))) { + insideComment = false; + slash = false; + + } else if (!eolComment && + (p[i] == '*') && + (i != (p.length-1)) && + (p[i+1] == '/')) { + insideComment = false; + slash = false; + + } else { + if ((p[i] > 32) && (p[i] < 127)) { + p[i] = rotateTable[p[i]]; + //p[i] = encode ? encodeTable[p[i]] : decodeTable[p[i]]; + } + //p[i] = ' '; + } + } else { // not yet inside a comment + if (p[i] == '/') { + if (slash) { + insideComment = true; + eolComment = true; + } else { + slash = true; + } + } else if (p[i] == '*') { + if (slash) { + insideComment = true; + eolComment = false; + } + } else { + slash = false; + } + } + } + //System.out.println(new String(p)); + return new String(p); + } + + protected String substipoot(String what, String incoming, String outgoing) { + PatternMatcher matcher = new Perl5Matcher(); + PatternCompiler compiler = new Perl5Compiler(); + Pattern pattern = null; + + try { + pattern = compiler.compile(incoming); + + } catch (MalformedPatternException e){ + System.err.println("Bad pattern."); + System.err.println(e.getMessage()); + System.exit(1); + } + + Perl5Substitution subst = + new Perl5Substitution(outgoing, Perl5Substitution.INTERPOLATE_ALL); + return Util.substitute(matcher, pattern, subst, what, + Util.SUBSTITUTE_ALL); + } + + //public void finalize() { + //System.out.println("finalizing KjcEngine"); + //} + + boolean newMessage; + + public void message(String s) { + if (messageMode == COMPILING) { + //System.out.println("leech2: " + new String(b, offset, length)); + //String s = new String(b, offset, length); + //if (s.indexOf(tempFilename) == 0) { + String fullTempFilename = buildPath + File.separator + tempFilename; + if (s.indexOf(fullTempFilename) == 0) { + String s1 = s.substring(fullTempFilename.length() + 1); + int colon = s1.indexOf(':'); + int lineNumber = Integer.parseInt(s1.substring(0, colon)); + //System.out.println("pde / line number: " + lineNumber); + + //String s2 = s1.substring(colon + 2); + int err = s1.indexOf("error:"); + if (err != -1) { + //err += "error:".length(); + String description = s1.substring(err + "error:".length()); + description = description.trim(); + //exception = new PdeException(description, lineNumber-2); + exception = new PdeException(description, lineNumber-1); + editor.error(exception); + + } else { + System.err.println("i suck: " + s); + } + + } else { + System.err.println("don't understand: " + s); + } + } else if (messageMode == RUNNING) { + //if (s.indexOf("MAKE WAY") != -1) { + //System.out.println("new message coming"); + //newMessage = true; + + //} else { + if (newMessage) { + //System.out.println("making msg of " + s); + exception = new PdeException(s); // type of java ex + //System.out.println("setting ex type to " + s); + newMessage = false; + } else { + int index = s.indexOf(tempFilename); + //System.out.println("> " + s); + if (index != -1) { + int len = tempFilename.length(); + String lineNumberStr = s.substring(index + len + 1); + index = lineNumberStr.indexOf(')'); + lineNumberStr = lineNumberStr.substring(0, index); + System.err.println("error line is: " + lineNumberStr); + try { + exception.line = Integer.parseInt(lineNumberStr) - 2; + //System.out.println("exception in RUNNING"); + editor.error(exception); + } catch (NumberFormatException e) { } + } else if ((index = s.indexOf(tempClass)) != -1) { + // code to check for: + // at Temporary_484_3845.loop(Compiled Code) + // would also probably get: + // at Temporary_484_3845.loop + // which (i believe) is used by the mac and/or jview + String functionStr = s.substring(index + tempClass.length() + 1); + index = functionStr.indexOf('('); + if (index != -1) { + functionStr = functionStr.substring(0, index); + } + exception = new PdeException(//"inside \"" + functionStr + "()\": " + + exception.getMessage() + + " inside " + functionStr + "() " + + "[add Compiler.disable() to setup()]"); + editor.error(exception); + // this will fall through in tihs example: + // at Temporary_4636_9696.pootie(Compiled Code) + // at Temporary_4636_9696.loop(Temporary_4636_9696.java:24) + // because pootie() (re)sets the exception title + // and throws it, but then the line number gets set + // because of the line that comes after + } + //System.out.println("got it " + s); + } + } + } + + + //public void error(Exception e) { + //newMessage = true; + //e.printStackTrace(leechErr); + //} + + + //public void reportTrouble(PositionedError trouble) { + //System.out.println("trubber: " + trouble); + //} + + + public boolean compileJava() throws PdeException { + String args[] = new String[2]; + //args[0] = "-dlib"; + //args[1] = tempFilename; + args[0] = "-d" + buildPath; + args[1] = buildPath + File.separator + tempFilename; + //System.out.println("args = " + args[0] + " " + args[1]); + + // this will catch and parse errors during compilation + // or should this be in the constructor? + messageStream = new KjcMessageStream(this); + leechErr = new PrintStream(messageStream); + //PrintStream systemErr = System.err; + System.setErr(leechErr); // NEED THIS + + messageMode = COMPILING; + boolean success = compile(args); + + // end of compilation error checking + //System.setErr(systemErr); + System.setErr(PdeEditorConsole.consoleErr); + //System.err.println("success = " + success); + + return success; + } + + + public void start() throws PdeException { + int numero1 = (int) (Math.random() * 10000); + int numero2 = (int) (Math.random() * 10000); + tempClass = TEMP_CLASS + "_" + numero1 + "_" + numero2; + //System.err.println("KjcEngine.started"); + writeJava(tempClass, true); + //System.err.println("KjcEngine wrote java"); + //System.out.println("thread active count is " + Thread.activeCount()); + + + //System.out.println("starting"); + + /* + if (!success) { + if (exception != null) { + throw exception; + } else { + throw new PdeException("KjcEngine.start uncaught problem [1]"); + } + } else if (exception != null) { + throw new PdeException("KjcEngine.start uncaught problem [2]"); + } + */ + //System.setErr(PdeEditorConsole.systemErr); + boolean result = compileJava(); + //System.setErr(PdeEditorConsole.consoleErr); + if (!result) return; + //System.err.println("compiling failed.. was error caught? "); + //System.err.println(exception); + //if (!success) return; + + //System.out.println("done compiling"); + + //System.err.println("system err is working"); + + messageMode = RUNNING; + Frame frame = editor.frame; + Point parentLoc = frame.getLocation(); + Insets parentInsets = frame.getInsets(); + + int x1 = parentLoc.x - 20; + //int y1 = parentLoc.y + parentInsets.top; // for Window version + int y1 = parentLoc.y; // + parentInsets.top; + + // then instantiate class poo using class.forName + try { + if (PdeBase.getBoolean("play.external", false)) { + String cmd = PdeBase.get("play.externalCommand"); + + //System.out.println( + process = Runtime.getRuntime().exec(/*"cmd /c " +*/ cmd + " " + tempClass + + " " + x1 + " " + y1); + new KjcMessageSiphon(process.getInputStream(), + process.getErrorStream(), leechErr); + + //tempClass + " " + portnum); + //umbilical = new ServerSocket(portnum); + //umbilical.accept(); + //portnum++; + + //InputStream is = process.getErrorStream(); + //InputStream is = process.getInputStream(); + //while (true) { + //System.out.print((char) is.read()); + //} + + } else { + // temporarily disabled + //KjcClassLoader loader = new KjcClassLoader(buildPath); + //Class c = loader.loadClass(tempClass); + Class c = Class.forName(tempClass); + + applet = (KjcApplet) c.newInstance(); + //((KjcApplet)applet).errStream = leechErr; + applet.setEngine(this); + applet.init(); + applet.start(); + + if (editor.presenting) { + window = new Window(new Frame()); + } else { + window = new Frame(); // gonna use ugly windows instead + ((Frame)window).setResizable(false); + window.pack(); // to get a peer, size set later, need for insets + + window.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + //System.exit(0); + editor.doClose(); + } + }); + } + if (!(window instanceof Frame)) y1 += parentInsets.top; + window.add(applet); + + // @#$((* java 1.3 + window.addMouseListener(applet); + window.addMouseMotionListener(applet); + window.addKeyListener(applet); + + Dimension screen = + Toolkit.getDefaultToolkit().getScreenSize(); + + //System.out.println(SystemColor.windowBorder.toString()); + + //window.setLayout(new BorderLayout()); + window.setLayout(null); + if (editor.presenting) { + window.setBounds((screen.width - applet.width) / 2, + (screen.height - applet.height) / 2, + applet.width, applet.height); + applet.setBounds(0, 0, applet.width, applet.height); + + } else { + Insets insets = window.getInsets(); + //System.out.println(insets); + int mw = PdeBase.getInteger("run.window.width.minimum", 120); + int mh = PdeBase.getInteger("run.window.height.minimum", 120); + int ww = Math.max(applet.width, mw) + insets.left + insets.right; + int wh = Math.max(applet.height, mh) + insets.top + insets.bottom; + window.setBounds(x1 - ww, y1, ww, wh); + + Color windowBgColor = + PdeBase.getColor("run.window.bgcolor", SystemColor.control); + //new Color(102, 102, 102)); + window.setBackground(windowBgColor); + //window.setBackground(SystemColor.windowBorder); + //window.setBackground(SystemColor.control); + + applet.setBounds((ww - applet.width)/2, + insets.top + ((wh-insets.top-insets.bottom) - + applet.height)/2, ww, wh); + /* + window.setBounds(x1 - applet.width, y1, + //parentLoc.x - (applet.width + 20), + //parentLoc.y + parentInsets.top, + applet.width, applet.height); + */ + } + + //new WindowDragger(window, applet.height); + /* + window.add(new MouseMotionAdapter() { + int px, py; + + public mouseDragged(MouseEvent e) { + } + }); + */ + + /* + window.addWindowListener(new WindowAdapter() { + public void windowOpened(WindowEvent e) { + System.out.println(e); + } + + public void windowClosing(WindowEvent e) { + System.out.println(e); + } + + public void windowClosed(WindowEvent e) { + System.out.println(e); + } + + public void windowIconified(WindowEvent e) { + System.out.println(e); + } + + public void windowDeiconified(WindowEvent e) { + System.out.println(e); + } + + public void windowActivated(WindowEvent e) { + System.out.println(e); + } + + public void windowDeactivated(WindowEvent e) { + System.out.println(e); + } + }); + */ + + /* + window.addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent e) { + Frame f = (Frame) e.getComponent(); // me + Rectangle bounds = f.getBounds(); + Insets insets = f.getInsets(); + System.out.println(insets); + + if ((bounds.x == -insets.left) && + (bounds.y == -insets.bottom)) { // half-assed maximizing + + Dimension screen = + Toolkit.getDefaultToolkit().getScreenSize(); + + //System.out.println(f.getInsets()); + //System.out.println(e.getComponent().getClass()); + System.out.println("asking for bounds " + + (screen.height + insets.top + insets.bottom)); + f.setBounds(-insets.left, -insets.top, + screen.width + insets.left + insets.right, + screen.height + insets.top + insets.bottom); + + f.doLayout(); + // center the applet in the window + + } + System.out.println(e); + } + + public void componentMoved(ComponentEvent e) { + //System.out.println(e); + } + + public void componentShown(ComponentEvent e) { + //System.out.println(e); + } + + public void componentHidden(ComponentEvent e) { + //System.out.println(e); + } + }); + + window.add(applet, BorderLayout.CENTER); + window.add(new Label(), BorderLayout.NORTH); + window.add(new Label(), BorderLayout.SOUTH); + window.add(new Label(), BorderLayout.EAST); + window.add(new Label(), BorderLayout.WEST); + */ + + //window.pack(); + applet.setVisible(true); // no effect + window.show(); + applet.requestFocus(); // necessary for key events + } + running = true; + + //while (running) { } + // since this is already contained in a thread + //applet.run(); + + //need to parse this code to give a decent error message + + //internal error + //java.lang.NullPointerException + // at ProcessingApplet.colorMode(ProcessingApplet.java:652) + // at Temporary_203_1176.setup(Temporary_203_1176.java:3) + + } catch (Exception e) { + // this will pass through to the first part of message + // this handles errors that happen inside setup() + newMessage = true; + e.printStackTrace(leechErr); + //if (exception != null) throw exception; + } + } + + + public void cleanup() { + File buildDir = new File(buildPath); + if (!buildDir.exists()) buildDir.mkdirs(); + + String list[] = buildDir.list(); + for (int i = 0; i < list.length; i++) { + if (list[i].equals("..") || list[i].equals(".")) + continue; + //System.out.println("removing: " + buildDir + " " + list[i]); + //deadMan.delete(); + new File(buildDir, list[i]).delete(); + } + + /* + try { + //System.out.println("cleaning up"); + File file = new File("lib/" + tempClassFilename); + //File file = new File(tempClassDir, tempClassFilename); + if (file.exists()) file.delete(); + } catch (Exception e) { + e.printStackTrace(); + } + + try { + File file = new File(tempFilename); + //File file = new File(tempDir, tempFilename); + if (file.exists()) file.delete(); + } catch (Exception e) { + e.printStackTrace(); + } + */ + } + + + public void stop() { + running = false; + + //System.out.println(); + //System.out.println("* stopping"); + + // in case stop is called during compilation + if (applet != null) applet.stop(); + //if (window != null) window.hide(); + + // above avoids NullPointerExceptions + // but still threading is too complex, and so + // some boogers are being left behind + + applet = null; + //window = null; + + if (process != null) { // running externally + //System.out.println("killing external process"); + //process.destroy(); + + //System.out.println("cutting umbilical cord"); + try { + FileOutputStream fos = new FileOutputStream("die"); + fos.close(); + } catch (Exception e) { + e.printStackTrace(); + } + //try { + //umbilical.close(); + //umbilical = null; + //} catch (IOException e) { + //e.printStackTrace();w + //} + } + + cleanup(); + + //System.gc(); + //System.out.println("* stopped"); + + //System.out.println("thread count: " + Thread.activeCount()); + //System.out.println(); + //System.out.println(); + } + + + public void close() { + //if (window != null) window.hide(); + if (window != null) { + //System.err.println("disposing window"); + window.dispose(); + window = null; + } + } + + + public void inform(String message) { + System.out.println("informing: " + message); + } +} + + +class KjcClassLoader extends ClassLoader { + String basePath; + + public KjcClassLoader(String basePath) { + this.basePath = basePath; + } + + public synchronized Class loadClass(String className, boolean resolveIt) + throws ClassNotFoundException { + + Class result; + byte classData[]; + + // Check the loaded class cache + result = findLoadedClass(className); + if (result != null) { + // Return a cached class + return result; + } + + // Check with the primordial class loader + try { + result = super.findSystemClass(className); + // Return a system class + return result; + } catch (ClassNotFoundException e) { } + + // Don't attempt to load a system file except through + // the primordial class loader + if (className.startsWith("java.")) { + throw new ClassNotFoundException(); + } + + // Try to load it from the basePath directory. + classData = getTypeFromBasePath(className); + if (classData == null) { + System.out.println("KjcClassLoader - Can't load class: " + className); + throw new ClassNotFoundException(); + } + + // Parse it + result = defineClass(className, classData, 0, classData.length); + if (result == null) { + System.out.println("KjcClassLoader - Class format error: " + + className); + throw new ClassFormatError(); + } + + if (resolveIt) { + resolveClass(result); + } + + // Return class from basePath directory + return result; + } + + private byte[] getTypeFromBasePath(String typeName) { + FileInputStream fis; + String fileName = basePath + File.separatorChar + + typeName.replace('.', File.separatorChar) + ".class"; + + try { + fis = new FileInputStream(fileName); + } catch (FileNotFoundException e) { + return null; + } + + BufferedInputStream bis = new BufferedInputStream(fis); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + try { + int c = bis.read(); + while (c != -1) { + out.write(c); + c = bis.read(); + } + } catch (IOException e) { + return null; + } + return out.toByteArray(); + } +} + + +class KjcMessageSiphon implements Runnable { + InputStream input, error; + PrintStream leechErr; + Thread thread; + + public KjcMessageSiphon(InputStream input, InputStream error, + PrintStream leechErr) { + this.input = input; + this.error = error; + + thread = new Thread(this); + thread.start(); + } + + public void run() { + while (Thread.currentThread() == thread) { + try { + if (error.available() > 0) { + while (error.available() > 0) { + System.out.print((char)error.read()); + } + error = null; // get out + throw new Exception(); + } + + while (input.available() > 0) { + System.out.print((char)input.read()); + } + Thread.sleep(100); + + /* + int c = error.read(); + if (c == -1) { + error = null; // get out + throw new Exception(); + } + System.out.print((char)c); + Thread.sleep(5); + */ + } catch (Exception e) { + if ((error != null) && (leechErr != null)) { + System.out.println("KjcMessageSiphon err " + e); + } + thread.stop(); + thread = null; + } + } + } +} + + +class KjcMessageStream extends OutputStream { + KjcEngine parent; + + public KjcMessageStream(KjcEngine parent) { + this.parent = parent; + } + + public void close() { } + + public void flush() { } + + public void write(byte b[]) { + System.out.println("leech1: " + new String(b)); + } + + public void write(byte b[], int offset, int length) { + //System.out.println("leech2: " + new String(b)); + parent.message(new String(b, offset, length)); + } + + public void write(int b) { + System.out.println("leech3: '" + ((char)b) + "'"); + } +} + + +/* +class WindowDragger implements MouseListener, MouseMotionListener { + Window window; + int minY; + boolean inside; + + int lastX, lastY; + + // if drag starts outside window, this will break.. easy to fix + + public WindowDragger(Window window, int minY) { + this.window = window; + this.minY = minY; + + window.addMouseListener(this); + window.addMouseMotionListener(this); + } + + public void mouseClicked(MouseEvent e) { } + + public void mousePressed(MouseEvent e) { + lastX = e.getX(); + lastY = e.getY(); + inside = (lastY > minY); + System.out.println("inside = " + inside); + } + + public void mouseReleased(MouseEvent e) { } + public void mouseEntered(MouseEvent e) { } + public void mouseExited(MouseEvent e) { } + + public void mouseDragged(MouseEvent e) { + if (!inside) return; + + System.out.println("inside, dragging"); + Point location = window.getLocation(); + int newX = e.getX(); + int newY = e.getY(); + window.setLocation(location.x + (newX-lastX), + location.y + (newY-lastY)); + lastX = newX; + lastY = newY; + } + + public void mouseMoved(MouseEvent e) { } +} +*/ diff --git a/processing/app/make.sh b/processing/app/make.sh index 6d39ad02d..133e7dc3f 100755 --- a/processing/app/make.sh +++ b/processing/app/make.sh @@ -1,17 +1,12 @@ #!/bin/sh -### standard Proce55ing application build - -### -- BUG need to test if lib/export exists, create it if not -### -- may exist but is being pruned by cvs - ### -- BUILD BAGEL ---------------------------------------------- cd .. cd bagel -set SAVED_CLASSPATH=$CLASSPATH -set CLASSPATH=java\lib\ext\comm.jar\;$CLASSPATH +# hmm? +#CLASSPATH=java\lib\ext\comm.jar\;$CLASSPATH ### --- make version with serial for the application echo Building bagel with serial support @@ -26,27 +21,17 @@ cp classes/*.class ../app/lib/export/ cd .. cd app -#set CLASSPATH = %SAVED_CLASSPATH% -set CLASSPATH=$SAVED_CLASSPATH - ### -- BUILD PDE ------------------------------------------------ echo Building PDE for JDK 1.3 -#CLASSPATH2=$CLASSPATH -CLASSPATH=classes:lib/kjc.jar:lib/oro.jar:java/lib/rt.jar:java/lib/ext/comm.jar -#echo cp2 is now ${CLASSPATH2} -#echo classpath is now $CLASSPATH - -#rm -f classes/*.class +#CLASSPATH=classes:lib/kjc.jar:lib/oro.jar:java/lib/rt.jar:java/lib/ext/comm.jar +CLASSPATH=classes:lib/kjc.jar:lib/oro.jar:$CLASSPATH perl buzz.pl "jikes +D -classpath $CLASSPATH -d classes" -dJDK13 *.java kjc/*.java -#perl buzz.pl "jikes +D -d classes" -dJDK13 *.java kjc/*.java cd classes rm -f ../lib/pde.jar zip -0q ../lib/pde.jar *.class cd .. -#CLASSPATH=$CLASSPATH2 - diff --git a/processing/build/shared/lib/buttons.gif b/processing/build/shared/lib/buttons.gif new file mode 100644 index 000000000..e3a76f562 Binary files /dev/null and b/processing/build/shared/lib/buttons.gif differ diff --git a/processing/build/shared/lib/pde.properties b/processing/build/shared/lib/pde.properties new file mode 100644 index 000000000..dd43eb7ba --- /dev/null +++ b/processing/build/shared/lib/pde.properties @@ -0,0 +1,75 @@ +# p r o c e s s i n g development environment settings +# these are similar to those used with the applet version. +# edit these only if you know what you're doing. + + +editor.buttons.bgcolor = #999999 +editor.buttons.status.font = SansSerif,plain,10 +editor.buttons.status.color = #333333 + +editor.program.rows = 20 +editor.program.columns = 60 +editor.program.font = Monospaced,plain,12 + +editor.header.bgcolor = #333333 +editor.header.fgcolor.primary = #ffffff +editor.header.fgcolor.secondary = #cccccc +editor.header.font = SansSerif,plain,12 + +editor.console.bgcolor = #0a0a0a +editor.console.fgcolor.output = #cccccc +editor.console.fgcolor.error = #cc0000 +editor.console.font = Monospaced,plain,11 +editor.console.lines = 6 + +#editor.status.notice.fgcolor = #333333 +#editor.status.notice.bgcolor = #cccccc +#editor.status.error.fgcolor = #ffffff +#editor.status.error.bgcolor = #CC0000 +#editor.status.prompt.fgcolor = #FFFFFF +#editor.status.prompt.bgcolor = #CC9900 +#editor.status.font = SansSerif,plain,10 + +# not necessary to set bgcolor of window b/c it comes from os +#run.window.bgcolor = #666666 +run.window.width.minimum = 120 +run.window.height.minimum = 120 +run.present.bgcolor = #999999 + +serial.port = COM1 +serial.rate = 9600 +serial.parity = N +serial.databits = 8 +serial.stopbits = 1 + +# enable this to run hack-version mildly stabler external processing +#play.external = true + +# use this with above under windows 2000 +play.externalCommand = .\\bin\\jre -cp lib;lib\\sketchbook;lib\\pde.jar;lib\\kjc.jar;lib\\comm.jar ProcessingAppletViewer + +# use this with above for window 95/98/ME and you want play.external +# it will also be necessary to put processing in c:\ +#play.externalCommand = C:\\processing\\bin\\jre -cp c:\\processing\\lib;c:\\processing\\lib\\pde.jar;c:\\processing\\lib\\kjc.jar;c:\\processing\\lib\\comm.jar ProcessingAppletViewer + +program = fillstrokebroken.pde +#program = lib/dbn.pde +#program = hack.pde +#program = glyphrot3.pde +#program = ../test/shape-spatial-lineloop.pde +#program = ../test/shape-points.pde +#program = ../test/font-vlw.pde +#program = ../test/bagelfixes.pde +#program = ../sketchbook/standard/SimpleSerialDemo.pde +#program = ../basicstamp/test.pde +#program = ../test/colorcube.pde +#program = ../kjc/export.pde + +editor.expandTabs=true +editor.tabSize=2 +editor.autoIndent=true +editor.balanceParens=true + +#update.enabled +#update.url = http://acg.media.mit.edu/people/fry/processing/update/ +#update.url = http://imrf.or.jp/processing/update/ diff --git a/processing/build/shared/notes.txt b/processing/build/shared/notes.txt new file mode 100644 index 000000000..bdb8d51e5 --- /dev/null +++ b/processing/build/shared/notes.txt @@ -0,0 +1,508 @@ +ABOUT REV 0035 + +- duplicate/rename replaced with save as + +- curves were broken (didn't draw anything) + now they're not (they draw things) + +- curve() now makes more sense and fits all four points provided + +- using translate() no longer makes lines turn black. ahem. + +- fixed status message color + +- added newline before program code when exporting .java files + +- removed NullPointerException on startup + + +ABOUT REV 0034 + +- fixed the problems with launching applets, implemented frame + around the applet being run, also implemented presentation mode + +- with any luck this one should be a little more stable than some + of these other ones in the 30s series that i keep releasing without + any sensible amount of quality control. + + +ABOUT REV 0033 + +- duplicate and rename now implemented, more (should be all) of + the menus are actually functional. some are hacks (item to + launch proce55ing.net and the reference) but things should be + generally more consistent. + + +ABOUT REV 0032 + +- another major release that irons out issues of export and + the toolbar. a button for a new project is included, and + the toolbar items properly open/load/save entries to/from + the sketchbook. export should be working, as should external + files accessed via getImage/getStream/etc. + + +ABOUT REV 0031 + +- this is a major release, representing several victories. + most important: sketchbook is finally in there. every piece + of work is a 'sketch', a very lightweight project setup. + +- export has not been tested and has a good bit of new code + so that may be problematic. + +- menubar with all available options--note that these relate to + sketchbook, and that the toolbar buttons may not work as well. + use menus/key commands where possible(!) + +- generally more application-like with prompts for the user + for saving changes when closing a sketch or quitting. + editor now keeps track of changes made. window positions and + the last sketch opened are saved. + +- concept of a user name associated with the app, right now + just set to 'default' but in beta will be able to change + the name for workshops and general use. + +- current items in sketchbook (serial/dbn) aren't in correct format, + and won't work if you switch to them + + +ABOUT REV 0030 + +- fix bug where comments were being removed from exported files + +- new 'color' datatype, the following are now valid: + color c = color(23, 45, 99); + color c = #ff00cc; + + +ABOUT REV 0029 + +- actually updated pde.jar, export, pde.properties, BApplet.java + in sketchbook, removed extra dbn.pde from lib (it's in sketchbk) + +- new api: triangle, quad (put rect back too) + +- keyPressed() and mousePressed() events + +- new functions: degrees(), radians() + +- new color tidbits (though color still ints) final solution + for get/set pixel debate + + +ABOUT REV 0028 + +- serial port should work again (win32comm was missing) + +- modified pde.properties slightly for console and header + +- added output console the main interface + +- old-style c++ int(), float(), char(), byte() all work + for casting of datatypes, instead of confusing c syntax + +- size now works in draw() mode + +- fixed annoying findSelection bug spew on startup + +- 0.4f now works, formerly wasn't allowed + +- lots of preprocessor tweaking for exceptional cases + +- jre now in its own subdirectory, separate from 'lib' + + +ABOUT REV 0027 + +- released on the floor of dis2002. welcome to london. + +- editor.buttons.bgcolor was having issues + +- plane is now quad, PLANE is now QUAD + +_ latest iteration of colors and buttons + + +ABOUT REV 0026 + +- fixed the situation where i'm a dork and forgot to + actually update the pde.jar file, which had rendered the + changes in rev 0025 irrelevant + + +ABOUT REV 0025 + +- 'rect' is now 'plane' + +- QUADS are now PLANES, QUAD_STRIP is PLANE_STRIP + +- curve() and bezier() now behave the same way + +- made all ui colors/fonts accessible from pde.properties + +- fixed long font names for the mac release + + +ABOUT REV 0024 + +- lighting was broken, but no longer + +- turned lights off by default + + +ABOUT REV 0023 + +- versions 21 through 23 dealt with getting the beast to work smoothly + for the numer workshop + + +ABOUT REV 0020 + +major release, significant, code-destroying changes + +- largeish handful of api changes (see docs for update) + +- naming of api for BagelImage and others changed to BImage + +- ProcessingApplet is now BApplet + +- doesn't work on the mac due to update problem + +- new user interface (not all features work yet) + +- no longer need to use 'f' with floats + in fact, don't ever use f with floats b/c you'll get an error + + +ABOUT REV 0019 + +noticeable changes: + +- many changes to names of functions in api + +- default background color is gray, size is 100x100 + +internal changes: + +- single color function, colors properly clamped, MemoryImageSource + moved into ProcessingApplet + +- rect() now affected by transforms more properly + +- long list of other tidbits in cvs + + +ABOUT REV 0018 + +bug fix: + +- i broke fonts in the last release. now they work again. my own fault + for trying to improve things. + +feature: + +- projectSize(x, y, z, width, height, depth) is like projectPoint() + but allows you to transform an object shape to screen space and puts + the size into g.projX, g.projY, g.projZ + + +ABOUT REV 0017 + +features and tweaks: + +- setFont() now takes a font size + +- exporting to applets is slightly less buggy + +- hopefully lines are only a single pixel thick when they should be, + in slightly more cases + +- added a 'hint' for smoothing of images and fonts. put + hint(SMOOTH_IMAGES) in your code to enable smoother text and images, + but at the risk of things running more slowly. use + unhint(SMOOTH_IMAGES) to disable. + +- millis is a variable that always contains the number of milliseconds + since your applet started as an int. before it was always zero. use + it wisely. + +- loadImage, loadFont, and getStream are behaving better + +- no longer the random exception in graphics that would cause your + programs to hang due to an ArrayIndexOutOfBoundsException. haven't + fixed the bug, but it's at least being caught and worked around. + +known issues: + +- if you're using 'extends ProcessingApplet' in your code, you'll have + to use that class name for anything that you export. otherwise incur + the wrath of a bunch of spew at the dos prompt. + +- consistently thin lines are still erratic and not under control + +- the line highlighted for any particular error is often a joke + +- lots of other things, too numerous to list that make me wonder if + this will ever be ready to go + + +ABOUT REV 0016 + +- disabled (by default) the sketchiness from the previous version. so + the commportinuse trouble is back, unless you re-enable the hack + in the pde.properties file and set 'play.external' to true + +- no actual code changes in this version, but just upped the rev + number to avoid confusion + + +ABOUT REV 0015 + +known issues: + +- this version of processing is even more sketchy than many other + ones. but maybe it fix two huge issues, so i'm releasing it + anyways with this caveat. just go back to 14 or another one if this + gives you too much trouble. + + +features and tweaks: + +- includes a strange hack that fixes the CommPortInUseException that + had been so annoying, forcing you to restart processing to run your + apps. the downside is that the fix means that if there's an error in + your app, you have to check the console (the msdos prompt) for the + error line, because it won't get highlighted automatically + +- switch to the IBM's java virtual machine. it seems stabler than the + sun one, and sun's stinks because of that nasty screen flickering + bonanza that starts after you've been running processing for a bit. + + +ABOUT REV 0014 + +features and tweaks: + +- completely flat, unresized images are now significantly faster. this + affects any time that you use image(img, x, y) and you haven't yet + used translate/rotate/scale/etc. + +- thin, one pixel lines are much much faster, provided you aren't + scaling them larger, by say scale(10) or something like that. + +- new version of java compiler (kjc) that hopefully sucks less. + +- bezierCurve() and catmullRomCurve() have reappeared + + +bugs fixed: + +- way too many OutOfMemoryErrors and maybe that nasty flickery/jumpy + thing. + +- 3D calls to vertex() weren't making things 3D unless a translate or + a rotate was used + + +known issues: + +- flickery/jumpy thing after the applet runs for a little while. this + is a bug in sun's java virtual machine (i can't actually program the + pyrotechnics you're seeing on your screen) but may have resurfaced + due to low memory conditions because run.bat was screwed up. so the + problem may be fixed. hopefully. maybe. hmm. + +- i've tweaked a bunch of stuff in this release but haven't had a lot + of time to test. things look like they're doing much better. but as + is the case with any release, you can always go back to a previous + version if the new one gives you too much trouble. + + +ABOUT REV 0013 + +features and tweaks: + +- you can set the background color to be used when your applet is + in full screen mode. in lib/pde.properties change the line + fullscreen.bgcolor=#0080ff + to include whatever color you want. the syntax is the same as web + pages, although you aren't limited to the web palette. + +- screenGrab() functionality! get happy. + add screenGrab() at the end of your loop() function to produce + a series of numbered tiff-format images that can be imported + into a video editing app. or call screenGrab() when the mouse is + pressed to take quick snapshots. + +- colorcube applet is updated to the current release. + it is also now included in the sketchbook/examples directory. + +- for the technically inclined or curious, the source code for + ProcessingApplet is included in the sketchbook/standard directory. + it's not particularly pretty, since it's continually changing, but + can be useful if you're wondering about how things work. + + +bugs fixed: + +- the fix for rev 12 wasn't actually included in rev 12. grr. + this implies 1) i'm an idiot, and 2) rev 11 and 12 are the same. + +- ellipse was drawing opposite the direction of the origin. + +- default program now actually works--replaced colorScale() + +- editor was selecting the wrong line for errors. + + +ABOUT REV 0012 + +this was a simple fix for a big problem... programs that included +'extends ProcessingApplet' didn't work and gave a cryptic error +message. other than that, no new features. + + +ABOUT REV 0011 + +i've changed (broken) enough things in this new release that i'm +writing down a list of changes. your programs may run a little funny +in rev 11, but it's all for the better in the long run. let me know if +you have trouble getting things to work. and of course, keep a copy of +rev 9 around in case things go wrong. + +that said, rev 11 should be a much happier place to work. due to the +harrassment of your classmates, i've completed (simple) font support, +among other things. + +[for those who missed rev 10, it only existed for 15 minutes, because a +bug was found as i was preparing to send it out.] + + + +FONTS are working. a simple example: + +void setup() { + size(300, 300); + setFont(loadFont("fonts/Univers76.vlw.gz")); + fill(200, 200, 00); + background(10, 70, 200); +} + +void loop() { + rect(10, 10, 100, 100); + translate(mouseX, mouseY); + scale(20, 20); + text("I'm a little typeface short and stout", 0, 0); +} + +the 0, 0 part at the end of 'text' is the x, y location to put it. +the scale(20, 20) means 20 point font (fonts are 1 pixel high). +(note that with the scale() in there, the x, y coords for text() will +also be multiplied by 20x.) + +bunch of cheezy fonts are included in a 'fonts' directory. not +sure if i'll include these in the future, but at least it's a start. + + + +IMAGES are working. a simple example: + +BagelImage b; + +void setup() { + size(300, 300); + fill(100); + b = loadImage("max_van_kleek.gif"); +} + +void loop() { + image(b, mouseX, mouseY); +} + +this drags poor max around the screen with the mouse position. the +image should be in the same directory as run.bat. jpeg images can be +used too. + + + +RANDOM() functions, more random than ever + +// get a float between 0 and 40, or [0..40) for math weenies +float a = random(40); + +// get a float between -1 and 1 +float b = random(-1, 1); + +// get an int between 0 and 9 +int c = (int) random(10); + + + +PIXELS... you want them + +pixels[] is an int array that contains all of the image data from the +screen, in ARGB format (packed into ints). play away. + +if you don't know what that means and would like to use the pixel +array directly, let me know. + + + +FIXED WIDTH FONTS + +make-your-own-fixed-width-fonts-in-photoshop are supported. +but i'm not gonna bother documenting them unless someone asks. + + + +ALTERCATIONS + ++ rect(x, y, width, height) instead of rect(x1, y1, x2, y2) + ++ ellipse(x, y, width, height) instead of oval + ++ box(size) instead of cube() + ++ box(width, height, depth) instead of box(x1, y1, z1, x2, y2, z2) + ++ sphere(size) stays the same + ++ image() instead of imageRect() + ++ translate(x, y) in addition to translate(x, y, z) + ++ scale(size) and scale(x, y) in addition to scale(x, y, z) + ++ rotate(angle) rotates by angle in 2D + ++ rotateX, rotateY, rotateZ (angle) each rotate by angle + around their respective axes + ++ transform( .. 16 floats here .. ) if you think you're matrix math + genius and wanna play with your own transformations + + + +LESS ANNOYANCE + ++ no longer write software backwards! new shapes being drawn actually +replace older shapes, even when using flat, 2D surfaces. + ++ no need to use 'extends KjcProcessingApplet' anymore, just use +'extends ProcessingApplet', and processing will figure out whether +the 'Kjc' part is relevant or not. + + + +PROBABLY NEVER NOTICED + ++ colorScale() no longer exists. use colorMode(RGB, ...) + instead, where ... is whatever you would've put inside colorScale() + ++ included run95.bat for people who are using 95/98/ME. you can use + this .bat if run.bat opens a dos window and closes it quickly + without starting processing. just put processing at the base of your + c: drive in a folder called 'processing'.