All Downloads are FREE. Search and download functionalities are using the official Maven repository.

playn.core.DebugDrawBox2D Maven / Gradle / Ivy

There is a newer version: 2.0.8
Show newest version
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;

public class DebugDrawBox2D extends DebugDraw {

  private final Platform plat;
  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 final Canvas canvas;

  public DebugDrawBox2D(Platform plat, float width, float height) {
    super(new OBBViewportTransform());
    this.plat = plat;
    viewportTransform.setYFlip(true);
    strokeWidth = 1.0f;
    strokeAlpha = 255;
    fillAlpha = 150;
    canvas = plat.graphics().createCanvas(width, height);
    canvas.setStrokeWidth(strokeWidth);
    setStrokeColorFromCache();
    setFillColorFromCache();
  }

  @Override
  public void drawCircle(Vec2 center, float radius, Color3f color) {
    setFillColor(color);
    setStrokeColor(color);
    // calculate the effective radius
    tempVec1.set(center.x + radius, center.y + radius);
    getWorldToScreenToOut(tempVec1, tempVec1);
    getWorldToScreenToOut(center, tempVec2);
    canvas.fillCircle(tempVec2.x, tempVec2.y, tempVec1.x - tempVec2.x);
    canvas.strokeCircle(tempVec2.x, tempVec2.y, tempVec1.x - tempVec2.x);
  }

  @Override
  public void drawPoint(Vec2 argPoint, float argRadiusOnScreen, Color3f color) {
    setFillColor(color);
    setStrokeColor(color);
    getWorldToScreenToOut(argPoint, tempVec1);
    canvas.fillCircle(tempVec1.x, tempVec1.y, argRadiusOnScreen);
  }

  @Override
  public void drawSegment(Vec2 p1, Vec2 p2, Color3f color) {
    setStrokeColor(color);
    setFillColor(color);
    getWorldToScreenToOut(p1, tempVec1);
    getWorldToScreenToOut(p2, tempVec2);
    canvas.drawLine(tempVec1.x, tempVec1.y, tempVec2.x, tempVec2.y);
  }

  @Override
  public void drawSolidCircle(Vec2 center, float radius, Vec2 axis, Color3f color) {
    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.fillCircle(tempVec2.x, tempVec2.y, tempVec1.x - tempVec2.x);
    canvas.strokeCircle(tempVec2.x, tempVec2.y, tempVec1.x - tempVec2.x);
  }

  @Override
  public void drawSolidPolygon(Vec2[] vertices, int vertexCount, Color3f color) {
    setFillColor(color);
    setStrokeColor(color);
    Path path = canvas.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.fillPath(path);
    canvas.strokePath(path);
  }

  @Override
  public void drawString(float x, float y, String s, Color3f color) {
    plat.log().info("drawString not yet implemented in DebugDrawBox2D: " + s);
  }

  @Override
  public void drawTransform(Transform xf) {
    getWorldToScreenToOut(xf.p, tempVec1);
    tempVec2.setZero();
    // float k_axisScale = 0.4f;

    canvas.setStrokeColor(Color.rgb(1, 0, 0)); // note: violates strokeAlpha
    tempVec2.x = xf.p.x; // + k_axisScale * xf.R.m11; // Transform no longer scales
    tempVec2.y = xf.p.y; // + k_axisScale * xf.R.m12;
    getWorldToScreenToOut(tempVec2, tempVec2);
    canvas.drawLine(tempVec1.x, tempVec1.y, tempVec2.x, tempVec2.y);

    canvas.setStrokeColor(Color.rgb(0, 1, 0)); // note: violates strokeAlpha
    tempVec2.x = xf.p.x; // + k_axisScale * xf.R.m21; // Transform no longer scales
    tempVec2.y = xf.p.y; // + k_axisScale * xf.R.m22;
    getWorldToScreenToOut(tempVec2, tempVec2);
    canvas.drawLine(tempVec1.x, tempVec1.y, tempVec2.x, tempVec2.y);

    canvas.setStrokeColor(Color.argb(strokeAlpha, 1, 0, 0)); // restores strokeAlpha
  }

  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 setFillAlpha(int fillAlpha) {
    this.fillAlpha = fillAlpha;
    setFillColorFromCache();
  }

  public void setFlipY(boolean flip) {
    viewportTransform.setYFlip(flip);
  }

  public void setStrokeAlpha(int strokeAlpha) {
    this.strokeAlpha = strokeAlpha;
    setStrokeColorFromCache();
  }

  public void setStrokeWidth(float strokeWidth) {
    this.strokeWidth = strokeWidth;
    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;
      setFillColorFromCache();
    }
  }

  /**
   * Sets the fill color from the cached rgb values.
   */
  private void setFillColorFromCache() {
    canvas.setFillColor(
      Color.argb(fillAlpha, (int) (255 * cacheFillR), (int) (255 * cacheFillG),
                 (int) (255 * cacheFillB)));
  }

  /**
   * 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;
      setStrokeColorFromCache();
    }
  }

  /**
   * Sets the fill color from the cached rgb values.
   */
  private void setStrokeColorFromCache() {
    canvas.setStrokeColor(
        Color.argb(strokeAlpha, (int) (255 * cacheStrokeR), (int) (255 * cacheStrokeG),
            (int) (255 * cacheStrokeB)));
  }

  private void updateCamera() {
    super.setCamera(cameraX, cameraY, cameraScale);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy