issue #2771: delay load

This commit is contained in:
boyu0 2013-11-04 19:26:34 +08:00
parent 00acd67ff3
commit 46710c5f06
4 changed files with 238 additions and 89 deletions

View File

@ -183,6 +183,12 @@ bool PhysicsWorld::init(Scene& scene)
{
do
{
_delayAddBodies = Array::create();
_delayRemoveBodies = Array::create();
CC_BREAK_IF(_delayAddBodies == nullptr || _delayRemoveBodies == nullptr);
_delayAddBodies->retain();
_delayRemoveBodies->retain();
_info = new PhysicsWorldInfo();
CC_BREAK_IF(_info == nullptr);
_bodies = Array::create();
@ -206,20 +212,99 @@ bool PhysicsWorld::init(Scene& scene)
return false;
}
void PhysicsWorld::delayTestAddBody(PhysicsBody* body)
{
if (_delayRemoveBodies->getIndexOfObject(body) != UINT_MAX)
{
_delayRemoveBodies->removeObject(body);
return;
}
if (_info->space->locked_private)
{
if (_delayAddBodies->getIndexOfObject(body) == UINT_MAX)
{
_delayAddBodies->addObject(body);
_delayDirty = true;
}
}else
{
realAddBody(body);
}
}
void PhysicsWorld::delayTestRemoveBody(PhysicsBody* body)
{
if (_delayAddBodies->getIndexOfObject(body) != UINT_MAX)
{
_delayAddBodies->removeObject(body);
return;
}
if (_info->space->locked_private)
{
if (_delayRemoveBodies->getIndexOfObject(body) == UINT_MAX)
{
_delayRemoveBodies->addObject(body);
_delayDirty = true;
}
}else
{
realRemoveBody(body);
}
}
void PhysicsWorld::delayTestAddJoint(PhysicsJoint* joint)
{
auto it = std::find(_delayRemoveJoints.begin(), _delayRemoveJoints.end(), joint);
if (it != _delayRemoveJoints.end())
{
_delayRemoveJoints.erase(it);
return;
}
if (_info->space->locked_private)
{
if (std::find(_delayAddJoints.begin(), _delayAddJoints.end(), joint) == _delayAddJoints.end())
{
_delayAddJoints.push_back(joint);
_delayDirty = true;
}
}else
{
realAddJoint(joint);
}
}
void PhysicsWorld::delayTestRemoveJoint(PhysicsJoint* joint)
{
auto it = std::find(_delayAddJoints.begin(), _delayAddJoints.end(), joint);
if (it != _delayAddJoints.end())
{
_delayAddJoints.erase(it);
return;
}
if (_info->space->locked_private)
{
if (std::find(_delayRemoveJoints.begin(), _delayRemoveJoints.end(), joint) == _delayRemoveJoints.end())
{
_delayRemoveJoints.push_back(joint);
_delayDirty = true;
}
}else
{
realRemoveJoint(joint);
}
}
void PhysicsWorld::addJoint(PhysicsJoint* joint)
{
auto it = std::find(_joints.begin(), _joints.end(), joint);
if (it == _joints.end())
{
for (auto subjoint : joint->_info->joints)
{
if (!cpSpaceContainsConstraint(_info->space, subjoint))
{
cpSpaceAddConstraint(_info->space, subjoint);
}
}
delayTestAddJoint(joint);
_joints.push_back(joint);
}
@ -231,14 +316,7 @@ void PhysicsWorld::removeJoint(PhysicsJoint* joint)
if (it != _joints.end())
{
for (auto subjoint : joint->_info->joints)
{
if (cpSpaceContainsConstraint(_info->space, subjoint))
{
cpSpaceRemoveConstraint(_info->space, subjoint);
}
}
delayTestRemoveJoint(*it);
_joints.remove(joint);
}
}
@ -247,13 +325,7 @@ void PhysicsWorld::removeAllJoints()
{
for (auto joint : _joints)
{
for (auto subjoint : joint->_info->joints)
{
if (!cpSpaceContainsConstraint(_info->space, subjoint))
{
cpSpaceRemoveConstraint(_info->space, subjoint);
}
}
delayTestRemoveJoint(joint);
}
_joints.clear();
@ -263,28 +335,22 @@ PhysicsShape* PhysicsWorld::addShape(PhysicsShape* shape)
{
for (auto cps : shape->_info->shapes)
{
if (cpSpaceContainsShape(_info->space, cps))
{
continue;
}
if (cpBodyIsStatic(shape->getBody()->_info->body))
{
cpSpaceAddStaticShape(_info->space, cps);
}
else
{
cpSpaceAddShape(_info->space, cps);
}
_info->addShape(cps);
}
return shape;
}
PhysicsBody* PhysicsWorld::addBody(PhysicsBody* body)
void PhysicsWorld::realAddJoint(PhysicsJoint *joint)
{
for (auto subjoint : joint->_info->joints)
{
_info->addJoint(subjoint);
}
}
void PhysicsWorld::realAddBody(PhysicsBody* body)
{
CCASSERT(body != nullptr, "the body can not be nullptr");
if (body->getWorld() != this && body->getWorld() != nullptr)
{
body->removeFromWorld();
@ -303,7 +369,7 @@ PhysicsBody* PhysicsWorld::addBody(PhysicsBody* body)
// add body to space
if (body->isDynamic())
{
cpSpaceAddBody(_info->space, body->_info->body);
_info->addBody(body->_info->body);
}
// add shapes to space
@ -312,13 +378,38 @@ PhysicsBody* PhysicsWorld::addBody(PhysicsBody* body)
addShape(dynamic_cast<PhysicsShape*>(shape));
}
}
}
PhysicsBody* PhysicsWorld::addBody(PhysicsBody* body)
{
CCASSERT(body != nullptr, "the body can not be nullptr");
delayTestAddBody(body);
_bodies->addObject(body);
return body;
}
void PhysicsWorld::removeBody(PhysicsBody* body)
{
delayTestRemoveBody(body);
_bodies->removeObject(body);
}
void PhysicsWorld::removeBodyByTag(int tag)
{
for (Object* obj : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
if (body->getTag() == tag)
{
removeBody(body);
return;
}
}
}
void PhysicsWorld::realRemoveBody(PhysicsBody* body)
{
CCASSERT(body != nullptr, "the body can not be nullptr");
@ -346,25 +437,16 @@ void PhysicsWorld::removeBody(PhysicsBody* body)
}
// remove body
if (cpSpaceContainsBody(_info->space, body->_info->body))
{
cpSpaceRemoveBody(_info->space, body->_info->body);
}
_info->removeBody(body->_info->body);
body->_world = nullptr;
_bodies->removeObject(body);
}
void PhysicsWorld::removeBodyByTag(int tag)
void PhysicsWorld::realRemoveJoint(PhysicsJoint* joint)
{
for (Object* obj : *_bodies)
for (auto subjoint : joint->_info->joints)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
if (body->getTag() == tag)
{
removeBody(body);
return;
}
_info->removeJoint(subjoint);
}
}
@ -372,33 +454,7 @@ void PhysicsWorld::removeAllBodies()
{
for (Object* obj : *_bodies)
{
PhysicsBody* body = dynamic_cast<PhysicsBody*>(obj);
// reset the gravity
if (!body->isGravityEnable())
{
body->applyForce(-_gravity);
}
// remove joints
for (auto joint : body->_joints)
{
removeJoint(joint);
}
// remove shaps
for (auto shape : *body->getShapes())
{
removeShape(dynamic_cast<PhysicsShape*>(shape));
}
// remove body
if (cpSpaceContainsBody(_info->space, body->_info->body))
{
cpSpaceRemoveBody(_info->space, body->_info->body);
}
body->_world = nullptr;
delayTestRemoveBody(dynamic_cast<PhysicsBody*>(obj));
}
_bodies->removeAllObjects();
@ -416,8 +472,57 @@ void PhysicsWorld::removeShape(PhysicsShape* shape)
}
}
void PhysicsWorld::updateBodies()
{
if (_info->space->locked_private)
{
return;
}
for (auto body : *_delayAddBodies)
{
realAddBody(dynamic_cast<PhysicsBody*>(body));
}
for (auto body : *_delayRemoveBodies)
{
realRemoveBody(dynamic_cast<PhysicsBody*>(body));
}
_delayAddBodies->removeAllObjects();
_delayRemoveBodies->removeAllObjects();
}
void PhysicsWorld::updateJoints()
{
if (_info->space->locked_private)
{
return;
}
for (auto joint : _delayAddJoints)
{
realAddJoint(joint);
}
for (auto joint : _delayRemoveJoints)
{
realRemoveJoint(joint);
}
_delayAddJoints.clear();
_delayRemoveJoints.clear();
}
void PhysicsWorld::update(float delta)
{
if (_delayDirty)
{
updateBodies();
updateJoints();
_delayDirty = !(_delayAddBodies->count() == 0 && _delayRemoveBodies->count() == 0 && _delayAddJoints.size() == 0 && _delayRemoveJoints.size() == 0);
}
for (auto body : *_bodies)
{
body->update(delta);
@ -804,8 +909,11 @@ PhysicsWorld::PhysicsWorld()
, _info(nullptr)
, _bodies(nullptr)
, _scene(nullptr)
, _delayDirty(false)
, _debugDraw(false)
, _drawNode(nullptr)
, _delayAddBodies(nullptr)
, _delayRemoveBodies(nullptr)
{
}
@ -814,6 +922,8 @@ PhysicsWorld::~PhysicsWorld()
{
removeAllBodies();
removeAllJoints();
CC_SAFE_RELEASE(_delayRemoveBodies);
CC_SAFE_RELEASE(_delayAddBodies);
CC_SAFE_DELETE(_info);
}

View File

@ -29,6 +29,7 @@
#define __CCPHYSICS_WORLD_H__
#include <list>
#include <vector>
#include "CCObject.h"
#include "CCGeometry.h"
@ -86,11 +87,15 @@ class PhysicsWorld
{
public:
/** Adds a joint to the physics world.*/
void addJoint(PhysicsJoint* joint);
virtual void addJoint(PhysicsJoint* joint);
/** Removes a joint from the physics world.*/
void removeJoint(PhysicsJoint* joint);
virtual void removeJoint(PhysicsJoint* joint);
/** Remove all joints from the physics world.*/
void removeAllJoints();
virtual void removeAllJoints();
virtual void removeBody(PhysicsBody* body);
virtual void removeBodyByTag(int tag);
virtual void removeAllBodies();
void rayCast(PhysicsRayCastCallback& callback, Point point1, Point point2, void* data);
void rectQuery(PhysicsRectQueryCallback& callback, Rect rect, void* data);
@ -115,10 +120,6 @@ public:
/** set the debug draw */
inline void setDebugDraw(bool debugDraw) { _debugDraw = debugDraw; }
virtual void removeBody(PhysicsBody* body);
virtual void removeBodyByTag(int tag);
virtual void removeAllBodies();
protected:
static PhysicsWorld* create(Scene& scene);
bool init(Scene& scene);
@ -132,25 +133,40 @@ protected:
virtual void drawWithShape(DrawNode* node, PhysicsShape* shape);
virtual void drawWithJoint(DrawNode* node, PhysicsJoint* joint);
virtual int collisionBeginCallback(PhysicsContact& contact);
virtual int collisionPreSolveCallback(PhysicsContact& contact);
virtual void collisionPostSolveCallback(PhysicsContact& contact);
virtual void collisionSeparateCallback(PhysicsContact& contact);
virtual void realAddBody(PhysicsBody* body);
virtual void realRemoveBody(PhysicsBody* body);
virtual void realAddJoint(PhysicsJoint* joint);
virtual void realRemoveJoint(PhysicsJoint* joint);
virtual void delayTestAddBody(PhysicsBody* body);
virtual void delayTestRemoveBody(PhysicsBody* body);
virtual void delayTestAddJoint(PhysicsJoint* joint);
virtual void delayTestRemoveJoint(PhysicsJoint* joint);
virtual void updateBodies();
virtual void updateJoints();
protected:
Point _gravity;
float _speed;
PhysicsWorldInfo* _info;
//EventListenerPhysicsContact* _listener;
Array* _bodies;
std::list<PhysicsJoint*> _joints;
Scene* _scene;
bool _delayDirty;
bool _debugDraw;
DrawNode* _drawNode;
Array* _delayAddBodies;
Array* _delayRemoveBodies;
std::vector<PhysicsJoint*> _delayAddJoints;
std::vector<PhysicsJoint*> _delayRemoveJoints;
protected:
PhysicsWorld();
virtual ~PhysicsWorld();

View File

@ -26,6 +26,21 @@
#if (CC_PHYSICS_ENGINE == CC_PHYSICS_CHIPMUNK)
NS_CC_BEGIN
#define PHYSICS_WORLD_INFO_FUNCTION_IMPLEMENTS(name, type) \
void PhysicsWorldInfo::add##name(cp##type* data) \
{ \
if (!cpSpaceContains##type(space, data)) cpSpaceAdd##type(space, data); \
} \
\
void PhysicsWorldInfo::remove##name(cp##type* data) \
{ \
if (cpSpaceContains##type(space, data)) cpSpaceRemove##type(space, data); \
} \
PHYSICS_WORLD_INFO_FUNCTION_IMPLEMENTS(Shape, Shape)
PHYSICS_WORLD_INFO_FUNCTION_IMPLEMENTS(Body, Body)
PHYSICS_WORLD_INFO_FUNCTION_IMPLEMENTS(Joint, Constraint)
PhysicsWorldInfo::PhysicsWorldInfo()
{
space = cpSpaceNew();

View File

@ -30,6 +30,7 @@
#include "chipmunk.h"
#include "CCPlatformMacros.h"
#include <vector>
NS_CC_BEGIN
class PhysicsWorldInfo
@ -37,6 +38,13 @@ class PhysicsWorldInfo
public:
cpSpace* space;
void addShape(cpShape* shape);
void removeShape(cpShape* shape);
void addBody(cpBody* body);
void removeBody(cpBody* body);
void addJoint(cpConstraint* joint);
void removeJoint(cpConstraint* joint);
private:
PhysicsWorldInfo();
~PhysicsWorldInfo();