[deploy] Add box2d debug draw

This commit is contained in:
Nomango 2020-02-23 14:56:14 +08:00
parent c3018315d8
commit 7b6397b49c
13 changed files with 315 additions and 57 deletions

View File

@ -97,26 +97,26 @@ FixturePtr Fixture::CreateEdge(const Param& param, const Point& p1, const Point&
return ptr; return ptr;
} }
FixturePtr Fixture::CreateChain(const Param& param, const Vector<Point>& vertexs, bool loop) FixturePtr Fixture::CreateChain(const Param& param, const Vector<Point>& vertices, bool loop)
{ {
FixturePtr ptr = new (std::nothrow) Fixture; FixturePtr ptr = new (std::nothrow) Fixture;
if (ptr) if (ptr)
{ {
Vector<b2Vec2> b2vertexs; Vector<b2Vec2> b2vertices;
b2vertexs.reserve(vertexs.size()); b2vertices.reserve(vertices.size());
for (const auto& v : vertexs) for (const auto& v : vertices)
{ {
b2vertexs.push_back(global::LocalToWorld(v)); b2vertices.push_back(global::LocalToWorld(v));
} }
auto shape = std::make_unique<b2ChainShape>(); auto shape = std::make_unique<b2ChainShape>();
if (loop) if (loop)
{ {
shape->CreateLoop(&b2vertexs[0], static_cast<int32>(b2vertexs.size())); shape->CreateLoop(&b2vertices[0], static_cast<int32>(b2vertices.size()));
} }
else else
{ {
shape->CreateChain(&b2vertexs[0], static_cast<int32>(b2vertexs.size())); shape->CreateChain(&b2vertices[0], static_cast<int32>(b2vertices.size()));
} }
ptr->shape_ = std::move(shape); ptr->shape_ = std::move(shape);

View File

@ -93,7 +93,7 @@ public:
/// @param param 夹具参数 /// @param param 夹具参数
/// @param vertexs 链条顶点 /// @param vertexs 链条顶点
/// @param loop 是否连接链条的起点和终点 /// @param loop 是否连接链条的起点和终点
static FixturePtr CreateChain(const Param& param, const Vector<Point>& vertexs, bool loop = false); static FixturePtr CreateChain(const Param& param, const Vector<Point>& vertices, bool loop = false);
Fixture(); Fixture();

View File

@ -42,7 +42,7 @@ Joint::~Joint()
bool Joint::Init(PhysicWorld* world) bool Joint::Init(PhysicWorld* world)
{ {
return false; return joint_ != nullptr;
} }
bool Joint::Init(PhysicWorld* world, b2JointDef* joint_def) bool Joint::Init(PhysicWorld* world, b2JointDef* joint_def)
@ -50,8 +50,6 @@ bool Joint::Init(PhysicWorld* world, b2JointDef* joint_def)
KGE_ASSERT(joint_ == nullptr); KGE_ASSERT(joint_ == nullptr);
KGE_ASSERT(world); KGE_ASSERT(world);
Destroy();
world_ = world; world_ = world;
b2World* b2world = world_->GetB2World(); b2World* b2world = world_->GetB2World();
@ -131,8 +129,9 @@ bool DistanceJoint::Init(PhysicWorld* world)
b2DistanceJointDef def; b2DistanceJointDef def;
def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor_a), def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor_a),
global::LocalToWorld(param_.anchor_b)); global::LocalToWorld(param_.anchor_b));
def.frequencyHz = param_.frequency_hz; def.frequencyHz = param_.frequency_hz;
def.dampingRatio = param_.damping_ratio; def.dampingRatio = param_.damping_ratio;
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2DistanceJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2DistanceJoint*>(GetB2Joint());
@ -176,8 +175,9 @@ bool FrictionJoint::Init(PhysicWorld* world)
b2FrictionJointDef def; b2FrictionJointDef def;
def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor)); def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor));
def.maxForce = param_.max_force; def.maxForce = param_.max_force;
def.maxTorque = global::LocalToWorld(param_.max_torque); def.maxTorque = global::LocalToWorld(param_.max_torque);
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2FrictionJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2FrictionJoint*>(GetB2Joint());
@ -232,9 +232,10 @@ bool GearJoint::Init(PhysicWorld* world)
KGE_ASSERT(param_.joint_a && param_.joint_b); KGE_ASSERT(param_.joint_a && param_.joint_b);
b2GearJointDef def; b2GearJointDef def;
def.joint1 = param_.joint_a->GetB2Joint(); def.joint1 = param_.joint_a->GetB2Joint();
def.joint2 = param_.joint_b->GetB2Joint(); def.joint2 = param_.joint_b->GetB2Joint();
def.ratio = param_.ratio; def.ratio = param_.ratio;
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2GearJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2GearJoint*>(GetB2Joint());
@ -281,6 +282,7 @@ bool MotorJoint::Init(PhysicWorld* world)
def.maxForce = param_.max_force; def.maxForce = param_.max_force;
def.maxTorque = global::LocalToWorld(param_.max_torque); def.maxTorque = global::LocalToWorld(param_.max_torque);
def.correctionFactor = param_.correction_factor; def.correctionFactor = param_.correction_factor;
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2MotorJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2MotorJoint*>(GetB2Joint());
@ -343,6 +345,7 @@ bool PrismaticJoint::Init(PhysicWorld* world)
def.enableMotor = param_.enable_motor; def.enableMotor = param_.enable_motor;
def.maxMotorForce = param_.max_motor_force; def.maxMotorForce = param_.max_motor_force;
def.motorSpeed = global::LocalToWorld(param_.motor_speed); def.motorSpeed = global::LocalToWorld(param_.motor_speed);
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2PrismaticJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2PrismaticJoint*>(GetB2Joint());
@ -406,6 +409,7 @@ bool PulleyJoint::Init(PhysicWorld* world)
def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.ground_anchor_a), def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.ground_anchor_a),
global::LocalToWorld(param_.ground_anchor_b), global::LocalToWorld(param_.anchor_a), global::LocalToWorld(param_.ground_anchor_b), global::LocalToWorld(param_.anchor_a),
global::LocalToWorld(param_.anchor_b), param_.ratio); global::LocalToWorld(param_.anchor_b), param_.ratio);
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2PulleyJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2PulleyJoint*>(GetB2Joint());
@ -479,12 +483,13 @@ bool RevoluteJoint::Init(PhysicWorld* world)
b2RevoluteJointDef def; b2RevoluteJointDef def;
def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor)); def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor));
def.enableLimit = param_.enable_limit; def.enableLimit = param_.enable_limit;
def.lowerAngle = math::Degree2Radian(param_.lower_angle); def.lowerAngle = math::Degree2Radian(param_.lower_angle);
def.upperAngle = math::Degree2Radian(param_.upper_angle); def.upperAngle = math::Degree2Radian(param_.upper_angle);
def.enableMotor = param_.enable_motor; def.enableMotor = param_.enable_motor;
def.maxMotorTorque = global::LocalToWorld(param_.max_motor_torque); def.maxMotorTorque = global::LocalToWorld(param_.max_motor_torque);
def.motorSpeed = math::Degree2Radian(param_.motor_speed); def.motorSpeed = math::Degree2Radian(param_.motor_speed);
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2RevoluteJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2RevoluteJoint*>(GetB2Joint());
@ -557,11 +562,12 @@ bool RopeJoint::Init(PhysicWorld* world)
KGE_ASSERT(param_.body_a && param_.body_b); KGE_ASSERT(param_.body_a && param_.body_b);
b2RopeJointDef def; b2RopeJointDef def;
def.bodyA = param_.body_a->GetB2Body(); def.bodyA = param_.body_a->GetB2Body();
def.bodyB = param_.body_b->GetB2Body(); def.bodyB = param_.body_b->GetB2Body();
def.localAnchorA = global::LocalToWorld(param_.local_anchor_a); def.localAnchorA = global::LocalToWorld(param_.local_anchor_a);
def.localAnchorB = global::LocalToWorld(param_.local_anchor_b); def.localAnchorB = global::LocalToWorld(param_.local_anchor_b);
def.maxLength = global::LocalToWorld(param_.max_length); def.maxLength = global::LocalToWorld(param_.max_length);
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2RopeJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2RopeJoint*>(GetB2Joint());
@ -605,8 +611,9 @@ bool WeldJoint::Init(PhysicWorld* world)
b2WeldJointDef def; b2WeldJointDef def;
def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor)); def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor));
def.frequencyHz = param_.frequency_hz; def.frequencyHz = param_.frequency_hz;
def.dampingRatio = param_.damping_ratio; def.dampingRatio = param_.damping_ratio;
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2WeldJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2WeldJoint*>(GetB2Joint());
@ -639,11 +646,12 @@ bool WheelJoint::Init(PhysicWorld* world)
b2WheelJointDef def; b2WheelJointDef def;
def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor), def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::LocalToWorld(param_.anchor),
b2Vec2(param_.axis.x, param_.axis.y)); b2Vec2(param_.axis.x, param_.axis.y));
def.enableMotor = param_.enable_motor; def.enableMotor = param_.enable_motor;
def.maxMotorTorque = global::LocalToWorld(param_.max_motor_torque); def.maxMotorTorque = global::LocalToWorld(param_.max_motor_torque);
def.motorSpeed = global::LocalToWorld(param_.motor_speed); def.motorSpeed = global::LocalToWorld(param_.motor_speed);
def.frequencyHz = param_.frequency_hz; def.frequencyHz = param_.frequency_hz;
def.dampingRatio = param_.damping_ratio; def.dampingRatio = param_.damping_ratio;
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2WheelJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2WheelJoint*>(GetB2Joint());
@ -698,12 +706,13 @@ bool MouseJoint::Init(PhysicWorld* world)
KGE_ASSERT(param_.body_a && param_.body_b); KGE_ASSERT(param_.body_a && param_.body_b);
b2MouseJointDef def; b2MouseJointDef def;
def.bodyA = param_.body_a->GetB2Body(); def.bodyA = param_.body_a->GetB2Body();
def.bodyB = param_.body_b->GetB2Body(); def.bodyB = param_.body_b->GetB2Body();
def.target = global::LocalToWorld(param_.target); def.target = global::LocalToWorld(param_.target);
def.maxForce = param_.max_force; def.maxForce = param_.max_force;
def.frequencyHz = param_.frequency_hz; def.frequencyHz = param_.frequency_hz;
def.dampingRatio = param_.damping_ratio; def.dampingRatio = param_.damping_ratio;
def.collideConnected = param_.collide_connected;
Joint::Init(world, &def); Joint::Init(world, &def);
raw_joint_ = static_cast<b2MouseJoint*>(GetB2Joint()); raw_joint_ = static_cast<b2MouseJoint*>(GetB2Joint());

View File

@ -70,18 +70,19 @@ public:
/// @brief 关节基础参数 /// @brief 关节基础参数
struct ParamBase struct ParamBase
{ {
PhysicBody* body_a; ///< 关节连接的物体A PhysicBody* body_a; ///< 关节连接的物体A
PhysicBody* body_b; ///< 关节连接的物体B PhysicBody* body_b; ///< 关节连接的物体B
bool collide_connected; // 关节连接的物体是否允许碰撞
ParamBase(PhysicBody* body_a, PhysicBody* body_b) ParamBase(PhysicBody* body_a, PhysicBody* body_b)
: body_a(body_a) : body_a(body_a)
, body_b(body_b) , body_b(body_b)
, collide_connected(false)
{ {
} }
ParamBase(PhysicBodyPtr body_a, PhysicBodyPtr body_b) ParamBase(PhysicBodyPtr body_a, PhysicBodyPtr body_b)
: body_a(body_a.Get()) : ParamBase(body_a.Get(), body_b.Get())
, body_b(body_b.Get())
{ {
} }
}; };

View File

@ -226,9 +226,9 @@ Fixture* PhysicBody::AddEdgeShape(const Point& p1, const Point& p2, float densit
return fixture.Get(); return fixture.Get();
} }
Fixture* PhysicBody::AddChainShape(const Vector<Point>& vertexs, bool loop, float density, float friction) Fixture* PhysicBody::AddChainShape(const Vector<Point>& vertices, bool loop, float density, float friction)
{ {
FixturePtr fixture = Fixture::CreateChain(Fixture::Param(density, friction), vertexs, loop); FixturePtr fixture = Fixture::CreateChain(Fixture::Param(density, friction), vertices, loop);
AddFixture(fixture); AddFixture(fixture);
return fixture.Get(); return fixture.Get();
} }
@ -356,12 +356,24 @@ Point PhysicBody::GetLocalPoint(const Point& world) const
return global::WorldToLocal(body_->GetLocalPoint(global::LocalToWorld(world))); return global::WorldToLocal(body_->GetLocalPoint(global::LocalToWorld(world)));
} }
Vec2 PhysicBody::GetLocalVector(const Vec2& world) const
{
KGE_ASSERT(body_);
return global::WorldToLocal(body_->GetLocalVector(global::LocalToWorld(world)));
}
Point PhysicBody::GetWorldPoint(const Point& local) const Point PhysicBody::GetWorldPoint(const Point& local) const
{ {
KGE_ASSERT(body_); KGE_ASSERT(body_);
return global::WorldToLocal(body_->GetWorldPoint(global::LocalToWorld(local))); return global::WorldToLocal(body_->GetWorldPoint(global::LocalToWorld(local)));
} }
Vec2 PhysicBody::GetWorldVector(const Vec2& local) const
{
KGE_ASSERT(body_);
return global::WorldToLocal(body_->GetWorldVector(global::LocalToWorld(local)));
}
Point PhysicBody::GetLocalCenter() const Point PhysicBody::GetLocalCenter() const
{ {
KGE_ASSERT(body_); KGE_ASSERT(body_);

View File

@ -111,7 +111,7 @@ public:
/// @param vertexs 链条端点 /// @param vertexs 链条端点
/// @param loop 是否闭合 /// @param loop 是否闭合
/// @param density 物体密度 /// @param density 物体密度
Fixture* AddChainShape(const Vector<Point>& vertexs, bool loop, float density, float friction = 0.2f); Fixture* AddChainShape(const Vector<Point>& vertices, bool loop, float density, float friction = 0.2f);
/// \~chinese /// \~chinese
/// @brief 移除夹具 /// @brief 移除夹具
@ -203,10 +203,18 @@ public:
/// @brief 获取世界坐标系上的点在物体上的位置 /// @brief 获取世界坐标系上的点在物体上的位置
Point GetLocalPoint(const Point& world) const; Point GetLocalPoint(const Point& world) const;
/// \~chinese
/// @brief 将世界坐标系中的向量转换到物体坐标系下
Vec2 GetLocalVector(const Vec2& world) const;
/// \~chinese /// \~chinese
/// @brief 获取物体上的点在世界坐标系的位置 /// @brief 获取物体上的点在世界坐标系的位置
Point GetWorldPoint(const Point& local) const; Point GetWorldPoint(const Point& local) const;
/// \~chinese
/// @brief 将物体坐标系中的向量转换到世界坐标系下
Vec2 GetWorldVector(const Vec2& local) const;
/// \~chinese /// \~chinese
/// @brief 获取物体质心相对于物体的位置 /// @brief 获取物体质心相对于物体的位置
Point GetLocalCenter() const; Point GetLocalCenter() const;
@ -231,6 +239,22 @@ public:
/// @brief 设置物体受重力的比例 /// @brief 设置物体受重力的比例
void SetGravityScale(float scale); void SetGravityScale(float scale);
/// \~chinese
/// @brief 获取线性阻尼
float GetLinearDamping() const;
/// \~chinese
/// @brief 设置线性阻尼
void SetLinearDamping(float damping);
/// \~chinese
/// @brief 获取旋转阻尼
float GetAngularDamping() const;
/// \~chinese
/// @brief 设置旋转阻尼
void SetAngularDamping(float damping);
/// \~chinese /// \~chinese
/// @brief 施力 /// @brief 施力
/// @param force 力的大小和方向 /// @param force 力的大小和方向
@ -443,6 +467,30 @@ inline void PhysicBody::SetGravityScale(float scale)
body_->SetGravityScale(scale); body_->SetGravityScale(scale);
} }
inline float PhysicBody::GetLinearDamping() const
{
KGE_ASSERT(body_);
return body_->GetLinearDamping();
}
inline void PhysicBody::SetLinearDamping(float damping)
{
KGE_ASSERT(body_);
body_->SetLinearDamping(damping);
}
inline float PhysicBody::GetAngularDamping() const
{
KGE_ASSERT(body_);
return body_->GetAngularDamping();
}
inline void PhysicBody::SetAngularDamping(float damping)
{
KGE_ASSERT(body_);
body_->SetAngularDamping(damping);
}
inline bool PhysicBody::IsIgnoreRotation() const inline bool PhysicBody::IsIgnoreRotation() const
{ {
KGE_ASSERT(body_); KGE_ASSERT(body_);

View File

@ -26,6 +26,124 @@ namespace kiwano
namespace physics namespace physics
{ {
class PhysicWorld::DebugDrawer : public b2Draw
{
public:
DebugDrawer(const Size& size)
{
canvas_ = Canvas::Create(size);
fill_brush_ = Brush::Create(Color::White);
line_brush_ = Brush::Create(Color::White);
canvas_->SetFillBrush(fill_brush_);
canvas_->SetStrokeBrush(line_brush_);
b2Draw::SetFlags(b2Draw::e_shapeBit | b2Draw::e_jointBit | b2Draw::e_jointBit | b2Draw::e_centerOfMassBit);
}
void BeginDraw()
{
canvas_->BeginDraw();
canvas_->Clear();
}
void EndDraw()
{
canvas_->EndDraw();
}
void Render(RenderContext& ctx)
{
canvas_->OnRender(ctx);
}
void SetFillColor(const b2Color& color)
{
fill_brush_->SetColor(reinterpret_cast<const Color&>(color));
}
void SetLineColor(const b2Color& color)
{
line_brush_->SetColor(reinterpret_cast<const Color&>(color));
}
void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override
{
SetLineColor(color);
b2Vec2 p1 = vertices[vertexCount - 1];
for (int32 i = 0; i < vertexCount; ++i)
{
b2Vec2 p2 = vertices[i];
canvas_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2));
p1 = p2;
}
}
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override
{
ShapeMaker maker;
maker.BeginPath(global::WorldToLocal(vertices[0]));
for (int32 i = 1; i < vertexCount; ++i)
{
maker.AddLine(global::WorldToLocal(vertices[i]));
}
maker.EndPath(true);
SetFillColor(color);
canvas_->FillShape(maker.GetShape());
}
void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) override
{
SetLineColor(color);
canvas_->DrawCircle(global::WorldToLocal(center), global::WorldToLocal(radius));
}
void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) override
{
SetFillColor(color);
canvas_->FillCircle(global::WorldToLocal(center), global::WorldToLocal(radius));
}
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override
{
SetLineColor(color);
canvas_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2));
}
void DrawTransform(const b2Transform& xf) override
{
const float k_axisScale = 0.4f;
b2Color red(1.0f, 0.0f, 0.0f);
b2Color green(0.0f, 1.0f, 0.0f);
b2Vec2 p1 = xf.p, p2;
p2 = p1 + k_axisScale * xf.q.GetXAxis();
SetLineColor(red);
canvas_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2));
p2 = p1 + k_axisScale * xf.q.GetYAxis();
SetLineColor(green);
canvas_->DrawLine(global::WorldToLocal(p1), global::WorldToLocal(p2));
}
void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color) override
{
SetFillColor(color);
canvas_->FillCircle(global::WorldToLocal(p), global::WorldToLocal(size));
}
private:
CanvasPtr canvas_;
BrushPtr fill_brush_;
BrushPtr line_brush_;
};
class DestructionListener : public b2DestructionListener class DestructionListener : public b2DestructionListener
{ {
Function<void(b2Joint*)> joint_destruction_callback_; Function<void(b2Joint*)> joint_destruction_callback_;
@ -254,6 +372,18 @@ void PhysicWorld::OnUpdate(Duration dt)
AfterSimulation(world_actor, Matrix3x2(), 0.0f); AfterSimulation(world_actor, Matrix3x2(), 0.0f);
} }
void PhysicWorld::OnRender(RenderContext& ctx)
{
if (drawer_)
{
drawer_->BeginDraw();
world_.DrawDebugData();
drawer_->EndDraw();
drawer_->Render(ctx);
}
}
void PhysicWorld::DispatchEvent(Event* evt) void PhysicWorld::DispatchEvent(Event* evt)
{ {
Actor* actor = GetBoundActor(); Actor* actor = GetBoundActor();
@ -309,5 +439,23 @@ void PhysicWorld::AfterSimulation(Actor* parent, const Matrix3x2& parent_to_worl
} }
} }
void PhysicWorld::ShowDebugInfo(bool show)
{
if (show)
{
if (!drawer_)
{
Size size = Renderer::GetInstance().GetOutputSize();
drawer_ = std::unique_ptr<DebugDrawer>(new DebugDrawer(size));
world_.SetDebugDraw(drawer_.get());
}
}
else
{
drawer_.reset();
}
}
} // namespace physics } // namespace physics
} // namespace kiwano } // namespace kiwano

View File

@ -112,6 +112,10 @@ public:
/// @brief 设置位置迭代次数, 默认为 2 /// @brief 设置位置迭代次数, 默认为 2
void SetPositionIterations(int pos_iter); void SetPositionIterations(int pos_iter);
/// \~chinese
/// @brief 设置是否绘制调试信息
void ShowDebugInfo(bool show);
/// \~chinese /// \~chinese
/// @brief 获取b2World /// @brief 获取b2World
b2World* GetB2World(); b2World* GetB2World();
@ -129,6 +133,10 @@ protected:
/// @brief 更新组件 /// @brief 更新组件
void OnUpdate(Duration dt) override; void OnUpdate(Duration dt) override;
/// \~chinese
/// @brief 渲染组件
void OnRender(RenderContext& ctx) override;
/// \~chinese /// \~chinese
/// @brief 分发物理世界事件 /// @brief 分发物理世界事件
void DispatchEvent(Event* evt); void DispatchEvent(Event* evt);
@ -146,9 +154,13 @@ protected:
void AfterSimulation(Actor* parent, const Matrix3x2& parent_to_world, float parent_rotation); void AfterSimulation(Actor* parent, const Matrix3x2& parent_to_world, float parent_rotation);
private: private:
b2World world_; bool debug_;
int vel_iter_; int vel_iter_;
int pos_iter_; int pos_iter_;
b2World world_;
class DebugDrawer;
std::unique_ptr<DebugDrawer> drawer_;
List<PhysicBodyPtr> bodies_; List<PhysicBodyPtr> bodies_;
List<JointPtr> joints_; List<JointPtr> joints_;

View File

@ -112,6 +112,7 @@ void Actor::Render(RenderContext& ctx)
if (CheckVisibility(ctx)) if (CheckVisibility(ctx))
{ {
PrepareToRender(ctx); PrepareToRender(ctx);
RenderComponents(ctx);
OnRender(ctx); OnRender(ctx);
} }
} }
@ -131,6 +132,7 @@ void Actor::Render(RenderContext& ctx)
if (CheckVisibility(ctx)) if (CheckVisibility(ctx))
{ {
PrepareToRender(ctx); PrepareToRender(ctx);
RenderComponents(ctx);
OnRender(ctx); OnRender(ctx);
} }
@ -299,6 +301,23 @@ void Actor::UpdateComponents(Duration dt)
} }
} }
void Actor::RenderComponents(RenderContext& ctx)
{
if (!components_.IsEmpty())
{
ComponentPtr next;
for (auto component = components_.GetFirst(); component; component = next)
{
next = component->GetNext();
if (component->IsEnable())
{
component->OnRender(ctx);
}
}
}
}
const Matrix3x2& Actor::GetTransformMatrix() const const Matrix3x2& Actor::GetTransformMatrix() const
{ {
UpdateTransform(); UpdateTransform();

View File

@ -495,6 +495,10 @@ protected:
/// @brief 更新组件 /// @brief 更新组件
void UpdateComponents(Duration dt); void UpdateComponents(Duration dt);
/// \~chinese
/// @brief 渲染组件
void RenderComponents(RenderContext& ctx);
private: private:
bool visible_; bool visible_;
bool update_pausing_; bool update_pausing_;

View File

@ -32,8 +32,6 @@ CanvasPtr Canvas::Create(const Size& size)
{ {
try try
{ {
ptr->stroke_brush_ = Brush::Create(Color::White);
ptr->fill_brush_ = Brush::Create(Color::White);
ptr->ResizeAndClear(size); ptr->ResizeAndClear(size);
} }
catch (std::exception) catch (std::exception)
@ -64,7 +62,6 @@ void Canvas::OnRender(RenderContext& ctx)
{ {
if (texture_cached_) if (texture_cached_)
{ {
PrepareToRender(ctx);
ctx.DrawTexture(*texture_cached_, nullptr, &GetBounds()); ctx.DrawTexture(*texture_cached_, nullptr, &GetBounds());
} }
} }

View File

@ -22,6 +22,7 @@
#include <kiwano/core/Time.h> #include <kiwano/core/Time.h>
#include <kiwano/core/ObjectBase.h> #include <kiwano/core/ObjectBase.h>
#include <kiwano/core/IntrusiveList.h> #include <kiwano/core/IntrusiveList.h>
#include <kiwano/render/RenderContext.h>
namespace kiwano namespace kiwano
{ {
@ -80,6 +81,10 @@ protected:
/// @brief 更新组件 /// @brief 更新组件
virtual void OnUpdate(Duration dt); virtual void OnUpdate(Duration dt);
/// \~chinese
/// @brief 渲染组件
virtual void OnRender(RenderContext& ctx);
/// \~chinese /// \~chinese
/// @brief 处理角色事件 /// @brief 处理角色事件
virtual void HandleEvent(Event* evt); virtual void HandleEvent(Event* evt);
@ -109,9 +114,14 @@ inline void Component::OnUpdate(Duration dt)
KGE_NOT_USED(dt); KGE_NOT_USED(dt);
} }
inline void Component::HandleEvent(Event* event) inline void Component::OnRender(RenderContext& ctx)
{ {
KGE_NOT_USED(event); KGE_NOT_USED(ctx);
}
inline void Component::HandleEvent(Event* evt)
{
KGE_NOT_USED(evt);
} }
} // namespace kiwano } // namespace kiwano

View File

@ -110,8 +110,6 @@ void GifSprite::OnRender(RenderContext& ctx)
{ {
if (frame_to_render_ && CheckVisibility(ctx)) if (frame_to_render_ && CheckVisibility(ctx))
{ {
PrepareToRender(ctx);
ctx.DrawTexture(*frame_to_render_, nullptr, &GetBounds()); ctx.DrawTexture(*frame_to_render_, nullptr, &GetBounds());
} }
} }