From b4732d8c17ff27813cdd465c7037ef48e31462a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 11 Jul 2017 12:11:20 +0200 Subject: [PATCH 01/32] Add Udp::ReceiveMultiple method --- include/Nazara/Network/UdpSocket.hpp | 1 + src/Nazara/Network/Posix/SocketImpl.cpp | 84 +++++++++++++++++++++++++ src/Nazara/Network/Posix/SocketImpl.hpp | 1 + src/Nazara/Network/UdpSocket.cpp | 36 +++++++++++ src/Nazara/Network/Win32/SocketImpl.cpp | 66 +++++++++++++++++++ src/Nazara/Network/Win32/SocketImpl.hpp | 1 + 6 files changed, 189 insertions(+) diff --git a/include/Nazara/Network/UdpSocket.hpp b/include/Nazara/Network/UdpSocket.hpp index 0086249e9..2934758aa 100644 --- a/include/Nazara/Network/UdpSocket.hpp +++ b/include/Nazara/Network/UdpSocket.hpp @@ -39,6 +39,7 @@ namespace Nz std::size_t QueryMaxDatagramSize(); bool Receive(void* buffer, std::size_t size, IpAddress* from, std::size_t* received); + bool ReceiveMultiple(NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, std::size_t* received); bool ReceivePacket(NetPacket* packet, IpAddress* from); bool Send(const IpAddress& to, const void* buffer, std::size_t size, std::size_t* sent); diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index be6f84581..474073f80 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -549,6 +549,90 @@ namespace Nz else // else we received something senderIp = IpAddressImpl::FromSockAddr(reinterpret_cast(&nameBuffer)); + if (from) + *from = IpAddressImpl::FromSockAddr(reinterpret_cast(&nameBuffer)); + + if (read) + *read = byteRead; + + if (error) + *error = SocketError_NoError; + + return true; + } + + bool SocketImpl::ReceiveMultiple(SocketHandle handle, NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, int* read, SocketError* error) + { + NazaraAssert(handle != InvalidHandle, "Invalid handle"); + NazaraAssert(buffers && bufferCount > 0, "Invalid buffers"); + + StackAllocation memory = NazaraStackAllocation(bufferCount * sizeof(iovec)); + struct iovec* sysBuffers = static_cast(memory.GetPtr()); + for (std::size_t i = 0; i < bufferCount; ++i) + { + sysBuffers[i].iov_base = buffers[i].data; + sysBuffers[i].iov_len = buffers[i].dataLength; + } + + struct msghdr msgHdr; + std::memset(&msgHdr, 0, sizeof(msgHdr)); + + msgHdr.msg_iov = sysBuffers; + msgHdr.msg_iovlen = static_cast(bufferCount); + + IpAddressImpl::SockAddrBuffer nameBuffer; + if (from) + { + msgHdr.msg_name = nameBuffer.data(); + msgHdr.msg_namelen = static_cast(nameBuffer.size()); + } + + int byteRead = recvmsg(handle, &msgHdr, MSG_NOSIGNAL); + if (byteRead == -1) + { + int errorCode = GetLastErrorCode(); + if (errorCode == EAGAIN) + errorCode = EWOULDBLOCK; + + switch (errorCode) + { + case EWOULDBLOCK: + { + // If we have no data and are not blocking, return true with 0 byte read + recvLength = 0; + senderIp = IpAddress::Invalid; + break; + } + + default: + { + if (error) + *error = TranslateErrnoToResolveError(errorCode); + + return false; //< Error + } + } + } + else if (byteRead == 0) + { + if (error) + *error = SocketError_ConnectionClosed; + + return false; //< Connection closed + } + else // else we received something + senderIp = IpAddressImpl::FromSockAddr(reinterpret_cast(nameBuffer.data())); + +#ifdef HAS_MSGHDR_FLAGS + if (msgHdr.msg_flags & MSG_TRUNC) + { + if (error) + *error = SocketError_DatagramSize; + + return false; + } +#endif + if (from) *from = senderIp; diff --git a/src/Nazara/Network/Posix/SocketImpl.hpp b/src/Nazara/Network/Posix/SocketImpl.hpp index 7ee2e24f6..abba97e4f 100644 --- a/src/Nazara/Network/Posix/SocketImpl.hpp +++ b/src/Nazara/Network/Posix/SocketImpl.hpp @@ -63,6 +63,7 @@ namespace Nz static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error); static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error); + static bool ReceiveMultiple(SocketHandle handle, NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, int* read, SocketError* error); static bool Send(SocketHandle handle, const void* buffer, int length, int* sent, SocketError* error); static bool SendMultiple(SocketHandle handle, const NetBuffer* buffers, std::size_t bufferCount, const IpAddress& to, int* sent, SocketError* error); diff --git a/src/Nazara/Network/UdpSocket.cpp b/src/Nazara/Network/UdpSocket.cpp index bc86f8401..c0a88eb88 100644 --- a/src/Nazara/Network/UdpSocket.cpp +++ b/src/Nazara/Network/UdpSocket.cpp @@ -118,6 +118,42 @@ namespace Nz return true; } + /*! + * \brief Receive multiple datagram from one peer + * \return true If data were sent + * + * \param to Destination IpAddress (must match socket protocol) + * \param buffers A pointer to an array of NetBuffer containing buffers and size data + * \param bufferCount Number of buffers available + * \param from IpAddress of the peer + * \param received Optional argument to get the number of bytes received + */ + bool UdpSocket::ReceiveMultiple(NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, std::size_t* received) + { + NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket hasn't been created"); + NazaraAssert(buffers && bufferCount > 0, "Invalid buffer"); + + int read; + if (!SocketImpl::ReceiveMultiple(m_handle, buffers, bufferCount, from, &read, &m_lastError)) + { + switch (m_lastError) + { + case SocketError_ConnectionClosed: + m_lastError = SocketError_NoError; + read = 0; + break; + + default: + return false; + } + } + + if (received) + *received = read; + + return true; + } + /*! * \brief Receives the packet available * \return true If packet received diff --git a/src/Nazara/Network/Win32/SocketImpl.cpp b/src/Nazara/Network/Win32/SocketImpl.cpp index 32404f53a..6c82f0505 100644 --- a/src/Nazara/Network/Win32/SocketImpl.cpp +++ b/src/Nazara/Network/Win32/SocketImpl.cpp @@ -586,6 +586,72 @@ namespace Nz return true; } + bool SocketImpl::ReceiveMultiple(SocketHandle handle, NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, int* read, SocketError* error) + { + NazaraAssert(handle != InvalidHandle, "Invalid handle"); + NazaraAssert(buffers && bufferCount > 0, "Invalid buffers"); + + IpAddressImpl::SockAddrBuffer nameBuffer; + int bufferLength = static_cast(nameBuffer.size()); + + IpAddress senderIp; + + StackAllocation memory = NazaraStackAllocation(bufferCount * sizeof(WSABUF)); + WSABUF* winBuffers = static_cast(memory.GetPtr()); + for (std::size_t i = 0; i < bufferCount; ++i) + { + winBuffers[i].buf = static_cast(buffers[i].data); + winBuffers[i].len = static_cast(buffers[i].dataLength); + } + + DWORD flags = 0; + DWORD byteRead; + if (WSARecvFrom(handle, winBuffers, static_cast(bufferCount), &byteRead, &flags, reinterpret_cast(nameBuffer.data()), &bufferLength, nullptr, nullptr) == SOCKET_ERROR) + { + int errorCode = WSAGetLastError(); + switch (errorCode) + { + case WSAECONNRESET: + case WSAEWOULDBLOCK: + { + // If we have no data and are not blocking, return true with 0 byte read + byteRead = 0; + senderIp = IpAddress::Invalid; + break; + } + + default: + { + if (error) + *error = TranslateWSAErrorToSocketError(errorCode); + + return false; //< Error + } + } + } + else + senderIp = IpAddressImpl::FromSockAddr(reinterpret_cast(&nameBuffer)); + + if (flags & MSG_PARTIAL) + { + if (error) + *error = SocketError_DatagramSize; + + return false; + } + + if (from) + *from = senderIp; + + if (read) + *read = byteRead; + + if (error) + *error = SocketError_NoError; + + return true; + } + bool SocketImpl::Send(SocketHandle handle, const void* buffer, int length, int* sent, SocketError* error) { NazaraAssert(handle != InvalidHandle, "Invalid handle"); diff --git a/src/Nazara/Network/Win32/SocketImpl.hpp b/src/Nazara/Network/Win32/SocketImpl.hpp index edcc7ce09..864e629dd 100644 --- a/src/Nazara/Network/Win32/SocketImpl.hpp +++ b/src/Nazara/Network/Win32/SocketImpl.hpp @@ -64,6 +64,7 @@ namespace Nz static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error); static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error); + static bool ReceiveMultiple(SocketHandle handle, NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, int* read, SocketError* error); static bool Send(SocketHandle handle, const void* buffer, int length, int* sent, SocketError* error); static bool SendMultiple(SocketHandle handle, const NetBuffer* buffers, std::size_t bufferCount, const IpAddress& to, int* sent, SocketError* error); From 9fb9289d6e3fcbf18eef810500e65bab7e4704f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 11 Jul 2017 12:11:43 +0200 Subject: [PATCH 02/32] Network/Socket: Fix IPv6 handling --- src/Nazara/Network/Posix/SocketImpl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index 474073f80..1cc9958ff 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -509,12 +509,12 @@ namespace Nz NazaraAssert(buffer && length > 0, "Invalid buffer"); IpAddressImpl::SockAddrBuffer nameBuffer; - socklen_t bufferLength = sizeof(sockaddr_in); + socklen_t bufferLength = static_cast(nameBuffer.size()); IpAddress senderIp; int byteRead = recvfrom(handle, buffer, length, 0, reinterpret_cast(&nameBuffer), &bufferLength); - if (byteRead == SOCKET_ERROR) + if (byteRead == -1) { int errorCode = GetLastErrorCode(); if (errorCode == EAGAIN) From cbcfa5cb4d6f66fc67f0947e874be1c62ddcaf95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 11 Jul 2017 12:12:12 +0200 Subject: [PATCH 03/32] Network/ENet: Fix throttle bug --- src/Nazara/Network/ENetPeer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nazara/Network/ENetPeer.cpp b/src/Nazara/Network/ENetPeer.cpp index cbae37148..80e46a36b 100644 --- a/src/Nazara/Network/ENetPeer.cpp +++ b/src/Nazara/Network/ENetPeer.cpp @@ -139,7 +139,7 @@ namespace Nz m_packetsLost = 0; m_packetLoss = 0; m_packetLossVariance = 0; - m_packetThrottle = ENetConstants::ENetProtocol_MaximumWindowSize; + m_packetThrottle = ENetConstants::ENetPeer_DefaultPacketThrottle; m_packetThrottleLimit = ENetConstants::ENetPeer_PacketThrottleScale; m_packetThrottleCounter = 0; m_packetThrottleEpoch = 0; @@ -1330,7 +1330,7 @@ namespace Nz { if (rtt < m_lastRoundTripTime) { - m_packetThrottle = std::max(m_packetThrottle + m_packetThrottleAcceleration, m_packetThrottleLimit); + m_packetThrottle = std::min(m_packetThrottle + m_packetThrottleAcceleration, m_packetThrottleLimit); return 1; } else if (rtt > m_lastRoundTripTime + 2 * m_lastRoundTripTimeVariance) From 394f0bc7303b471f420a0576930d74dafd061bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 11 Jul 2017 12:12:38 +0200 Subject: [PATCH 04/32] Network/ENetHost: Fix hostname resolve --- src/Nazara/Network/ENetHost.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Nazara/Network/ENetHost.cpp b/src/Nazara/Network/ENetHost.cpp index 5850d4ab7..9fdfe284f 100644 --- a/src/Nazara/Network/ENetHost.cpp +++ b/src/Nazara/Network/ENetHost.cpp @@ -128,13 +128,18 @@ namespace Nz if (!result.address) continue; - if (result.socketType != SocketType_UDP) - continue; - hostnameAddress = result.address; break; //< Take first valid address } + if (!hostnameAddress.IsValid()) + { + if (error) + *error = ResolveError_NotFound; + + return nullptr; + } + return Connect(hostnameAddress, channelCount, data); } From aac8d8301b90fe8d06190a97fae4923888012370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 11 Jul 2017 12:19:11 +0200 Subject: [PATCH 05/32] Network: Fix Linux build --- src/Nazara/Network/Posix/SocketImpl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index 1cc9958ff..7ca69ae29 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -587,6 +587,8 @@ namespace Nz msgHdr.msg_namelen = static_cast(nameBuffer.size()); } + IpAddress senderIp; + int byteRead = recvmsg(handle, &msgHdr, MSG_NOSIGNAL); if (byteRead == -1) { @@ -599,7 +601,7 @@ namespace Nz case EWOULDBLOCK: { // If we have no data and are not blocking, return true with 0 byte read - recvLength = 0; + byteRead = 0; senderIp = IpAddress::Invalid; break; } From 28e837770806757c9a9d9d3b17506aebb1678528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 12 Jul 2017 16:23:14 +0200 Subject: [PATCH 06/32] Physics2D: Fix shape BB --- src/Nazara/Physics2D/Collider2D.cpp | 4 ++-- src/Nazara/Physics2D/PhysWorld2D.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nazara/Physics2D/Collider2D.cpp b/src/Nazara/Physics2D/Collider2D.cpp index 3a679fad9..6309b08fd 100644 --- a/src/Nazara/Physics2D/Collider2D.cpp +++ b/src/Nazara/Physics2D/Collider2D.cpp @@ -41,7 +41,7 @@ namespace Nz float BoxCollider2D::ComputeInertialMatrix(float mass) const { - return static_cast(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y + m_rect.height, m_rect.x + m_rect.width, m_rect.y))); + return static_cast(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height))); } ColliderType2D BoxCollider2D::GetType() const @@ -52,7 +52,7 @@ namespace Nz std::vector BoxCollider2D::CreateShapes(RigidBody2D* body) const { std::vector shapes; - shapes.push_back(cpBoxShapeNew2(body->GetHandle(), cpBBNew(m_rect.x, m_rect.y + m_rect.height, m_rect.x + m_rect.width, m_rect.y), m_radius)); + shapes.push_back(cpBoxShapeNew2(body->GetHandle(), cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height), m_radius)); return shapes; } diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index cbf098786..e6f1c95ca 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -146,7 +146,7 @@ namespace Nz }; cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask); - cpSpaceBBQuery(m_handle, cpBBNew(boundingBox.x, boundingBox.y + boundingBox.height, boundingBox.x + boundingBox.width, boundingBox.y), filter, callback, bodies); + cpSpaceBBQuery(m_handle, cpBBNew(boundingBox.x, boundingBox.y, boundingBox.x + boundingBox.width, boundingBox.y + boundingBox.height), filter, callback, bodies); } void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, const Callback& callbacks) From b00487c88c9710013107054d3d7af98b684c376b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 25 Jul 2017 14:44:30 +0200 Subject: [PATCH 07/32] PhysicsID/RigidBody: Add GetWorld() accessor --- include/Nazara/Physics2D/RigidBody2D.hpp | 1 + include/Nazara/Physics3D/RigidBody3D.hpp | 1 + src/Nazara/Physics2D/RigidBody2D.cpp | 5 +++++ src/Nazara/Physics3D/RigidBody3D.cpp | 7 ++++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Physics2D/RigidBody2D.hpp b/include/Nazara/Physics2D/RigidBody2D.hpp index 9763aba47..1af3ea89c 100644 --- a/include/Nazara/Physics2D/RigidBody2D.hpp +++ b/include/Nazara/Physics2D/RigidBody2D.hpp @@ -48,6 +48,7 @@ namespace Nz float GetRotation() const; void* GetUserdata() const; Vector2f GetVelocity() const; + PhysWorld2D* GetWorld() const; bool IsMoveable() const; bool IsSleeping() const; diff --git a/include/Nazara/Physics3D/RigidBody3D.hpp b/include/Nazara/Physics3D/RigidBody3D.hpp index 502fd21a7..bc7f668b0 100644 --- a/include/Nazara/Physics3D/RigidBody3D.hpp +++ b/include/Nazara/Physics3D/RigidBody3D.hpp @@ -47,6 +47,7 @@ namespace Nz Vector3f GetPosition() const; Quaternionf GetRotation() const; Vector3f GetVelocity() const; + PhysWorld3D* GetWorld() const; bool IsAutoSleepEnabled() const; bool IsMoveable() const; diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index a19107c2c..9c25c1cbe 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -191,6 +191,11 @@ namespace Nz return Vector2f(static_cast(vel.x), static_cast(vel.y)); } + PhysWorld2D* RigidBody2D::GetWorld() const + { + return m_world; + } + bool RigidBody2D::IsMoveable() const { return m_mass > 0.f; diff --git a/src/Nazara/Physics3D/RigidBody3D.cpp b/src/Nazara/Physics3D/RigidBody3D.cpp index 9a909f98f..3d697aa8c 100644 --- a/src/Nazara/Physics3D/RigidBody3D.cpp +++ b/src/Nazara/Physics3D/RigidBody3D.cpp @@ -204,6 +204,11 @@ namespace Nz return velocity; } + PhysWorld3D* RigidBody3D::GetWorld() const + { + return m_world; + } + bool RigidBody3D::IsAutoSleepEnabled() const { return NewtonBodyGetAutoSleep(m_body) != 0; @@ -314,7 +319,7 @@ namespace Nz NazaraUnused(userData); NewtonBodySetSleepState(body, 0); return 1; - }, + }, nullptr); } } From afdc0187787670b7a5d62c9c0a6a0ab0b345ef4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 27 Jul 2017 11:39:23 +0200 Subject: [PATCH 08/32] Physics2D/Collider2D: Implement CompoundCollider2D and ConvexCollider2D --- include/Nazara/Physics2D/Collider2D.hpp | 68 ++++++++++++++++--- include/Nazara/Physics2D/Collider2D.inl | 14 ++++ include/Nazara/Physics2D/Enums.hpp | 1 + src/Nazara/Physics2D/Collider2D.cpp | 86 +++++++++++++++++++------ src/Nazara/Physics2D/RigidBody2D.cpp | 6 +- 5 files changed, 143 insertions(+), 32 deletions(-) diff --git a/include/Nazara/Physics2D/Collider2D.hpp b/include/Nazara/Physics2D/Collider2D.hpp index b09e8781f..06d55300b 100644 --- a/include/Nazara/Physics2D/Collider2D.hpp +++ b/include/Nazara/Physics2D/Collider2D.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ namespace Nz { friend Collider2DLibrary; friend RigidBody2D; + friend class CompoundCollider2D; //< See CompoundCollider2D::CreateShapes public: inline Collider2D(); @@ -40,7 +42,7 @@ namespace Nz Collider2D(Collider2D&&) = delete; virtual ~Collider2D(); - virtual float ComputeInertialMatrix(float mass) const = 0; + virtual float ComputeMomentOfInertia(float mass) const = 0; inline Nz::UInt32 GetCategoryMask() const; inline Nz::UInt32 GetCollisionGroup() const; @@ -64,7 +66,7 @@ namespace Nz NazaraSignal(OnColliderRelease, const Collider2D* /*collider*/); protected: - virtual std::vector CreateShapes(RigidBody2D* body) const = 0; + virtual void CreateShapes(RigidBody2D* body, std::vector& shapes) const = 0; bool m_trigger; Nz::UInt32 m_categoryMask; @@ -89,7 +91,7 @@ namespace Nz BoxCollider2D(const Vector2f& size, float radius = 0.f); BoxCollider2D(const Rectf& rect, float radius = 0.f); - float ComputeInertialMatrix(float mass) const override; + float ComputeMomentOfInertia(float mass) const override; inline const Rectf& GetRect() const; inline Vector2f GetSize() const; @@ -98,7 +100,7 @@ namespace Nz template static BoxCollider2DRef New(Args&&... args); private: - std::vector CreateShapes(RigidBody2D* body) const override; + void CreateShapes(RigidBody2D* body, std::vector& shapes) const override; Rectf m_rect; float m_radius; @@ -114,7 +116,7 @@ namespace Nz public: CircleCollider2D(float radius, const Vector2f& offset = Vector2f::Zero()); - float ComputeInertialMatrix(float mass) const override; + float ComputeMomentOfInertia(float mass) const override; inline float GetRadius() const; ColliderType2D GetType() const override; @@ -122,12 +124,58 @@ namespace Nz template static CircleCollider2DRef New(Args&&... args); private: - std::vector CreateShapes(RigidBody2D* body) const override; + void CreateShapes(RigidBody2D* body, std::vector& shapes) const override; Vector2f m_offset; float m_radius; }; + class CompoundCollider2D; + + using CompoundCollider2DConstRef = ObjectRef; + using CompoundCollider2DRef = ObjectRef; + + class NAZARA_PHYSICS2D_API CompoundCollider2D : public Collider2D + { + public: + CompoundCollider2D(std::vector geoms); + + float ComputeMomentOfInertia(float mass) const override; + + inline const std::vector& GetGeoms() const; + ColliderType2D GetType() const override; + + template static CompoundCollider2DRef New(Args&&... args); + + private: + void CreateShapes(RigidBody2D* body, std::vector& shapes) const override; + + std::vector m_geoms; + }; + + class ConvexCollider2D; + + using ConvexCollider2DConstRef = ObjectRef; + using ConvexCollider2DRef = ObjectRef; + + class NAZARA_PHYSICS2D_API ConvexCollider2D : public Collider2D + { + public: + ConvexCollider2D(SparsePtr vertices, std::size_t vertexCount, float radius = 0.f); + + float ComputeMomentOfInertia(float mass) const override; + + ColliderType2D GetType() const override; + + template static ConvexCollider2DRef New(Args&&... args); + + private: + void CreateShapes(RigidBody2D* body, std::vector& shapes) const override; + + std::vector m_vertices; + float m_radius; + }; + class NullCollider2D; using NullCollider2DConstRef = ObjectRef; @@ -138,14 +186,14 @@ namespace Nz public: NullCollider2D() = default; - float ComputeInertialMatrix(float mass) const override; + float ComputeMomentOfInertia(float mass) const override; ColliderType2D GetType() const override; template static NullCollider2DRef New(Args&&... args); private: - std::vector CreateShapes(RigidBody2D* body) const override; + void CreateShapes(RigidBody2D* body, std::vector& shapes) const override; }; class SegmentCollider2D; @@ -158,7 +206,7 @@ namespace Nz public: inline SegmentCollider2D(const Vector2f& first, const Vector2f& second, float thickness = 1.f); - float ComputeInertialMatrix(float mass) const override; + float ComputeMomentOfInertia(float mass) const override; inline const Vector2f& GetFirstPoint() const; inline float GetLength() const; @@ -168,7 +216,7 @@ namespace Nz template static SegmentCollider2DRef New(Args&&... args); private: - std::vector CreateShapes(RigidBody2D* body) const override; + void CreateShapes(RigidBody2D* body, std::vector& shapes) const override; Vector2f m_first; Vector2f m_second; diff --git a/include/Nazara/Physics2D/Collider2D.inl b/include/Nazara/Physics2D/Collider2D.inl index 60cf8559f..dee95687a 100644 --- a/include/Nazara/Physics2D/Collider2D.inl +++ b/include/Nazara/Physics2D/Collider2D.inl @@ -100,6 +100,20 @@ namespace Nz return object.release(); } + inline const std::vector& Nz::CompoundCollider2D::GetGeoms() const + { + return m_geoms; + } + + template + CompoundCollider2DRef CompoundCollider2D::New(Args&&... args) + { + std::unique_ptr object(new CompoundCollider2D(std::forward(args)...)); + object->SetPersistent(false); + + return object.release(); + } + template NullCollider2DRef NullCollider2D::New(Args&&... args) { diff --git a/include/Nazara/Physics2D/Enums.hpp b/include/Nazara/Physics2D/Enums.hpp index 86c1411f4..8cbb73d39 100644 --- a/include/Nazara/Physics2D/Enums.hpp +++ b/include/Nazara/Physics2D/Enums.hpp @@ -12,6 +12,7 @@ namespace Nz enum ColliderType2D { ColliderType2D_Box, + ColliderType2D_Compound, ColliderType2D_Convex, ColliderType2D_Circle, ColliderType2D_Null, diff --git a/src/Nazara/Physics2D/Collider2D.cpp b/src/Nazara/Physics2D/Collider2D.cpp index 6309b08fd..9c7d964a5 100644 --- a/src/Nazara/Physics2D/Collider2D.cpp +++ b/src/Nazara/Physics2D/Collider2D.cpp @@ -15,7 +15,9 @@ namespace Nz { cpShapeFilter filter = cpShapeFilterNew(m_collisionGroup, m_categoryMask, m_collisionMask); - std::vector shapes = CreateShapes(body); + std::vector shapes; + CreateShapes(body, shapes); + for (cpShape* shape : shapes) { cpShapeSetFilter(shape, filter); @@ -39,7 +41,7 @@ namespace Nz { } - float BoxCollider2D::ComputeInertialMatrix(float mass) const + float BoxCollider2D::ComputeMomentOfInertia(float mass) const { return static_cast(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height))); } @@ -49,12 +51,9 @@ namespace Nz return ColliderType2D_Box; } - std::vector BoxCollider2D::CreateShapes(RigidBody2D* body) const + void BoxCollider2D::CreateShapes(RigidBody2D* body, std::vector& shapes) const { - std::vector shapes; shapes.push_back(cpBoxShapeNew2(body->GetHandle(), cpBBNew(m_rect.x, m_rect.y, m_rect.x + m_rect.width, m_rect.y + m_rect.height), m_radius)); - - return shapes; } /******************************** CircleCollider2D *********************************/ @@ -65,7 +64,7 @@ namespace Nz { } - float CircleCollider2D::ComputeInertialMatrix(float mass) const + float CircleCollider2D::ComputeMomentOfInertia(float mass) const { return static_cast(cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y))); } @@ -75,12 +74,66 @@ namespace Nz return ColliderType2D_Circle; } - std::vector CircleCollider2D::CreateShapes(RigidBody2D* body) const + void CircleCollider2D::CreateShapes(RigidBody2D* body, std::vector& shapes) const { - std::vector shapes; shapes.push_back(cpCircleShapeNew(body->GetHandle(), m_radius, cpv(m_offset.x, m_offset.y))); + } - return shapes; + /******************************** CompoundCollider2D *********************************/ + + CompoundCollider2D::CompoundCollider2D(std::vector geoms) : + m_geoms(std::move(geoms)) + { + } + + float CompoundCollider2D::ComputeMomentOfInertia(float mass) const + { + ///TODO: Correctly compute moment using parallel axis theorem: + /// https://chipmunk-physics.net/forum/viewtopic.php?t=1056 + float momentOfInertia = 0.f; + for (const auto& geom : m_geoms) + momentOfInertia += geom->ComputeMomentOfInertia(mass); //< Eeeer + + return momentOfInertia; + } + + ColliderType2D CompoundCollider2D::GetType() const + { + return ColliderType2D_Compound; + } + + void CompoundCollider2D::CreateShapes(RigidBody2D* body, std::vector& shapes) const + { + // Since C++ does not allow protected call from other objects, we have to be a friend of Collider2D, yay + for (const auto& geom : m_geoms) + geom->CreateShapes(body, shapes); + } + + /******************************** ConvexCollider2D *********************************/ + + ConvexCollider2D::ConvexCollider2D(SparsePtr vertices, std::size_t vertexCount, float radius) : + m_radius(radius) + { + m_vertices.resize(vertexCount); + for (std::size_t i = 0; i < vertexCount; ++i) + m_vertices[i].Set(*vertices++); + } + + float ConvexCollider2D::ComputeMomentOfInertia(float mass) const + { + static_assert(sizeof(cpVect) == sizeof(Vector2d), "Chipmunk vector is not equivalent to Vector2d"); + + return static_cast(cpMomentForPoly(mass, int(m_vertices.size()), reinterpret_cast(m_vertices.data()), cpv(0.0, 0.0), m_radius)); + } + + ColliderType2D ConvexCollider2D::GetType() const + { + return ColliderType2D_Convex; + } + + void ConvexCollider2D::CreateShapes(RigidBody2D* body, std::vector& shapes) const + { + shapes.push_back(cpPolyShapeNew(body->GetHandle(), int(m_vertices.size()), reinterpret_cast(m_vertices.data()), cpTransformIdentity, m_radius)); } /********************************* NullCollider2D **********************************/ @@ -90,19 +143,18 @@ namespace Nz return ColliderType2D_Null; } - float NullCollider2D::ComputeInertialMatrix(float /*mass*/) const + float NullCollider2D::ComputeMomentOfInertia(float /*mass*/) const { return 0.f; } - std::vector NullCollider2D::CreateShapes(RigidBody2D* /*body*/) const + void NullCollider2D::CreateShapes(RigidBody2D* /*body*/, std::vector& /*shapes*/) const { - return std::vector(); } /******************************** SegmentCollider2D *********************************/ - float SegmentCollider2D::ComputeInertialMatrix(float mass) const + float SegmentCollider2D::ComputeMomentOfInertia(float mass) const { return static_cast(cpMomentForSegment(mass, cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness)); } @@ -112,12 +164,8 @@ namespace Nz return ColliderType2D_Segment; } - std::vector SegmentCollider2D::CreateShapes(RigidBody2D* body) const + void SegmentCollider2D::CreateShapes(RigidBody2D* body, std::vector& shapes) const { - std::vector shapes; shapes.push_back(cpSegmentShapeNew(body->GetHandle(), cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness)); - - return shapes; } - } diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index 9c25c1cbe..85d43ee76 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -245,7 +245,7 @@ namespace Nz cpSpaceAddShape(space, shape); } - cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + cpBodySetMoment(m_handle, m_geom->ComputeMomentOfInertia(m_mass)); } void RigidBody2D::SetMass(float mass) @@ -257,7 +257,7 @@ namespace Nz m_world->RegisterPostStep(this, [mass](Nz::RigidBody2D* body) { cpBodySetMass(body->GetHandle(), mass); - cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeInertialMatrix(mass)); + cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeMomentOfInertia(mass)); }); } else @@ -271,7 +271,7 @@ namespace Nz { cpBodySetType(body->GetHandle(), CP_BODY_TYPE_DYNAMIC); cpBodySetMass(body->GetHandle(), mass); - cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeInertialMatrix(mass)); + cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeMomentOfInertia(mass)); } }); } From 6047018082e69208e017f2ca952f1acc4227ff46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 27 Jul 2017 11:40:42 +0200 Subject: [PATCH 09/32] Physics3D/Collider3D: Improve CompoundCollider3D constructor --- include/Nazara/Physics3D/Collider3D.hpp | 2 +- src/Nazara/Physics3D/Collider3D.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/Nazara/Physics3D/Collider3D.hpp b/include/Nazara/Physics3D/Collider3D.hpp index 13bf32c2f..d8300bdf2 100644 --- a/include/Nazara/Physics3D/Collider3D.hpp +++ b/include/Nazara/Physics3D/Collider3D.hpp @@ -135,7 +135,7 @@ namespace Nz class NAZARA_PHYSICS3D_API CompoundCollider3D : public Collider3D { public: - CompoundCollider3D(Collider3D** geoms, std::size_t geomCount); + CompoundCollider3D(std::vector geoms); const std::vector& GetGeoms() const; ColliderType3D GetType() const override; diff --git a/src/Nazara/Physics3D/Collider3D.cpp b/src/Nazara/Physics3D/Collider3D.cpp index d71f4caa8..857ec4ba8 100644 --- a/src/Nazara/Physics3D/Collider3D.cpp +++ b/src/Nazara/Physics3D/Collider3D.cpp @@ -128,12 +128,12 @@ namespace Nz std::size_t primitiveCount = list.GetSize(); if (primitiveCount > 1) { - std::vector geoms(primitiveCount); + std::vector geoms(primitiveCount); for (unsigned int i = 0; i < primitiveCount; ++i) geoms[i] = CreateGeomFromPrimitive(list.GetPrimitive(i)); - return CompoundCollider3D::New(&geoms[0], primitiveCount); + return CompoundCollider3D::New(std::move(geoms)); } else if (primitiveCount > 0) return CreateGeomFromPrimitive(list.GetPrimitive(0)); @@ -239,11 +239,9 @@ namespace Nz /******************************* CompoundCollider3D ********************************/ - CompoundCollider3D::CompoundCollider3D(Collider3D** geoms, std::size_t geomCount) + CompoundCollider3D::CompoundCollider3D(std::vector geoms) : + m_geoms(std::move(geoms)) { - m_geoms.reserve(geomCount); - for (std::size_t i = 0; i < geomCount; ++i) - m_geoms.emplace_back(geoms[i]); } const std::vector& CompoundCollider3D::GetGeoms() const From 326fb930af75e0e0f4429e2c0ea06398c1fe94fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 27 Jul 2017 11:41:13 +0200 Subject: [PATCH 10/32] Sdk/LuaBinding: Add support for component binding without default constructor (will throw a lua error) --- SDK/include/NDK/Lua/LuaBinding.inl | 46 +++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/SDK/include/NDK/Lua/LuaBinding.inl b/SDK/include/NDK/Lua/LuaBinding.inl index 502f179ae..cb80305d7 100644 --- a/SDK/include/NDK/Lua/LuaBinding.inl +++ b/SDK/include/NDK/Lua/LuaBinding.inl @@ -6,6 +6,35 @@ namespace Ndk { + namespace Detail + { + template + struct AddComponentIf; + + template<> + struct AddComponentIf + { + template + static int AddComponent(Nz::LuaState& lua, EntityHandle& handle) + { + T& component = handle->AddComponent(); + lua.Push(component.CreateHandle()); + return 1; + } + }; + + template<> + struct AddComponentIf + { + template + static int AddComponent(Nz::LuaState& lua, EntityHandle& /*handle*/) + { + lua.Error("Component has no default constructor and cannot be created from Lua yet"); + return 0; + } + }; + } + /*! * \brief Binds a component to a name * @@ -13,14 +42,15 @@ namespace Ndk * * \remark Produces a NazaraAssert if name is empty */ - template void LuaBinding::BindComponent(const Nz::String& name) { NazaraAssert(!name.IsEmpty(), "Component name cannot be empty"); + static_assert(std::is_base_of::value, "ComponentType must inherit BaseComponent"); + ComponentBinding binding; - binding.adder = &AddComponentOfType; + binding.adder = &Detail::AddComponentIf::value>::AddComponent; binding.getter = &PushComponentOfType; binding.index = T::componentIndex; binding.name = name; @@ -32,21 +62,9 @@ namespace Ndk m_componentBindingByName[name] = T::componentIndex; } - template - int LuaBinding::AddComponentOfType(Nz::LuaState& lua, EntityHandle& handle) - { - static_assert(std::is_base_of::value, "ComponentType must inherit BaseComponent"); - - T& component = handle->AddComponent(); - lua.Push(component.CreateHandle()); - return 1; - } - template int LuaBinding::PushComponentOfType(Nz::LuaState& lua, BaseComponent& component) { - static_assert(std::is_base_of::value, "ComponentType must inherit BaseComponent"); - T& rightComponent = static_cast(component); lua.Push(rightComponent.CreateHandle()); return 1; From 2b365167580dae32e7a81ee5b1209ee7f70196ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 27 Jul 2017 14:39:34 +0200 Subject: [PATCH 11/32] Fix compilation --- SDK/include/NDK/Lua/LuaBinding.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/include/NDK/Lua/LuaBinding.inl b/SDK/include/NDK/Lua/LuaBinding.inl index cb80305d7..d95314099 100644 --- a/SDK/include/NDK/Lua/LuaBinding.inl +++ b/SDK/include/NDK/Lua/LuaBinding.inl @@ -50,7 +50,7 @@ namespace Ndk static_assert(std::is_base_of::value, "ComponentType must inherit BaseComponent"); ComponentBinding binding; - binding.adder = &Detail::AddComponentIf::value>::AddComponent; + binding.adder = &Detail::AddComponentIf::value>::template AddComponent; binding.getter = &PushComponentOfType; binding.index = T::componentIndex; binding.name = name; From b64ab862fec6c4cd61e602d8d0975b751f907a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 27 Jul 2017 14:39:48 +0200 Subject: [PATCH 12/32] Fix warnings --- SDK/include/NDK/Canvas.hpp | 14 +++++++------- SDK/include/NDK/Canvas.inl | 14 +++++++------- SDK/src/NDK/Canvas.cpp | 6 +++--- include/Nazara/Lua/LuaState.inl | 5 +++-- src/Nazara/Graphics/ForwardRenderQueue.cpp | 3 +-- src/Nazara/Physics2D/PhysWorld2D.cpp | 10 +++++----- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/SDK/include/NDK/Canvas.hpp b/SDK/include/NDK/Canvas.hpp index 0cc314b73..33453306f 100644 --- a/SDK/include/NDK/Canvas.hpp +++ b/SDK/include/NDK/Canvas.hpp @@ -44,13 +44,13 @@ namespace Ndk void UnregisterWidget(std::size_t index); private: - void OnMouseButtonPressed(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseButtonEvent& event); - void OnMouseButtonRelease(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseButtonEvent& event); - void OnMouseMoved(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseMoveEvent& event); - void OnMouseLeft(const Nz::EventHandler* eventHandler); - void OnKeyPressed(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event); - void OnKeyReleased(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event); - void OnTextEntered(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::TextEvent& event); + void OnEventMouseButtonPressed(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseButtonEvent& event); + void OnEventMouseButtonRelease(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseButtonEvent& event); + void OnEventMouseMoved(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseMoveEvent& event); + void OnEventMouseLeft(const Nz::EventHandler* eventHandler); + void OnEventKeyPressed(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event); + void OnEventKeyReleased(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event); + void OnEventTextEntered(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::TextEvent& event); struct WidgetBox { diff --git a/SDK/include/NDK/Canvas.inl b/SDK/include/NDK/Canvas.inl index 3dd5de87f..9b2ba461e 100644 --- a/SDK/include/NDK/Canvas.inl +++ b/SDK/include/NDK/Canvas.inl @@ -20,13 +20,13 @@ namespace Ndk RegisterToCanvas(); // Connect to every meaningful event - m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, this, &Canvas::OnKeyPressed); - m_keyReleasedSlot.Connect(eventHandler.OnKeyReleased, this, &Canvas::OnKeyReleased); - m_mouseButtonPressedSlot.Connect(eventHandler.OnMouseButtonPressed, this, &Canvas::OnMouseButtonPressed); - m_mouseButtonReleasedSlot.Connect(eventHandler.OnMouseButtonReleased, this, &Canvas::OnMouseButtonRelease); - m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, this, &Canvas::OnMouseMoved); - m_mouseLeftSlot.Connect(eventHandler.OnMouseLeft, this, &Canvas::OnMouseLeft); - m_textEnteredSlot.Connect(eventHandler.OnTextEntered, this, &Canvas::OnTextEntered); + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, this, &Canvas::OnEventKeyPressed); + m_keyReleasedSlot.Connect(eventHandler.OnKeyReleased, this, &Canvas::OnEventKeyReleased); + m_mouseButtonPressedSlot.Connect(eventHandler.OnMouseButtonPressed, this, &Canvas::OnEventMouseButtonPressed); + m_mouseButtonReleasedSlot.Connect(eventHandler.OnMouseButtonReleased, this, &Canvas::OnEventMouseButtonRelease); + m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, this, &Canvas::OnEventMouseMoved); + m_mouseLeftSlot.Connect(eventHandler.OnMouseLeft, this, &Canvas::OnEventMouseLeft); + m_textEnteredSlot.Connect(eventHandler.OnTextEntered, this, &Canvas::OnEventTextEntered); // Disable padding by default SetPadding(0.f, 0.f, 0.f, 0.f); diff --git a/SDK/src/NDK/Canvas.cpp b/SDK/src/NDK/Canvas.cpp index 84e4b5bd8..f41695409 100644 --- a/SDK/src/NDK/Canvas.cpp +++ b/SDK/src/NDK/Canvas.cpp @@ -48,7 +48,7 @@ namespace Ndk m_widgetBoxes.pop_back(); } - void Canvas::OnMouseButtonPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent& event) + void Canvas::OnEventMouseButtonPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent& event) { if (m_hoveredWidget) { @@ -59,7 +59,7 @@ namespace Ndk } } - void Canvas::OnMouseButtonRelease(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent & event) + void Canvas::OnEventMouseButtonRelease(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent & event) { if (m_hoveredWidget) { @@ -70,7 +70,7 @@ namespace Ndk } } - void Canvas::OnMouseMoved(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent& event) + void Canvas::OnEventMouseMoved(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent& event) { const WidgetBox* bestEntry = nullptr; float bestEntryArea = std::numeric_limits::infinity(); diff --git a/include/Nazara/Lua/LuaState.inl b/include/Nazara/Lua/LuaState.inl index da191d8a2..a5fa57f8c 100644 --- a/include/Nazara/Lua/LuaState.inl +++ b/include/Nazara/Lua/LuaState.inl @@ -788,16 +788,17 @@ namespace Nz template std::enable_if_t::value, T> LuaState::CheckBounds(int index, long long value) const { + unsigned long long uValue = static_cast(value); constexpr unsigned long long minBounds = 0; constexpr unsigned long long maxBounds = std::numeric_limits::max(); - if (value < minBounds || value > maxBounds) + if (uValue < minBounds || uValue > maxBounds) { Nz::StringStream stream; stream << "Argument #" << index << " is outside value range [" << minBounds << ", " << maxBounds << "] (" << value << ')'; Error(stream); } - return static_cast(value); + return static_cast(uValue); } inline LuaState LuaState::GetState(lua_State* internalState) diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index ba8c68358..840875ea3 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -697,7 +697,7 @@ namespace Nz auto it = layers.find(i); if (it == layers.end()) it = layers.insert(std::make_pair(i, Layer())).first; - + Layer& layer = it->second; layer.clearCount = 0; @@ -729,7 +729,6 @@ namespace Nz void ForwardRenderQueue::SortForOrthographic(const AbstractViewer * viewer) { Planef nearPlane = viewer->GetFrustum().GetPlane(FrustumPlane_Near); - Vector3f viewerPos = viewer->GetEyePosition(); for (auto& pair : layers) { diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index e6f1c95ca..997b53468 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -60,12 +60,12 @@ namespace Nz { cpPointQueryInfo queryInfo; - if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, &queryInfo)) + if (cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, &queryInfo)) { result->closestPoint.Set(Nz::Vector2(queryInfo.point.x, queryInfo.point.y)); result->distance = float(queryInfo.distance); result->fraction.Set(Nz::Vector2(queryInfo.gradient.x, queryInfo.gradient.y)); - result->nearestBody = static_cast(cpShapeGetUserData(shape)); + result->nearestBody = static_cast(cpShapeGetUserData(queryInfo.shape)); return true; } @@ -74,7 +74,7 @@ namespace Nz } else { - if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, nullptr)) + if (cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, nullptr)) return true; else return false; @@ -114,7 +114,7 @@ namespace Nz { cpSegmentQueryInfo queryInfo; - if (cpShape* shape = cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, &queryInfo)) + if (cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, &queryInfo)) { hitInfo->fraction = float(queryInfo.alpha); hitInfo->hitNormal.Set(Nz::Vector2(queryInfo.normal.x, queryInfo.normal.y)); @@ -128,7 +128,7 @@ namespace Nz } else { - if (cpShape* shape = cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, nullptr)) + if (cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, nullptr)) return true; else return false; From adf7bb15cf7782fb97626d01f2688f93f4ce7f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 27 Jul 2017 14:50:08 +0200 Subject: [PATCH 13/32] Save your files kids.. --- SDK/src/NDK/BaseWidget.cpp | 14 +++++++------- SDK/src/NDK/Canvas.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/SDK/src/NDK/BaseWidget.cpp b/SDK/src/NDK/BaseWidget.cpp index c4ef2d1f8..38c080e4c 100644 --- a/SDK/src/NDK/BaseWidget.cpp +++ b/SDK/src/NDK/BaseWidget.cpp @@ -142,11 +142,11 @@ namespace Ndk m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex); } - void BaseWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) + void BaseWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& /*key*/) { } - void BaseWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) + void BaseWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& /*key*/) { } @@ -154,15 +154,15 @@ namespace Ndk { } - void BaseWidget::OnMouseMoved(int x, int y, int deltaX, int deltaY) + void BaseWidget::OnMouseMoved(int /*x*/, int /*y*/, int /*deltaX*/, int /*deltaY*/) { } - void BaseWidget::OnMouseButtonPress(int x, int y, Nz::Mouse::Button button) + void BaseWidget::OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button /*button*/) { } - void BaseWidget::OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button) + void BaseWidget::OnMouseButtonRelease(int /*x*/, int /*y*/, Nz::Mouse::Button /*button*/) { } @@ -170,11 +170,11 @@ namespace Ndk { } - void BaseWidget::OnParentResized(const Nz::Vector2f& newSize) + void BaseWidget::OnParentResized(const Nz::Vector2f& /*newSize*/) { } - void BaseWidget::OnTextEntered(char32_t character, bool repeated) + void BaseWidget::OnTextEntered(char32_t /*character*/, bool /*repeated*/) { } diff --git a/SDK/src/NDK/Canvas.cpp b/SDK/src/NDK/Canvas.cpp index f41695409..11e9d1ce9 100644 --- a/SDK/src/NDK/Canvas.cpp +++ b/SDK/src/NDK/Canvas.cpp @@ -120,7 +120,7 @@ namespace Ndk } } - void Canvas::OnMouseLeft(const Nz::EventHandler* /*eventHandler*/) + void Canvas::OnEventMouseLeft(const Nz::EventHandler* /*eventHandler*/) { if (m_hoveredWidget) { @@ -129,19 +129,19 @@ namespace Ndk } } - void Canvas::OnKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event) + void Canvas::OnEventKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event) { if (m_keyboardOwner) m_keyboardOwner->OnKeyPressed(event); } - void Canvas::OnKeyReleased(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event) + void Canvas::OnEventKeyReleased(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event) { if (m_keyboardOwner) m_keyboardOwner->OnKeyReleased(event); } - void Canvas::OnTextEntered(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::TextEvent& event) + void Canvas::OnEventTextEntered(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::TextEvent& event) { if (m_keyboardOwner) m_keyboardOwner->OnTextEntered(event.character, event.repeated); From 3d368b2fe7451173e959d61b479dd657a12a2b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 4 Aug 2017 13:37:17 +0200 Subject: [PATCH 14/32] Network/SocketPoller: Fix behavior of Wait method (-1 will block) --- include/Nazara/Network/SocketPoller.hpp | 2 +- src/Nazara/Network/Linux/SocketPollerImpl.cpp | 2 +- src/Nazara/Network/Linux/SocketPollerImpl.hpp | 2 +- src/Nazara/Network/Posix/SocketPollerImpl.cpp | 2 +- src/Nazara/Network/Posix/SocketPollerImpl.hpp | 2 +- src/Nazara/Network/SocketPoller.cpp | 4 ++-- src/Nazara/Network/Win32/SocketPollerImpl.cpp | 4 ++-- src/Nazara/Network/Win32/SocketPollerImpl.hpp | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/Nazara/Network/SocketPoller.hpp b/include/Nazara/Network/SocketPoller.hpp index c801ca5e2..5b583fa0f 100644 --- a/include/Nazara/Network/SocketPoller.hpp +++ b/include/Nazara/Network/SocketPoller.hpp @@ -31,7 +31,7 @@ namespace Nz bool RegisterSocket(AbstractSocket& socket, SocketPollEventFlags eventFlags); void UnregisterSocket(AbstractSocket& socket); - bool Wait(UInt64 msTimeout); + bool Wait(int msTimeout); inline SocketPoller& operator=(SocketPoller&& socketPoller); diff --git a/src/Nazara/Network/Linux/SocketPollerImpl.cpp b/src/Nazara/Network/Linux/SocketPollerImpl.cpp index 6617efd37..6e902a587 100644 --- a/src/Nazara/Network/Linux/SocketPollerImpl.cpp +++ b/src/Nazara/Network/Linux/SocketPollerImpl.cpp @@ -80,7 +80,7 @@ namespace Nz NazaraWarning("An error occured while removing socket from epoll structure (errno " + String::Number(errno) + ": " + Error::GetLastSystemError() + ')'); } - int SocketPollerImpl::Wait(UInt64 msTimeout, SocketError* error) + int SocketPollerImpl::Wait(int msTimeout, SocketError* error) { int activeSockets; diff --git a/src/Nazara/Network/Linux/SocketPollerImpl.hpp b/src/Nazara/Network/Linux/SocketPollerImpl.hpp index a804102fa..882141d38 100644 --- a/src/Nazara/Network/Linux/SocketPollerImpl.hpp +++ b/src/Nazara/Network/Linux/SocketPollerImpl.hpp @@ -30,7 +30,7 @@ namespace Nz bool RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags); void UnregisterSocket(SocketHandle socket); - int Wait(UInt64 msTimeout, SocketError* error); + int Wait(int msTimeout, SocketError* error); private: std::unordered_set m_readyToReadSockets; diff --git a/src/Nazara/Network/Posix/SocketPollerImpl.cpp b/src/Nazara/Network/Posix/SocketPollerImpl.cpp index 59b8a8ca7..ed391c6f3 100644 --- a/src/Nazara/Network/Posix/SocketPollerImpl.cpp +++ b/src/Nazara/Network/Posix/SocketPollerImpl.cpp @@ -76,7 +76,7 @@ namespace Nz m_readyToWriteSockets.erase(socket); } - int SocketPollerImpl::Wait(UInt64 msTimeout, SocketError* error) + int SocketPollerImpl::Wait(int msTimeout, SocketError* error) { int activeSockets; diff --git a/src/Nazara/Network/Posix/SocketPollerImpl.hpp b/src/Nazara/Network/Posix/SocketPollerImpl.hpp index 3582121d4..1ded2dabc 100644 --- a/src/Nazara/Network/Posix/SocketPollerImpl.hpp +++ b/src/Nazara/Network/Posix/SocketPollerImpl.hpp @@ -30,7 +30,7 @@ namespace Nz bool RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags); void UnregisterSocket(SocketHandle socket); - int Wait(UInt64 msTimeout, SocketError* error); + int Wait(int msTimeout, SocketError* error); private: std::unordered_set m_readyToReadSockets; diff --git a/src/Nazara/Network/SocketPoller.cpp b/src/Nazara/Network/SocketPoller.cpp index 7ef261ef9..50eeb5cdf 100644 --- a/src/Nazara/Network/SocketPoller.cpp +++ b/src/Nazara/Network/SocketPoller.cpp @@ -170,7 +170,7 @@ namespace Nz * 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 IsReadyToRead or IsReadyToWrite functions. * - * \param msTimeout Maximum time to wait in milliseconds, 0 for infinity + * \param msTimeout Maximum time to wait in milliseconds, 0 will returns immediately and -1 will block indefinitely * * \return True if at least one socket registered to the poller is ready. * @@ -179,7 +179,7 @@ namespace Nz * \see IsReady * \see RegisterSocket */ - bool SocketPoller::Wait(UInt64 msTimeout) + bool SocketPoller::Wait(int msTimeout) { SocketError error; diff --git a/src/Nazara/Network/Win32/SocketPollerImpl.cpp b/src/Nazara/Network/Win32/SocketPollerImpl.cpp index b6dee66e9..6789f35f4 100644 --- a/src/Nazara/Network/Win32/SocketPollerImpl.cpp +++ b/src/Nazara/Network/Win32/SocketPollerImpl.cpp @@ -129,7 +129,7 @@ namespace Nz #endif } - int SocketPollerImpl::Wait(UInt64 msTimeout, SocketError* error) + int SocketPollerImpl::Wait(int msTimeout, SocketError* error) { int activeSockets; @@ -179,7 +179,7 @@ namespace Nz tv.tv_sec = static_cast(msTimeout / 1000ULL); tv.tv_usec = static_cast((msTimeout % 1000ULL) * 1000ULL); - activeSockets = ::select(0xDEADBEEF, readSet, writeSet, nullptr, (msTimeout > 0) ? &tv : nullptr); //< The first argument is ignored on Windows + activeSockets = ::select(0xDEADBEEF, readSet, writeSet, nullptr, (msTimeout >= 0) ? &tv : nullptr); //< The first argument is ignored on Windows if (activeSockets == SOCKET_ERROR) { if (error) diff --git a/src/Nazara/Network/Win32/SocketPollerImpl.hpp b/src/Nazara/Network/Win32/SocketPollerImpl.hpp index a94af1372..2dfb32070 100644 --- a/src/Nazara/Network/Win32/SocketPollerImpl.hpp +++ b/src/Nazara/Network/Win32/SocketPollerImpl.hpp @@ -32,7 +32,7 @@ namespace Nz bool RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags); void UnregisterSocket(SocketHandle socket); - int Wait(UInt64 msTimeout, SocketError* error); + int Wait(int msTimeout, SocketError* error); private: #if NAZARA_NETWORK_POLL_SUPPORT From 80ddfd1fbefb7512121943a8121e9e91cd4b04de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Fri, 4 Aug 2017 13:38:23 +0200 Subject: [PATCH 15/32] Sdk/World: Fix Clear not clearing everything --- SDK/src/NDK/World.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index 3ed1a25d0..702452fc4 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -119,6 +119,7 @@ namespace Ndk // This is made to avoid that handle warn uselessly entities before their destruction m_entities.clear(); m_entityBlocks.clear(); + m_freeIdList.clear(); m_waitingEntities.clear(); m_aliveEntities.Clear(); From 732c37a194a97dbba35a60ac4793c3f266d9f65d Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 5 Aug 2017 20:51:48 +0200 Subject: [PATCH 16/32] Sdk/BaseWidget: Begin doc --- SDK/src/NDK/BaseWidget.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/SDK/src/NDK/BaseWidget.cpp b/SDK/src/NDK/BaseWidget.cpp index c4ef2d1f8..baff9f2d7 100644 --- a/SDK/src/NDK/BaseWidget.cpp +++ b/SDK/src/NDK/BaseWidget.cpp @@ -11,6 +11,20 @@ namespace Ndk { + /*! + * \ingroup NDK + * \class Ndk::BaseWidget + * \brief Abstract class serving as a base class for all widgets + */ + + /*! + * \brief Constructs a BaseWidget object using another widget as its parent + * + * \param parent Parent widget, must be valid and attached to a canvas + * + * Constructs a BaseWidget object using another widget as a base. + * This will also register the widget to the canvas owning the top-most widget. + */ BaseWidget::BaseWidget(BaseWidget* parent) : BaseWidget() { @@ -24,11 +38,19 @@ namespace Ndk RegisterToCanvas(); } + /*! + * \brief Frees the widget, unregistering it from its canvas + */ BaseWidget::~BaseWidget() { UnregisterFromCanvas(); } + /*! + * \brief Destroy the widget, deleting it in the process. + * + * Calling this function immediately destroys the widget, freeing its memory. + */ void BaseWidget::Destroy() { NazaraAssert(this != m_canvas, "Canvas cannot be destroyed by calling Destroy()"); @@ -36,6 +58,9 @@ namespace Ndk m_widgetParent->DestroyChild(this); //< This does delete us } + /*! + * \brief Enable or disables the widget background. + */ void BaseWidget::EnableBackground(bool enable) { if (m_backgroundEntity.IsValid() == enable) From 74af157113cdeb345511170f2381d949fb321e76 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 6 Aug 2017 23:08:36 +0200 Subject: [PATCH 17/32] PhysWorld2D: Use std::function for callbacks --- include/Nazara/Physics2D/PhysWorld2D.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index 30a3b1141..36a0c5c42 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -24,10 +25,10 @@ namespace Nz { friend RigidBody2D; - using ContactEndCallback = void(*)(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 ContactStartCallback = bool(*)(PhysWorld2D& world, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata); + using ContactEndCallback = std::function; + using ContactPreSolveCallback = std::function; + using ContactPostSolveCallback = std::function; + using ContactStartCallback = std::function; public: struct Callback; From 506a963539d0cb1f91997eb178fd863040edc34c Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 6 Aug 2017 23:37:14 +0200 Subject: [PATCH 18/32] SimpleTextDrawer: Assert after update --- src/Nazara/Utility/SimpleTextDrawer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Nazara/Utility/SimpleTextDrawer.cpp b/src/Nazara/Utility/SimpleTextDrawer.cpp index 1b53f808f..2b42ecbe8 100644 --- a/src/Nazara/Utility/SimpleTextDrawer.cpp +++ b/src/Nazara/Utility/SimpleTextDrawer.cpp @@ -105,11 +105,10 @@ namespace Nz const AbstractTextDrawer::Line& SimpleTextDrawer::GetLine(std::size_t index) const { - NazaraAssert(index < m_lines.size(), "Line index out of range"); - if (!m_glyphUpdated) UpdateGlyphs(); + NazaraAssert(index < m_lines.size(), "Line index out of range"); return m_lines[index]; } From 5aa2efc737c3ffa94223476c5bbd5041609dda73 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 6 Aug 2017 23:37:35 +0200 Subject: [PATCH 19/32] TextAreaWidget: Add support for 2D cursor --- SDK/include/NDK/Widgets/TextAreaWidget.hpp | 10 ++- SDK/include/NDK/Widgets/TextAreaWidget.inl | 73 +++++++++++++++++++--- SDK/src/NDK/Widgets/TextAreaWidget.cpp | 53 +++++++--------- 3 files changed, 95 insertions(+), 41 deletions(-) diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.hpp b/SDK/include/NDK/Widgets/TextAreaWidget.hpp index 0bf5a3a59..7bab6f1bf 100644 --- a/SDK/include/NDK/Widgets/TextAreaWidget.hpp +++ b/SDK/include/NDK/Widgets/TextAreaWidget.hpp @@ -32,7 +32,8 @@ namespace Ndk inline void EnableMultiline(bool enable = true); - inline std::size_t GetCursorPosition() const; + inline const Nz::Vector2ui& GetCursorPosition() const; + inline std::size_t GetGlyphUnderCursor() const; inline std::size_t GetLineCount() const; inline const Nz::String& GetText() const; inline const Nz::Color& GetTextColor() const; @@ -43,10 +44,12 @@ namespace Ndk inline bool IsReadOnly() const; inline void MoveCursor(int offset); + inline void MoveCursor(const Nz::Vector2i& offset); void ResizeToContent() override; - inline void SetCursorPosition(std::size_t cursorPosition); + inline void SetCursorPosition(std::size_t glyphIndex); + inline void SetCursorPosition(Nz::Vector2ui cursorPosition); inline void SetReadOnly(bool readOnly = true); inline void SetText(const Nz::String& text); inline void SetTextColor(const Nz::Color& text); @@ -82,7 +85,8 @@ namespace Ndk Nz::SimpleTextDrawer m_drawer; Nz::SpriteRef m_cursorSprite; Nz::TextSpriteRef m_textSprite; - std::size_t m_cursorPosition; + Nz::Vector2ui m_cursorPosition; + std::size_t m_cursorGlyph; bool m_multiLineEnabled; bool m_readOnly; }; diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.inl b/SDK/include/NDK/Widgets/TextAreaWidget.inl index 077f538ec..f76147ec7 100644 --- a/SDK/include/NDK/Widgets/TextAreaWidget.inl +++ b/SDK/include/NDK/Widgets/TextAreaWidget.inl @@ -20,11 +20,16 @@ namespace Ndk m_multiLineEnabled = enable; } - inline std::size_t TextAreaWidget::GetCursorPosition() const + inline const Nz::Vector2ui& TextAreaWidget::GetCursorPosition() const { return m_cursorPosition; } + inline std::size_t Ndk::TextAreaWidget::GetGlyphUnderCursor() const + { + return m_cursorGlyph; + } + inline std::size_t TextAreaWidget::GetLineCount() const { return m_drawer.GetLineCount(); @@ -53,26 +58,80 @@ namespace Ndk inline void TextAreaWidget::MoveCursor(int offset) { if (offset >= 0) - SetCursorPosition(m_cursorPosition += static_cast(offset)); + SetCursorPosition(m_cursorGlyph + static_cast(offset)); else { std::size_t nOffset = static_cast(-offset); - if (nOffset >= m_cursorPosition) + if (nOffset >= m_cursorGlyph) SetCursorPosition(0); else - SetCursorPosition(m_cursorPosition - nOffset); + SetCursorPosition(m_cursorGlyph - nOffset); } } - inline void TextAreaWidget::SetCursorPosition(std::size_t cursorPosition) + inline void TextAreaWidget::MoveCursor(const Nz::Vector2i& offset) { - OnTextAreaCursorMove(this, &cursorPosition); + auto BoundOffset = [] (unsigned int cursorPosition, int offset) -> unsigned int + { + if (offset >= 0) + return cursorPosition + offset; + else + { + unsigned int nOffset = static_cast(-offset); + if (nOffset >= cursorPosition) + return 0; + else + return cursorPosition - nOffset; + } + }; - m_cursorPosition = std::min(cursorPosition, m_drawer.GetGlyphCount()); + Nz::Vector2ui cursorPosition = m_cursorPosition; + cursorPosition.x = BoundOffset(static_cast(cursorPosition.x), offset.x); + cursorPosition.y = BoundOffset(static_cast(cursorPosition.y), offset.y); + + SetCursorPosition(cursorPosition); + } + + inline void TextAreaWidget::SetCursorPosition(std::size_t glyphIndex) + { + OnTextAreaCursorMove(this, &glyphIndex); + + m_cursorGlyph = std::min(glyphIndex, m_drawer.GetGlyphCount()); + + std::size_t lineCount = m_drawer.GetLineCount(); + std::size_t line = 0U; + for (std::size_t i = line + 1; i < lineCount; ++i) + { + if (m_drawer.GetLine(i).glyphIndex > m_cursorGlyph) + break; + + line = i; + } + + const auto& lineInfo = m_drawer.GetLine(line); + + m_cursorPosition.y = line; + m_cursorPosition.x = m_cursorGlyph - lineInfo.glyphIndex; RefreshCursor(); } + inline void TextAreaWidget::SetCursorPosition(Nz::Vector2ui cursorPosition) + { + std::size_t lineCount = m_drawer.GetLineCount(); + if (cursorPosition.y >= lineCount) + cursorPosition.y = static_cast(lineCount - 1); + + const auto& lineInfo = m_drawer.GetLine(cursorPosition.y); + if (cursorPosition.y + 1 < lineCount) + { + const auto& nextLineInfo = m_drawer.GetLine(cursorPosition.y + 1); + cursorPosition.x = std::min(cursorPosition.x, static_cast(nextLineInfo.glyphIndex - lineInfo.glyphIndex - 1)); + } + + SetCursorPosition(lineInfo.glyphIndex + cursorPosition.x); //= m_drawer.GetGlyphCount()) + if (m_cursorGlyph >= m_drawer.GetGlyphCount()) { AppendText(text); SetCursorPosition(m_drawer.GetGlyphCount()); @@ -89,10 +90,10 @@ namespace Ndk else { Nz::String currentText = m_drawer.GetText(); - currentText.Insert(currentText.GetCharacterPosition(m_cursorPosition), text); + currentText.Insert(currentText.GetCharacterPosition(m_cursorGlyph), text); SetText(currentText); - SetCursorPosition(m_cursorPosition + text.GetLength()); + SetCursorPosition(m_cursorGlyph + text.GetLength()); } } @@ -114,11 +115,11 @@ namespace Ndk const Nz::String& text = m_drawer.GetText(); Nz::String newText; - if (m_cursorPosition > 0) - newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition) - 1)); + if (m_cursorGlyph > 0) + newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorGlyph) - 1)); - if (m_cursorPosition < m_drawer.GetGlyphCount()) - newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition + 1))); + if (m_cursorGlyph < m_drawer.GetGlyphCount()) + newText.Append(text.SubString(text.GetCharacterPosition(m_cursorGlyph + 1))); m_drawer.SetText(newText); m_textSprite->Update(m_drawer); @@ -133,7 +134,7 @@ namespace Ndk if (ignoreDefaultAction) break; - //TODO + MoveCursor({0, 1}); break; } @@ -145,7 +146,7 @@ namespace Ndk if (ignoreDefaultAction) break; - MoveCursor(-1); + MoveCursor({-1, 0}); break; } @@ -157,7 +158,7 @@ namespace Ndk if (ignoreDefaultAction) break; - MoveCursor(1); + MoveCursor({1, 0}); break; } @@ -169,7 +170,7 @@ namespace Ndk if (ignoreDefaultAction) break; - //TODO + MoveCursor({0, -1}); break; } } @@ -221,13 +222,13 @@ namespace Ndk const Nz::String& text = m_drawer.GetText(); Nz::String newText; - if (m_cursorPosition > 1) - newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition - 1) - 1)); + if (m_cursorGlyph > 1) + newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorGlyph - 1) - 1)); - if (m_cursorPosition < m_drawer.GetGlyphCount()) - newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition))); + if (m_cursorGlyph < m_drawer.GetGlyphCount()) + newText.Append(text.SubString(text.GetCharacterPosition(m_cursorGlyph))); - MoveCursor(-1); + MoveCursor({-1, 0}); SetText(newText); break; } @@ -258,25 +259,15 @@ namespace Ndk void TextAreaWidget::RefreshCursor() { - std::size_t lineCount = m_drawer.GetLineCount(); - std::size_t line = 0U; - for (std::size_t i = line + 1; i < lineCount; ++i) - { - if (m_drawer.GetLine(i).glyphIndex > m_cursorPosition) - break; - - line = i; - } - - const auto& lineInfo = m_drawer.GetLine(line); + const auto& lineInfo = m_drawer.GetLine(m_cursorPosition.y); std::size_t glyphCount = m_drawer.GetGlyphCount(); float position; - if (glyphCount > 0 && lineInfo.glyphIndex < m_cursorPosition) + if (glyphCount > 0 && lineInfo.glyphIndex < m_cursorGlyph) { - const auto& glyph = m_drawer.GetGlyph(std::min(m_cursorPosition, glyphCount - 1)); + const auto& glyph = m_drawer.GetGlyph(std::min(m_cursorGlyph, glyphCount - 1)); position = glyph.bounds.x; - if (m_cursorPosition >= glyphCount) + if (m_cursorGlyph >= glyphCount) position += glyph.bounds.width; } else From 4e9508e23a22a3103b78cc1e5245848dab276b0b Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 6 Aug 2017 23:40:41 +0200 Subject: [PATCH 20/32] TextAreaWidget: It feels natural now *.* --- SDK/include/NDK/Widgets/TextAreaWidget.inl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.inl b/SDK/include/NDK/Widgets/TextAreaWidget.inl index f76147ec7..ffc75c8ba 100644 --- a/SDK/include/NDK/Widgets/TextAreaWidget.inl +++ b/SDK/include/NDK/Widgets/TextAreaWidget.inl @@ -121,7 +121,9 @@ namespace Ndk std::size_t lineCount = m_drawer.GetLineCount(); if (cursorPosition.y >= lineCount) cursorPosition.y = static_cast(lineCount - 1); - + + m_cursorPosition = cursorPosition; + const auto& lineInfo = m_drawer.GetLine(cursorPosition.y); if (cursorPosition.y + 1 < lineCount) { @@ -129,7 +131,13 @@ namespace Ndk cursorPosition.x = std::min(cursorPosition.x, static_cast(nextLineInfo.glyphIndex - lineInfo.glyphIndex - 1)); } - SetCursorPosition(lineInfo.glyphIndex + cursorPosition.x); // Date: Sun, 6 Aug 2017 23:46:55 +0200 Subject: [PATCH 21/32] RigidBody2D: Add experimental SetMomentOfInertia method --- include/Nazara/Physics2D/RigidBody2D.hpp | 1 + src/Nazara/Physics2D/RigidBody2D.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/include/Nazara/Physics2D/RigidBody2D.hpp b/include/Nazara/Physics2D/RigidBody2D.hpp index 1af3ea89c..f2b3da2d7 100644 --- a/include/Nazara/Physics2D/RigidBody2D.hpp +++ b/include/Nazara/Physics2D/RigidBody2D.hpp @@ -57,6 +57,7 @@ namespace Nz void SetGeom(Collider2DRef geom); void SetMass(float mass); void SetMassCenter(const Vector2f& center); + void SetMomentOfInertia(float moment); void SetPosition(const Vector2f& position); void SetRotation(float rotation); void SetUserdata(void* ud); diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index 85d43ee76..370b01b3b 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -285,6 +285,14 @@ namespace Nz cpBodySetCenterOfGravity(m_handle, cpv(center.x, center.y)); } + void RigidBody2D::SetMomentOfInertia(float moment) + { + m_world->RegisterPostStep(this, [moment] (Nz::RigidBody2D* body) + { + cpBodySetMoment(body->GetHandle(), moment); + }); + } + void RigidBody2D::SetPosition(const Vector2f& position) { cpBodySetPosition(m_handle, cpv(position.x, position.y)); From 061b358857a061d5c2b12c41b273e4261328be80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 8 Aug 2017 16:34:22 +0200 Subject: [PATCH 22/32] Sdk/ButtonWidget: Fix layout not triggering when updating text --- SDK/include/NDK/Widgets/ButtonWidget.inl | 2 ++ SDK/src/NDK/Widgets/ButtonWidget.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/SDK/include/NDK/Widgets/ButtonWidget.inl b/SDK/include/NDK/Widgets/ButtonWidget.inl index fedc7614a..4013d290d 100644 --- a/SDK/include/NDK/Widgets/ButtonWidget.inl +++ b/SDK/include/NDK/Widgets/ButtonWidget.inl @@ -9,5 +9,7 @@ namespace Ndk inline void ButtonWidget::UpdateText(const Nz::AbstractTextDrawer& drawer) { m_textSprite->Update(drawer); + + Layout(); } } diff --git a/SDK/src/NDK/Widgets/ButtonWidget.cpp b/SDK/src/NDK/Widgets/ButtonWidget.cpp index 29c04c98f..a525d7a68 100644 --- a/SDK/src/NDK/Widgets/ButtonWidget.cpp +++ b/SDK/src/NDK/Widgets/ButtonWidget.cpp @@ -61,7 +61,6 @@ namespace Ndk m_gradientSprite->SetColor(Nz::Color(128, 128, 128)); } - void ButtonWidget::OnMouseExit() { m_gradientSprite->SetColor(Nz::Color(74, 74, 74)); From 84e5ea00238804c8b9f5e2e613f3e6c0bcaf96e4 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 13 Aug 2017 21:40:41 +0200 Subject: [PATCH 23/32] SimpleTextDrawer: Fix Faux-Bold --- src/Nazara/Utility/SimpleTextDrawer.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Nazara/Utility/SimpleTextDrawer.cpp b/src/Nazara/Utility/SimpleTextDrawer.cpp index 2b42ecbe8..739af792e 100644 --- a/src/Nazara/Utility/SimpleTextDrawer.cpp +++ b/src/Nazara/Utility/SimpleTextDrawer.cpp @@ -318,6 +318,10 @@ namespace Nz glyph.color = m_color; glyph.flipped = fontGlyph.flipped; + glyph.bounds.Set(fontGlyph.aabb); + glyph.bounds.x += m_drawPos.x; + glyph.bounds.y += m_drawPos.y; + if (fontGlyph.requireFauxBold) { // Let's simulate bold by enlarging the glyph (not a neat idea, but should work) @@ -329,16 +333,13 @@ namespace Nz // Replace it at the correct height Vector2f offset(glyph.bounds.GetCenter() - center); + glyph.bounds.x -= offset.x; glyph.bounds.y -= offset.y; // Adjust advance (+10%) advance += advance / 10; } - glyph.bounds.Set(fontGlyph.aabb); - glyph.bounds.x += m_drawPos.x; - glyph.bounds.y += m_drawPos.y; - // We "lean" the glyph to simulate italics style float italic = (fontGlyph.requireFauxItalic) ? 0.208f : 0.f; float italicTop = italic * glyph.bounds.y; From 973e3b094aa5cbc9751286e02c140aef9a900c39 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 14 Aug 2017 01:59:17 +0200 Subject: [PATCH 24/32] Build: Add PremakeProject option --- build/scripts/common.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/build/scripts/common.lua b/build/scripts/common.lua index ea7097e97..220d2084b 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -42,7 +42,7 @@ end function NazaraBuild:Execute() if (_ACTION == nil) then -- If no action is specified, the user probably only wants to know how all of this works - return -- Alors l'utilisateur voulait probablement savoir comment utiliser le programme, on ne fait rien + return end local platformData @@ -74,7 +74,6 @@ function NazaraBuild:Execute() includedirs("../extlibs/include") libdirs("../extlibs/lib/common") location(_ACTION) - kind("StaticLib") for k, libTable in ipairs(self.OrderedExtLibs) do project(libTable.Name) @@ -129,6 +128,13 @@ function NazaraBuild:Execute() language("C++") location(_ACTION) + if (self.Config["PremakeProject"]) then + local commandLine = "premake5.exe " .. table.concat(_ARGV, ' ') + project("_PremakeProject") + kind("Utility") + prebuildcommands("cd .. && " .. commandLine) + end + -- Modules if (_OPTIONS["united"]) then project("NazaraEngine") @@ -517,9 +523,9 @@ function NazaraBuild:LoadConfig() end end - AddBoolOption("BuildDependencies", "with-extlibs", "Builds the extern libraries") AddBoolOption("BuildExamples", "with-examples", "Builds the examples") + AddBoolOption("PremakeProject", "premakeproject", "Add a PremakeProject as a shortcut to call Premake") AddBoolOption("ServerMode", "server", "Excludes client-only modules/tools/examples") AddBoolOption("UniteModules", "united", "Builds all the modules as one united library") From 5531e81e6546f1f2689a87d23456f1c4a767d8fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 15 Aug 2017 12:32:19 +0200 Subject: [PATCH 25/32] Core: Add CRC64 and regenerate global headers --- SDK/src/NDK/Lua/LuaBinding_Core.cpp | 5 +- include/Nazara/Core/Enums.hpp | 1 + include/Nazara/Core/Hash/CRC64.hpp | 34 ++++++++ include/Nazara/Network.hpp | 4 + src/Nazara/Core/AbstractHash.cpp | 4 + src/Nazara/Core/Hash/CRC64.cpp | 115 ++++++++++++++++++++++++++++ 6 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 include/Nazara/Core/Hash/CRC64.hpp create mode 100644 src/Nazara/Core/Hash/CRC64.cpp diff --git a/SDK/src/NDK/Lua/LuaBinding_Core.cpp b/SDK/src/NDK/Lua/LuaBinding_Core.cpp index f86aafa98..1e4a02e7f 100644 --- a/SDK/src/NDK/Lua/LuaBinding_Core.cpp +++ b/SDK/src/NDK/Lua/LuaBinding_Core.cpp @@ -321,10 +321,11 @@ namespace Ndk state.SetGlobal("CursorPosition"); // Nz::HashType - static_assert(Nz::HashType_Max + 1 == 9, "Nz::HashType has been updated but change was not reflected to Lua binding"); - state.PushTable(0, 9); + static_assert(Nz::HashType_Max + 1 == 10, "Nz::HashType has been updated but change was not reflected to Lua binding"); + state.PushTable(0, 10); { state.PushField("CRC32", Nz::HashType_CRC32); + state.PushField("CRC64", Nz::HashType_CRC64); state.PushField("Fletcher16", Nz::HashType_Fletcher16); state.PushField("MD5", Nz::HashType_MD5); state.PushField("SHA1", Nz::HashType_SHA1); diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index 2bacb1f2d..937c01a44 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -63,6 +63,7 @@ namespace Nz enum HashType { HashType_CRC32, + HashType_CRC64, HashType_Fletcher16, HashType_MD5, HashType_SHA1, diff --git a/include/Nazara/Core/Hash/CRC64.hpp b/include/Nazara/Core/Hash/CRC64.hpp new file mode 100644 index 000000000..1c9819e5f --- /dev/null +++ b/include/Nazara/Core/Hash/CRC64.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_HASH_CRC64_HPP +#define NAZARA_HASH_CRC64_HPP + +#include +#include +#include + +namespace Nz +{ + class NAZARA_CORE_API HashCRC64 : public AbstractHash + { + public: + HashCRC64() = default; + ~HashCRC64() = default; + + void Append(const UInt8* data, std::size_t len) override; + void Begin() override; + ByteArray End() override; + + std::size_t GetDigestLength() const override; + const char* GetHashName() const override; + + private: + Nz::UInt64 m_crc; + }; +} + +#endif // NAZARA_HASH_CRC64_HPP diff --git a/include/Nazara/Network.hpp b/include/Nazara/Network.hpp index 1b2dc72c5..151bc3f52 100644 --- a/include/Nazara/Network.hpp +++ b/include/Nazara/Network.hpp @@ -32,6 +32,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include diff --git a/src/Nazara/Core/AbstractHash.cpp b/src/Nazara/Core/AbstractHash.cpp index ae2cb63b5..39e5a2ef2 100644 --- a/src/Nazara/Core/AbstractHash.cpp +++ b/src/Nazara/Core/AbstractHash.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,9 @@ namespace Nz case HashType_CRC32: return std::make_unique(); + case HashType_CRC64: + return std::make_unique(); + case HashType_MD5: return std::make_unique(); diff --git a/src/Nazara/Core/Hash/CRC64.cpp b/src/Nazara/Core/Hash/CRC64.cpp new file mode 100644 index 000000000..3001009a3 --- /dev/null +++ b/src/Nazara/Core/Hash/CRC64.cpp @@ -0,0 +1,115 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + struct HashCRC64_state + { + UInt64 crc; + }; + + namespace + { + static const UInt64 crc64_table[256] = { + 0x0000000000000000ULL, 0x7ad870c830358979ULL, 0xf5b0e190606b12f2ULL, 0x8f689158505e9b8bULL, + 0xc038e5739841b68fULL, 0xbae095bba8743ff6ULL, 0x358804e3f82aa47dULL, 0x4f50742bc81f2d04ULL, + 0xab28ecb46814fe75ULL, 0xd1f09c7c5821770cULL, 0x5e980d24087fec87ULL, 0x24407dec384a65feULL, + 0x6b1009c7f05548faULL, 0x11c8790fc060c183ULL, 0x9ea0e857903e5a08ULL, 0xe478989fa00bd371ULL, + 0x7d08ff3b88be6f81ULL, 0x07d08ff3b88be6f8ULL, 0x88b81eabe8d57d73ULL, 0xf2606e63d8e0f40aULL, + 0xbd301a4810ffd90eULL, 0xc7e86a8020ca5077ULL, 0x4880fbd87094cbfcULL, 0x32588b1040a14285ULL, + 0xd620138fe0aa91f4ULL, 0xacf86347d09f188dULL, 0x2390f21f80c18306ULL, 0x594882d7b0f40a7fULL, + 0x1618f6fc78eb277bULL, 0x6cc0863448deae02ULL, 0xe3a8176c18803589ULL, 0x997067a428b5bcf0ULL, + 0xfa11fe77117cdf02ULL, 0x80c98ebf2149567bULL, 0x0fa11fe77117cdf0ULL, 0x75796f2f41224489ULL, + 0x3a291b04893d698dULL, 0x40f16bccb908e0f4ULL, 0xcf99fa94e9567b7fULL, 0xb5418a5cd963f206ULL, + 0x513912c379682177ULL, 0x2be1620b495da80eULL, 0xa489f35319033385ULL, 0xde51839b2936bafcULL, + 0x9101f7b0e12997f8ULL, 0xebd98778d11c1e81ULL, 0x64b116208142850aULL, 0x1e6966e8b1770c73ULL, + 0x8719014c99c2b083ULL, 0xfdc17184a9f739faULL, 0x72a9e0dcf9a9a271ULL, 0x08719014c99c2b08ULL, + 0x4721e43f0183060cULL, 0x3df994f731b68f75ULL, 0xb29105af61e814feULL, 0xc849756751dd9d87ULL, + 0x2c31edf8f1d64ef6ULL, 0x56e99d30c1e3c78fULL, 0xd9810c6891bd5c04ULL, 0xa3597ca0a188d57dULL, + 0xec09088b6997f879ULL, 0x96d1784359a27100ULL, 0x19b9e91b09fcea8bULL, 0x636199d339c963f2ULL, + 0xdf7adabd7a6e2d6fULL, 0xa5a2aa754a5ba416ULL, 0x2aca3b2d1a053f9dULL, 0x50124be52a30b6e4ULL, + 0x1f423fcee22f9be0ULL, 0x659a4f06d21a1299ULL, 0xeaf2de5e82448912ULL, 0x902aae96b271006bULL, + 0x74523609127ad31aULL, 0x0e8a46c1224f5a63ULL, 0x81e2d7997211c1e8ULL, 0xfb3aa75142244891ULL, + 0xb46ad37a8a3b6595ULL, 0xceb2a3b2ba0eececULL, 0x41da32eaea507767ULL, 0x3b024222da65fe1eULL, + 0xa2722586f2d042eeULL, 0xd8aa554ec2e5cb97ULL, 0x57c2c41692bb501cULL, 0x2d1ab4dea28ed965ULL, + 0x624ac0f56a91f461ULL, 0x1892b03d5aa47d18ULL, 0x97fa21650afae693ULL, 0xed2251ad3acf6feaULL, + 0x095ac9329ac4bc9bULL, 0x7382b9faaaf135e2ULL, 0xfcea28a2faafae69ULL, 0x8632586aca9a2710ULL, + 0xc9622c4102850a14ULL, 0xb3ba5c8932b0836dULL, 0x3cd2cdd162ee18e6ULL, 0x460abd1952db919fULL, + 0x256b24ca6b12f26dULL, 0x5fb354025b277b14ULL, 0xd0dbc55a0b79e09fULL, 0xaa03b5923b4c69e6ULL, + 0xe553c1b9f35344e2ULL, 0x9f8bb171c366cd9bULL, 0x10e3202993385610ULL, 0x6a3b50e1a30ddf69ULL, + 0x8e43c87e03060c18ULL, 0xf49bb8b633338561ULL, 0x7bf329ee636d1eeaULL, 0x012b592653589793ULL, + 0x4e7b2d0d9b47ba97ULL, 0x34a35dc5ab7233eeULL, 0xbbcbcc9dfb2ca865ULL, 0xc113bc55cb19211cULL, + 0x5863dbf1e3ac9decULL, 0x22bbab39d3991495ULL, 0xadd33a6183c78f1eULL, 0xd70b4aa9b3f20667ULL, + 0x985b3e827bed2b63ULL, 0xe2834e4a4bd8a21aULL, 0x6debdf121b863991ULL, 0x1733afda2bb3b0e8ULL, + 0xf34b37458bb86399ULL, 0x8993478dbb8deae0ULL, 0x06fbd6d5ebd3716bULL, 0x7c23a61ddbe6f812ULL, + 0x3373d23613f9d516ULL, 0x49aba2fe23cc5c6fULL, 0xc6c333a67392c7e4ULL, 0xbc1b436e43a74e9dULL, + 0x95ac9329ac4bc9b5ULL, 0xef74e3e19c7e40ccULL, 0x601c72b9cc20db47ULL, 0x1ac40271fc15523eULL, + 0x5594765a340a7f3aULL, 0x2f4c0692043ff643ULL, 0xa02497ca54616dc8ULL, 0xdafce7026454e4b1ULL, + 0x3e847f9dc45f37c0ULL, 0x445c0f55f46abeb9ULL, 0xcb349e0da4342532ULL, 0xb1eceec59401ac4bULL, + 0xfebc9aee5c1e814fULL, 0x8464ea266c2b0836ULL, 0x0b0c7b7e3c7593bdULL, 0x71d40bb60c401ac4ULL, + 0xe8a46c1224f5a634ULL, 0x927c1cda14c02f4dULL, 0x1d148d82449eb4c6ULL, 0x67ccfd4a74ab3dbfULL, + 0x289c8961bcb410bbULL, 0x5244f9a98c8199c2ULL, 0xdd2c68f1dcdf0249ULL, 0xa7f41839ecea8b30ULL, + 0x438c80a64ce15841ULL, 0x3954f06e7cd4d138ULL, 0xb63c61362c8a4ab3ULL, 0xcce411fe1cbfc3caULL, + 0x83b465d5d4a0eeceULL, 0xf96c151de49567b7ULL, 0x76048445b4cbfc3cULL, 0x0cdcf48d84fe7545ULL, + 0x6fbd6d5ebd3716b7ULL, 0x15651d968d029fceULL, 0x9a0d8ccedd5c0445ULL, 0xe0d5fc06ed698d3cULL, + 0xaf85882d2576a038ULL, 0xd55df8e515432941ULL, 0x5a3569bd451db2caULL, 0x20ed197575283bb3ULL, + 0xc49581ead523e8c2ULL, 0xbe4df122e51661bbULL, 0x3125607ab548fa30ULL, 0x4bfd10b2857d7349ULL, + 0x04ad64994d625e4dULL, 0x7e7514517d57d734ULL, 0xf11d85092d094cbfULL, 0x8bc5f5c11d3cc5c6ULL, + 0x12b5926535897936ULL, 0x686de2ad05bcf04fULL, 0xe70573f555e26bc4ULL, 0x9ddd033d65d7e2bdULL, + 0xd28d7716adc8cfb9ULL, 0xa85507de9dfd46c0ULL, 0x273d9686cda3dd4bULL, 0x5de5e64efd965432ULL, + 0xb99d7ed15d9d8743ULL, 0xc3450e196da80e3aULL, 0x4c2d9f413df695b1ULL, 0x36f5ef890dc31cc8ULL, + 0x79a59ba2c5dc31ccULL, 0x037deb6af5e9b8b5ULL, 0x8c157a32a5b7233eULL, 0xf6cd0afa9582aa47ULL, + 0x4ad64994d625e4daULL, 0x300e395ce6106da3ULL, 0xbf66a804b64ef628ULL, 0xc5bed8cc867b7f51ULL, + 0x8aeeace74e645255ULL, 0xf036dc2f7e51db2cULL, 0x7f5e4d772e0f40a7ULL, 0x05863dbf1e3ac9deULL, + 0xe1fea520be311aafULL, 0x9b26d5e88e0493d6ULL, 0x144e44b0de5a085dULL, 0x6e963478ee6f8124ULL, + 0x21c640532670ac20ULL, 0x5b1e309b16452559ULL, 0xd476a1c3461bbed2ULL, 0xaeaed10b762e37abULL, + 0x37deb6af5e9b8b5bULL, 0x4d06c6676eae0222ULL, 0xc26e573f3ef099a9ULL, 0xb8b627f70ec510d0ULL, + 0xf7e653dcc6da3dd4ULL, 0x8d3e2314f6efb4adULL, 0x0256b24ca6b12f26ULL, 0x788ec2849684a65fULL, + 0x9cf65a1b368f752eULL, 0xe62e2ad306bafc57ULL, 0x6946bb8b56e467dcULL, 0x139ecb4366d1eea5ULL, + 0x5ccebf68aecec3a1ULL, 0x2616cfa09efb4ad8ULL, 0xa97e5ef8cea5d153ULL, 0xd3a62e30fe90582aULL, + 0xb0c7b7e3c7593bd8ULL, 0xca1fc72bf76cb2a1ULL, 0x45775673a732292aULL, 0x3faf26bb9707a053ULL, + 0x70ff52905f188d57ULL, 0x0a2722586f2d042eULL, 0x854fb3003f739fa5ULL, 0xff97c3c80f4616dcULL, + 0x1bef5b57af4dc5adULL, 0x61372b9f9f784cd4ULL, 0xee5fbac7cf26d75fULL, 0x9487ca0fff135e26ULL, + 0xdbd7be24370c7322ULL, 0xa10fceec0739fa5bULL, 0x2e675fb4576761d0ULL, 0x54bf2f7c6752e8a9ULL, + 0xcdcf48d84fe75459ULL, 0xb71738107fd2dd20ULL, 0x387fa9482f8c46abULL, 0x42a7d9801fb9cfd2ULL, + 0x0df7adabd7a6e2d6ULL, 0x772fdd63e7936bafULL, 0xf8474c3bb7cdf024ULL, 0x829f3cf387f8795dULL, + 0x66e7a46c27f3aa2cULL, 0x1c3fd4a417c62355ULL, 0x935745fc4798b8deULL, 0xe98f353477ad31a7ULL, + 0xa6df411fbfb21ca3ULL, 0xdc0731d78f8795daULL, 0x536fa08fdfd90e51ULL, 0x29b7d047efec8728ULL + }; + } + + void HashCRC64::Append(const UInt8* data, std::size_t len) + { + while (len--) + m_crc = crc64_table[(m_crc ^ *data++) & 0xFF] ^ (m_crc >> 8); + } + + void HashCRC64::Begin() + { + m_crc = 0; + } + + ByteArray HashCRC64::End() + { + #ifdef NAZARA_LITTLE_ENDIAN + SwapBytes(&m_crc, sizeof(UInt64)); + #endif + + return ByteArray(reinterpret_cast(&m_crc), 8); + } + + std::size_t HashCRC64::GetDigestLength() const + { + return 8; + } + + const char* HashCRC64::GetHashName() const + { + return "CRC64"; + } +} From 0e99f93866f050bb51eddff372d5d803acbdcdc4 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 16 Aug 2017 20:32:50 +0200 Subject: [PATCH 26/32] Demo: New LogoDemo for particles, yay --- examples/Particles/LogoDemo.cpp | 152 +++++++++++++++++++++++++++----- examples/Particles/LogoDemo.hpp | 5 +- examples/Particles/main.cpp | 2 +- 3 files changed, 134 insertions(+), 25 deletions(-) diff --git a/examples/Particles/LogoDemo.cpp b/examples/Particles/LogoDemo.cpp index cc0c2a610..c127a23db 100644 --- a/examples/Particles/LogoDemo.cpp +++ b/examples/Particles/LogoDemo.cpp @@ -1,4 +1,5 @@ #include "LogoDemo.hpp" +#include #include #include #include @@ -8,12 +9,22 @@ namespace { const float duration = 10.f; - const float maxVel = 50.f; + const float maxSpeed = 100.f; + const float maxMouseForce = 1000.f; + const float mouseForce = 500.f; const float pauseTime = 3.f; const float startTime = 2.f; const float speed = 3.f; } +struct ParticleData +{ + Nz::Color color; + Nz::Vector2f destination; + Nz::Vector2f position; + Nz::Vector2f velocity; +}; + struct SpriteController : public Nz::ParticleController { void Apply(Nz::ParticleGroup& system, Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) override @@ -21,15 +32,74 @@ struct SpriteController : public Nz::ParticleController if (!enabled) return; - auto posPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Position); - auto velPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Velocity); + auto destPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Userdata0); + auto posPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Position); + auto velPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Velocity); + std::uniform_real_distribution dis(-1.f, 1.f); + + unsigned int count = 0; for (unsigned int i = startId; i <= endId; ++i) - posPtr[i] += velPtr[i] * elapsedTime * factor; + { + Nz::Vector2f newVel = destPtr[i] - posPtr[i]; + float length; + newVel.Normalize(&length); + + float distance = SquaredDistancePointSegment(oldMousePos, actualMousePos, posPtr[i]); + if (distance < 250.f) + { + count++; + Nz::Vector2f mouseLine = actualMousePos - oldMousePos; + float mouseLength; + mouseLine.Normalize(&mouseLength); + if (mouseLength > 5.f) + { + velPtr[i] += mouseLine * std::min(mouseLength * mouseForce, maxMouseForce) * elapsedTime; + velPtr[i] += Nz::Vector2f(dis(randomGen), dis(randomGen)) * std::min(mouseLength, maxMouseForce * 0.1f); + } + } + + if (length > 1.f || velPtr[i].GetSquaredLength() > Nz::IntegralPow(30.f, 2)) + { + newVel *= maxSpeed; + + velPtr[i] = Nz::Lerp(velPtr[i], newVel, 0.4f * elapsedTime); + posPtr[i] += velPtr[i] * elapsedTime; + } + else + { + velPtr[i] = Nz::Vector2f::Zero(); + posPtr[i] = destPtr[i]; + } + } + + std::cout << count << std::endl; } + static float SquaredDistancePointSegment(const Nz::Vector2f& s0, const Nz::Vector2f& s1, const Nz::Vector2f& point) + { + // http://geomalgorithms.com/a02-_lines.html + Nz::Vector2f v = s1 - s0; + Nz::Vector2f w = point - s0; + + float c1 = Nz::Vector2f::DotProduct(w, v); + if (c1 <= 0.f) + return point.SquaredDistance(s0); + + float c2 = Nz::Vector2f::DotProduct(v, v); + if (c2 <= c1) + return point.SquaredDistance(s1); + + float b = c1 / c2; + Nz::Vector2f projPoint = s0 + b * v; + return projPoint.SquaredDistance(point); + } + + std::mt19937 randomGen; bool enabled = false; - float factor = 1.f; + float factor = 1000.f; + Nz::Vector2f actualMousePos; + Nz::Vector2f oldMousePos; }; @@ -67,9 +137,9 @@ ParticleDemo("Logo", sharedData) unsigned int height = m_logo.GetHeight(); m_pixels.reserve(width * height); - for (unsigned int y = 0; y < height; ++y) + for (unsigned int x = 0; x < width; ++x) { - for (unsigned int x = 0; x < width; ++x) + for (unsigned int y = 0; y < height; ++y) { Nz::Color color = m_logo.GetPixelColor(x, y); if (color.a == 0) @@ -93,6 +163,12 @@ ParticleDemo("Logo", sharedData) m_controller = new SpriteController; m_renderer = new SpriteRenderer(std::move(material)); + + m_declaration = Nz::ParticleDeclaration::New(); + m_declaration->EnableComponent(Nz::ParticleComponent_Color, Nz::ComponentType_Color, NazaraOffsetOf(ParticleData, color)); + m_declaration->EnableComponent(Nz::ParticleComponent_Position, Nz::ComponentType_Float2, NazaraOffsetOf(ParticleData, position)); + m_declaration->EnableComponent(Nz::ParticleComponent_Userdata0, Nz::ComponentType_Float2, NazaraOffsetOf(ParticleData, destination)); + m_declaration->EnableComponent(Nz::ParticleComponent_Velocity, Nz::ComponentType_Float2, NazaraOffsetOf(ParticleData, velocity)); } void LogoExample::Enter(Ndk::StateMachine& fsm) @@ -106,17 +182,20 @@ void LogoExample::Enter(Ndk::StateMachine& fsm) m_shared.world2D->GetSystem().SetDefaultBackground(Nz::TextureBackground::New(std::move(backgroundTexture))); Ndk::EntityHandle particleGroupEntity = m_shared.world2D->CreateEntity(); - Ndk::ParticleGroupComponent& particleGroup = particleGroupEntity->AddComponent(m_pixels.size(), Nz::ParticleLayout_Sprite); + Ndk::ParticleGroupComponent& particleGroup = particleGroupEntity->AddComponent(m_pixels.size(), m_declaration); RegisterParticleGroup(particleGroupEntity); particleGroup.AddController(m_controller); particleGroup.SetRenderer(m_renderer); - m_particles = static_cast(particleGroup.CreateParticles(m_pixels.size())); + m_particles = particleGroup.CreateParticles(m_pixels.size()); ResetParticles(-duration * (speed / 2.f)); m_accumulator = pauseTime + duration; m_totalAccumulator = 0.f; + + SpriteController* controller = static_cast(m_controller.Get()); + controller->actualMousePos = controller->oldMousePos = Nz::Vector2f(Nz::Mouse::GetPosition(*m_shared.target)); } void LogoExample::Leave(Ndk::StateMachine & fsm) @@ -136,35 +215,62 @@ bool LogoExample::Update(Ndk::StateMachine& fsm, float elapsedTime) m_accumulator += elapsedTime; SpriteController* controller = static_cast(m_controller.Get()); - if (m_accumulator > pauseTime + 2.f * duration) + controller->enabled = (m_accumulator > pauseTime); + + if (m_mouseClock.GetMilliseconds() > 1000/30) { - ResetParticles(0.f); - m_accumulator = 0.f; + m_mouseClock.Restart(); + + controller->oldMousePos = controller->actualMousePos; + controller->actualMousePos = Nz::Vector2f(Nz::Mouse::GetPosition(*m_shared.target)); } - controller->enabled = (m_accumulator > pauseTime); - controller->factor = -speed + speed * (m_accumulator - pauseTime) / (duration); + if (Nz::Mouse::IsButtonPressed(Nz::Mouse::Left)) + { + if (!m_hasClicked) + { + m_hasClicked = true; + std::uniform_real_distribution dis(50.f, 60.f); + + ParticleData* sprite = static_cast(m_particles); + for (std::size_t i = 0; i < m_pixels.size(); ++i) + { + Nz::Vector2f particleToMouse = sprite[i].position - controller->actualMousePos; + float sqDist = particleToMouse.GetSquaredLength(); + if (sqDist < 10000.f) + { + float dist = std::sqrt(sqDist); + particleToMouse /= std::max(dist, 1.f); + + sprite[i].velocity += particleToMouse * dis(m_shared.randomGen); + } + } + } + } + else + m_hasClicked = false; return true; } void LogoExample::ResetParticles(float elapsed) { - Nz::Vector2f center = {m_shared.target->GetWidth() / 2.f, m_shared.target->GetHeight() / 2.f}; + unsigned int width = m_shared.target->GetWidth(); + unsigned int height = m_shared.target->GetHeight(); + + Nz::Vector2f center = {width / 2.f, height / 2.f}; Nz::Vector2f offset = center - Nz::Vector2f(Nz::Vector2ui(m_logo.GetSize()) / 2); - float ratio = float(m_shared.target->GetWidth()) / m_shared.target->GetHeight(); - std::uniform_real_distribution disX(-maxVel * ratio, maxVel * ratio); - std::uniform_real_distribution disY(-maxVel, maxVel); + std::uniform_real_distribution disX(0.f, float(width)); + std::uniform_real_distribution disY(-float(height) * 0.5f, float(height) * 1.5f); - Nz::ParticleStruct_Sprite* sprite = m_particles; + ParticleData* sprite = static_cast(m_particles); for (PixelData& data : m_pixels) { sprite->color = data.color; - sprite->position = offset + Nz::Vector2f(data.pos); - sprite->rotation = 0.f; - sprite->velocity.Set(disX(m_shared.randomGen), disY(m_shared.randomGen), 0.f); - sprite->position += sprite->velocity * elapsed; + sprite->destination = offset + Nz::Vector2f(data.pos); + sprite->position.Set(disX(m_shared.randomGen) - float(width), disY(m_shared.randomGen)); + sprite->velocity = Nz::Vector2f::Zero(); sprite++; } } diff --git a/examples/Particles/LogoDemo.hpp b/examples/Particles/LogoDemo.hpp index d5c374d32..7ce594080 100644 --- a/examples/Particles/LogoDemo.hpp +++ b/examples/Particles/LogoDemo.hpp @@ -30,10 +30,13 @@ class LogoExample : public ParticleDemo std::vector m_pixels; Nz::BackgroundRef m_oldBackground; - Nz::ParticleStruct_Sprite* m_particles; + void* m_particles; + Nz::Clock m_mouseClock; Nz::Image m_logo; Nz::ParticleControllerRef m_controller; + Nz::ParticleDeclarationRef m_declaration; Nz::ParticleRendererRef m_renderer; + bool m_hasClicked; float m_accumulator; float m_totalAccumulator; }; diff --git a/examples/Particles/main.cpp b/examples/Particles/main.cpp index bf230bfe7..f4754c136 100644 --- a/examples/Particles/main.cpp +++ b/examples/Particles/main.cpp @@ -105,7 +105,7 @@ int main() fpsNode.SetPosition(5.f, window.GetHeight() - fpsCountBox.height - particleCountBox.height - 5.f); - //shared.demos.push_back(std::make_shared(shared)); + shared.demos.push_back(std::make_shared(shared)); shared.demos.push_back(std::make_shared(shared)); std::size_t demoIndex = 0; From fc2fd81719f269289be2b3feb6ccd11b1984b4a7 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 16 Aug 2017 20:33:13 +0200 Subject: [PATCH 27/32] Utility: Make Window constructor explicit --- include/Nazara/Renderer/RenderWindow.hpp | 2 +- include/Nazara/Utility/Window.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/Nazara/Renderer/RenderWindow.hpp b/include/Nazara/Renderer/RenderWindow.hpp index c71ad2b34..17a9b705d 100644 --- a/include/Nazara/Renderer/RenderWindow.hpp +++ b/include/Nazara/Renderer/RenderWindow.hpp @@ -31,7 +31,7 @@ namespace Nz public: RenderWindow() = default; RenderWindow(VideoMode mode, const String& title, WindowStyleFlags style = WindowStyle_Default, const ContextParameters& parameters = ContextParameters()); - RenderWindow(WindowHandle handle, const ContextParameters& parameters = ContextParameters()); + explicit RenderWindow(WindowHandle handle, const ContextParameters& parameters = ContextParameters()); RenderWindow(const RenderWindow&) = delete; RenderWindow(RenderWindow&&) = delete; ///TODO virtual ~RenderWindow(); diff --git a/include/Nazara/Utility/Window.hpp b/include/Nazara/Utility/Window.hpp index 32487370a..b9cbdb6fb 100644 --- a/include/Nazara/Utility/Window.hpp +++ b/include/Nazara/Utility/Window.hpp @@ -38,7 +38,7 @@ namespace Nz public: Window(); inline Window(VideoMode mode, const String& title, WindowStyleFlags style = WindowStyle_Default); - inline Window(WindowHandle handle); + inline explicit Window(WindowHandle handle); Window(const Window&) = delete; inline Window(Window&& window) noexcept; virtual ~Window(); From b7692400c4e9511c0688b61cbd6b3030a1bc1e44 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 16 Aug 2017 20:33:23 +0200 Subject: [PATCH 28/32] HardwareBuffer: Fix wtf behavior --- src/Nazara/Renderer/HardwareBuffer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp index 52bc339c2..f8378abf3 100644 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ b/src/Nazara/Renderer/HardwareBuffer.cpp @@ -50,7 +50,8 @@ namespace Nz UInt32 totalSize = m_parent->GetSize(); - bool forceDiscard = (size == totalSize); + //bool forceDiscard = (size == totalSize); + bool forceDiscard = true; OpenGL::BindBuffer(m_type, m_buffer); From 2fe905a4531644bacf93f3e73889ec9e587eeed6 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 16 Aug 2017 20:33:37 +0200 Subject: [PATCH 29/32] Increase instance buffer size --- include/Nazara/Renderer/Config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Nazara/Renderer/Config.hpp b/include/Nazara/Renderer/Config.hpp index f4458216f..873008941 100644 --- a/include/Nazara/Renderer/Config.hpp +++ b/include/Nazara/Renderer/Config.hpp @@ -30,7 +30,7 @@ /// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci // La taille du buffer d'Instancing (définit le nombre maximum d'instances en un rendu) -#define NAZARA_RENDERER_INSTANCE_BUFFER_SIZE 524288 // 8192 matrices 4x4 flottantes +#define NAZARA_RENDERER_INSTANCE_BUFFER_SIZE 1 * 1024 * 1024 // Utilise un manager de mémoire pour gérer les allocations dynamiques (détecte les leaks au prix d'allocations/libérations dynamiques plus lentes) #define NAZARA_RENDERER_MANAGE_MEMORY 0 From a09accc22ef5fc09e2ff5231a6e4780102344f0a Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 16 Aug 2017 20:34:19 +0200 Subject: [PATCH 30/32] LogoDemo: remove debug log --- examples/Particles/LogoDemo.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/Particles/LogoDemo.cpp b/examples/Particles/LogoDemo.cpp index c127a23db..831fcffd5 100644 --- a/examples/Particles/LogoDemo.cpp +++ b/examples/Particles/LogoDemo.cpp @@ -38,7 +38,6 @@ struct SpriteController : public Nz::ParticleController std::uniform_real_distribution dis(-1.f, 1.f); - unsigned int count = 0; for (unsigned int i = startId; i <= endId; ++i) { Nz::Vector2f newVel = destPtr[i] - posPtr[i]; @@ -48,7 +47,6 @@ struct SpriteController : public Nz::ParticleController float distance = SquaredDistancePointSegment(oldMousePos, actualMousePos, posPtr[i]); if (distance < 250.f) { - count++; Nz::Vector2f mouseLine = actualMousePos - oldMousePos; float mouseLength; mouseLine.Normalize(&mouseLength); @@ -72,8 +70,6 @@ struct SpriteController : public Nz::ParticleController posPtr[i] = destPtr[i]; } } - - std::cout << count << std::endl; } static float SquaredDistancePointSegment(const Nz::Vector2f& s0, const Nz::Vector2f& s1, const Nz::Vector2f& point) From a2a05f6d92513ba62186a4fda7534941de15aefe Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 20 Aug 2017 21:33:42 +0200 Subject: [PATCH 31/32] Build: Add PremakeProject config value --- build/config.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/config.lua b/build/config.lua index 12a9f8e77..b644423b3 100644 --- a/build/config.lua +++ b/build/config.lua @@ -16,6 +16,9 @@ Configurations = "Debug,Release" -- "Debug,Release,ReleaseWithDebug" -- Setup additionnals install directories, separated by a semi-colon ; (library binaries will be copied there) --InstallDir = "/usr/local/lib64" +-- Adds a project which will recall premake with its original arguments when built +PremakeProject = true + -- Excludes client-only modules/tools/examples ServerMode = false From f363420ebe93472bd9554472717ab412a22925b4 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 20 Aug 2017 21:34:12 +0200 Subject: [PATCH 32/32] Sdk/ParticleEmitterComponent: Fix Enable inline option --- SDK/include/NDK/Components/ParticleEmitterComponent.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/include/NDK/Components/ParticleEmitterComponent.hpp b/SDK/include/NDK/Components/ParticleEmitterComponent.hpp index dd40f7aaa..3e2c5f8af 100644 --- a/SDK/include/NDK/Components/ParticleEmitterComponent.hpp +++ b/SDK/include/NDK/Components/ParticleEmitterComponent.hpp @@ -24,7 +24,7 @@ namespace Ndk ParticleEmitterComponent(ParticleEmitterComponent&& emitter) = default; ~ParticleEmitterComponent() = default; - void Enable(bool active = true); + inline void Enable(bool active = true); inline bool IsActive() const;