Skip to content

Commit

Permalink
Added support for drawing debug information
Browse files Browse the repository at this point in the history
Press on the example app to toggle the debug information.
  • Loading branch information
bjorn committed Nov 26, 2010
1 parent 43ed7f6 commit 6fd94cf
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 4 deletions.
6 changes: 4 additions & 2 deletions box2d.pro
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ INSTALLS += target qmldir

SOURCES += box2dplugin.cpp \
box2dworld.cpp \
box2dbody.cpp
box2dbody.cpp \
box2ddebugdraw.cpp

HEADERS += \
box2dplugin.h \
box2dworld.h \
box2dbody.h
box2dbody.h \
box2ddebugdraw.h
2 changes: 0 additions & 2 deletions box2dbody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
#include <Box2D.h>
#include <cmath>

static const float scaleRatio = 32.0f; // 32 pixels in one meter

Box2DBody::Box2DBody(QDeclarativeItem *parent) :
QDeclarativeItem(parent),
mBody(0),
Expand Down
185 changes: 185 additions & 0 deletions box2ddebugdraw.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/*
* Box2D QML plugin
* Copyright (C) 2010 Nokia Corporation
*
* This file is part of the Box2D QML plugin.
*
* 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, see <http://www.gnu.org/licenses/>.
*/

#include "box2ddebugdraw.h"

#include "box2dworld.h"

#include <Box2D.h>

#include <QPainter>

class DebugDraw : public b2DebugDraw
{
public:
DebugDraw(QPainter *painter, Box2DWorld *world);

void draw();

void DrawPolygon(const b2Vec2 *vertices, int32 vertexCount,
const b2Color &color);
void DrawSolidPolygon(const b2Vec2 *vertices, int32 vertexCount,
const b2Color &color);
void DrawCircle(const b2Vec2 &center, float32 radius,
const b2Color &color);
void DrawSolidCircle(const b2Vec2 &center, float32 radius,
const b2Vec2 &axis, const b2Color &color);
void DrawSegment(const b2Vec2 &p1, const b2Vec2 &p2,
const b2Color &color);
void DrawTransform(const b2Transform &xf);

private:
QPainter *mP;
b2World *mWorld;
};

DebugDraw::DebugDraw(QPainter *painter, Box2DWorld *world)
: mP(painter)
, mWorld(world->world())
{
SetFlags(e_shapeBit |
e_jointBit |
e_aabbBit |
e_pairBit |
e_centerOfMassBit);
}

void DebugDraw::draw()
{
mWorld->SetDebugDraw(this);
mWorld->DrawDebugData();
mWorld->SetDebugDraw(0);
}

static QPointF toQPointF(const b2Vec2 &vec)
{
return QPointF(vec.x * scaleRatio,
-vec.y * scaleRatio);
}

static QColor toQColor(const b2Color &color)
{
return QColor(color.r * 255,
color.g * 255,
color.b * 255);
}

static QPolygonF toQPolygonF(const b2Vec2 *vertices, int32 vertexCount)
{
QPolygonF polygon;
polygon.reserve(vertexCount);

for (int i = 0; i < vertexCount; ++i)
polygon.append(toQPointF(vertices[i]));

return polygon;
}

void DebugDraw::DrawPolygon(const b2Vec2 *vertices, int32 vertexCount,
const b2Color &color)
{
mP->setPen(toQColor(color));
mP->setBrush(Qt::NoBrush);
mP->drawPolygon(toQPolygonF(vertices, vertexCount));
}

void DebugDraw::DrawSolidPolygon(const b2Vec2 *vertices, int32 vertexCount,
const b2Color &color)
{
mP->setPen(Qt::NoPen);
mP->setBrush(toQColor(color));
mP->drawPolygon(toQPolygonF(vertices, vertexCount));
}

void DebugDraw::DrawCircle(const b2Vec2 &center, float32 radius,
const b2Color &color)
{
mP->setPen(toQColor(color));
mP->setBrush(Qt::NoBrush);
mP->drawEllipse(toQPointF(center),
radius * scaleRatio,
radius * scaleRatio);
}

void DebugDraw::DrawSolidCircle(const b2Vec2 &center, float32 radius,
const b2Vec2 &axis, const b2Color &color)
{
Q_UNUSED(axis)

mP->setPen(Qt::NoPen);
mP->setBrush(toQColor(color));
mP->drawEllipse(toQPointF(center),
radius * scaleRatio,
radius * scaleRatio);
}

void DebugDraw::DrawSegment(const b2Vec2 &p1, const b2Vec2 &p2,
const b2Color &color)
{
mP->setPen(toQColor(color));
mP->drawLine(toQPointF(p1), toQPointF(p2));
}

void DebugDraw::DrawTransform(const b2Transform &xf)
{
Q_UNUSED(xf)
// TODO: Not sure how to draw transforms
}


Box2DDebugDraw::Box2DDebugDraw(QDeclarativeItem *parent) :
QDeclarativeItem(parent),
mWorld(0)
{
setFlag(QGraphicsItem::ItemHasNoContents, false);
}

void Box2DDebugDraw::setWorld(Box2DWorld *world)
{
if (mWorld == world)
return;

if (mWorld)
mWorld->disconnect(this);

mWorld = world;

if (mWorld)
connect(mWorld, SIGNAL(stepped()), SLOT(onWorldStepped()));
}

void Box2DDebugDraw::paint(QPainter *p, const QStyleOptionGraphicsItem *,
QWidget *)
{
if (!mWorld)
return;

// Darken the view to make the debug draw stand out more
p->fillRect(0, 0, width(), height(), QColor(0, 0, 0, 128));

DebugDraw debugDraw(p, mWorld);
debugDraw.draw();
}

void Box2DDebugDraw::onWorldStepped()
{
if (isVisible() && opacity() > 0)
update();
}
49 changes: 49 additions & 0 deletions box2ddebugdraw.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Box2D QML plugin
* Copyright (C) 2010 Nokia Corporation
*
* This file is part of the Box2D QML plugin.
*
* 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, see <http://www.gnu.org/licenses/>.
*/

#ifndef BOX2DDEBUGDRAW_H
#define BOX2DDEBUGDRAW_H

#include <QDeclarativeItem>

class Box2DWorld;

class Box2DDebugDraw : public QDeclarativeItem
{
Q_OBJECT

Q_PROPERTY(Box2DWorld *world READ world WRITE setWorld)

public:
explicit Box2DDebugDraw(QDeclarativeItem *parent = 0);

Box2DWorld *world() const { return mWorld; }
void setWorld(Box2DWorld *world);

void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);

private slots:
void onWorldStepped();

private:
Box2DWorld *mWorld;
};

#endif // BOX2DDEBUGDRAW_H
2 changes: 2 additions & 0 deletions box2dplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "box2dworld.h"
#include "box2dbody.h"
#include "box2ddebugdraw.h"

Box2DPlugin::Box2DPlugin(QObject *parent) :
QDeclarativeExtensionPlugin(parent)
Expand All @@ -32,6 +33,7 @@ void Box2DPlugin::registerTypes(const char *uri)
{
qmlRegisterType<Box2DWorld>(uri, 2, 0, "World");
qmlRegisterType<Box2DBody>(uri, 2, 0, "Body");
qmlRegisterType<Box2DDebugDraw>(uri, 2, 0, "DebugDraw");
}

Q_EXPORT_PLUGIN2(Box2DPlugin, Box2DPlugin)
1 change: 1 addition & 0 deletions box2dworld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ void Box2DWorld::timerEvent(QTimerEvent *event)
mWorld->ClearForces();
foreach (Box2DBody *body, mBodies)
body->synchronize();
emit stepped();
}
QDeclarativeItem::timerEvent(event);
}
Expand Down
7 changes: 7 additions & 0 deletions box2dworld.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ class Box2DBody;

class b2World;

// TODO: Maybe turn this into a property of the world, though it can't be
// changed dynamically.
static const float scaleRatio = 32.0f; // 32 pixels in one meter

/**
* Wrapper class around a Box2D world.
*/
Expand Down Expand Up @@ -86,8 +90,11 @@ class Box2DWorld : public QDeclarativeItem
void registerBody(Box2DBody *body);
void unregisterBody(Box2DBody *body);

b2World *world() const { return mWorld; }

signals:
void gravityChanged();
void stepped();

protected:
void timerEvent(QTimerEvent *);
Expand Down
13 changes: 13 additions & 0 deletions examples/boxes/boxes.qml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ Image {
anchors { left: parent.right; bottom: ground.top; top: ceiling.bottom }
bodyType: Body.Static
}

DebugDraw {
id: debugDraw
world: world
anchors.fill: world
opacity: 0.75
visible: false
}
MouseArea {
id: debugMouseArea
anchors.fill: world
onPressed: debugDraw.visible = !debugDraw.visible
}
}

Accelerometer {
Expand Down

0 comments on commit 6fd94cf

Please sign in to comment.