issue #2771: change rayCast and rectQuery callback class to std::function

This commit is contained in:
boyu0 2013-11-07 16:23:50 +08:00
parent eb508e4728
commit ef5440f738
4 changed files with 74 additions and 127 deletions

View File

@ -73,7 +73,7 @@ namespace
typedef struct RayCastCallbackInfo
{
PhysicsWorld* world;
PhysicsRayCastCallback* callback;
PhysicsRayCastCallbackFunc func;
Point p1;
Point p2;
void* data;
@ -82,7 +82,7 @@ namespace
typedef struct RectQueryCallbackInfo
{
PhysicsWorld* world;
PhysicsRectQueryCallback* callback;
PhysicsRectQueryCallbackFunc func;
void* data;
}RectQueryCallbackInfo;
}
@ -148,7 +148,7 @@ void PhysicsWorldCallback::rayCastCallbackFunc(cpShape *shape, cpFloat t, cpVect
auto it = PhysicsShapeInfo::getMap().find(shape);
CC_ASSERT(it != PhysicsShapeInfo::getMap().end());
PhysicsRayCastCallback::Info callbackInfo =
PhysicsRayCastInfo callbackInfo =
{
it->second->getShape(),
info->p1,
@ -158,7 +158,7 @@ void PhysicsWorldCallback::rayCastCallbackFunc(cpShape *shape, cpFloat t, cpVect
(float)t,
};
PhysicsWorldCallback::continues = info->callback->report(*info->world, callbackInfo, info->data);
PhysicsWorldCallback::continues = info->func(*info->world, callbackInfo, info->data);
}
void PhysicsWorldCallback::rectQueryCallbackFunc(cpShape *shape, RectQueryCallbackInfo *info)
@ -172,9 +172,7 @@ void PhysicsWorldCallback::rectQueryCallbackFunc(cpShape *shape, RectQueryCallba
return;
}
PhysicsWorldCallback::continues = info->callback->report(*info->world,
*it->second->getShape(),
info->data);
PhysicsWorldCallback::continues = info->func(*info->world, *it->second->getShape(), info->data);
}
void PhysicsWorldCallback::nearestPointQueryFunc(cpShape *shape, cpFloat distance, cpVect point, Array *arr)
@ -883,13 +881,13 @@ void PhysicsWorld::setGravity(const Vect& gravity)
}
void PhysicsWorld::rayCast(PhysicsRayCastCallback& callback, const Point& point1, const Point& point2, void* data)
void PhysicsWorld::rayCast(PhysicsRayCastCallbackFunc func, const Point& point1, const Point& point2, void* data)
{
CCASSERT(callback.report != nullptr, "callback.report shouldn't be nullptr");
CCASSERT(func != nullptr, "callback.report shouldn't be nullptr");
if (callback.report != nullptr)
if (func != nullptr)
{
RayCastCallbackInfo info = { this, &callback, point1, point2, data };
RayCastCallbackInfo info = { this, func, point1, point2, data };
PhysicsWorldCallback::continues = true;
cpSpaceSegmentQuery(this->_info->getSpace(),
@ -903,13 +901,13 @@ void PhysicsWorld::rayCast(PhysicsRayCastCallback& callback, const Point& point1
}
void PhysicsWorld::rectQuery(PhysicsRectQueryCallback& callback, const Rect& rect, void* data)
void PhysicsWorld::rectQuery(PhysicsRectQueryCallbackFunc func, const Rect& rect, void* data)
{
CCASSERT(callback.report != nullptr, "callback.report shouldn't be nullptr");
CCASSERT(func != nullptr, "callback.report shouldn't be nullptr");
if (callback.report != nullptr)
if (func != nullptr)
{
RectQueryCallbackInfo info = {this, &callback, data};
RectQueryCallbackInfo info = {this, func, data};
PhysicsWorldCallback::continues = true;
cpSpaceBBQuery(this->_info->getSpace(),

View File

@ -48,10 +48,9 @@ class Scene;
class DrawNode;
class PhysicsWorld;
class PhysicsRayCastCallback
{
public:
typedef struct Info
typedef struct PhysicsRayCastInfo
{
PhysicsShape* shape;
Point start;
@ -60,13 +59,8 @@ public:
Vect normal;
float fraction;
void* data;
}Info;
}PhysicsRayCastInfo;
public:
PhysicsRayCastCallback()
: report(nullptr)
{}
virtual ~PhysicsRayCastCallback(){}
/**
* @brief Called for each fixture found in the query. You control how the ray cast
* proceeds by returning a float:
@ -77,20 +71,8 @@ public:
* @param normal the normal vector at the point of intersection
* @return true to continue, false to terminate
*/
std::function<bool(PhysicsWorld& world, const Info& info, void* data)> report;
};
class PhysicsRectQueryCallback
{
public:
PhysicsRectQueryCallback()
: report(nullptr)
{}
virtual ~PhysicsRectQueryCallback(){}
public:
std::function<bool(PhysicsWorld&, PhysicsShape&, void*)> report;
};
typedef std::function<bool(PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data)> PhysicsRayCastCallbackFunc;
typedef std::function<bool(PhysicsWorld&, PhysicsShape&, void*)> PhysicsRectQueryCallbackFunc;
/**
* @brief An PhysicsWorld object simulates collisions and other physical properties. You do not create PhysicsWorld objects directly; instead, you can get it from an Scene object.
@ -109,8 +91,8 @@ public:
virtual void removeBody(int tag);
virtual void removeAllBodies();
void rayCast(PhysicsRayCastCallback& callback, const Point& point1, const Point& point2, void* data);
void rectQuery(PhysicsRectQueryCallback& callback, const Rect& rect, void* data);
void rayCast(PhysicsRayCastCallbackFunc func, const Point& point1, const Point& point2, void* data);
void rectQuery(PhysicsRectQueryCallbackFunc func, const Rect& rect, void* data);
Array* getShapes(const Point& point) const;
PhysicsShape* getShape(const Point& point) const;
Array* getAllBodies() const;

View File

@ -602,65 +602,12 @@ void PhysicsDemoRayCast::changeModeCallback(Object* sender)
}
}
bool PhysicsDemoRayCast::anyRay(PhysicsWorld& world, const PhysicsRayCastCallback::Info& info, void* data)
bool PhysicsDemoRayCast::anyRay(PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data)
{
*((Point*)data) = info.contact;
return false;
}
class PhysicsDemoNearestRayCastCallback : public PhysicsRayCastCallback
{
public:
PhysicsDemoNearestRayCastCallback();
private:
float _friction;
};
PhysicsDemoNearestRayCastCallback::PhysicsDemoNearestRayCastCallback()
: _friction(1.0f)
{
report = [this](PhysicsWorld& world, const PhysicsRayCastCallback::Info& info, void* data)->bool
{
if (_friction > info.fraction)
{
*((Point*)data) = info.contact;
_friction = info.fraction;
}
return true;
};
}
namespace
{
static const int MAX_MULTI_RAYCAST_NUM = 5;
}
class PhysicsDemoMultiRayCastCallback : public PhysicsRayCastCallback
{
public:
PhysicsDemoMultiRayCastCallback();
public:
Point points[MAX_MULTI_RAYCAST_NUM];
int num;
};
PhysicsDemoMultiRayCastCallback::PhysicsDemoMultiRayCastCallback()
: num(0)
{
report = [this](PhysicsWorld& world, const PhysicsRayCastCallback::Info& info, void* data)->bool
{
if (num < MAX_MULTI_RAYCAST_NUM)
{
points[num++] = info.contact;
}
return true;
};
}
void PhysicsDemoRayCast::update(float delta)
{
float L = 150.0f;
@ -674,11 +621,10 @@ void PhysicsDemoRayCast::update(float delta)
{
case 0:
{
PhysicsRayCastCallback callback;
Point point3 = point2;
callback.report = CC_CALLBACK_3(PhysicsDemoRayCast::anyRay, this);
auto func = CC_CALLBACK_3(PhysicsDemoRayCast::anyRay, this);
_scene->getPhysicsWorld()->rayCast(callback, point1, point2, &point3);
_scene->getPhysicsWorld()->rayCast(func, point1, point2, &point3);
_node->drawSegment(point1, point3, 1, STATIC_COLOR);
if (point2 != point3)
@ -691,10 +637,20 @@ void PhysicsDemoRayCast::update(float delta)
}
case 1:
{
PhysicsDemoNearestRayCastCallback callback;
Point point3 = point2;
float friction = 1.0f;
PhysicsRayCastCallbackFunc func = [&point3, &friction](PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data)->bool
{
if (friction > info.fraction)
{
point3 = info.contact;
friction = info.fraction;
}
_scene->getPhysicsWorld()->rayCast(callback, point1, point2, &point3);
return true;
};
_scene->getPhysicsWorld()->rayCast(func, point1, point2, nullptr);
_node->drawSegment(point1, point3, 1, STATIC_COLOR);
if (point2 != point3)
@ -707,15 +663,27 @@ void PhysicsDemoRayCast::update(float delta)
}
case 2:
{
PhysicsDemoMultiRayCastCallback callback;
#define MAX_MULTI_RAYCAST_NUM 5
Point points[MAX_MULTI_RAYCAST_NUM];
int num = 0;
_scene->getPhysicsWorld()->rayCast(callback, point1, point2, nullptr);
PhysicsRayCastCallbackFunc func = [&points, &num](PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data)->bool
{
if (num < MAX_MULTI_RAYCAST_NUM)
{
points[num++] = info.contact;
}
return true;
};
_scene->getPhysicsWorld()->rayCast(func, point1, point2, nullptr);
_node->drawSegment(point1, point2, 1, STATIC_COLOR);
for (int i = 0; i < callback.num; ++i)
for (int i = 0; i < num; ++i)
{
_node->drawDot(callback.points[i], 2, Color4F(1.0f, 1.0f, 1.0f, 1.0f));
_node->drawDot(points[i], 2, Color4F(1.0f, 1.0f, 1.0f, 1.0f));
}
addChild(_node);
@ -1089,7 +1057,7 @@ void PhysicsDemoSlice::onEnter()
addChild(box);
}
bool PhysicsDemoSlice::slice(PhysicsWorld &world, const PhysicsRayCastCallback::Info &info, void *data)
bool PhysicsDemoSlice::slice(PhysicsWorld &world, const PhysicsRayCastInfo& info, void *data)
{
if (info.shape->getBody()->getTag() != _sliceTag)
{
@ -1156,9 +1124,8 @@ void PhysicsDemoSlice::clipPoly(PhysicsShapePolygon* shape, Point normal, float
void PhysicsDemoSlice::onTouchEnded(Touch *touch, Event *event)
{
PhysicsRayCastCallback callback;
callback.report = CC_CALLBACK_3(PhysicsDemoSlice::slice, this);
_scene->getPhysicsWorld()->rayCast(callback, touch->getStartLocation(), touch->getLocation(), nullptr);
auto func = CC_CALLBACK_3(PhysicsDemoSlice::slice, this);
_scene->getPhysicsWorld()->rayCast(func, touch->getStartLocation(), touch->getLocation(), nullptr);
}
std::string PhysicsDemoSlice::title()

View File

@ -96,7 +96,7 @@ public:
void changeModeCallback(Object* sender);
bool anyRay(PhysicsWorld& world, const PhysicsRayCastCallback::Info& info, void* data);
bool anyRay(PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data);
private:
float _angle;
@ -150,7 +150,7 @@ public:
std::string title() override;
std::string subtitle() override;
bool slice(PhysicsWorld& world, const PhysicsRayCastCallback::Info& info, void* data);
bool slice(PhysicsWorld& world, const PhysicsRayCastInfo& info, void* data);
void clipPoly(PhysicsShapePolygon* shape, Point normal, float distance);
bool onTouchBegan(Touch *touch, Event *event);