123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*
- * 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 "box2dbody.h"
- #include "box2dfixture.h"
- #include "box2dworld.h"
- #include <cmath>
- Box2DBody::Box2DBody(QDeclarativeItem *parent) :
- QDeclarativeItem(parent),
- mBody(0),
- mWorld(0),
- mLinearDamping(0.0f),
- mAngularDamping(0.0f),
- mBodyType(Dynamic),
- mBullet(false),
- mSleepingAllowed(true),
- mFixedRotation(false),
- mActive(true),
- mSynchronizing(false),
- mInitializePending(false)
- {
- setTransformOrigin(TopLeft);
- connect(this, SIGNAL(rotationChanged()), SLOT(onRotationChanged()));
- }
- Box2DBody::~Box2DBody()
- {
- }
- void Box2DBody::setLinearDamping(qreal linearDamping)
- {
- if (mLinearDamping == linearDamping)
- return;
- mLinearDamping = linearDamping;
- if (mBody)
- mBody->SetLinearDamping(linearDamping);
- emit linearDampingChanged();
- }
- void Box2DBody::setAngularDamping(qreal angularDamping)
- {
- if (mAngularDamping == angularDamping)
- return;
- mAngularDamping = angularDamping;
- if (mBody)
- mBody->SetAngularDamping(angularDamping);
- emit angularDampingChanged();
- }
- void Box2DBody::setBodyType(BodyType bodyType)
- {
- if (mBodyType == bodyType)
- return;
- mBodyType = bodyType;
- if (mBody)
- mBody->SetType(static_cast<b2BodyType>(bodyType));
- emit bodyTypeChanged();
- }
- void Box2DBody::setBullet(bool bullet)
- {
- if (mBullet == bullet)
- return;
- mBullet = bullet;
- if (mBody)
- mBody->SetBullet(bullet);
- emit bulletChanged();
- }
- void Box2DBody::setSleepingAllowed(bool allowed)
- {
- if (mSleepingAllowed == allowed)
- return;
- mSleepingAllowed = allowed;
- if (mBody)
- mBody->SetSleepingAllowed(allowed);
- emit sleepingAllowedChanged();
- }
- void Box2DBody::setFixedRotation(bool fixedRotation)
- {
- if (mFixedRotation == fixedRotation)
- return;
- mFixedRotation = fixedRotation;
- if (mBody)
- mBody->SetFixedRotation(fixedRotation);
- emit fixedRotationChanged();
- }
- void Box2DBody::setActive(bool active)
- {
- if (mActive == active)
- return;
- mActive = active;
- if (mBody)
- mBody->SetActive(active);
- }
- void Box2DBody::setLinearVelocity(const QPointF &linearVelocity)
- {
- if (mLinearVelocity == linearVelocity)
- return;
- mLinearVelocity = linearVelocity;
- if (mBody)
- mBody->SetLinearVelocity(b2Vec2(mLinearVelocity.x() / scaleRatio,
- -mLinearVelocity.y() / scaleRatio));
- emit linearVelocityChanged();
- }
- void Box2DBody::setAngularVelocity(float angularVelocity)
- {
- if (mAngularVelocity == angularVelocity)
- return;
- mAngularVelocity = angularVelocity;
- if (mBody)
- mBody->SetAngularVelocity(angularVelocity);
- emit angularVelocityChanged();
- }
- QDeclarativeListProperty<Box2DFixture> Box2DBody::fixtures()
- {
- return QDeclarativeListProperty<Box2DFixture>(this, 0,
- &Box2DBody::append_fixture);
- }
- void Box2DBody::append_fixture(QDeclarativeListProperty<Box2DFixture> *list,
- Box2DFixture *fixture)
- {
- Box2DBody *body = static_cast<Box2DBody*>(list->object);
- fixture->setParentItem(body);
- body->mFixtures.append(fixture);
- }
- void Box2DBody::initialize(b2World *world)
- {
- mWorld = world;
- if (!isComponentComplete()) {
- // When components are created dynamically, they get their parent
- // assigned before they have been completely initialized. In that case
- // we need to delay initialization.
- mInitializePending = true;
- return;
- }
- b2BodyDef bodyDef;
- bodyDef.type = static_cast<b2BodyType>(mBodyType);
- bodyDef.position.Set(x() / scaleRatio, -y() / scaleRatio);
- bodyDef.angle = -(rotation() * (2 * M_PI)) / 360.0;
- bodyDef.linearDamping = mLinearDamping;
- bodyDef.angularDamping = mAngularDamping;
- bodyDef.bullet = mBullet;
- bodyDef.allowSleep = mSleepingAllowed;
- bodyDef.fixedRotation = mFixedRotation;
- mBody = world->CreateBody(&bodyDef);
- mInitializePending = false;
- foreach (Box2DFixture *fixture, mFixtures)
- fixture->createFixture(mBody);
- emit bodyCreated();
- }
- /**
- * Synchronizes the state of this body with the internal Box2D state.
- */
- void Box2DBody::synchronize()
- {
- Q_ASSERT(mBody);
- mSynchronizing = true;
- const b2Vec2 position = mBody->GetPosition();
- const float32 angle = mBody->GetAngle();
- const qreal newX = position.x * scaleRatio;
- const qreal newY = -position.y * scaleRatio;
- const qreal newRotation = -(angle * 360.0) / (2 * M_PI);
- // Do fuzzy comparisions to avoid small inaccuracies causing repaints
- if (!qFuzzyCompare(x(), newX) || !qFuzzyCompare(y(), newY))
- setPos(newX, newY);
- if (!qFuzzyCompare(rotation(), newRotation))
- setRotation(newRotation);
- b2Vec2 linearVelocity = mBody->GetLinearVelocity();
- setLinearVelocity(QPointF(linearVelocity.x * scaleRatio,
- -linearVelocity.y * scaleRatio));
- float angularVelocity = mBody->GetAngularVelocity();
- setAngularVelocity(angularVelocity);
- mSynchronizing = false;
- }
- void Box2DBody::resetVelocities()
- {
- mBody->SetLinearVelocity(b2Vec2(0, 0));
- mBody->SetAngularVelocity(0);
- }
- void Box2DBody::cleanup(b2World *world)
- {
- world->DestroyBody(mBody);
- mBody = 0;
- mWorld = 0;
- }
- void Box2DBody::componentComplete()
- {
- QDeclarativeItem::componentComplete();
- if (mInitializePending)
- initialize(mWorld);
- }
- b2Body* Box2DBody::body() const
- {
- return mBody;
- }
- void Box2DBody::geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry)
- {
- if (!mSynchronizing && mBody) {
- if (newGeometry.topLeft() != oldGeometry.topLeft()) {
- const QPointF pos = newGeometry.topLeft();
- mBody->SetTransform(b2Vec2(pos.x() / scaleRatio,
- -pos.y() / scaleRatio),
- mBody->GetAngle());
- }
- }
- QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
- }
- void Box2DBody::onRotationChanged()
- {
- if (!mSynchronizing && mBody) {
- mBody->SetTransform(mBody->GetPosition(),
- (rotation() * 2 * M_PI) / -360.0);
- }
- }
- void Box2DBody::applyLinearImpulse(const QPointF &impulse,
- const QPointF &point)
- {
- if (mBody) {
- mBody->ApplyLinearImpulse(b2Vec2(impulse.x() / scaleRatio,
- -impulse.y() / scaleRatio),
- b2Vec2(point.x() / scaleRatio,
- -point.y() / scaleRatio));
- }
- }
- void Box2DBody::applyTorque(qreal torque)
- {
- if (mBody)
- mBody->ApplyTorque(torque);
- }
- QPointF Box2DBody::getWorldCenter() const
- {
- QPointF worldCenter;
- if (mBody) {
- const b2Vec2 ¢er = mBody->GetWorldCenter();
- worldCenter.setX(center.x * scaleRatio);
- worldCenter.setY(-center.y * scaleRatio);
- }
- return worldCenter;
- }
|