Merge remote-tracking branch 'refs/remotes/origin/master' into reflection-mapping
This commit is contained in:
commit
62fd66a159
|
|
@ -47,6 +47,7 @@ namespace Ndk
|
||||||
virtual void OnComponentAttached(BaseComponent& component);
|
virtual void OnComponentAttached(BaseComponent& component);
|
||||||
virtual void OnComponentDetached(BaseComponent& component);
|
virtual void OnComponentDetached(BaseComponent& component);
|
||||||
virtual void OnDetached();
|
virtual void OnDetached();
|
||||||
|
virtual void OnEntityDestruction();
|
||||||
|
|
||||||
void SetEntity(Entity* entity);
|
void SetEntity(Entity* entity);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ namespace Ndk
|
||||||
inline void BaseWidget::AddChild(std::unique_ptr<BaseWidget>&& widget)
|
inline void BaseWidget::AddChild(std::unique_ptr<BaseWidget>&& widget)
|
||||||
{
|
{
|
||||||
widget->Show(m_visible);
|
widget->Show(m_visible);
|
||||||
|
widget->SetParent(this);
|
||||||
m_children.emplace_back(std::move(widget));
|
m_children.emplace_back(std::move(widget));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ namespace Ndk
|
||||||
void OnComponentAttached(BaseComponent& component) override;
|
void OnComponentAttached(BaseComponent& component) override;
|
||||||
void OnComponentDetached(BaseComponent& component) override;
|
void OnComponentDetached(BaseComponent& component) override;
|
||||||
void OnDetached() override;
|
void OnDetached() override;
|
||||||
|
void OnEntityDestruction() override;
|
||||||
|
|
||||||
std::unique_ptr<Nz::RigidBody2D> m_object;
|
std::unique_ptr<Nz::RigidBody2D> m_object;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ namespace Ndk
|
||||||
void OnComponentAttached(BaseComponent& component) override;
|
void OnComponentAttached(BaseComponent& component) override;
|
||||||
void OnComponentDetached(BaseComponent& component) override;
|
void OnComponentDetached(BaseComponent& component) override;
|
||||||
void OnDetached() override;
|
void OnDetached() override;
|
||||||
|
void OnEntityDestruction() override;
|
||||||
|
|
||||||
std::unique_ptr<Nz::RigidBody3D> m_object;
|
std::unique_ptr<Nz::RigidBody3D> m_object;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <Nazara/Core/Bitset.hpp>
|
#include <Nazara/Core/Bitset.hpp>
|
||||||
#include <Nazara/Core/HandledObject.hpp>
|
#include <Nazara/Core/HandledObject.hpp>
|
||||||
|
#include <Nazara/Core/Signal.hpp>
|
||||||
#include <NDK/Algorithm.hpp>
|
#include <NDK/Algorithm.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -65,6 +66,8 @@ namespace Ndk
|
||||||
Entity& operator=(const Entity&) = delete;
|
Entity& operator=(const Entity&) = delete;
|
||||||
Entity& operator=(Entity&&) = delete;
|
Entity& operator=(Entity&&) = delete;
|
||||||
|
|
||||||
|
NazaraSignal(OnEntityDestruction, Entity* /*entity*/);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Entity(World* world, EntityId id);
|
Entity(World* world, EntityId id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,15 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Operation to perform when the entity is destroyed and we're still attached to it
|
||||||
|
*
|
||||||
|
* \remark This is always called before the entity proper destruction, and thus its components.
|
||||||
|
*/
|
||||||
|
void BaseComponent::OnEntityDestruction()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<BaseComponent::ComponentEntry> BaseComponent::s_entries;
|
std::vector<BaseComponent::ComponentEntry> BaseComponent::s_entries;
|
||||||
std::unordered_map<ComponentId, ComponentIndex> BaseComponent::s_idToIndex;
|
std::unordered_map<ComponentId, ComponentIndex> BaseComponent::s_idToIndex;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,5 +88,11 @@ namespace Ndk
|
||||||
m_object.reset();
|
m_object.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicsComponent2D::OnEntityDestruction()
|
||||||
|
{
|
||||||
|
// Kill rigidbody before entity destruction to force contact callbacks to be called while the entity is still valid
|
||||||
|
m_object.reset();
|
||||||
|
}
|
||||||
|
|
||||||
ComponentIndex PhysicsComponent2D::componentIndex;
|
ComponentIndex PhysicsComponent2D::componentIndex;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,5 +88,11 @@ namespace Ndk
|
||||||
m_object.reset();
|
m_object.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicsComponent3D::OnEntityDestruction()
|
||||||
|
{
|
||||||
|
// Kill rigid body before entity destruction to force contact callbacks to be called while the entity is still valid
|
||||||
|
m_object.reset();
|
||||||
|
}
|
||||||
|
|
||||||
ComponentIndex PhysicsComponent3D::componentIndex;
|
ComponentIndex PhysicsComponent3D::componentIndex;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ namespace Ndk
|
||||||
m_enabled(entity.m_enabled),
|
m_enabled(entity.m_enabled),
|
||||||
m_valid(entity.m_valid)
|
m_valid(entity.m_valid)
|
||||||
{
|
{
|
||||||
|
entity.m_world = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -53,6 +54,7 @@ namespace Ndk
|
||||||
|
|
||||||
Entity::~Entity()
|
Entity::~Entity()
|
||||||
{
|
{
|
||||||
|
if (m_world)
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,6 +147,17 @@ namespace Ndk
|
||||||
|
|
||||||
void Entity::Destroy()
|
void Entity::Destroy()
|
||||||
{
|
{
|
||||||
|
OnEntityDestruction(this);
|
||||||
|
OnEntityDestruction.Clear();
|
||||||
|
|
||||||
|
// We prepare components for entity destruction (some components needs this to handle some final callbacks while the entity is still valid)
|
||||||
|
for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
||||||
|
m_components[i]->OnEntityDestruction();
|
||||||
|
|
||||||
|
// Detach components while they're still attached to systems
|
||||||
|
for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
||||||
|
m_components[i]->SetEntity(nullptr);
|
||||||
|
|
||||||
// We alert each system
|
// We alert each system
|
||||||
for (std::size_t index = m_systemBits.FindFirst(); index != m_systemBits.npos; index = m_systemBits.FindNext(index))
|
for (std::size_t index = m_systemBits.FindFirst(); index != m_systemBits.npos; index = m_systemBits.FindNext(index))
|
||||||
{
|
{
|
||||||
|
|
@ -158,10 +171,7 @@ namespace Ndk
|
||||||
}
|
}
|
||||||
m_systemBits.Clear();
|
m_systemBits.Clear();
|
||||||
|
|
||||||
// We properly destroy each component
|
// Destroy components
|
||||||
for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
|
||||||
m_components[i]->SetEntity(nullptr);
|
|
||||||
|
|
||||||
m_components.clear();
|
m_components.clear();
|
||||||
m_componentBits.Reset();
|
m_componentBits.Reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -185,12 +185,12 @@ namespace Ndk
|
||||||
|
|
||||||
NazaraAssert(entity.IsValid(), "Entity must be valid");
|
NazaraAssert(entity.IsValid(), "Entity must be valid");
|
||||||
|
|
||||||
// Send back the identifier of the entity to the free queue
|
|
||||||
m_freeIdList.push_back(entity.GetId());
|
|
||||||
|
|
||||||
// Destruction of the entity (invalidation of handle by the same way)
|
// Destruction of the entity (invalidation of handle by the same way)
|
||||||
entity.Destroy();
|
entity.Destroy();
|
||||||
|
|
||||||
|
// Send back the identifier of the entity to the free queue
|
||||||
|
m_freeIdList.push_back(entity.GetId());
|
||||||
|
|
||||||
// We take out the handle from the list of alive entities
|
// We take out the handle from the list of alive entities
|
||||||
// With the idiom swap and pop
|
// With the idiom swap and pop
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
-- This file contains special configurations values, such as directories to extern libraries (Qt)
|
-- This file contains special configurations values, such as directories to extern libraries (Qt)
|
||||||
-- Editing this file is not required to use/compile the engine, as default values should be enough
|
-- Editing this file is not required to use/compile the engine, as default values should be enough
|
||||||
|
|
||||||
|
-- Additionnal compilation options
|
||||||
|
--AdditionalCompilationOptions = "-fsanitize=address" -- Enable ASan
|
||||||
|
|
||||||
-- Builds Nazara extern libraries (such as lua/STB)
|
-- Builds Nazara extern libraries (such as lua/STB)
|
||||||
BuildDependencies = true
|
BuildDependencies = true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ ACTION.Function = function ()
|
||||||
local exeFilterFunc
|
local exeFilterFunc
|
||||||
if (os.is("windows")) then
|
if (os.is("windows")) then
|
||||||
binFileMasks = {"**.dll"}
|
binFileMasks = {"**.dll"}
|
||||||
libFileMasks = {"**.lib", "**.a"}
|
libFileMasks = {"**.lib", "**.a", "**.pdb"}
|
||||||
exeFileExt = ".exe"
|
exeFileExt = ".exe"
|
||||||
exeFilterFunc = function (filePath) return true end
|
exeFilterFunc = function (filePath) return true end
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -505,11 +505,47 @@ function NazaraBuild:LoadConfig()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local AddStringOption = function (option, name, description)
|
||||||
|
newoption({
|
||||||
|
trigger = name,
|
||||||
|
description = description
|
||||||
|
})
|
||||||
|
|
||||||
|
local str = _OPTIONS[name]
|
||||||
|
if (str) then
|
||||||
|
configTable[option] = str
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
AddBoolOption("BuildDependencies", "with-extlibs", "Builds the extern libraries")
|
AddBoolOption("BuildDependencies", "with-extlibs", "Builds the extern libraries")
|
||||||
AddBoolOption("BuildExamples", "with-examples", "Builds the examples")
|
AddBoolOption("BuildExamples", "with-examples", "Builds the examples")
|
||||||
AddBoolOption("ServerMode", "server", "Excludes client-only modules/tools/examples")
|
AddBoolOption("ServerMode", "server", "Excludes client-only modules/tools/examples")
|
||||||
AddBoolOption("UniteModules", "united", "Builds all the modules as one united library")
|
AddBoolOption("UniteModules", "united", "Builds all the modules as one united library")
|
||||||
|
|
||||||
|
-- AdditionalCompilationOptions
|
||||||
|
do
|
||||||
|
newoption({
|
||||||
|
trigger = "compile-options",
|
||||||
|
description = "Specify additionnal compilation options to be added to every generated project."
|
||||||
|
})
|
||||||
|
|
||||||
|
configTable["AdditionalCompilationOptions"] = configTable["AdditionalCompilationOptions"] or ""
|
||||||
|
if (_OPTIONS["compile-options"] ~= nil) then
|
||||||
|
configTable["AdditionalCompilationOptions"] = configTable["AdditionalCompilationOptions"] .. ";" .. _OPTIONS["compile-options"]
|
||||||
|
end
|
||||||
|
|
||||||
|
local configs = {}
|
||||||
|
local paths = string.explode(configTable["AdditionalCompilationOptions"], ";")
|
||||||
|
for k,v in pairs(paths) do
|
||||||
|
if (#v > 0) then
|
||||||
|
table.insert(configs, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
configTable["AdditionalCompilationOptions"] = configs
|
||||||
|
end
|
||||||
|
|
||||||
-- Configurations
|
-- Configurations
|
||||||
do
|
do
|
||||||
newoption({
|
newoption({
|
||||||
|
|
@ -792,6 +828,8 @@ function NazaraBuild:PrepareGeneric()
|
||||||
buildoptions("-ftree-vectorize")
|
buildoptions("-ftree-vectorize")
|
||||||
|
|
||||||
filter({})
|
filter({})
|
||||||
|
|
||||||
|
buildoptions(self.Config["AdditionalCompilationOptions"])
|
||||||
end
|
end
|
||||||
|
|
||||||
function NazaraBuild:PrepareMainWorkspace()
|
function NazaraBuild:PrepareMainWorkspace()
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ namespace Nz
|
||||||
SlotListIndex index;
|
SlotListIndex index;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Disconnect(const SlotPtr& slot);
|
void Disconnect(const SlotPtr& slot) noexcept;
|
||||||
|
|
||||||
SlotList m_slots;
|
SlotList m_slots;
|
||||||
mutable SlotListIndex m_slotIterator;
|
mutable SlotListIndex m_slotIterator;
|
||||||
|
|
@ -84,17 +84,17 @@ namespace Nz
|
||||||
public:
|
public:
|
||||||
Connection() = default;
|
Connection() = default;
|
||||||
Connection(const Connection& connection) = default;
|
Connection(const Connection& connection) = default;
|
||||||
Connection(Connection&& connection) = default;
|
Connection(Connection&& connection) noexcept;
|
||||||
~Connection() = default;
|
~Connection() = default;
|
||||||
|
|
||||||
template<typename... ConnectArgs>
|
template<typename... ConnectArgs>
|
||||||
void Connect(BaseClass& signal, ConnectArgs&&... args);
|
void Connect(BaseClass& signal, ConnectArgs&&... args);
|
||||||
void Disconnect();
|
void Disconnect() noexcept;
|
||||||
|
|
||||||
bool IsConnected() const;
|
bool IsConnected() const;
|
||||||
|
|
||||||
Connection& operator=(const Connection& connection) = default;
|
Connection& operator=(const Connection& connection) = default;
|
||||||
Connection& operator=(Connection&& connection) = default;
|
Connection& operator=(Connection&& connection) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Connection(const SlotPtr& slot);
|
Connection(const SlotPtr& slot);
|
||||||
|
|
@ -113,12 +113,12 @@ namespace Nz
|
||||||
ConnectionGuard(const Connection& connection);
|
ConnectionGuard(const Connection& connection);
|
||||||
ConnectionGuard(const ConnectionGuard& connection) = delete;
|
ConnectionGuard(const ConnectionGuard& connection) = delete;
|
||||||
ConnectionGuard(Connection&& connection);
|
ConnectionGuard(Connection&& connection);
|
||||||
ConnectionGuard(ConnectionGuard&& connection) = default;
|
ConnectionGuard(ConnectionGuard&& connection) noexcept = default;
|
||||||
~ConnectionGuard();
|
~ConnectionGuard();
|
||||||
|
|
||||||
template<typename... ConnectArgs>
|
template<typename... ConnectArgs>
|
||||||
void Connect(BaseClass& signal, ConnectArgs&&... args);
|
void Connect(BaseClass& signal, ConnectArgs&&... args);
|
||||||
void Disconnect();
|
void Disconnect() noexcept;
|
||||||
|
|
||||||
Connection& GetConnection();
|
Connection& GetConnection();
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ namespace Nz
|
||||||
ConnectionGuard& operator=(const Connection& connection);
|
ConnectionGuard& operator=(const Connection& connection);
|
||||||
ConnectionGuard& operator=(const ConnectionGuard& connection) = delete;
|
ConnectionGuard& operator=(const ConnectionGuard& connection) = delete;
|
||||||
ConnectionGuard& operator=(Connection&& connection);
|
ConnectionGuard& operator=(Connection&& connection);
|
||||||
ConnectionGuard& operator=(ConnectionGuard&& connection);
|
ConnectionGuard& operator=(ConnectionGuard&& connection) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Connection m_connection;
|
Connection m_connection;
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ namespace Nz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void Signal<Args...>::Disconnect(const SlotPtr& slot)
|
void Signal<Args...>::Disconnect(const SlotPtr& slot) noexcept
|
||||||
{
|
{
|
||||||
NazaraAssert(slot, "Invalid slot pointer");
|
NazaraAssert(slot, "Invalid slot pointer");
|
||||||
NazaraAssert(slot->index < m_slots.size(), "Invalid slot index");
|
NazaraAssert(slot->index < m_slots.size(), "Invalid slot index");
|
||||||
|
|
@ -246,6 +246,18 @@ namespace Nz
|
||||||
* \brief Core class that represents a connection attached to a signal
|
* \brief Core class that represents a connection attached to a signal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a Signal::Connection object with by move semantic
|
||||||
|
*
|
||||||
|
* \param connection Connection object to move
|
||||||
|
*/
|
||||||
|
template<typename... Args>
|
||||||
|
Signal<Args...>::Connection::Connection(Connection&& connection) noexcept :
|
||||||
|
m_ptr(std::move(connection.m_ptr))
|
||||||
|
{
|
||||||
|
connection.m_ptr.reset(); //< Fuck you GCC 4.9
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Constructs a Signal::Connection object with a slot
|
* \brief Constructs a Signal::Connection object with a slot
|
||||||
*
|
*
|
||||||
|
|
@ -277,7 +289,7 @@ namespace Nz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void Signal<Args...>::Connection::Disconnect()
|
void Signal<Args...>::Connection::Disconnect() noexcept
|
||||||
{
|
{
|
||||||
if (SlotPtr ptr = m_ptr.lock())
|
if (SlotPtr ptr = m_ptr.lock())
|
||||||
ptr->signal->Disconnect(ptr);
|
ptr->signal->Disconnect(ptr);
|
||||||
|
|
@ -294,6 +306,20 @@ namespace Nz
|
||||||
return !m_ptr.expired();
|
return !m_ptr.expired();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a Signal::ConnectionGuard object by move semantic
|
||||||
|
*
|
||||||
|
* \param connection Connection to move
|
||||||
|
*/
|
||||||
|
template<typename... Args>
|
||||||
|
typename Signal<Args...>::Connection& Signal<Args...>::Connection::operator=(Connection&& connection) noexcept
|
||||||
|
{
|
||||||
|
m_ptr = std::move(connection.m_ptr);
|
||||||
|
connection.m_ptr.reset(); //< Fuck you GCC 4.9
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \class Nz::Signal::ConnectionGuard
|
* \class Nz::Signal::ConnectionGuard
|
||||||
* \brief Core class that represents a RAII for a connection attached to a signal
|
* \brief Core class that represents a RAII for a connection attached to a signal
|
||||||
|
|
@ -353,7 +379,7 @@ namespace Nz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void Signal<Args...>::ConnectionGuard::Disconnect()
|
void Signal<Args...>::ConnectionGuard::Disconnect() noexcept
|
||||||
{
|
{
|
||||||
m_connection.Disconnect();
|
m_connection.Disconnect();
|
||||||
}
|
}
|
||||||
|
|
@ -405,9 +431,12 @@ namespace Nz
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
typename Signal<Args...>::ConnectionGuard& Signal<Args...>::ConnectionGuard::operator=(Connection&& connection)
|
typename Signal<Args...>::ConnectionGuard& Signal<Args...>::ConnectionGuard::operator=(Connection&& connection)
|
||||||
|
{
|
||||||
|
if (&connection != this)
|
||||||
{
|
{
|
||||||
m_connection.Disconnect();
|
m_connection.Disconnect();
|
||||||
m_connection = std::move(connection);
|
m_connection = std::move(connection);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -420,10 +449,13 @@ namespace Nz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
typename Signal<Args...>::ConnectionGuard& Signal<Args...>::ConnectionGuard::operator=(ConnectionGuard&& connection)
|
typename Signal<Args...>::ConnectionGuard& Signal<Args...>::ConnectionGuard::operator=(ConnectionGuard&& connection) noexcept
|
||||||
|
{
|
||||||
|
if (&connection != this)
|
||||||
{
|
{
|
||||||
m_connection.Disconnect();
|
m_connection.Disconnect();
|
||||||
m_connection = std::move(connection.m_connection);
|
m_connection = std::move(connection.m_connection);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,19 @@ namespace Nz
|
||||||
|
|
||||||
virtual float ComputeInertialMatrix(float mass) const = 0;
|
virtual float ComputeInertialMatrix(float mass) const = 0;
|
||||||
|
|
||||||
|
inline Nz::UInt32 GetCategoryMask() const;
|
||||||
|
inline Nz::UInt32 GetCollisionGroup() const;
|
||||||
inline unsigned int GetCollisionId() const;
|
inline unsigned int GetCollisionId() const;
|
||||||
|
inline Nz::UInt32 GetCollisionMask() const;
|
||||||
|
|
||||||
virtual ColliderType2D GetType() const = 0;
|
virtual ColliderType2D GetType() const = 0;
|
||||||
|
|
||||||
inline bool IsTrigger() const;
|
inline bool IsTrigger() const;
|
||||||
|
|
||||||
inline void SetCollisionId(unsigned long typeId);
|
inline void SetCategoryMask(Nz::UInt32 categoryMask);
|
||||||
|
inline void SetCollisionGroup(Nz::UInt32 groupId);
|
||||||
|
inline void SetCollisionId(unsigned int typeId);
|
||||||
|
inline void SetCollisionMask(Nz::UInt32 mask);
|
||||||
inline void SetTrigger(bool trigger);
|
inline void SetTrigger(bool trigger);
|
||||||
|
|
||||||
Collider2D& operator=(const Collider2D&) = delete;
|
Collider2D& operator=(const Collider2D&) = delete;
|
||||||
|
|
@ -61,7 +67,10 @@ namespace Nz
|
||||||
virtual std::vector<cpShape*> CreateShapes(RigidBody2D* body) const = 0;
|
virtual std::vector<cpShape*> CreateShapes(RigidBody2D* body) const = 0;
|
||||||
|
|
||||||
bool m_trigger;
|
bool m_trigger;
|
||||||
|
Nz::UInt32 m_categoryMask;
|
||||||
|
Nz::UInt32 m_collisionGroup;
|
||||||
unsigned int m_collisionId;
|
unsigned int m_collisionId;
|
||||||
|
Nz::UInt32 m_collisionMask;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual std::vector<cpShape*> GenerateShapes(RigidBody2D* body) const;
|
virtual std::vector<cpShape*> GenerateShapes(RigidBody2D* body) const;
|
||||||
|
|
|
||||||
|
|
@ -2,32 +2,66 @@
|
||||||
// This file is part of the "Nazara Engine - Physics 2D module"
|
// This file is part of the "Nazara Engine - Physics 2D module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Physics2D/Collider2D.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <Nazara/Physics2D/Debug.hpp>
|
#include <Nazara/Physics2D/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline Collider2D::Collider2D() :
|
inline Collider2D::Collider2D() :
|
||||||
|
m_trigger(false),
|
||||||
|
m_categoryMask(0xFFFFFFFF),
|
||||||
|
m_collisionGroup(0),
|
||||||
m_collisionId(0),
|
m_collisionId(0),
|
||||||
m_trigger(false)
|
m_collisionMask(0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Nz::UInt32 Collider2D::GetCategoryMask() const
|
||||||
|
{
|
||||||
|
return m_categoryMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Nz::UInt32 Collider2D::GetCollisionGroup() const
|
||||||
|
{
|
||||||
|
return m_collisionGroup;
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned int Collider2D::GetCollisionId() const
|
inline unsigned int Collider2D::GetCollisionId() const
|
||||||
{
|
{
|
||||||
return m_collisionId;
|
return m_collisionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Nz::UInt32 Collider2D::GetCollisionMask() const
|
||||||
|
{
|
||||||
|
return m_collisionMask;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Collider2D::IsTrigger() const
|
inline bool Collider2D::IsTrigger() const
|
||||||
{
|
{
|
||||||
return m_trigger;
|
return m_trigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Collider2D::SetCollisionId(unsigned long typeId)
|
inline void Collider2D::SetCategoryMask(Nz::UInt32 categoryMask)
|
||||||
|
{
|
||||||
|
m_categoryMask = categoryMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Collider2D::SetCollisionGroup(Nz::UInt32 groupId)
|
||||||
|
{
|
||||||
|
m_collisionGroup = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Collider2D::SetCollisionId(unsigned int typeId)
|
||||||
{
|
{
|
||||||
m_collisionId = typeId;
|
m_collisionId = typeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Collider2D::SetCollisionMask(Nz::UInt32 mask)
|
||||||
|
{
|
||||||
|
m_collisionMask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
inline void Collider2D::SetTrigger(bool trigger)
|
inline void Collider2D::SetTrigger(bool trigger)
|
||||||
{
|
{
|
||||||
m_trigger = trigger;
|
m_trigger = trigger;
|
||||||
|
|
@ -108,4 +142,3 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Physics2D/DebugOff.hpp>
|
#include <Nazara/Physics2D/DebugOff.hpp>
|
||||||
#include "Collider2D.hpp"
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,10 @@
|
||||||
#define NAZARA_PHYSWORLD2D_HPP
|
#define NAZARA_PHYSWORLD2D_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
|
#include <Nazara/Core/Signal.hpp>
|
||||||
#include <Nazara/Math/Vector2.hpp>
|
#include <Nazara/Math/Vector2.hpp>
|
||||||
#include <Nazara/Physics2D/Config.hpp>
|
#include <Nazara/Physics2D/Config.hpp>
|
||||||
|
#include <Nazara/Physics2D/RigidBody2D.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
@ -18,10 +20,10 @@ struct cpSpace;
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class RigidBody2D;
|
|
||||||
|
|
||||||
class NAZARA_PHYSICS2D_API PhysWorld2D
|
class NAZARA_PHYSICS2D_API PhysWorld2D
|
||||||
{
|
{
|
||||||
|
friend RigidBody2D;
|
||||||
|
|
||||||
using ContactEndCallback = void(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata);
|
using ContactEndCallback = void(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata);
|
||||||
using ContactPreSolveCallback = bool(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata);
|
using ContactPreSolveCallback = bool(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata);
|
||||||
using ContactPostSolveCallback = void(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata);
|
using ContactPostSolveCallback = void(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata);
|
||||||
|
|
@ -29,6 +31,8 @@ namespace Nz
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Callback;
|
struct Callback;
|
||||||
|
struct NearestQueryResult;
|
||||||
|
struct RaycastHit;
|
||||||
|
|
||||||
PhysWorld2D();
|
PhysWorld2D();
|
||||||
PhysWorld2D(const PhysWorld2D&) = delete;
|
PhysWorld2D(const PhysWorld2D&) = delete;
|
||||||
|
|
@ -39,6 +43,12 @@ namespace Nz
|
||||||
cpSpace* GetHandle() const;
|
cpSpace* GetHandle() const;
|
||||||
float GetStepSize() const;
|
float GetStepSize() const;
|
||||||
|
|
||||||
|
bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody = nullptr);
|
||||||
|
bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result);
|
||||||
|
|
||||||
|
bool RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<RaycastHit>* hitInfos);
|
||||||
|
bool RaycastQueryFirst(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RaycastHit* hitInfo = nullptr);
|
||||||
|
|
||||||
void RegisterCallbacks(unsigned int collisionId, const Callback& callbacks);
|
void RegisterCallbacks(unsigned int collisionId, const Callback& callbacks);
|
||||||
void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, const Callback& callbacks);
|
void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, const Callback& callbacks);
|
||||||
|
|
||||||
|
|
@ -59,10 +69,47 @@ namespace Nz
|
||||||
void* userdata;
|
void* userdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NearestQueryResult
|
||||||
|
{
|
||||||
|
Nz::RigidBody2D* nearestBody;
|
||||||
|
Nz::Vector2f closestPoint;
|
||||||
|
Nz::Vector2f fraction;
|
||||||
|
float distance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RaycastHit
|
||||||
|
{
|
||||||
|
Nz::RigidBody2D* nearestBody;
|
||||||
|
Nz::Vector2f hitPos;
|
||||||
|
Nz::Vector2f hitNormal;
|
||||||
|
float fraction;
|
||||||
|
};
|
||||||
|
|
||||||
|
NazaraSignal(OnPhysWorld2DPreStep, const PhysWorld2D* /*physWorld*/);
|
||||||
|
NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks);
|
void InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks);
|
||||||
|
|
||||||
|
using PostStep = std::function<void(Nz::RigidBody2D* body)>;
|
||||||
|
|
||||||
|
void OnRigidBodyMoved(RigidBody2D* oldPointer, RigidBody2D* newPointer);
|
||||||
|
void OnRigidBodyRelease(RigidBody2D* rigidBody);
|
||||||
|
|
||||||
|
void RegisterPostStep(RigidBody2D* rigidBody, PostStep&& func);
|
||||||
|
|
||||||
|
struct PostStepContainer
|
||||||
|
{
|
||||||
|
NazaraSlot(RigidBody2D, OnRigidBody2DMove, onMovedSlot);
|
||||||
|
NazaraSlot(RigidBody2D, OnRigidBody2DRelease, onReleaseSlot);
|
||||||
|
|
||||||
|
std::vector<PostStep> funcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(std::is_nothrow_move_constructible<PostStepContainer>::value, "PostStepContainer should be noexcept MoveConstructible");
|
||||||
|
|
||||||
std::unordered_map<cpCollisionHandler*, std::unique_ptr<Callback>> m_callbacks;
|
std::unordered_map<cpCollisionHandler*, std::unique_ptr<Callback>> m_callbacks;
|
||||||
|
std::unordered_map<RigidBody2D*, PostStepContainer> m_rigidPostSteps;
|
||||||
cpSpace* m_handle;
|
cpSpace* m_handle;
|
||||||
float m_stepSize;
|
float m_stepSize;
|
||||||
float m_timestepAccumulator;
|
float m_timestepAccumulator;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ namespace Nz
|
||||||
|
|
||||||
void AddForce(const Vector2f& force, CoordSys coordSys = CoordSys_Global);
|
void AddForce(const Vector2f& force, CoordSys coordSys = CoordSys_Global);
|
||||||
void AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys = CoordSys_Global);
|
void AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys = CoordSys_Global);
|
||||||
|
void AddImpulse(const Vector2f& impulse, CoordSys coordSys = CoordSys_Global);
|
||||||
|
void AddImpulse(const Vector2f& impulse, const Vector2f& point, CoordSys coordSys = CoordSys_Global);
|
||||||
void AddTorque(float torque);
|
void AddTorque(float torque);
|
||||||
|
|
||||||
Rectf GetAABB() const;
|
Rectf GetAABB() const;
|
||||||
|
|
|
||||||
|
|
@ -142,13 +142,15 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Wait until any registered socket switches to a ready state
|
* \brief Wait until any registered socket switches to a ready state.
|
||||||
*
|
*
|
||||||
* Waits a specific/undetermined amount of time until at least one socket part of the SocketPoller becomes ready.
|
* Waits a specific/undetermined amount of time until at least one socket part of the SocketPoller becomes ready.
|
||||||
* To query the ready state of the registered socket, use the IsReady function.
|
* To query the ready state of the registered socket, use the IsReady function.
|
||||||
*
|
*
|
||||||
* \param msTimeout Maximum time to wait in milliseconds, 0 for infinity
|
* \param msTimeout Maximum time to wait in milliseconds, 0 for infinity
|
||||||
*
|
*
|
||||||
|
* \return True if at least one socket registered to the poller is ready.
|
||||||
|
*
|
||||||
* \remark It is an error to try to unregister a non-registered socket from a SocketPoller.
|
* \remark It is an error to try to unregister a non-registered socket from a SocketPoller.
|
||||||
*
|
*
|
||||||
* \see IsReady
|
* \see IsReady
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,12 @@ namespace Nz
|
||||||
|
|
||||||
std::vector<cpShape*> Collider2D::GenerateShapes(RigidBody2D* body) const
|
std::vector<cpShape*> Collider2D::GenerateShapes(RigidBody2D* body) const
|
||||||
{
|
{
|
||||||
|
cpShapeFilter filter = cpShapeFilterNew(m_collisionGroup, m_categoryMask, m_collisionMask);
|
||||||
|
|
||||||
std::vector<cpShape*> shapes = CreateShapes(body);
|
std::vector<cpShape*> shapes = CreateShapes(body);
|
||||||
for (cpShape* shape : shapes)
|
for (cpShape* shape : shapes)
|
||||||
{
|
{
|
||||||
|
cpShapeSetFilter(shape, filter);
|
||||||
cpShapeSetCollisionType(shape, m_collisionId);
|
cpShapeSetCollisionType(shape, m_collisionId);
|
||||||
cpShapeSetSensor(shape, (m_trigger) ? cpTrue : cpFalse);
|
cpShapeSetSensor(shape, (m_trigger) ? cpTrue : cpFalse);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,102 @@ namespace Nz
|
||||||
return m_stepSize;
|
return m_stepSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PhysWorld2D::NearestBodyQuery(const Vector2f & from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody)
|
||||||
|
{
|
||||||
|
cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask);
|
||||||
|
|
||||||
|
if (cpShape* shape = cpSpacePointQueryNearest(m_handle, {from.x, from.y}, maxDistance, filter, nullptr))
|
||||||
|
{
|
||||||
|
if (nearestBody)
|
||||||
|
*nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(shape));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhysWorld2D::NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result)
|
||||||
|
{
|
||||||
|
cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
cpPointQueryInfo queryInfo;
|
||||||
|
|
||||||
|
if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, &queryInfo))
|
||||||
|
{
|
||||||
|
result->closestPoint.Set(queryInfo.point.x, queryInfo.point.y);
|
||||||
|
result->distance = queryInfo.distance;
|
||||||
|
result->fraction.Set(queryInfo.gradient.x, queryInfo.gradient.y);
|
||||||
|
result->nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(shape));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, nullptr))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhysWorld2D::RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<RaycastHit>* hitInfos)
|
||||||
|
{
|
||||||
|
auto callback = [](cpShape* shape, cpVect point, cpVect normal, cpFloat alpha, void* data)
|
||||||
|
{
|
||||||
|
std::vector<RaycastHit>* results = reinterpret_cast<std::vector<RaycastHit>*>(data);
|
||||||
|
|
||||||
|
RaycastHit hitInfo;
|
||||||
|
hitInfo.fraction = alpha;
|
||||||
|
hitInfo.hitNormal.Set(normal.x, normal.y);
|
||||||
|
hitInfo.hitPos.Set(point.x, point.y);
|
||||||
|
hitInfo.nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(shape));
|
||||||
|
|
||||||
|
results->emplace_back(std::move(hitInfo));
|
||||||
|
};
|
||||||
|
|
||||||
|
cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask);
|
||||||
|
|
||||||
|
std::size_t previousSize = hitInfos->size();
|
||||||
|
cpSpaceSegmentQuery(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, callback, hitInfos);
|
||||||
|
|
||||||
|
return hitInfos->size() != previousSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhysWorld2D::RaycastQueryFirst(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RaycastHit* hitInfo)
|
||||||
|
{
|
||||||
|
cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask);
|
||||||
|
|
||||||
|
if (hitInfo)
|
||||||
|
{
|
||||||
|
cpSegmentQueryInfo queryInfo;
|
||||||
|
|
||||||
|
if (cpShape* shape = cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, &queryInfo))
|
||||||
|
{
|
||||||
|
hitInfo->fraction = queryInfo.alpha;
|
||||||
|
hitInfo->hitNormal.Set(queryInfo.normal.x, queryInfo.normal.y);
|
||||||
|
hitInfo->hitPos.Set(queryInfo.point.x, queryInfo.point.y);
|
||||||
|
hitInfo->nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(queryInfo.shape));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cpShape* shape = cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, nullptr))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, const Callback& callbacks)
|
void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, const Callback& callbacks)
|
||||||
{
|
{
|
||||||
InitCallbacks(cpSpaceAddWildcardHandler(m_handle, collisionId), callbacks);
|
InitCallbacks(cpSpaceAddWildcardHandler(m_handle, collisionId), callbacks);
|
||||||
|
|
@ -63,7 +159,22 @@ namespace Nz
|
||||||
|
|
||||||
while (m_timestepAccumulator >= m_stepSize)
|
while (m_timestepAccumulator >= m_stepSize)
|
||||||
{
|
{
|
||||||
|
OnPhysWorld2DPreStep(this);
|
||||||
|
|
||||||
cpSpaceStep(m_handle, m_stepSize);
|
cpSpaceStep(m_handle, m_stepSize);
|
||||||
|
|
||||||
|
OnPhysWorld2DPostStep(this);
|
||||||
|
if (!m_rigidPostSteps.empty())
|
||||||
|
{
|
||||||
|
for (const auto& pair : m_rigidPostSteps)
|
||||||
|
{
|
||||||
|
for (const auto& step : pair.second.funcs)
|
||||||
|
step(pair.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rigidPostSteps.clear();
|
||||||
|
}
|
||||||
|
|
||||||
m_timestepAccumulator -= m_stepSize;
|
m_timestepAccumulator -= m_stepSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -162,4 +273,41 @@ namespace Nz
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysWorld2D::OnRigidBodyMoved(RigidBody2D* oldPointer, RigidBody2D* newPointer)
|
||||||
|
{
|
||||||
|
auto it = m_rigidPostSteps.find(oldPointer);
|
||||||
|
if (it == m_rigidPostSteps.end())
|
||||||
|
return; //< Shouldn't happen
|
||||||
|
|
||||||
|
m_rigidPostSteps.emplace(std::make_pair(newPointer, std::move(it->second)));
|
||||||
|
m_rigidPostSteps.erase(oldPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysWorld2D::OnRigidBodyRelease(RigidBody2D* rigidBody)
|
||||||
|
{
|
||||||
|
m_rigidPostSteps.erase(rigidBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysWorld2D::RegisterPostStep(RigidBody2D* rigidBody, PostStep&& func)
|
||||||
|
{
|
||||||
|
// If space isn't locked, no need to wait
|
||||||
|
if (!cpSpaceIsLocked(m_handle))
|
||||||
|
{
|
||||||
|
func(rigidBody);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_rigidPostSteps.find(rigidBody);
|
||||||
|
if (it == m_rigidPostSteps.end())
|
||||||
|
{
|
||||||
|
PostStepContainer postStep;
|
||||||
|
postStep.onMovedSlot.Connect(rigidBody->OnRigidBody2DMove, this, &PhysWorld2D::OnRigidBodyMoved);
|
||||||
|
postStep.onReleaseSlot.Connect(rigidBody->OnRigidBody2DRelease, this, &PhysWorld2D::OnRigidBodyRelease);
|
||||||
|
|
||||||
|
it = m_rigidPostSteps.insert(std::make_pair(rigidBody, std::move(postStep))).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->second.funcs.emplace_back(std::move(func));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ namespace Nz
|
||||||
m_mass(object.m_mass)
|
m_mass(object.m_mass)
|
||||||
{
|
{
|
||||||
cpBodySetUserData(m_handle, this);
|
cpBodySetUserData(m_handle, this);
|
||||||
|
for (cpShape* shape : m_shapes)
|
||||||
|
cpShapeSetUserData(shape, this);
|
||||||
|
|
||||||
object.m_handle = nullptr;
|
object.m_handle = nullptr;
|
||||||
|
|
||||||
|
|
@ -93,6 +95,25 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RigidBody2D::AddImpulse(const Vector2f& impulse, CoordSys coordSys)
|
||||||
|
{
|
||||||
|
return AddImpulse(impulse, GetCenterOfGravity(coordSys), coordSys);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RigidBody2D::AddImpulse(const Vector2f& impulse, const Vector2f& point, CoordSys coordSys)
|
||||||
|
{
|
||||||
|
switch (coordSys)
|
||||||
|
{
|
||||||
|
case CoordSys_Global:
|
||||||
|
cpBodyApplyImpulseAtWorldPoint(m_handle, cpv(impulse.x, impulse.y), cpv(point.x, point.y));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CoordSys_Local:
|
||||||
|
cpBodyApplyImpulseAtLocalPoint(m_handle, cpv(impulse.x, impulse.y), cpv(point.x, point.y));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RigidBody2D::AddTorque(float torque)
|
void RigidBody2D::AddTorque(float torque)
|
||||||
{
|
{
|
||||||
cpBodySetTorque(m_handle, cpBodyGetTorque(m_handle) + torque);
|
cpBodySetTorque(m_handle, cpBodyGetTorque(m_handle) + torque);
|
||||||
|
|
@ -210,7 +231,10 @@ namespace Nz
|
||||||
|
|
||||||
cpSpace* space = m_world->GetHandle();
|
cpSpace* space = m_world->GetHandle();
|
||||||
for (cpShape* shape : m_shapes)
|
for (cpShape* shape : m_shapes)
|
||||||
|
{
|
||||||
|
cpShapeSetUserData(shape, this);
|
||||||
cpSpaceAddShape(space, shape);
|
cpSpaceAddShape(space, shape);
|
||||||
|
}
|
||||||
|
|
||||||
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
|
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
|
||||||
}
|
}
|
||||||
|
|
@ -221,20 +245,26 @@ namespace Nz
|
||||||
{
|
{
|
||||||
if (mass > 0.f)
|
if (mass > 0.f)
|
||||||
{
|
{
|
||||||
cpBodySetMass(m_handle, mass);
|
m_world->RegisterPostStep(this, [mass](Nz::RigidBody2D* body)
|
||||||
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
|
{
|
||||||
|
cpBodySetMass(body->GetHandle(), mass);
|
||||||
|
cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeInertialMatrix(mass));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cpBodySetType(m_handle, CP_BODY_TYPE_STATIC);
|
m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body) { cpBodySetType(body->GetHandle(), CP_BODY_TYPE_STATIC); } );
|
||||||
}
|
}
|
||||||
else if (mass > 0.f)
|
else if (mass > 0.f)
|
||||||
{
|
{
|
||||||
if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC)
|
m_world->RegisterPostStep(this, [mass](Nz::RigidBody2D* body)
|
||||||
{
|
{
|
||||||
cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC);
|
if (cpBodyGetType(body->GetHandle()) == CP_BODY_TYPE_STATIC)
|
||||||
cpBodySetMass(m_handle, mass);
|
{
|
||||||
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
|
cpBodySetType(body->GetHandle(), CP_BODY_TYPE_DYNAMIC);
|
||||||
|
cpBodySetMass(body->GetHandle(), mass);
|
||||||
|
cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeInertialMatrix(mass));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
m_mass = mass;
|
m_mass = mass;
|
||||||
|
|
@ -290,6 +320,8 @@ namespace Nz
|
||||||
m_world = object.m_world;
|
m_world = object.m_world;
|
||||||
|
|
||||||
cpBodySetUserData(m_handle, this);
|
cpBodySetUserData(m_handle, this);
|
||||||
|
for (cpShape* shape : m_shapes)
|
||||||
|
cpShapeSetUserData(shape, this);
|
||||||
|
|
||||||
object.m_handle = nullptr;
|
object.m_handle = nullptr;
|
||||||
|
|
||||||
|
|
@ -302,6 +334,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
m_handle = cpBodyNew(mass, moment);
|
m_handle = cpBodyNew(mass, moment);
|
||||||
cpBodySetUserData(m_handle, this);
|
cpBodySetUserData(m_handle, this);
|
||||||
|
|
||||||
cpSpaceAddBody(m_world->GetHandle(), m_handle);
|
cpSpaceAddBody(m_world->GetHandle(), m_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue