This commit is contained in:
Lynix 2017-08-05 20:51:52 +02:00
commit d2b74cd3be
35 changed files with 447 additions and 111 deletions

View File

@ -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
{

View File

@ -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);

View File

@ -6,6 +6,35 @@
namespace Ndk
{
namespace Detail
{
template<bool HasDefaultConstructor>
struct AddComponentIf;
template<>
struct AddComponentIf<true>
{
template<typename T>
static int AddComponent(Nz::LuaState& lua, EntityHandle& handle)
{
T& component = handle->AddComponent<T>();
lua.Push(component.CreateHandle());
return 1;
}
};
template<>
struct AddComponentIf<false>
{
template<typename T>
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<typename T>
void LuaBinding::BindComponent(const Nz::String& name)
{
NazaraAssert(!name.IsEmpty(), "Component name cannot be empty");
static_assert(std::is_base_of<BaseComponent, T>::value, "ComponentType must inherit BaseComponent");
ComponentBinding binding;
binding.adder = &AddComponentOfType<T>;
binding.adder = &Detail::AddComponentIf<std::is_default_constructible<T>::value>::template AddComponent<T>;
binding.getter = &PushComponentOfType<T>;
binding.index = T::componentIndex;
binding.name = name;
@ -32,21 +62,9 @@ namespace Ndk
m_componentBindingByName[name] = T::componentIndex;
}
template<typename T>
int LuaBinding::AddComponentOfType(Nz::LuaState& lua, EntityHandle& handle)
{
static_assert(std::is_base_of<BaseComponent, T>::value, "ComponentType must inherit BaseComponent");
T& component = handle->AddComponent<T>();
lua.Push(component.CreateHandle());
return 1;
}
template<typename T>
int LuaBinding::PushComponentOfType(Nz::LuaState& lua, BaseComponent& component)
{
static_assert(std::is_base_of<BaseComponent, T>::value, "ComponentType must inherit BaseComponent");
T& rightComponent = static_cast<T&>(component);
lua.Push(rightComponent.CreateHandle());
return 1;

View File

@ -167,11 +167,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*/)
{
}
@ -179,15 +179,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*/)
{
}
@ -195,11 +195,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*/)
{
}

View File

@ -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<float>::infinity();
@ -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);

View File

@ -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();

View File

@ -788,16 +788,17 @@ namespace Nz
template<typename T>
std::enable_if_t<std::is_unsigned<T>::value, T> LuaState::CheckBounds(int index, long long value) const
{
unsigned long long uValue = static_cast<unsigned long long>(value);
constexpr unsigned long long minBounds = 0;
constexpr unsigned long long maxBounds = std::numeric_limits<T>::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<T>(value);
return static_cast<T>(uValue);
}
inline LuaState LuaState::GetState(lua_State* internalState)

View File

@ -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);

View File

@ -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);

View File

@ -11,6 +11,7 @@
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/ObjectLibrary.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Core/SparsePtr.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Physics2D/Config.hpp>
@ -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<cpShape*> CreateShapes(RigidBody2D* body) const = 0;
virtual void CreateShapes(RigidBody2D* body, std::vector<cpShape*>& 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<typename... Args> static BoxCollider2DRef New(Args&&... args);
private:
std::vector<cpShape*> CreateShapes(RigidBody2D* body) const override;
void CreateShapes(RigidBody2D* body, std::vector<cpShape*>& 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<typename... Args> static CircleCollider2DRef New(Args&&... args);
private:
std::vector<cpShape*> CreateShapes(RigidBody2D* body) const override;
void CreateShapes(RigidBody2D* body, std::vector<cpShape*>& shapes) const override;
Vector2f m_offset;
float m_radius;
};
class CompoundCollider2D;
using CompoundCollider2DConstRef = ObjectRef<const CompoundCollider2D>;
using CompoundCollider2DRef = ObjectRef<CompoundCollider2D>;
class NAZARA_PHYSICS2D_API CompoundCollider2D : public Collider2D
{
public:
CompoundCollider2D(std::vector<Collider2DRef> geoms);
float ComputeMomentOfInertia(float mass) const override;
inline const std::vector<Collider2DRef>& GetGeoms() const;
ColliderType2D GetType() const override;
template<typename... Args> static CompoundCollider2DRef New(Args&&... args);
private:
void CreateShapes(RigidBody2D* body, std::vector<cpShape*>& shapes) const override;
std::vector<Collider2DRef> m_geoms;
};
class ConvexCollider2D;
using ConvexCollider2DConstRef = ObjectRef<const ConvexCollider2D>;
using ConvexCollider2DRef = ObjectRef<ConvexCollider2D>;
class NAZARA_PHYSICS2D_API ConvexCollider2D : public Collider2D
{
public:
ConvexCollider2D(SparsePtr<const Vector2f> vertices, std::size_t vertexCount, float radius = 0.f);
float ComputeMomentOfInertia(float mass) const override;
ColliderType2D GetType() const override;
template<typename... Args> static ConvexCollider2DRef New(Args&&... args);
private:
void CreateShapes(RigidBody2D* body, std::vector<cpShape*>& shapes) const override;
std::vector<Vector2d> m_vertices;
float m_radius;
};
class NullCollider2D;
using NullCollider2DConstRef = ObjectRef<const NullCollider2D>;
@ -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<typename... Args> static NullCollider2DRef New(Args&&... args);
private:
std::vector<cpShape*> CreateShapes(RigidBody2D* body) const override;
void CreateShapes(RigidBody2D* body, std::vector<cpShape*>& 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<typename... Args> static SegmentCollider2DRef New(Args&&... args);
private:
std::vector<cpShape*> CreateShapes(RigidBody2D* body) const override;
void CreateShapes(RigidBody2D* body, std::vector<cpShape*>& shapes) const override;
Vector2f m_first;
Vector2f m_second;

View File

@ -100,6 +100,20 @@ namespace Nz
return object.release();
}
inline const std::vector<Collider2DRef>& Nz::CompoundCollider2D::GetGeoms() const
{
return m_geoms;
}
template<typename... Args>
CompoundCollider2DRef CompoundCollider2D::New(Args&&... args)
{
std::unique_ptr<CompoundCollider2D> object(new CompoundCollider2D(std::forward<Args>(args)...));
object->SetPersistent(false);
return object.release();
}
template<typename... Args>
NullCollider2DRef NullCollider2D::New(Args&&... args)
{

View File

@ -12,6 +12,7 @@ namespace Nz
enum ColliderType2D
{
ColliderType2D_Box,
ColliderType2D_Compound,
ColliderType2D_Convex,
ColliderType2D_Circle,
ColliderType2D_Null,

View File

@ -48,6 +48,7 @@ namespace Nz
float GetRotation() const;
void* GetUserdata() const;
Vector2f GetVelocity() const;
PhysWorld2D* GetWorld() const;
bool IsMoveable() const;
bool IsSleeping() const;

View File

@ -135,7 +135,7 @@ namespace Nz
class NAZARA_PHYSICS3D_API CompoundCollider3D : public Collider3D
{
public:
CompoundCollider3D(Collider3D** geoms, std::size_t geomCount);
CompoundCollider3D(std::vector<Collider3DRef> geoms);
const std::vector<Collider3DRef>& GetGeoms() const;
ColliderType3D GetType() const override;

View File

@ -47,6 +47,7 @@ namespace Nz
Vector3f GetPosition() const;
Quaternionf GetRotation() const;
Vector3f GetVelocity() const;
PhysWorld3D* GetWorld() const;
bool IsAutoSleepEnabled() const;
bool IsMoveable() const;

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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)

View File

@ -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;

View File

@ -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<SocketHandle> m_readyToReadSockets;

View File

@ -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<socklen_t>(nameBuffer.size());
IpAddress senderIp;
int byteRead = recvfrom(handle, buffer, length, 0, reinterpret_cast<sockaddr*>(&nameBuffer), &bufferLength);
if (byteRead == SOCKET_ERROR)
if (byteRead == -1)
{
int errorCode = GetLastErrorCode();
if (errorCode == EAGAIN)
@ -549,6 +549,92 @@ namespace Nz
else // else we received something
senderIp = IpAddressImpl::FromSockAddr(reinterpret_cast<const sockaddr*>(&nameBuffer));
if (from)
*from = IpAddressImpl::FromSockAddr(reinterpret_cast<const sockaddr*>(&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<struct iovec*>(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<int>(bufferCount);
IpAddressImpl::SockAddrBuffer nameBuffer;
if (from)
{
msgHdr.msg_name = nameBuffer.data();
msgHdr.msg_namelen = static_cast<socklen_t>(nameBuffer.size());
}
IpAddress senderIp;
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
byteRead = 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<const sockaddr*>(nameBuffer.data()));
#ifdef HAS_MSGHDR_FLAGS
if (msgHdr.msg_flags & MSG_TRUNC)
{
if (error)
*error = SocketError_DatagramSize;
return false;
}
#endif
if (from)
*from = senderIp;

View File

@ -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);

View File

@ -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;

View File

@ -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<SocketHandle> m_readyToReadSockets;

View File

@ -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;

View File

@ -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

View File

@ -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<int>(nameBuffer.size());
IpAddress senderIp;
StackAllocation memory = NazaraStackAllocation(bufferCount * sizeof(WSABUF));
WSABUF* winBuffers = static_cast<WSABUF*>(memory.GetPtr());
for (std::size_t i = 0; i < bufferCount; ++i)
{
winBuffers[i].buf = static_cast<CHAR*>(buffers[i].data);
winBuffers[i].len = static_cast<ULONG>(buffers[i].dataLength);
}
DWORD flags = 0;
DWORD byteRead;
if (WSARecvFrom(handle, winBuffers, static_cast<DWORD>(bufferCount), &byteRead, &flags, reinterpret_cast<sockaddr*>(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<const sockaddr*>(&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");

View File

@ -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);

View File

@ -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<long>(msTimeout / 1000ULL);
tv.tv_usec = static_cast<long>((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)

View File

@ -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

View File

@ -15,7 +15,9 @@ namespace Nz
{
cpShapeFilter filter = cpShapeFilterNew(m_collisionGroup, m_categoryMask, m_collisionMask);
std::vector<cpShape*> shapes = CreateShapes(body);
std::vector<cpShape*> shapes;
CreateShapes(body, shapes);
for (cpShape* shape : shapes)
{
cpShapeSetFilter(shape, filter);
@ -39,9 +41,9 @@ namespace Nz
{
}
float BoxCollider2D::ComputeInertialMatrix(float mass) const
float BoxCollider2D::ComputeMomentOfInertia(float mass) const
{
return static_cast<float>(cpMomentForBox2(mass, cpBBNew(m_rect.x, m_rect.y + m_rect.height, m_rect.x + m_rect.width, m_rect.y)));
return static_cast<float>(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
@ -49,12 +51,9 @@ namespace Nz
return ColliderType2D_Box;
}
std::vector<cpShape*> BoxCollider2D::CreateShapes(RigidBody2D* body) const
void BoxCollider2D::CreateShapes(RigidBody2D* body, std::vector<cpShape*>& shapes) const
{
std::vector<cpShape*> 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));
return 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));
}
/******************************** CircleCollider2D *********************************/
@ -65,7 +64,7 @@ namespace Nz
{
}
float CircleCollider2D::ComputeInertialMatrix(float mass) const
float CircleCollider2D::ComputeMomentOfInertia(float mass) const
{
return static_cast<float>(cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y)));
}
@ -75,12 +74,66 @@ namespace Nz
return ColliderType2D_Circle;
}
std::vector<cpShape*> CircleCollider2D::CreateShapes(RigidBody2D* body) const
void CircleCollider2D::CreateShapes(RigidBody2D* body, std::vector<cpShape*>& shapes) const
{
std::vector<cpShape*> shapes;
shapes.push_back(cpCircleShapeNew(body->GetHandle(), m_radius, cpv(m_offset.x, m_offset.y)));
}
return shapes;
/******************************** CompoundCollider2D *********************************/
CompoundCollider2D::CompoundCollider2D(std::vector<Collider2DRef> 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<cpShape*>& 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<const Vector2f> 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<float>(cpMomentForPoly(mass, int(m_vertices.size()), reinterpret_cast<const cpVect*>(m_vertices.data()), cpv(0.0, 0.0), m_radius));
}
ColliderType2D ConvexCollider2D::GetType() const
{
return ColliderType2D_Convex;
}
void ConvexCollider2D::CreateShapes(RigidBody2D* body, std::vector<cpShape*>& shapes) const
{
shapes.push_back(cpPolyShapeNew(body->GetHandle(), int(m_vertices.size()), reinterpret_cast<const cpVect*>(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<cpShape*> NullCollider2D::CreateShapes(RigidBody2D* /*body*/) const
void NullCollider2D::CreateShapes(RigidBody2D* /*body*/, std::vector<cpShape*>& /*shapes*/) const
{
return std::vector<cpShape*>();
}
/******************************** SegmentCollider2D *********************************/
float SegmentCollider2D::ComputeInertialMatrix(float mass) const
float SegmentCollider2D::ComputeMomentOfInertia(float mass) const
{
return static_cast<float>(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<cpShape*> SegmentCollider2D::CreateShapes(RigidBody2D* body) const
void SegmentCollider2D::CreateShapes(RigidBody2D* body, std::vector<cpShape*>& shapes) const
{
std::vector<cpShape*> 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;
}
}

View File

@ -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<cpFloat>(queryInfo.point.x, queryInfo.point.y));
result->distance = float(queryInfo.distance);
result->fraction.Set(Nz::Vector2<cpFloat>(queryInfo.gradient.x, queryInfo.gradient.y));
result->nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(shape));
result->nearestBody = static_cast<Nz::RigidBody2D*>(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<cpFloat>(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;
@ -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)

View File

@ -191,6 +191,11 @@ namespace Nz
return Vector2f(static_cast<float>(vel.x), static_cast<float>(vel.y));
}
PhysWorld2D* RigidBody2D::GetWorld() const
{
return m_world;
}
bool RigidBody2D::IsMoveable() const
{
return m_mass > 0.f;
@ -240,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)
@ -252,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
@ -266,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));
}
});
}

View File

@ -128,12 +128,12 @@ namespace Nz
std::size_t primitiveCount = list.GetSize();
if (primitiveCount > 1)
{
std::vector<Collider3D*> geoms(primitiveCount);
std::vector<Collider3DRef> 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<Collider3DRef> 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<Collider3DRef>& CompoundCollider3D::GetGeoms() const

View File

@ -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);
}
}