Add physic::Contact
This commit is contained in:
parent
eb069a9fef
commit
dade0ef4cd
|
|
@ -12,6 +12,8 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Body.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Contact.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\ContactListener.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Fixture.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\helper.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-physics\Joint.h" />
|
||||
|
|
@ -21,6 +23,8 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Body.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Contact.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\ContactListener.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Fixture.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Joint.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Shape.cpp" />
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
<ClInclude Include="..\..\src\kiwano-physics\Shape.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\ContactListener.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Body.cpp" />
|
||||
|
|
@ -15,5 +17,7 @@
|
|||
<ClCompile Include="..\..\src\kiwano-physics\Joint.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Shape.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Fixture.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\Contact.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano-physics\ContactListener.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -36,7 +36,7 @@ namespace
|
|||
|
||||
uint32_t write_data(void* buffer, uint32_t size, uint32_t nmemb, void* userp)
|
||||
{
|
||||
kiwano::string* recv_buffer = (kiwano::string*)userp;
|
||||
core::string* recv_buffer = (core::string*)userp;
|
||||
uint32_t total = size * nmemb;
|
||||
|
||||
// add data to the end of recv_buffer
|
||||
|
|
@ -46,10 +46,10 @@ namespace
|
|||
return total;
|
||||
}
|
||||
|
||||
kiwano::string convert_to_utf8(kiwano::wstring const& str)
|
||||
core::string convert_to_utf8(core::wstring const& str)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
|
||||
kiwano::string result;
|
||||
core::string result;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -63,10 +63,10 @@ namespace
|
|||
return result;
|
||||
}
|
||||
|
||||
kiwano::wstring convert_from_utf8(kiwano::string const& str)
|
||||
core::wstring convert_from_utf8(core::string const& str)
|
||||
{
|
||||
kiwano::string_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
|
||||
kiwano::wstring result;
|
||||
core::wstring result;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -104,7 +104,7 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
bool Init(HttpClient* client, Vector<kiwano::string> const& headers, kiwano::string const& url, kiwano::string* response_data, kiwano::string* response_header, char* error_buffer)
|
||||
bool Init(HttpClient* client, Vector<core::string> const& headers, core::string const& url, core::string* response_data, core::string* response_header, char* error_buffer)
|
||||
{
|
||||
if (!SetOption(CURLOPT_ERRORBUFFER, error_buffer))
|
||||
return false;
|
||||
|
|
@ -170,11 +170,11 @@ namespace
|
|||
public:
|
||||
static inline bool GetRequest(
|
||||
HttpClient* client,
|
||||
Vector<kiwano::string> const& headers,
|
||||
kiwano::string const& url,
|
||||
Vector<core::string> const& headers,
|
||||
core::string const& url,
|
||||
long* response_code,
|
||||
kiwano::string* response_data,
|
||||
kiwano::string* response_header,
|
||||
core::string* response_data,
|
||||
core::string* response_header,
|
||||
char* error_buffer)
|
||||
{
|
||||
Curl curl;
|
||||
|
|
@ -185,12 +185,12 @@ namespace
|
|||
|
||||
static inline bool PostRequest(
|
||||
HttpClient* client,
|
||||
Vector<kiwano::string> const& headers,
|
||||
kiwano::string const& url,
|
||||
kiwano::string const& request_data,
|
||||
Vector<core::string> const& headers,
|
||||
core::string const& url,
|
||||
core::string const& request_data,
|
||||
long* response_code,
|
||||
kiwano::string* response_data,
|
||||
kiwano::string* response_header,
|
||||
core::string* response_data,
|
||||
core::string* response_header,
|
||||
char* error_buffer)
|
||||
{
|
||||
Curl curl;
|
||||
|
|
@ -203,12 +203,12 @@ namespace
|
|||
|
||||
static inline bool PutRequest(
|
||||
HttpClient* client,
|
||||
Vector<kiwano::string> const& headers,
|
||||
kiwano::string const& url,
|
||||
kiwano::string const& request_data,
|
||||
Vector<core::string> const& headers,
|
||||
core::string const& url,
|
||||
core::string const& request_data,
|
||||
long* response_code,
|
||||
kiwano::string* response_data,
|
||||
kiwano::string* response_header,
|
||||
core::string* response_data,
|
||||
core::string* response_header,
|
||||
char* error_buffer)
|
||||
{
|
||||
Curl curl;
|
||||
|
|
@ -221,11 +221,11 @@ namespace
|
|||
|
||||
static inline bool DeleteRequest(
|
||||
HttpClient* client,
|
||||
Vector<kiwano::string> const& headers,
|
||||
kiwano::string const& url,
|
||||
Vector<core::string> const& headers,
|
||||
core::string const& url,
|
||||
long* response_code,
|
||||
kiwano::string* response_data,
|
||||
kiwano::string* response_header,
|
||||
core::string* response_data,
|
||||
core::string* response_header,
|
||||
char* error_buffer)
|
||||
{
|
||||
Curl curl;
|
||||
|
|
@ -307,13 +307,13 @@ namespace kiwano
|
|||
bool ok = false;
|
||||
long response_code = 0;
|
||||
char error_message[256] = { 0 };
|
||||
kiwano::string response_header;
|
||||
kiwano::string response_data;
|
||||
core::string response_header;
|
||||
core::string response_data;
|
||||
|
||||
kiwano::string url = convert_to_utf8(request->GetUrl());
|
||||
kiwano::string data = convert_to_utf8(request->GetData());
|
||||
core::string url = convert_to_utf8(request->GetUrl());
|
||||
core::string data = convert_to_utf8(request->GetData());
|
||||
|
||||
Vector<kiwano::string> headers;
|
||||
Vector<core::string> headers;
|
||||
headers.reserve(request->GetHeaders().size());
|
||||
for (const auto& pair : request->GetHeaders())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ namespace kiwano
|
|||
: body_(nullptr)
|
||||
, actor_(nullptr)
|
||||
, world_(nullptr)
|
||||
, category_bits_(0x0001)
|
||||
, mask_bits_(0xFFFF)
|
||||
, group_index_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +114,57 @@ namespace kiwano
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
KGE_ASSERT(body_ && world_);
|
||||
|
|
@ -252,5 +306,14 @@ namespace kiwano
|
|||
}
|
||||
}
|
||||
|
||||
void PhysicBody::UpdateFixtureFilter(b2Fixture* fixture)
|
||||
{
|
||||
b2Filter filter;
|
||||
filter.categoryBits = category_bits_;
|
||||
filter.maskBits = mask_bits_;
|
||||
filter.groupIndex = group_index_;
|
||||
fixture->SetFilterData(filter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <kiwano-physics/helper.h>
|
||||
#include <kiwano-physics/Shape.h>
|
||||
#include <kiwano-physics/Fixture.h>
|
||||
#include <kiwano-physics/Contact.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -60,11 +61,26 @@ namespace kiwano
|
|||
PhysicFixture AddChainShape(Vector<Point> const& vertexs, bool loop, float density = 0.f);
|
||||
|
||||
// 삿혤셸야
|
||||
PhysicFixture GetFixture() const { KGE_ASSERT(body_); PhysicFixture(body_->GetFixtureList()); }
|
||||
PhysicFixture GetFixtureList() const { KGE_ASSERT(body_); PhysicFixture(body_->GetFixtureList()); }
|
||||
|
||||
// 盧뇜셸야
|
||||
void RemoveFixture(PhysicFixture const& fixture);
|
||||
|
||||
// »ñÈ¡½Ó´¥±ß
|
||||
PhysicContactEdge GetContactList() const { KGE_ASSERT(body_); PhysicContactEdge(body_->GetContactList()); }
|
||||
|
||||
// Àà±ðÂë
|
||||
uint16_t GetCategoryBits() const { return category_bits_; }
|
||||
void SetCategoryBits(uint16_t category_bits);
|
||||
|
||||
// ÅöײÑÚÂë
|
||||
uint16_t GetMaskBits() const { return mask_bits_; }
|
||||
void SetMaskBits(uint16_t mask_bits);
|
||||
|
||||
// ×éË÷Òý
|
||||
int16_t GetGroupIndex() const { return group_index_; }
|
||||
void SetGroupIndex(int16_t index);
|
||||
|
||||
// 旗瘻실똑
|
||||
float GetBodyRotation() const { KGE_ASSERT(body_); return math::Radian2Degree(body_->GetAngle()); }
|
||||
void SetBodyRotation(float angle) { SetBodyTransform(GetBodyPosition(), angle); }
|
||||
|
|
@ -143,10 +159,17 @@ namespace kiwano
|
|||
void UpdateActor();
|
||||
void UpdateFromActor();
|
||||
|
||||
protected:
|
||||
void UpdateFixtureFilter(b2Fixture* fixture);
|
||||
|
||||
protected:
|
||||
Actor* actor_;
|
||||
PhysicWorld* world_;
|
||||
b2Body* body_;
|
||||
|
||||
uint16_t category_bits_;
|
||||
uint16_t mask_bits_;
|
||||
int16_t group_index_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
// 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/Contact.h>
|
||||
#include <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/World.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace physics
|
||||
{
|
||||
|
||||
PhysicContact::PhysicContact()
|
||||
: contact_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
PhysicContact::PhysicContact(b2Contact* contact)
|
||||
: PhysicContact()
|
||||
{
|
||||
SetB2Contact(contact);
|
||||
}
|
||||
|
||||
PhysicContact PhysicContact::GetNext()
|
||||
{
|
||||
KGE_ASSERT(contact_);
|
||||
return PhysicContact(contact_->GetNext());
|
||||
}
|
||||
|
||||
const PhysicContact PhysicContact::GetNext() const
|
||||
{
|
||||
KGE_ASSERT(contact_);
|
||||
return PhysicContact(contact_->GetNext());
|
||||
}
|
||||
|
||||
PhysicFixture PhysicContact::GetFixtureA()
|
||||
{
|
||||
KGE_ASSERT(contact_);
|
||||
return PhysicFixture(contact_->GetFixtureA());
|
||||
}
|
||||
|
||||
const PhysicFixture PhysicContact::GetFixtureA() const
|
||||
{
|
||||
KGE_ASSERT(contact_);
|
||||
return PhysicFixture(contact_->GetFixtureA());
|
||||
}
|
||||
|
||||
PhysicFixture PhysicContact::GetFixtureB()
|
||||
{
|
||||
KGE_ASSERT(contact_);
|
||||
return PhysicFixture(contact_->GetFixtureB());
|
||||
}
|
||||
|
||||
const PhysicFixture PhysicContact::GetFixtureB() const
|
||||
{
|
||||
KGE_ASSERT(contact_);
|
||||
return PhysicFixture(contact_->GetFixtureB());
|
||||
}
|
||||
|
||||
void PhysicContact::SetTangentSpeed(float speed)
|
||||
{
|
||||
KGE_ASSERT(contact_);
|
||||
|
||||
PhysicBody* body = GetFixtureA().GetBody();
|
||||
KGE_ASSERT(body);
|
||||
|
||||
PhysicWorld* world = body->GetWorld();
|
||||
KGE_ASSERT(world);
|
||||
|
||||
contact_->SetTangentSpeed(world->Stage2World(speed));
|
||||
}
|
||||
|
||||
float PhysicContact::GetTangentSpeed() const
|
||||
{
|
||||
KGE_ASSERT(contact_);
|
||||
|
||||
const PhysicBody* body = GetFixtureA().GetBody();
|
||||
KGE_ASSERT(body);
|
||||
|
||||
const PhysicWorld* world = body->GetWorld();
|
||||
KGE_ASSERT(world);
|
||||
|
||||
return world->World2Stage(contact_->GetTangentSpeed());
|
||||
}
|
||||
|
||||
|
||||
PhysicContactEdge::PhysicContactEdge()
|
||||
: edge_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
PhysicContactEdge::PhysicContactEdge(b2ContactEdge* edge)
|
||||
: PhysicContactEdge()
|
||||
{
|
||||
SetB2ContactEdge(edge);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
// 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-physics/helper.h>
|
||||
#include <kiwano-physics/Fixture.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace physics
|
||||
{
|
||||
class PhysicBody;
|
||||
|
||||
// 接触
|
||||
class KGE_API PhysicContact
|
||||
{
|
||||
public:
|
||||
PhysicContact();
|
||||
PhysicContact(b2Contact* contact);
|
||||
|
||||
// 是否是接触
|
||||
bool IsTouching() const { KGE_ASSERT(contact_); return contact_->IsTouching(); }
|
||||
|
||||
// 启用或禁用 (仅作用于一个时间步)
|
||||
void SetEnabled(bool flag) { KGE_ASSERT(contact_); contact_->SetEnabled(flag); }
|
||||
bool IsEnabled() const { KGE_ASSERT(contact_); return contact_->IsEnabled(); }
|
||||
|
||||
// 获取下一接触
|
||||
PhysicContact GetNext();
|
||||
const PhysicContact GetNext() const;
|
||||
|
||||
// 夹具 A
|
||||
PhysicFixture GetFixtureA();
|
||||
const PhysicFixture GetFixtureA() const;
|
||||
|
||||
// 夹具 B
|
||||
PhysicFixture GetFixtureB();
|
||||
const PhysicFixture GetFixtureB() const;
|
||||
|
||||
// 摩擦
|
||||
void SetFriction(float friction) { KGE_ASSERT(contact_); contact_->SetFriction(friction); }
|
||||
float GetFriction() const { KGE_ASSERT(contact_); return contact_->GetFriction(); }
|
||||
void ResetFriction() { KGE_ASSERT(contact_); contact_->ResetFriction(); }
|
||||
|
||||
// 弹性恢复
|
||||
void SetRestitution(float restitution) { KGE_ASSERT(contact_); contact_->SetRestitution(restitution); }
|
||||
float GetRestitution() const { KGE_ASSERT(contact_); return contact_->GetRestitution(); }
|
||||
void ResetRestitution() { KGE_ASSERT(contact_); contact_->ResetRestitution(); }
|
||||
|
||||
// 切线速度
|
||||
void SetTangentSpeed(float speed);
|
||||
float GetTangentSpeed() const;
|
||||
|
||||
b2Contact* GetB2Contact() { return contact_; }
|
||||
const b2Contact* GetB2Contact() const { return contact_; }
|
||||
void SetB2Contact(b2Contact* contact) { contact_ = contact; }
|
||||
|
||||
protected:
|
||||
b2Contact* contact_;
|
||||
};
|
||||
|
||||
|
||||
// 接触边
|
||||
class KGE_API PhysicContactEdge
|
||||
{
|
||||
public:
|
||||
PhysicContactEdge();
|
||||
PhysicContactEdge(b2ContactEdge* edge);
|
||||
|
||||
// 获取接触物体
|
||||
PhysicBody* GetOtherBody() { KGE_ASSERT(edge_); return static_cast<PhysicBody*>(edge_->other->GetUserData()); }
|
||||
const PhysicBody* GetOtherBody() const { KGE_ASSERT(edge_); return static_cast<PhysicBody*>(edge_->other->GetUserData()); }
|
||||
|
||||
// 获取接触
|
||||
PhysicContact GetContact() { KGE_ASSERT(edge_); return PhysicContact(edge_->contact); }
|
||||
const PhysicContact GetContact() const { KGE_ASSERT(edge_); return PhysicContact(edge_->contact); }
|
||||
|
||||
// 获取上一接触边
|
||||
PhysicContactEdge GetPrev() { KGE_ASSERT(edge_); return PhysicContactEdge(edge_->prev); }
|
||||
const PhysicContactEdge GetPrev() const { KGE_ASSERT(edge_); return PhysicContactEdge(edge_->prev); }
|
||||
|
||||
// 获取下一接触边
|
||||
PhysicContactEdge GetNext() { KGE_ASSERT(edge_); return PhysicContactEdge(edge_->next); }
|
||||
const PhysicContactEdge GetNext() const { KGE_ASSERT(edge_); return PhysicContactEdge(edge_->next); }
|
||||
|
||||
b2ContactEdge* GetB2ContactEdge() { return edge_; }
|
||||
const b2ContactEdge* GetB2ContactEdge() const { return edge_; }
|
||||
void SetB2ContactEdge(b2ContactEdge* edge) { edge_ = edge; }
|
||||
|
||||
protected:
|
||||
b2ContactEdge* edge_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
// 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/ContactListener.h>
|
||||
#include <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/World.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace physics
|
||||
{
|
||||
PhysicContactListener::PhysicContactListener()
|
||||
: running_(true)
|
||||
{
|
||||
}
|
||||
|
||||
PhysicContactListener::~PhysicContactListener()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PhysicContactCallbackListener::PhysicContactCallbackListener()
|
||||
{
|
||||
}
|
||||
|
||||
PhysicContactCallbackListener::~PhysicContactCallbackListener()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PhysicContactListener* PhysicContactDispatcher::AddContactListener(PhysicContactListenerPtr listener)
|
||||
{
|
||||
return AddContactListener(listener.get());
|
||||
}
|
||||
|
||||
PhysicContactListener* PhysicContactDispatcher::AddContactListener(PhysicContactListener* listener)
|
||||
{
|
||||
KGE_ASSERT(listener && "AddListener failed, NULL pointer exception");
|
||||
|
||||
if (listener)
|
||||
{
|
||||
listeners_.push_back(listener);
|
||||
}
|
||||
return listener;
|
||||
}
|
||||
|
||||
void PhysicContactDispatcher::StartContactListeners(String const& listener_name)
|
||||
{
|
||||
for (auto listener = listeners_.first_item(); listener; listener = listener->next_item())
|
||||
{
|
||||
if (listener->IsName(listener_name))
|
||||
{
|
||||
listener->Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicContactDispatcher::StopContactListeners(String const& listener_name)
|
||||
{
|
||||
for (auto listener = listeners_.first_item(); listener; listener = listener->next_item())
|
||||
{
|
||||
if (listener->IsName(listener_name))
|
||||
{
|
||||
listener->Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicContactDispatcher::RemoveContactListeners(String const& listener_name)
|
||||
{
|
||||
PhysicContactListenerPtr next;
|
||||
for (auto listener = listeners_.first_item(); listener; listener = next)
|
||||
{
|
||||
next = listener->next_item();
|
||||
|
||||
if (listener->IsName(listener_name))
|
||||
{
|
||||
listeners_.remove(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicContactDispatcher::OnContactBegin(b2Contact* b2contact)
|
||||
{
|
||||
if (listeners_.empty())
|
||||
return;
|
||||
|
||||
PhysicContact contact(b2contact);
|
||||
PhysicContactListenerPtr next;
|
||||
for (auto listener = listeners_.first_item(); listener; listener = next)
|
||||
{
|
||||
next = listener->next_item();
|
||||
|
||||
if (listener->IsRunning())
|
||||
{
|
||||
listener->OnContactBegin(contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicContactDispatcher::OnContactEnd(b2Contact* b2contact)
|
||||
{
|
||||
if (listeners_.empty())
|
||||
return;
|
||||
|
||||
PhysicContact contact(b2contact);
|
||||
PhysicContactListenerPtr next;
|
||||
for (auto listener = listeners_.first_item(); listener; listener = next)
|
||||
{
|
||||
next = listener->next_item();
|
||||
|
||||
if (listener->IsRunning())
|
||||
{
|
||||
listener->OnContactEnd(contact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
// 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-physics/Contact.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace physics
|
||||
{
|
||||
class PhysicContactDispatcher;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(PhysicContactListener);
|
||||
|
||||
// 接触监听器
|
||||
class KGE_API PhysicContactListener
|
||||
: public ObjectBase
|
||||
, protected IntrusiveListItem<PhysicContactListenerPtr>
|
||||
{
|
||||
friend IntrusiveList<PhysicContactListenerPtr>;
|
||||
friend class PhysicContactDispatcher;
|
||||
|
||||
public:
|
||||
PhysicContactListener();
|
||||
virtual ~PhysicContactListener();
|
||||
|
||||
// 接触开始
|
||||
virtual void OnContactBegin(PhysicContact contact) { KGE_NOT_USED(contact); }
|
||||
|
||||
// 接触结束
|
||||
virtual void OnContactEnd(PhysicContact contact) { KGE_NOT_USED(contact); }
|
||||
|
||||
inline void Start() { running_ = true; }
|
||||
inline void Stop() { running_ = true; }
|
||||
inline bool IsRunning() const { return running_; }
|
||||
|
||||
protected:
|
||||
bool running_;
|
||||
};
|
||||
|
||||
|
||||
KGE_DECLARE_SMART_PTR(PhysicContactCallbackListener);
|
||||
|
||||
// 接触回调监听器
|
||||
class KGE_API PhysicContactCallbackListener
|
||||
: public PhysicContactListener
|
||||
{
|
||||
friend IntrusiveList<PhysicContactListenerPtr>;
|
||||
friend class PhysicContactDispatcher;
|
||||
|
||||
public:
|
||||
using ContactBeginCallback = Function<void(PhysicContact)>;
|
||||
using ContactEndCallback = Function<void(PhysicContact)>;
|
||||
|
||||
PhysicContactCallbackListener();
|
||||
virtual ~PhysicContactCallbackListener();
|
||||
|
||||
// 接触开始回调
|
||||
void SetCallbackOnContactBegin(ContactBeginCallback const& cb) { begin_ = cb; }
|
||||
ContactBeginCallback GetCallbackOnContactBegin() const { return begin_; }
|
||||
|
||||
// 接触结束回调
|
||||
void SetCallbackOnContactEnd(ContactEndCallback const& cb) { end_ = cb; }
|
||||
ContactEndCallback GetCallbackOnContactEnd() const { return end_; }
|
||||
|
||||
void OnContactBegin(PhysicContact contact) override { if (begin_) begin_(contact); }
|
||||
void OnContactEnd(PhysicContact contact) override { if (end_) end_(contact); }
|
||||
|
||||
protected:
|
||||
ContactBeginCallback begin_;
|
||||
ContactEndCallback end_;
|
||||
};
|
||||
|
||||
|
||||
// 接触分发器
|
||||
class KGE_API PhysicContactDispatcher
|
||||
{
|
||||
public:
|
||||
using Listeners = IntrusiveList<PhysicContactListenerPtr>;
|
||||
|
||||
// 添加监听器
|
||||
PhysicContactListener* AddContactListener(
|
||||
PhysicContactListenerPtr listener
|
||||
);
|
||||
|
||||
// 添加监听器
|
||||
PhysicContactListener* AddContactListener(
|
||||
PhysicContactListener* listener
|
||||
);
|
||||
|
||||
// 启动监听器
|
||||
void StartContactListeners(
|
||||
String const& listener_name
|
||||
);
|
||||
|
||||
// 停止监听器
|
||||
void StopContactListeners(
|
||||
String const& listener_name
|
||||
);
|
||||
|
||||
// 移除监听器
|
||||
void RemoveContactListeners(
|
||||
String const& listener_name
|
||||
);
|
||||
|
||||
protected:
|
||||
void OnContactBegin(b2Contact* contact);
|
||||
|
||||
void OnContactEnd(b2Contact* contact);
|
||||
|
||||
private:
|
||||
Listeners listeners_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +58,18 @@ namespace kiwano
|
|||
return PhysicFixture();
|
||||
}
|
||||
|
||||
PhysicBody* PhysicFixture::GetBody()
|
||||
{
|
||||
KGE_ASSERT(fixture_);
|
||||
return static_cast<PhysicBody*>(fixture_->GetBody()->GetUserData());
|
||||
}
|
||||
|
||||
const PhysicBody* PhysicFixture::GetBody() const
|
||||
{
|
||||
KGE_ASSERT(fixture_);
|
||||
return static_cast<const PhysicBody*>(fixture_->GetBody()->GetUserData());
|
||||
}
|
||||
|
||||
PhysicShape PhysicFixture::GetShape() const
|
||||
{
|
||||
KGE_ASSERT(fixture_);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,14 @@ namespace kiwano
|
|||
|
||||
static PhysicFixture Create(PhysicBody* body, PhysicShape* shape, float density = 0.f, float friction = 0.2f, float restitution = 0.f);
|
||||
|
||||
// 物体
|
||||
PhysicBody* GetBody();
|
||||
const PhysicBody* GetBody() const;
|
||||
|
||||
// 形状
|
||||
PhysicShape GetShape() const;
|
||||
|
||||
// 下一夹具 (同一物体上)
|
||||
PhysicFixture GetNext() const;
|
||||
|
||||
bool IsValid() const { return !!fixture_; }
|
||||
|
|
|
|||
|
|
@ -53,16 +53,37 @@ namespace kiwano
|
|||
}
|
||||
};
|
||||
|
||||
class PhysicWorld::ContactListener
|
||||
: public b2ContactListener
|
||||
{
|
||||
PhysicWorld* world_;
|
||||
|
||||
public:
|
||||
ContactListener(PhysicWorld* world)
|
||||
: world_(world)
|
||||
{
|
||||
}
|
||||
|
||||
void BeginContact(b2Contact* contact) override { world_->OnContactBegin(contact); }
|
||||
void EndContact(b2Contact* contact) override { world_->OnContactEnd(contact); }
|
||||
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); }
|
||||
};
|
||||
|
||||
PhysicWorld::PhysicWorld()
|
||||
: world_(b2Vec2(0, 10.0f))
|
||||
, vel_iter_(6)
|
||||
, pos_iter_(2)
|
||||
, global_scale_(DefaultGlobalScale)
|
||||
, 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_);
|
||||
}
|
||||
|
||||
PhysicWorld::~PhysicWorld()
|
||||
|
|
@ -74,6 +95,13 @@ namespace kiwano
|
|||
destruction_listener_ = nullptr;
|
||||
}
|
||||
|
||||
world_.SetContactListener(nullptr);
|
||||
if (contact_listener_)
|
||||
{
|
||||
delete contact_listener_;
|
||||
contact_listener_ = nullptr;
|
||||
}
|
||||
|
||||
// Make sure b2World was destroyed after b2Body
|
||||
RemoveAllChildren();
|
||||
RemoveAllBodies();
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#pragma once
|
||||
#include <kiwano-physics/Body.h>
|
||||
#include <kiwano-physics/Joint.h>
|
||||
#include <kiwano-physics/ContactListener.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -29,6 +30,7 @@ namespace kiwano
|
|||
// 物理世界
|
||||
class KGE_API PhysicWorld
|
||||
: public Stage
|
||||
, public PhysicContactDispatcher
|
||||
{
|
||||
friend class PhysicBody;
|
||||
friend class PhysicJoint;
|
||||
|
|
@ -45,32 +47,29 @@ namespace kiwano
|
|||
void SetGravity(Vec2 gravity);
|
||||
|
||||
// 获取全局缩放比例
|
||||
inline float GetGlobalScale() const { return global_scale_; }
|
||||
inline float GetGlobalScale() const { return global_scale_; }
|
||||
|
||||
// 设置全局缩放比例
|
||||
inline void SetGlobalScale(float scale) { global_scale_ = scale; }
|
||||
inline void SetGlobalScale(float scale) { global_scale_ = scale; }
|
||||
|
||||
// 游戏世界单位转换为物理世界单位
|
||||
inline float World2Stage(float value) { return value * GetGlobalScale(); }
|
||||
inline Point World2Stage(const b2Vec2& pos) { return Point(World2Stage(pos.x), World2Stage(pos.y)); }
|
||||
inline float World2Stage(float value) const { return value * GetGlobalScale(); }
|
||||
inline Point World2Stage(const b2Vec2& pos) const { return Point(World2Stage(pos.x), World2Stage(pos.y)); }
|
||||
|
||||
// 物理世界单位转换为游戏世界单位
|
||||
inline float Stage2World(float value) { return value / GetGlobalScale(); }
|
||||
inline b2Vec2 Stage2World(const Point& pos) { return b2Vec2(Stage2World(pos.x), Stage2World(pos.y)); }
|
||||
inline float Stage2World(float value) const { return value / GetGlobalScale(); }
|
||||
inline b2Vec2 Stage2World(const Point& pos) const { return b2Vec2(Stage2World(pos.x), Stage2World(pos.y)); }
|
||||
|
||||
// 设置速度迭代次数, 默认为 6
|
||||
inline void SetVelocityIterations(int vel_iter) { vel_iter_ = vel_iter; }
|
||||
inline void SetVelocityIterations(int vel_iter) { vel_iter_ = vel_iter; }
|
||||
|
||||
// 设置位置迭代次数, 默认为 2
|
||||
inline void SetPositionIterations(int pos_iter) { pos_iter_ = pos_iter; }
|
||||
inline void SetPositionIterations(int pos_iter) { pos_iter_ = pos_iter; }
|
||||
|
||||
// »ñÈ¡ Box2D ÊÀ½ç
|
||||
b2World* GetB2World();
|
||||
|
||||
// »ñÈ¡ Box2D ÊÀ½ç
|
||||
const b2World* GetB2World() const;
|
||||
|
||||
protected:
|
||||
private:
|
||||
// 移除物体
|
||||
void RemoveBody(PhysicBody* body);
|
||||
|
||||
|
|
@ -89,19 +88,22 @@ namespace kiwano
|
|||
// 关节被移除
|
||||
void JointRemoved(b2Joint* joint);
|
||||
|
||||
protected:
|
||||
void Update(Duration dt) override;
|
||||
|
||||
class DestructionListener;
|
||||
friend DestructionListener;
|
||||
|
||||
protected:
|
||||
private:
|
||||
b2World world_;
|
||||
int vel_iter_;
|
||||
int pos_iter_;
|
||||
float global_scale_;
|
||||
|
||||
class DestructionListener;
|
||||
friend DestructionListener;
|
||||
DestructionListener* destruction_listener_;
|
||||
|
||||
class ContactListener;
|
||||
friend ContactListener;
|
||||
ContactListener* contact_listener_;
|
||||
|
||||
bool removing_joint_;
|
||||
Vector<PhysicJoint*> joints_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ namespace kiwano
|
|||
|
||||
void Actor::SetStage(Stage* stage)
|
||||
{
|
||||
if (stage && stage_ != stage)
|
||||
if (stage_ != stage)
|
||||
{
|
||||
stage_ = stage;
|
||||
for (Actor* child = children_.first_item().get(); child; child = child->next_item().get())
|
||||
|
|
@ -539,6 +539,11 @@ namespace kiwano
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Actor::Children& Actor::GetAllChildren()
|
||||
{
|
||||
return children_;
|
||||
}
|
||||
|
||||
Actor::Children const & Actor::GetAllChildren() const
|
||||
{
|
||||
return children_;
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ namespace kiwano
|
|||
Actor();
|
||||
|
||||
// 更新角色
|
||||
virtual void OnUpdate(Duration dt) { KGE_UNUSED(dt); }
|
||||
virtual void OnUpdate(Duration dt) { KGE_NOT_USED(dt); }
|
||||
|
||||
// 渲染角色
|
||||
virtual void OnRender(RenderTarget* rt) { KGE_UNUSED(rt); }
|
||||
virtual void OnRender(RenderTarget* rt) { KGE_NOT_USED(rt); }
|
||||
|
||||
// 获取显示状态
|
||||
bool IsVisible() const { return visible_; }
|
||||
|
|
@ -334,6 +334,9 @@ namespace kiwano
|
|||
String const& name
|
||||
) const;
|
||||
|
||||
// 获取全部子角色
|
||||
Children& GetAllChildren();
|
||||
|
||||
// 获取全部子角色
|
||||
Children const& GetAllChildren() const;
|
||||
|
||||
|
|
@ -407,7 +410,7 @@ namespace kiwano
|
|||
|
||||
void SetStage(Stage* stage);
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool visible_;
|
||||
bool update_pausing_;
|
||||
bool cascade_opacity_;
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ namespace kiwano
|
|||
|
||||
void DebugActor::OnUpdate(Duration dt)
|
||||
{
|
||||
KGE_UNUSED(dt);
|
||||
KGE_NOT_USED(dt);
|
||||
|
||||
frame_time_.push_back(Time::Now());
|
||||
while (frame_time_.back() - frame_time_.front() >= time::Sec)
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ namespace kiwano
|
|||
if (!swallow_)
|
||||
{
|
||||
ActorPtr prev;
|
||||
for (auto child = children_.last_item(); child; child = prev)
|
||||
for (auto child = GetAllChildren().last_item(); child; child = prev)
|
||||
{
|
||||
prev = child->prev_item();
|
||||
child->Dispatch(evt);
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ namespace kiwano
|
|||
|
||||
void RoundRectActor::SetRadius(Vec2 const& radius)
|
||||
{
|
||||
SetRoundedRect(size_, radius);
|
||||
SetRoundedRect(GetSize(), radius);
|
||||
}
|
||||
|
||||
void RoundRectActor::SetRectSize(Size const& size)
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ namespace kiwano
|
|||
|
||||
inline Vec2 GetRadius() const { return radius_; }
|
||||
|
||||
inline Size GetRectSize() const { return size_; }
|
||||
inline Size GetRectSize() const { return GetSize(); }
|
||||
|
||||
void SetRadius(
|
||||
Vec2 const& radius
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace kiwano
|
|||
{
|
||||
Stage::Stage()
|
||||
{
|
||||
stage_ = this;
|
||||
SetStage(this);
|
||||
|
||||
SetAnchor(Vec2{ 0, 0 });
|
||||
SetSize(Renderer::GetInstance()->GetOutputSize());
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ namespace kiwano
|
|||
|
||||
Text::Text()
|
||||
: font_(text_default_font)
|
||||
, style_(text_default_style)
|
||||
, layout_dirty_(false)
|
||||
, format_dirty_(false)
|
||||
{
|
||||
text_layout_.SetTextStyle(text_default_style);
|
||||
}
|
||||
|
||||
Text::Text(String const& text)
|
||||
|
|
@ -65,11 +65,11 @@ namespace kiwano
|
|||
|
||||
Text::Text(String const& text, const Font & font, const TextStyle & style)
|
||||
: font_(font)
|
||||
, style_(style)
|
||||
, text_(text)
|
||||
, layout_dirty_(true)
|
||||
, format_dirty_(true)
|
||||
{
|
||||
text_layout_.SetTextStyle(style);
|
||||
}
|
||||
|
||||
Text::~Text()
|
||||
|
|
@ -84,7 +84,7 @@ namespace kiwano
|
|||
|
||||
void Text::SetStyle(const TextStyle& style)
|
||||
{
|
||||
style_ = style;
|
||||
text_layout_.SetTextStyle(style);
|
||||
layout_dirty_ = true;
|
||||
}
|
||||
|
||||
|
|
@ -121,11 +121,6 @@ namespace kiwano
|
|||
}
|
||||
}
|
||||
|
||||
void Text::SetColor(Color const& color)
|
||||
{
|
||||
style_.color = color;
|
||||
}
|
||||
|
||||
void Text::SetItalic(bool italic)
|
||||
{
|
||||
if (font_.italic != italic)
|
||||
|
|
@ -137,67 +132,73 @@ namespace kiwano
|
|||
|
||||
void Text::SetWrapWidth(float wrap_width)
|
||||
{
|
||||
if (style_.wrap_width != wrap_width)
|
||||
if (text_layout_.GetTextStyle().wrap_width != wrap_width)
|
||||
{
|
||||
style_.wrap_width = wrap_width;
|
||||
text_layout_.GetTextStyle().wrap_width = wrap_width;
|
||||
layout_dirty_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::SetLineSpacing(float line_spacing)
|
||||
{
|
||||
if (style_.line_spacing != line_spacing)
|
||||
if (text_layout_.GetTextStyle().line_spacing != line_spacing)
|
||||
{
|
||||
style_.line_spacing = line_spacing;
|
||||
text_layout_.GetTextStyle().line_spacing = line_spacing;
|
||||
layout_dirty_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::SetAlignment(TextAlign align)
|
||||
{
|
||||
if (style_.alignment != align)
|
||||
if (text_layout_.GetTextStyle().alignment != align)
|
||||
{
|
||||
style_.alignment = align;
|
||||
text_layout_.GetTextStyle().alignment = align;
|
||||
layout_dirty_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::SetUnderline(bool underline)
|
||||
{
|
||||
if (style_.underline != underline)
|
||||
if (text_layout_.GetTextStyle().underline != underline)
|
||||
{
|
||||
style_.underline = underline;
|
||||
text_layout_.GetTextStyle().underline = underline;
|
||||
layout_dirty_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::SetStrikethrough(bool strikethrough)
|
||||
{
|
||||
if (style_.strikethrough != strikethrough)
|
||||
if (text_layout_.GetTextStyle().strikethrough != strikethrough)
|
||||
{
|
||||
style_.strikethrough = strikethrough;
|
||||
text_layout_.GetTextStyle().strikethrough = strikethrough;
|
||||
layout_dirty_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::SetColor(Color const& color)
|
||||
{
|
||||
text_layout_.GetTextStyle().color = color;
|
||||
text_layout_.GetTextStyle().color = color;
|
||||
}
|
||||
|
||||
void Text::SetOutline(bool outline)
|
||||
{
|
||||
style_.outline = outline;
|
||||
text_layout_.GetTextStyle().outline = outline;
|
||||
}
|
||||
|
||||
void Text::SetOutlineColor(Color const&outline_color)
|
||||
{
|
||||
style_.outline_color = outline_color;
|
||||
text_layout_.GetTextStyle().outline_color = outline_color;
|
||||
}
|
||||
|
||||
void Text::SetOutlineWidth(float outline_width)
|
||||
{
|
||||
style_.outline_width = outline_width;
|
||||
text_layout_.GetTextStyle().outline_width = outline_width;
|
||||
}
|
||||
|
||||
void Text::SetOutlineStroke(StrokeStyle outline_stroke)
|
||||
{
|
||||
style_.outline_stroke = outline_stroke;
|
||||
text_layout_.GetTextStyle().outline_stroke = outline_stroke;
|
||||
}
|
||||
|
||||
void Text::OnRender(RenderTarget* rt)
|
||||
|
|
@ -216,13 +217,13 @@ namespace kiwano
|
|||
if (format_dirty_)
|
||||
{
|
||||
format_dirty_ = false;
|
||||
text_layout_.Update(font_);
|
||||
text_layout_.UpdateFont(font_);
|
||||
}
|
||||
|
||||
if (layout_dirty_)
|
||||
{
|
||||
layout_dirty_ = false;
|
||||
text_layout_.Update(text_, style_);
|
||||
text_layout_.UpdateLayout(text_);
|
||||
SetSize(text_layout_.GetLayoutSize());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ namespace kiwano
|
|||
inline Font GetFont() const { return font_; }
|
||||
|
||||
// 获取文本样式
|
||||
inline TextStyle GetStyle() const { return style_; }
|
||||
inline TextStyle GetStyle() const { return text_layout_.GetTextStyle(); }
|
||||
|
||||
// 获取文本布局
|
||||
inline TextLayout GetLayout() const { return text_layout_; }
|
||||
|
|
@ -171,6 +171,5 @@ namespace kiwano
|
|||
TextLayout text_layout_;
|
||||
String text_;
|
||||
Font font_;
|
||||
TextStyle style_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace kiwano
|
|||
{
|
||||
next = listener->next_item();
|
||||
|
||||
if (listener->type_ == evt.type)
|
||||
if (listener->IsRunning() && listener->type_ == evt.type)
|
||||
{
|
||||
listener->callback_(evt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,6 @@
|
|||
# pragma warning (disable: 4251)
|
||||
#endif
|
||||
|
||||
#define KGE_UNUSED(VAR) ((void)VAR)
|
||||
#define KGE_NOT_USED(VAR) ((void)VAR)
|
||||
|
||||
#define KGE_DEPRECATED(...) __declspec(deprecated(__VA_ARGS__))
|
||||
|
|
|
|||
|
|
@ -53,19 +53,18 @@ namespace kiwano
|
|||
|
||||
TextLayout::TextLayout(String const& text, Font const& font, TextStyle const& style)
|
||||
{
|
||||
Update(font);
|
||||
Update(text, style);
|
||||
UpdateFont(font);
|
||||
SetTextStyle(style);
|
||||
UpdateLayout(text);
|
||||
}
|
||||
|
||||
void TextLayout::Update(Font const& font)
|
||||
void TextLayout::UpdateFont(Font const& font)
|
||||
{
|
||||
text_format_.Update(font);
|
||||
}
|
||||
|
||||
void TextLayout::Update(String const& text, TextStyle const& style)
|
||||
void TextLayout::UpdateLayout(String const& text)
|
||||
{
|
||||
style_ = style;
|
||||
|
||||
if (text.empty())
|
||||
{
|
||||
text_format_.SetTextFormat(nullptr);
|
||||
|
|
@ -83,7 +82,7 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (style.line_spacing == 0.f)
|
||||
if (style_.line_spacing == 0.f)
|
||||
{
|
||||
hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
|
||||
}
|
||||
|
|
@ -91,25 +90,25 @@ namespace kiwano
|
|||
{
|
||||
hr = text_layout_->SetLineSpacing(
|
||||
DWRITE_LINE_SPACING_METHOD_UNIFORM,
|
||||
style.line_spacing,
|
||||
style.line_spacing * 0.8f
|
||||
style_.line_spacing,
|
||||
style_.line_spacing * 0.8f
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = text_layout_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style.alignment));
|
||||
hr = text_layout_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style_.alignment));
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = text_layout_->SetWordWrapping((style.wrap_width > 0) ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
|
||||
hr = text_layout_->SetWordWrapping((style_.wrap_width > 0) ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (style.underline)
|
||||
if (style_.underline)
|
||||
{
|
||||
hr = text_layout_->SetUnderline(true, { 0, UINT32(text.length()) });
|
||||
}
|
||||
|
|
@ -117,7 +116,7 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (style.strikethrough)
|
||||
if (style_.strikethrough)
|
||||
{
|
||||
text_layout_->SetStrikethrough(true, { 0, UINT32(text.length()) });
|
||||
}
|
||||
|
|
@ -125,9 +124,9 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (style.wrap_width > 0)
|
||||
if (style_.wrap_width > 0)
|
||||
{
|
||||
hr = text_layout_->SetMaxWidth(style.wrap_width);
|
||||
hr = text_layout_->SetMaxWidth(style_.wrap_width);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -52,15 +52,17 @@ namespace kiwano
|
|||
|
||||
TextLayout(String const& text, Font const& font, TextStyle const& style);
|
||||
|
||||
void Update(Font const& font);
|
||||
void UpdateFont(Font const& font);
|
||||
|
||||
void Update(String const& text, TextStyle const& style);
|
||||
void UpdateLayout(String const& text);
|
||||
|
||||
uint32_t GetLineCount();
|
||||
|
||||
Size GetLayoutSize() const;
|
||||
|
||||
inline TextStyle& GetTextStyle() { return style_; }
|
||||
inline TextStyle const& GetTextStyle() const { return style_; }
|
||||
inline void SetTextStyle(TextStyle const& style) { style_ = style; }
|
||||
|
||||
public:
|
||||
inline TextFormat GetTextFormat() const { return text_format_; }
|
||||
|
|
|
|||
|
|
@ -213,10 +213,10 @@ namespace kiwano
|
|||
__in DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
|
||||
IUnknown* clientDrawingEffect)
|
||||
{
|
||||
KGE_UNUSED(clientDrawingContext);
|
||||
KGE_UNUSED(measuringMode);
|
||||
KGE_UNUSED(glyphRunDescription);
|
||||
KGE_UNUSED(clientDrawingEffect);
|
||||
KGE_NOT_USED(clientDrawingContext);
|
||||
KGE_NOT_USED(measuringMode);
|
||||
KGE_NOT_USED(glyphRunDescription);
|
||||
KGE_NOT_USED(clientDrawingEffect);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
|
|
@ -311,8 +311,8 @@ namespace kiwano
|
|||
__in DWRITE_UNDERLINE const* underline,
|
||||
IUnknown* clientDrawingEffect)
|
||||
{
|
||||
KGE_UNUSED(clientDrawingContext);
|
||||
KGE_UNUSED(clientDrawingEffect);
|
||||
KGE_NOT_USED(clientDrawingContext);
|
||||
KGE_NOT_USED(clientDrawingEffect);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
|
|
@ -380,8 +380,8 @@ namespace kiwano
|
|||
__in DWRITE_STRIKETHROUGH const* strikethrough,
|
||||
IUnknown* clientDrawingEffect)
|
||||
{
|
||||
KGE_UNUSED(clientDrawingContext);
|
||||
KGE_UNUSED(clientDrawingEffect);
|
||||
KGE_NOT_USED(clientDrawingContext);
|
||||
KGE_NOT_USED(clientDrawingEffect);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
|
|
@ -451,13 +451,13 @@ namespace kiwano
|
|||
BOOL IsRightToLeft,
|
||||
IUnknown* clientDrawingEffect)
|
||||
{
|
||||
KGE_UNUSED(clientDrawingContext);
|
||||
KGE_UNUSED(originX);
|
||||
KGE_UNUSED(originY);
|
||||
KGE_UNUSED(inlineObject);
|
||||
KGE_UNUSED(IsSideways);
|
||||
KGE_UNUSED(IsRightToLeft);
|
||||
KGE_UNUSED(clientDrawingEffect);
|
||||
KGE_NOT_USED(clientDrawingContext);
|
||||
KGE_NOT_USED(originX);
|
||||
KGE_NOT_USED(originY);
|
||||
KGE_NOT_USED(inlineObject);
|
||||
KGE_NOT_USED(IsSideways);
|
||||
KGE_NOT_USED(IsRightToLeft);
|
||||
KGE_NOT_USED(clientDrawingEffect);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
|
@ -465,7 +465,7 @@ namespace kiwano
|
|||
__maybenull void* clientDrawingContext,
|
||||
__out BOOL* isDisabled)
|
||||
{
|
||||
KGE_UNUSED(clientDrawingContext);
|
||||
KGE_NOT_USED(clientDrawingContext);
|
||||
|
||||
*isDisabled = FALSE;
|
||||
return S_OK;
|
||||
|
|
@ -475,7 +475,7 @@ namespace kiwano
|
|||
__maybenull void* clientDrawingContext,
|
||||
__out DWRITE_MATRIX* transform)
|
||||
{
|
||||
KGE_UNUSED(clientDrawingContext);
|
||||
KGE_NOT_USED(clientDrawingContext);
|
||||
|
||||
pRT_->GetTransform(reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));
|
||||
return S_OK;
|
||||
|
|
@ -485,7 +485,7 @@ namespace kiwano
|
|||
__maybenull void* clientDrawingContext,
|
||||
__out float* pixelsPerDip)
|
||||
{
|
||||
KGE_UNUSED(clientDrawingContext);
|
||||
KGE_NOT_USED(clientDrawingContext);
|
||||
|
||||
float x, yUnused;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue