diff --git a/projects/kiwano-physics/kiwano-physics.vcxproj b/projects/kiwano-physics/kiwano-physics.vcxproj
index d4888d5b..29ea6605 100644
--- a/projects/kiwano-physics/kiwano-physics.vcxproj
+++ b/projects/kiwano-physics/kiwano-physics.vcxproj
@@ -11,24 +11,25 @@
-
+
-
+
-
+
-
+
+
-
+
{DF599AFB-744F-41E5-AF0C-2146F90575C8}
diff --git a/projects/kiwano-physics/kiwano-physics.vcxproj.filters b/projects/kiwano-physics/kiwano-physics.vcxproj.filters
index df3e5d6d..6638c59c 100644
--- a/projects/kiwano-physics/kiwano-physics.vcxproj.filters
+++ b/projects/kiwano-physics/kiwano-physics.vcxproj.filters
@@ -2,22 +2,23 @@
-
-
-
+
+
+
-
-
+
+
+
\ No newline at end of file
diff --git a/src/kiwano-physics/Body.cpp b/src/kiwano-physics/Body.cpp
deleted file mode 100644
index 50f43465..00000000
--- a/src/kiwano-physics/Body.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-// Copyright (c) 2018-2019 Kiwano - Nomango
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include
-#include
-
-namespace kiwano
-{
-namespace physics
-{
-
-BodyPtr Body::Create(World* world, Actor* actor, Type type)
-{
- BodyPtr ptr = new (std::nothrow) Body;
- if (ptr)
- {
- if (!ptr->InitBody(world, actor))
- return nullptr;
-
- ptr->SetType(type);
- }
- return ptr;
-}
-
-Body::Body()
- : body_(nullptr)
- , actor_(nullptr)
- , world_(nullptr)
- , category_bits_(0x0001)
- , mask_bits_(0xFFFF)
- , group_index_(0)
-{
-}
-
-Body::~Body()
-{
- Destroy();
-}
-
-bool Body::InitBody(World* world, Actor* actor)
-{
- KGE_ASSERT(world);
-
- Destroy();
-
- world_ = world;
- b2BodyDef def;
- b2Body* b2body = world->GetB2World()->CreateBody(&def);
-
- if (b2body)
- {
- SetB2Body(b2body);
- SetActor(actor);
- UpdateFromActor();
- return true;
- }
- return false;
-}
-
-void Body::AddFixture(FixturePtr fixture)
-{
- fixtures_.push_back(fixture);
-}
-
-Fixture* Body::AddCircleShape(float radius, float density, float friction, float restitution, bool is_sensor)
-{
- Fixture::Param param(density, friction, restitution, is_sensor);
- FixturePtr fixture = Fixture::CreateCircle(this, param, radius);
- AddFixture(fixture);
- return fixture.Get();
-}
-
-Fixture* Body::AddRectShape(Vec2 const& size, float density, float friction, float restitution, bool is_sensor)
-{
- Fixture::Param param(density, friction, restitution, is_sensor);
- FixturePtr fixture = Fixture::CreateRect(this, param, size);
- AddFixture(fixture);
- return fixture.Get();
-}
-
-Fixture* Body::AddPolygonShape(Vector const& vertexs, float density, float friction, float restitution,
- bool is_sensor)
-{
- Fixture::Param param(density, friction, restitution, is_sensor);
- FixturePtr fixture = Fixture::CreatePolygon(this, param, vertexs);
- AddFixture(fixture);
- return fixture.Get();
-}
-
-Fixture* Body::AddEdgeShape(Point const& p1, Point const& p2, float density, float friction, float restitution,
- bool is_sensor)
-{
- Fixture::Param param(density, friction, restitution, is_sensor);
- FixturePtr fixture = Fixture::CreateEdge(this, param, p1, p2);
- AddFixture(fixture);
- return fixture.Get();
-}
-
-Fixture* Body::AddChainShape(Vector const& vertexs, bool loop, float density, float friction, float restitution,
- bool is_sensor)
-{
- Fixture::Param param(density, friction, restitution, is_sensor);
- FixturePtr fixture = Fixture::CreateChain(this, param, vertexs, loop);
- AddFixture(fixture);
- return fixture.Get();
-}
-
-void Body::RemoveFixture(FixturePtr fixture)
-{
- if (fixture)
- {
- body_->DestroyFixture(fixture->GetB2Fixture());
-
- for (auto iter = fixtures_.begin(); iter != fixtures_.end();)
- {
- if (*iter == fixture)
- iter = fixtures_.erase(iter);
- else
- ++iter;
- }
- }
-}
-
-void Body::SetCategoryBits(uint16_t category_bits)
-{
- KGE_ASSERT(body_);
-
- if (category_bits != category_bits_)
- {
- category_bits_ = category_bits;
-
- b2Fixture* fixture = body_->GetFixtureList();
- while (fixture)
- {
- UpdateFixtureFilter(fixture);
- fixture = fixture->GetNext();
- }
- }
-}
-
-void Body::SetMaskBits(uint16_t mask_bits)
-{
- KGE_ASSERT(body_);
-
- if (mask_bits != mask_bits_)
- {
- mask_bits_ = mask_bits;
-
- b2Fixture* fixture = body_->GetFixtureList();
- while (fixture)
- {
- UpdateFixtureFilter(fixture);
- fixture = fixture->GetNext();
- }
- }
-}
-
-void Body::SetGroupIndex(int16_t index)
-{
- KGE_ASSERT(body_);
-
- if (index != group_index_)
- {
- group_index_ = index;
-
- b2Fixture* fixture = body_->GetFixtureList();
- while (fixture)
- {
- UpdateFixtureFilter(fixture);
- fixture = fixture->GetNext();
- }
- }
-}
-
-void Body::GetMassData(float* mass, Point* center, float* inertia) const
-{
- KGE_ASSERT(body_ && world_);
-
- b2MassData data;
- body_->GetMassData(&data);
-
- if (mass)
- *mass = data.mass;
- if (center)
- *center = world_->World2Stage(data.center);
- if (inertia)
- *inertia = data.I;
-}
-
-void Body::SetMassData(float mass, Point const& center, float inertia)
-{
- KGE_ASSERT(body_ && world_);
-
- b2MassData data;
- data.mass = mass;
- data.center = world_->Stage2World(center);
- data.I = inertia;
- body_->SetMassData(&data);
-}
-
-void Body::ResetMassData()
-{
- KGE_ASSERT(body_);
- body_->ResetMassData();
-}
-
-Point Body::GetBodyPosition() const
-{
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetPosition());
-}
-
-void Body::SetBodyTransform(Point const& pos, float angle)
-{
- KGE_ASSERT(body_ && world_);
- body_->SetTransform(world_->Stage2World(pos), math::Degree2Radian(angle));
-}
-
-Point Body::GetLocalPoint(Point const& world) const
-{
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetLocalPoint(world_->Stage2World(world)));
-}
-
-Point Body::GetWorldPoint(Point const& local) const
-{
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetWorldPoint(world_->Stage2World(local)));
-}
-
-Point Body::GetLocalCenter() const
-{
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetLocalCenter());
-}
-
-Point Body::GetWorldCenter() const
-{
- KGE_ASSERT(body_ && world_);
- return world_->World2Stage(body_->GetWorldCenter());
-}
-
-void Body::ApplyForce(Vec2 const& force, Point const& point, bool wake)
-{
- KGE_ASSERT(body_ && world_);
- body_->ApplyForce(b2Vec2(force.x, force.y), world_->Stage2World(point), wake);
-}
-
-void Body::ApplyForceToCenter(Vec2 const& force, bool wake)
-{
- KGE_ASSERT(body_ && world_);
- body_->ApplyForceToCenter(b2Vec2(force.x, force.y), wake);
-}
-
-void Body::ApplyTorque(float torque, bool wake)
-{
- KGE_ASSERT(body_ && world_);
- body_->ApplyTorque(torque, wake);
-}
-
-void Body::SetB2Body(b2Body* body)
-{
- body_ = body;
- if (body_)
- {
- body_->SetUserData(this);
- }
-}
-
-void Body::Destroy()
-{
- fixtures_.clear();
-
- if (world_)
- {
- world_->RemoveBody(this);
- }
-
- body_ = nullptr;
- world_ = nullptr;
- actor_ = nullptr;
-}
-
-void Body::UpdateActor()
-{
- if (actor_ && body_)
- {
- if (world_)
- {
- actor_->SetPosition(world_->World2Stage(body_->GetPosition()));
- }
- else
- {
- actor_->SetPosition(World2Stage(body_->GetPosition()));
- }
- actor_->SetRotation(math::Radian2Degree(body_->GetAngle()));
- }
-}
-
-void Body::UpdateFromActor()
-{
- if (actor_ && body_)
- {
- if (world_)
- {
- body_->SetTransform(world_->Stage2World(actor_->GetPosition()), math::Degree2Radian(actor_->GetRotation()));
- }
- else
- {
- body_->SetTransform(Stage2World(actor_->GetPosition()), math::Degree2Radian(actor_->GetRotation()));
- }
- }
-}
-
-void Body::UpdateFixtureFilter(b2Fixture* fixture)
-{
- b2Filter filter;
- filter.categoryBits = category_bits_;
- filter.maskBits = mask_bits_;
- filter.groupIndex = group_index_;
- fixture->SetFilterData(filter);
-}
-
-} // namespace physics
-} // namespace kiwano
diff --git a/src/kiwano-physics/Contact.cpp b/src/kiwano-physics/Contact.cpp
index 072bb8c9..80e63a36 100644
--- a/src/kiwano-physics/Contact.cpp
+++ b/src/kiwano-physics/Contact.cpp
@@ -18,9 +18,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include
+#include
#include
-#include
+#include
namespace kiwano
{
@@ -48,12 +48,12 @@ Fixture* Contact::GetFixtureB() const
return fixture;
}
-Body* Contact::GetBodyA() const
+PhysicBody* Contact::GetBodyA() const
{
return GetFixtureA()->GetBody();
}
-Body* Contact::GetBodyB() const
+PhysicBody* Contact::GetBodyB() const
{
return GetFixtureB()->GetBody();
}
@@ -61,27 +61,13 @@ Body* Contact::GetBodyB() const
void Contact::SetTangentSpeed(float speed)
{
KGE_ASSERT(contact_);
-
- Body* body = GetFixtureA()->GetBody();
- KGE_ASSERT(body);
-
- World* world = body->GetWorld();
- KGE_ASSERT(world);
-
- contact_->SetTangentSpeed(world->Stage2World(speed));
+ contact_->SetTangentSpeed(global::ToMeters(speed));
}
float Contact::GetTangentSpeed() const
{
KGE_ASSERT(contact_);
-
- const Body* body = GetFixtureA()->GetBody();
- KGE_ASSERT(body);
-
- const World* world = body->GetWorld();
- KGE_ASSERT(world);
-
- return world->World2Stage(contact_->GetTangentSpeed());
+ return global::ToPixels(contact_->GetTangentSpeed());
}
} // namespace physics
diff --git a/src/kiwano-physics/Contact.h b/src/kiwano-physics/Contact.h
index 5598cf57..41605438 100644
--- a/src/kiwano-physics/Contact.h
+++ b/src/kiwano-physics/Contact.h
@@ -20,13 +20,11 @@
#pragma once
#include
-#include
namespace kiwano
{
namespace physics
{
-class Body;
/**
* \addtogroup Physics
@@ -40,10 +38,6 @@ class KGE_API Contact
public:
Contact();
- /// \~chinese
- /// @brief 是否有效
- bool IsValid() const;
-
/// \~chinese
/// @brief 是否是接触
bool IsTouching() const;
@@ -66,11 +60,11 @@ public:
/// \~chinese
/// @brief 获取物体A
- Body* GetBodyA() const;
+ PhysicBody* GetBodyA() const;
/// \~chinese
/// @brief 获取物体B
- Body* GetBodyB() const;
+ PhysicBody* GetBodyB() const;
/// \~chinese
/// @brief 设置摩擦力
@@ -104,8 +98,12 @@ public:
/// @brief 获取切线速度
float GetTangentSpeed() const;
+ /// \~chinese
+ /// @brief 获取b2Contact
b2Contact* GetB2Contact() const;
+ /// \~chinese
+ /// @brief 设置b2Contact
void SetB2Contact(b2Contact* contact);
bool operator==(const Contact& rhs) const;
@@ -120,29 +118,33 @@ private:
class ContactList
{
template
- class IteratorImpl : public std::iterator
+ class IteratorImpl
{
- using herit = std::iterator;
-
public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = _Ty;
+ using pointer = _Ty*;
+ using reference = _Ty&;
+ using difference_type = ptrdiff_t;
+
IteratorImpl(const _Ty& elem)
: elem_(elem)
{
}
- inline typename herit::reference operator*() const
+ inline reference operator*() const
{
- return const_cast(elem_);
+ return const_cast(elem_);
}
- inline typename herit::pointer operator->() const
+ inline pointer operator->() const
{
- return std::pointer_traits::pointer_to(**this);
+ return std::pointer_traits::pointer_to(**this);
}
inline IteratorImpl& operator++()
{
- elem_ = elem_.GetB2Contact()->GetNext();
+ elem_.SetB2Contact(elem_.GetB2Contact()->GetNext());
return *this;
}
@@ -225,67 +227,75 @@ private:
/** @} */
-inline bool Contact::IsValid() const
-{
- return contact_ != nullptr;
-}
inline bool Contact::IsTouching() const
{
KGE_ASSERT(contact_);
return contact_->IsTouching();
}
+
inline void Contact::SetEnabled(bool flag)
{
KGE_ASSERT(contact_);
contact_->SetEnabled(flag);
}
+
inline bool Contact::IsEnabled() const
{
KGE_ASSERT(contact_);
return contact_->IsEnabled();
}
+
inline void Contact::SetFriction(float friction)
{
KGE_ASSERT(contact_);
contact_->SetFriction(friction);
}
+
inline float Contact::GetFriction() const
{
KGE_ASSERT(contact_);
return contact_->GetFriction();
}
+
inline void Contact::ResetFriction()
{
KGE_ASSERT(contact_);
contact_->ResetFriction();
}
+
inline void Contact::SetRestitution(float restitution)
{
KGE_ASSERT(contact_);
contact_->SetRestitution(restitution);
}
+
inline float Contact::GetRestitution() const
{
KGE_ASSERT(contact_);
return contact_->GetRestitution();
}
+
inline void Contact::ResetRestitution()
{
KGE_ASSERT(contact_);
contact_->ResetRestitution();
}
+
inline b2Contact* Contact::GetB2Contact() const
{
return contact_;
}
+
inline void Contact::SetB2Contact(b2Contact* contact)
{
contact_ = contact;
}
+
inline bool Contact::operator==(const Contact& rhs) const
{
return contact_ == rhs.contact_;
}
+
inline bool Contact::operator!=(const Contact& rhs) const
{
return contact_ != rhs.contact_;
diff --git a/src/kiwano-physics/ContactEdge.cpp b/src/kiwano-physics/ContactEdge.cpp
index 9de13ff3..d75b4d04 100644
--- a/src/kiwano-physics/ContactEdge.cpp
+++ b/src/kiwano-physics/ContactEdge.cpp
@@ -30,10 +30,13 @@ ContactEdge::ContactEdge()
{
}
-ContactEdge::ContactEdge(b2ContactEdge* edge)
- : ContactEdge()
+Contact ContactEdge::GetContact() const
{
- SetB2ContactEdge(edge);
+ KGE_ASSERT(edge_);
+
+ Contact contact;
+ contact.SetB2Contact(edge_->contact);
+ return contact;
}
} // namespace physics
diff --git a/src/kiwano-physics/ContactEdge.h b/src/kiwano-physics/ContactEdge.h
index d43b8cbd..e62deef0 100644
--- a/src/kiwano-physics/ContactEdge.h
+++ b/src/kiwano-physics/ContactEdge.h
@@ -37,22 +37,20 @@ class KGE_API ContactEdge
public:
ContactEdge();
- ContactEdge(b2ContactEdge* edge);
-
- /// \~chinese
- /// @brief 是否有效
- bool IsValid() const;
-
/// \~chinese
/// @brief 获取接触物体
- Body* GetOtherBody() const;
+ PhysicBody* GetOtherBody() const;
/// \~chinese
/// @brief 获取接触
Contact GetContact() const;
+ /// \~chinese
+ /// @brief 获取b2ContactEdge
b2ContactEdge* GetB2ContactEdge() const;
+ /// \~chinese
+ /// @brief 设置b2ContactEdge
void SetB2ContactEdge(b2ContactEdge* edge);
bool operator==(const ContactEdge& rhs) const;
@@ -67,36 +65,40 @@ private:
class ContactEdgeList
{
template
- class IteratorImpl : public std::iterator
+ class IteratorImpl
{
- using herit = std::iterator;
-
public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = _Ty;
+ using pointer = _Ty*;
+ using reference = _Ty&;
+ using difference_type = ptrdiff_t;
+
inline IteratorImpl(const _Ty& elem)
: elem_(elem)
{
}
- inline typename herit::reference operator*() const
+ inline reference operator*() const
{
- return const_cast(elem_);
+ return const_cast(elem_);
}
- inline typename herit::pointer operator->() const
+ inline pointer operator->() const
{
- return std::pointer_traits::pointer_to(**this);
+ return std::pointer_traits::pointer_to(**this);
}
inline IteratorImpl& operator++()
{
- elem_ = elem_.GetB2ContactEdge()->next;
+ elem_.SetB2ContactEdge(elem_.GetB2ContactEdge()->next);
return *this;
}
inline IteratorImpl operator++(int)
{
IteratorImpl old = *this;
- operator++();
+ operator++();
return old;
}
@@ -153,7 +155,7 @@ public:
inline iterator end()
{
- return iterator(nullptr);
+ return iterator(ContactEdge());
}
inline const_iterator end() const
@@ -163,7 +165,7 @@ public:
inline const_iterator cend() const
{
- return const_iterator(nullptr);
+ return const_iterator(ContactEdge());
}
private:
@@ -172,24 +174,10 @@ private:
/** @} */
-inline bool ContactEdge::IsValid() const
-{
- return edge_ != nullptr;
-}
-
-inline Body* ContactEdge::GetOtherBody() const
+inline PhysicBody* ContactEdge::GetOtherBody() const
{
KGE_ASSERT(edge_);
- return static_cast(edge_->other->GetUserData());
-}
-
-inline Contact ContactEdge::GetContact() const
-{
- KGE_ASSERT(edge_);
-
- Contact contact;
- contact.SetB2Contact(edge_->contact);
- return contact;
+ return static_cast(edge_->other->GetUserData());
}
inline b2ContactEdge* ContactEdge::GetB2ContactEdge() const
diff --git a/src/kiwano-physics/ContactEvent.h b/src/kiwano-physics/ContactEvent.h
index d19f0262..eee6a1a7 100644
--- a/src/kiwano-physics/ContactEvent.h
+++ b/src/kiwano-physics/ContactEvent.h
@@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
-#include
+#include
#include
namespace kiwano
diff --git a/src/kiwano-physics/Fixture.cpp b/src/kiwano-physics/Fixture.cpp
index 51e20a2b..48d5116e 100644
--- a/src/kiwano-physics/Fixture.cpp
+++ b/src/kiwano-physics/Fixture.cpp
@@ -18,127 +18,111 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include
+#include
#include
-#include
+#include
namespace kiwano
{
namespace physics
{
-namespace
+FixturePtr Fixture::CreateCircle(Param const& param, float radius, Point const& offset)
{
-
-FixturePtr CreateFixture(Body* body, b2Shape* shape, const Fixture::Param& param)
-{
- KGE_ASSERT(body);
-
- b2Body* b2body = body->GetB2Body();
- KGE_ASSERT(b2body);
-
- b2FixtureDef fd;
- fd.density = param.density;
- fd.friction = param.friction;
- fd.restitution = param.restitution;
- fd.shape = shape;
-
FixturePtr ptr = new (std::nothrow) Fixture;
if (ptr)
{
- b2Fixture* fixture = b2body->CreateFixture(&fd);
- if (fixture)
+ auto shape = std::make_unique();
+ shape->m_radius = global::ToMeters(radius);
+ shape->m_p = global::ToMeters(offset);
+
+ ptr->shape_ = std::move(shape);
+ ptr->param_ = param;
+ }
+ return ptr;
+}
+
+FixturePtr Fixture::CreateRect(Param const& param, Size const& size, Point const& offset, float rotation)
+{
+ FixturePtr ptr = new (std::nothrow) Fixture;
+ if (ptr)
+ {
+ b2Vec2 b2size = global::ToMeters(size);
+ b2Vec2 b2offset = global::ToMeters(offset);
+
+ auto shape = std::make_unique();
+ shape->SetAsBox(b2size.x / 2, b2size.y / 2, b2offset, math::Degree2Radian(rotation));
+
+ ptr->shape_ = std::move(shape);
+ ptr->param_ = param;
+ }
+ return ptr;
+}
+
+FixturePtr Fixture::CreatePolygon(Param const& param, Vector const& vertexs)
+{
+ FixturePtr ptr = new (std::nothrow) Fixture;
+ if (ptr)
+ {
+ Vector b2vertexs;
+ b2vertexs.reserve(vertexs.size());
+ for (const auto& v : vertexs)
{
- fixture->SetUserData(ptr.Get());
- ptr->SetB2Fixture(fixture);
- return ptr;
+ b2vertexs.push_back(global::ToMeters(v));
}
+
+ auto shape = std::make_unique();
+ shape->Set(&b2vertexs[0], static_cast(b2vertexs.size()));
+
+ ptr->shape_ = std::move(shape);
+ ptr->param_ = param;
}
- return nullptr;
+ return ptr;
}
-} // namespace
-
-FixturePtr Fixture::CreateCircle(Body* body, Param const& param, float radius, Point const& offset)
+FixturePtr Fixture::CreateEdge(Param const& param, Point const& p1, Point const& p2)
{
- KGE_ASSERT(body);
- World* world = body->GetWorld();
-
- b2CircleShape shape;
- shape.m_radius = world->Stage2World(radius);
- shape.m_p = world->Stage2World(offset);
-
- return CreateFixture(body, &shape, param);
-}
-
-FixturePtr Fixture::CreateRect(Body* body, Param const& param, Size const& size, Point const& offset, float rotation)
-{
- KGE_ASSERT(body);
- World* world = body->GetWorld();
-
- b2Vec2 b2size = world->Stage2World(size);
- b2Vec2 b2offset = world->Stage2World(offset);
-
- b2PolygonShape shape;
- shape.SetAsBox(b2size.x / 2, b2size.y / 2, b2offset, math::Degree2Radian(rotation));
-
- return CreateFixture(body, &shape, param);
-}
-
-FixturePtr Fixture::CreatePolygon(Body* body, Param const& param, Vector const& vertexs)
-{
- KGE_ASSERT(body);
- World* world = body->GetWorld();
-
- Vector b2vertexs;
- b2vertexs.reserve(vertexs.size());
- for (const auto& v : vertexs)
+ FixturePtr ptr = new (std::nothrow) Fixture;
+ if (ptr)
{
- b2vertexs.push_back(world->Stage2World(v));
+ b2Vec2 start = global::ToMeters(p1);
+ b2Vec2 end = global::ToMeters(p2);
+
+ auto shape = std::make_unique();
+ shape->Set(start, end);
+
+ ptr->shape_ = std::move(shape);
+ ptr->param_ = param;
}
-
- b2PolygonShape shape;
- shape.Set(&b2vertexs[0], static_cast(b2vertexs.size()));
-
- return CreateFixture(body, &shape, param);
+ return ptr;
}
-FixturePtr Fixture::CreateEdge(Body* body, Param const& param, Point const& p1, Point const& p2)
+FixturePtr Fixture::CreateChain(Param const& param, Vector const& vertexs, bool loop)
{
- KGE_ASSERT(body);
- World* world = body->GetWorld();
-
- b2Vec2 start = world->Stage2World(p1);
- b2Vec2 end = world->Stage2World(p2);
-
- b2EdgeShape shape;
- shape.Set(start, end);
-
- return CreateFixture(body, &shape, param);
-}
-
-FixturePtr Fixture::CreateChain(Body* body, Param const& param, Vector const& vertexs, bool loop)
-{
- KGE_ASSERT(body);
- World* world = body->GetWorld();
-
- Vector b2vertexs;
- b2vertexs.reserve(vertexs.size());
- for (const auto& v : vertexs)
+ FixturePtr ptr = new (std::nothrow) Fixture;
+ if (ptr)
{
- b2vertexs.push_back(world->Stage2World(v));
- }
+ Vector b2vertexs;
+ b2vertexs.reserve(vertexs.size());
+ for (const auto& v : vertexs)
+ {
+ b2vertexs.push_back(global::ToMeters(v));
+ }
- b2ChainShape shape;
- if (loop)
- {
- shape.CreateLoop(&b2vertexs[0], static_cast(b2vertexs.size()));
+ auto shape = std::make_unique();
+ if (loop)
+ {
+ shape->CreateLoop(&b2vertexs[0], static_cast(b2vertexs.size()));
+ }
+ else
+ {
+ shape->CreateChain(&b2vertexs[0], static_cast(b2vertexs.size()));
+ }
+
+ ptr->shape_ = std::move(shape);
+ ptr->param_ = param;
}
- else
- {
- shape.CreateChain(&b2vertexs[0], static_cast(b2vertexs.size()));
- }
- return CreateFixture(body, &shape, param);
+ return ptr;
}
Fixture::Fixture()
@@ -148,40 +132,64 @@ Fixture::Fixture()
Fixture::~Fixture()
{
- if (fixture_)
- {
- b2Body* body = fixture_->GetBody();
- if (body)
- {
- body->DestroyFixture(fixture_);
- }
- }
}
-Body* Fixture::GetBody() const
+bool Fixture::Init(PhysicBodyPtr body)
+{
+ return this->Init(body.Get());
+}
+
+bool Fixture::Init(PhysicBody* body)
+{
+ KGE_ASSERT(fixture_ == nullptr);
+ KGE_ASSERT(body);
+
+ if (body)
+ {
+ b2Body* b2body = body->GetB2Body();
+ if (b2body == nullptr)
+ {
+ // lazy init
+ return true;
+ }
+
+ b2FixtureDef fd;
+ fd.density = param_.density;
+ fd.friction = param_.friction;
+ fd.restitution = param_.restitution;
+ fd.isSensor = param_.is_sensor;
+ fd.shape = shape_.get();
+
+ b2Fixture* fixture = b2body->CreateFixture(&fd);
+ if (fixture)
+ {
+ this->SetB2Fixture(fixture);
+
+ // Don't need shape any more, b2Fixture already has a clone
+ shape_.reset();
+ return true;
+ }
+ }
+ return false;
+}
+
+PhysicBody* Fixture::GetBody() const
{
- fixture_->GetShape();
KGE_ASSERT(fixture_);
- return static_cast(fixture_->GetBody()->GetUserData());
+ return static_cast(fixture_->GetBody()->GetUserData());
}
void Fixture::GetMassData(float* mass, Point* center, float* inertia) const
{
KGE_ASSERT(fixture_);
- const Body* body = GetBody();
- KGE_ASSERT(body);
-
- const World* world = body->GetWorld();
- KGE_ASSERT(world);
-
b2MassData data;
fixture_->GetMassData(&data);
if (mass)
*mass = data.mass;
if (center)
- *center = world->World2Stage(data.center);
+ *center = global::ToPixels(data.center);
if (inertia)
*inertia = data.I;
}
@@ -189,14 +197,20 @@ void Fixture::GetMassData(float* mass, Point* center, float* inertia) const
bool Fixture::TestPoint(const Point& p) const
{
KGE_ASSERT(fixture_);
+ return fixture_->TestPoint(global::ToMeters(p));
+}
- const Body* body = GetBody();
- KGE_ASSERT(body);
-
- const World* world = body->GetWorld();
- KGE_ASSERT(world);
-
- return fixture_->TestPoint(world->Stage2World(p));
+void Fixture::Destroy()
+{
+ if (fixture_)
+ {
+ b2Body* body = fixture_->GetBody();
+ if (body)
+ {
+ body->DestroyFixture(fixture_);
+ }
+ fixture_ = nullptr;
+ }
}
} // namespace physics
diff --git a/src/kiwano-physics/Fixture.h b/src/kiwano-physics/Fixture.h
index b8c261fa..9a71414e 100644
--- a/src/kiwano-physics/Fixture.h
+++ b/src/kiwano-physics/Fixture.h
@@ -19,13 +19,13 @@
// THE SOFTWARE.
#pragma once
-#include
+#include
+#include
namespace kiwano
{
namespace physics
{
-class Body;
KGE_DECLARE_SMART_PTR(Fixture);
@@ -61,56 +61,55 @@ public:
/// \~chinese
/// @brief 创建圆形夹具
- /// @param body 添加夹具的物体
/// @param param 夹具参数
/// @param radius 圆形半径
/// @param offset 偏移量
- static FixturePtr CreateCircle(Body* body, Param const& param, float radius, Point const& offset = Point());
+ static FixturePtr CreateCircle(Param const& param, float radius, Point const& offset = Point());
/// \~chinese
/// @brief 创建矩形夹具
- /// @param body 添加夹具的物体
/// @param param 夹具参数
/// @param size 矩形大小
/// @param offset 偏移量
/// @param rotation 旋转角度
- static FixturePtr CreateRect(Body* body, Param const& param, Size const& size, Point const& offset = Point(),
+ static FixturePtr CreateRect(Param const& param, Size const& size, Point const& offset = Point(),
float rotation = 0.f);
/// \~chinese
/// @brief 创建多边形夹具
- /// @param body 添加夹具的物体
/// @param param 夹具参数
/// @param vertexs 多边形顶点
- static FixturePtr CreatePolygon(Body* body, Param const& param, Vector const& vertexs);
+ static FixturePtr CreatePolygon(Param const& param, Vector const& vertexs);
/// \~chinese
/// @brief 创建边夹具
- /// @param body 添加夹具的物体
/// @param param 夹具参数
/// @param p1 边的起点
/// @param p2 边的终点
- static FixturePtr CreateEdge(Body* body, Param const& param, Point const& p1, Point const& p2);
+ static FixturePtr CreateEdge(Param const& param, Point const& p1, Point const& p2);
/// \~chinese
/// @brief 创建链条夹具
- /// @param body 添加夹具的物体
/// @param param 夹具参数
/// @param vertexs 链条顶点
/// @param loop 是否连接链条的起点和终点
- static FixturePtr CreateChain(Body* body, Param const& param, Vector const& vertexs, bool loop = false);
+ static FixturePtr CreateChain(Param const& param, Vector const& vertexs, bool loop = false);
Fixture();
virtual ~Fixture();
/// \~chinese
- /// @brief 是否有效
- bool IsValid() const;
+ /// @brief 初始化夹具
+ bool Init(PhysicBodyPtr body);
+
+ /// \~chinese
+ /// @brief 初始化夹具
+ bool Init(PhysicBody* body);
/// \~chinese
/// @brief 获取夹具所在的物体
- Body* GetBody() const;
+ PhysicBody* GetBody() const;
/// \~chinese
/// @brief 是否是接触传感器
@@ -153,15 +152,25 @@ public:
/// @brief 点测试
bool TestPoint(const Point& p) const;
+ /// \~chinese
+ /// @brief 销毁夹具
+ void Destroy();
+
+ /// \~chinese
+ /// @brief 获取b2Fixture
b2Fixture* GetB2Fixture() const;
+ /// \~chinese
+ /// @brief 设置b2Fixture
void SetB2Fixture(b2Fixture* fixture);
bool operator==(const Fixture& rhs) const;
bool operator!=(const Fixture& rhs) const;
private:
- b2Fixture* fixture_;
+ b2Fixture* fixture_;
+ std::unique_ptr shape_;
+ Fixture::Param param_;
};
/// \~chinese
@@ -169,13 +178,14 @@ private:
class FixtureList
{
template
- class IteratorImpl : public std::iterator
+ class IteratorImpl
{
- using herit = std::iterator;
-
public:
- using reference = typename herit::reference;
- using pointer = typename herit::pointer;
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = _Ty;
+ using pointer = _Ty*;
+ using reference = _Ty&;
+ using difference_type = ptrdiff_t;
IteratorImpl(pointer elem)
: elem_(elem)
@@ -184,12 +194,12 @@ class FixtureList
inline reference operator*() const
{
- return const_cast(*elem_);
+ return const_cast(*elem_);
}
inline pointer operator->() const
{
- return std::pointer_traits::pointer_to(**this);
+ return std::pointer_traits::pointer_to(**this);
}
inline IteratorImpl& operator++()
@@ -203,7 +213,6 @@ class FixtureList
inline IteratorImpl operator++(int)
{
IteratorImpl old = *this;
-
operator++();
return old;
}
@@ -224,6 +233,8 @@ class FixtureList
public:
using value_type = Fixture;
+ using reference = value_type&;
+ using pointer = value_type*;
using iterator = IteratorImpl;
using const_iterator = IteratorImpl;
@@ -232,7 +243,7 @@ public:
{
}
- inline FixtureList(value_type* first)
+ inline FixtureList(pointer first)
: first_(first)
{
}
@@ -278,62 +289,77 @@ public:
}
private:
- value_type* first_;
+ pointer first_;
};
/** @} */
inline bool Fixture::IsSensor() const
{
- KGE_ASSERT(fixture_);
- return fixture_->IsSensor();
+ return param_.is_sensor;
}
inline void Fixture::SetSensor(bool sensor)
{
- KGE_ASSERT(fixture_);
- fixture_->SetSensor(sensor);
+ if (param_.is_sensor != sensor)
+ {
+ param_.is_sensor = sensor;
+ if (fixture_)
+ {
+ fixture_->SetSensor(sensor);
+ }
+ }
}
inline float Fixture::GetDensity() const
{
- KGE_ASSERT(fixture_);
- return fixture_->GetDensity();
+ return param_.density;
}
inline void Fixture::SetDensity(float density)
{
- KGE_ASSERT(fixture_);
- fixture_->SetDensity(density);
+ if (param_.density != density)
+ {
+ param_.density = density;
+ if (fixture_)
+ {
+ fixture_->SetDensity(density);
+ }
+ }
}
inline float Fixture::GetFriction() const
{
- KGE_ASSERT(fixture_);
- return fixture_->GetFriction();
+ return param_.friction;
}
inline void Fixture::SetFriction(float friction)
{
- KGE_ASSERT(fixture_);
- fixture_->SetFriction(friction);
+ if (param_.friction != friction)
+ {
+ param_.friction = friction;
+ if (fixture_)
+ {
+ fixture_->SetFriction(friction);
+ }
+ }
}
inline float Fixture::GetRestitution() const
{
- KGE_ASSERT(fixture_);
- return fixture_->GetRestitution();
+ return param_.restitution;
}
inline void Fixture::SetRestitution(float restitution)
{
- KGE_ASSERT(fixture_);
- fixture_->SetRestitution(restitution);
-}
-
-inline bool Fixture::IsValid() const
-{
- return fixture_ != nullptr;
+ if (param_.restitution != restitution)
+ {
+ param_.restitution = restitution;
+ if (fixture_)
+ {
+ fixture_->SetRestitution(restitution);
+ }
+ }
}
inline b2Fixture* Fixture::GetB2Fixture() const
@@ -344,6 +370,10 @@ inline b2Fixture* Fixture::GetB2Fixture() const
inline void Fixture::SetB2Fixture(b2Fixture* fixture)
{
fixture_ = fixture;
+ if (fixture)
+ {
+ fixture->SetUserData(this);
+ }
}
inline bool Fixture::operator==(const Fixture& rhs) const
diff --git a/src/kiwano-physics/helper.h b/src/kiwano-physics/Global.cpp
similarity index 68%
rename from src/kiwano-physics/helper.h
rename to src/kiwano-physics/Global.cpp
index f3be4fbf..3bc64dc6 100644
--- a/src/kiwano-physics/helper.h
+++ b/src/kiwano-physics/Global.cpp
@@ -19,22 +19,51 @@
// THE SOFTWARE.
#pragma once
-#include
-
-// Box2D
-#include <3rd-party/Box2D/Box2D.h>
+#include
namespace kiwano
{
namespace physics
{
-inline b2Vec2 Stage2World(const Vec2& pos)
+namespace global
{
- return b2Vec2(pos.x, pos.y);
-}
-inline Vec2 World2Stage(const b2Vec2& pos)
+
+namespace
{
- return Vec2(pos.x, pos.y);
+float global_scale = 100.f; // 100 pixels per meters
}
+
+float GetScale()
+{
+ return global_scale;
+}
+
+void SetScale(float scale)
+{
+ global_scale = scale;
+}
+
+float ToPixels(float value)
+{
+ return value * global_scale;
+}
+
+Vec2 ToPixels(const b2Vec2& pos)
+{
+ return Point(ToPixels(pos.x), ToPixels(pos.y));
+}
+
+float ToMeters(float value)
+{
+ return value / global_scale;
+}
+
+b2Vec2 ToMeters(const Vec2& pos)
+{
+ return b2Vec2(ToMeters(pos.x), ToMeters(pos.y));
+}
+
+} // namespace global
+
} // namespace physics
} // namespace kiwano
diff --git a/src/kiwano-physics/Global.h b/src/kiwano-physics/Global.h
new file mode 100644
index 00000000..0fbaeffd
--- /dev/null
+++ b/src/kiwano-physics/Global.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2018-2019 Kiwano - Nomango
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#pragma once
+#include
+
+// Box2D
+#include <3rd-party/Box2D/Box2D.h>
+
+namespace kiwano
+{
+namespace physics
+{
+
+KGE_DECLARE_SMART_PTR(PhysicWorld);
+KGE_DECLARE_SMART_PTR(PhysicBody);
+
+namespace global
+{
+
+/// \~chinese
+/// @brief 获取全局缩放比例
+/// @details 缩放比例是指由物理世界的单位米转换到屏幕像素的比例,默认比例为1:100
+float GetScale();
+
+/// \~chinese
+/// @brief 设置全局缩放比例
+/// @details 缩放比例是指由物理世界的单位米转换到屏幕像素的比例,默认比例为1:100
+void SetScale(float scale);
+
+/// \~chinese
+/// @brief 游戏世界单位转换为物理世界单位
+/// @details 根据全局缩放比例将物理世界的单位米转换为像素单位
+float ToPixels(float value);
+
+/// \~chinese
+/// @brief 游戏世界单位转换为物理世界单位
+/// @details 根据全局缩放比例将物理世界的单位米转换为像素单位
+Vec2 ToPixels(const b2Vec2& pos);
+
+/// \~chinese
+/// @brief 物理世界单位转换为游戏世界单位
+/// @details 根据全局缩放比例将像素单位转换为物理世界的单位米
+float ToMeters(float value);
+
+/// \~chinese
+/// @brief 物理世界单位转换为游戏世界单位
+/// @details 根据全局缩放比例将像素单位转换为物理世界的单位米
+b2Vec2 ToMeters(const Vec2& pos);
+
+} // namespace global
+} // namespace physics
+} // namespace kiwano
diff --git a/src/kiwano-physics/Joint.cpp b/src/kiwano-physics/Joint.cpp
index 08462be9..83a2ac25 100644
--- a/src/kiwano-physics/Joint.cpp
+++ b/src/kiwano-physics/Joint.cpp
@@ -19,7 +19,7 @@
// THE SOFTWARE.
#include
-#include
+#include
namespace kiwano
{
@@ -38,42 +38,46 @@ Joint::Joint()
Joint::~Joint()
{
- Destroy();
}
-bool Joint::InitJoint(World* world, b2JointDef* joint_def)
+bool Joint::Init(PhysicWorld* world)
{
+ return false;
+}
+
+bool Joint::Init(PhysicWorld* world, b2JointDef* joint_def)
+{
+ KGE_ASSERT(joint_ == nullptr);
KGE_ASSERT(world);
Destroy();
world_ = world;
- if (world_)
+
+ b2World* b2world = world_->GetB2World();
+ b2Joint* joint = b2world->CreateJoint(joint_def);
+ if (joint)
{
- world_->AddJoint(this);
-
- b2Joint* joint = world_->GetB2World()->CreateJoint(joint_def);
SetB2Joint(joint);
-
- return joint != nullptr;
+ return true;
}
return false;
}
-BodyPtr Joint::GetBodyA() const
+PhysicBodyPtr Joint::GetBodyA() const
{
KGE_ASSERT(joint_);
b2Body* body = joint_->GetBodyA();
- return BodyPtr(static_cast(body->GetUserData()));
+ return PhysicBodyPtr(static_cast(body->GetUserData()));
}
-BodyPtr Joint::GetBodyB() const
+PhysicBodyPtr Joint::GetBodyB() const
{
KGE_ASSERT(joint_);
b2Body* body = joint_->GetBodyB();
- return BodyPtr(static_cast(body->GetUserData()));
+ return PhysicBodyPtr(static_cast(body->GetUserData()));
}
void Joint::SetB2Joint(b2Joint* joint)
@@ -81,97 +85,101 @@ void Joint::SetB2Joint(b2Joint* joint)
joint_ = joint;
if (joint_)
{
+ joint_->SetUserData(this);
type_ = Joint::Type(joint_->GetType());
}
}
void Joint::Destroy()
{
- if (world_)
+ if (joint_ && world_)
{
- world_->RemoveJoint(this);
+ b2World* b2world = world_->GetB2World();
+ if (b2world)
+ {
+ b2world->DestroyJoint(joint_);
+ }
}
+
+ joint_ = nullptr;
+ world_ = nullptr;
}
//
// DistanceJoint
//
-DistanceJointPtr DistanceJoint::Create(World* world, Param const& param)
+DistanceJointPtr DistanceJoint::Create(Param const& param)
{
DistanceJointPtr ptr = new (std::nothrow) DistanceJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
DistanceJoint::DistanceJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool DistanceJoint::InitJoint(World* world, DistanceJoint::Param const& param)
+bool DistanceJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2DistanceJointDef def;
- def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.anchor_a),
- world->Stage2World(param.anchor_b));
- def.frequencyHz = param.frequency_hz;
- def.dampingRatio = param.damping_ratio;
+ def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::ToMeters(param_.anchor_a),
+ global::ToMeters(param_.anchor_b));
+ def.frequencyHz = param_.frequency_hz;
+ def.dampingRatio = param_.damping_ratio;
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
void DistanceJoint::SetLength(float length)
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- raw_joint_->SetLength(GetWorld()->Stage2World(length));
+ KGE_ASSERT(raw_joint_);
+ raw_joint_->SetLength(global::ToMeters(length));
}
float DistanceJoint::GetLength() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetLength());
+ KGE_ASSERT(raw_joint_);
+ return global::ToMeters(raw_joint_->GetLength());
}
//
// FrictionJoint
//
-FrictionJointPtr FrictionJoint::Create(World* world, Param const& param)
+FrictionJointPtr FrictionJoint::Create(Param const& param)
{
FrictionJointPtr ptr = new (std::nothrow) FrictionJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
FrictionJoint::FrictionJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool FrictionJoint::InitJoint(World* world, FrictionJoint::Param const& param)
+bool FrictionJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2FrictionJointDef def;
- def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.anchor));
- def.maxForce = param.max_force;
- def.maxTorque = world->Stage2World(param.max_torque);
+ def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::ToMeters(param_.anchor));
+ def.maxForce = param_.max_force;
+ def.maxTorque = global::ToMeters(param_.max_torque);
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
@@ -190,47 +198,45 @@ float FrictionJoint::GetMaxForce() const
void FrictionJoint::SetMaxTorque(float length)
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- raw_joint_->SetMaxTorque(GetWorld()->Stage2World(length));
+ KGE_ASSERT(raw_joint_);
+ raw_joint_->SetMaxTorque(global::ToMeters(length));
}
float FrictionJoint::GetMaxTorque() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetMaxTorque());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetMaxTorque());
}
//
// GearJoint
//
-GearJointPtr GearJoint::Create(World* world, Param const& param)
+GearJointPtr GearJoint::Create(Param const& param)
{
GearJointPtr ptr = new (std::nothrow) GearJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
GearJoint::GearJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool GearJoint::InitJoint(World* world, GearJoint::Param const& param)
+bool GearJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.joint_a && param.joint_b);
+ KGE_ASSERT(param_.joint_a && param_.joint_b);
b2GearJointDef def;
- def.joint1 = param.joint_a->GetB2Joint();
- def.joint2 = param.joint_b->GetB2Joint();
- def.ratio = param.ratio;
+ def.joint1 = param_.joint_a->GetB2Joint();
+ def.joint2 = param_.joint_b->GetB2Joint();
+ def.ratio = param_.ratio;
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
@@ -251,34 +257,32 @@ float GearJoint::GetRatio() const
// MotorJoint
//
-MotorJointPtr MotorJoint::Create(World* world, Param const& param)
+MotorJointPtr MotorJoint::Create(Param const& param)
{
MotorJointPtr ptr = new (std::nothrow) MotorJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
MotorJoint::MotorJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool MotorJoint::InitJoint(World* world, MotorJoint::Param const& param)
+bool MotorJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2MotorJointDef def;
- def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body());
- def.maxForce = param.max_force;
- def.maxTorque = world->Stage2World(param.max_torque);
- def.correctionFactor = param.correction_factor;
+ def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body());
+ def.maxForce = param_.max_force;
+ def.maxTorque = global::ToMeters(param_.max_torque);
+ def.correctionFactor = param_.correction_factor;
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
@@ -297,131 +301,127 @@ float MotorJoint::GetMaxForce() const
void MotorJoint::SetMaxTorque(float length)
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- raw_joint_->SetMaxTorque(GetWorld()->Stage2World(length));
+ KGE_ASSERT(raw_joint_);
+ raw_joint_->SetMaxTorque(global::ToMeters(length));
}
float MotorJoint::GetMaxTorque() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetMaxTorque());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetMaxTorque());
}
//
// PrismaticJoint
//
-PrismaticJointPtr PrismaticJoint::Create(World* world, Param const& param)
+PrismaticJointPtr PrismaticJoint::Create(Param const& param)
{
PrismaticJointPtr ptr = new (std::nothrow) PrismaticJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
PrismaticJoint::PrismaticJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool PrismaticJoint::InitJoint(World* world, PrismaticJoint::Param const& param)
+bool PrismaticJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2PrismaticJointDef def;
- def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.anchor),
- Stage2World(param.axis));
- def.enableLimit = param.enable_limit;
- def.lowerTranslation = world->Stage2World(param.lower_translation);
- def.upperTranslation = world->Stage2World(param.upper_translation);
- def.enableMotor = param.enable_motor;
- def.maxMotorForce = param.max_motor_force;
- def.motorSpeed = world->Stage2World(param.motor_speed);
+ def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::ToMeters(param_.anchor),
+ b2Vec2(param_.axis.x, param_.axis.y));
+ def.enableLimit = param_.enable_limit;
+ def.lowerTranslation = global::ToMeters(param_.lower_translation);
+ def.upperTranslation = global::ToMeters(param_.upper_translation);
+ def.enableMotor = param_.enable_motor;
+ def.maxMotorForce = param_.max_motor_force;
+ def.motorSpeed = global::ToMeters(param_.motor_speed);
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
float PrismaticJoint::GetJointTranslation() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetJointTranslation());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetJointTranslation());
}
float PrismaticJoint::GetJointSpeed() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetJointSpeed());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetJointSpeed());
}
float PrismaticJoint::GetLowerLimit() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetLowerLimit());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetLowerLimit());
}
float PrismaticJoint::GetUpperLimit() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetUpperLimit());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetUpperLimit());
}
void PrismaticJoint::SetLimits(float lower, float upper)
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- raw_joint_->SetLimits(GetWorld()->Stage2World(lower), GetWorld()->Stage2World(upper));
+ KGE_ASSERT(raw_joint_);
+ raw_joint_->SetLimits(global::ToMeters(lower), global::ToMeters(upper));
}
//
// PulleyJoint
//
-PulleyJointPtr PulleyJoint::Create(World* world, Param const& param)
+PulleyJointPtr PulleyJoint::Create(Param const& param)
{
PulleyJointPtr ptr = new (std::nothrow) PulleyJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
PulleyJoint::PulleyJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool PulleyJoint::InitJoint(World* world, PulleyJoint::Param const& param)
+bool PulleyJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2PulleyJointDef def;
- def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.ground_anchor_a),
- world->Stage2World(param.ground_anchor_b), world->Stage2World(param.anchor_a),
- world->Stage2World(param.anchor_b), param.ratio);
+ def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::ToMeters(param_.ground_anchor_a),
+ global::ToMeters(param_.ground_anchor_b), global::ToMeters(param_.anchor_a),
+ global::ToMeters(param_.anchor_b), param_.ratio);
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
Point PulleyJoint::GetGroundAnchorA() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetGroundAnchorA());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetGroundAnchorA());
}
Point PulleyJoint::GetGroundAnchorB() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetGroundAnchorB());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetGroundAnchorB());
}
float PulleyJoint::GetRatio() const
@@ -432,189 +432,183 @@ float PulleyJoint::GetRatio() const
float PulleyJoint::GetLengthA() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetLengthA());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetLengthA());
}
float PulleyJoint::GetLengthB() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetLengthB());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetLengthB());
}
float PulleyJoint::GetCurrentLengthA() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetCurrentLengthA());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetCurrentLengthA());
}
float PulleyJoint::GetCurrentLengthB() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetCurrentLengthB());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetCurrentLengthB());
}
//
// RevoluteJoint
//
-RevoluteJointPtr RevoluteJoint::Create(World* world, Param const& param)
+RevoluteJointPtr RevoluteJoint::Create(Param const& param)
{
RevoluteJointPtr ptr = new (std::nothrow) RevoluteJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
RevoluteJoint::RevoluteJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool RevoluteJoint::InitJoint(World* world, RevoluteJoint::Param const& param)
+bool RevoluteJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2RevoluteJointDef def;
- def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.anchor));
- def.enableLimit = param.enable_limit;
- def.lowerAngle = math::Degree2Radian(param.lower_angle);
- def.upperAngle = math::Degree2Radian(param.upper_angle);
- def.enableMotor = param.enable_motor;
- def.maxMotorTorque = world->Stage2World(param.max_motor_torque);
- def.motorSpeed = math::Degree2Radian(param.motor_speed);
+ def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::ToMeters(param_.anchor));
+ def.enableLimit = param_.enable_limit;
+ def.lowerAngle = math::Degree2Radian(param_.lower_angle);
+ def.upperAngle = math::Degree2Radian(param_.upper_angle);
+ def.enableMotor = param_.enable_motor;
+ def.maxMotorTorque = global::ToMeters(param_.max_motor_torque);
+ def.motorSpeed = math::Degree2Radian(param_.motor_speed);
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
float RevoluteJoint::GetJointAngle() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
+ KGE_ASSERT(raw_joint_);
return math::Radian2Degree(raw_joint_->GetJointAngle());
}
float RevoluteJoint::GetJointSpeed() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
+ KGE_ASSERT(raw_joint_);
return math::Radian2Degree(raw_joint_->GetJointSpeed());
}
float RevoluteJoint::GetLowerLimit() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
+ KGE_ASSERT(raw_joint_);
return math::Radian2Degree(raw_joint_->GetLowerLimit());
}
float RevoluteJoint::GetUpperLimit() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
+ KGE_ASSERT(raw_joint_);
return math::Radian2Degree(raw_joint_->GetUpperLimit());
}
void RevoluteJoint::SetLimits(float lower, float upper)
{
- KGE_ASSERT(raw_joint_ && GetWorld());
+ KGE_ASSERT(raw_joint_);
raw_joint_->SetLimits(math::Degree2Radian(lower), math::Degree2Radian(upper));
}
void RevoluteJoint::SetMaxMotorTorque(float torque)
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- raw_joint_->SetMaxMotorTorque(GetWorld()->Stage2World(torque));
+ KGE_ASSERT(raw_joint_);
+ raw_joint_->SetMaxMotorTorque(global::ToMeters(torque));
}
float RevoluteJoint::GetMaxMotorTorque() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetMaxMotorTorque());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetMaxMotorTorque());
}
//
// RopeJoint
//
-RopeJointPtr RopeJoint::Create(World* world, Param const& param)
+RopeJointPtr RopeJoint::Create(Param const& param)
{
RopeJointPtr ptr = new (std::nothrow) RopeJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
RopeJoint::RopeJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool RopeJoint::InitJoint(World* world, RopeJoint::Param const& param)
+bool RopeJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2RopeJointDef def;
- def.bodyA = param.body_a->GetB2Body();
- def.bodyB = param.body_b->GetB2Body();
- def.localAnchorA = world->Stage2World(param.local_anchor_a);
- def.localAnchorB = world->Stage2World(param.local_anchor_b);
- def.maxLength = world->Stage2World(param.max_length);
+ def.bodyA = param_.body_a->GetB2Body();
+ def.bodyB = param_.body_b->GetB2Body();
+ def.localAnchorA = global::ToMeters(param_.local_anchor_a);
+ def.localAnchorB = global::ToMeters(param_.local_anchor_b);
+ def.maxLength = global::ToMeters(param_.max_length);
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
void RopeJoint::SetMaxLength(float length)
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- raw_joint_->SetMaxLength(GetWorld()->Stage2World(length));
+ KGE_ASSERT(raw_joint_);
+ raw_joint_->SetMaxLength(global::ToMeters(length));
}
float RopeJoint::GetMaxLength() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetMaxLength());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetMaxLength());
}
//
// WeldJoint
//
-WeldJointPtr WeldJoint::Create(World* world, Param const& param)
+WeldJointPtr WeldJoint::Create(Param const& param)
{
WeldJointPtr ptr = new (std::nothrow) WeldJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
WeldJoint::WeldJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool WeldJoint::InitJoint(World* world, WeldJoint::Param const& param)
+bool WeldJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2WeldJointDef def;
- def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.anchor));
- def.frequencyHz = param.frequency_hz;
- def.dampingRatio = param.damping_ratio;
+ def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::ToMeters(param_.anchor));
+ def.frequencyHz = param_.frequency_hz;
+ def.dampingRatio = param_.damping_ratio;
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
@@ -623,99 +617,95 @@ bool WeldJoint::InitJoint(World* world, WeldJoint::Param const& param)
// WheelJoint
//
-WheelJointPtr WheelJoint::Create(World* world, Param const& param)
+WheelJointPtr WheelJoint::Create(Param const& param)
{
WheelJointPtr ptr = new (std::nothrow) WheelJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
WheelJoint::WheelJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool WheelJoint::InitJoint(World* world, WheelJoint::Param const& param)
+bool WheelJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2WheelJointDef def;
- def.Initialize(param.body_a->GetB2Body(), param.body_b->GetB2Body(), world->Stage2World(param.anchor),
- Stage2World(param.axis));
- def.enableMotor = param.enable_motor;
- def.maxMotorTorque = world->Stage2World(param.max_motor_torque);
- def.motorSpeed = world->Stage2World(param.motor_speed);
- def.frequencyHz = param.frequency_hz;
- def.dampingRatio = param.damping_ratio;
+ def.Initialize(param_.body_a->GetB2Body(), param_.body_b->GetB2Body(), global::ToMeters(param_.anchor),
+ b2Vec2(param_.axis.x, param_.axis.y));
+ def.enableMotor = param_.enable_motor;
+ def.maxMotorTorque = global::ToMeters(param_.max_motor_torque);
+ def.motorSpeed = global::ToMeters(param_.motor_speed);
+ def.frequencyHz = param_.frequency_hz;
+ def.dampingRatio = param_.damping_ratio;
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
float WheelJoint::GetJointTranslation() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetJointTranslation());
+ KGE_ASSERT(raw_joint_);
+ return global::ToMeters(raw_joint_->GetJointTranslation());
}
float WheelJoint::GetJointLinearSpeed() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetJointLinearSpeed());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetJointLinearSpeed());
}
void WheelJoint::SetMaxMotorTorque(float torque)
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- raw_joint_->SetMaxMotorTorque(GetWorld()->Stage2World(torque));
+ KGE_ASSERT(raw_joint_);
+ raw_joint_->SetMaxMotorTorque(global::ToMeters(torque));
}
float WheelJoint::GetMaxMotorTorque() const
{
- KGE_ASSERT(raw_joint_ && GetWorld());
- return GetWorld()->World2Stage(raw_joint_->GetMaxMotorTorque());
+ KGE_ASSERT(raw_joint_);
+ return global::ToPixels(raw_joint_->GetMaxMotorTorque());
}
//
// MouseJoint
//
-MouseJointPtr MouseJoint::Create(World* world, Param const& param)
+MouseJointPtr MouseJoint::Create(Param const& param)
{
MouseJointPtr ptr = new (std::nothrow) MouseJoint;
if (ptr)
{
- if (!ptr->InitJoint(world, param))
- return nullptr;
+ ptr->param_ = param;
}
return ptr;
}
MouseJoint::MouseJoint()
- : Joint()
- , raw_joint_(nullptr)
+ : raw_joint_(nullptr)
{
}
-bool MouseJoint::InitJoint(World* world, MouseJoint::Param const& param)
+bool MouseJoint::Init(PhysicWorld* world)
{
- KGE_ASSERT(param.body_a && param.body_b);
+ KGE_ASSERT(param_.body_a && param_.body_b);
b2MouseJointDef def;
- def.bodyA = param.body_a->GetB2Body();
- def.bodyB = param.body_b->GetB2Body();
- def.target = world->Stage2World(param.target);
- def.maxForce = param.max_force;
- def.frequencyHz = param.frequency_hz;
- def.dampingRatio = param.damping_ratio;
+ def.bodyA = param_.body_a->GetB2Body();
+ def.bodyB = param_.body_b->GetB2Body();
+ def.target = global::ToMeters(param_.target);
+ def.maxForce = param_.max_force;
+ def.frequencyHz = param_.frequency_hz;
+ def.dampingRatio = param_.damping_ratio;
- Joint::InitJoint(world, &def);
+ Joint::Init(world, &def);
raw_joint_ = static_cast(GetB2Joint());
return raw_joint_ != nullptr;
}
diff --git a/src/kiwano-physics/Joint.h b/src/kiwano-physics/Joint.h
index 8301637d..578c02e0 100644
--- a/src/kiwano-physics/Joint.h
+++ b/src/kiwano-physics/Joint.h
@@ -19,8 +19,7 @@
// THE SOFTWARE.
#pragma once
-#include
-#include
+#include
namespace kiwano
{
@@ -71,16 +70,16 @@ public:
/// @brief 关节基础参数
struct ParamBase
{
- Body* body_a; ///< 关节连接的物体A
- Body* body_b; ///< 关节连接的物体B
+ PhysicBody* body_a; ///< 关节连接的物体A
+ PhysicBody* body_b; ///< 关节连接的物体B
- ParamBase(Body* body_a, Body* body_b)
+ ParamBase(PhysicBody* body_a, PhysicBody* body_b)
: body_a(body_a)
, body_b(body_b)
{
}
- ParamBase(BodyPtr body_a, BodyPtr body_b)
+ ParamBase(PhysicBodyPtr body_a, PhysicBodyPtr body_b)
: body_a(body_a.Get())
, body_b(body_b.Get())
{
@@ -93,31 +92,40 @@ public:
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, b2JointDef* joint_def);
+ virtual bool Init(PhysicWorld* world);
+
+ /// \~chinese
+ /// @brief 初始化关节
+ bool Init(PhysicWorld* world, b2JointDef* joint_def);
/// \~chinese
/// @brief 获取关节连接的物体A
- BodyPtr GetBodyA() const;
+ PhysicBodyPtr GetBodyA() const;
/// \~chinese
/// @brief 获取关节连接的物体B
- BodyPtr GetBodyB() const;
+ PhysicBodyPtr GetBodyB() const;
/// \~chinese
/// @brief 获取物理世界
- World* GetWorld() const;
+ PhysicWorld* GetWorld() const;
/// \~chinese
/// @brief 销毁关节
void Destroy();
+ /// \~chinese
+ /// @brief 获取b2Joint
b2Joint* GetB2Joint() const;
- void SetB2Joint(b2Joint* joint);
+
+ /// \~chinese
+ /// @brief 设置b2Joint
+ void SetB2Joint(b2Joint* joint);
private:
- b2Joint* joint_;
- World* world_;
- Type type_;
+ b2Joint* joint_;
+ PhysicWorld* world_;
+ Type type_;
};
/// \~chinese
@@ -134,34 +142,31 @@ public:
float frequency_hz; ///< 响应速度,数值越高关节响应的速度越快,看上去越坚固
float damping_ratio; ///< 阻尼率,值越大关节运动阻尼越大
- Param(Body* body_a, Body* body_b, Point const& anchor_a, Point const& anchor_b, float frequency_hz = 0.f,
- float damping_ratio = 0.f)
- : ParamBase(body_a, body_b)
- , anchor_a(anchor_a)
- , anchor_b(anchor_b)
- , frequency_hz(frequency_hz)
- , damping_ratio(damping_ratio)
+ Param()
+ : Param(nullptr, nullptr, Point(), Point())
{
}
- Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor_a, Point const& anchor_b, float frequency_hz = 0.f,
- float damping_ratio = 0.f)
- : Param(body_a.Get(), body_b.Get(), anchor_a, anchor_b, frequency_hz, damping_ratio)
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, Point const& anchor_a, Point const& anchor_b)
+ : ParamBase(body_a, body_b)
+ , anchor_a(anchor_a)
+ , anchor_b(anchor_b)
+ , frequency_hz(0.0f)
+ , damping_ratio(0.0f)
{
}
};
/// \~chinese
/// @brief 创建固定距离关节
- /// @param world 物理世界
/// @param param 关节参数
- static DistanceJointPtr Create(World* world, Param const& param);
+ static DistanceJointPtr Create(Param const& param);
DistanceJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 设置关节长度
@@ -188,6 +193,7 @@ public:
float GetDampingRatio() const;
private:
+ Param param_;
b2DistanceJoint* raw_joint_;
};
@@ -202,31 +208,30 @@ public:
float max_force; ///< 最大摩擦力
float max_torque; ///< 最大扭力
- Param(Body* body_a, Body* body_b, Point const& anchor, float max_force = 0.f, float max_torque = 0.f)
+ Param()
+ : Param(nullptr, nullptr, Point())
+ {
+ }
+
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, Point const& anchor, float max_force = 0.f, float max_torque = 0.f)
: ParamBase(body_a, body_b)
, anchor(anchor)
, max_force(max_force)
, max_torque(max_torque)
{
}
-
- Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, float max_force = 0.f, float max_torque = 0.f)
- : Param(body_a.Get(), body_b.Get(), anchor, max_force, max_torque)
- {
- }
};
/// \~chinese
/// @brief 创建摩擦关节
- /// @param world 物理世界
/// @param param 关节参数
- static FrictionJointPtr Create(World* world, Param const& param);
+ static FrictionJointPtr Create(Param const& param);
FrictionJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 设置最大摩擦力
@@ -245,6 +250,7 @@ public:
float GetMaxTorque() const;
private:
+ Param param_;
b2FrictionJoint* raw_joint_;
};
@@ -261,31 +267,30 @@ public:
Joint* joint_b; ///< 关节B(旋转关节/平移关节)
float ratio; ///< 齿轮传动比
- Param(Joint* joint_a, Joint* joint_b, float ratio = 1.f)
- : ParamBase(nullptr, nullptr)
- , joint_a(joint_a)
- , joint_b(joint_b)
- , ratio(ratio)
+ Param()
+ : Param(nullptr, nullptr)
{
}
Param(JointPtr joint_a, JointPtr joint_b, float ratio = 1.f)
- : Param(joint_a.Get(), joint_b.Get(), ratio)
+ : ParamBase(nullptr, nullptr)
+ , joint_a(joint_a.Get())
+ , joint_b(joint_b.Get())
+ , ratio(ratio)
{
}
};
/// \~chinese
/// @brief 创建齿轮关节
- /// @param world 物理世界
/// @param param 关节参数
- static GearJointPtr Create(World* world, Param const& param);
+ static GearJointPtr Create(Param const& param);
GearJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 设定齿轮传动比
@@ -296,6 +301,7 @@ public:
float GetRatio() const;
private:
+ Param param_;
b2GearJoint* raw_joint_;
};
@@ -312,33 +318,30 @@ public:
float max_torque; ///< 最大转矩
float correction_factor; ///< 位置矫正因子(范围 0-1)
- Param(Body* body_a, Body* body_b, float max_force = 1.f, float max_torque = 100.f,
- float correction_factor = 0.3f)
- : ParamBase(body_a, body_b)
- , max_force(max_force)
- , max_torque(max_torque)
- , correction_factor(correction_factor)
+ Param()
+ : Param(nullptr, nullptr)
{
}
- Param(BodyPtr body_a, BodyPtr body_b, float max_force = 0.f, float max_torque = 0.f,
- float correction_factor = 0.3f)
- : Param(body_a.Get(), body_b.Get(), max_force, max_torque, correction_factor)
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, float max_force = 0.f, float max_torque = 0.f)
+ : ParamBase(body_a, body_b)
+ , max_force(max_force)
+ , max_torque(max_torque)
+ , correction_factor(0.3f)
{
}
};
/// \~chinese
/// @brief 创建马达关节
- /// @param world 物理世界
/// @param param 关节参数
- static MotorJointPtr Create(World* world, Param const& param);
+ static MotorJointPtr Create(Param const& param);
MotorJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 设置最大摩擦力
@@ -357,6 +360,7 @@ public:
float GetMaxTorque() const;
private:
+ Param param_;
b2MotorJoint* raw_joint_;
};
@@ -369,50 +373,44 @@ public:
/// @brief 平移关节参数
struct Param : public Joint::ParamBase
{
- Point anchor; ///< 关节位置
- Vec2 axis; ///< 物体A滑动的方向
- bool enable_limit; ///< 是否启用限制
+ Point anchor; ///< 关节位置
+ Vec2 axis; ///< 物体A滑动的方向
+ bool enable_limit; ///< 是否启用限制
float lower_translation; ///< 移动的最小限制,与方向同向为正,反向为负,启用限制后才有效果
float upper_translation; ///< 移动的最大限制,与方向同向为正,反向为负,启用限制后才有效果
- bool enable_motor; ///< 是否启用马达
- float max_motor_force; ///< 最大马达力 [N]
- float motor_speed; ///< 马达转速 [degree/s]
+ bool enable_motor; ///< 是否启用马达
+ float max_motor_force; ///< 最大马达力 [N]
+ float motor_speed; ///< 马达转速 [degree/s]
- Param(Body* body_a, Body* body_b, Point const& anchor, Vec2 const& axis, bool enable_limit = false,
- float lower_translation = 0.0f, float upper_translation = 0.0f, bool enable_motor = false,
- float max_motor_force = 0.0f, float motor_speed = 0.0f)
- : ParamBase(body_a, body_b)
- , anchor(anchor)
- , axis(axis)
- , enable_limit(enable_limit)
- , lower_translation(lower_translation)
- , upper_translation(upper_translation)
- , enable_motor(enable_motor)
- , max_motor_force(max_motor_force)
- , motor_speed(motor_speed)
+ Param()
+ : Param(nullptr, nullptr, Point(), Vec2())
{
}
- Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, Vec2 const& axis, bool enable_limit = false,
- float lower_translation = 0.0f, float upper_translation = 0.0f, bool enable_motor = false,
- float max_motor_force = 0.0f, float motor_speed = 0.0f)
- : Param(body_a.Get(), body_b.Get(), anchor, axis, enable_limit, lower_translation, upper_translation,
- enable_motor, max_motor_force, motor_speed)
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, Point const& anchor, Vec2 const& axis)
+ : ParamBase(body_a, body_b)
+ , anchor(anchor)
+ , axis(axis)
+ , enable_limit(false)
+ , lower_translation(0.0f)
+ , upper_translation(0.0f)
+ , enable_motor(false)
+ , max_motor_force(0.0f)
+ , motor_speed(0.0f)
{
}
};
/// \~chinese
/// @brief 创建平移关节
- /// @param world 物理世界
/// @param param 关节参数
- static PrismaticJointPtr Create(World* world, Param const& param);
+ static PrismaticJointPtr Create(Param const& param);
PrismaticJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 获取参考角
@@ -471,6 +469,7 @@ public:
float GetMaxMotorForce() const;
private:
+ Param param_;
b2PrismaticJoint* raw_joint_;
};
@@ -489,8 +488,13 @@ public:
Point ground_anchor_b; ///< 物体B对应的滑轮的位置
float ratio; ///< 滑轮比,关节传动时,滑轮上升和下降的两头的位移比例
- Param(Body* body_a, Body* body_b, Point const& anchor_a, Point const& anchor_b, Point const& ground_anchor_a,
- Point const& ground_anchor_b, float ratio = 1.0f)
+ Param()
+ : Param(nullptr, nullptr, Point(), Point(), Point(), Point())
+ {
+ }
+
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, Point const& anchor_a, Point const& anchor_b,
+ Point const& ground_anchor_a, Point const& ground_anchor_b, float ratio = 1.0f)
: ParamBase(body_a, body_b)
, anchor_a(anchor_a)
, anchor_b(anchor_b)
@@ -499,25 +503,18 @@ public:
, ratio(ratio)
{
}
-
- Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor_a, Point const& anchor_b,
- Point const& ground_anchor_a, Point const& ground_anchor_b, float ratio = 1.0f)
- : Param(body_a.Get(), body_b.Get(), anchor_a, anchor_b, ground_anchor_a, ground_anchor_b, ratio)
- {
- }
};
/// \~chinese
/// @brief 创建滑轮关节
- /// @param world 物理世界
/// @param param 关节参数
- static PulleyJointPtr Create(World* world, Param const& param);
+ static PulleyJointPtr Create(Param const& param);
PulleyJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 物体A对应的滑轮的位置
@@ -548,6 +545,7 @@ public:
float GetCurrentLengthB() const;
private:
+ Param param_;
b2PulleyJoint* raw_joint_;
};
@@ -560,48 +558,42 @@ public:
/// @brief 旋转关节参数
struct Param : public Joint::ParamBase
{
- Point anchor; ///< 关节位置
- bool enable_limit; ///< 是否启用限制
- float lower_angle; ///< 移动的最小限制,与方向同向为正,反向为负,启用限制后才有效果
- float upper_angle; ///< 移动的最大限制,与方向同向为正,反向为负,启用限制后才有效果
+ Point anchor; ///< 关节位置
+ bool enable_limit; ///< 是否启用限制
+ float lower_angle; ///< 移动的最小限制,与方向同向为正,反向为负,启用限制后才有效果
+ float upper_angle; ///< 移动的最大限制,与方向同向为正,反向为负,启用限制后才有效果
bool enable_motor; ///< 是否启用马达
float max_motor_torque; ///< 最大马达力 [N]
float motor_speed; ///< 马达转速 [degree/s]
- Param(Body* body_a, Body* body_b, Point const& anchor, bool enable_limit = false, float lower_angle = 0.0f,
- float upper_angle = 0.0f, bool enable_motor = false, float max_motor_torque = 0.0f,
- float motor_speed = 0.0f)
- : ParamBase(body_a, body_b)
- , anchor(anchor)
- , enable_limit(enable_limit)
- , lower_angle(lower_angle)
- , upper_angle(upper_angle)
- , enable_motor(enable_motor)
- , max_motor_torque(max_motor_torque)
- , motor_speed(motor_speed)
+ Param()
+ : Param(nullptr, nullptr, Point())
{
}
- Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, bool enable_limit = false, float lower_angle = 0.0f,
- float upper_angle = 0.0f, bool enable_motor = false, float max_motor_torque = 0.0f,
- float motor_speed = 0.0f)
- : Param(body_a.Get(), body_b.Get(), anchor, enable_limit, lower_angle, upper_angle, enable_motor,
- max_motor_torque, motor_speed)
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, Point const& anchor)
+ : ParamBase(body_a, body_b)
+ , anchor(anchor)
+ , enable_limit(false)
+ , lower_angle(0.0f)
+ , upper_angle(0.0f)
+ , enable_motor(false)
+ , max_motor_torque(0.0f)
+ , motor_speed(0.0f)
{
}
};
/// \~chinese
/// @brief 创建旋转关节
- /// @param world 物理世界
/// @param param 关节参数
- static RevoluteJointPtr Create(World* world, Param const& param);
+ static RevoluteJointPtr Create(Param const& param);
RevoluteJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 获取参考角
@@ -660,6 +652,7 @@ public:
float GetMaxMotorTorque() const;
private:
+ Param param_;
b2RevoluteJoint* raw_joint_;
};
@@ -676,33 +669,30 @@ public:
Point local_anchor_b; ///< 关节在物体B上的连接点
float max_length; ///< 绳索最大长度
- Param(Body* body_a, Body* body_b, Point const& local_anchor_a, Point const& local_anchor_b,
- float max_length = 0.f)
- : ParamBase(body_a, body_b)
- , local_anchor_a(local_anchor_a)
- , local_anchor_b(local_anchor_b)
- , max_length(max_length)
+ Param()
+ : Param(nullptr, nullptr, Point(), Point())
{
}
- Param(BodyPtr body_a, BodyPtr body_b, Point const& local_anchor_a, Point const& local_anchor_b,
- float max_length = 0.f)
- : Param(body_a.Get(), body_b.Get(), local_anchor_a, local_anchor_b, max_length)
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, Point const& local_anchor_a, Point const& local_anchor_b)
+ : ParamBase(body_a, body_b)
+ , local_anchor_a(local_anchor_a)
+ , local_anchor_b(local_anchor_b)
+ , max_length(0.0f)
{
}
};
/// \~chinese
/// @brief 创建绳关节
- /// @param world 物理世界
/// @param param 关节参数
- static RopeJointPtr Create(World* world, Param const& param);
+ static RopeJointPtr Create(Param const& param);
RopeJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 设置关节最大长度
@@ -713,6 +703,7 @@ public:
float GetMaxLength() const;
private:
+ Param param_;
b2RopeJoint* raw_joint_;
};
@@ -729,31 +720,30 @@ public:
float frequency_hz; ///< 响应速度,数值越高关节响应的速度越快,看上去越坚固
float damping_ratio; ///< 阻尼率,值越大关节运动阻尼越大
- Param(Body* body_a, Body* body_b, Point const& anchor, float frequency_hz = 0.f, float damping_ratio = 0.f)
- : ParamBase(body_a, body_b)
- , anchor(anchor)
- , frequency_hz(frequency_hz)
- , damping_ratio(damping_ratio)
+ Param()
+ : Param(nullptr, nullptr, Point())
{
}
- Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, float frequency_hz = 0.f, float damping_ratio = 0.f)
- : Param(body_a.Get(), body_b.Get(), anchor, frequency_hz, damping_ratio)
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, Point const& anchor)
+ : ParamBase(body_a, body_b)
+ , anchor(anchor)
+ , frequency_hz(0.0f)
+ , damping_ratio(0.0f)
{
}
};
/// \~chinese
/// @brief 创建焊接关节
- /// @param world 物理世界
/// @param param 关节参数
- static WeldJointPtr Create(World* world, Param const& param);
+ static WeldJointPtr Create(Param const& param);
WeldJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 获取物体B相对于物体A的角度
@@ -776,6 +766,7 @@ public:
float GetDampingRatio() const;
private:
+ Param param_;
b2WeldJoint* raw_joint_;
};
@@ -796,40 +787,34 @@ public:
float frequency_hz; ///< 响应速度,数值越高关节响应的速度越快,看上去越坚固
float damping_ratio; ///< 弹簧阻尼率,值越大关节运动阻尼越大
- Param(Body* body_a, Body* body_b, Point const& anchor, Vec2 const& axis, float frequency_hz = 2.0f,
- float damping_ratio = 0.7f, bool enable_motor = false, float max_motor_torque = 0.0f,
- float motor_speed = 0.0f)
- : ParamBase(body_a, body_b)
- , anchor(anchor)
- , axis(axis)
- , enable_motor(enable_motor)
- , max_motor_torque(max_motor_torque)
- , motor_speed(motor_speed)
- , frequency_hz(frequency_hz)
- , damping_ratio(damping_ratio)
+ Param()
+ : Param(nullptr, nullptr, Point(), Vec2())
{
}
- Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, Vec2 const& axis, float frequency_hz = 2.0f,
- float damping_ratio = 0.7f, bool enable_motor = false, float max_motor_torque = 0.0f,
- float motor_speed = 0.0f)
- : Param(body_a.Get(), body_b.Get(), anchor, axis, frequency_hz, damping_ratio, enable_motor,
- max_motor_torque, motor_speed)
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, Point const& anchor, Vec2 const& axis)
+ : ParamBase(body_a, body_b)
+ , anchor(anchor)
+ , axis(axis)
+ , enable_motor(false)
+ , max_motor_torque(0.0f)
+ , motor_speed(0.0f)
+ , frequency_hz(2.0f)
+ , damping_ratio(0.7f)
{
}
};
/// \~chinese
/// @brief 创建轮关节
- /// @param world 物理世界
/// @param param 关节参数
- static WheelJointPtr Create(World* world, Param const& param);
+ static WheelJointPtr Create(Param const& param);
WheelJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 获取关节当前的平移距离
@@ -888,6 +873,7 @@ public:
float GetSpringDampingRatio() const;
private:
+ Param param_;
b2WheelJoint* raw_joint_;
};
@@ -906,34 +892,31 @@ public:
float frequency_hz; ///< 响应速度,数值越高关节响应的速度越快,看上去越坚固
float damping_ratio; ///< 阻尼率,值越大关节运动阻尼越大
- Param(Body* body_a, Body* body_b, Point const& target, float max_force, float frequency_hz = 5.0f,
- float damping_ratio = 0.7f)
- : ParamBase(body_a, body_b)
- , target(target)
- , max_force(max_force)
- , frequency_hz(frequency_hz)
- , damping_ratio(damping_ratio)
+ Param()
+ : Param(nullptr, nullptr, Point())
{
}
- Param(BodyPtr body_a, BodyPtr body_b, Point const& target, float max_force, float frequency_hz = 5.0f,
- float damping_ratio = 0.7f)
- : Param(body_a.Get(), body_b.Get(), target, max_force, frequency_hz, damping_ratio)
+ Param(PhysicBodyPtr body_a, PhysicBodyPtr body_b, Point const& target)
+ : ParamBase(body_a, body_b)
+ , target(target)
+ , max_force(0.0f)
+ , frequency_hz(5.0f)
+ , damping_ratio(0.7f)
{
}
};
/// \~chinese
/// @brief 创建鼠标关节
- /// @param world 物理世界
/// @param param 关节参数
- static MouseJointPtr Create(World* world, Param const& param);
+ static MouseJointPtr Create(Param const& param);
MouseJoint();
/// \~chinese
/// @brief 初始化关节
- bool InitJoint(World* world, Param const& param);
+ bool Init(PhysicWorld* world) override;
/// \~chinese
/// @brief 设定最大摩擦力 [N]
@@ -960,6 +943,7 @@ public:
float GetDampingRatio() const;
private:
+ Param param_;
b2MouseJoint* raw_joint_;
};
@@ -969,7 +953,7 @@ inline b2Joint* Joint::GetB2Joint() const
{
return joint_;
}
-inline World* Joint::GetWorld() const
+inline PhysicWorld* Joint::GetWorld() const
{
return world_;
}
diff --git a/src/kiwano-physics/PhysicBody.cpp b/src/kiwano-physics/PhysicBody.cpp
new file mode 100644
index 00000000..a11bd777
--- /dev/null
+++ b/src/kiwano-physics/PhysicBody.cpp
@@ -0,0 +1,378 @@
+// Copyright (c) 2018-2019 Kiwano - Nomango
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include
+#include
+
+namespace kiwano
+{
+namespace physics
+{
+
+PhysicBodyPtr PhysicBody::Create(ActorPtr actor, Type type)
+{
+ return PhysicBody::Create(actor.Get(), type);
+}
+
+PhysicBodyPtr PhysicBody::Create(Actor* actor, Type type)
+{
+ if (!actor)
+ {
+ return nullptr;
+ }
+
+ PhysicBodyPtr ptr = new (std::nothrow) PhysicBody;
+ if (ptr)
+ {
+ ptr->SetType(type);
+ actor->AddComponent(ptr);
+ }
+ return ptr;
+}
+
+PhysicBody::PhysicBody()
+ : body_(nullptr)
+ , world_(nullptr)
+ , type_(Type::Static)
+ , category_bits_(0x0001)
+ , mask_bits_(0xFFFF)
+ , group_index_(0)
+{
+}
+
+PhysicBody::~PhysicBody() {}
+
+void PhysicBody::InitComponent(Actor* actor)
+{
+ Component::InitComponent(actor);
+ UpdateFromActor();
+}
+
+void PhysicBody::DestroyComponent()
+{
+ // Detach from actor first
+ Component::DestroyComponent();
+
+ // Destruction of fixtures may cause contact end
+ RemoveAllFixtures();
+
+ if (world_)
+ {
+ world_->RemoveBody(this);
+ }
+}
+
+bool PhysicBody::Init(PhysicWorldPtr world)
+{
+ return Init(world.Get());
+}
+
+bool PhysicBody::Init(PhysicWorld* world)
+{
+ KGE_ASSERT(body_ == nullptr);
+ KGE_ASSERT(world);
+
+ world_ = world;
+
+ b2BodyDef def;
+ def.type = b2BodyType(type_);
+
+ b2Body* b2body = world->GetB2World()->CreateBody(&def);
+ if (b2body)
+ {
+ SetB2Body(b2body);
+ UpdateFromActor();
+
+ // lazy init fixtures
+ for (auto fixture : fixtures_)
+ {
+ bool success = fixture->Init(this);
+ KGE_ASSERT(success);
+ }
+ return true;
+ }
+ return false;
+}
+
+void PhysicBody::AddFixture(FixturePtr fixture)
+{
+ if (fixture)
+ {
+ bool success = fixture->Init(this);
+ KGE_ASSERT(success);
+
+ fixtures_.push_back(fixture);
+ }
+}
+
+Fixture* PhysicBody::AddCircleShape(float radius, float density, float friction)
+{
+ FixturePtr fixture = Fixture::CreateCircle(Fixture::Param(density, friction), radius);
+ AddFixture(fixture);
+ return fixture.Get();
+}
+
+Fixture* PhysicBody::AddRectShape(Vec2 const& size, float density, float friction)
+{
+ FixturePtr fixture = Fixture::CreateRect(Fixture::Param(density, friction), size);
+ AddFixture(fixture);
+ return fixture.Get();
+}
+
+Fixture* PhysicBody::AddPolygonShape(Vector const& vertexs, float density, float friction)
+{
+ FixturePtr fixture = Fixture::CreatePolygon(Fixture::Param(density, friction), vertexs);
+ AddFixture(fixture);
+ return fixture.Get();
+}
+
+Fixture* PhysicBody::AddEdgeShape(Point const& p1, Point const& p2, float density, float friction)
+{
+ FixturePtr fixture = Fixture::CreateEdge(Fixture::Param(density, friction), p1, p2);
+ AddFixture(fixture);
+ return fixture.Get();
+}
+
+Fixture* PhysicBody::AddChainShape(Vector const& vertexs, bool loop, float density, float friction)
+{
+ FixturePtr fixture = Fixture::CreateChain(Fixture::Param(density, friction), vertexs, loop);
+ AddFixture(fixture);
+ return fixture.Get();
+}
+
+void PhysicBody::RemoveFixture(FixturePtr fixture)
+{
+ if (fixture)
+ {
+ auto iter = std::find(fixtures_.begin(), fixtures_.end(), fixture);
+ if (iter != fixtures_.end())
+ {
+ fixture->Destroy();
+ fixtures_.erase(iter);
+ }
+ }
+}
+
+void PhysicBody::RemoveAllFixtures()
+{
+ for (auto fixture : fixtures_)
+ {
+ fixture->Destroy();
+ }
+ fixtures_.clear();
+}
+
+void PhysicBody::SetCategoryBits(uint16_t category_bits)
+{
+ KGE_ASSERT(body_);
+
+ if (category_bits != category_bits_)
+ {
+ category_bits_ = category_bits;
+
+ b2Fixture* fixture = body_->GetFixtureList();
+ while (fixture)
+ {
+ UpdateFixtureFilter(fixture);
+ fixture = fixture->GetNext();
+ }
+ }
+}
+
+void PhysicBody::SetMaskBits(uint16_t mask_bits)
+{
+ KGE_ASSERT(body_);
+
+ if (mask_bits != mask_bits_)
+ {
+ mask_bits_ = mask_bits;
+
+ b2Fixture* fixture = body_->GetFixtureList();
+ while (fixture)
+ {
+ UpdateFixtureFilter(fixture);
+ fixture = fixture->GetNext();
+ }
+ }
+}
+
+void PhysicBody::SetGroupIndex(int16_t index)
+{
+ KGE_ASSERT(body_);
+
+ if (index != group_index_)
+ {
+ group_index_ = index;
+
+ b2Fixture* fixture = body_->GetFixtureList();
+ while (fixture)
+ {
+ UpdateFixtureFilter(fixture);
+ fixture = fixture->GetNext();
+ }
+ }
+}
+
+void PhysicBody::GetMassData(float* mass, Point* center, float* inertia) const
+{
+ KGE_ASSERT(body_);
+
+ b2MassData data;
+ body_->GetMassData(&data);
+
+ if (mass)
+ *mass = data.mass;
+ if (center)
+ *center = global::ToPixels(data.center);
+ if (inertia)
+ *inertia = data.I;
+}
+
+void PhysicBody::SetMassData(float mass, Point const& center, float inertia)
+{
+ KGE_ASSERT(body_);
+
+ b2MassData data;
+ data.mass = mass;
+ data.center = global::ToMeters(center);
+ data.I = inertia;
+ body_->SetMassData(&data);
+}
+
+void PhysicBody::ResetMassData()
+{
+ KGE_ASSERT(body_);
+ body_->ResetMassData();
+}
+
+Point PhysicBody::GetPosition() const
+{
+ KGE_ASSERT(body_);
+ return global::ToPixels(body_->GetPosition());
+}
+
+void PhysicBody::SetTransform(Point const& pos, float angle)
+{
+ KGE_ASSERT(body_);
+ body_->SetTransform(global::ToMeters(pos), math::Degree2Radian(angle));
+}
+
+Point PhysicBody::GetLocalPoint(Point const& world) const
+{
+ KGE_ASSERT(body_);
+ return global::ToPixels(body_->GetLocalPoint(global::ToMeters(world)));
+}
+
+Point PhysicBody::GetWorldPoint(Point const& local) const
+{
+ KGE_ASSERT(body_);
+ return global::ToPixels(body_->GetWorldPoint(global::ToMeters(local)));
+}
+
+Point PhysicBody::GetLocalCenter() const
+{
+ KGE_ASSERT(body_);
+ return global::ToPixels(body_->GetLocalCenter());
+}
+
+Point PhysicBody::GetWorldCenter() const
+{
+ KGE_ASSERT(body_);
+ return global::ToPixels(body_->GetWorldCenter());
+}
+
+void PhysicBody::ApplyForce(Vec2 const& force, Point const& point, bool wake)
+{
+ KGE_ASSERT(body_);
+ body_->ApplyForce(b2Vec2(force.x, force.y), global::ToMeters(point), wake);
+}
+
+void PhysicBody::ApplyForceToCenter(Vec2 const& force, bool wake)
+{
+ KGE_ASSERT(body_);
+ body_->ApplyForceToCenter(b2Vec2(force.x, force.y), wake);
+}
+
+void PhysicBody::ApplyTorque(float torque, bool wake)
+{
+ KGE_ASSERT(body_);
+ body_->ApplyTorque(torque, wake);
+}
+
+void PhysicBody::SetB2Body(b2Body* body)
+{
+ body_ = body;
+ if (body_)
+ {
+ body_->SetUserData(this);
+ type_ = PhysicBody::Type(body_->GetType());
+ }
+}
+
+void PhysicBody::Destroy()
+{
+ RemoveAllFixtures();
+
+ if (body_ && world_)
+ {
+ b2World* b2world = world_->GetB2World();
+ b2world->DestroyBody(body_);
+ }
+
+ body_ = nullptr;
+ world_ = nullptr;
+
+ Component::RemoveFromActor();
+}
+
+void PhysicBody::UpdateActor()
+{
+ Actor* actor = GetBoundActor();
+ if (actor && body_)
+ {
+ Point position = global::ToPixels(body_->GetPosition());
+ float rotation = math::Radian2Degree(body_->GetAngle());
+ actor->SetPosition(position);
+ actor->SetRotation(rotation);
+ }
+}
+
+void PhysicBody::UpdateFromActor()
+{
+ Actor* actor = GetBoundActor();
+ if (actor && body_)
+ {
+ b2Vec2 position = global::ToMeters(actor->GetPosition());
+ float angle = math::Degree2Radian(actor->GetRotation());
+ body_->SetTransform(position, angle);
+ }
+}
+
+void PhysicBody::UpdateFixtureFilter(b2Fixture* fixture)
+{
+ b2Filter filter;
+ filter.categoryBits = category_bits_;
+ filter.maskBits = mask_bits_;
+ filter.groupIndex = group_index_;
+ fixture->SetFilterData(filter);
+}
+
+} // namespace physics
+} // namespace kiwano
diff --git a/src/kiwano-physics/Body.h b/src/kiwano-physics/PhysicBody.h
similarity index 70%
rename from src/kiwano-physics/Body.h
rename to src/kiwano-physics/PhysicBody.h
index 5b46cde1..07153915 100644
--- a/src/kiwano-physics/Body.h
+++ b/src/kiwano-physics/PhysicBody.h
@@ -19,17 +19,13 @@
// THE SOFTWARE.
#pragma once
-#include
#include
-#include
+#include
namespace kiwano
{
namespace physics
{
-class World;
-
-KGE_DECLARE_SMART_PTR(Body);
/**
* \addtogroup Physics
@@ -38,7 +34,7 @@ KGE_DECLARE_SMART_PTR(Body);
/// \~chinese
/// @brief 物体
-class KGE_API Body : public virtual ObjectBase
+class KGE_API PhysicBody : public Component
{
public:
/// \~chinese
@@ -51,34 +47,30 @@ public:
};
/// \~chinese
- /// @brief 初始化
- /// @param[in] world 物理世界
- /// @param[in] actor 绑定的角色
- /// @param[in] type 物体类型
- static BodyPtr Create(World* world, ActorPtr actor, Type type);
+ /// @brief 初始化物体
+ /// @param actor 绑定该物体的角色
+ /// @param type 物体类型
+ static PhysicBodyPtr Create(ActorPtr actor, Type type);
/// \~chinese
- /// @brief 初始化
- /// @param[in] world 物理世界
- /// @param[in] actor 绑定的角色
- /// @param[in] type 物体类型
- static BodyPtr Create(World* world, Actor* actor, Type type);
+ /// @brief 初始化物体
+ /// @param actor 绑定该物体的角色
+ /// @param type 物体类型
+ static PhysicBodyPtr Create(Actor* actor, Type type);
- Body();
+ PhysicBody();
- virtual ~Body();
+ virtual ~PhysicBody();
/// \~chinese
- /// @brief 初始化
+ /// @brief 初始化物体
/// @param[in] world 物理世界
- /// @param[in] actor 绑定的角色
- bool InitBody(World* world, ActorPtr actor);
+ bool Init(PhysicWorldPtr world);
/// \~chinese
- /// @brief 初始化
+ /// @brief 初始化物体
/// @param[in] world 物理世界
- /// @param[in] actor 绑定的角色
- bool InitBody(World* world, Actor* actor);
+ bool Init(PhysicWorld* world);
/// \~chinese
/// @brief 添加夹具
@@ -88,44 +80,43 @@ public:
/// @brief 添加圆形夹具
/// @param radius 圆形半径
/// @param density 物体密度
- /// @param
- Fixture* AddCircleShape(float radius, float density, float friction = 0.2f, float restitution = 0.f,
- bool is_sensor = false);
+ /// @param
+ Fixture* AddCircleShape(float radius, float density, float friction = 0.2f);
/// \~chinese
/// @brief 添加矩形夹具
/// @param size 矩形大小
/// @param density 物体密度
- Fixture* AddRectShape(Vec2 const& size, float density, float friction = 0.2f, float restitution = 0.f,
- bool is_sensor = false);
+ Fixture* AddRectShape(Vec2 const& size, float density, float friction = 0.2f);
/// \~chinese
/// @brief 添加多边形夹具
/// @param vertexs 多边形端点
/// @param density 物体密度
- Fixture* AddPolygonShape(Vector const& vertexs, float density, float friction = 0.2f,
- float restitution = 0.f, bool is_sensor = false);
+ Fixture* AddPolygonShape(Vector const& vertexs, float density, float friction = 0.2f);
/// \~chinese
/// @brief 添加线段形夹具
/// @param p1 线段起点
/// @param p2 线段终点
/// @param density 物体密度
- Fixture* AddEdgeShape(Point const& p1, Point const& p2, float density, float friction = 0.2f,
- float restitution = 0.f, bool is_sensor = false);
+ Fixture* AddEdgeShape(Point const& p1, Point const& p2, float density, float friction = 0.2f);
/// \~chinese
/// @brief 添加链条形夹具
/// @param vertexs 链条端点
/// @param loop 是否闭合
/// @param density 物体密度
- Fixture* AddChainShape(Vector const& vertexs, bool loop, float density, float friction = 0.2f,
- float restitution = 0.f, bool is_sensor = false);
+ Fixture* AddChainShape(Vector const& vertexs, bool loop, float density, float friction = 0.2f);
/// \~chinese
/// @brief 移除夹具
void RemoveFixture(FixturePtr fixture);
+ /// \~chinese
+ /// @brief 移除所有夹具
+ void RemoveAllFixtures();
+
/// \~chinese
/// @brief 获取夹具列表
FixtureList GetFixtureList() const;
@@ -160,23 +151,23 @@ public:
/// \~chinese
/// @brief 获取旋转角度
- float GetBodyRotation() const;
+ float GetRotation() const;
/// \~chinese
/// @brief 设置旋转角度
- void SetBodyRotation(float angle);
+ void SetRotation(float angle);
/// \~chinese
/// @brief 获取物体位置
- Point GetBodyPosition() const;
+ Point GetPosition() const;
/// \~chinese
/// @brief 设置物体位置
- void SetBodyPosition(Point const& pos);
+ void SetPosition(Point const& pos);
/// \~chinese
/// @brief 位置和旋转变换
- void SetBodyTransform(Point const& pos, float angle);
+ void SetTransform(Point const& pos, float angle);
/// \~chinese
/// @brief 获取质量 [kg]
@@ -297,15 +288,7 @@ public:
/// \~chinese
/// @brief 获取物体所在物理世界
- World* GetWorld() const;
-
- /// \~chinese
- /// @brief 获取物体绑定的角色
- Actor* GetActor() const;
-
- /// \~chinese
- /// @brief 设置物体绑定的角色
- void SetActor(Actor* actor);
+ PhysicWorld* GetWorld() const;
/// \~chinese
/// @brief 将物体信息更新到角色
@@ -315,43 +298,47 @@ public:
/// @brief 将角色信息更新到物体
void UpdateFromActor();
- b2Body* GetB2Body() const;
- void SetB2Body(b2Body* body);
-
-private:
- /// \~chinese
- /// @brief 销毁物体
- void UpdateFixtureFilter(b2Fixture* fixture);
-
/// \~chinese
/// @brief 销毁物体
void Destroy();
+ /// \~chinese
+ /// @brief 获取b2Body
+ b2Body* GetB2Body() const;
+
+ /// \~chinese
+ /// @brief 设置b2Body
+ void SetB2Body(b2Body* body);
+
+protected:
+ /// \~chinese
+ /// @brief 初始化组件
+ void InitComponent(Actor* actor) override;
+
+ /// \~chinese
+ /// @brief 销毁组件
+ void DestroyComponent() override;
+
private:
- Actor* actor_;
- World* world_;
+ /// \~chinese
+ /// @brief 更新夹具过滤器
+ void UpdateFixtureFilter(b2Fixture* fixture);
+
+private:
+ PhysicWorld* world_;
b2Body* body_;
- uint16_t category_bits_;
- uint16_t mask_bits_;
- int16_t group_index_;
+ uint16_t category_bits_;
+ uint16_t mask_bits_;
+ int16_t group_index_;
+ PhysicBody::Type type_;
Vector fixtures_;
};
/** @} */
-inline BodyPtr Body::Create(World* world, ActorPtr actor, Type type)
-{
- return Body::Create(world, actor.Get(), type);
-}
-
-inline bool Body::InitBody(World* world, ActorPtr actor)
-{
- return InitBody(world, actor.Get());
-}
-
-inline FixtureList Body::GetFixtureList() const
+inline FixtureList PhysicBody::GetFixtureList() const
{
KGE_ASSERT(body_);
@@ -362,157 +349,155 @@ inline FixtureList Body::GetFixtureList() const
return FixtureList(fixture);
}
-inline ContactEdgeList Body::GetContactList() const
+inline ContactEdgeList PhysicBody::GetContactList() const
{
KGE_ASSERT(body_);
- return ContactEdgeList(ContactEdge(body_->GetContactList()));
+ ContactEdge edge;
+ edge.SetB2ContactEdge(body_->GetContactList());
+ return ContactEdgeList(edge);
}
-inline uint16_t Body::GetCategoryBits() const
+inline uint16_t PhysicBody::GetCategoryBits() const
{
return category_bits_;
}
-inline uint16_t Body::GetMaskBits() const
+inline uint16_t PhysicBody::GetMaskBits() const
{
return mask_bits_;
}
-inline int16_t Body::GetGroupIndex() const
+inline int16_t PhysicBody::GetGroupIndex() const
{
return group_index_;
}
-inline float Body::GetBodyRotation() const
+inline float PhysicBody::GetRotation() const
{
KGE_ASSERT(body_);
return math::Radian2Degree(body_->GetAngle());
}
-inline void Body::SetBodyRotation(float angle)
+inline void PhysicBody::SetRotation(float angle)
{
- SetBodyTransform(GetBodyPosition(), angle);
+ SetTransform(GetPosition(), angle);
}
-inline void Body::SetBodyPosition(Point const& pos)
+inline void PhysicBody::SetPosition(Point const& pos)
{
- SetBodyTransform(pos, GetBodyRotation());
+ SetTransform(pos, GetRotation());
}
-inline float Body::GetMass() const
+inline float PhysicBody::GetMass() const
{
KGE_ASSERT(body_);
return body_->GetMass();
}
-inline float Body::GetInertia() const
+inline float PhysicBody::GetInertia() const
{
KGE_ASSERT(body_);
return body_->GetInertia();
}
-inline Body::Type Body::GetType() const
+inline PhysicBody::Type PhysicBody::GetType() const
{
- KGE_ASSERT(body_);
- return Type(body_->GetType());
+ return type_;
}
-inline void Body::SetType(Type type)
+inline void PhysicBody::SetType(Type type)
{
- KGE_ASSERT(body_);
- body_->SetType(static_cast(type));
+ if (type_ != type)
+ {
+ type_ = type;
+ if (body_)
+ {
+ body_->SetType(b2BodyType(type));
+ }
+ }
}
-inline float Body::GetGravityScale() const
+inline float PhysicBody::GetGravityScale() const
{
KGE_ASSERT(body_);
return body_->GetGravityScale();
}
-inline void Body::SetGravityScale(float scale)
+inline void PhysicBody::SetGravityScale(float scale)
{
KGE_ASSERT(body_);
body_->SetGravityScale(scale);
}
-inline bool Body::IsIgnoreRotation() const
+inline bool PhysicBody::IsIgnoreRotation() const
{
KGE_ASSERT(body_);
return body_->IsFixedRotation();
}
-inline void Body::SetIgnoreRotation(bool flag)
+inline void PhysicBody::SetIgnoreRotation(bool flag)
{
KGE_ASSERT(body_);
body_->SetFixedRotation(flag);
}
-inline bool Body::IsBullet() const
+inline bool PhysicBody::IsBullet() const
{
KGE_ASSERT(body_);
return body_->IsBullet();
}
-inline void Body::SetBullet(bool flag)
+inline void PhysicBody::SetBullet(bool flag)
{
KGE_ASSERT(body_);
body_->SetBullet(flag);
}
-inline bool Body::IsAwake() const
+inline bool PhysicBody::IsAwake() const
{
KGE_ASSERT(body_);
return body_->IsAwake();
}
-inline void Body::SetAwake(bool flag)
+inline void PhysicBody::SetAwake(bool flag)
{
KGE_ASSERT(body_);
body_->SetAwake(flag);
}
-inline bool Body::IsSleepingAllowed() const
+inline bool PhysicBody::IsSleepingAllowed() const
{
KGE_ASSERT(body_);
return body_->IsSleepingAllowed();
}
-inline void Body::SetSleepingAllowed(bool flag)
+inline void PhysicBody::SetSleepingAllowed(bool flag)
{
KGE_ASSERT(body_);
body_->SetSleepingAllowed(flag);
}
-inline bool Body::IsActive() const
+inline bool PhysicBody::IsActive() const
{
KGE_ASSERT(body_);
return body_->IsActive();
}
-inline void Body::SetActive(bool flag)
+inline void PhysicBody::SetActive(bool flag)
{
KGE_ASSERT(body_);
body_->SetActive(flag);
}
-inline Actor* Body::GetActor() const
-{
- return actor_;
-}
-
-inline void Body::SetActor(Actor* actor)
-{
- actor_ = actor;
-}
-
-inline b2Body* Body::GetB2Body() const
+inline b2Body* PhysicBody::GetB2Body() const
{
return body_;
}
-inline World* Body::GetWorld() const
+inline PhysicWorld* PhysicBody::GetWorld() const
{
return world_;
}
+
} // namespace physics
} // namespace kiwano
diff --git a/src/kiwano-physics/PhysicWorld.cpp b/src/kiwano-physics/PhysicWorld.cpp
new file mode 100644
index 00000000..fcfeadcd
--- /dev/null
+++ b/src/kiwano-physics/PhysicWorld.cpp
@@ -0,0 +1,278 @@
+// Copyright (c) 2018-2019 Kiwano - Nomango
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include
+#include
+
+namespace kiwano
+{
+namespace physics
+{
+
+class DestructionListener : public b2DestructionListener
+{
+ Function joint_destruction_callback_;
+
+public:
+ DestructionListener(Function callback)
+ : joint_destruction_callback_(callback)
+ {
+ }
+
+ void SayGoodbye(b2Joint* joint) override
+ {
+ joint_destruction_callback_(joint);
+ }
+
+ void SayGoodbye(b2Fixture* fixture) override {}
+};
+
+class ContactListener : public b2ContactListener
+{
+ Function dispatcher_;
+
+public:
+ ContactListener(Function dispatcher)
+ : dispatcher_(dispatcher)
+ {
+ }
+
+ void BeginContact(b2Contact* b2contact) override
+ {
+ Contact contact;
+ contact.SetB2Contact(b2contact);
+
+ ContactBeginEventPtr evt = new ContactBeginEvent(contact);
+ dispatcher_(evt.Get());
+ }
+
+ void EndContact(b2Contact* b2contact) override
+ {
+ PhysicBody* body_a = static_cast(b2contact->GetFixtureA()->GetBody()->GetUserData());
+ PhysicBody* body_b = static_cast(b2contact->GetFixtureB()->GetBody()->GetUserData());
+ if (!body_a || !body_b || !body_a->GetBoundActor() || !body_b->GetBoundActor())
+ {
+ // Don't dispatch contact event after the body has been detached
+ return;
+ }
+
+ Contact contact;
+ contact.SetB2Contact(b2contact);
+
+ ContactEndEventPtr evt = new ContactEndEvent(contact);
+ dispatcher_(evt.Get());
+ }
+
+ void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override
+ {
+ KGE_NOT_USED(contact);
+ KGE_NOT_USED(oldManifold);
+ }
+ void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) override
+ {
+ KGE_NOT_USED(contact);
+ KGE_NOT_USED(impulse);
+ }
+};
+
+PhysicWorldPtr PhysicWorld::Create()
+{
+ PhysicWorldPtr ptr = new (std::nothrow) PhysicWorld;
+ return ptr;
+}
+
+PhysicWorldPtr PhysicWorld::Create(const Vec2& gravity)
+{
+ PhysicWorldPtr ptr = new (std::nothrow) PhysicWorld;
+ if (ptr)
+ {
+ ptr->SetGravity(gravity);
+ }
+ return ptr;
+}
+
+PhysicWorld::PhysicWorld()
+ : world_(b2Vec2(0, 10.0f))
+ , vel_iter_(6)
+ , pos_iter_(2)
+{
+ destroy_listener_ = std::make_unique(Closure(this, &PhysicWorld::JointRemoved));
+ world_.SetDestructionListener(destroy_listener_.get());
+
+ contact_listener_ = std::make_unique(Closure(this, &PhysicWorld::DispatchEvent));
+ world_.SetContactListener(contact_listener_.get());
+}
+
+PhysicWorld::~PhysicWorld()
+{
+ world_.SetDestructionListener(nullptr);
+ world_.SetContactListener(nullptr);
+
+ // Make sure b2World was destroyed after b2Body
+ RemoveAllJoints();
+ RemoveAllBodies();
+}
+
+void PhysicWorld::AddBody(PhysicBodyPtr body)
+{
+ if (body)
+ {
+ bool success = body->Init(this);
+ KGE_ASSERT(success);
+
+ bodies_.push_back(body);
+ }
+}
+
+void PhysicWorld::RemoveBody(PhysicBodyPtr body)
+{
+ if (body)
+ {
+ auto iter = std::find(bodies_.begin(), bodies_.end(), body);
+ if (iter != bodies_.end())
+ {
+ body->Destroy();
+ bodies_.erase(iter);
+ }
+ }
+}
+
+void PhysicWorld::RemoveAllBodies()
+{
+ for (auto body : bodies_)
+ {
+ body->Destroy();
+ }
+ bodies_.clear();
+}
+
+const List& PhysicWorld::GetAllBodies() const
+{
+ return bodies_;
+}
+
+void PhysicWorld::AddJoint(JointPtr joint)
+{
+ if (joint)
+ {
+ bool success = joint->Init(this);
+ KGE_ASSERT(success);
+
+ joints_.push_back(joint);
+ }
+}
+
+void PhysicWorld::RemoveJoint(JointPtr joint)
+{
+ if (joint)
+ {
+ auto iter = std::find(joints_.begin(), joints_.end(), joint);
+ if (iter != joints_.end())
+ {
+ joint->Destroy();
+ joints_.erase(iter);
+ }
+ }
+}
+
+void PhysicWorld::RemoveAllJoints()
+{
+ for (auto joint : joints_)
+ {
+ joint->Destroy();
+ }
+ joints_.clear();
+}
+
+const List& PhysicWorld::GetAllJoints() const
+{
+ return joints_;
+}
+
+b2World* PhysicWorld::GetB2World()
+{
+ return &world_;
+}
+
+const b2World* PhysicWorld::GetB2World() const
+{
+ return &world_;
+}
+
+Vec2 PhysicWorld::GetGravity() const
+{
+ b2Vec2 g = world_.GetGravity();
+ return Vec2(g.x, g.y);
+}
+
+void PhysicWorld::SetGravity(Vec2 gravity)
+{
+ world_.SetGravity(b2Vec2(gravity.x, gravity.y));
+}
+
+ContactList PhysicWorld::GetContactList()
+{
+ Contact contact;
+ contact.SetB2Contact(world_.GetContactList());
+ return ContactList(contact);
+}
+
+void PhysicWorld::OnUpdate(Duration dt)
+{
+ // Update bodies transform from actors
+ for (auto& body : bodies_)
+ {
+ body->UpdateFromActor();
+ }
+
+ world_.Step(dt.Seconds(), vel_iter_, pos_iter_);
+
+ // Update actors transform from bodies
+ for (auto& body : bodies_)
+ {
+ if (body->GetType() != PhysicBody::Type::Static)
+ body->UpdateActor();
+ }
+}
+
+void PhysicWorld::DispatchEvent(Event* evt)
+{
+ Actor* actor = GetBoundActor();
+ if (actor)
+ {
+ actor->DispatchEvent(evt);
+ }
+}
+
+void PhysicWorld::JointRemoved(b2Joint* b2joint)
+{
+ Joint* joint = static_cast(b2joint->GetUserData());
+ if (joint)
+ {
+ auto iter = std::find(joints_.begin(), joints_.end(), joint);
+ if (iter != joints_.end())
+ {
+ joints_.erase(iter);
+ }
+ }
+}
+
+} // namespace physics
+} // namespace kiwano
diff --git a/src/kiwano-physics/World.h b/src/kiwano-physics/PhysicWorld.h
similarity index 50%
rename from src/kiwano-physics/World.h
rename to src/kiwano-physics/PhysicWorld.h
index 1e635fc4..39843882 100644
--- a/src/kiwano-physics/World.h
+++ b/src/kiwano-physics/PhysicWorld.h
@@ -19,14 +19,13 @@
// THE SOFTWARE.
#pragma once
-#include
+#include
#include
namespace kiwano
{
namespace physics
{
-KGE_DECLARE_SMART_PTR(World);
/**
* \~chinese
@@ -42,15 +41,56 @@ KGE_DECLARE_SMART_PTR(World);
* \~chinese
* @brief 物理世界
*/
-class KGE_API World : public Stage
+class KGE_API PhysicWorld : public Component
{
- friend class Body;
+ friend class PhysicBody;
friend class Joint;
public:
- World();
+ /// \~chinese
+ /// @brief 创建物理世界
+ static PhysicWorldPtr Create();
- virtual ~World();
+ /// \~chinese
+ /// @brief 创建物理世界
+ /// @param gravity 重力
+ static PhysicWorldPtr Create(const Vec2& gravity);
+
+ PhysicWorld();
+
+ virtual ~PhysicWorld();
+
+ /// \~chinese
+ /// @brief 添加物体
+ void AddBody(PhysicBodyPtr body);
+
+ /// \~chinese
+ /// @brief 移除物体
+ void RemoveBody(PhysicBodyPtr body);
+
+ /// \~chinese
+ /// @brief 移除所有物体
+ void RemoveAllBodies();
+
+ /// \~chinese
+ /// @brief 获取所有物体
+ const List& GetAllBodies() const;
+
+ /// \~chinese
+ /// @brief 添加关节
+ void AddJoint(JointPtr joint);
+
+ /// \~chinese
+ /// @brief 移除关节
+ void RemoveJoint(JointPtr joint);
+
+ /// \~chinese
+ /// @brief 移除所有关节
+ void RemoveAllJoints();
+
+ /// \~chinese
+ /// @brief 获取所有关节
+ const List& GetAllJoints() const;
/// \~chinese
/// @brief 获取重力 [N]
@@ -64,36 +104,6 @@ public:
/// @brief 获取物理接触列表
ContactList GetContactList();
- /// \~chinese
- /// @brief 获取全局缩放比例
- /// @details 缩放比例是指由物理世界的单位米转换到屏幕像素的比例,默认比例为1:100
- float GetGlobalScale() const;
-
- /// \~chinese
- /// @brief 设置全局缩放比例
- /// @details 缩放比例是指由物理世界的单位米转换到屏幕像素的比例,默认比例为1:100
- void SetGlobalScale(float scale);
-
- /// \~chinese
- /// @brief 游戏世界单位转换为物理世界单位
- /// @details 根据全局缩放比例将物理世界的单位米转换为像素单位
- float World2Stage(float value) const;
-
- /// \~chinese
- /// @brief 游戏世界单位转换为物理世界单位
- /// @details 根据全局缩放比例将物理世界的单位米转换为像素单位
- Vec2 World2Stage(const b2Vec2& pos) const;
-
- /// \~chinese
- /// @brief 物理世界单位转换为游戏世界单位
- /// @details 根据全局缩放比例将像素单位转换为物理世界的单位米
- float Stage2World(float value) const;
-
- /// \~chinese
- /// @brief 物理世界单位转换为游戏世界单位
- /// @details 根据全局缩放比例将像素单位转换为物理世界的单位米
- b2Vec2 Stage2World(const Vec2& pos) const;
-
/// \~chinese
/// @brief 设置速度迭代次数, 默认为 6
void SetVelocityIterations(int vel_iter);
@@ -102,96 +112,44 @@ public:
/// @brief 设置位置迭代次数, 默认为 2
void SetPositionIterations(int pos_iter);
+ /// \~chinese
+ /// @brief 获取b2World
b2World* GetB2World();
+ /// \~chinese
+ /// @brief 获取b2World
const b2World* GetB2World() const;
-private:
- /// \~chinese
- /// @brief 移除物体
- void RemoveBody(Body* body);
-
- /// \~chinese
- /// @brief 移除所有物体
- void RemoveAllBodies();
-
- /// \~chinese
- /// @brief 添加关节
- void AddJoint(Joint* joint);
-
- /// \~chinese
- /// @brief 移除关节
- void RemoveJoint(Joint* joint);
-
- /// \~chinese
- /// @brief 移除所有关节
- void RemoveAllJoints();
-
- /// \~chinese
- /// @brief 关节被移除
- void JointRemoved(b2Joint* joint);
-
protected:
- void Update(Duration dt) override;
+ void OnUpdate(Duration dt) override;
+
+ void DispatchEvent(Event* evt);
+
+ void JointRemoved(b2Joint* b2joint);
private:
b2World world_;
int vel_iter_;
int pos_iter_;
- float global_scale_;
- class DestructionListener;
- friend DestructionListener;
- DestructionListener* destruction_listener_;
+ List bodies_;
+ List joints_;
- class ContactListener;
- friend ContactListener;
- ContactListener* contact_listener_;
-
- bool removing_joint_;
- Vector joints_;
+ std::unique_ptr destroy_listener_;
+ std::unique_ptr contact_listener_;
};
/** @} */
-inline float World::GetGlobalScale() const
-{
- return global_scale_;
-}
-
-inline void World::SetGlobalScale(float scale)
-{
- global_scale_ = scale;
-}
-
-inline float World::World2Stage(float value) const
-{
- return value * GetGlobalScale();
-}
-
-inline Vec2 World::World2Stage(const b2Vec2& pos) const
-{
- return Point(World2Stage(pos.x), World2Stage(pos.y));
-}
-
-inline float World::Stage2World(float value) const
-{
- return value / GetGlobalScale();
-}
-
-inline b2Vec2 World::Stage2World(const Vec2& pos) const
-{
- return b2Vec2(Stage2World(pos.x), Stage2World(pos.y));
-}
-
-inline void World::SetVelocityIterations(int vel_iter)
+inline void PhysicWorld::SetVelocityIterations(int vel_iter)
{
vel_iter_ = vel_iter;
}
-inline void World::SetPositionIterations(int pos_iter)
+inline void PhysicWorld::SetPositionIterations(int pos_iter)
{
pos_iter_ = pos_iter;
}
+
} // namespace physics
} // namespace kiwano
diff --git a/src/kiwano-physics/World.cpp b/src/kiwano-physics/World.cpp
deleted file mode 100644
index 0f7d8a2a..00000000
--- a/src/kiwano-physics/World.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright (c) 2018-2019 Kiwano - Nomango
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "World.h"
-
-#include
-
-namespace kiwano
-{
-namespace physics
-{
-namespace
-{
-const float default_global_scale = 100.f; // 100 pixels per meters
-}
-
-class World::DestructionListener : public b2DestructionListener
-{
- World* world_;
-
-public:
- DestructionListener(World* world)
- : world_(world)
- {
- }
-
- void SayGoodbye(b2Joint* joint) override
- {
- if (world_)
- {
- world_->JointRemoved(joint);
- }
- }
-
- void SayGoodbye(b2Fixture* fixture) override {}
-};
-
-class World::ContactListener : public b2ContactListener
-{
- World* world_;
-
-public:
- ContactListener(World* world)
- : world_(world)
- {
- }
-
- void BeginContact(b2Contact* b2contact) override
- {
- Contact contact;
- contact.SetB2Contact(b2contact);
-
- ContactBeginEventPtr evt = new ContactBeginEvent(contact);
- world_->DispatchEvent(evt.Get());
- }
-
- void EndContact(b2Contact* b2contact) override
- {
- Contact contact;
- contact.SetB2Contact(b2contact);
-
- ContactEndEventPtr evt = new ContactEndEvent(contact);
- world_->DispatchEvent(evt.Get());
- }
-
- void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override
- {
- KGE_NOT_USED(contact);
- KGE_NOT_USED(oldManifold);
- }
- void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) override
- {
- KGE_NOT_USED(contact);
- KGE_NOT_USED(impulse);
- }
-};
-
-World::World()
- : world_(b2Vec2(0, 10.0f))
- , vel_iter_(6)
- , pos_iter_(2)
- , global_scale_(default_global_scale)
- , destruction_listener_(nullptr)
- , contact_listener_(nullptr)
- , removing_joint_(false)
-{
- destruction_listener_ = new DestructionListener(this);
- world_.SetDestructionListener(destruction_listener_);
-
- contact_listener_ = new ContactListener(this);
- world_.SetContactListener(contact_listener_);
-}
-
-World::~World()
-{
- world_.SetDestructionListener(nullptr);
- if (destruction_listener_)
- {
- delete destruction_listener_;
- destruction_listener_ = nullptr;
- }
-
- world_.SetContactListener(nullptr);
- if (contact_listener_)
- {
- delete contact_listener_;
- contact_listener_ = nullptr;
- }
-
- // Make sure b2World was destroyed after b2Body
- RemoveAllChildren();
- RemoveAllBodies();
- RemoveAllJoints();
-}
-
-void World::RemoveBody(Body* body)
-{
- if (body && body->GetB2Body())
- {
- world_.DestroyBody(body->GetB2Body());
- }
-}
-
-void World::RemoveAllBodies()
-{
- if (world_.GetBodyCount())
- {
- b2Body* body = world_.GetBodyList();
- while (body)
- {
- b2Body* next = body->GetNext();
- world_.DestroyBody(body);
- body = next;
- }
- }
-}
-
-void World::AddJoint(Joint* joint)
-{
- if (joint)
- {
- joints_.push_back(joint);
- }
-}
-
-void World::RemoveJoint(Joint* joint)
-{
- if (joint)
- {
- auto iter = std::find(joints_.begin(), joints_.end(), joint);
- if (iter != joints_.end())
- {
- joints_.erase(iter);
-
- if (joint->GetB2Joint())
- {
- removing_joint_ = true;
- world_.DestroyJoint(joint->GetB2Joint());
- removing_joint_ = false;
- }
- }
- }
-}
-
-void World::RemoveAllJoints()
-{
- if (world_.GetJointCount())
- {
- removing_joint_ = true;
- {
- b2Joint* joint = world_.GetJointList();
- while (joint)
- {
- b2Joint* next = joint->GetNext();
- world_.DestroyJoint(joint);
- joint = next;
- }
- }
- removing_joint_ = false;
- }
- joints_.clear();
-}
-
-void World::JointRemoved(b2Joint* joint)
-{
- if (!removing_joint_ && joint)
- {
- auto iter = std::find_if(joints_.begin(), joints_.end(),
- [joint](Joint* j) -> bool { return j->GetB2Joint() == joint; });
-
- if (iter != joints_.end())
- {
- joints_.erase(iter);
- }
- }
-}
-
-b2World* World::GetB2World()
-{
- return &world_;
-}
-
-const b2World* World::GetB2World() const
-{
- return &world_;
-}
-
-Vec2 World::GetGravity() const
-{
- b2Vec2 g = world_.GetGravity();
- return Vec2(g.x, g.y);
-}
-
-void World::SetGravity(Vec2 gravity)
-{
- world_.SetGravity(b2Vec2(gravity.x, gravity.y));
-}
-
-ContactList World::GetContactList()
-{
- Contact contact;
- contact.SetB2Contact(world_.GetContactList());
- return ContactList(contact);
-}
-
-void World::Update(Duration dt)
-{
-
- b2Body* b2body = world_.GetBodyList();
- while (b2body)
- {
- Body* body = static_cast(b2body->GetUserData());
- if (body && body->GetType() != Body::Type::Static)
- {
- body->UpdateFromActor();
- }
-
- b2body = b2body->GetNext();
- }
-
- world_.Step(dt.Seconds(), vel_iter_, pos_iter_);
-
- b2body = world_.GetBodyList();
- while (b2body)
- {
- Body* body = static_cast(b2body->GetUserData());
- if (body && body->GetType() != Body::Type::Static)
- {
- body->UpdateActor();
- }
-
- b2body = b2body->GetNext();
- }
-
- Stage::Update(dt);
-}
-
-} // namespace physics
-} // namespace kiwano
diff --git a/src/kiwano-physics/kiwano-physics.h b/src/kiwano-physics/kiwano-physics.h
index b0e92e43..ebbec21f 100644
--- a/src/kiwano-physics/kiwano-physics.h
+++ b/src/kiwano-physics/kiwano-physics.h
@@ -20,9 +20,9 @@
#pragma once
-#include
+#include
#include
#include
#include
#include
-#include
+#include
diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp
index 82624667..5e6a53cf 100644
--- a/src/kiwano/2d/Actor.cpp
+++ b/src/kiwano/2d/Actor.cpp
@@ -68,11 +68,16 @@ Actor::Actor()
{
}
-Actor::~Actor() {}
+Actor::~Actor()
+{
+ RemoveAllComponents();
+ RemoveAllChildren();
+}
void Actor::Update(Duration dt)
{
UpdateActions(this, dt);
+ UpdateComponents(dt);
UpdateTimers(dt);
if (!update_pausing_)
@@ -159,7 +164,7 @@ void Actor::RenderBorder(RenderContext& ctx)
for (auto& child : children_)
{
- child.RenderBorder(ctx);
+ child->RenderBorder(ctx);
}
}
@@ -221,7 +226,10 @@ bool Actor::HandleEvent(Event* evt)
{
next = component->GetNext();
- component->HandleEvent(evt);
+ if (component->IsEnable())
+ {
+ component->HandleEvent(evt);
+ }
}
}
@@ -273,6 +281,23 @@ bool Actor::HandleEvent(Event* evt)
return true;
}
+void Actor::UpdateComponents(Duration dt)
+{
+ if (!components_.IsEmpty())
+ {
+ ComponentPtr next;
+ for (auto component = components_.GetFirst(); component; component = next)
+ {
+ next = component->GetNext();
+
+ if (component->IsEnable())
+ {
+ component->OnUpdate(dt);
+ }
+ }
+ }
+}
+
const Matrix3x2& Actor::GetTransformMatrix() const
{
UpdateTransform();
@@ -318,7 +343,7 @@ void Actor::UpdateTransform() const
// update children's transform
for (const auto& child : children_)
- child.dirty_transform_ = true;
+ child->dirty_transform_ = true;
}
void Actor::UpdateOpacity()
@@ -334,7 +359,7 @@ void Actor::UpdateOpacity()
for (auto& child : children_)
{
- child.UpdateOpacity();
+ child->UpdateOpacity();
}
}
@@ -345,7 +370,7 @@ void Actor::SetStage(Stage* stage)
stage_ = stage;
for (auto& child : children_)
{
- child.stage_ = stage;
+ child->stage_ = stage;
}
}
}
@@ -356,7 +381,7 @@ void Actor::Reorder()
{
ActorPtr me = this;
- parent_->children_.Remove(me.Get());
+ parent_->children_.Remove(me);
ActorPtr sibling = parent_->children_.GetLast();
@@ -373,11 +398,11 @@ void Actor::Reorder()
if (sibling)
{
- parent_->children_.InsertAfter(me.Get(), sibling);
+ parent_->children_.InsertAfter(me, sibling);
}
else
{
- parent_->children_.PushFront(me.Get());
+ parent_->children_.PushFront(me);
}
}
}
@@ -487,7 +512,7 @@ void Actor::SetRotation(float angle)
is_fast_transform_ = false;
}
-void Actor::AddChild(Actor* child, int zorder)
+void Actor::AddChild(ActorPtr child, int zorder)
{
KGE_ASSERT(child && "Actor::AddChild failed, NULL pointer exception");
@@ -519,11 +544,6 @@ void Actor::AddChild(Actor* child, int zorder)
}
}
-void Actor::AddChild(ActorPtr child, int zorder)
-{
- AddChild(child.Get());
-}
-
void Actor::AddChildren(Vector const& children)
{
for (const auto& actor : children)
@@ -549,9 +569,9 @@ Vector Actor::GetChildren(String const& name) const
for (const auto& child : children_)
{
- if (child.hash_name_ == hash_code && child.IsName(name))
+ if (child->hash_name_ == hash_code && child->IsName(name))
{
- children.push_back(const_cast(&child));
+ children.push_back(child);
}
}
return children;
@@ -563,9 +583,9 @@ ActorPtr Actor::GetChild(String const& name) const
for (const auto& child : children_)
{
- if (child.hash_name_ == hash_code && child.IsName(name))
+ if (child->hash_name_ == hash_code && child->IsName(name))
{
- return const_cast(&child);
+ return child;
}
}
return nullptr;
@@ -590,19 +610,15 @@ void Actor::RemoveFromParent()
}
Component* Actor::AddComponent(ComponentPtr component)
-{
- return this->AddComponent(component.Get());
-}
-
-Component* Actor::AddComponent(Component* component)
{
KGE_ASSERT(component && "AddComponent failed, NULL pointer exception");
if (component)
{
+ component->InitComponent(this);
components_.PushBack(component);
}
- return component;
+ return component.Get();
}
ComponentList& Actor::GetAllComponents()
@@ -615,6 +631,16 @@ const ComponentList& Actor::GetAllComponents() const
return components_;
}
+void Actor::RemoveComponent(ComponentPtr component)
+{
+ auto iter = std::find(components_.begin(), components_.end(), component);
+ if (iter != components_.end())
+ {
+ component->DestroyComponent();
+ components_.Remove(component);
+ }
+}
+
void Actor::RemoveComponents(String const& name)
{
if (!components_.IsEmpty())
@@ -626,6 +652,7 @@ void Actor::RemoveComponents(String const& name)
if (component->IsName(name))
{
+ component->DestroyComponent();
components_.Remove(component);
}
}
@@ -634,15 +661,21 @@ void Actor::RemoveComponents(String const& name)
void Actor::RemoveAllComponents()
{
+ // Destroy all components
+ if (!components_.IsEmpty())
+ {
+ ComponentPtr next;
+ for (auto component = components_.GetFirst(); component; component = next)
+ {
+ next = component->GetNext();
+
+ component->DestroyComponent();
+ }
+ }
components_.Clear();
}
void Actor::RemoveChild(ActorPtr child)
-{
- RemoveChild(child.Get());
-}
-
-void Actor::RemoveChild(Actor* child)
{
KGE_ASSERT(child && "Actor::RemoveChild failed, NULL pointer exception");
diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h
index 045fc1e0..95f08b40 100644
--- a/src/kiwano/2d/Actor.h
+++ b/src/kiwano/2d/Actor.h
@@ -326,10 +326,6 @@ public:
/// @brief 添加子角色
void AddChild(ActorPtr child, int zorder = 0);
- /// \~chinese
- /// @brief 添加子角色
- void AddChild(Actor* child, int zorder = 0);
-
/// \~chinese
/// @brief 添加多个子角色
void AddChildren(Vector const& children);
@@ -354,10 +350,6 @@ public:
/// @brief 移除子角色
void RemoveChild(ActorPtr child);
- /// \~chinese
- /// @brief 移除子角色
- void RemoveChild(Actor* child);
-
/// \~chinese
/// @brief 移除所有名称相同的子角色
void RemoveChildren(String const& child_name);
@@ -375,11 +367,6 @@ public:
/// @param component 组件
Component* AddComponent(ComponentPtr component);
- /// \~chinese
- /// @brief 添加组件
- /// @param component 组件
- Component* AddComponent(Component* component);
-
/// \~chinese
/// @brief 获取所有组件
ComponentList& GetAllComponents();
@@ -388,6 +375,10 @@ public:
/// @brief 获取所有组件
const ComponentList& GetAllComponents() const;
+ /// \~chinese
+ /// @brief 移除组件
+ void RemoveComponent(ComponentPtr component);
+
/// \~chinese
/// @brief 移除组件
/// @param name 组件名称
@@ -476,6 +467,10 @@ protected:
/// @brief 处理事件
bool HandleEvent(Event* evt);
+ /// \~chinese
+ /// @brief 更新组件
+ void UpdateComponents(Duration dt);
+
private:
bool visible_;
bool update_pausing_;
diff --git a/src/kiwano/2d/Button.cpp b/src/kiwano/2d/Button.cpp
index bcb10afb..6e44f0d0 100644
--- a/src/kiwano/2d/Button.cpp
+++ b/src/kiwano/2d/Button.cpp
@@ -25,18 +25,17 @@
namespace kiwano
{
-ButtonPtr Button::Create(ActorPtr actor, Callback const& click)
+ButtonPtr Button::Create(Callback const& click)
{
- return Button::Create(actor, click, nullptr, nullptr, nullptr);
+ return Button::Create(click, nullptr, nullptr, nullptr);
}
-ButtonPtr Button::Create(ActorPtr actor, Callback const& click, Callback const& pressed, Callback const& mouse_over,
+ButtonPtr Button::Create(Callback const& click, Callback const& pressed, Callback const& mouse_over,
Callback const& mouse_out)
{
ButtonPtr ptr = new (std::nothrow) Button;
if (ptr)
{
- ptr->BindActor(actor);
ptr->SetClickCallback(click);
ptr->SetPressedCallback(pressed);
ptr->SetMouseOverCallback(mouse_over);
@@ -46,52 +45,12 @@ ButtonPtr Button::Create(ActorPtr actor, Callback const& click, Callback const&
}
Button::Button()
- : enabled_(true)
- , status_(Status::Normal)
+ : status_(Status::Normal)
{
}
Button::~Button()
{
- Unbind();
-}
-
-bool Button::IsEnable() const
-{
- return enabled_;
-}
-
-void Button::SetEnabled(bool enabled)
-{
- if (enabled_ != enabled)
- {
- enabled_ = enabled;
- }
-}
-
-void Button::SetClickCallback(const Callback& func)
-{
- click_callback_ = func;
-}
-
-void Button::SetPressedCallback(const Callback& func)
-{
- pressed_callback_ = func;
-}
-
-void Button::SetMouseOverCallback(const Callback& func)
-{
- mouse_over_callback_ = func;
-}
-
-void Button::SetMouseOutCallback(const Callback& func)
-{
- mouse_out_callback_ = func;
-}
-
-Button::Status Button::GetStatus() const
-{
- return status_;
}
void Button::SetStatus(Status status)
@@ -105,7 +64,7 @@ void Button::SetStatus(Status status)
Application::GetInstance().GetMainWindow()->SetCursor(CursorType::Arrow);
if (mouse_out_callback_)
- mouse_out_callback_(this, actor_);
+ mouse_out_callback_(this, GetBoundActor());
}
else if (status == Status::Hover)
{
@@ -114,24 +73,35 @@ void Button::SetStatus(Status status)
if (old_status != Status::Pressed)
{
if (mouse_over_callback_)
- mouse_over_callback_(this, actor_);
+ mouse_over_callback_(this, GetBoundActor());
}
}
else if (status == Status::Pressed)
{
if (pressed_callback_)
- pressed_callback_(this, actor_);
+ pressed_callback_(this, GetBoundActor());
}
status_ = status;
}
}
+void Button::InitComponent(Actor* actor)
+{
+ Component::InitComponent(actor);
+ if (actor)
+ {
+ actor->SetResponsible(true);
+ }
+}
+
+void Button::DestroyComponent()
+{
+ Component::DestroyComponent();
+}
+
void Button::HandleEvent(Event* evt)
{
- if (!enabled_)
- return;
-
if (evt->IsType())
{
SetStatus(Status::Hover);
@@ -151,16 +121,7 @@ void Button::HandleEvent(Event* evt)
else if (evt->IsType())
{
if (click_callback_)
- click_callback_(this, actor_);
- }
-}
-
-void Button::BindActor(Actor* actor)
-{
- Component::BindActor(actor);
- if (actor)
- {
- actor->SetResponsible(true);
+ click_callback_(this, GetBoundActor());
}
}
diff --git a/src/kiwano/2d/Button.h b/src/kiwano/2d/Button.h
index de41c305..39a4a6b3 100644
--- a/src/kiwano/2d/Button.h
+++ b/src/kiwano/2d/Button.h
@@ -39,32 +39,22 @@ public:
/// \~chinese
/// @brief 创建按钮
- /// @param actor 绑定的角色
/// @param click 按钮点击回调函数
- static ButtonPtr Create(ActorPtr actor, Callback const& click);
+ static ButtonPtr Create(Callback const& click);
/// \~chinese
/// @brief 创建按钮
- /// @param actor 绑定的角色
/// @param click 按钮点击回调函数
/// @param pressed 按钮按下回调函数
/// @param mouse_over 按钮移入回调函数
/// @param mouse_out 按钮移出回调函数
- static ButtonPtr Create(ActorPtr actor, Callback const& click, Callback const& pressed, Callback const& mouse_over,
+ static ButtonPtr Create(Callback const& click, Callback const& pressed, Callback const& mouse_over,
Callback const& mouse_out);
Button();
virtual ~Button();
- /// \~chinese
- /// @brief 获取按钮状态是启用还是禁用
- bool IsEnable() const;
-
- /// \~chinese
- /// @brief 设置按钮启用或禁用
- void SetEnabled(bool enabled);
-
/// \~chinese
/// @brief 设置按钮点击后的回调函数
void SetClickCallback(const Callback& func);
@@ -81,14 +71,6 @@ public:
/// @brief 设置鼠标移出按钮时的回调函数
void SetMouseOutCallback(const Callback& func);
- /// \~chinese
- /// @brief 绑定到角色
- void BindActor(ActorPtr actor);
-
- /// \~chinese
- /// @brief 绑定到角色
- void BindActor(Actor* actor) override;
-
protected:
/// \~chinese
/// @brief 按钮状态
@@ -107,12 +89,19 @@ protected:
/// @brief 设置按钮状态
void SetStatus(Status status);
+ /// \~chinese
+ /// @brief 初始化组件
+ void InitComponent(Actor* actor) override;
+
+ /// \~chinese
+ /// @brief 销毁组件
+ void DestroyComponent() override;
+
/// \~chinese
/// @brief 处理角色事件
void HandleEvent(Event* evt) override;
private:
- bool enabled_;
Status status_;
Callback click_callback_;
Callback pressed_callback_;
@@ -120,9 +109,29 @@ private:
Callback mouse_out_callback_;
};
-inline void Button::BindActor(ActorPtr actor)
+inline void Button::SetClickCallback(const Callback& func)
{
- this->BindActor(actor.Get());
+ click_callback_ = func;
+}
+
+inline void Button::SetPressedCallback(const Callback& func)
+{
+ pressed_callback_ = func;
+}
+
+inline void Button::SetMouseOverCallback(const Callback& func)
+{
+ mouse_over_callback_ = func;
+}
+
+inline void Button::SetMouseOutCallback(const Callback& func)
+{
+ mouse_out_callback_ = func;
+}
+
+inline Button::Status Button::GetStatus() const
+{
+ return status_;
}
} // namespace kiwano
diff --git a/src/kiwano/2d/Component.cpp b/src/kiwano/2d/Component.cpp
index 5af4f3f9..a22a9c22 100644
--- a/src/kiwano/2d/Component.cpp
+++ b/src/kiwano/2d/Component.cpp
@@ -19,32 +19,36 @@
// THE SOFTWARE.
#include
+#include
namespace kiwano
{
Component::Component()
- : actor_(nullptr)
+ : enabled_(true)
+ , actor_(nullptr)
{
}
-Component::~Component()
-{
- Unbind();
-}
+Component::~Component() {}
-void Component::BindActor(Actor* actor)
+void Component::InitComponent(Actor* actor)
{
- if (actor_)
- {
- Unbind();
- }
actor_ = actor;
}
-void Component::Unbind()
+void Component::DestroyComponent()
{
actor_ = nullptr;
}
+void Component::RemoveFromActor()
+{
+ if (actor_)
+ {
+ actor_->RemoveComponent(this);
+ actor_ = nullptr;
+ }
+}
+
} // namespace kiwano
diff --git a/src/kiwano/2d/Component.h b/src/kiwano/2d/Component.h
index 6c9045e0..3fb2f6b0 100644
--- a/src/kiwano/2d/Component.h
+++ b/src/kiwano/2d/Component.h
@@ -19,6 +19,7 @@
// THE SOFTWARE.
#pragma once
+#include
#include
#include
@@ -47,35 +48,67 @@ class KGE_API Component
public:
/// \~chinese
- /// @brief 绑定到角色
- virtual void BindActor(Actor* actor);
+ /// @brief 是否启用组件
+ bool IsEnable() const;
/// \~chinese
- /// @brief 取消绑定到角色
- virtual void Unbind();
+ /// @brief 设置组件启用或禁用
+ void SetEnabled(bool enabled);
/// \~chinese
/// @brief 获取绑定的角色
Actor* GetBoundActor() const;
+ /// \~chinese
+ /// @brief 从角色中移除
+ void RemoveFromActor();
+
protected:
Component();
virtual ~Component();
+ /// \~chinese
+ /// @brief 初始化组件
+ virtual void InitComponent(Actor* actor);
+
+ /// \~chinese
+ /// @brief 销毁组件
+ virtual void DestroyComponent();
+
+ /// \~chinese
+ /// @brief 更新组件
+ virtual void OnUpdate(Duration dt);
+
/// \~chinese
/// @brief 处理角色事件
virtual void HandleEvent(Event* evt);
-protected:
+private:
+ bool enabled_;
Actor* actor_;
};
+inline bool Component::IsEnable() const
+{
+ return enabled_;
+}
+
+inline void Component::SetEnabled(bool enabled)
+{
+ enabled_ = enabled;
+}
+
inline Actor* Component::GetBoundActor() const
{
return actor_;
}
+inline void Component::OnUpdate(Duration dt)
+{
+ KGE_NOT_USED(dt);
+}
+
inline void Component::HandleEvent(Event* event)
{
KGE_NOT_USED(event);
diff --git a/src/kiwano/2d/TextActor.cpp b/src/kiwano/2d/TextActor.cpp
index 5a8e2169..63f6e00f 100644
--- a/src/kiwano/2d/TextActor.cpp
+++ b/src/kiwano/2d/TextActor.cpp
@@ -27,12 +27,7 @@ namespace kiwano
TextActorPtr TextActor::Create(const String& text)
{
- TextActorPtr ptr = new (std::nothrow) TextActor;
- if (ptr)
- {
- ptr->SetText(text);
- }
- return ptr;
+ return TextActor::Create(text, TextStyle());
}
TextActorPtr TextActor::Create(const String& text, const TextStyle& style)
@@ -48,7 +43,6 @@ TextActorPtr TextActor::Create(const String& text, const TextStyle& style)
TextActor::TextActor()
{
- layout_ = TextLayout::Create();
}
TextActor::~TextActor() {}
@@ -69,13 +63,18 @@ Size TextActor::GetSize() const
void TextActor::SetText(String const& text)
{
+ if (!layout_)
+ {
+ layout_ = TextLayout::Create();
+ }
layout_->Reset(text, style_);
}
void TextActor::SetStyle(const TextStyle& style)
{
style_ = style;
- layout_->Reset(style);
+ if (layout_)
+ layout_->Reset(style);
}
void TextActor::SetFont(FontPtr font)
@@ -83,7 +82,8 @@ void TextActor::SetFont(FontPtr font)
if (style_.font != font)
{
style_.font = font;
- layout_->SetFont(font, { 0, layout_->GetContentLength() });
+ if (layout_)
+ layout_->SetFont(font, { 0, layout_->GetContentLength() });
}
}
@@ -92,7 +92,8 @@ void TextActor::SetFontFamily(String const& family)
if (style_.font_family != family)
{
style_.font_family = family;
- layout_->SetFontFamily(family, { 0, layout_->GetContentLength() });
+ if (layout_)
+ layout_->SetFontFamily(family, { 0, layout_->GetContentLength() });
}
}
@@ -101,7 +102,8 @@ void TextActor::SetFontSize(float size)
if (style_.font_size != size)
{
style_.font_size = size;
- layout_->SetFontSize(size, { 0, layout_->GetContentLength() });
+ if (layout_)
+ layout_->SetFontSize(size, { 0, layout_->GetContentLength() });
}
}
@@ -110,7 +112,8 @@ void TextActor::SetFontWeight(uint32_t weight)
if (style_.font_weight != weight)
{
style_.font_weight = weight;
- layout_->SetFontWeight(weight, { 0, layout_->GetContentLength() });
+ if (layout_)
+ layout_->SetFontWeight(weight, { 0, layout_->GetContentLength() });
}
}
@@ -119,7 +122,8 @@ void TextActor::SetItalic(bool italic)
if (style_.italic != italic)
{
style_.italic = italic;
- layout_->SetItalic(italic, { 0, layout_->GetContentLength() });
+ if (layout_)
+ layout_->SetItalic(italic, { 0, layout_->GetContentLength() });
}
}
@@ -128,7 +132,8 @@ void TextActor::SetUnderline(bool enable)
if (style_.show_underline != enable)
{
style_.show_underline = enable;
- layout_->SetUnderline(enable, { 0, layout_->GetContentLength() });
+ if (layout_)
+ layout_->SetUnderline(enable, { 0, layout_->GetContentLength() });
}
}
@@ -137,7 +142,8 @@ void TextActor::SetStrikethrough(bool enable)
if (style_.show_strikethrough != enable)
{
style_.show_strikethrough = enable;
- layout_->SetStrikethrough(enable, { 0, layout_->GetContentLength() });
+ if (layout_)
+ layout_->SetStrikethrough(enable, { 0, layout_->GetContentLength() });
}
}
@@ -146,7 +152,8 @@ void TextActor::SetWrapWidth(float wrap_width)
if (style_.wrap_width != wrap_width)
{
style_.wrap_width = wrap_width;
- layout_->SetWrapWidth(wrap_width);
+ if (layout_)
+ layout_->SetWrapWidth(wrap_width);
}
}
@@ -155,7 +162,8 @@ void TextActor::SetLineSpacing(float line_spacing)
if (style_.line_spacing != line_spacing)
{
style_.line_spacing = line_spacing;
- layout_->SetLineSpacing(line_spacing);
+ if (layout_)
+ layout_->SetLineSpacing(line_spacing);
}
}
@@ -164,7 +172,8 @@ void TextActor::SetAlignment(TextAlign align)
if (style_.alignment != align)
{
style_.alignment = align;
- layout_->SetAlignment(align);
+ if (layout_)
+ layout_->SetAlignment(align);
}
}
@@ -173,7 +182,8 @@ void TextActor::SetFillBrush(BrushPtr brush)
if (style_.fill_brush != brush)
{
style_.fill_brush = brush;
- layout_->SetDefaultFillBrush(brush);
+ if (layout_)
+ layout_->SetDefaultFillBrush(brush);
}
}
@@ -182,7 +192,8 @@ void TextActor::SetOutlineBrush(BrushPtr brush)
if (style_.outline_brush != brush)
{
style_.outline_brush = brush;
- layout_->SetDefaultOutlineBrush(brush);
+ if (layout_)
+ layout_->SetDefaultOutlineBrush(brush);
}
}
@@ -191,7 +202,8 @@ void TextActor::SetOutlineStrokeStyle(StrokeStylePtr stroke)
if (style_.outline_stroke != stroke)
{
style_.outline_stroke = stroke;
- layout_->SetDefaultOutlineStrokeStyle(stroke);
+ if (layout_)
+ layout_->SetDefaultOutlineStrokeStyle(stroke);
}
}
@@ -221,8 +233,6 @@ void TextActor::SetOutlineColor(Color const& outline_color)
void TextActor::SetTextLayout(TextLayoutPtr layout)
{
- KGE_ASSERT(layout && "TextLayout must not be nullptr");
-
if (layout_ != layout)
{
layout_ = layout;
@@ -243,8 +253,7 @@ bool TextActor::CheckVisibility(RenderContext& ctx) const
void TextActor::UpdateDirtyLayout()
{
- KGE_ASSERT(layout_);
- if (layout_->UpdateWhenDirty())
+ if (layout_ && layout_->UpdateWhenDirty())
{
ForceUpdateLayout();
}
@@ -252,10 +261,15 @@ void TextActor::UpdateDirtyLayout()
void TextActor::ForceUpdateLayout()
{
- KGE_ASSERT(layout_);
-
- layout_->UpdateWhenDirty();
- SetSize(layout_->GetSize());
+ if (layout_)
+ {
+ layout_->UpdateWhenDirty();
+ SetSize(layout_->GetSize());
+ }
+ else
+ {
+ SetSize(Size());
+ }
}
} // namespace kiwano
diff --git a/src/kiwano/2d/TextActor.h b/src/kiwano/2d/TextActor.h
index 00d85277..62517df3 100644
--- a/src/kiwano/2d/TextActor.h
+++ b/src/kiwano/2d/TextActor.h
@@ -56,11 +56,11 @@ public:
/// \~chinese
/// @brief 获取文本
- const String& GetText() const;
+ String GetText() const;
/// \~chinese
/// @brief 获取文本样式
- const TextStyle& GetStyle() const;
+ TextStyle GetStyle() const;
/// \~chinese
/// @brief 获取文本布局
@@ -182,10 +182,13 @@ private:
/** @} */
-inline const String& TextActor::GetText() const
+inline String TextActor::GetText() const
{
- KGE_ASSERT(layout_);
- return layout_->GetContent();
+ if (layout_)
+ {
+ return layout_->GetContent();
+ }
+ return String();
}
inline FontPtr TextActor::GetFont() const
@@ -193,7 +196,7 @@ inline FontPtr TextActor::GetFont() const
return style_.font;
}
-inline const TextStyle& TextActor::GetStyle() const
+inline TextStyle TextActor::GetStyle() const
{
return style_;
}
diff --git a/src/kiwano/2d/action/ActionManager.cpp b/src/kiwano/2d/action/ActionManager.cpp
index 52ec1acd..a23e5818 100644
--- a/src/kiwano/2d/action/ActionManager.cpp
+++ b/src/kiwano/2d/action/ActionManager.cpp
@@ -43,11 +43,6 @@ void ActionManager::UpdateActions(Actor* target, Duration dt)
}
Action* ActionManager::AddAction(ActionPtr action)
-{
- return AddAction(action.Get());
-}
-
-Action* ActionManager::AddAction(Action* action)
{
KGE_ASSERT(action && "AddAction failed, NULL pointer exception");
@@ -55,7 +50,7 @@ Action* ActionManager::AddAction(Action* action)
{
actions_.PushBack(action);
}
- return action;
+ return action.Get();
}
void ActionManager::ResumeAllActions()
@@ -65,7 +60,7 @@ void ActionManager::ResumeAllActions()
for (auto& action : actions_)
{
- action.Resume();
+ action->Resume();
}
}
@@ -76,7 +71,7 @@ void ActionManager::PauseAllActions()
for (auto& action : actions_)
{
- action.Pause();
+ action->Pause();
}
}
@@ -87,7 +82,7 @@ void ActionManager::StopAllActions()
for (auto& action : actions_)
{
- action.Stop();
+ action->Stop();
}
}
@@ -97,9 +92,8 @@ ActionPtr ActionManager::GetAction(String const& name)
return nullptr;
for (auto& action : actions_)
- if (action.IsName(name))
- return &action;
-
+ if (action->IsName(name))
+ return action;
return nullptr;
}
diff --git a/src/kiwano/2d/action/ActionManager.h b/src/kiwano/2d/action/ActionManager.h
index 2334bd2e..0ffcf412 100644
--- a/src/kiwano/2d/action/ActionManager.h
+++ b/src/kiwano/2d/action/ActionManager.h
@@ -39,10 +39,6 @@ public:
/// @brief 添加动画
Action* AddAction(ActionPtr action);
- /// \~chinese
- /// @brief 添加动画
- Action* AddAction(Action* action);
-
/// \~chinese
/// @brief 继续所有暂停动画
void ResumeAllActions();
diff --git a/src/kiwano/core/EventDispatcher.cpp b/src/kiwano/core/EventDispatcher.cpp
index 286ca092..8904ecf7 100644
--- a/src/kiwano/core/EventDispatcher.cpp
+++ b/src/kiwano/core/EventDispatcher.cpp
@@ -46,11 +46,6 @@ bool EventDispatcher::DispatchEvent(Event* evt)
}
EventListener* EventDispatcher::AddListener(EventListenerPtr listener)
-{
- return AddListener(listener.Get());
-}
-
-EventListener* EventDispatcher::AddListener(EventListener* listener)
{
KGE_ASSERT(listener && "AddListener failed, NULL pointer exception");
@@ -58,7 +53,7 @@ EventListener* EventDispatcher::AddListener(EventListener* listener)
{
listeners_.PushBack(listener);
}
- return listener;
+ return listener.Get();
}
EventListener* EventDispatcher::AddListener(String const& name, EventType type, EventListener::Callback callback)
@@ -77,9 +72,9 @@ void EventDispatcher::StartListeners(String const& name)
{
for (auto& listener : listeners_)
{
- if (listener.IsName(name))
+ if (listener->IsName(name))
{
- listener.Start();
+ listener->Start();
}
}
}
@@ -88,9 +83,9 @@ void EventDispatcher::StopListeners(String const& name)
{
for (auto& listener : listeners_)
{
- if (listener.IsName(name))
+ if (listener->IsName(name))
{
- listener.Stop();
+ listener->Stop();
}
}
}
@@ -99,9 +94,9 @@ void EventDispatcher::RemoveListeners(String const& name)
{
for (auto& listener : listeners_)
{
- if (listener.IsName(name))
+ if (listener->IsName(name))
{
- listener.Remove();
+ listener->Remove();
}
}
}
@@ -110,9 +105,9 @@ void EventDispatcher::StartListeners(const EventType& type)
{
for (auto& listener : listeners_)
{
- if (listener.GetEventType() == type)
+ if (listener->GetEventType() == type)
{
- listener.Start();
+ listener->Start();
}
}
}
@@ -121,9 +116,9 @@ void EventDispatcher::StopListeners(const EventType& type)
{
for (auto& listener : listeners_)
{
- if (listener.GetEventType() == type)
+ if (listener->GetEventType() == type)
{
- listener.Stop();
+ listener->Stop();
}
}
}
@@ -132,9 +127,9 @@ void EventDispatcher::RemoveListeners(const EventType& type)
{
for (auto& listener : listeners_)
{
- if (listener.GetEventType() == type)
+ if (listener->GetEventType() == type)
{
- listener.Remove();
+ listener->Remove();
}
}
}
@@ -143,7 +138,7 @@ void EventDispatcher::StartAllListeners()
{
for (auto& listener : listeners_)
{
- listener.Start();
+ listener->Start();
}
}
@@ -151,7 +146,7 @@ void EventDispatcher::StopAllListeners()
{
for (auto& listener : listeners_)
{
- listener.Stop();
+ listener->Stop();
}
}
@@ -159,7 +154,7 @@ void EventDispatcher::RemoveAllListeners()
{
for (auto& listener : listeners_)
{
- listener.Remove();
+ listener->Remove();
}
}
diff --git a/src/kiwano/core/EventDispatcher.h b/src/kiwano/core/EventDispatcher.h
index 741e8d4d..9876071e 100644
--- a/src/kiwano/core/EventDispatcher.h
+++ b/src/kiwano/core/EventDispatcher.h
@@ -34,10 +34,6 @@ public:
/// @brief 添加监听器
EventListener* AddListener(EventListenerPtr listener);
- /// \~chinese
- /// @brief 添加监听器
- EventListener* AddListener(EventListener* listener);
-
/// \~chinese
/// @brief 添加监听器
/// @param type 监听的事件类型
diff --git a/src/kiwano/core/IntrusiveList.h b/src/kiwano/core/IntrusiveList.h
index 04e73dff..5e14170c 100644
--- a/src/kiwano/core/IntrusiveList.h
+++ b/src/kiwano/core/IntrusiveList.h
@@ -33,8 +33,8 @@ template
class IntrusiveList
{
public:
- using value_type = typename std::pointer_traits<_PtrTy>::element_type;
- using pointer = typename std::pointer_traits<_PtrTy>::pointer;
+ using value_type = typename std::pointer_traits<_PtrTy>::pointer;
+ using pointer = value_type*;
using reference = value_type&;
IntrusiveList()
@@ -50,28 +50,28 @@ public:
/// \~chinese
/// @brief 获取首元素
- const pointer GetFirst() const
+ const value_type& GetFirst() const
{
return first_;
}
/// \~chinese
/// @brief 获取首元素
- pointer GetFirst()
+ value_type& GetFirst()
{
return first_;
}
/// \~chinese
/// @brief 获取尾元素
- const pointer GetLast() const
+ const value_type& GetLast() const
{
return last_;
}
/// \~chinese
/// @brief 获取尾元素
- pointer GetLast()
+ value_type& GetLast()
{
return last_;
}
@@ -85,7 +85,7 @@ public:
/// \~chinese
/// @brief 在链表尾部添加对象
- void PushBack(pointer child)
+ void PushBack(reference child)
{
if (child->prev_)
child->prev_->next_ = child->next_;
@@ -109,7 +109,7 @@ public:
/// \~chinese
/// @brief 在链表头部添加对象
- void PushFront(pointer child)
+ void PushFront(reference child)
{
if (child->prev_)
child->prev_->next_ = child->next_;
@@ -133,7 +133,7 @@ public:
/// \~chinese
/// @brief 在链表的对象前插入新对象
- void InsertBefore(pointer child, pointer before)
+ void InsertBefore(reference child, reference before)
{
if (child->prev_)
child->prev_->next_ = child->next_;
@@ -152,7 +152,7 @@ public:
/// \~chinese
/// @brief 在链表的对象后插入新对象
- void InsertAfter(pointer child, pointer after)
+ void InsertAfter(reference child, reference after)
{
if (child->prev_)
child->prev_->next_ = child->next_;
@@ -171,7 +171,7 @@ public:
/// \~chinese
/// @brief 移除对象
- void Remove(pointer child)
+ void Remove(reference child)
{
if (child->next_)
{
@@ -199,10 +199,10 @@ public:
/// @brief 清空所有对象
void Clear()
{
- pointer p = first_;
+ value_type p = first_;
while (p)
{
- pointer tmp = p;
+ value_type tmp = p;
p = p->next_;
if (tmp)
{
@@ -222,8 +222,9 @@ public:
return true;
int pos = 0;
- pointer p = first_;
- pointer tmp = p;
+
+ value_type p = first_;
+ value_type tmp = p;
do
{
tmp = p;
@@ -245,42 +246,36 @@ public:
}
public:
- template
+ template
struct Iterator
{
using iterator_category = std::bidirectional_iterator_tag;
- using pointer = _PTy;
- using reference = typename IntrusiveList::reference;
+ using value_type = _PtrTy;
+ using pointer = _PtrTy*;
+ using reference = _PtrTy&;
using difference_type = ptrdiff_t;
- inline Iterator(pointer ptr = nullptr, bool is_end = false)
+ inline Iterator(value_type ptr = nullptr, bool is_end = false)
: base_(ptr)
, is_end_(is_end)
{
}
- inline pointer Get() const
- {
- KGE_ASSERT(!is_end_);
- return const_cast(base_);
- }
-
inline reference operator*() const
{
KGE_ASSERT(base_ && !is_end_);
- return const_cast(*base_);
+ return const_cast(base_);
}
inline pointer operator->() const
{
- KGE_ASSERT(base_ && !is_end_);
- return const_cast(base_);
+ return std::pointer_traits::pointer_to(**this);
}
inline Iterator& operator++()
{
KGE_ASSERT(base_ && !is_end_);
- pointer next = base_->GetNext();
+ value_type next = base_->GetNext();
if (next)
base_ = next;
else
@@ -330,12 +325,12 @@ public:
private:
bool is_end_;
- typename IntrusiveList::pointer base_;
+ typename std::remove_const::type base_;
};
public:
- using iterator = Iterator;
- using const_iterator = Iterator;
+ using iterator = Iterator;
+ using const_iterator = Iterator;
using reverse_iterator = std::reverse_iterator;
using const_reverse_iterator = std::reverse_iterator;
@@ -399,28 +394,28 @@ public:
return rend();
}
- inline pointer front()
+ inline value_type& front()
{
if (IsEmpty())
throw std::out_of_range("front() called on empty list");
return first_;
}
- inline const pointer front() const
+ inline const value_type& front() const
{
if (IsEmpty())
throw std::out_of_range("front() called on empty list");
return first_;
}
- inline pointer back()
+ inline value_type& back()
{
if (IsEmpty())
throw std::out_of_range("back() called on empty list");
return last_;
}
- inline const pointer back() const
+ inline const value_type& back() const
{
if (IsEmpty())
throw std::out_of_range("back() called on empty list");
@@ -428,8 +423,8 @@ public:
}
private:
- pointer first_;
- pointer last_;
+ value_type first_;
+ value_type last_;
};
@@ -439,7 +434,9 @@ template
class IntrusiveListValue
{
public:
- using pointer = typename std::pointer_traits<_PtrTy>::pointer;
+ using value_type = typename std::pointer_traits<_PtrTy>::pointer;
+ using reference = value_type&;
+ using pointer = value_type*;
IntrusiveListValue()
: prev_(nullptr)
@@ -447,7 +444,7 @@ public:
{
}
- IntrusiveListValue(pointer rhs)
+ IntrusiveListValue(value_type rhs)
: prev_(nullptr)
, next_(nullptr)
{
@@ -460,35 +457,35 @@ public:
/// \~chinese
/// @brief 获取前一元素
- const pointer GetPrev() const
+ const value_type& GetPrev() const
{
return prev_;
}
/// \~chinese
/// @brief 获取前一元素
- pointer GetPrev()
+ value_type& GetPrev()
{
return prev_;
}
/// \~chinese
/// @brief 获取下一元素
- const pointer GetNext() const
+ const value_type& GetNext() const
{
return next_;
}
/// \~chinese
/// @brief 获取下一元素
- pointer GetNext()
+ value_type& GetNext()
{
return next_;
}
private:
- pointer prev_;
- pointer next_;
+ value_type prev_;
+ value_type next_;
friend class IntrusiveList<_PtrTy>;
};
diff --git a/src/kiwano/core/TimerManager.cpp b/src/kiwano/core/TimerManager.cpp
index 44d747b9..b3d05a9c 100644
--- a/src/kiwano/core/TimerManager.cpp
+++ b/src/kiwano/core/TimerManager.cpp
@@ -71,9 +71,9 @@ void TimerManager::StopTimers(String const& name)
for (auto& timer : timers_)
{
- if (timer.IsName(name))
+ if (timer->IsName(name))
{
- timer.Stop();
+ timer->Stop();
}
}
}
@@ -85,9 +85,9 @@ void TimerManager::StartTimers(String const& name)
for (auto& timer : timers_)
{
- if (timer.IsName(name))
+ if (timer->IsName(name))
{
- timer.Start();
+ timer->Start();
}
}
}
@@ -99,9 +99,9 @@ void TimerManager::RemoveTimers(String const& name)
for (auto& timer : timers_)
{
- if (timer.IsName(name))
+ if (timer->IsName(name))
{
- timer.Remove();
+ timer->Remove();
}
}
}
@@ -113,7 +113,7 @@ void TimerManager::StopAllTimers()
for (auto& timer : timers_)
{
- timer.Stop();
+ timer->Stop();
}
}
@@ -124,7 +124,7 @@ void TimerManager::StartAllTimers()
for (auto& timer : timers_)
{
- timer.Start();
+ timer->Start();
}
}
diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp
index 5ad04f40..ca29f4d4 100644
--- a/src/kiwano/platform/Application.cpp
+++ b/src/kiwano/platform/Application.cpp
@@ -63,17 +63,17 @@ void Application::Run(RunnerPtr runner, bool debug)
}
// Everything is ready
- runner->OnReady();
- runner->SetLastUpdateTime(Time::Now());
+ runner->Ready();
quiting_ = false;
while (!quiting_)
{
- quiting_ = !runner->MainLoop();
+ if (!runner->MainLoop())
+ quiting_ = true;
}
// Destroy all resources
- runner->OnDestroy();
+ runner->Destroy();
this->Destroy();
}
diff --git a/src/kiwano/platform/Runner.cpp b/src/kiwano/platform/Runner.cpp
index 55a3fdfe..ec915ba0 100644
--- a/src/kiwano/platform/Runner.cpp
+++ b/src/kiwano/platform/Runner.cpp
@@ -58,7 +58,7 @@ RunnerPtr Runner::Create(WindowPtr main_window, Function on_ready, Funct
SmartPtr ptr = new (std::nothrow) CallbackRunner;
if (ptr)
{
- ptr->on_ready = on_ready;
+ ptr->on_ready = on_ready;
ptr->on_destroy = on_destroy;
ptr->SetMainWindow(main_window);
}
@@ -97,4 +97,21 @@ bool Runner::MainLoop()
return true;
}
+void Runner::Ready()
+{
+ OnReady();
+ last_update_time_ = Time::Now();
+}
+
+void Runner::Destroy()
+{
+ OnDestroy();
+
+ if (main_window_)
+ {
+ main_window_->Destroy();
+ main_window_.Reset();
+ }
+}
+
} // namespace kiwano
diff --git a/src/kiwano/platform/Runner.h b/src/kiwano/platform/Runner.h
index 7f4d5f51..6b22016f 100644
--- a/src/kiwano/platform/Runner.h
+++ b/src/kiwano/platform/Runner.h
@@ -26,6 +26,8 @@
namespace kiwano
{
+class Application;
+
KGE_DECLARE_SMART_PTR(Runner);
/**
@@ -34,6 +36,8 @@ KGE_DECLARE_SMART_PTR(Runner);
*/
class KGE_API Runner : public virtual ObjectBase
{
+ friend class Application;
+
public:
/// \~chinese
/// @brief 创建程序运行器
@@ -85,9 +89,10 @@ public:
/// @brief 获取上一次更新时间
Time GetLastUpdateTime() const;
- /// \~chinese
- /// @brief 设置上一次更新时间
- void SetLastUpdateTime(Time time);
+private:
+ void Ready();
+
+ void Destroy();
private:
WindowPtr main_window_;
@@ -118,9 +123,4 @@ inline Time Runner::GetLastUpdateTime() const
return last_update_time_;
}
-inline void Runner::SetLastUpdateTime(Time time)
-{
- last_update_time_ = time;
-}
-
} // namespace kiwano
diff --git a/src/kiwano/platform/Window.cpp b/src/kiwano/platform/Window.cpp
index 35ccc97e..e784c7cb 100644
--- a/src/kiwano/platform/Window.cpp
+++ b/src/kiwano/platform/Window.cpp
@@ -33,7 +33,6 @@ Window::Window()
Window::~Window()
{
- Destroy();
}
EventPtr Window::PollEvent()