mirror of
https://github.com/processing/processing4.git
synced 2026-05-31 04:28:06 +02:00
major changes to internal rendering for PShape, also changes to candy to
reflect PShape object
This commit is contained in:
@@ -80,7 +80,7 @@ The naming of jar and zip files in the tool/* directory doesn't matter.
|
||||
|
||||
When Processing loads, the jar and zip files will be searched for
|
||||
Mangler.class. Even though this tool is found in package poos.shoe,
|
||||
it will be sussed out. Package names are encouraged/recommended/required.
|
||||
it will be sussed out. Package names are required.
|
||||
|
||||
Loose .class files are not supported, use only jar and zip files.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry excluding="processing/candy/Group.java" kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/core"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/xml"/>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#Sat Nov 11 10:35:15 EST 2006
|
||||
#Thu Aug 28 18:42:23 EDT 2008
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.3
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore
|
||||
org.eclipse.jdt.core.compiler.source=1.3
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#Sat Nov 11 10:35:15 EST 2006
|
||||
eclipse.preferences.version=1
|
||||
internal.default.compliance=default
|
||||
@@ -0,0 +1,609 @@
|
||||
package processing.candy;
|
||||
|
||||
import java.awt.Paint;
|
||||
import java.util.HashMap;
|
||||
|
||||
import processing.core.*;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
public class BaseObject extends PShape {
|
||||
XMLElement element;
|
||||
|
||||
float opacity;
|
||||
|
||||
Gradient strokeGradient;
|
||||
Paint strokeGradientPaint;
|
||||
String strokeName; // id of another object, gradients only?
|
||||
|
||||
Gradient fillGradient;
|
||||
Paint fillGradientPaint;
|
||||
String fillName; // id of another object
|
||||
|
||||
|
||||
|
||||
public BaseObject(BaseObject parent, XMLElement properties) {
|
||||
//super(GROUP);
|
||||
|
||||
if (parent == null) {
|
||||
// set values to their defaults according to the SVG spec
|
||||
stroke = false;
|
||||
strokeColor = 0xff000000;
|
||||
strokeWeight = 1;
|
||||
strokeCap = PConstants.SQUARE; // equivalent to BUTT in svg spec
|
||||
strokeJoin = PConstants.MITER;
|
||||
strokeGradient = null;
|
||||
strokeGradientPaint = null;
|
||||
strokeName = null;
|
||||
|
||||
fill = true;
|
||||
fillColor = 0xff000000;
|
||||
fillGradient = null;
|
||||
fillGradientPaint = null;
|
||||
fillName = null;
|
||||
|
||||
//hasTransform = false;
|
||||
//transformation = null; //new float[] { 1, 0, 0, 1, 0, 0 };
|
||||
|
||||
opacity = 1;
|
||||
|
||||
} else {
|
||||
stroke = parent.stroke;
|
||||
strokeColor = parent.strokeColor;
|
||||
strokeWeight = parent.strokeWeight;
|
||||
strokeCap = parent.strokeCap;
|
||||
strokeJoin = parent.strokeJoin;
|
||||
strokeGradient = parent.strokeGradient;
|
||||
strokeGradientPaint = parent.strokeGradientPaint;
|
||||
strokeName = parent.strokeName;
|
||||
|
||||
fill = parent.fill;
|
||||
fillColor = parent.fillColor;
|
||||
fillGradient = parent.fillGradient;
|
||||
fillGradientPaint = parent.fillGradientPaint;
|
||||
fillName = parent.fillName;
|
||||
|
||||
//hasTransform = parent.hasTransform;
|
||||
//transformation = parent.transformation;
|
||||
|
||||
opacity = parent.opacity;
|
||||
}
|
||||
|
||||
element = properties;
|
||||
|
||||
name = properties.getStringAttribute("id");
|
||||
if (name != null) {
|
||||
table.put(name, this);
|
||||
//System.out.println("now parsing " + id);
|
||||
}
|
||||
|
||||
String displayStr = properties.getStringAttribute("display", "inline");
|
||||
visible = !displayStr.equals("none");
|
||||
|
||||
String transformStr = properties.getStringAttribute("transform");
|
||||
if (transformStr != null) {
|
||||
float[] t = parseMatrix(transformStr);
|
||||
matrix = new PMatrix3D(t[0], t[1], t[2], t[3], t[4], t[5]);
|
||||
}
|
||||
|
||||
parseColors(properties);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// http://www.w3.org/TR/SVG/coords.html#TransformAttribute
|
||||
static protected float[] parseMatrix(String matrixStr) {
|
||||
/*
|
||||
String prefix = "matrix(";
|
||||
int start = matrixStr.indexOf(prefix);
|
||||
if (start == -1) return null;
|
||||
int stop = matrixStr.indexOf(')');
|
||||
String content = matrixStr.substring(start + matrixStr.length(), stop);
|
||||
return PApplet.parseFloat(PApplet.splitTokens(content.trim()));
|
||||
*/
|
||||
String[] pieces = PApplet.match(matrixStr, "\\s*(\\w+)\\((.*)\\)");
|
||||
if (pieces.length != 2) {
|
||||
System.err.println("Could not parse transform " + matrixStr);
|
||||
return null;
|
||||
}
|
||||
float[] m = PApplet.parseFloat(PApplet.splitTokens(pieces[1]));
|
||||
|
||||
if (pieces[0].equals("matrix")) {
|
||||
return m;
|
||||
|
||||
} else if (pieces[0].equals("translate")) {
|
||||
float tx = m[0];
|
||||
float ty = (m.length == 2) ? m[1] : m[0];
|
||||
return new float[] { 1, 0, tx, 0, 1, ty };
|
||||
|
||||
} else if (pieces[0].equals("scale")) {
|
||||
float sx = m[0];
|
||||
float sy = (m.length == 2) ? m[1] : m[0];
|
||||
return new float[] { sx, 0, 0, 0, sy, 0 };
|
||||
|
||||
} else if (pieces[0].equals("rotate")) {
|
||||
float angle = m[0];
|
||||
|
||||
if (m.length == 1) {
|
||||
float c = PApplet.cos(angle);
|
||||
float s = PApplet.sin(angle);
|
||||
return new float[] { c, -s, 0, s, c, 0 };
|
||||
|
||||
} else if (m.length == 3) {
|
||||
PMatrix2D mat = new PMatrix2D(0, 1, m[1], 1, 0, m[2]);
|
||||
mat.rotate(m[0]);
|
||||
mat.translate(-m[1], -m[2]);
|
||||
return mat.get(null);
|
||||
}
|
||||
|
||||
} else if (pieces[0].equals("skewX")) {
|
||||
return new float[] { 1, PApplet.tan(m[0]), 0, 0, 1, 0 };
|
||||
|
||||
} else if (pieces[0].equals("skewY")) {
|
||||
return new float[] { 1, 0, 0, PApplet.tan(m[0]), 1, 0 };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
protected void parseTransformation2(XMLElement properties) {
|
||||
String transform =
|
||||
if (transform != null) {
|
||||
//this.hasTransform = true;
|
||||
transform = transform.substring(7, transform.length() - 2);
|
||||
String tf[] = PApplet.splitTokens(transform);
|
||||
float[] transformation = PApplet.parseFloat(tf);
|
||||
matrix = new PMatrix3D(transformation[0], transformation[1], transformation[2],
|
||||
transformation[3], transformation[4], transformation[5]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
static protected AffineTransform parseTransform(String what) {
|
||||
if (what != null) {
|
||||
if (what.startsWith("matrix(") && what.endsWith(")")) {
|
||||
// columns go first with AT constructor
|
||||
what = what.substring(7, what.length() - 1);
|
||||
return new AffineTransform(PApplet.parseFloat(PApplet.split(what, ' ')));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
protected void parseColors(XMLElement properties) {
|
||||
if (properties.hasAttribute("opacity")) {
|
||||
opacity = properties.getFloatAttribute("opacity");
|
||||
}
|
||||
int opacityMask = ((int) (opacity * 255)) << 24;
|
||||
|
||||
if (properties.hasAttribute("stroke")) {
|
||||
String strokeText = properties.getStringAttribute("stroke");
|
||||
if (strokeText.equals("none")) {
|
||||
stroke = false;
|
||||
} else if (strokeText.startsWith("#")) {
|
||||
stroke = true;
|
||||
strokeColor = opacityMask |
|
||||
(Integer.parseInt(strokeText.substring(1), 16)) & 0xFFFFFF;
|
||||
} else if (strokeText.startsWith("rgb")) {
|
||||
stroke = true;
|
||||
strokeColor = opacityMask | parseRGB(strokeText);
|
||||
} else if (strokeText.startsWith("url(#")) {
|
||||
strokeName = strokeText.substring(5, strokeText.length() - 1);
|
||||
Object strokeObject = table.get(strokeName);
|
||||
if (strokeObject instanceof Gradient) {
|
||||
strokeGradient = (Gradient) strokeObject;
|
||||
strokeGradientPaint = calcGradientPaint(strokeGradient); //, opacity);
|
||||
} else {
|
||||
System.err.println("url " + strokeName + " refers to unexpected data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.hasAttribute("stroke-width")) {
|
||||
// if NaN (i.e. if it's 'inherit') then default back to the inherit setting
|
||||
strokeWeight = properties.getFloatAttribute("stroke-width", strokeWeight);
|
||||
}
|
||||
|
||||
if (properties.hasAttribute("stroke-linejoin")) {
|
||||
String linejoin = properties.getStringAttribute("stroke-linejoin");
|
||||
if (linejoin.equals("inherit")) {
|
||||
// do nothing, will inherit automatically
|
||||
|
||||
} else if (linejoin.equals("miter")) {
|
||||
strokeJoin = PConstants.MITER;
|
||||
|
||||
} else if (linejoin.equals("round")) {
|
||||
strokeJoin = PConstants.ROUND;
|
||||
|
||||
} else if (linejoin.equals("bevel")) {
|
||||
strokeJoin = PConstants.BEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.hasAttribute("stroke-linecap")) {
|
||||
String linecap = properties.getStringAttribute("stroke-linecap");
|
||||
if (linecap.equals("inherit")) {
|
||||
// do nothing, will inherit automatically
|
||||
|
||||
} else if (linecap.equals("butt")) {
|
||||
strokeCap = PConstants.SQUARE;
|
||||
|
||||
} else if (linecap.equals("round")) {
|
||||
strokeCap = PConstants.ROUND;
|
||||
|
||||
} else if (linecap.equals("square")) {
|
||||
strokeCap = PConstants.PROJECT;
|
||||
}
|
||||
}
|
||||
|
||||
// fill defaults to black (though stroke defaults to "none")
|
||||
// http://www.w3.org/TR/SVG/painting.html#FillProperties
|
||||
if (properties.hasAttribute("fill")) {
|
||||
String fillText = properties.getStringAttribute("fill");
|
||||
if (fillText.equals("none")) {
|
||||
fill = false;
|
||||
} else if (fillText.startsWith("#")) {
|
||||
fill = true;
|
||||
fillColor = opacityMask |
|
||||
(Integer.parseInt(fillText.substring(1), 16)) & 0xFFFFFF;
|
||||
//System.out.println("hex for fill is " + PApplet.hex(fillColor));
|
||||
} else if (fillText.startsWith("rgb")) {
|
||||
fill = true;
|
||||
fillColor = opacityMask | parseRGB(fillText);
|
||||
} else if (fillText.startsWith("url(#")) {
|
||||
fillName = fillText.substring(5, fillText.length() - 1);
|
||||
//PApplet.println("looking for " + fillName);
|
||||
Object fillObject = table.get(fillName);
|
||||
//PApplet.println("found " + fillObject);
|
||||
if (fillObject instanceof Gradient) {
|
||||
fill = true;
|
||||
fillGradient = (Gradient) fillObject;
|
||||
fillGradientPaint = calcGradientPaint(fillGradient); //, opacity);
|
||||
//PApplet.println("got filla " + fillObject);
|
||||
} else {
|
||||
System.err.println("url " + fillName + " refers to unexpected data");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static protected int parseRGB(String what) {
|
||||
int leftParen = what.indexOf('(') + 1;
|
||||
int rightParen = what.indexOf(')');
|
||||
String sub = what.substring(leftParen, rightParen);
|
||||
int[] values = PApplet.parseInt(PApplet.splitTokens(sub, ", "));
|
||||
return (values[0] << 16) | (values[1] << 8) | (values[2]);
|
||||
}
|
||||
|
||||
|
||||
static protected HashMap<String, String> parseStyleAttributes(String style) {
|
||||
HashMap<String, String> table = new HashMap<String, String>();
|
||||
String[] pieces = style.split(";");
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
String[] parts = pieces[i].split(":");
|
||||
table.put(parts[0], parts[1]);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse a size that may have a suffix for its units.
|
||||
* Ignoring cases where this could also be a percentage.
|
||||
* The <A HREF="http://www.w3.org/TR/SVG/coords.html#Units">units</A> spec:
|
||||
* <UL>
|
||||
* <LI>"1pt" equals "1.25px" (and therefore 1.25 user units)
|
||||
* <LI>"1pc" equals "15px" (and therefore 15 user units)
|
||||
* <LI>"1mm" would be "3.543307px" (3.543307 user units)
|
||||
* <LI>"1cm" equals "35.43307px" (and therefore 35.43307 user units)
|
||||
* <LI>"1in" equals "90px" (and therefore 90 user units)
|
||||
* </UL>
|
||||
*/
|
||||
static protected float parseUnitSize(String text) {
|
||||
int len = text.length() - 2;
|
||||
|
||||
if (text.endsWith("pt")) {
|
||||
return PApplet.parseFloat(text.substring(0, len)) * 1.25f;
|
||||
} else if (text.endsWith("pc")) {
|
||||
return PApplet.parseFloat(text.substring(0, len)) * 15;
|
||||
} else if (text.endsWith("mm")) {
|
||||
return PApplet.parseFloat(text.substring(0, len)) * 3.543307f;
|
||||
} else if (text.endsWith("cm")) {
|
||||
return PApplet.parseFloat(text.substring(0, len)) * 35.43307f;
|
||||
} else if (text.endsWith("in")) {
|
||||
return PApplet.parseFloat(text.substring(0, len)) * 90;
|
||||
} else if (text.endsWith("px")) {
|
||||
return PApplet.parseFloat(text.substring(0, len));
|
||||
} else {
|
||||
return PApplet.parseFloat(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
// these are a set of hacks so that gradients can be hacked into Java 2D.
|
||||
|
||||
/*
|
||||
protected Paint getGradient(String name, float cx, float cy, float r) {
|
||||
BaseObject obj = (BaseObject) findChild(name);
|
||||
|
||||
if (obj != null) {
|
||||
if (obj.fillGradient != null) {
|
||||
return obj.calcGradientPaint(obj.fillGradient, cx, cy, r);
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No gradient found for shape " + name);
|
||||
}
|
||||
|
||||
|
||||
protected Paint getGradient(String name, float x1, float y1, float x2, float y2) {
|
||||
BaseObject obj = (BaseObject) findChild(name);
|
||||
|
||||
if (obj != null) {
|
||||
if (obj.fillGradient != null) {
|
||||
return obj.calcGradientPaint(obj.fillGradient, x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No gradient found for shape " + name);
|
||||
}
|
||||
|
||||
|
||||
protected void strokeGradient(PGraphics g, String name, float x, float y, float r) {
|
||||
Paint paint = getGradient(name, x, y, r);
|
||||
|
||||
if (g instanceof PGraphicsJava2D) {
|
||||
PGraphicsJava2D p2d = (PGraphicsJava2D) g;
|
||||
|
||||
p2d.strokeGradient = true;
|
||||
p2d.strokeGradientObject = paint;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void strokeGradient(PGraphics g, String name, float x1, float y1, float x2, float y2) {
|
||||
Paint paint = getGradient(name, x1, y1, x2, y2);
|
||||
|
||||
if (g instanceof PGraphicsJava2D) {
|
||||
PGraphicsJava2D p2d = (PGraphicsJava2D) g;
|
||||
|
||||
p2d.strokeGradient = true;
|
||||
p2d.strokeGradientObject = paint;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void fillGradient(PGraphics g, String name, float x, float y, float r) {
|
||||
Paint paint = getGradient(name, x, y, r);
|
||||
|
||||
if (g instanceof PGraphicsJava2D) {
|
||||
PGraphicsJava2D p2d = (PGraphicsJava2D) g;
|
||||
|
||||
p2d.fillGradient = true;
|
||||
p2d.fillGradientObject = paint;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void fillGradient(PGraphics g, String name, float x1, float y1, float x2, float y2) {
|
||||
Paint paint = getGradient(name, x1, y1, x2, y2);
|
||||
|
||||
if (g instanceof PGraphicsJava2D) {
|
||||
PGraphicsJava2D p2d = (PGraphicsJava2D) g;
|
||||
|
||||
p2d.fillGradient = true;
|
||||
p2d.fillGradientObject = paint;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
protected Paint calcGradientPaint(Gradient gradient) {
|
||||
if (gradient instanceof LinearGradient) {
|
||||
LinearGradient grad = (LinearGradient) gradient;
|
||||
return new LinearGradientPaint(grad.x1, grad.y1, grad.x2, grad.y2,
|
||||
grad.offset, grad.color, grad.count,
|
||||
opacity);
|
||||
|
||||
} else if (gradient instanceof RadialGradient) {
|
||||
RadialGradient grad = (RadialGradient) gradient;
|
||||
return new RadialGradientPaint(grad.cx, grad.cy, grad.r,
|
||||
grad.offset, grad.color, grad.count,
|
||||
opacity);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected Paint calcGradientPaint(Gradient gradient,
|
||||
float x1, float y1, float x2, float y2) {
|
||||
if (gradient instanceof LinearGradient) {
|
||||
LinearGradient grad = (LinearGradient) gradient;
|
||||
return new LinearGradientPaint(x1, y1, x2, y2,
|
||||
grad.offset, grad.color, grad.count,
|
||||
opacity);
|
||||
}
|
||||
throw new RuntimeException("Not a linear gradient.");
|
||||
}
|
||||
|
||||
|
||||
protected Paint calcGradientPaint(Gradient gradient,
|
||||
float cx, float cy, float r) {
|
||||
if (gradient instanceof RadialGradient) {
|
||||
RadialGradient grad = (RadialGradient) gradient;
|
||||
return new RadialGradientPaint(cx, cy, r,
|
||||
grad.offset, grad.color, grad.count,
|
||||
opacity);
|
||||
}
|
||||
throw new RuntimeException("Not a radial gradient.");
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
protected void styles(PGraphics g) {
|
||||
super.styles(g);
|
||||
|
||||
if (g instanceof PGraphicsJava2D) {
|
||||
PGraphicsJava2D p2d = (PGraphicsJava2D) g;
|
||||
|
||||
if (strokeGradient != null) {
|
||||
p2d.strokeGradient = true;
|
||||
p2d.strokeGradientObject = strokeGradientPaint;
|
||||
} else {
|
||||
// need to shut off, in case parent object has a gradient applied
|
||||
//p2d.strokeGradient = false;
|
||||
}
|
||||
if (fillGradient != null) {
|
||||
p2d.fillGradient = true;
|
||||
p2d.fillGradientObject = fillGradientPaint;
|
||||
} else {
|
||||
// need to shut off, in case parent object has a gradient applied
|
||||
//p2d.fillGradient = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overrides SVG-set styles and uses PGraphics styles and colors.
|
||||
* Identical to ignoreStyles(true).
|
||||
*/
|
||||
public void ignoreStyles() {
|
||||
//ignoreStyles(true);
|
||||
styles = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enables or disables style information (fill and stroke) set in the file.
|
||||
* @param state true to use user-specified stroke/fill, false for svg version
|
||||
*/
|
||||
public void ignoreStyles(boolean state) {
|
||||
//ignoreStyles = state;
|
||||
styles = !state;
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
public void drawImpl(PGraphics g) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
/**
|
||||
* Get a particular element based on its SVG ID. When editing SVG by hand,
|
||||
* this is the id="" tag on any SVG element. When editing from Illustrator,
|
||||
* these IDs can be edited by expanding the layers palette. The names used
|
||||
* in the layers palette, both for the layers or the shapes and groups
|
||||
* beneath them can be used here.
|
||||
* <PRE>
|
||||
* // This code grabs "Layer 3" and the shapes beneath it.
|
||||
* SVG layer3 = svg.get("Layer 3");
|
||||
* </PRE>
|
||||
*/
|
||||
public PShape getChild(String name) {
|
||||
PShape found = super.getChild(name);
|
||||
if (found != null) return found;
|
||||
// otherwise try with underscores instead of spaces
|
||||
return super.getChild(name.replace(' ', '_'));
|
||||
}
|
||||
|
||||
|
||||
protected void parseGroup(XMLElement graphics) {
|
||||
XMLElement[] elements = graphics.getChildren();
|
||||
//objects = new BaseObject[elements.length];
|
||||
children = new PShape[elements.length];
|
||||
childCount = 0;
|
||||
|
||||
for (XMLElement elem : elements) {
|
||||
addChild(parseGroupChild(elem));
|
||||
}
|
||||
|
||||
// for (int i = 0; i < elements.length; i++) {
|
||||
// String name = elements[i].getName(); //getElement();
|
||||
// XMLElement elem = elements[i];
|
||||
//
|
||||
// addChild(parseGroupChild(elem, name));
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
protected PShape parseGroupChild(XMLElement elem) {
|
||||
String name = elem.getName();
|
||||
|
||||
if (name.equals("g")) {
|
||||
return new BaseObject(this, elem);
|
||||
|
||||
} else if (name.equals("defs")) {
|
||||
// generally this will contain gradient info, so may
|
||||
// as well just throw it into a group element for parsing
|
||||
return new BaseObject(this, elem);
|
||||
|
||||
} else if (name.equals("line")) {
|
||||
return new Line(this, elem);
|
||||
|
||||
} else if (name.equals("circle")) {
|
||||
return new Circle(this, elem);
|
||||
|
||||
} else if (name.equals("ellipse")) {
|
||||
return new Ellipse(this, elem);
|
||||
|
||||
} else if (name.equals("rect")) {
|
||||
return new Rect(this, elem);
|
||||
|
||||
} else if (name.equals("polygon")) {
|
||||
return new Poly(this, elem, true);
|
||||
|
||||
} else if (name.equals("polyline")) {
|
||||
return new Poly(this, elem, false);
|
||||
|
||||
} else if (name.equals("path")) {
|
||||
return new Path(this, elem);
|
||||
|
||||
} else if (name.equals("radialGradient")) {
|
||||
return new RadialGradient(this, elem);
|
||||
|
||||
} else if (name.equals("linearGradient")) {
|
||||
return new LinearGradient(this, elem);
|
||||
|
||||
} else if (name.equals("text")) {
|
||||
PApplet.println("Text is not currently handled, " +
|
||||
"convert text to outlines instead.");
|
||||
|
||||
} else if (name.equals("filter")) {
|
||||
PApplet.println("Filters are not supported.");
|
||||
|
||||
} else if (name.equals("mask")) {
|
||||
PApplet.println("Masks are not supported.");
|
||||
|
||||
} else {
|
||||
System.err.println("Ignoring <" + name + "> tag.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints out the SVG document useful for parsing
|
||||
*/
|
||||
public void print() {
|
||||
PApplet.println(element.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package processing.candy;
|
||||
|
||||
import processing.core.*;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
public class Circle extends BaseObject {
|
||||
//float x, y, radius;
|
||||
|
||||
public Circle(BaseObject parent, XMLElement properties) {
|
||||
super(parent, properties);
|
||||
this.x = properties.getFloatAttribute("cx");
|
||||
this.y = properties.getFloatAttribute("cy");
|
||||
float radius = properties.getFloatAttribute("r") * 2;
|
||||
width = height = radius;
|
||||
}
|
||||
|
||||
|
||||
public void drawImpl(PGraphics g) {
|
||||
g.ellipseMode(PConstants.CENTER);
|
||||
g.ellipse(x, y, width, height);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package processing.candy;
|
||||
|
||||
import processing.core.*;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
public class Ellipse extends BaseObject {
|
||||
// float x, y, rx, ry;
|
||||
|
||||
public Ellipse(BaseObject parent, XMLElement properties) {
|
||||
super(parent, properties);
|
||||
|
||||
x = properties.getFloatAttribute("cx");
|
||||
y = properties.getFloatAttribute("cy");
|
||||
|
||||
float rx = properties.getFloatAttribute("rx");
|
||||
float ry = properties.getFloatAttribute("ry");
|
||||
|
||||
x -= rx;
|
||||
y -= ry;
|
||||
|
||||
width = rx * 2;
|
||||
height = ry * 2;
|
||||
}
|
||||
|
||||
public void drawImpl(PGraphics g) {
|
||||
//g.ellipseMode(PConstants.CENTER);
|
||||
//g.ellipse(x, y, rx, ry);
|
||||
g.ellipseMode(PConstants.CORNERS);
|
||||
g.ellipse(x, y, width, height);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package processing.candy;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.util.HashMap;
|
||||
|
||||
import processing.core.PApplet;
|
||||
import processing.core.PGraphics;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
abstract public class Gradient extends BaseObject {
|
||||
AffineTransform transform;
|
||||
|
||||
float[] offset;
|
||||
int[] color;
|
||||
int count;
|
||||
|
||||
public Gradient(BaseObject parent, XMLElement properties) {
|
||||
super(parent, properties);
|
||||
|
||||
XMLElement elements[] = properties.getChildren();
|
||||
offset = new float[elements.length];
|
||||
color = new int[elements.length];
|
||||
|
||||
// <stop offset="0" style="stop-color:#967348"/>
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
XMLElement elem = elements[i];
|
||||
String name = elem.getName();
|
||||
if (name.equals("stop")) {
|
||||
offset[count] = elem.getFloatAttribute("offset");
|
||||
String style = elem.getStringAttribute("style");
|
||||
HashMap<String, String> styles = parseStyleAttributes(style);
|
||||
|
||||
String colorStr = styles.get("stop-color");
|
||||
if (colorStr == null) colorStr = "#000000";
|
||||
String opacityStr = styles.get("stop-opacity");
|
||||
if (opacityStr == null) opacityStr = "1";
|
||||
int tupacity = (int) (PApplet.parseFloat(opacityStr) * 255);
|
||||
color[count] = (tupacity << 24) |
|
||||
Integer.parseInt(colorStr.substring(1), 16);
|
||||
count++;
|
||||
//System.out.println("this color is " + PApplet.hex(color[count]));
|
||||
/*
|
||||
int idx = farbe.indexOf("#");
|
||||
if (idx != -1) {
|
||||
color[count] = Integer.parseInt(farbe.substring(idx+1), 16);
|
||||
count++;
|
||||
} else {
|
||||
System.err.println("problem with gradient stop " + properties);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract public void drawImpl(PGraphics g);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package processing.candy;
|
||||
|
||||
import processing.core.PGraphics;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
public class Line extends BaseObject {
|
||||
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
public Line(BaseObject parent, XMLElement properties) {
|
||||
super(parent, properties);
|
||||
|
||||
kind = LINES;
|
||||
|
||||
this.x1 = properties.getFloatAttribute("x1");
|
||||
this.y1 = properties.getFloatAttribute("y1");
|
||||
this.x2 = properties.getFloatAttribute("x2");
|
||||
this.y2 = properties.getFloatAttribute("y2");
|
||||
}
|
||||
|
||||
public void drawImpl(PGraphics g) {
|
||||
g.line(x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package processing.candy;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import processing.core.PGraphics;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
public class LinearGradient extends Gradient {
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
public LinearGradient(BaseObject parent, XMLElement properties) {
|
||||
super(parent, properties);
|
||||
|
||||
this.x1 = properties.getFloatAttribute("x1");
|
||||
this.y1 = properties.getFloatAttribute("y1");
|
||||
this.x2 = properties.getFloatAttribute("x2");
|
||||
this.y2 = properties.getFloatAttribute("y2");
|
||||
|
||||
String transformStr =
|
||||
properties.getStringAttribute("gradientTransform");
|
||||
|
||||
if (transformStr != null) {
|
||||
this.transform = new AffineTransform(parseMatrix(transformStr));
|
||||
|
||||
Point2D t1 = transform.transform(new Point2D.Float(x1, y1), null);
|
||||
Point2D t2 = transform.transform(new Point2D.Float(x2, y2), null);
|
||||
|
||||
this.x1 = (float) t1.getX();
|
||||
this.y1 = (float) t1.getY();
|
||||
this.x2 = (float) t2.getX();
|
||||
this.y2 = (float) t2.getY();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void drawImpl(PGraphics g) { }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,416 @@
|
||||
package processing.candy;
|
||||
|
||||
import processing.core.*;
|
||||
import processing.core.PConstants;
|
||||
import processing.core.PGraphics;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
public class Path extends BaseObject {
|
||||
|
||||
public int count = 0;
|
||||
public float[] x = new float[4];
|
||||
public float[] y = new float[4];
|
||||
|
||||
static public final int MOVETO = 0;
|
||||
static public final int LINETO = 1;
|
||||
static public final int CURVETO = 2;
|
||||
static public final int QCURVETO = 3;
|
||||
public int[] kind = new int[4];
|
||||
|
||||
public boolean closed = false;
|
||||
|
||||
|
||||
public Path(BaseObject parent, XMLElement properties) {
|
||||
super(parent, properties);
|
||||
String pathDataBuffer = "";
|
||||
|
||||
if (!properties.hasAttribute("d"))
|
||||
return;
|
||||
|
||||
pathDataBuffer = properties.getStringAttribute("d");
|
||||
StringBuffer pathChars = new StringBuffer();
|
||||
|
||||
boolean lastSeparate = false;
|
||||
|
||||
for (int i = 0; i < pathDataBuffer.length(); i++) {
|
||||
char c = pathDataBuffer.charAt(i);
|
||||
boolean separate = false;
|
||||
|
||||
if (c == 'M' || c == 'm' ||
|
||||
c == 'L' || c == 'l' ||
|
||||
c == 'H' || c == 'h' ||
|
||||
c == 'V' || c == 'v' ||
|
||||
c == 'C' || c == 'c' || // beziers
|
||||
c == 'S' || c == 's' ||
|
||||
c == 'Q' || c == 'q' || // quadratic beziers
|
||||
c == 'T' || c == 't' ||
|
||||
c == 'Z' || c == 'z' || // closepath
|
||||
c == ',') {
|
||||
separate = true;
|
||||
if (i != 0) {
|
||||
pathChars.append("|");
|
||||
}
|
||||
}
|
||||
if (c == 'Z' || c == 'z') {
|
||||
separate = false;
|
||||
}
|
||||
if (c == '-' && !lastSeparate) {
|
||||
pathChars.append("|");
|
||||
}
|
||||
if (c != ',') {
|
||||
pathChars.append("" + pathDataBuffer.charAt(i));
|
||||
}
|
||||
if (separate && c != ',' && c != '-') {
|
||||
pathChars.append("|");
|
||||
}
|
||||
lastSeparate = separate;
|
||||
}
|
||||
|
||||
pathDataBuffer = pathChars.toString();
|
||||
|
||||
//String pathDataKeys[] = PApplet.split(pathDataBuffer, '|');
|
||||
// use whitespace constant to get rid of extra spaces and CR or LF
|
||||
String pathDataKeys[] =
|
||||
PApplet.splitTokens(pathDataBuffer, "|" + PConstants.WHITESPACE);
|
||||
//for (int j = 0; j < pathDataKeys.length; j++) {
|
||||
// PApplet.println(j + "\t" + pathDataKeys[j]);
|
||||
//}
|
||||
//PApplet.println(pathDataKeys);
|
||||
//PApplet.println();
|
||||
|
||||
//float cp[] = {0, 0};
|
||||
float cx = 0;
|
||||
float cy = 0;
|
||||
|
||||
int i = 0;
|
||||
//for (int i = 0; i < pathDataKeys.length; i++) {
|
||||
while (i < pathDataKeys.length) {
|
||||
char c = pathDataKeys[i].charAt(0);
|
||||
switch (c) {
|
||||
|
||||
//M - move to (absolute)
|
||||
case 'M':
|
||||
/*
|
||||
cp[0] = PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
cp[1] = PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
float s[] = {cp[0], cp[1]};
|
||||
i += 2;
|
||||
points.add(s);
|
||||
*/
|
||||
cx = PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
cy = PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
moveto(cx, cy);
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
|
||||
//m - move to (relative)
|
||||
case 'm':
|
||||
/*
|
||||
cp[0] = cp[0] + PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
cp[1] = cp[1] + PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
float s[] = {cp[0], cp[1]};
|
||||
i += 2;
|
||||
points.add(s);
|
||||
*/
|
||||
cx = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
cy = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
moveto(cx, cy);
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
|
||||
case 'L':
|
||||
cx = PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
cy = PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
lineto(cx, cy);
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
|
||||
case 'l':
|
||||
cx = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
cy = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
lineto(cx, cy);
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
|
||||
// horizontal lineto absolute
|
||||
case 'H':
|
||||
cx = PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
lineto(cx, cy);
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
|
||||
// horizontal lineto relative
|
||||
case 'h':
|
||||
cx = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
lineto(cx, cy);
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
|
||||
case 'V':
|
||||
cy = PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
lineto(cx, cy);
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
|
||||
case 'v':
|
||||
cy = cy + PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
lineto(cx, cy);
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
|
||||
// C - curve to (absolute)
|
||||
case 'C': {
|
||||
float ctrlX1 = PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
float ctrlY1 = PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
float ctrlX2 = PApplet.parseFloat(pathDataKeys[i + 3]);
|
||||
float ctrlY2 = PApplet.parseFloat(pathDataKeys[i + 4]);
|
||||
float endX = PApplet.parseFloat(pathDataKeys[i + 5]);
|
||||
float endY = PApplet.parseFloat(pathDataKeys[i + 6]);
|
||||
curveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
|
||||
cx = endX;
|
||||
cy = endY;
|
||||
i += 7;
|
||||
}
|
||||
break;
|
||||
|
||||
// c - curve to (relative)
|
||||
case 'c': {
|
||||
float ctrlX1 = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
float ctrlY1 = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
float ctrlX2 = cx + PApplet.parseFloat(pathDataKeys[i + 3]);
|
||||
float ctrlY2 = cy + PApplet.parseFloat(pathDataKeys[i + 4]);
|
||||
float endX = cx + PApplet.parseFloat(pathDataKeys[i + 5]);
|
||||
float endY = cy + PApplet.parseFloat(pathDataKeys[i + 6]);
|
||||
curveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
|
||||
cx = endX;
|
||||
cy = endY;
|
||||
i += 7;
|
||||
}
|
||||
break;
|
||||
|
||||
// S - curve to shorthand (absolute)
|
||||
case 'S': {
|
||||
float ppx = x[count-2];
|
||||
float ppy = y[count-2];
|
||||
float px = x[count-1];
|
||||
float py = y[count-1];
|
||||
float ctrlX1 = px + (px - ppx);
|
||||
float ctrlY1 = py + (py - ppy);
|
||||
float ctrlX2 = PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
float ctrlY2 = PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
float endX = PApplet.parseFloat(pathDataKeys[i + 3]);
|
||||
float endY = PApplet.parseFloat(pathDataKeys[i + 4]);
|
||||
curveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
|
||||
cx = endX;
|
||||
cy = endY;
|
||||
i += 5;
|
||||
}
|
||||
break;
|
||||
|
||||
// s - curve to shorthand (relative)
|
||||
case 's': {
|
||||
float ppx = x[count-2];
|
||||
float ppy = y[count-2];
|
||||
float px = x[count-1];
|
||||
float py = y[count-1];
|
||||
float ctrlX1 = px + (px - ppx);
|
||||
float ctrlY1 = py + (py - ppy);
|
||||
float ctrlX2 = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
float ctrlY2 = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
float endX = cx + PApplet.parseFloat(pathDataKeys[i + 3]);
|
||||
float endY = cy + PApplet.parseFloat(pathDataKeys[i + 4]);
|
||||
curveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
|
||||
cx = endX;
|
||||
cy = endY;
|
||||
i += 5;
|
||||
}
|
||||
break;
|
||||
|
||||
// Q - quadratic curve to (absolute)
|
||||
case 'Q': {
|
||||
float ctrlX = PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
float ctrlY = PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
float endX = PApplet.parseFloat(pathDataKeys[i + 3]);
|
||||
float endY = PApplet.parseFloat(pathDataKeys[i + 4]);
|
||||
curveto(ctrlX, ctrlY, endX, endY);
|
||||
cx = endX;
|
||||
cy = endY;
|
||||
i += 5;
|
||||
}
|
||||
break;
|
||||
|
||||
// q - quadratic curve to (relative)
|
||||
case 'q': {
|
||||
float ctrlX = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
float ctrlY = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
float endX = cx + PApplet.parseFloat(pathDataKeys[i + 3]);
|
||||
float endY = cy + PApplet.parseFloat(pathDataKeys[i + 4]);
|
||||
curveto(ctrlX, ctrlY, endX, endY);
|
||||
cx = endX;
|
||||
cy = endY;
|
||||
i += 5;
|
||||
}
|
||||
break;
|
||||
|
||||
// T - quadratic curve to shorthand (absolute)
|
||||
// The control point is assumed to be the reflection of the
|
||||
// control point on the previous command relative to the
|
||||
// current point. (If there is no previous command or if the
|
||||
// previous command was not a Q, q, T or t, assume the control
|
||||
// point is coincident with the current point.)
|
||||
case 'T': {
|
||||
float ppx = x[count-2];
|
||||
float ppy = y[count-2];
|
||||
float px = x[count-1];
|
||||
float py = y[count-1];
|
||||
float ctrlX = px + (px - ppx);
|
||||
float ctrlY = py + (py - ppy);
|
||||
float endX = PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
float endY = PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
curveto(ctrlX, ctrlY, endX, endY);
|
||||
cx = endX;
|
||||
cy = endY;
|
||||
i += 3;
|
||||
}
|
||||
break;
|
||||
|
||||
// t - quadratic curve to shorthand (relative)
|
||||
case 't': {
|
||||
float ppx = x[count-2];
|
||||
float ppy = y[count-2];
|
||||
float px = x[count-1];
|
||||
float py = y[count-1];
|
||||
float ctrlX = px + (px - ppx);
|
||||
float ctrlY = py + (py - ppy);
|
||||
float endX = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
|
||||
float endY = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
|
||||
curveto(ctrlX, ctrlY, endX, endY);
|
||||
cx = endX;
|
||||
cy = endY;
|
||||
i += 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
case 'z':
|
||||
closed = true;
|
||||
i++;
|
||||
break;
|
||||
|
||||
default:
|
||||
String parsed =
|
||||
PApplet.join(PApplet.subset(pathDataKeys, 0, i), ",");
|
||||
String unparsed =
|
||||
PApplet.join(PApplet.subset(pathDataKeys, i), ",");
|
||||
System.err.println("parsed: " + parsed);
|
||||
System.err.println("unparsed: " + unparsed);
|
||||
throw new RuntimeException("shape command not handled: " + pathDataKeys[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void moveto(float px, float py) {
|
||||
if (count == x.length) {
|
||||
x = PApplet.expand(x);
|
||||
y = PApplet.expand(y);
|
||||
kind = PApplet.expand(kind);
|
||||
}
|
||||
kind[count] = MOVETO;
|
||||
x[count] = px;
|
||||
y[count] = py;
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
protected void lineto(float px, float py) {
|
||||
if (count == x.length) {
|
||||
x = PApplet.expand(x);
|
||||
y = PApplet.expand(y);
|
||||
kind = PApplet.expand(kind);
|
||||
}
|
||||
kind[count] = LINETO;
|
||||
x[count] = px;
|
||||
y[count] = py;
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
/** Quadratic curveto command. */
|
||||
protected void curveto(float x1, float y1, float x2, float y2) {
|
||||
if (count + 2 >= x.length) {
|
||||
x = PApplet.expand(x);
|
||||
y = PApplet.expand(y);
|
||||
kind = PApplet.expand(kind);
|
||||
}
|
||||
kind[count] = QCURVETO;
|
||||
x[count] = x1;
|
||||
y[count] = y1;
|
||||
count++;
|
||||
x[count] = x2;
|
||||
y[count] = y2;
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
/** Cubic curveto command. */
|
||||
protected void curveto(float x1, float y1, float x2, float y2, float x3, float y3) {
|
||||
if (count + 2 >= x.length) {
|
||||
x = PApplet.expand(x);
|
||||
y = PApplet.expand(y);
|
||||
kind = PApplet.expand(kind);
|
||||
}
|
||||
kind[count] = CURVETO;
|
||||
x[count] = x1;
|
||||
y[count] = y1;
|
||||
count++;
|
||||
x[count] = x2;
|
||||
y[count] = y2;
|
||||
count++;
|
||||
x[count] = x3;
|
||||
y[count] = y3;
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
public void drawImpl(PGraphics g) {
|
||||
g.beginShape();
|
||||
|
||||
g.vertex(x[0], y[0]);
|
||||
int i = 1; // moveto has the first point
|
||||
while (i < count) {
|
||||
switch (kind[i]) {
|
||||
case MOVETO:
|
||||
g.breakShape();
|
||||
g.vertex(x[i], y[i]);
|
||||
i++;
|
||||
break;
|
||||
|
||||
case LINETO:
|
||||
g.vertex(x[i], y[i]);
|
||||
i++;
|
||||
break;
|
||||
|
||||
case QCURVETO: // doubles the control point
|
||||
g.bezierVertex(x[i], y[i], x[i+1], y[i+1], x[i+1], y[i+1]);
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case CURVETO:
|
||||
g.bezierVertex(x[i], y[i], x[i+1], y[i+1], x[i+2], y[i+2]);
|
||||
i += 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g.endShape(closed ? PConstants.CLOSE : PConstants.OPEN);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package processing.candy;
|
||||
|
||||
import processing.core.*;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
public class Poly extends BaseObject {
|
||||
|
||||
float points[][] = null;
|
||||
/** true if polygon, false if polyline */
|
||||
boolean closed;
|
||||
|
||||
public Poly(BaseObject parent, XMLElement properties, boolean closed) {
|
||||
super(parent, properties);
|
||||
String pointsBuffer[] = null;
|
||||
this.closed = closed;
|
||||
|
||||
if (properties.hasAttribute("points")) {
|
||||
pointsBuffer = PApplet.splitTokens(properties.getStringAttribute("points"));
|
||||
}
|
||||
|
||||
points = new float[pointsBuffer.length][2];
|
||||
for (int i = 0; i < points.length; i++) {
|
||||
String pb[] = PApplet.split(pointsBuffer[i], ',');
|
||||
points[i][0] = Float.valueOf(pb[0]).floatValue();
|
||||
points[i][1] = Float.valueOf(pb[1]).floatValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawImpl(PGraphics g) {
|
||||
if (points != null) {
|
||||
if (points.length > 0) {
|
||||
g.beginShape();
|
||||
for (int i = 0; i < points.length; i++) {
|
||||
g.vertex(points[i][0], points[i][1]);
|
||||
}
|
||||
g.endShape(closed ? PConstants.CLOSE : PConstants.OPEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package processing.candy;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import processing.core.PGraphics;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
public class RadialGradient extends Gradient {
|
||||
float cx, cy, r;
|
||||
|
||||
public RadialGradient(BaseObject parent, XMLElement properties) {
|
||||
super(parent, properties);
|
||||
|
||||
this.cx = properties.getFloatAttribute("cx");
|
||||
this.cy = properties.getFloatAttribute("cy");
|
||||
this.r = properties.getFloatAttribute("r");
|
||||
|
||||
String transformStr =
|
||||
properties.getStringAttribute("gradientTransform");
|
||||
|
||||
if (transformStr != null) {
|
||||
this.transform = new AffineTransform(parseMatrix(transformStr));
|
||||
|
||||
Point2D t1 = transform.transform(new Point2D.Float(cx, cy), null);
|
||||
Point2D t2 = transform.transform(new Point2D.Float(cx + r, cy), null);
|
||||
|
||||
this.cx = (float) t1.getX();
|
||||
this.cy = (float) t1.getY();
|
||||
this.r = (float) (t2.getX() - t1.getX());
|
||||
}
|
||||
}
|
||||
|
||||
public void drawImpl(PGraphics g) { }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package processing.candy;
|
||||
|
||||
import processing.core.*;
|
||||
import processing.xml.XMLElement;
|
||||
|
||||
|
||||
public class Rect extends BaseObject {
|
||||
// float x, y, w, h;
|
||||
|
||||
public Rect(BaseObject parent, XMLElement properties) {
|
||||
super(parent, properties);
|
||||
x = properties.getFloatAttribute("x");
|
||||
y = properties.getFloatAttribute("y");
|
||||
width = properties.getFloatAttribute("width");
|
||||
height = properties.getFloatAttribute("height");
|
||||
}
|
||||
|
||||
public void drawImpl(PGraphics g) {
|
||||
g.rectMode(PConstants.CORNER);
|
||||
g.rect(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+50
-1482
File diff suppressed because it is too large
Load Diff
@@ -187,9 +187,11 @@ public interface PConstants {
|
||||
// the low four bits set the variety,
|
||||
// higher bits set the specific shape type
|
||||
|
||||
static final int POINTS = (1 << 4) | 0;
|
||||
static final int GROUP = (1 << 2);
|
||||
|
||||
static final int POINTS = (1 << 4);
|
||||
|
||||
static final int LINES = (1 << 5) | 0;
|
||||
static final int LINES = (1 << 5);
|
||||
//static final int LINE_STRIP = (1 << 5) | 1;
|
||||
//static final int LINE_LOOP = (1 << 5) | 2;
|
||||
|
||||
|
||||
@@ -108,47 +108,11 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
static public final int EG = 33;
|
||||
static public final int EB = 34;
|
||||
|
||||
//has this vertex been lit yet
|
||||
// has this vertex been lit yet
|
||||
static public final int BEEN_LIT = 35;
|
||||
|
||||
static final int VERTEX_FIELD_COUNT = 36;
|
||||
|
||||
// line & triangle fields (note how these overlap)
|
||||
|
||||
static public final int INDEX = 0; // shape index
|
||||
static public final int VERTEX1 = 1;
|
||||
static public final int VERTEX2 = 2;
|
||||
static public final int VERTEX3 = 3; // (triangles only)
|
||||
static public final int TEXTURE_INDEX = 4; // (triangles only)
|
||||
static public final int STROKE_MODE = 3; // (lines only)
|
||||
static public final int STROKE_WEIGHT = 4; // (lines only)
|
||||
|
||||
static public final int LINE_FIELD_COUNT = 5;
|
||||
static public final int TRIANGLE_FIELD_COUNT = 5;
|
||||
|
||||
static public final int TRI_DIFFUSE_R = 0;
|
||||
static public final int TRI_DIFFUSE_G = 1;
|
||||
static public final int TRI_DIFFUSE_B = 2;
|
||||
static public final int TRI_DIFFUSE_A = 3;
|
||||
static public final int TRI_SPECULAR_R = 4;
|
||||
static public final int TRI_SPECULAR_G = 5;
|
||||
static public final int TRI_SPECULAR_B = 6;
|
||||
static public final int TRI_SPECULAR_A = 7;
|
||||
|
||||
static public final int TRIANGLE_COLOR_COUNT = 8;
|
||||
|
||||
|
||||
// normal modes for lighting, these have the uglier naming
|
||||
// because the constants are never seen by users
|
||||
|
||||
/// normal calculated per triangle
|
||||
static public final int AUTO_NORMAL = 0;
|
||||
/// one normal manually specified per shape
|
||||
static public final int MANUAL_SHAPE_NORMAL = 1;
|
||||
/// normals specified for each shape vertex
|
||||
static public final int MANUAL_VERTEX_NORMAL = 2;
|
||||
|
||||
|
||||
/// width minus one (useful for many calculations)
|
||||
public int width1;
|
||||
|
||||
@@ -982,24 +946,9 @@ public abstract class PGraphics extends PImage implements PConstants {
|
||||
* that's how things are implemented.
|
||||
*/
|
||||
abstract public void beginShape(int kind);
|
||||
/*
|
||||
shape = kind;
|
||||
|
||||
// reset vertex, line and triangle information
|
||||
// every shape is rendered at endShape();
|
||||
vertexCount = 0;
|
||||
|
||||
splineVertexCount = 0;
|
||||
//spline_vertices_flat = true;
|
||||
|
||||
//strokeChanged = false;
|
||||
//fillChanged = false;
|
||||
//normalChanged = false;
|
||||
*/
|
||||
|
||||
|
||||
public void normal(float nx, float ny, float nz) {
|
||||
//depthError("normal");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1792,9 +1792,6 @@ public class PGraphics2D extends PGraphics {
|
||||
*/
|
||||
protected void clear() {
|
||||
Arrays.fill(pixels, backgroundColor);
|
||||
// for (int i = 0; i < pixelCount; i++) {
|
||||
// pixels[i] = backgroundColor;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,41 @@ import java.util.*;
|
||||
*/
|
||||
public class PGraphics3D extends PGraphics {
|
||||
|
||||
// line & triangle fields (note how these overlap)
|
||||
|
||||
static public final int INDEX = 0; // shape index
|
||||
static public final int VERTEX1 = 1;
|
||||
static public final int VERTEX2 = 2;
|
||||
static public final int VERTEX3 = 3; // (triangles only)
|
||||
static public final int TEXTURE_INDEX = 4; // (triangles only)
|
||||
static public final int STROKE_MODE = 3; // (lines only)
|
||||
static public final int STROKE_WEIGHT = 4; // (lines only)
|
||||
|
||||
static public final int LINE_FIELD_COUNT = 5;
|
||||
static public final int TRIANGLE_FIELD_COUNT = 5;
|
||||
|
||||
static public final int TRI_DIFFUSE_R = 0;
|
||||
static public final int TRI_DIFFUSE_G = 1;
|
||||
static public final int TRI_DIFFUSE_B = 2;
|
||||
static public final int TRI_DIFFUSE_A = 3;
|
||||
static public final int TRI_SPECULAR_R = 4;
|
||||
static public final int TRI_SPECULAR_G = 5;
|
||||
static public final int TRI_SPECULAR_B = 6;
|
||||
static public final int TRI_SPECULAR_A = 7;
|
||||
|
||||
static public final int TRIANGLE_COLOR_COUNT = 8;
|
||||
|
||||
|
||||
// normal modes for lighting, these have the uglier naming
|
||||
// because the constants are never seen by users
|
||||
|
||||
/// normal calculated per triangle
|
||||
static public final int AUTO_NORMAL = 0;
|
||||
/// one normal manually specified per shape
|
||||
static public final int MANUAL_SHAPE_NORMAL = 1;
|
||||
/// normals specified for each shape vertex
|
||||
static public final int MANUAL_VERTEX_NORMAL = 2;
|
||||
|
||||
// ........................................................
|
||||
|
||||
// Lighting-related variables
|
||||
@@ -251,7 +286,7 @@ public class PGraphics3D extends PGraphics {
|
||||
cameraFOV = 60 * DEG_TO_RAD; // at least for now
|
||||
cameraX = width / 2.0f;
|
||||
cameraY = height / 2.0f;
|
||||
cameraZ = cameraY / ((float) tan(cameraFOV / 2.0f));
|
||||
cameraZ = cameraY / ((float) Math.tan(cameraFOV / 2.0f));
|
||||
cameraNear = cameraZ / 10.0f;
|
||||
cameraFar = cameraZ * 10.0f;
|
||||
cameraAspect = (float)width / (float)height;
|
||||
@@ -502,12 +537,9 @@ public class PGraphics3D extends PGraphics {
|
||||
textureImage = image;
|
||||
|
||||
if (texture_index == textures.length - 1) {
|
||||
PImage temp[] = new PImage[texture_index<<1];
|
||||
System.arraycopy(textures, 0, temp, 0, texture_index);
|
||||
textures = temp;
|
||||
//message(CHATTER, "allocating more textures " + textures.length);
|
||||
textures = (PImage[]) PApplet.expand(textures);
|
||||
}
|
||||
if (textures[texture_index] != null) {
|
||||
if (textures[texture_index] != null) { // ???
|
||||
texture_index++;
|
||||
}
|
||||
textures[texture_index] = image;
|
||||
@@ -2038,13 +2070,6 @@ public class PGraphics3D extends PGraphics {
|
||||
}
|
||||
|
||||
|
||||
private void crossProduct(float[] u, float[] v, float[] out) {
|
||||
out[0] = u[1]*v[2] - u[2]*v[1];
|
||||
out[1] = u[2]*v[0] - u[0]*v[2];
|
||||
out[2] = u[0]*v[1] - u[1]*v[0];
|
||||
}
|
||||
|
||||
|
||||
private void light_triangle(int triIndex) {
|
||||
int vIndex;
|
||||
|
||||
@@ -2109,7 +2134,7 @@ public class PGraphics3D extends PGraphics {
|
||||
dv2[2] = vertices[vIndex3][VZ] - vertices[vIndex][VZ];
|
||||
|
||||
//float[] norm = new float[3];
|
||||
crossProduct(dv1, dv2, norm);
|
||||
cross(dv1, dv2, norm);
|
||||
float nMag = mag(norm[X], norm[Y], norm[Z]);
|
||||
if (nMag != 0 && nMag != 1) {
|
||||
norm[X] /= nMag; norm[Y] /= nMag; norm[Z] /= nMag;
|
||||
@@ -2177,7 +2202,7 @@ public class PGraphics3D extends PGraphics {
|
||||
dv2[2] = vertices[vIndex3][VZ] - vertices[vIndex][VZ];
|
||||
|
||||
//float[] norm = new float[3];
|
||||
crossProduct(dv1, dv2, norm);
|
||||
cross(dv1, dv2, norm);
|
||||
float nMag = mag(norm[X], norm[Y], norm[Z]);
|
||||
if (nMag != 0 && nMag != 1) {
|
||||
norm[X] /= nMag; norm[Y] /= nMag; norm[Z] /= nMag;
|
||||
@@ -3116,7 +3141,7 @@ public class PGraphics3D extends PGraphics {
|
||||
*/
|
||||
public void perspective(float fov, float aspect, float zNear, float zFar) {
|
||||
//float ymax = zNear * tan(fovy * PI / 360.0f);
|
||||
float ymax = zNear * tan(fov / 2.0f);
|
||||
float ymax = zNear * (float) Math.tan(fov / 2);
|
||||
float ymin = -ymax;
|
||||
|
||||
float xmin = ymin * aspect;
|
||||
@@ -3758,7 +3783,7 @@ public class PGraphics3D extends PGraphics {
|
||||
lightPosition(lightCount, x, y, z);
|
||||
lightDirection(lightCount, nx, ny, nz);
|
||||
lightSpotAngle[lightCount] = angle;
|
||||
lightSpotAngleCos[lightCount] = max(0, cos(angle));
|
||||
lightSpotAngleCos[lightCount] = max(0, (float) Math.cos(angle));
|
||||
lightSpotConcentration[lightCount] = concentration;
|
||||
lightCount++;
|
||||
|
||||
@@ -3848,13 +3873,6 @@ public class PGraphics3D extends PGraphics {
|
||||
*/
|
||||
public void background(PImage image) {
|
||||
super.background(image);
|
||||
|
||||
/*
|
||||
for (int i = 0; i < pixelCount; i++) {
|
||||
zbuffer[i] = Float.MAX_VALUE;
|
||||
//stencil[i] = 0;
|
||||
}
|
||||
*/
|
||||
Arrays.fill(zbuffer, Float.MAX_VALUE);
|
||||
}
|
||||
|
||||
@@ -3864,18 +3882,8 @@ public class PGraphics3D extends PGraphics {
|
||||
* Stencil buffer should also be cleared, but for now is ignored in P3D.
|
||||
*/
|
||||
protected void clear() {
|
||||
//System.out.println("PGraphics3.clear(" +
|
||||
// PApplet.hex(backgroundColor) + ")");
|
||||
/*
|
||||
for (int i = 0; i < pixelCount; i++) {
|
||||
pixels[i] = backgroundColor;
|
||||
zbuffer[i] = Float.MAX_VALUE;
|
||||
//stencil[i] = 0;
|
||||
}
|
||||
*/
|
||||
Arrays.fill(pixels, backgroundColor);
|
||||
Arrays.fill(zbuffer, Float.MAX_VALUE);
|
||||
|
||||
clearRaw();
|
||||
}
|
||||
|
||||
@@ -3928,18 +3936,12 @@ public class PGraphics3D extends PGraphics {
|
||||
// MATH (internal use only)
|
||||
|
||||
|
||||
/*
|
||||
private final float mag(float a, float b) {
|
||||
return (float)Math.sqrt(a*a + b*b);
|
||||
}
|
||||
*/
|
||||
|
||||
private final float mag(float a, float b, float c) {
|
||||
return (float)Math.sqrt(a*a + b*b + c*c);
|
||||
return (float) Math.sqrt(a*a + b*b + c*c);
|
||||
}
|
||||
|
||||
private final float mag(float abc[]) {
|
||||
return (float)Math.sqrt(abc[0]*abc[0] + abc[1]*abc[1] + abc[2]*abc[2]);
|
||||
return (float) Math.sqrt(abc[0]*abc[0] + abc[1]*abc[1] + abc[2]*abc[2]);
|
||||
}
|
||||
|
||||
private final float min(float a, float b) {
|
||||
@@ -3950,41 +3952,23 @@ public class PGraphics3D extends PGraphics {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
/*
|
||||
private final float max(float a, float b, float c) {
|
||||
return Math.max(a, Math.max(b, c));
|
||||
}
|
||||
|
||||
private final float sq(float a) {
|
||||
return a*a;
|
||||
}
|
||||
*/
|
||||
|
||||
private final float pow(float a, float b) {
|
||||
return (float)Math.pow(a, b);
|
||||
return (float) Math.pow(a, b);
|
||||
}
|
||||
|
||||
private final float abs(float a) {
|
||||
return (a < 0) ? -a : a;
|
||||
}
|
||||
|
||||
/*
|
||||
private final float sin(float angle) {
|
||||
return (float)Math.sin(angle);
|
||||
}
|
||||
*/
|
||||
|
||||
private final float cos(float angle) {
|
||||
return (float)Math.cos(angle);
|
||||
}
|
||||
|
||||
private final float tan(float angle) {
|
||||
return (float)Math.tan(angle);
|
||||
}
|
||||
|
||||
private float dot(float ax, float ay, float az,
|
||||
float bx, float by, float bz) {
|
||||
return ax * bx + ay * by + az * bz;
|
||||
}
|
||||
|
||||
private final void cross(float[] a, float[] b, float[] out) {
|
||||
out[0] = a[1]*b[2] - a[2]*b[1];
|
||||
out[1] = a[2]*b[0] - a[0]*b[2];
|
||||
out[2] = a[0]*b[1] - a[1]*b[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2005-08 Ben Fry and Casey Reas
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General
|
||||
Public License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.core;
|
||||
|
||||
|
||||
/**
|
||||
* 4x4 matrix implementation.
|
||||
*/
|
||||
public final class PMatrix2D implements PConstants {
|
||||
|
||||
public float m00, m01, m02;
|
||||
public float m10, m11, m12;
|
||||
|
||||
|
||||
public PMatrix2D() {
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
public PMatrix2D(float m00, float m01, float m02,
|
||||
float m10, float m11, float m12) {
|
||||
set(m00, m01, m02,
|
||||
m10, m11, m12);
|
||||
}
|
||||
|
||||
|
||||
public void reset() {
|
||||
set(1, 0, 0,
|
||||
0, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a copy of this PMatrix.
|
||||
*/
|
||||
public PMatrix2D get() {
|
||||
PMatrix2D outgoing = new PMatrix2D();
|
||||
outgoing.set(this);
|
||||
return outgoing;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copies the matrix contents into a 16 entry float array.
|
||||
* If target is null (or not the correct size), a new array will be created.
|
||||
*/
|
||||
public float[] get(float[] target) {
|
||||
if ((target == null) || (target.length != 6)) {
|
||||
target = new float[6];
|
||||
}
|
||||
target[0] = m00;
|
||||
target[1] = m01;
|
||||
target[2] = m02;
|
||||
|
||||
target[3] = m10;
|
||||
target[4] = m11;
|
||||
target[5] = m12;
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
public void set(PMatrix2D src) {
|
||||
set(src.m00, src.m01, src.m02,
|
||||
src.m10, src.m11, src.m12);
|
||||
}
|
||||
|
||||
|
||||
public void set(float[] source) {
|
||||
m00 = source[0];
|
||||
m01 = source[1];
|
||||
m02 = source[2];
|
||||
|
||||
m10 = source[3];
|
||||
m11 = source[4];
|
||||
m12 = source[5];
|
||||
}
|
||||
|
||||
|
||||
public void set(float m00, float m01, float m02,
|
||||
float m10, float m11, float m12) {
|
||||
this.m00 = m00; this.m01 = m01; this.m02 = m02;
|
||||
this.m10 = m10; this.m11 = m11; this.m12 = m12;
|
||||
}
|
||||
|
||||
|
||||
public void translate(float tx, float ty) {
|
||||
m02 = tx*m00 + ty*m01 + m02;
|
||||
m12 = tx*m10 + ty*m11 + m12;
|
||||
}
|
||||
|
||||
|
||||
public void rotate(float angle) {
|
||||
// TODO fixme
|
||||
}
|
||||
|
||||
|
||||
public void rotateX(float angle) {
|
||||
}
|
||||
|
||||
|
||||
public void rotateY(float angle) {
|
||||
}
|
||||
|
||||
|
||||
public void rotateZ(float angle) {
|
||||
}
|
||||
|
||||
|
||||
public void rotate(float angle, float v0, float v1, float v2) {
|
||||
}
|
||||
|
||||
|
||||
public void scale(float s) {
|
||||
scale(s, s);
|
||||
}
|
||||
|
||||
|
||||
public void scale(float sx, float sy) {
|
||||
m00 *= sx; m01 *= sy;
|
||||
m10 *= sx; m11 *= sy;
|
||||
}
|
||||
|
||||
|
||||
public void scale(float x, float y, float z) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Multiply this matrix by another.
|
||||
*/
|
||||
public void apply(PMatrix2D source) {
|
||||
apply(source.m00, source.m01, source.m02,
|
||||
source.m10, source.m11, source.m12);
|
||||
}
|
||||
|
||||
|
||||
public void apply(float n00, float n01, float n02,
|
||||
float n10, float n11, float n12) {
|
||||
float t0 = m00;
|
||||
float t1 = m01;
|
||||
m00 = n00 * t0 + n10 * t1;
|
||||
m01 = n01 * t0 + n11 * t1;
|
||||
m02 += n02 * t0 + n12 * t1;
|
||||
|
||||
t0 = m10;
|
||||
t1 = m11;
|
||||
m10 = n00 * t0 + n10 * t1;
|
||||
m11 = n01 * t0 + n11 * t1;
|
||||
m12 += n02 * t0 + n12 * t1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply another matrix to the left of this one.
|
||||
*/
|
||||
public void preApply(PMatrix2D left) {
|
||||
preApply(left.m00, left.m01, left.m02,
|
||||
left.m10, left.m11, left.m12);
|
||||
}
|
||||
|
||||
|
||||
public void preApply(float n00, float n01, float n02,
|
||||
float n10, float n11, float n12) {
|
||||
float t0 = m02;
|
||||
float t1 = m12;
|
||||
n02 += t0 * n00 + t1 * n01;
|
||||
n12 += t0 * n10 + t1 * n11;
|
||||
|
||||
m02 = n02;
|
||||
m12 = n12;
|
||||
|
||||
t0 = m00;
|
||||
t1 = m10;
|
||||
m00 = t0 * n00 + t1 * n01;
|
||||
m10 = t0 * n10 + t1 * n11;
|
||||
|
||||
t0 = m01;
|
||||
t1 = m11;
|
||||
m01 = t0 * n00 + t1 * n01;
|
||||
m11 = t0 * n10 + t1 * n11; }
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Multiply a four element vector against this matrix.
|
||||
* If out is null or not length four, a new float array will be returned.
|
||||
* The values for vec and out can be the same (though that's less efficient).
|
||||
*/
|
||||
public float[] multiply(float vec[], float out[]) {
|
||||
if (out == null || out.length != 2) {
|
||||
out = new float[2];
|
||||
}
|
||||
|
||||
if (vec == out) {
|
||||
float tx = m00*vec[0] + m01*vec[1] + m02;
|
||||
float ty = m10*vec[0] + m11*vec[1] + m12;
|
||||
|
||||
out[0] = tx;
|
||||
out[1] = ty;
|
||||
|
||||
} else {
|
||||
out[0] = m00*vec[0] + m01*vec[1] + m02;
|
||||
out[1] = m10*vec[0] + m11*vec[1] + m12;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transpose this matrix.
|
||||
*/
|
||||
public void transpose() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invert this matrix. Implementation stolen from OpenJDK.
|
||||
* @return true if successful
|
||||
*/
|
||||
public boolean invert() {
|
||||
float determinant = determinant();
|
||||
if (Math.abs(determinant) <= Float.MIN_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float t00 = m00;
|
||||
float t01 = m01;
|
||||
float t02 = m02;
|
||||
float t10 = m10;
|
||||
float t11 = m11;
|
||||
float t12 = m12;
|
||||
|
||||
m00 = t11 / determinant;
|
||||
m10 = -t10 / determinant;
|
||||
m01 = -t01 / determinant;
|
||||
m11 = t00 / determinant;
|
||||
m02 = (t01 * t12 - t11 * t02) / determinant;
|
||||
m12 = (t10 * t02 - t00 * t12) / determinant;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the determinant of the matrix
|
||||
*/
|
||||
public float determinant() {
|
||||
return m00 * m11 - m01 * m10;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public void print() {
|
||||
int big = (int) abs(max(PApplet.max(abs(m00), abs(m01), abs(m02)),
|
||||
PApplet.max(abs(m10), abs(m11), abs(m12))));
|
||||
|
||||
int digits = 1;
|
||||
if (Float.isNaN(big) || Float.isInfinite(big)) { // avoid infinite loop
|
||||
digits = 5;
|
||||
} else {
|
||||
while ((big /= 10) != 0) digits++; // cheap log()
|
||||
}
|
||||
|
||||
System.out.println(PApplet.nfs(m00, digits, 4) + " " +
|
||||
PApplet.nfs(m01, digits, 4) + " " +
|
||||
PApplet.nfs(m02, digits, 4));
|
||||
|
||||
System.out.println(PApplet.nfs(m10, digits, 4) + " " +
|
||||
PApplet.nfs(m11, digits, 4) + " " +
|
||||
PApplet.nfs(m12, digits, 4));
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
private final float max(float a, float b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
private final float abs(float a) {
|
||||
return (a < 0) ? -a : a;
|
||||
}
|
||||
|
||||
private final float sin(float angle) {
|
||||
return (float)Math.sin(angle);
|
||||
}
|
||||
|
||||
private final float cos(float angle) {
|
||||
return (float)Math.cos(angle);
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public final class PMatrix3D implements PConstants {
|
||||
|
||||
|
||||
public PMatrix3D(float m00, float m01, float m02,
|
||||
float m10, float m11, float m12) {
|
||||
float m10, float m11, float m12) {
|
||||
set(m00, m01, m02, 0,
|
||||
m10, m11, m12, 0,
|
||||
0, 0, 1, 0,
|
||||
@@ -67,9 +67,9 @@ public final class PMatrix3D implements PConstants {
|
||||
|
||||
|
||||
public PMatrix3D(float m00, float m01, float m02, float m03,
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23,
|
||||
float m30, float m31, float m32, float m33) {
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23,
|
||||
float m30, float m31, float m32, float m33) {
|
||||
set(m00, m01, m02, m03,
|
||||
m10, m11, m12, m13,
|
||||
m20, m21, m22, m23,
|
||||
@@ -640,33 +640,32 @@ public final class PMatrix3D implements PConstants {
|
||||
max(max(abs(m30), abs(m31)),
|
||||
max(abs(m32), abs(m33))))));
|
||||
|
||||
// avoid infinite loop
|
||||
if (Float.isNaN(big) || Float.isInfinite(big)) {
|
||||
big = 1000000; // set to something arbitrary
|
||||
int digits = 1;
|
||||
if (Float.isNaN(big) || Float.isInfinite(big)) { // avoid infinite loop
|
||||
digits = 5;
|
||||
} else {
|
||||
while ((big /= 10) != 0) digits++; // cheap log()
|
||||
}
|
||||
|
||||
int d = 1;
|
||||
while ((big /= 10) != 0) d++; // cheap log()
|
||||
System.out.println(PApplet.nfs(m00, digits, 4) + " " +
|
||||
PApplet.nfs(m01, digits, 4) + " " +
|
||||
PApplet.nfs(m02, digits, 4) + " " +
|
||||
PApplet.nfs(m03, digits, 4));
|
||||
|
||||
System.out.println(PApplet.nfs(m00, d, 4) + " " +
|
||||
PApplet.nfs(m01, d, 4) + " " +
|
||||
PApplet.nfs(m02, d, 4) + " " +
|
||||
PApplet.nfs(m03, d, 4));
|
||||
System.out.println(PApplet.nfs(m10, digits, 4) + " " +
|
||||
PApplet.nfs(m11, digits, 4) + " " +
|
||||
PApplet.nfs(m12, digits, 4) + " " +
|
||||
PApplet.nfs(m13, digits, 4));
|
||||
|
||||
System.out.println(PApplet.nfs(m10, d, 4) + " " +
|
||||
PApplet.nfs(m11, d, 4) + " " +
|
||||
PApplet.nfs(m12, d, 4) + " " +
|
||||
PApplet.nfs(m13, d, 4));
|
||||
System.out.println(PApplet.nfs(m20, digits, 4) + " " +
|
||||
PApplet.nfs(m21, digits, 4) + " " +
|
||||
PApplet.nfs(m22, digits, 4) + " " +
|
||||
PApplet.nfs(m23, digits, 4));
|
||||
|
||||
System.out.println(PApplet.nfs(m20, d, 4) + " " +
|
||||
PApplet.nfs(m21, d, 4) + " " +
|
||||
PApplet.nfs(m22, d, 4) + " " +
|
||||
PApplet.nfs(m23, d, 4));
|
||||
|
||||
System.out.println(PApplet.nfs(m30, d, 4) + " " +
|
||||
PApplet.nfs(m31, d, 4) + " " +
|
||||
PApplet.nfs(m32, d, 4) + " " +
|
||||
PApplet.nfs(m33, d, 4));
|
||||
System.out.println(PApplet.nfs(m30, digits, 4) + " " +
|
||||
PApplet.nfs(m31, digits, 4) + " " +
|
||||
PApplet.nfs(m32, digits, 4) + " " +
|
||||
PApplet.nfs(m33, digits, 4));
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
package processing.core;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
// take a look at the obj loader to see how this fits with things
|
||||
|
||||
// PShape.line() PShape.ellipse()?
|
||||
@@ -30,57 +32,67 @@ package processing.core;
|
||||
// line()
|
||||
// endShape(s)
|
||||
|
||||
public class PShape {
|
||||
abstract public class PShape implements PConstants {
|
||||
|
||||
public String name;
|
||||
protected String name;
|
||||
|
||||
protected int kind;
|
||||
protected int drawMode;
|
||||
protected PMatrix3D matrix;
|
||||
|
||||
// setAxis -> .x and .y to move x and y coords of origin
|
||||
protected float x;
|
||||
protected float y;
|
||||
protected float width;
|
||||
protected float height;
|
||||
|
||||
// set to false if the object is hidden in the layers palette
|
||||
public boolean display;
|
||||
protected boolean visible;
|
||||
|
||||
public boolean stroke;
|
||||
public int strokeColor;
|
||||
public float strokeWeight; // default is 1
|
||||
public int strokeCap;
|
||||
public int strokeJoin;
|
||||
protected boolean stroke;
|
||||
protected int strokeColor;
|
||||
protected float strokeWeight; // default is 1
|
||||
protected int strokeCap;
|
||||
protected int strokeJoin;
|
||||
|
||||
public boolean fill;
|
||||
public int fillColor;
|
||||
protected boolean fill;
|
||||
protected int fillColor;
|
||||
|
||||
protected boolean styles;
|
||||
|
||||
//public boolean hasTransform;
|
||||
public float[] transformation;
|
||||
|
||||
//
|
||||
|
||||
int kind;
|
||||
PMatrix3D matrix;
|
||||
//protected float[] transformation;
|
||||
|
||||
int[] opcode;
|
||||
int opcodeCount;
|
||||
// need to reorder vertex fields to make a VERTEX_SHORT_COUNT
|
||||
// that puts all the non-rendering fields into later indices
|
||||
int dataCount;
|
||||
float[][] data; // second param is the VERTEX_FIELD_COUNT
|
||||
// should this be called vertices (consistent with PGraphics internals)
|
||||
// or does that hurt flexibility?
|
||||
|
||||
int childCount;
|
||||
PShape[] children;
|
||||
protected PShape parent;
|
||||
protected int childCount;
|
||||
protected PShape[] children;
|
||||
protected HashMap<String,PShape> table;
|
||||
|
||||
// POINTS, LINES, xLINE_STRIP, xLINE_LOOP
|
||||
// TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN
|
||||
// QUADS, QUAD_STRIP
|
||||
// xPOLYGON
|
||||
static final int PATH = 1; // POLYGON, LINE_LOOP, LINE_STRIP
|
||||
static final int GROUP = 2;
|
||||
// static final int PATH = 1; // POLYGON, LINE_LOOP, LINE_STRIP
|
||||
// static final int GROUP = 2;
|
||||
|
||||
// how to handle rectmode/ellipsemode?
|
||||
// are they bitshifted into the constant?
|
||||
// CORNER, CORNERS, CENTER, (CENTER_RADIUS?)
|
||||
static final int RECT = 3; // could just be QUAD, but would be x1/y1/x2/y2
|
||||
static final int ELLIPSE = 4;
|
||||
|
||||
static final int VERTEX = 7;
|
||||
static final int CURVE = 5;
|
||||
static final int BEZIER = 6;
|
||||
// static final int RECT = 3; // could just be QUAD, but would be x1/y1/x2/y2
|
||||
// static final int ELLIPSE = 4;
|
||||
//
|
||||
// static final int VERTEX = 7;
|
||||
// static final int CURVE = 5;
|
||||
// static final int BEZIER = 6;
|
||||
|
||||
|
||||
// fill and stroke functions will need a pointer to the parent
|
||||
@@ -92,37 +104,93 @@ public class PShape {
|
||||
// material parameters will be thrown out,
|
||||
// except those currently supported (kinds of lights)
|
||||
|
||||
// setAxis -> .x and .y to move x and y coords of origin
|
||||
public float x;
|
||||
public float y;
|
||||
|
||||
// pivot point for transformations
|
||||
public float px;
|
||||
public float py;
|
||||
// public float px;
|
||||
// public float py;
|
||||
|
||||
|
||||
public PShape() {
|
||||
this.kind = GROUP;
|
||||
}
|
||||
|
||||
|
||||
public PShape(int kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
|
||||
public PShape(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
|
||||
public void setVisible(boolean visible) {
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
protected void checkBounds() {
|
||||
if (width == 0 || height == 0) {
|
||||
// calculate bounds here (also take kids into account)
|
||||
width = 1;
|
||||
height = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public float getWidth() {
|
||||
checkBounds();
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
public float getHeight() {
|
||||
checkBounds();
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called by the following (the shape() command adds the g)
|
||||
* PShape s = loadShapes("blah.svg");
|
||||
* shape(s);
|
||||
* Set the orientation for drawn objects, similar to PImage.imageMode().
|
||||
* @param which Either CORNER, CORNERS, or CENTER.
|
||||
*/
|
||||
public void draw(PGraphics g) {
|
||||
boolean flat = g instanceof PGraphics3D;
|
||||
public void drawMode(int which) {
|
||||
drawMode = which;
|
||||
}
|
||||
|
||||
|
||||
boolean strokeSaved;
|
||||
int strokeColorSaved;
|
||||
float strokeWeightSaved;
|
||||
int strokeCapSaved;
|
||||
int strokeJoinSaved;
|
||||
|
||||
boolean fillSaved;
|
||||
int fillColorSaved;
|
||||
|
||||
int ellipseModeSaved;
|
||||
|
||||
|
||||
protected void pre(PGraphics g) {
|
||||
if (matrix != null) {
|
||||
boolean flat = g instanceof PGraphics3D;
|
||||
|
||||
g.pushMatrix();
|
||||
if (flat) {
|
||||
g.applyMatrix(matrix.m00, matrix.m01, matrix.m02,
|
||||
@@ -135,50 +203,217 @@ public class PShape {
|
||||
}
|
||||
}
|
||||
|
||||
// if g subclasses PGraphics2, ignore all lighting stuff and z coords
|
||||
// otherwise if PGraphics3, need to call diffuse() etc
|
||||
strokeSaved = g.stroke;
|
||||
strokeColorSaved = g.strokeColor;
|
||||
strokeWeightSaved = g.strokeWeight;
|
||||
strokeCapSaved = g.strokeCap;
|
||||
strokeJoinSaved = g.strokeJoin;
|
||||
|
||||
// unfortunately, also a problem with no way to encode stroke/fill
|
||||
// being enabled/disabled.. this quickly gets into just having opcodes
|
||||
// for the entire api, to deal with things like textures and images
|
||||
fillSaved = g.fill;
|
||||
fillColorSaved = g.fillColor;
|
||||
|
||||
switch (kind) {
|
||||
case PATH:
|
||||
for (int i = 0; i < opcodeCount; i++) {
|
||||
switch (opcode[i]) {
|
||||
case VERTEX:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
ellipseModeSaved = g.ellipseMode;
|
||||
|
||||
case GROUP:
|
||||
break;
|
||||
|
||||
case RECT:
|
||||
break;
|
||||
if (styles) {
|
||||
styles(g);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void styles(PGraphics g) {
|
||||
// should not be necessary because using only the int version of color
|
||||
//parent.colorMode(PConstants.RGB, 255);
|
||||
|
||||
if (stroke) {
|
||||
g.stroke(strokeColor);
|
||||
g.strokeWeight(strokeWeight);
|
||||
g.strokeCap(strokeCap);
|
||||
g.strokeJoin(strokeJoin);
|
||||
} else {
|
||||
g.noStroke();
|
||||
}
|
||||
|
||||
if (fill) {
|
||||
//System.out.println("filling " + PApplet.hex(fillColor));
|
||||
g.fill(fillColor);
|
||||
} else {
|
||||
g.noFill();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void post(PGraphics g) {
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
children[i].draw(g);
|
||||
}
|
||||
|
||||
// TODO this is not sufficient, since not saving fillR et al.
|
||||
g.stroke = strokeSaved;
|
||||
g.strokeColor = strokeColorSaved;
|
||||
g.strokeWeight = strokeWeightSaved;
|
||||
g.strokeCap = strokeCapSaved;
|
||||
g.strokeJoin = strokeJoinSaved;
|
||||
|
||||
g.fill = fillSaved;
|
||||
g.fillColor = fillColorSaved;
|
||||
|
||||
g.ellipseMode = ellipseModeSaved;
|
||||
|
||||
if (matrix != null) {
|
||||
g.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by the following (the shape() command adds the g)
|
||||
* PShape s = loadShapes("blah.svg");
|
||||
* shape(s);
|
||||
*/
|
||||
public void draw(PGraphics g) {
|
||||
if (!visible) return;
|
||||
|
||||
if (drawMode == PConstants.CENTER) {
|
||||
g.pushMatrix();
|
||||
g.translate(-width/2, -height/2);
|
||||
}
|
||||
|
||||
pre(g);
|
||||
drawImpl(g);
|
||||
post(g);
|
||||
|
||||
if (drawMode == PConstants.CENTER) {
|
||||
g.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to draw at a particular location.
|
||||
*/
|
||||
public void draw(PGraphics g, float x, float y) {
|
||||
if (!visible) return;
|
||||
|
||||
g.pushMatrix();
|
||||
|
||||
if (drawMode == PConstants.CENTER) {
|
||||
g.translate(x - width/2, y - height/2);
|
||||
|
||||
} else if ((drawMode == PConstants.CORNER) ||
|
||||
(drawMode == PConstants.CORNERS)) {
|
||||
g.translate(x, y);
|
||||
}
|
||||
pre(g);
|
||||
drawImpl(g);
|
||||
post(g);
|
||||
|
||||
g.popMatrix();
|
||||
}
|
||||
|
||||
|
||||
public void draw(PGraphics g, float x, float y, float c, float d) {
|
||||
if (!visible) return;
|
||||
|
||||
g.pushMatrix();
|
||||
|
||||
if (drawMode == PConstants.CENTER) {
|
||||
// x and y are center, c and d refer to a diameter
|
||||
g.translate(x - c/2f, y - d/2f);
|
||||
g.scale(c / width, d / height);
|
||||
|
||||
} else if (drawMode == PConstants.CORNER) {
|
||||
g.translate(x, y);
|
||||
g.scale(c / width, d / height);
|
||||
|
||||
} else if (drawMode == PConstants.CORNERS) {
|
||||
// c and d are x2/y2, make them into width/height
|
||||
c -= x;
|
||||
d -= y;
|
||||
// then same as above
|
||||
g.translate(x, y);
|
||||
g.scale(c / width, d / height);
|
||||
}
|
||||
pre(g);
|
||||
drawImpl(g);
|
||||
post(g);
|
||||
|
||||
g.popMatrix();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws the SVG document.
|
||||
*/
|
||||
abstract public void drawImpl(PGraphics g);
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
public int getChildCount() {
|
||||
return childCount;
|
||||
}
|
||||
|
||||
|
||||
public PShape getChild(int index) {
|
||||
return children[index];
|
||||
}
|
||||
|
||||
|
||||
public PShape getChild(String name) {
|
||||
if (table != null) {
|
||||
for (String n : table.keySet()) {
|
||||
if (n.equals(name)) {
|
||||
return table.get(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
PShape found = children[i].getChild(name);
|
||||
if (found != null) return found;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as getChild(name), except that it first walks all the way up the
|
||||
* hierarchy to the farthest parent, so that children can be found anywhere.
|
||||
*/
|
||||
public PShape findChild(String name) {
|
||||
if (parent == null) {
|
||||
return getChild(name);
|
||||
|
||||
} else {
|
||||
return parent.findChild(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// can't be 'add' because that suggests additive geometry
|
||||
public void addChild(PShape who) {
|
||||
if (children == null) {
|
||||
children = new PShape[2];
|
||||
}
|
||||
if (childCount == children.length) {
|
||||
children = (PShape[]) PApplet.expand(children);
|
||||
}
|
||||
children[childCount++] = who;
|
||||
who.parent = this;
|
||||
|
||||
if (table == null) {
|
||||
table = new HashMap<String,PShape>();
|
||||
}
|
||||
table.put(who.getName(), who);
|
||||
}
|
||||
|
||||
|
||||
public PShape createGroup() {
|
||||
PShape group = new PShape();
|
||||
group.kind = GROUP;
|
||||
addChild(group);
|
||||
return group;
|
||||
}
|
||||
// public PShape createGroup() {
|
||||
// PShape group = new PShape();
|
||||
// group.kind = GROUP;
|
||||
// addChild(group);
|
||||
// return group;
|
||||
// }
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
@@ -200,9 +435,6 @@ public class PShape {
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
||||
|
||||
public void rotateX(float angle) {
|
||||
rotate(angle, 1, 0, 0);
|
||||
}
|
||||
@@ -232,10 +464,12 @@ public class PShape {
|
||||
scale(s, s, s);
|
||||
}
|
||||
|
||||
|
||||
public void scale(float sx, float sy) {
|
||||
scale(sx, sy, 1);
|
||||
}
|
||||
|
||||
|
||||
public void scale(float x, float y, float z) {
|
||||
checkMatrix();
|
||||
matrix.scale(x, y, z);
|
||||
@@ -245,6 +479,10 @@ public class PShape {
|
||||
//
|
||||
|
||||
|
||||
public void resetMatrix() {
|
||||
}
|
||||
|
||||
|
||||
public void applyMatrix(float n00, float n01, float n02,
|
||||
float n10, float n11, float n12) {
|
||||
checkMatrix();
|
||||
@@ -254,6 +492,7 @@ public class PShape {
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
public void applyMatrix(float n00, float n01, float n02, float n03,
|
||||
float n10, float n11, float n12, float n13,
|
||||
float n20, float n21, float n22, float n23,
|
||||
@@ -287,17 +526,17 @@ public class PShape {
|
||||
* This will also need to flip the y axis (scale(1, -1)) in cases
|
||||
* like Adobe Illustrator where the coordinates start at the bottom.
|
||||
*/
|
||||
public void center() {
|
||||
}
|
||||
// public void center() {
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Set the pivot point for all transformations.
|
||||
*/
|
||||
public void pivot(float x, float y) {
|
||||
px = x;
|
||||
py = y;
|
||||
}
|
||||
// public void pivot(float x, float y) {
|
||||
// px = x;
|
||||
// py = y;
|
||||
// }
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
@@ -16,14 +16,14 @@ X build it and then exit
|
||||
X notations have been added to the bug report that cover the plw changes
|
||||
X Toolmenu won't show until I compile Mangler
|
||||
X http://dev.processing.org/bugs/show_bug.cgi?id=892
|
||||
|
||||
_ transport error 208
|
||||
_ http://dev.processing.org/bugs/show_bug.cgi?id=895
|
||||
_ possible http://www.jetbrains.net/jira/browse/IDEADEV-4268
|
||||
|
||||
X update quaqua to 4.4.7 on macosx (http://www.randelshofer.ch/quaqua/)
|
||||
X now supports 10.5 an 64 bit jnilib
|
||||
|
||||
_ video capture problems with opengl
|
||||
_ http://dev.processing.org/bugs/show_bug.cgi?id=882
|
||||
_ serial.available() broken with video
|
||||
_ http://dev.processing.org/bugs/show_bug.cgi?id=829
|
||||
|
||||
_ add local variables to PdeRecognizer
|
||||
_ remove static methods in PdePreprocessor, instead pull things from recog
|
||||
|
||||
@@ -59,6 +59,8 @@ _ but: open() is platform specific anyway, ppl can use exec()
|
||||
|
||||
[ needs verification ]
|
||||
|
||||
_ transport error 202
|
||||
_ http://dev.processing.org/bugs/show_bug.cgi?id=895
|
||||
_ check to see whether this bug is fixed once 0140 is released
|
||||
_ properly handle non-ascii chars in p5 folder name
|
||||
_ http://dev.processing.org/bugs/show_bug.cgi?id=49
|
||||
|
||||
Reference in New Issue
Block a user