Add Button, PhysicWorld, PhysicBody components
This commit is contained in:
parent
9077c55b9c
commit
fcc55bac81
|
|
@ -11,24 +11,25 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Body.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\PhysicBody.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Contact.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\ContactEdge.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\ContactEvent.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Fixture.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\helper.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Global.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Joint.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\kiwano-physics.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\World.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\PhysicWorld.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Body.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\PhysicBody.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Contact.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\ContactEdge.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\ContactEvent.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Fixture.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Global.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Joint.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\World.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\PhysicWorld.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{DF599AFB-744F-41E5-AF0C-2146F90575C8}</ProjectGuid>
|
||||
|
|
|
|||
|
|
@ -2,22 +2,23 @@
|
|||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\kiwano-physics\kiwano-physics.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Body.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\World.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Joint.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\helper.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Fixture.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Contact.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\ContactEvent.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\ContactEdge.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Global.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\PhysicBody.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\PhysicWorld.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Body.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\World.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Joint.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Fixture.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Contact.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\ContactEvent.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\ContactEdge.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Global.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\PhysicBody.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\PhysicWorld.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -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 <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/World.h>
|
||||
|
||||
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<Point> 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<Point> 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
|
||||
|
|
@ -18,9 +18,9 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/PhysicBody.h>
|
||||
#include <kiwano-physics/Contact.h>
|
||||
#include <kiwano-physics/World.h>
|
||||
#include <kiwano-physics/PhysicWorld.h>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -20,13 +20,11 @@
|
|||
|
||||
#pragma once
|
||||
#include <kiwano-physics/Fixture.h>
|
||||
#include <kiwano-physics/helper.h>
|
||||
|
||||
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 <typename _Ty>
|
||||
class IteratorImpl : public std::iterator<std::forward_iterator_tag, _Ty>
|
||||
class IteratorImpl
|
||||
{
|
||||
using herit = std::iterator<std::forward_iterator_tag, _Ty>;
|
||||
|
||||
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<typename herit::reference>(elem_);
|
||||
return const_cast<reference>(elem_);
|
||||
}
|
||||
|
||||
inline typename herit::pointer operator->() const
|
||||
inline pointer operator->() const
|
||||
{
|
||||
return std::pointer_traits<typename herit::pointer>::pointer_to(**this);
|
||||
return std::pointer_traits<pointer>::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_;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <typename _Ty>
|
||||
class IteratorImpl : public std::iterator<std::forward_iterator_tag, _Ty>
|
||||
class IteratorImpl
|
||||
{
|
||||
using herit = std::iterator<std::forward_iterator_tag, _Ty>;
|
||||
|
||||
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<typename herit::reference>(elem_);
|
||||
return const_cast<reference>(elem_);
|
||||
}
|
||||
|
||||
inline typename herit::pointer operator->() const
|
||||
inline pointer operator->() const
|
||||
{
|
||||
return std::pointer_traits<typename herit::pointer>::pointer_to(**this);
|
||||
return std::pointer_traits<pointer>::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<Body*>(edge_->other->GetUserData());
|
||||
}
|
||||
|
||||
inline Contact ContactEdge::GetContact() const
|
||||
{
|
||||
KGE_ASSERT(edge_);
|
||||
|
||||
Contact contact;
|
||||
contact.SetB2Contact(edge_->contact);
|
||||
return contact;
|
||||
return static_cast<PhysicBody*>(edge_->other->GetUserData());
|
||||
}
|
||||
|
||||
inline b2ContactEdge* ContactEdge::GetB2ContactEdge() const
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/PhysicBody.h>
|
||||
#include <kiwano-physics/Contact.h>
|
||||
|
||||
namespace kiwano
|
||||
|
|
|
|||
|
|
@ -18,127 +18,111 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/PhysicBody.h>
|
||||
#include <kiwano-physics/Fixture.h>
|
||||
#include <kiwano-physics/World.h>
|
||||
#include <kiwano-physics/PhysicWorld.h>
|
||||
|
||||
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<b2CircleShape>();
|
||||
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<b2PolygonShape>();
|
||||
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<Point> const& vertexs)
|
||||
{
|
||||
FixturePtr ptr = new (std::nothrow) Fixture;
|
||||
if (ptr)
|
||||
{
|
||||
Vector<b2Vec2> 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<b2PolygonShape>();
|
||||
shape->Set(&b2vertexs[0], static_cast<int32>(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<Point> const& vertexs)
|
||||
{
|
||||
KGE_ASSERT(body);
|
||||
World* world = body->GetWorld();
|
||||
|
||||
Vector<b2Vec2> 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<b2EdgeShape>();
|
||||
shape->Set(start, end);
|
||||
|
||||
ptr->shape_ = std::move(shape);
|
||||
ptr->param_ = param;
|
||||
}
|
||||
|
||||
b2PolygonShape shape;
|
||||
shape.Set(&b2vertexs[0], static_cast<int32>(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<Point> 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<Point> const& vertexs, bool loop)
|
||||
{
|
||||
KGE_ASSERT(body);
|
||||
World* world = body->GetWorld();
|
||||
|
||||
Vector<b2Vec2> 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<b2Vec2> 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<int32>(b2vertexs.size()));
|
||||
auto shape = std::make_unique<b2ChainShape>();
|
||||
if (loop)
|
||||
{
|
||||
shape->CreateLoop(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
shape->CreateChain(&b2vertexs[0], static_cast<int32>(b2vertexs.size()));
|
||||
}
|
||||
|
||||
ptr->shape_ = std::move(shape);
|
||||
ptr->param_ = param;
|
||||
}
|
||||
else
|
||||
{
|
||||
shape.CreateChain(&b2vertexs[0], static_cast<int32>(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<Body*>(fixture_->GetBody()->GetUserData());
|
||||
return static_cast<PhysicBody*>(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
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano-physics/helper.h>
|
||||
#include <memory>
|
||||
#include <kiwano-physics/Global.h>
|
||||
|
||||
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<Point> const& vertexs);
|
||||
static FixturePtr CreatePolygon(Param const& param, Vector<Point> 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<Point> const& vertexs, bool loop = false);
|
||||
static FixturePtr CreateChain(Param const& param, Vector<Point> 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<b2Shape> shape_;
|
||||
Fixture::Param param_;
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
|
|
@ -169,13 +178,14 @@ private:
|
|||
class FixtureList
|
||||
{
|
||||
template <typename _Ty>
|
||||
class IteratorImpl : public std::iterator<std::forward_iterator_tag, _Ty>
|
||||
class IteratorImpl
|
||||
{
|
||||
using herit = std::iterator<std::forward_iterator_tag, _Ty>;
|
||||
|
||||
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<typename herit::reference>(*elem_);
|
||||
return const_cast<reference>(*elem_);
|
||||
}
|
||||
|
||||
inline pointer operator->() const
|
||||
{
|
||||
return std::pointer_traits<typename herit::pointer>::pointer_to(**this);
|
||||
return std::pointer_traits<pointer>::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<value_type>;
|
||||
using const_iterator = IteratorImpl<const value_type>;
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -19,22 +19,51 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano/kiwano.h>
|
||||
|
||||
// Box2D
|
||||
#include <3rd-party/Box2D/Box2D.h>
|
||||
#include <kiwano-physics/Global.h>
|
||||
|
||||
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
|
||||
|
|
@ -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 <kiwano/kiwano.h>
|
||||
|
||||
// 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
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano-physics/Joint.h>
|
||||
#include <kiwano-physics/World.h>
|
||||
#include <kiwano-physics/PhysicWorld.h>
|
||||
|
||||
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*>(body->GetUserData()));
|
||||
return PhysicBodyPtr(static_cast<PhysicBody*>(body->GetUserData()));
|
||||
}
|
||||
|
||||
BodyPtr Joint::GetBodyB() const
|
||||
PhysicBodyPtr Joint::GetBodyB() const
|
||||
{
|
||||
KGE_ASSERT(joint_);
|
||||
|
||||
b2Body* body = joint_->GetBodyB();
|
||||
return BodyPtr(static_cast<Body*>(body->GetUserData()));
|
||||
return PhysicBodyPtr(static_cast<PhysicBody*>(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<b2DistanceJoint*>(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<b2FrictionJoint*>(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<b2GearJoint*>(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<b2MotorJoint*>(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<b2PrismaticJoint*>(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<b2PulleyJoint*>(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<b2RevoluteJoint*>(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<b2RopeJoint*>(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<b2WeldJoint*>(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<b2WheelJoint*>(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<b2MouseJoint*>(GetB2Joint());
|
||||
return raw_joint_ != nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/helper.h>
|
||||
#include <kiwano-physics/PhysicBody.h>
|
||||
|
||||
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_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <kiwano-physics/PhysicBody.h>
|
||||
#include <kiwano-physics/PhysicWorld.h>
|
||||
|
||||
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<Point> 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<Point> 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
|
||||
|
|
@ -19,17 +19,13 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano-physics/ContactEdge.h>
|
||||
#include <kiwano-physics/Fixture.h>
|
||||
#include <kiwano-physics/helper.h>
|
||||
#include <kiwano-physics/ContactEdge.h>
|
||||
|
||||
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<Point> const& vertexs, float density, float friction = 0.2f,
|
||||
float restitution = 0.f, bool is_sensor = false);
|
||||
Fixture* AddPolygonShape(Vector<Point> 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<Point> const& vertexs, bool loop, float density, float friction = 0.2f,
|
||||
float restitution = 0.f, bool is_sensor = false);
|
||||
Fixture* AddChainShape(Vector<Point> 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<FixturePtr> 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<b2BodyType>(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
|
||||
|
|
@ -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 <kiwano-physics/PhysicWorld.h>
|
||||
#include <kiwano-physics/ContactEvent.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace physics
|
||||
{
|
||||
|
||||
class DestructionListener : public b2DestructionListener
|
||||
{
|
||||
Function<void(b2Joint*)> joint_destruction_callback_;
|
||||
|
||||
public:
|
||||
DestructionListener(Function<void(b2Joint*)> callback)
|
||||
: joint_destruction_callback_(callback)
|
||||
{
|
||||
}
|
||||
|
||||
void SayGoodbye(b2Joint* joint) override
|
||||
{
|
||||
joint_destruction_callback_(joint);
|
||||
}
|
||||
|
||||
void SayGoodbye(b2Fixture* fixture) override {}
|
||||
};
|
||||
|
||||
class ContactListener : public b2ContactListener
|
||||
{
|
||||
Function<void(Event*)> dispatcher_;
|
||||
|
||||
public:
|
||||
ContactListener(Function<void(Event*)> 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<PhysicBody*>(b2contact->GetFixtureA()->GetBody()->GetUserData());
|
||||
PhysicBody* body_b = static_cast<PhysicBody*>(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<DestructionListener>(Closure(this, &PhysicWorld::JointRemoved));
|
||||
world_.SetDestructionListener(destroy_listener_.get());
|
||||
|
||||
contact_listener_ = std::make_unique<ContactListener>(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<PhysicBodyPtr>& 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<JointPtr>& 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<Joint*>(b2joint->GetUserData());
|
||||
if (joint)
|
||||
{
|
||||
auto iter = std::find(joints_.begin(), joints_.end(), joint);
|
||||
if (iter != joints_.end())
|
||||
{
|
||||
joints_.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace physics
|
||||
} // namespace kiwano
|
||||
|
|
@ -19,14 +19,13 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/PhysicBody.h>
|
||||
#include <kiwano-physics/Joint.h>
|
||||
|
||||
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<PhysicBodyPtr>& GetAllBodies() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加关节
|
||||
void AddJoint(JointPtr joint);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除关节
|
||||
void RemoveJoint(JointPtr joint);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除所有关节
|
||||
void RemoveAllJoints();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取所有关节
|
||||
const List<JointPtr>& 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<PhysicBodyPtr> bodies_;
|
||||
List<JointPtr> joints_;
|
||||
|
||||
class ContactListener;
|
||||
friend ContactListener;
|
||||
ContactListener* contact_listener_;
|
||||
|
||||
bool removing_joint_;
|
||||
Vector<Joint*> joints_;
|
||||
std::unique_ptr<b2DestructionListener> destroy_listener_;
|
||||
std::unique_ptr<b2ContactListener> 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
|
||||
|
|
@ -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 <kiwano-physics/ContactEvent.h>
|
||||
|
||||
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<Body*>(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<Body*>(b2body->GetUserData());
|
||||
if (body && body->GetType() != Body::Type::Static)
|
||||
{
|
||||
body->UpdateActor();
|
||||
}
|
||||
|
||||
b2body = b2body->GetNext();
|
||||
}
|
||||
|
||||
Stage::Update(dt);
|
||||
}
|
||||
|
||||
} // namespace physics
|
||||
} // namespace kiwano
|
||||
|
|
@ -20,9 +20,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/PhysicBody.h>
|
||||
#include <kiwano-physics/Contact.h>
|
||||
#include <kiwano-physics/ContactEvent.h>
|
||||
#include <kiwano-physics/Fixture.h>
|
||||
#include <kiwano-physics/Joint.h>
|
||||
#include <kiwano-physics/World.h>
|
||||
#include <kiwano-physics/PhysicWorld.h>
|
||||
|
|
|
|||
|
|
@ -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<ActorPtr> const& children)
|
||||
{
|
||||
for (const auto& actor : children)
|
||||
|
|
@ -549,9 +569,9 @@ Vector<ActorPtr> 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<Actor*>(&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<Actor*>(&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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ActorPtr> 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_;
|
||||
|
|
|
|||
|
|
@ -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<MouseHoverEvent>())
|
||||
{
|
||||
SetStatus(Status::Hover);
|
||||
|
|
@ -151,16 +121,7 @@ void Button::HandleEvent(Event* evt)
|
|||
else if (evt->IsType<MouseClickEvent>())
|
||||
{
|
||||
if (click_callback_)
|
||||
click_callback_(this, actor_);
|
||||
}
|
||||
}
|
||||
|
||||
void Button::BindActor(Actor* actor)
|
||||
{
|
||||
Component::BindActor(actor);
|
||||
if (actor)
|
||||
{
|
||||
actor->SetResponsible(true);
|
||||
click_callback_(this, GetBoundActor());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -19,32 +19,36 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/2d/Component.h>
|
||||
#include <kiwano/2d/Actor.h>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano/core/Time.h>
|
||||
#include <kiwano/core/ObjectBase.h>
|
||||
#include <kiwano/core/IntrusiveList.h>
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,10 +39,6 @@ public:
|
|||
/// @brief 添加动画
|
||||
Action* AddAction(ActionPtr action);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加动画
|
||||
Action* AddAction(Action* action);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 继续所有暂停动画
|
||||
void ResumeAllActions();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,10 +34,6 @@ public:
|
|||
/// @brief 添加监听器
|
||||
EventListener* AddListener(EventListenerPtr listener);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加监听器
|
||||
EventListener* AddListener(EventListener* listener);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加监听器
|
||||
/// @param type 监听的事件类型
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ template <typename _PtrTy>
|
|||
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 <typename _PTy>
|
||||
template <typename _PtrTy>
|
||||
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<pointer&>(base_);
|
||||
}
|
||||
|
||||
inline reference operator*() const
|
||||
{
|
||||
KGE_ASSERT(base_ && !is_end_);
|
||||
return const_cast<reference>(*base_);
|
||||
return const_cast<reference>(base_);
|
||||
}
|
||||
|
||||
inline pointer operator->() const
|
||||
{
|
||||
KGE_ASSERT(base_ && !is_end_);
|
||||
return const_cast<pointer&>(base_);
|
||||
return std::pointer_traits<pointer>::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<value_type>::type base_;
|
||||
};
|
||||
|
||||
public:
|
||||
using iterator = Iterator<pointer>;
|
||||
using const_iterator = Iterator<const pointer>;
|
||||
using iterator = Iterator<value_type>;
|
||||
using const_iterator = Iterator<const value_type>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_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 <typename _PtrTy>
|
|||
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>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ RunnerPtr Runner::Create(WindowPtr main_window, Function<void()> on_ready, Funct
|
|||
SmartPtr<CallbackRunner> 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ Window::Window()
|
|||
|
||||
Window::~Window()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
EventPtr Window::PollEvent()
|
||||
|
|
|
|||
Loading…
Reference in New Issue