diff --git a/build/cocos2d_tests.xcodeproj/project.pbxproj b/build/cocos2d_tests.xcodeproj/project.pbxproj index 6ef7474ee4..c3fb3dd9da 100644 --- a/build/cocos2d_tests.xcodeproj/project.pbxproj +++ b/build/cocos2d_tests.xcodeproj/project.pbxproj @@ -7723,7 +7723,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; INFOPLIST_FILE = "$(SRCROOT)/../tests/cpp-tests/proj.mac/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; - USER_HEADER_SEARCH_PATHS = "$(inherited) $(SRCROOT)/../external/glfw3/include/mac $(SRCROOT)/../external/freetype2/include/mac/freetype2"; + USER_HEADER_SEARCH_PATHS = "$(inherited) $(SRCROOT)/../external/glfw3/include/mac $(SRCROOT)/../external/freetype2/include/mac/freetype2 $(SRCROOT)/../tests/cpp-tests/Classes"; }; name = Debug; }; @@ -7739,7 +7739,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; INFOPLIST_FILE = "$(SRCROOT)/../tests/cpp-tests/proj.mac/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; - USER_HEADER_SEARCH_PATHS = "$(inherited) $(SRCROOT)/../external/glfw3/include/mac $(SRCROOT)/../external/freetype2/include/mac/freetype2"; + USER_HEADER_SEARCH_PATHS = "$(inherited) $(SRCROOT)/../external/glfw3/include/mac $(SRCROOT)/../external/freetype2/include/mac/freetype2 $(SRCROOT)/../tests/cpp-tests/Classes"; VALIDATE_PRODUCT = YES; }; name = Release; diff --git a/cocos/physics/CCPhysicsJoint.cpp b/cocos/physics/CCPhysicsJoint.cpp index de5e07f2ba..afa1cf98a6 100644 --- a/cocos/physics/CCPhysicsJoint.cpp +++ b/cocos/physics/CCPhysicsJoint.cpp @@ -34,6 +34,83 @@ NS_CC_BEGIN +template +class Optional { + +public: + Optional() {} + Optional(T d) :_isSet(true), _data(d) {} + Optional(const Optional &t) : _isSet(t._isSet), _data(t._data) {} + + //bool isNull() const { return !_isSet; } + //bool isDefineded() const { return _isSet; } + //bool isEmpty() const { return !_isSet; } + + T get() const { CCASSERT(_isSet, "data should be set!"); return _data; } + void set(T d) { _isSet = true; _data = d; } + +private: + bool _isSet = false; + T _data; +}; + +class WriteCache { +public: + Optional _grooveA; + Optional _grooveB; + Optional _anchr1; + Optional _anchr2; + Optional _min; + Optional _max; + Optional _distance; + Optional _restLength; + Optional _restAngle; + Optional _stiffness; + Optional _damping; + Optional _angle; + Optional _phase; + Optional _ratchet; + Optional _ratio; + Optional _rate; +}; + +#if (defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__) +#define LIKELY(x) (__builtin_expect((x), 1)) +#define UNLIKELY(x) (__builtin_expect((x), 0)) +#else +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif + + +#define CC_PJOINT_CACHE_READ(field) \ + do { \ + if(UNLIKELY(_initDirty)) \ + { \ + return _writeCache->field.get(); \ + } \ + }while(0) + + + +#define CC_PJOINT_CACHE_WRITE2(field, method, arg, convertedArg) \ + do { \ + if(UNLIKELY(_initDirty)) \ + { \ + _writeCache->field.set(arg); \ + delay([this, arg]() { \ + method(_cpConstraints.front(), convertedArg); \ + }); \ + } \ + else \ + { \ + method(_cpConstraints.front(), convertedArg); \ + } \ + }while(0) + +#define CC_PJOINT_CACHE_WRITE(field, method, arg) \ + CC_PJOINT_CACHE_WRITE2(field, method, arg, arg) + PhysicsJoint::PhysicsJoint() : _bodyA(nullptr) , _bodyB(nullptr) @@ -45,7 +122,7 @@ PhysicsJoint::PhysicsJoint() , _maxForce(PHYSICS_INFINITY) , _initDirty(true) { - + _writeCache = new WriteCache(); } PhysicsJoint::~PhysicsJoint() @@ -58,6 +135,8 @@ PhysicsJoint::~PhysicsJoint() cpConstraintFree(joint); } _cpConstraints.clear(); + + delete _writeCache; } bool PhysicsJoint::init(cocos2d::PhysicsBody *a, cocos2d::PhysicsBody *b) @@ -99,6 +178,15 @@ bool PhysicsJoint::initJoint() return ret; } +void PhysicsJoint::flushDelayTasks() +{ + for (auto tsk : _delayTasks) + { + tsk(); + } + _delayTasks.clear(); +} + void PhysicsJoint::setEnable(bool enable) { if (_enable != enable) @@ -137,10 +225,23 @@ void PhysicsJoint::removeFormWorld() void PhysicsJoint::setMaxForce(float force) { - _maxForce = force; - for (auto joint : _cpConstraints) + if(_initDirty) { - cpConstraintSetMaxForce(joint, force); + delay([this, force]() { + _maxForce = force; + for (auto joint : _cpConstraints) + { + cpConstraintSetMaxForce(joint, force); + } + }); + } + else + { + _maxForce = force; + for (auto joint : _cpConstraints) + { + cpConstraintSetMaxForce(joint, force); + } } } @@ -285,42 +386,46 @@ bool PhysicsJointLimit::createConstraints() float PhysicsJointLimit::getMin() const { + CC_PJOINT_CACHE_READ(_min); return PhysicsHelper::cpfloat2float(cpSlideJointGetMin(_cpConstraints.front())); } void PhysicsJointLimit::setMin(float min) { - cpSlideJointSetMin(_cpConstraints.front(), min); + CC_PJOINT_CACHE_WRITE(_min, cpSlideJointSetMin, min); } float PhysicsJointLimit::getMax() const { + CC_PJOINT_CACHE_READ(_max); return PhysicsHelper::cpfloat2float(cpSlideJointGetMax(_cpConstraints.front())); } void PhysicsJointLimit::setMax(float max) { - cpSlideJointSetMax(_cpConstraints.front(), max); + CC_PJOINT_CACHE_WRITE(_max, cpSlideJointSetMax, max); } Vec2 PhysicsJointLimit::getAnchr1() const { + CC_PJOINT_CACHE_READ(_anchr1); return PhysicsHelper::cpv2point(cpSlideJointGetAnchorA(_cpConstraints.front())); } void PhysicsJointLimit::setAnchr1(const Vec2& anchr) { - cpSlideJointSetAnchorA(_cpConstraints.front(), PhysicsHelper::point2cpv(anchr)); + CC_PJOINT_CACHE_WRITE2(_anchr1, cpSlideJointSetAnchorA, anchr, PhysicsHelper::point2cpv(anchr)); } Vec2 PhysicsJointLimit::getAnchr2() const { + CC_PJOINT_CACHE_READ(_anchr2); return PhysicsHelper::cpv2point(cpSlideJointGetAnchorB(_cpConstraints.front())); } void PhysicsJointLimit::setAnchr2(const Vec2& anchr) { - cpSlideJointSetAnchorB(_cpConstraints.front(), PhysicsHelper::point2cpv(anchr)); + CC_PJOINT_CACHE_WRITE2(_anchr2, cpSlideJointSetAnchorB, anchr, PhysicsHelper::point2cpv(anchr)); } PhysicsJointDistance* PhysicsJointDistance::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2) @@ -358,12 +463,13 @@ bool PhysicsJointDistance::createConstraints() float PhysicsJointDistance::getDistance() const { + CC_PJOINT_CACHE_READ(_distance); return PhysicsHelper::cpfloat2float(cpPinJointGetDist(_cpConstraints.front())); } void PhysicsJointDistance::setDistance(float distance) { - cpPinJointSetDist(_cpConstraints.front(), distance); + CC_PJOINT_CACHE_WRITE(_distance, cpPinJointSetDist, distance); } PhysicsJointSpring* PhysicsJointSpring::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2, float stiffness, float damping) @@ -406,52 +512,57 @@ bool PhysicsJointSpring::createConstraints() Vec2 PhysicsJointSpring::getAnchr1() const { + CC_PJOINT_CACHE_READ(_anchr1); return PhysicsHelper::cpv2point(cpDampedSpringGetAnchorA(_cpConstraints.front())); } void PhysicsJointSpring::setAnchr1(const Vec2& anchr) { - cpDampedSpringSetAnchorA(_cpConstraints.front(), PhysicsHelper::point2cpv(anchr)); + CC_PJOINT_CACHE_WRITE2(_anchr1, cpDampedSpringSetAnchorA, anchr, PhysicsHelper::point2cpv(anchr)); } Vec2 PhysicsJointSpring::getAnchr2() const { + CC_PJOINT_CACHE_READ(_anchr2); return PhysicsHelper::cpv2point(cpDampedSpringGetAnchorB(_cpConstraints.front())); } void PhysicsJointSpring::setAnchr2(const Vec2& anchr) { - cpDampedSpringSetAnchorB(_cpConstraints.front(), PhysicsHelper::point2cpv(anchr)); + CC_PJOINT_CACHE_WRITE2(_anchr2, cpDampedSpringSetAnchorB, anchr, PhysicsHelper::point2cpv(anchr)); } float PhysicsJointSpring::getRestLength() const { + CC_PJOINT_CACHE_READ(_restLength); return PhysicsHelper::cpfloat2float(cpDampedSpringGetRestLength(_cpConstraints.front())); } void PhysicsJointSpring::setRestLength(float restLength) { - cpDampedSpringSetRestLength(_cpConstraints.front(), restLength); + CC_PJOINT_CACHE_WRITE(_restLength, cpDampedSpringSetRestLength, restLength); } float PhysicsJointSpring::getStiffness() const { + CC_PJOINT_CACHE_READ(_stiffness); return PhysicsHelper::cpfloat2float(cpDampedSpringGetStiffness(_cpConstraints.front())); } void PhysicsJointSpring::setStiffness(float stiffness) { - cpDampedSpringSetStiffness(_cpConstraints.front(), stiffness); + CC_PJOINT_CACHE_WRITE(_stiffness, cpDampedSpringSetStiffness, stiffness); } float PhysicsJointSpring::getDamping() const { + CC_PJOINT_CACHE_READ(_damping); return PhysicsHelper::cpfloat2float(cpDampedSpringGetDamping(_cpConstraints.front())); } void PhysicsJointSpring::setDamping(float damping) { - cpDampedSpringSetDamping(_cpConstraints.front(), damping); + CC_PJOINT_CACHE_WRITE(_damping, cpDampedSpringSetDamping, damping); } PhysicsJointGroove* PhysicsJointGroove::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& grooveA, const Vec2& grooveB, const Vec2& anchr2) @@ -491,32 +602,35 @@ bool PhysicsJointGroove::createConstraints() Vec2 PhysicsJointGroove::getGrooveA() const { + CC_PJOINT_CACHE_READ(_grooveA); return PhysicsHelper::cpv2point(cpGrooveJointGetGrooveA(_cpConstraints.front())); } void PhysicsJointGroove::setGrooveA(const Vec2& grooveA) { - cpGrooveJointSetGrooveA(_cpConstraints.front(), PhysicsHelper::point2cpv(grooveA)); + CC_PJOINT_CACHE_WRITE2(_grooveA, cpGrooveJointSetGrooveA, grooveA, PhysicsHelper::point2cpv(grooveA)); } Vec2 PhysicsJointGroove::getGrooveB() const { + CC_PJOINT_CACHE_READ(_grooveB); return PhysicsHelper::cpv2point(cpGrooveJointGetGrooveB(_cpConstraints.front())); } void PhysicsJointGroove::setGrooveB(const Vec2& grooveB) { - cpGrooveJointSetGrooveB(_cpConstraints.front(), PhysicsHelper::point2cpv(grooveB)); + CC_PJOINT_CACHE_WRITE2(_grooveB, cpGrooveJointSetGrooveB, grooveB, PhysicsHelper::point2cpv(grooveB)); } Vec2 PhysicsJointGroove::getAnchr2() const { + CC_PJOINT_CACHE_READ(_anchr2); return PhysicsHelper::cpv2point(cpGrooveJointGetAnchorB(_cpConstraints.front())); } void PhysicsJointGroove::setAnchr2(const Vec2& anchr2) { - cpGrooveJointSetAnchorB(_cpConstraints.front(), PhysicsHelper::point2cpv(anchr2)); + CC_PJOINT_CACHE_WRITE2(_anchr2, cpGrooveJointSetAnchorB, anchr2, PhysicsHelper::point2cpv(anchr2)); } PhysicsJointRotarySpring* PhysicsJointRotarySpring::construct(PhysicsBody* a, PhysicsBody* b, float stiffness, float damping) @@ -555,32 +669,35 @@ bool PhysicsJointRotarySpring::createConstraints() float PhysicsJointRotarySpring::getRestAngle() const { + CC_PJOINT_CACHE_READ(_restAngle); return PhysicsHelper::cpfloat2float(cpDampedRotarySpringGetRestAngle(_cpConstraints.front())); } void PhysicsJointRotarySpring::setRestAngle(float restAngle) { - cpDampedRotarySpringSetRestAngle(_cpConstraints.front(), restAngle); + CC_PJOINT_CACHE_WRITE(_restAngle, cpDampedRotarySpringSetRestAngle, restAngle); } float PhysicsJointRotarySpring::getStiffness() const { + CC_PJOINT_CACHE_READ(_stiffness); return PhysicsHelper::cpfloat2float(cpDampedRotarySpringGetStiffness(_cpConstraints.front())); } void PhysicsJointRotarySpring::setStiffness(float stiffness) { - cpDampedRotarySpringSetStiffness(_cpConstraints.front(), stiffness); + CC_PJOINT_CACHE_WRITE(_stiffness, cpDampedRotarySpringSetStiffness, stiffness); } float PhysicsJointRotarySpring::getDamping() const { + CC_PJOINT_CACHE_READ(_damping); return PhysicsHelper::cpfloat2float(cpDampedRotarySpringGetDamping(_cpConstraints.front())); } void PhysicsJointRotarySpring::setDamping(float damping) { - cpDampedRotarySpringSetDamping(_cpConstraints.front(), damping); + CC_PJOINT_CACHE_WRITE(_damping, cpDampedRotarySpringSetDamping, damping); } PhysicsJointRotaryLimit* PhysicsJointRotaryLimit::construct(PhysicsBody* a, PhysicsBody* b, float min, float max) @@ -624,22 +741,24 @@ bool PhysicsJointRotaryLimit::createConstraints() float PhysicsJointRotaryLimit::getMin() const { + CC_PJOINT_CACHE_READ(_min); return PhysicsHelper::cpfloat2float(cpRotaryLimitJointGetMin(_cpConstraints.front())); } void PhysicsJointRotaryLimit::setMin(float min) { - cpRotaryLimitJointSetMin(_cpConstraints.front(), min); + CC_PJOINT_CACHE_WRITE(_min, cpRotaryLimitJointSetMin, min); } float PhysicsJointRotaryLimit::getMax() const { + CC_PJOINT_CACHE_READ(_max); return PhysicsHelper::cpfloat2float(cpRotaryLimitJointGetMax(_cpConstraints.front())); } void PhysicsJointRotaryLimit::setMax(float max) { - cpRotaryLimitJointSetMax(_cpConstraints.front(), max); + CC_PJOINT_CACHE_WRITE(_max, cpRotaryLimitJointSetMax, max); } PhysicsJointRatchet* PhysicsJointRatchet::construct(PhysicsBody* a, PhysicsBody* b, float phase, float ratchet) @@ -678,32 +797,35 @@ bool PhysicsJointRatchet::createConstraints() float PhysicsJointRatchet::getAngle() const { + CC_PJOINT_CACHE_READ(_angle); return PhysicsHelper::cpfloat2float(cpRatchetJointGetAngle(_cpConstraints.front())); } void PhysicsJointRatchet::setAngle(float angle) { - cpRatchetJointSetAngle(_cpConstraints.front(), angle); + CC_PJOINT_CACHE_WRITE(_angle, cpRatchetJointSetAngle, angle); } float PhysicsJointRatchet::getPhase() const { + CC_PJOINT_CACHE_READ(_phase); return PhysicsHelper::cpfloat2float(cpRatchetJointGetPhase(_cpConstraints.front())); } void PhysicsJointRatchet::setPhase(float phase) { - cpRatchetJointSetPhase(_cpConstraints.front(), phase); + CC_PJOINT_CACHE_WRITE(_phase, cpRatchetJointSetPhase, phase); } float PhysicsJointRatchet::getRatchet() const { + CC_PJOINT_CACHE_READ(_ratchet); return PhysicsHelper::cpfloat2float(cpRatchetJointGetRatchet(_cpConstraints.front())); } void PhysicsJointRatchet::setRatchet(float ratchet) { - cpRatchetJointSetRatchet(_cpConstraints.front(), ratchet); + CC_PJOINT_CACHE_WRITE(_ratchet, cpRatchetJointSetRatchet, ratchet); } PhysicsJointGear* PhysicsJointGear::construct(PhysicsBody* a, PhysicsBody* b, float phase, float ratio) @@ -742,22 +864,24 @@ bool PhysicsJointGear::createConstraints() float PhysicsJointGear::getPhase() const { + CC_PJOINT_CACHE_READ(_phase); return PhysicsHelper::cpfloat2float(cpGearJointGetPhase(_cpConstraints.front())); } void PhysicsJointGear::setPhase(float phase) { - cpGearJointSetPhase(_cpConstraints.front(), phase); + CC_PJOINT_CACHE_WRITE(_phase, cpGearJointSetPhase, phase); } float PhysicsJointGear::getRatio() const { + CC_PJOINT_CACHE_READ(_ratio); return PhysicsHelper::cpfloat2float(cpGearJointGetRatio(_cpConstraints.front())); } void PhysicsJointGear::setRatio(float ratio) { - cpGearJointSetRatio(_cpConstraints.front(), ratio); + CC_PJOINT_CACHE_WRITE(_ratio, cpGearJointSetRatio, ratio); } PhysicsJointMotor* PhysicsJointMotor::construct(PhysicsBody* a, PhysicsBody* b, float rate) @@ -794,12 +918,13 @@ bool PhysicsJointMotor::createConstraints() float PhysicsJointMotor::getRate() const { + CC_PJOINT_CACHE_READ(_rate); return PhysicsHelper::cpfloat2float(cpSimpleMotorGetRate(_cpConstraints.front())); } void PhysicsJointMotor::setRate(float rate) { - cpSimpleMotorSetRate(_cpConstraints.front(), rate); + CC_PJOINT_CACHE_WRITE(_rate, cpSimpleMotorSetRate, rate); } NS_CC_END diff --git a/cocos/physics/CCPhysicsJoint.h b/cocos/physics/CCPhysicsJoint.h index b49bdc6664..51c9782dcf 100644 --- a/cocos/physics/CCPhysicsJoint.h +++ b/cocos/physics/CCPhysicsJoint.h @@ -26,6 +26,8 @@ #ifndef __CCPHYSICS_JOINT_H__ #define __CCPHYSICS_JOINT_H__ +#include + #include "base/ccConfig.h" #if CC_USE_PHYSICS @@ -40,6 +42,8 @@ class Node; class PhysicsBody; class PhysicsWorld; +class WriteCache; + /** * @addtogroup physics * @{ @@ -52,6 +56,8 @@ class PhysicsWorld; */ class CC_DLL PhysicsJoint { +protected: + typedef std::function DelayTask; protected: PhysicsJoint(); virtual ~PhysicsJoint() = 0; @@ -105,15 +111,22 @@ protected: bool init(PhysicsBody* a, PhysicsBody* b); bool initJoint(); + + void delay(const DelayTask & task) { _delayTasks.push_back(task); } + + void flushDelayTasks(); /** Create constraints for this type joint */ virtual bool createConstraints() { return false; } std::vector _cpConstraints; + std::vector _delayTasks; PhysicsBody* _bodyA; PhysicsBody* _bodyB; PhysicsWorld* _world; + WriteCache *_writeCache = nullptr; + bool _enable; bool _collisionEnable; bool _destroyMark; @@ -573,6 +586,7 @@ protected: /** @} */ + NS_CC_END #endif // CC_USE_PHYSICS diff --git a/cocos/physics/CCPhysicsWorld.cpp b/cocos/physics/CCPhysicsWorld.cpp index d7f88e6304..cd6effd739 100644 --- a/cocos/physics/CCPhysicsWorld.cpp +++ b/cocos/physics/CCPhysicsWorld.cpp @@ -701,6 +701,10 @@ void PhysicsWorld::updateJoints() doRemoveJoint(joint); } _delayRemoveJoints.clear(); + + for (auto joint : _joints) { + joint->flushDelayTasks(); + } } void PhysicsWorld::removeShape(PhysicsShape* shape)