package playn.core;
import org.jbox2d.callbacks.DebugDraw;
import org.jbox2d.common.Color3f;
import org.jbox2d.common.OBBViewportTransform;
import org.jbox2d.common.Transform;
import org.jbox2d.common.Vec2;
import static playn.core.PlayN.graphics;
import static playn.core.PlayN.log;
public class DebugDrawBox2D extends DebugDraw {
private static String CANVASERROR =
"Must set canvas (DebugDrawBox2D.setCanvas()) in DebugDrawBox2D before drawing.";
private CanvasLayer canvas;
private float strokeWidth;
private int strokeAlpha;
private int fillAlpha;
private float cameraX, cameraY, cameraScale = 1;
private static float cacheFillR, cacheFillG, cacheFillB; // cached fill color
private static float cacheStrokeR, cacheStrokeG, cacheStrokeB; // cached
// stroke color
private final Vec2 tempVec1 = new Vec2();
private final Vec2 tempVec2 = new Vec2();
private final Vec2 tempVec3 = new Vec2();
public DebugDrawBox2D() {
super(new OBBViewportTransform());
viewportTransform.setYFlip(true);
strokeWidth = 1.0f;
strokeAlpha = 255;
fillAlpha = 150;
}
@Override
public void drawCircle(Vec2 center, float radius, Color3f color) {
if (canvas == null) {
log().error(CANVASERROR);
return;
}
setFillColor(color);
setStrokeColor(color);
// calculate the effective radius
tempVec1.set(center.x + radius, center.y + radius);
getWorldToScreenToOut(tempVec1, tempVec1);
getWorldToScreenToOut(center, tempVec2);
canvas.canvas().fillCircle(tempVec2.x, tempVec2.y, tempVec1.x - tempVec2.x);
canvas.canvas().strokeCircle(tempVec2.x, tempVec2.y, tempVec1.x - tempVec2.x);
}
@Override
public void drawPoint(Vec2 argPoint, float argRadiusOnScreen, Color3f color) {
if (canvas == null) {
log().error(CANVASERROR);
return;
}
setFillColor(color);
setStrokeColor(color);
getWorldToScreenToOut(argPoint, tempVec1);
canvas.canvas().fillCircle(tempVec1.x, tempVec1.y, argRadiusOnScreen);
}
@Override
public void drawSegment(Vec2 p1, Vec2 p2, Color3f color) {
if (canvas == null) {
log().error(CANVASERROR);
return;
}
setStrokeColor(color);
setFillColor(color);
getWorldToScreenToOut(p1, tempVec1);
getWorldToScreenToOut(p2, tempVec2);
canvas.canvas().drawLine(tempVec1.x, tempVec1.y, tempVec2.x, tempVec2.y);
}
@Override
public void drawSolidCircle(Vec2 center, float radius, Vec2 axis, Color3f color) {
if (canvas == null) {
log().error(CANVASERROR);
return;
}
setFillColor(color);
setStrokeColor(color);
// calculate the effective radius
tempVec1.set(center.x + radius, center.y + radius);
getWorldToScreenToOut(tempVec1, tempVec1);
getWorldToScreenToOut(center, tempVec2);
getWorldToScreenToOut(axis, tempVec3);
canvas.canvas().fillCircle(tempVec2.x, tempVec2.y, tempVec1.x - tempVec2.x);
canvas.canvas().strokeCircle(tempVec2.x, tempVec2.y, tempVec1.x - tempVec2.x);
}
@Override
public void drawSolidPolygon(Vec2[] vertices, int vertexCount, Color3f color) {
if (canvas == null) {
log().error(CANVASERROR);
return;
}
setFillColor(color);
setStrokeColor(color);
Path path = graphics().createPath();
for (int i = 0; i < vertexCount; i++) {
getWorldToScreenToOut(vertices[i], tempVec1);
if (i == 0) {
path.moveTo(tempVec1.x, tempVec1.y);
} else {
path.lineTo(tempVec1.x, tempVec1.y);
}
}
path.close();
canvas.canvas().fillPath(path);
canvas.canvas().strokePath(path);
}
@Override
public void drawString(float x, float y, String s, Color3f color) {
if (canvas == null) {
log().error(CANVASERROR);
return;
}
log().info("drawString not yet implemented in DebugDrawBox2D: " + s);
}
@Override
public void drawTransform(Transform xf) {
if (canvas == null) {
log().error(CANVASERROR);
return;
}
getWorldToScreenToOut(xf.position, tempVec1);
tempVec2.setZero();
float k_axisScale = 0.4f;
canvas.canvas().setStrokeColor(Color.rgb(1, 0, 0)); // note: violates
// strokeAlpha
tempVec2.x = xf.position.x + k_axisScale * xf.R.m11;
tempVec2.y = xf.position.y + k_axisScale * xf.R.m12;
getWorldToScreenToOut(tempVec2, tempVec2);
canvas.canvas().drawLine(tempVec1.x, tempVec1.y, tempVec2.x, tempVec2.y);
canvas.canvas().setStrokeColor(Color.rgb(0, 1, 0)); // note: violates
// strokeAlpha
tempVec2.x = xf.position.x + k_axisScale * xf.R.m21;
tempVec2.y = xf.position.y + k_axisScale * xf.R.m22;
getWorldToScreenToOut(tempVec2, tempVec2);
canvas.canvas().drawLine(tempVec1.x, tempVec1.y, tempVec2.x, tempVec2.y);
canvas.canvas().setStrokeColor(Color.argb(strokeAlpha, 1, 0, 0)); // restores
// strokeAlpha
}
public CanvasLayer getCanvas() {
return canvas;
}
public int getFillAlpha() {
return fillAlpha;
}
public int getStrokeAlpha() {
return strokeAlpha;
}
public float getStrokeWidth() {
return strokeWidth;
}
@Override
public void setCamera(float x, float y, float scale) {
cameraX = x;
cameraY = y;
cameraScale = scale;
updateCamera();
}
public void setCameraScale(float scale) {
cameraScale = scale;
updateCamera();
}
public void setCameraX(float x) {
cameraX = x;
updateCamera();
}
public void setCameraY(float y) {
cameraY = y;
updateCamera();
}
public void setCanvas(CanvasLayer canvas) {
this.canvas = canvas;
canvas.canvas().setStrokeWidth(strokeWidth);
}
public void setFillAlpha(int fillAlpha) {
this.fillAlpha = fillAlpha;
}
public void setFlipY(boolean flip) {
viewportTransform.setYFlip(flip);
}
public void setStrokeAlpha(int strokeAlpha) {
this.strokeAlpha = strokeAlpha;
}
public void setStrokeWidth(float strokeWidth) {
this.strokeWidth = strokeWidth;
if (canvas != null) {
canvas.canvas().setStrokeWidth(strokeWidth);
}
}
/**
* Sets the fill color from a Color3f
*
* @param color color where (r,g,b) = (x,y,z)
*/
private void setFillColor(Color3f color) {
if (cacheFillR == color.x && cacheFillG == color.y && cacheFillB == color.z) {
// no need to re-set the fill color, just use the cached values
} else {
cacheFillR = color.x;
cacheFillG = color.y;
cacheFillB = color.z;
canvas.canvas()
.setFillColor(
Color.argb(fillAlpha, (int) (255 * color.x), (int) (255 * color.y),
(int) (255 * color.z)));
}
}
/**
* Sets the stroke color from a Color3f
*
* @param color color where (r,g,b) = (x,y,z)
*/
private void setStrokeColor(Color3f color) {
if (cacheStrokeR == color.x && cacheStrokeG == color.y && cacheStrokeB == color.z) {
// no need to re-set the stroke color, just use the cached values
} else {
cacheStrokeR = color.x;
cacheStrokeG = color.y;
cacheStrokeB = color.z;
canvas.canvas().setStrokeColor(
Color.argb(strokeAlpha, (int) (255 * color.x), (int) (255 * color.y),
(int) (255 * color.z)));
}
}
private void updateCamera() {
super.setCamera(cameraX, cameraY, cameraScale);
}
@Override
public void clear() {
getCanvas().canvas().clear();
}
}