diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..ee31794e8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# http://editorconfig.org/ + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{hpp,inl,cpp,lua}] +indent_style = tab + +[*.html] +indent_size = 4 +indent_style = space diff --git a/Doxyfile b/Doxyfile index 47af03df4..04a327a38 100644 --- a/Doxyfile +++ b/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Nazara Engine" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.1 +PROJECT_NUMBER = 0.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/SDK/include/NDK/BaseSystem.hpp b/SDK/include/NDK/BaseSystem.hpp index a4ff0bf41..7433f7d04 100644 --- a/SDK/include/NDK/BaseSystem.hpp +++ b/SDK/include/NDK/BaseSystem.hpp @@ -35,6 +35,7 @@ namespace Ndk inline const std::vector& GetEntities() const; inline SystemIndex GetIndex() const; + inline int GetUpdateOrder() const; inline float GetUpdateRate() const; inline World& GetWorld() const; @@ -42,6 +43,7 @@ namespace Ndk inline bool HasEntity(const Entity* entity) const; + void SetUpdateOrder(int updateOrder); inline void SetUpdateRate(float updatePerSecond); inline void Update(float elapsedTime); @@ -93,6 +95,7 @@ namespace Ndk bool m_updateEnabled; float m_updateCounter; float m_updateRate; + int m_updateOrder; static SystemIndex s_nextIndex; }; diff --git a/SDK/include/NDK/BaseSystem.inl b/SDK/include/NDK/BaseSystem.inl index 31a0c314e..79971e3d6 100644 --- a/SDK/include/NDK/BaseSystem.inl +++ b/SDK/include/NDK/BaseSystem.inl @@ -16,7 +16,9 @@ namespace Ndk inline BaseSystem::BaseSystem(SystemIndex systemId) : m_systemIndex(systemId), - m_updateEnabled(true) + m_world(nullptr), + m_updateEnabled(true), + m_updateOrder(0) { SetUpdateRate(30); } @@ -33,7 +35,8 @@ namespace Ndk m_systemIndex(system.m_systemIndex), m_updateEnabled(system.m_updateEnabled), m_updateCounter(0.f), - m_updateRate(system.m_updateRate) + m_updateRate(system.m_updateRate), + m_updateOrder(system.m_updateOrder) { } @@ -69,7 +72,18 @@ namespace Ndk } /*! - * \brief Gets the rate of update for the system + * \brief Gets the update order of the system + * \return Update order + * + * \see SetUpdateOrder + */ + inline int BaseSystem::GetUpdateOrder() const + { + return m_updateOrder; + } + + /*! + * \brief Gets the rate of update of the system * \return Update rate */ diff --git a/SDK/include/NDK/Components.hpp b/SDK/include/NDK/Components.hpp index 3338e5f52..3a2916009 100644 --- a/SDK/include/NDK/Components.hpp +++ b/SDK/include/NDK/Components.hpp @@ -6,6 +6,7 @@ #define NDK_COMPONENTS_GLOBAL_HPP #include +#include #include #include #include @@ -13,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/SDK/include/NDK/Components/CameraComponent.hpp b/SDK/include/NDK/Components/CameraComponent.hpp index a5ad89b70..5a9efe742 100644 --- a/SDK/include/NDK/Components/CameraComponent.hpp +++ b/SDK/include/NDK/Components/CameraComponent.hpp @@ -18,9 +18,12 @@ namespace Ndk { + class CameraComponent; class Entity; - class NDK_API CameraComponent : public Component, public Nz::AbstractViewer + using CameraComponentHandle = Nz::ObjectHandle; + + class NDK_API CameraComponent : public Component, public Nz::AbstractViewer, public Nz::HandledObject { public: inline CameraComponent(); @@ -51,7 +54,7 @@ namespace Ndk float GetZNear() const override; inline void SetFOV(float fov); - inline void SetLayer(unsigned int layer); + void SetLayer(unsigned int layer); inline void SetProjectionType(Nz::ProjectionType projection); inline void SetSize(const Nz::Vector2f& size); inline void SetSize(float width, float height); diff --git a/SDK/include/NDK/Components/CameraComponent.inl b/SDK/include/NDK/Components/CameraComponent.inl index ed94b19e2..9aadfd509 100644 --- a/SDK/include/NDK/Components/CameraComponent.inl +++ b/SDK/include/NDK/Components/CameraComponent.inl @@ -101,7 +101,7 @@ namespace Ndk * \brief Gets the field of view of the camera * \return Field of view of the camera */ - float CameraComponent::GetFOV() const + inline float CameraComponent::GetFOV() const { return m_fov; } diff --git a/SDK/include/NDK/Components/CollisionComponent2D.hpp b/SDK/include/NDK/Components/CollisionComponent2D.hpp new file mode 100644 index 000000000..b282a850e --- /dev/null +++ b/SDK/include/NDK/Components/CollisionComponent2D.hpp @@ -0,0 +1,58 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_COMPONENTS_COLLISIONCOMPONENT2D_HPP +#define NDK_COMPONENTS_COLLISIONCOMPONENT2D_HPP + +#include +#include +#include + +namespace Nz +{ + class RigidBody2D; +} + +namespace Ndk +{ + class Entity; + + class NDK_API CollisionComponent2D : public Component + { + friend class PhysicsSystem2D; + + public: + CollisionComponent2D(Nz::Collider2DRef geom = Nz::Collider2DRef()); + CollisionComponent2D(const CollisionComponent2D& collision); + ~CollisionComponent2D() = default; + + const Nz::Collider2DRef& GetGeom() const; + + void SetGeom(Nz::Collider2DRef geom); + + CollisionComponent2D& operator=(Nz::Collider2DRef geom); + CollisionComponent2D& operator=(CollisionComponent2D&& collision) = default; + + static ComponentIndex componentIndex; + + private: + void InitializeStaticBody(); + Nz::RigidBody2D* GetStaticBody(); + + void OnAttached() override; + void OnComponentAttached(BaseComponent& component) override; + void OnComponentDetached(BaseComponent& component) override; + void OnDetached() override; + + std::unique_ptr m_staticBody; + Nz::Collider2DRef m_geom; + bool m_bodyUpdated; + }; +} + +#include + +#endif // NDK_COMPONENTS_COLLISIONCOMPONENT2D_HPP diff --git a/SDK/include/NDK/Components/CollisionComponent2D.inl b/SDK/include/NDK/Components/CollisionComponent2D.inl new file mode 100644 index 000000000..62bf422cb --- /dev/null +++ b/SDK/include/NDK/Components/CollisionComponent2D.inl @@ -0,0 +1,70 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include + +namespace Ndk +{ + /*! + * \brief Constructs a CollisionComponent2D object with a geometry + * + * \param geom Reference to a geometry symbolizing the entity + */ + + inline CollisionComponent2D::CollisionComponent2D(Nz::Collider2DRef geom) : + m_geom(std::move(geom)), + m_bodyUpdated(false) + { + } + + /*! + * \brief Constructs a CollisionComponent2D object by copy semantic + * + * \param collision CollisionComponent2D to copy + */ + + inline CollisionComponent2D::CollisionComponent2D(const CollisionComponent2D& collision) : + m_geom(collision.m_geom), + m_bodyUpdated(false) + { + } + + /*! + * \brief Gets the geometry representing the entity + * \return A constant reference to the physics geometry + */ + + inline const Nz::Collider2DRef& CollisionComponent2D::GetGeom() const + { + return m_geom; + } + + /*! + * \brief Assigns the geometry to this component + * \return A reference to this + * + * \param geom Reference to a geometry symbolizing the entity + */ + + inline CollisionComponent2D& CollisionComponent2D::operator=(Nz::Collider2DRef geom) + { + SetGeom(geom); + + return *this; + } + + /*! + * \brief Gets the static body used by the entity + * \return A pointer to the entity + */ + + inline Nz::RigidBody2D* CollisionComponent2D::GetStaticBody() + { + return m_staticBody.get(); + } +} diff --git a/SDK/include/NDK/Components/CollisionComponent3D.hpp b/SDK/include/NDK/Components/CollisionComponent3D.hpp index f6a07ede6..9a9671660 100644 --- a/SDK/include/NDK/Components/CollisionComponent3D.hpp +++ b/SDK/include/NDK/Components/CollisionComponent3D.hpp @@ -4,8 +4,8 @@ #pragma once -#ifndef NDK_COMPONENTS_COLLISIONCOMPONENT_HPP -#define NDK_COMPONENTS_COLLISIONCOMPONENT_HPP +#ifndef NDK_COMPONENTS_COLLISIONCOMPONENT3D_HPP +#define NDK_COMPONENTS_COLLISIONCOMPONENT3D_HPP #include #include @@ -23,7 +23,6 @@ namespace Ndk class NDK_API CollisionComponent3D : public Component { friend class PhysicsSystem3D; - friend class StaticCollisionSystem; public: CollisionComponent3D(Nz::Collider3DRef geom = Nz::Collider3DRef()); @@ -56,4 +55,4 @@ namespace Ndk #include -#endif // NDK_COMPONENTS_COLLISIONCOMPONENT_HPP +#endif // NDK_COMPONENTS_COLLISIONCOMPONENT3D_HPP diff --git a/SDK/include/NDK/Components/PhysicsComponent2D.hpp b/SDK/include/NDK/Components/PhysicsComponent2D.hpp new file mode 100644 index 000000000..90dd7a5e6 --- /dev/null +++ b/SDK/include/NDK/Components/PhysicsComponent2D.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_COMPONENTS_PHYSICSCOMPONENT2D_HPP +#define NDK_COMPONENTS_PHYSICSCOMPONENT2D_HPP + +#include +#include +#include + +namespace Ndk +{ + class Entity; + + class NDK_API PhysicsComponent2D : public Component + { + friend class CollisionComponent2D; + friend class PhysicsSystem2D; + + public: + PhysicsComponent2D() = default; + PhysicsComponent2D(const PhysicsComponent2D& physics); + ~PhysicsComponent2D() = default; + + void AddForce(const Nz::Vector2f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global); + void AddForce(const Nz::Vector2f& force, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global); + void AddTorque(float torque); + + Nz::Rectf GetAABB() const; + float GetAngularVelocity() const; + Nz::Vector2f GetCenterOfGravity(Nz::CoordSys coordSys = Nz::CoordSys_Local) const; + float GetMass() const; + Nz::Vector2f GetPosition() const; + float GetRotation() const; + Nz::Vector2f GetVelocity() const; + + bool IsSleeping() const; + + void SetAngularVelocity(float angularVelocity); + void SetMass(float mass); + void SetMassCenter(const Nz::Vector2f& center); + void SetPosition(const Nz::Vector2f& position); + void SetRotation(float rotation); + void SetVelocity(const Nz::Vector2f& velocity); + + static ComponentIndex componentIndex; + + private: + Nz::RigidBody2D& GetRigidBody(); + + void OnAttached() override; + void OnComponentAttached(BaseComponent& component) override; + void OnComponentDetached(BaseComponent& component) override; + void OnDetached() override; + + std::unique_ptr m_object; + }; +} + +#include + +#endif // NDK_COMPONENTS_PHYSICSCOMPONENT2D_HPP diff --git a/SDK/include/NDK/Components/PhysicsComponent2D.inl b/SDK/include/NDK/Components/PhysicsComponent2D.inl new file mode 100644 index 000000000..312e23e3a --- /dev/null +++ b/SDK/include/NDK/Components/PhysicsComponent2D.inl @@ -0,0 +1,284 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include "PhysicsComponent2D.hpp" + +namespace Ndk +{ + /*! + * \brief Constructs a PhysicsComponent2D object by copy semantic + * + * \param physics PhysicsComponent2D to copy + */ + + inline PhysicsComponent2D::PhysicsComponent2D(const PhysicsComponent2D& physics) + { + // No copy of physical object (because we only create it when attached to an entity) + NazaraUnused(physics); + } + + /*! + * \brief Applies a physics force to the entity + * + * \param force Force to apply on the entity + * \param coordSys System coordinates to consider + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::AddForce(const Nz::Vector2f& force, Nz::CoordSys coordSys) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->AddForce(force, coordSys); + } + + /*! + * \brief Applies a physics force to the entity + * + * \param force Force to apply on the entity + * \param point Point where to apply the force + * \param coordSys System coordinates to consider + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::AddForce(const Nz::Vector2f& force, const Nz::Vector2f& point, Nz::CoordSys coordSys) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->AddForce(force, point, coordSys); + } + + /*! + * \brief Applies a torque to the entity + * + * \param torque Torque to apply on the entity + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::AddTorque(float torque) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->AddTorque(torque); + } + + /*! + * \brief Gets the AABB of the physics object + * \return AABB of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + inline Nz::Rectf PhysicsComponent2D::GetAABB() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetAABB(); + } + + /*! + * \brief Gets the angular velocity of the physics object + * \return Angular velocity of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline float PhysicsComponent2D::GetAngularVelocity() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetAngularVelocity(); + } + + /*! + * \brief Gets the gravity center of the physics object + * \return Gravity center of the object + * + * \param coordSys System coordinates to consider + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline Nz::Vector2f PhysicsComponent2D::GetCenterOfGravity(Nz::CoordSys coordSys) const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetCenterOfGravity(coordSys); + } + + /*! + * \brief Gets the mass of the physics object + * \return Mass of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline float PhysicsComponent2D::GetMass() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetMass(); + } + + /*! + * \brief Gets the position of the physics object + * \return Position of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline Nz::Vector2f PhysicsComponent2D::GetPosition() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetPosition(); + } + + /*! + * \brief Gets the rotation of the physics object + * \return Rotation of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline float PhysicsComponent2D::GetRotation() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetRotation(); + } + + /*! + * \brief Gets the velocity of the physics object + * \return Velocity of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline Nz::Vector2f PhysicsComponent2D::GetVelocity() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetVelocity(); + } + + /*! + * \brief Checks whether the entity is currently sleeping + * \return true If it is the case + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline bool PhysicsComponent2D::IsSleeping() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->IsSleeping(); + } + + /*! + * \brief Sets the angular velocity of the physics object + * + * \param angularVelocity Angular velocity of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetAngularVelocity(float angularVelocity) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetAngularVelocity(angularVelocity); + } + + /*! + * \brief Sets the mass of the physics object + * + * \param mass Mass of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + * \remark Produces a NazaraAssert if the mass is negative + */ + + inline void PhysicsComponent2D::SetMass(float mass) + { + NazaraAssert(m_object, "Invalid physics object"); + NazaraAssert(mass > 0.f, "Mass should be positive"); + + m_object->SetMass(mass); + } + + /*! + * \brief Sets the gravity center of the physics object + * + * \param center Gravity center of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetMassCenter(const Nz::Vector2f& center) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetMassCenter(center); + } + + /*! + * \brief Sets the position of the physics object + * + * \param position Position of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetPosition(const Nz::Vector2f& position) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetPosition(position); + } + + /*! + * \brief Sets the rotation of the physics object + * + * \param rotation Rotation of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetRotation(float rotation) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetRotation(rotation); + } + + /*! + * \brief Sets the velocity of the physics object + * + * \param velocity Velocity of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetVelocity(const Nz::Vector2f& velocity) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetVelocity(velocity); + } + + /*! + * \brief Gets the underlying physics object + * \return A reference to the physics object + */ + + inline Nz::RigidBody2D& PhysicsComponent2D::GetRigidBody() + { + return *m_object.get(); + } +} diff --git a/SDK/include/NDK/Components/PhysicsComponent3D.hpp b/SDK/include/NDK/Components/PhysicsComponent3D.hpp index fc1367d84..9fb1bb45e 100644 --- a/SDK/include/NDK/Components/PhysicsComponent3D.hpp +++ b/SDK/include/NDK/Components/PhysicsComponent3D.hpp @@ -56,7 +56,7 @@ namespace Ndk static ComponentIndex componentIndex; private: - Nz::RigidBody3D& GetPhysObject(); + Nz::RigidBody3D& GetRigidBody(); void OnAttached() override; void OnComponentAttached(BaseComponent& component) override; diff --git a/SDK/include/NDK/Components/PhysicsComponent3D.inl b/SDK/include/NDK/Components/PhysicsComponent3D.inl index 84bc36db7..cad098af8 100644 --- a/SDK/include/NDK/Components/PhysicsComponent3D.inl +++ b/SDK/include/NDK/Components/PhysicsComponent3D.inl @@ -350,7 +350,7 @@ namespace Ndk * \return A reference to the physics object */ - inline Nz::RigidBody3D& PhysicsComponent3D::GetPhysObject() + inline Nz::RigidBody3D& PhysicsComponent3D::GetRigidBody() { return *m_object.get(); } diff --git a/SDK/include/NDK/LuaAPI.inl b/SDK/include/NDK/LuaAPI.inl index e50699528..f2ddf251c 100644 --- a/SDK/include/NDK/LuaAPI.inl +++ b/SDK/include/NDK/LuaAPI.inl @@ -28,15 +28,6 @@ namespace Nz { - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param color Resulting color - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Color* color, TypeTag) { instance.CheckType(index, Nz::LuaType_Table); @@ -49,15 +40,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param angles Resulting euler angles - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, EulerAnglesd* angles, TypeTag) { switch (instance.GetType(index)) @@ -78,15 +60,6 @@ namespace Nz } } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param angles Resulting euler angles - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, EulerAnglesf* angles, TypeTag) { EulerAnglesd anglesDouble; @@ -96,15 +69,6 @@ namespace Nz return ret; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param fontRef Resulting reference to a font - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, FontRef* fontRef, TypeTag) { *fontRef = *static_cast(instance.CheckUserdata(index, "Font")); @@ -112,15 +76,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param params Resulting parameters for a font - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, FontParams* params, TypeTag) { NazaraUnused(params); @@ -132,14 +87,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param params Resulting parameters for an image - */ inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, ImageParams* params, TypeTag) { instance.CheckType(index, Nz::LuaType_Table); @@ -150,15 +97,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param address Resulting IP address - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, IpAddress* address, TypeTag) { switch (instance.GetType(index)) @@ -173,15 +111,6 @@ namespace Nz } } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param quat Resulting quaternion - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Matrix4d* mat, TypeTag) { switch (instance.GetType(index)) @@ -212,15 +141,6 @@ namespace Nz } } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param quat Resulting quaternion - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Matrix4f* mat, TypeTag) { Matrix4d matDouble = Matrix4d::Identity(); @@ -230,15 +150,6 @@ namespace Nz return ret; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param params Resulting parameters for a mesh - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, MeshParams* params, TypeTag) { instance.CheckType(index, Nz::LuaType_Table); @@ -252,15 +163,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param quat Resulting quaternion - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Quaterniond* quat, TypeTag) { switch (instance.GetType(index)) @@ -281,15 +183,6 @@ namespace Nz } } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param quat Resulting quaternion - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Quaternionf* quat, TypeTag) { Quaterniond quatDouble; @@ -299,15 +192,6 @@ namespace Nz return ret; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param rect Resulting rectangle - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Rectd* rect, TypeTag) { instance.CheckType(index, LuaType_Table); @@ -320,15 +204,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param rect Resulting rectangle - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Rectf* rect, TypeTag) { Rectd rectDouble; @@ -338,14 +213,14 @@ namespace Nz return ret; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param rect Resulting rectangle - */ + inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Recti* rect, TypeTag) + { + Rectd rectDouble; + unsigned int ret = LuaImplQueryArg(instance, index, &rectDouble, TypeTag()); + + rect->Set(rectDouble); + return ret; + } inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Rectui* rect, TypeTag) { @@ -356,15 +231,6 @@ namespace Nz return ret; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param vec Resulting vector2D - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Vector2d* vec, TypeTag) { switch (instance.GetType(index)) @@ -386,15 +252,6 @@ namespace Nz } } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param vec Resulting vector2D - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Vector2f* vec, TypeTag) { Vector2d vecDouble; @@ -404,15 +261,6 @@ namespace Nz return ret; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param vec Resulting vector2D - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Vector2ui* vec, TypeTag) { Vector2d vecDouble; @@ -422,15 +270,6 @@ namespace Nz return ret; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param vec Resulting vector3D - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Vector3d* vec, TypeTag) { switch (instance.GetType(index)) @@ -452,15 +291,6 @@ namespace Nz } } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param vec Resulting vector3D - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Vector3f* vec, TypeTag) { Vector3d vecDouble; @@ -470,15 +300,6 @@ namespace Nz return ret; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param vec Resulting vector3D - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Vector3ui* vec, TypeTag) { Vector3d vecDouble; @@ -488,15 +309,6 @@ namespace Nz return ret; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param handle Resulting entity - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Ndk::EntityHandle* handle, TypeTag) { *handle = *static_cast(instance.CheckUserdata(index, "Entity")); @@ -504,15 +316,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param handle Resulting world - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Ndk::WorldHandle* handle, TypeTag) { *handle = *static_cast(instance.CheckUserdata(index, "World")); @@ -521,16 +324,6 @@ namespace Nz } #ifndef NDK_SERVER - - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param renderable Resulting reference to a instanced renderable - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, InstancedRenderableRef* renderable, TypeTag) { if (instance.IsOfType(index, "InstancedRenderable") || @@ -545,15 +338,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param renderable Resulting reference to a material - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, MaterialRef* materialRef, TypeTag) { *materialRef = *static_cast(instance.CheckUserdata(index, "Material")); @@ -561,15 +345,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param params Resulting parameters for a material - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, MaterialParams* params, TypeTag) { instance.CheckType(index, Nz::LuaType_Table); @@ -585,15 +360,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param params Resulting parameters for a model - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, ModelParameters* params, TypeTag) { instance.CheckType(index, Nz::LuaType_Table); @@ -606,15 +372,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param params Resulting parameters for a music - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, MusicParams* params, TypeTag) { instance.CheckType(index, Nz::LuaType_Table); @@ -624,15 +381,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param params Resulting parameters for a sound buffer - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, SoundBufferParams* params, TypeTag) { instance.CheckType(index, Nz::LuaType_Table); @@ -642,15 +390,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param renderable Resulting reference to a sprite - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, SpriteRef* spriteRef, TypeTag) { *spriteRef = *static_cast(instance.CheckUserdata(index, "Sprite")); @@ -658,15 +397,6 @@ namespace Nz return 1; } - /*! - * \brief Queries arguments for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param index Index type - * \param fontRef Resulting reference to a font - */ - inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, TextureRef* textureRef, TypeTag) { *textureRef = *static_cast(instance.CheckUserdata(index, "Texture")); @@ -676,14 +406,6 @@ namespace Nz #endif - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting color - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Color&& val, TypeTag) { instance.PushTable(); @@ -695,56 +417,24 @@ namespace Nz return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting euler angles - */ - inline int LuaImplReplyVal(const LuaInstance& instance, EulerAnglesd&& val, TypeTag) { instance.PushInstance("EulerAngles", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting euler angles - */ - inline int LuaImplReplyVal(const LuaInstance& instance, EulerAnglesf&& val, TypeTag) { instance.PushInstance("EulerAngles", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting reference to a font - */ - inline int LuaImplReplyVal(const LuaInstance& instance, FontRef&& val, TypeTag) { instance.PushInstance("Font", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting size information for a font - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Font::SizeInfo&& val, TypeTag) { instance.PushTable(); @@ -756,14 +446,6 @@ namespace Nz return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting ImageParams - */ - inline int LuaImplReplyVal(const LuaInstance& instance, ImageParams&& val, TypeTag) { instance.PushTable(0, 2); @@ -773,111 +455,53 @@ namespace Nz return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting IP address - */ - inline int LuaImplReplyVal(const LuaInstance& instance, IpAddress&& val, TypeTag) { instance.PushInstance("IpAddress", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting rectangle - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Matrix4d&& val, TypeTag) { instance.PushInstance("Matrix4", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting rectangle - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Matrix4f&& val, TypeTag) { instance.PushInstance("Matrix4", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting quaternion - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Quaterniond&& val, TypeTag) { instance.PushInstance("Quaternion", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting quaternion - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Quaternionf&& val, TypeTag) { instance.PushInstance("Quaternion", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting rectangle - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Rectd&& val, TypeTag) { instance.PushInstance("Rect", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting rectangle - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Rectf&& val, TypeTag) { instance.PushInstance("Rect", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting rectangle - */ + inline int LuaImplReplyVal(const LuaInstance& instance, Recti&& val, TypeTag) + { + instance.PushInstance("Rect", val); + return 1; + } inline int LuaImplReplyVal(const LuaInstance& instance, Rectui&& val, TypeTag) { @@ -885,182 +509,78 @@ namespace Nz return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting vector2D - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Vector2d&& val, TypeTag) { instance.PushInstance("Vector2", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting vector2D - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Vector2f&& val, TypeTag) { instance.PushInstance("Vector2", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting vector2D - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Vector2ui&& val, TypeTag) { instance.PushInstance("Vector2", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting vector3D - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Vector3d&& val, TypeTag) { instance.PushInstance("Vector3", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting vector3D - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Vector3f&& val, TypeTag) { instance.PushInstance("Vector3", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting vector3D - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Vector3ui&& val, TypeTag) { instance.PushInstance("Vector3", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param ptr Resulting entity - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::Entity* ptr, TypeTag) { instance.PushInstance("Entity", ptr); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param ptr Resulting application - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::Application* ptr, TypeTag) { instance.PushInstance("Application", ptr); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param handle Resulting entity - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::EntityHandle&& handle, TypeTag) { instance.PushInstance("Entity", handle); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param handle Resulting node component - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::NodeComponentHandle&& handle, TypeTag) { instance.PushInstance("NodeComponent", handle); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param handle Resulting velocity component - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::VelocityComponentHandle&& handle, TypeTag) { instance.PushInstance("VelocityComponent", handle); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param ptr Resulting world - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::World* ptr, TypeTag) { instance.PushInstance("World", ptr); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param ptr Resulting world - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::WorldHandle&& handle, TypeTag) { instance.PushInstance("World", handle); @@ -1068,70 +588,35 @@ namespace Nz } #ifndef NDK_SERVER - - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param handle Resulting material - */ - inline int LuaImplReplyVal(const LuaInstance& instance, MaterialRef&& handle, TypeTag) { instance.PushInstance("Material", handle); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param val Resulting sound buffer - */ - inline int LuaImplReplyVal(const LuaInstance& instance, const SoundBuffer* val, TypeTag) { instance.PushInstance("SoundBuffer", val); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param handle Resulting sprite - */ - inline int LuaImplReplyVal(const LuaInstance& instance, SpriteRef&& handle, TypeTag) { instance.PushInstance("Sprite", handle); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param handle Resulting texture - */ - inline int LuaImplReplyVal(const LuaInstance& instance, TextureRef&& handle, TypeTag) { instance.PushInstance("Texture", handle); return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param handle Resulting console - */ + inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::CameraComponentHandle&& handle, TypeTag) + { + instance.PushInstance("CameraComponent", handle); + return 1; + } inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::ConsoleHandle&& handle, TypeTag) { @@ -1139,14 +624,6 @@ namespace Nz return 1; } - /*! - * \brief Replies by value for Lua - * \return 1 in case of success - * - * \param instance Lua instance to interact with - * \param handle Resulting graphics component - */ - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::GraphicsComponentHandle&& handle, TypeTag) { instance.PushInstance("GraphicsComponent", handle); diff --git a/SDK/include/NDK/LuaBinding.hpp b/SDK/include/NDK/LuaBinding.hpp index 0eb083162..559d6ac1f 100644 --- a/SDK/include/NDK/LuaBinding.hpp +++ b/SDK/include/NDK/LuaBinding.hpp @@ -58,6 +58,7 @@ namespace Ndk // Utility Nz::LuaClass abstractImage; Nz::LuaClass font; + Nz::LuaClass keyboard; Nz::LuaClass node; // SDK @@ -75,6 +76,7 @@ namespace Ndk Nz::LuaClass soundEmitter; // Graphics + Nz::LuaClass abstractViewer; Nz::LuaClass instancedRenderable; Nz::LuaClass material; Nz::LuaClass model; @@ -87,6 +89,7 @@ namespace Ndk Nz::LuaClass texture; // SDK + Nz::LuaClass cameraComponent; Nz::LuaClass console; Nz::LuaClass graphicsComponent; #endif diff --git a/SDK/include/NDK/Prerequesites.hpp b/SDK/include/NDK/Prerequesites.hpp index 78b894ccc..f1ff2757a 100644 --- a/SDK/include/NDK/Prerequesites.hpp +++ b/SDK/include/NDK/Prerequesites.hpp @@ -25,6 +25,11 @@ #ifndef NDK_PREREQUESITES_HPP #define NDK_PREREQUESITES_HPP +/*! +* \defgroup NDK (NazaraSDK) Nazara Development Kit +* A library grouping every modules of Nazara into multiple higher-level features suchs as scene management (handled by an ECS), application, lua binding, etc. +*/ + #include // Importation/Exportation of the API diff --git a/SDK/include/NDK/Systems.hpp b/SDK/include/NDK/Systems.hpp index 45a79bc6c..a0ee23e77 100644 --- a/SDK/include/NDK/Systems.hpp +++ b/SDK/include/NDK/Systems.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include diff --git a/SDK/include/NDK/Systems/PhysicsSystem2D.hpp b/SDK/include/NDK/Systems/PhysicsSystem2D.hpp new file mode 100644 index 000000000..31426450a --- /dev/null +++ b/SDK/include/NDK/Systems/PhysicsSystem2D.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_SYSTEMS_PHYSICSSYSTEM2D_HPP +#define NDK_SYSTEMS_PHYSICSSYSTEM2D_HPP + +#include +#include +#include +#include + +namespace Ndk +{ + class NDK_API PhysicsSystem2D : public System + { + public: + PhysicsSystem2D(); + PhysicsSystem2D(const PhysicsSystem2D& system); + ~PhysicsSystem2D() = default; + + Nz::PhysWorld2D& GetWorld(); + const Nz::PhysWorld2D& GetWorld() const; + + static SystemIndex systemIndex; + + private: + void CreatePhysWorld() const; + void OnEntityValidation(Entity* entity, bool justAdded) override; + void OnUpdate(float elapsedTime) override; + + EntityList m_dynamicObjects; + EntityList m_staticObjects; + mutable std::unique_ptr m_world; ///TODO: std::optional (Should I make a Nz::Optional class?) + }; +} + +#include + +#endif // NDK_SYSTEMS_PHYSICSSYSTEM2D_HPP diff --git a/SDK/include/NDK/Systems/PhysicsSystem2D.inl b/SDK/include/NDK/Systems/PhysicsSystem2D.inl new file mode 100644 index 000000000..21a34a6d4 --- /dev/null +++ b/SDK/include/NDK/Systems/PhysicsSystem2D.inl @@ -0,0 +1,32 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +namespace Ndk +{ + /*! + * \brief Gets the physical world + * \return A reference to the physical world + */ + + inline Nz::PhysWorld2D& PhysicsSystem2D::GetWorld() + { + if (!m_world) + CreatePhysWorld(); + + return *m_world; + } + + /*! + * \brief Gets the physical world + * \return A constant reference to the physical world + */ + + inline const Nz::PhysWorld2D& PhysicsSystem2D::GetWorld() const + { + if (!m_world) + CreatePhysWorld(); + + return *m_world; + } +} diff --git a/SDK/include/NDK/World.hpp b/SDK/include/NDK/World.hpp index 5d1dabb77..5e819e517 100644 --- a/SDK/include/NDK/World.hpp +++ b/SDK/include/NDK/World.hpp @@ -24,6 +24,7 @@ namespace Ndk class NDK_API World : public Nz::HandledObject { + friend BaseSystem; friend Entity; public: @@ -72,6 +73,8 @@ namespace Ndk private: inline void Invalidate(); inline void Invalidate(EntityId id); + inline void InvalidateSystemOrder(); + void ReorderSystems(); struct EntityBlock { @@ -83,15 +86,17 @@ namespace Ndk EntityBlock(EntityBlock&& block) = default; Entity entity; - unsigned int aliveIndex; + std::size_t aliveIndex; }; std::vector> m_systems; + std::vector m_orderedSystems; std::vector m_entities; std::vector m_freeIdList; EntityList m_aliveEntities; Nz::Bitset m_dirtyEntities; Nz::Bitset m_killedEntities; + bool m_orderedSystemsUpdated; }; } diff --git a/SDK/include/NDK/World.inl b/SDK/include/NDK/World.inl index 9960aef05..212038625 100644 --- a/SDK/include/NDK/World.inl +++ b/SDK/include/NDK/World.inl @@ -53,6 +53,7 @@ namespace Ndk m_systems[index]->SetWorld(this); Invalidate(); // We force an update for every entities + InvalidateSystemOrder(); // And regenerate the system update list return *m_systems[index].get(); } @@ -206,6 +207,8 @@ namespace Ndk inline void World::RemoveAllSystems() { m_systems.clear(); + + InvalidateSystemOrder(); } /*! @@ -219,7 +222,11 @@ namespace Ndk inline void World::RemoveSystem(SystemIndex index) { if (HasSystem(index)) + { m_systems[index].reset(); + + InvalidateSystemOrder(); + } } /*! @@ -246,32 +253,8 @@ namespace Ndk Update(); //< Update entities // And then update systems - for (auto& systemPtr : m_systems) - { - if (systemPtr) - systemPtr->Update(elapsedTime); - } - } - - /*! - * \brief Invalidates each entity in the world - */ - - inline void World::Invalidate() - { - m_dirtyEntities.Resize(m_entities.size(), false); - m_dirtyEntities.Set(true); // Activation of all bits - } - - /*! - * \brief Invalidates an entity in the world - * - * \param id Identifier of the entity - */ - - inline void World::Invalidate(EntityId id) - { - m_dirtyEntities.UnboundedSet(id, true); + for (auto& systemPtr : m_orderedSystems) + systemPtr->Update(elapsedTime); } /*! @@ -281,10 +264,12 @@ namespace Ndk inline World& World::operator=(World&& world) noexcept { - m_aliveEntities = std::move(world.m_aliveEntities); - m_dirtyEntities = std::move(world.m_dirtyEntities); - m_freeIdList = std::move(world.m_freeIdList); - m_killedEntities = std::move(world.m_killedEntities); + m_aliveEntities = std::move(world.m_aliveEntities); + m_dirtyEntities = std::move(world.m_dirtyEntities); + m_freeIdList = std::move(world.m_freeIdList); + m_killedEntities = std::move(world.m_killedEntities); + m_orderedSystems = std::move(world.m_orderedSystems); + m_orderedSystemsUpdated = world.m_orderedSystemsUpdated; m_entities = std::move(world.m_entities); for (EntityBlock& block : m_entities) @@ -296,4 +281,20 @@ namespace Ndk return *this; } + + inline void World::Invalidate() + { + m_dirtyEntities.Resize(m_entities.size(), false); + m_dirtyEntities.Set(true); // Activation of all bits + } + + inline void World::Invalidate(EntityId id) + { + m_dirtyEntities.UnboundedSet(id, true); + } + + inline void World::InvalidateSystemOrder() + { + m_orderedSystemsUpdated = false; + } } diff --git a/SDK/src/NDK/BaseSystem.cpp b/SDK/src/NDK/BaseSystem.cpp index 8a2a9dce5..b6ebe9892 100644 --- a/SDK/src/NDK/BaseSystem.cpp +++ b/SDK/src/NDK/BaseSystem.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Prerequesites.hpp #include +#include namespace Ndk { @@ -56,6 +57,26 @@ namespace Ndk return true; } + /*! + * \brief Sets the update order of this system + * + * The system update order is used by the world it belongs to in order to know in which order they should be updated, as some application logic may rely a specific update order. + * A system with a greater update order (ex: 1) is guaranteed to be updated after a system with a lesser update order (ex: -1), otherwise the order is unspecified (and is not guaranteed to be stable). + * + * \param updateOrder The relative update order of the system + * + * \remark The update order is only used by World::Update(float) and does not have any effect regarding a call to BaseSystem::Update(float) + * + * \see GetUpdateOrder + */ + void BaseSystem::SetUpdateOrder(int updateOrder) + { + m_updateOrder = updateOrder; + + if (m_world) + m_world->InvalidateSystemOrder(); + } + /*! * \brief Operation to perform when entity is added to the system * diff --git a/SDK/src/NDK/Components/CollisionComponent2D.cpp b/SDK/src/NDK/Components/CollisionComponent2D.cpp new file mode 100644 index 000000000..912742b0e --- /dev/null +++ b/SDK/src/NDK/Components/CollisionComponent2D.cpp @@ -0,0 +1,118 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + /*! + * \ingroup NDK + * \class Ndk::CollisionComponent2D + * \brief NDK class that represents a two-dimensional collision geometry + */ + + /*! + * \brief Sets geometry for the entity + * + * \param geom Geometry used for collisions + * + * \remark Produces a NazaraAssert if the entity has no physics component and has no static body + */ + + void CollisionComponent2D::SetGeom(Nz::Collider2DRef geom) + { + m_geom = std::move(geom); + + if (m_entity->HasComponent()) + { + // We update the geometry of the PhysiscsObject linked to the PhysicsComponent2D + PhysicsComponent2D& physComponent = m_entity->GetComponent(); + physComponent.GetRigidBody().SetGeom(m_geom); + } + else + { + NazaraAssert(m_staticBody, "An entity without physics component should have a static body"); + m_staticBody->SetGeom(m_geom); + } + } + + /*! + * \brief Initializes the static body + * + * \remark Produces a NazaraAssert if entity is invalid + * \remark Produces a NazaraAssert if entity is not linked to a world, or the world has no physics system + */ + + void CollisionComponent2D::InitializeStaticBody() + { + NazaraAssert(m_entity, "Invalid entity"); + World* entityWorld = m_entity->GetWorld(); + + NazaraAssert(entityWorld, "Entity must have world"); + NazaraAssert(entityWorld->HasSystem(), "World must have a physics system"); + Nz::PhysWorld2D& physWorld = entityWorld->GetSystem().GetWorld(); + + m_staticBody.reset(new Nz::RigidBody2D(&physWorld, 0.f, m_geom)); + + Nz::Matrix4f matrix; + if (m_entity->HasComponent()) + matrix = m_entity->GetComponent().GetTransformMatrix(); + else + matrix.MakeIdentity(); + + m_staticBody->SetPosition(Nz::Vector2f(matrix.GetTranslation())); + + } + + /*! + * \brief Operation to perform when component is attached to an entity + */ + + void CollisionComponent2D::OnAttached() + { + if (!m_entity->HasComponent()) + InitializeStaticBody(); + } + + /*! + * \brief Operation to perform when component is attached to this component + * + * \param component Component being attached + */ + + void CollisionComponent2D::OnComponentAttached(BaseComponent& component) + { + if (IsComponent(component)) + m_staticBody.reset(); + } + + /*! + * \brief Operation to perform when component is detached from this component + * + * \param component Component being detached + */ + + void CollisionComponent2D::OnComponentDetached(BaseComponent& component) + { + if (IsComponent(component)) + InitializeStaticBody(); + } + + /*! + * \brief Operation to perform when component is detached from an entity + */ + + void CollisionComponent2D::OnDetached() + { + m_staticBody.reset(); + } + + ComponentIndex CollisionComponent2D::componentIndex; +} diff --git a/SDK/src/NDK/Components/CollisionComponent3D.cpp b/SDK/src/NDK/Components/CollisionComponent3D.cpp index 423b06cb4..d54c460be 100644 --- a/SDK/src/NDK/Components/CollisionComponent3D.cpp +++ b/SDK/src/NDK/Components/CollisionComponent3D.cpp @@ -33,7 +33,7 @@ namespace Ndk { // We update the geometry of the PhysiscsObject linked to the PhysicsComponent3D PhysicsComponent3D& physComponent = m_entity->GetComponent(); - physComponent.GetPhysObject().SetGeom(m_geom); + physComponent.GetRigidBody().SetGeom(m_geom); } else { diff --git a/SDK/src/NDK/Components/PhysicsComponent2D.cpp b/SDK/src/NDK/Components/PhysicsComponent2D.cpp new file mode 100644 index 000000000..db66178b9 --- /dev/null +++ b/SDK/src/NDK/Components/PhysicsComponent2D.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + /*! + * \ingroup NDK + * \class Ndk::PhysicsComponent2D + * \brief NDK class that represents a physics point, without any collision + */ + + /*! + * \brief Operation to perform when component is attached to an entity + * + * \remark Produces a NazaraAssert if the world does not have a physics system + */ + + void PhysicsComponent2D::OnAttached() + { + World* entityWorld = m_entity->GetWorld(); + NazaraAssert(entityWorld->HasSystem(), "World must have a 2D physics system"); + + Nz::PhysWorld2D& world = entityWorld->GetSystem().GetWorld(); + + Nz::Collider2DRef geom; + if (m_entity->HasComponent()) + geom = m_entity->GetComponent().GetGeom(); + + Nz::Matrix4f matrix; + if (m_entity->HasComponent()) + matrix = m_entity->GetComponent().GetTransformMatrix(); + else + matrix.MakeIdentity(); + + m_object.reset(new Nz::RigidBody2D(&world, 1.f, geom)); + m_object->SetPosition(Nz::Vector2f(matrix.GetTranslation())); + } + + /*! + * \brief Operation to perform when component is attached to this component + * + * \param component Component being attached + * + * \remark Produces a NazaraAssert if physical object is invalid + */ + + void PhysicsComponent2D::OnComponentAttached(BaseComponent& component) + { + if (IsComponent(component)) + { + NazaraAssert(m_object, "Invalid object"); + m_object->SetGeom(static_cast(component).GetGeom()); + } + } + + /*! + * \brief Operation to perform when component is detached from this component + * + * \param component Component being detached + * + * \remark Produces a NazaraAssert if physical object is invalid + */ + + void PhysicsComponent2D::OnComponentDetached(BaseComponent& component) + { + if (IsComponent(component)) + { + NazaraAssert(m_object, "Invalid object"); + m_object->SetGeom(Nz::NullCollider2D::New()); + } + } + + /*! + * \brief Operation to perform when component is detached from an entity + */ + + void PhysicsComponent2D::OnDetached() + { + m_object.reset(); + } + + ComponentIndex PhysicsComponent2D::componentIndex; +} diff --git a/SDK/src/NDK/Entity.cpp b/SDK/src/NDK/Entity.cpp index a49a8f6aa..4f60bb427 100644 --- a/SDK/src/NDK/Entity.cpp +++ b/SDK/src/NDK/Entity.cpp @@ -148,9 +148,11 @@ namespace Ndk // We alert each system for (std::size_t index = m_systemBits.FindFirst(); index != m_systemBits.npos; index = m_systemBits.FindNext(index)) { - if (m_world->HasSystem(index)) + auto sysIndex = static_cast(index); + + if (m_world->HasSystem(sysIndex)) { - BaseSystem& system = m_world->GetSystem(index); + BaseSystem& system = m_world->GetSystem(sysIndex); system.RemoveEntity(this); } } diff --git a/SDK/src/NDK/LuaBinding.cpp b/SDK/src/NDK/LuaBinding.cpp index 789427f26..9b990bdfd 100644 --- a/SDK/src/NDK/LuaBinding.cpp +++ b/SDK/src/NDK/LuaBinding.cpp @@ -36,6 +36,7 @@ namespace Ndk // Utility abstractImage("AbstractImage"), font("Font"), + keyboard("Keyboard"), node("Node"), // SDK @@ -55,6 +56,7 @@ namespace Ndk soundEmitter("SoundEmitter"), // Graphics + abstractViewer("AbstractViewer"), instancedRenderable("InstancedRenderable"), material("Material"), model("Model"), @@ -67,6 +69,7 @@ namespace Ndk texture("Texture"), // SDK + cameraComponent("CameraComponent"), console("Console"), graphicsComponent("GraphicsComponent") #endif diff --git a/SDK/src/NDK/LuaBinding_Core.cpp b/SDK/src/NDK/LuaBinding_Core.cpp index 4a1e343f4..3108e1a52 100644 --- a/SDK/src/NDK/LuaBinding_Core.cpp +++ b/SDK/src/NDK/LuaBinding_Core.cpp @@ -13,14 +13,37 @@ namespace Ndk void LuaBinding::BindCore() { /*********************************** Nz::Clock **********************************/ - clock.SetConstructor([](Nz::LuaInstance& lua, Nz::Clock* instance, std::size_t /*argumentCount*/) + clock.SetConstructor([](Nz::LuaInstance& lua, Nz::Clock* instance, std::size_t argumentCount) { - int argIndex = 2; - Nz::Int64 startingValue = lua.Check(&argIndex, 0); - bool paused = lua.Check(&argIndex, false); + std::size_t argCount = std::min(argumentCount, 2U); - Nz::PlacementNew(instance, startingValue, paused); - return true; + int argIndex = 2; + switch (argCount) + { + case 0: + Nz::PlacementNew(instance); + return true; + + case 1: + { + Nz::Int64 startingValue = lua.Check(&argIndex, 0); + + Nz::PlacementNew(instance, startingValue); + return true; + } + + case 2: + { + Nz::Int64 startingValue = lua.Check(&argIndex, 0); + bool paused = lua.Check(&argIndex, false); + + Nz::PlacementNew(instance, startingValue, paused); + return true; + } + } + + lua.Error("No matching overload for Clock constructor"); + return false; }); clock.BindMethod("GetMicroseconds", &Nz::Clock::GetMicroseconds); diff --git a/SDK/src/NDK/LuaBinding_Graphics.cpp b/SDK/src/NDK/LuaBinding_Graphics.cpp index d1cff2ef5..cdee66636 100644 --- a/SDK/src/NDK/LuaBinding_Graphics.cpp +++ b/SDK/src/NDK/LuaBinding_Graphics.cpp @@ -12,6 +12,18 @@ namespace Ndk void LuaBinding::BindGraphics() { + /*********************************** Nz::AbstractViewer ***********************************/ + abstractViewer.BindMethod("GetAspectRatio", &Nz::AbstractViewer::GetAspectRatio); + abstractViewer.BindMethod("GetEyePosition", &Nz::AbstractViewer::GetEyePosition); + abstractViewer.BindMethod("GetForward", &Nz::AbstractViewer::GetForward); + //abstractViewer.BindMethod("GetFrustum", &Nz::AbstractViewer::GetFrustum); + abstractViewer.BindMethod("GetProjectionMatrix", &Nz::AbstractViewer::GetProjectionMatrix); + //abstractViewer.BindMethod("GetTarget", &Nz::AbstractViewer::GetTarget); + abstractViewer.BindMethod("GetViewMatrix", &Nz::AbstractViewer::GetViewMatrix); + abstractViewer.BindMethod("GetViewport", &Nz::AbstractViewer::GetViewport); + abstractViewer.BindMethod("GetZFar", &Nz::AbstractViewer::GetZFar); + abstractViewer.BindMethod("GetZNear", &Nz::AbstractViewer::GetZNear); + /*********************************** Nz::InstancedRenderable ***********************************/ /*********************************** Nz::Material ***********************************/ @@ -122,7 +134,7 @@ namespace Ndk material.BindMethod("IsShadowCastingEnabled", &Nz::Material::IsShadowCastingEnabled); material.BindMethod("IsShadowReceiveEnabled", &Nz::Material::IsShadowReceiveEnabled); - material.BindMethod("LoadFromFile", &Nz::Material::LoadFromFile); + material.BindMethod("LoadFromFile", &Nz::Material::LoadFromFile, Nz::MaterialParams()); material.BindMethod("Reset", &Nz::Material::Reset); @@ -281,13 +293,37 @@ namespace Ndk sprite.BindMethod("SetColor", &Nz::Sprite::SetColor); sprite.BindMethod("SetCornerColor", &Nz::Sprite::SetCornerColor); sprite.BindMethod("SetDefaultMaterial", &Nz::Sprite::SetDefaultMaterial); - sprite.BindMethod("SetMaterial", &Nz::Sprite::SetMaterial, true); sprite.BindMethod("SetOrigin", &Nz::Sprite::SetOrigin); sprite.BindMethod("SetSize", (void(Nz::Sprite::*)(const Nz::Vector2f&)) &Nz::Sprite::SetSize); - sprite.BindMethod("SetTexture", &Nz::Sprite::SetTexture, true); sprite.BindMethod("SetTextureCoords", &Nz::Sprite::SetTextureCoords); sprite.BindMethod("SetTextureRect", &Nz::Sprite::SetTextureRect); + sprite.BindMethod("SetMaterial", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + bool resizeSprite = lua.CheckBoolean(argIndex + 1, true); + + if (lua.IsOfType(argIndex, "Material")) + instance->SetMaterial(*static_cast(lua.ToUserdata(argIndex)), resizeSprite); + else + instance->SetMaterial(lua.Check(&argIndex), resizeSprite); + + return 0; + }); + + sprite.BindMethod("SetTexture", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + bool resizeSprite = lua.CheckBoolean(argIndex + 1, true); + + if (lua.IsOfType(argIndex, "Texture")) + instance->SetTexture(*static_cast(lua.ToUserdata(argIndex)), resizeSprite); + else + instance->SetTexture(lua.Check(&argIndex), resizeSprite); + + return 0; + }); + /*********************************** Nz::SpriteLibrary ***********************************/ spriteLibrary.BindStaticMethod("Get", &Nz::SpriteLibrary::Get); @@ -323,6 +359,7 @@ namespace Ndk void LuaBinding::RegisterGraphics(Nz::LuaInstance& instance) { + abstractViewer.Register(instance); instancedRenderable.Register(instance); material.Register(instance); model.Register(instance); diff --git a/SDK/src/NDK/LuaBinding_Math.cpp b/SDK/src/NDK/LuaBinding_Math.cpp index 35ad13a2e..f777dce7f 100644 --- a/SDK/src/NDK/LuaBinding_Math.cpp +++ b/SDK/src/NDK/LuaBinding_Math.cpp @@ -37,6 +37,9 @@ namespace Ndk return false; }); + eulerAngles.BindMethod("Normalize", &Nz::EulerAnglesd::Normalize); + eulerAngles.BindMethod("ToQuaternion", &Nz::EulerAnglesd::ToQuaternion); + eulerAngles.BindMethod("__tostring", &Nz::EulerAnglesd::ToString); eulerAngles.SetGetter([] (Nz::LuaInstance& lua, Nz::EulerAnglesd& instance) @@ -174,7 +177,7 @@ namespace Ndk case 16: { double values[16]; - for (std::size_t i = 0; i < 16; ++i) + for (int i = 0; i < 16; ++i) values[i] = lua.CheckNumber(i); Nz::PlacementNew(matrix, values); @@ -377,7 +380,7 @@ namespace Ndk PlacementNew(instance, *static_cast(lua.ToUserdata(1))); else if (lua.IsOfType(1, Nz::LuaType_Table)) { - // TODO => Faire sans avoir à mettre de nom dans la table et prendre les éléments un à un pour créer le Rectd + // TODO => Faire sans avoir à mettre de nom dans la table et prendre les éléments un à un pour créer le Rectd PlacementNew(instance, lua.CheckField("x", 1), lua.CheckField("y", 1), lua.CheckField("width", 1), @@ -554,8 +557,58 @@ namespace Ndk return false; }); + quaternion.BindMethod("ComputeW", &Nz::Quaterniond::ComputeW); + quaternion.BindMethod("Conjugate", &Nz::Quaterniond::Conjugate); + quaternion.BindMethod("DotProduct", &Nz::Quaterniond::DotProduct); + quaternion.BindMethod("GetConjugate", &Nz::Quaterniond::GetConjugate); + quaternion.BindMethod("GetInverse", &Nz::Quaterniond::GetInverse); + + quaternion.BindMethod("Inverse", &Nz::Quaterniond::Inverse); + quaternion.BindMethod("Magnitude", &Nz::Quaterniond::Magnitude); + + quaternion.BindMethod("SquaredMagnitude", &Nz::Quaterniond::SquaredMagnitude); + quaternion.BindMethod("ToEulerAngles", &Nz::Quaterniond::ToEulerAngles); + quaternion.BindMethod("__tostring", &Nz::Quaterniond::ToString); + quaternion.BindStaticMethod("Lerp", &Nz::Quaterniond::Lerp); + quaternion.BindStaticMethod("RotationBetween", &Nz::Quaterniond::RotationBetween); + quaternion.BindStaticMethod("Slerp", &Nz::Quaterniond::Slerp); + + quaternion.BindMethod("GetNormal", [] (Nz::LuaInstance& lua, Nz::Quaterniond& instance, std::size_t /*argumentCount*/) -> int + { + double length; + + lua.Push(instance.GetNormal(&length)); + lua.Push(length); + + return 2; + }); + + quaternion.BindMethod("Normalize", [] (Nz::LuaInstance& lua, Nz::Quaterniond& instance, std::size_t /*argumentCount*/) -> int + { + double length; + + instance.Normalize(&length); + lua.Push(1); //< instance + lua.Push(length); + + return 2; + }); + + quaternion.BindStaticMethod("Normalize", [] (Nz::LuaInstance& instance) -> int + { + int argIndex = 1; + Nz::Quaterniond quat = instance.Check(&argIndex); + + double length; + + instance.Push(Nz::Quaterniond::Normalize(quat, &length)); + instance.Push(length); + + return 2; + }); + quaternion.SetGetter([] (Nz::LuaInstance& lua, Nz::Quaterniond& instance) { std::size_t length; @@ -904,5 +957,12 @@ namespace Ndk rect.Register(instance); vector2d.Register(instance); vector3d.Register(instance); + + quaternion.PushGlobalTable(instance); + { + instance.PushField("Identity", Nz::Quaterniond::Identity()); + instance.PushField("Zero", Nz::Quaterniond::Zero()); + } + instance.Pop(); } } diff --git a/SDK/src/NDK/LuaBinding_SDK.cpp b/SDK/src/NDK/LuaBinding_SDK.cpp index 880e49064..37c2d71e9 100644 --- a/SDK/src/NDK/LuaBinding_SDK.cpp +++ b/SDK/src/NDK/LuaBinding_SDK.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 Jérôme Leclercq, Arnaud Cadot +// Copyright (C) 2016 Jérôme Leclercq, Arnaud Cadot // This file is part of the "Nazara Development Kit" // For conditions of distribution and use, see copyright notice in Prerequesites.hpp @@ -138,6 +138,25 @@ namespace Ndk #ifndef NDK_SERVER + /*********************************** Ndk::CameraComponent **********************************/ + cameraComponent.Inherit(abstractViewer, [] (CameraComponentHandle* handle) -> Nz::AbstractViewer* + { + return handle->GetObject(); + }); + + cameraComponent.BindMethod("GetFOV", &Ndk::CameraComponent::GetFOV); + cameraComponent.BindMethod("GetLayer", &Ndk::CameraComponent::GetLayer); + + cameraComponent.BindMethod("SetFOV", &Ndk::CameraComponent::SetFOV); + cameraComponent.BindMethod("SetLayer", &Ndk::CameraComponent::SetLayer); + cameraComponent.BindMethod("SetProjectionType", &Ndk::CameraComponent::SetProjectionType); + cameraComponent.BindMethod("SetSize", (void(Ndk::CameraComponent::*)(const Nz::Vector2f&)) &Ndk::CameraComponent::SetSize); + //cameraComponent.BindMethod("SetTarget", &Ndk::CameraComponent::SetTarget); + cameraComponent.BindMethod("SetTargetRegion", &Ndk::CameraComponent::SetTargetRegion); + cameraComponent.BindMethod("SetViewport", &Ndk::CameraComponent::SetViewport); + cameraComponent.BindMethod("SetZFar", &Ndk::CameraComponent::SetZFar); + cameraComponent.BindMethod("SetZNear", &Ndk::CameraComponent::SetZNear); + /*********************************** Ndk::GraphicsComponent **********************************/ graphicsComponent.BindMethod("Attach", [] (Nz::LuaInstance& lua, Ndk::GraphicsComponent* instance, std::size_t argumentCount) -> int { @@ -205,6 +224,7 @@ namespace Ndk BindComponent("Velocity"); #ifndef NDK_SERVER + BindComponent("Camera"); BindComponent("Graphics"); #endif } @@ -225,6 +245,7 @@ namespace Ndk world.Register(instance); #ifndef NDK_SERVER + cameraComponent.Register(instance); console.Register(instance); graphicsComponent.Register(instance); #endif diff --git a/SDK/src/NDK/LuaBinding_Utility.cpp b/SDK/src/NDK/LuaBinding_Utility.cpp index e693ce35c..686182410 100644 --- a/SDK/src/NDK/LuaBinding_Utility.cpp +++ b/SDK/src/NDK/LuaBinding_Utility.cpp @@ -153,6 +153,10 @@ namespace Ndk font.BindStaticMethod("SetDefaultGlyphBorder", &Nz::Font::SetDefaultGlyphBorder); font.BindStaticMethod("SetDefaultMinimumStepSize", &Nz::Font::SetDefaultMinimumStepSize); + /*********************************** Nz::Keyboard **********************************/ + keyboard.BindStaticMethod("GetKeyName", &Nz::Keyboard::GetKeyName); + keyboard.BindStaticMethod("IsKeyPressed", &Nz::Keyboard::IsKeyPressed); + /*********************************** Nz::Node **********************************/ node.BindMethod("GetBackward", &Nz::Node::GetBackward); //nodeClass.SetMethod("GetChilds", &Nz::Node::GetChilds); @@ -322,6 +326,92 @@ namespace Ndk { abstractImage.Register(instance); font.Register(instance); + keyboard.Register(instance); node.Register(instance); + + keyboard.PushGlobalTable(instance); + { + instance.PushField("Undefined", Nz::Keyboard::Undefined); + + // A-Z + for (std::size_t i = 0; i < 26; ++i) + instance.PushField(Nz::String('A' + char(i)), Nz::Keyboard::A + i); + + // Numerical + for (std::size_t i = 0; i < 10; ++i) + { + instance.PushField("Num" + Nz::String::Number(i), Nz::Keyboard::Num0 + i); + instance.PushField("Numpad" + Nz::String::Number(i), Nz::Keyboard::Numpad0 + i); + } + + // F1-F15 + for (std::size_t i = 0; i < 15; ++i) + instance.PushField('F' + Nz::String::Number(i+1), Nz::Keyboard::F1 + i); + + // And all the others... + instance.PushField("Down", Nz::Keyboard::Down); + instance.PushField("Left", Nz::Keyboard::Left); + instance.PushField("Right", Nz::Keyboard::Right); + instance.PushField("Up", Nz::Keyboard::Up); + + instance.PushField("Add", Nz::Keyboard::Add); + instance.PushField("Decimal", Nz::Keyboard::Decimal); + instance.PushField("Divide", Nz::Keyboard::Divide); + instance.PushField("Multiply", Nz::Keyboard::Multiply); + instance.PushField("Subtract", Nz::Keyboard::Subtract); + + instance.PushField("Backslash", Nz::Keyboard::Backslash); + instance.PushField("Backspace", Nz::Keyboard::Backspace); + instance.PushField("Clear", Nz::Keyboard::Clear); + instance.PushField("Comma", Nz::Keyboard::Comma); + instance.PushField("Dash", Nz::Keyboard::Dash); + instance.PushField("Delete", Nz::Keyboard::Delete); + instance.PushField("End", Nz::Keyboard::End); + instance.PushField("Equal", Nz::Keyboard::Equal); + instance.PushField("Escape", Nz::Keyboard::Escape); + instance.PushField("Home", Nz::Keyboard::Home); + instance.PushField("Insert", Nz::Keyboard::Insert); + instance.PushField("LAlt", Nz::Keyboard::LAlt); + instance.PushField("LBracket", Nz::Keyboard::LBracket); + instance.PushField("LControl", Nz::Keyboard::LControl); + instance.PushField("LShift", Nz::Keyboard::LShift); + instance.PushField("LSystem", Nz::Keyboard::LSystem); + instance.PushField("PageDown", Nz::Keyboard::PageDown); + instance.PushField("PageUp", Nz::Keyboard::PageUp); + instance.PushField("Pause", Nz::Keyboard::Pause); + instance.PushField("Period", Nz::Keyboard::Period); + instance.PushField("Print", Nz::Keyboard::Print); + instance.PushField("PrintScreen", Nz::Keyboard::PrintScreen); + instance.PushField("Quote", Nz::Keyboard::Quote); + instance.PushField("RAlt", Nz::Keyboard::RAlt); + instance.PushField("RBracket", Nz::Keyboard::RBracket); + instance.PushField("RControl", Nz::Keyboard::RControl); + instance.PushField("Return", Nz::Keyboard::Return); + instance.PushField("RShift", Nz::Keyboard::RShift); + instance.PushField("RSystem", Nz::Keyboard::RSystem); + instance.PushField("Semicolon", Nz::Keyboard::Semicolon); + instance.PushField("Slash", Nz::Keyboard::Slash); + instance.PushField("Space", Nz::Keyboard::Space); + instance.PushField("Tab", Nz::Keyboard::Tab); + instance.PushField("Tilde", Nz::Keyboard::Tilde); + instance.PushField("Browser_Back", Nz::Keyboard::Browser_Back); + instance.PushField("Browser_Favorites", Nz::Keyboard::Browser_Favorites); + instance.PushField("Browser_Forward", Nz::Keyboard::Browser_Forward); + instance.PushField("Browser_Home", Nz::Keyboard::Browser_Home); + instance.PushField("Browser_Refresh", Nz::Keyboard::Browser_Refresh); + instance.PushField("Browser_Search", Nz::Keyboard::Browser_Search); + instance.PushField("Browser_Stop", Nz::Keyboard::Browser_Stop); + instance.PushField("Media_Next", Nz::Keyboard::Media_Next); + instance.PushField("Media_Play", Nz::Keyboard::Media_Play); + instance.PushField("Media_Previous", Nz::Keyboard::Media_Previous); + instance.PushField("Media_Stop", Nz::Keyboard::Media_Stop); + instance.PushField("Volume_Down", Nz::Keyboard::Volume_Down); + instance.PushField("Volume_Mute", Nz::Keyboard::Volume_Mute); + instance.PushField("Volume_Up", Nz::Keyboard::Volume_Up); + instance.PushField("CapsLock", Nz::Keyboard::CapsLock); + instance.PushField("NumLock", Nz::Keyboard::NumLock); + instance.PushField("ScrollLock", Nz::Keyboard::ScrollLock); + } + instance.Pop(); } } diff --git a/SDK/src/NDK/Sdk.cpp b/SDK/src/NDK/Sdk.cpp index 36283ada3..81080af06 100644 --- a/SDK/src/NDK/Sdk.cpp +++ b/SDK/src/NDK/Sdk.cpp @@ -9,14 +9,18 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#include #include #include +#include #include #include @@ -68,6 +72,7 @@ namespace Ndk Nz::Lua::Initialize(); Nz::Noise::Initialize(); + Nz::Physics2D::Initialize(); Nz::Physics3D::Initialize(); Nz::Utility::Initialize(); @@ -83,9 +88,11 @@ namespace Ndk BaseComponent::Initialize(); // Shared components - InitializeComponent("NdkColli"); + InitializeComponent("NdkColl2"); + InitializeComponent("NdkColl3"); InitializeComponent("NdkNode"); - InitializeComponent("NdkPhys"); + InitializeComponent("NdkPhys2"); + InitializeComponent("NdkPhys3"); InitializeComponent("NdkVeloc"); #ifndef NDK_SERVER @@ -103,6 +110,7 @@ namespace Ndk BaseSystem::Initialize(); // Shared systems + InitializeSystem(); InitializeSystem(); InitializeSystem(); @@ -161,6 +169,7 @@ namespace Ndk // Shared modules Nz::Lua::Uninitialize(); Nz::Noise::Uninitialize(); + Nz::Physics2D::Uninitialize(); Nz::Physics3D::Uninitialize(); Nz::Utility::Uninitialize(); diff --git a/SDK/src/NDK/Systems/ListenerSystem.cpp b/SDK/src/NDK/Systems/ListenerSystem.cpp index 9c7333d34..3de647a08 100644 --- a/SDK/src/NDK/Systems/ListenerSystem.cpp +++ b/SDK/src/NDK/Systems/ListenerSystem.cpp @@ -25,6 +25,7 @@ namespace Ndk ListenerSystem::ListenerSystem() { Requires(); + SetUpdateOrder(100); //< Update last, after every movement is done } /*! @@ -33,11 +34,9 @@ namespace Ndk * \param elapsedTime Delta time used for the update */ - void ListenerSystem::OnUpdate(float elapsedTime) + void ListenerSystem::OnUpdate(float /*elapsedTime*/) { - NazaraUnused(elapsedTime); - - unsigned int activeListenerCount = 0; + std::size_t activeListenerCount = 0; for (const Ndk::EntityHandle& entity : GetEntities()) { diff --git a/SDK/src/NDK/Systems/PhysicsSystem2D.cpp b/SDK/src/NDK/Systems/PhysicsSystem2D.cpp new file mode 100644 index 000000000..adedfc170 --- /dev/null +++ b/SDK/src/NDK/Systems/PhysicsSystem2D.cpp @@ -0,0 +1,140 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + /*! + * \ingroup NDK + * \class Ndk::PhysicsSystem2D + * \brief NDK class that represents a two-dimensional physics system + * + * \remark This system is enabled if the entity has the trait: NodeComponent and any of these two: CollisionComponent3D or PhysicsComponent3D + * \remark Static objects do not have a velocity specified by the physical engine + */ + + /*! + * \brief Constructs an PhysicsSystem object by default + */ + + PhysicsSystem2D::PhysicsSystem2D() + { + Requires(); + RequiresAny(); + Excludes(); + } + + /*! + * \brief Constructs a PhysicsSystem object by copy semantic + * + * \param system PhysicsSystem to copy + */ + + PhysicsSystem2D::PhysicsSystem2D(const PhysicsSystem2D& system) : + System(system), + m_world() + { + } + + void PhysicsSystem2D::CreatePhysWorld() const + { + NazaraAssert(!m_world, "Physics world should not be created twice"); + + m_world = std::make_unique(); + } + + /*! + * \brief Operation to perform when entity is validated for the system + * + * \param entity Pointer to the entity + * \param justAdded Is the entity newly added + */ + + void PhysicsSystem2D::OnEntityValidation(Entity* entity, bool justAdded) + { + // It's possible our entity got revalidated because of the addition/removal of a PhysicsComponent3D + if (!justAdded) + { + // We take the opposite array from which the entity should belong to + auto& entities = (entity->HasComponent()) ? m_staticObjects : m_dynamicObjects; + entities.Remove(entity); + } + + auto& entities = (entity->HasComponent()) ? m_dynamicObjects : m_staticObjects; + entities.Insert(entity); + + if (!m_world) + CreatePhysWorld(); + } + + /*! + * \brief Operation to perform when system is updated + * + * \param elapsedTime Delta time used for the update + */ + + void PhysicsSystem2D::OnUpdate(float elapsedTime) + { + if (!m_world) + return; + + m_world->Step(elapsedTime); + + for (const Ndk::EntityHandle& entity : m_dynamicObjects) + { + NodeComponent& node = entity->GetComponent(); + PhysicsComponent2D& phys = entity->GetComponent(); + + Nz::RigidBody2D& body = phys.GetRigidBody(); + node.SetRotation(Nz::EulerAnglesf(0.f, 0.f, body.GetRotation()), Nz::CoordSys_Global); + node.SetPosition(Nz::Vector3f(body.GetPosition(), node.GetPosition(Nz::CoordSys_Global).z), Nz::CoordSys_Global); + } + + float invElapsedTime = 1.f / elapsedTime; + for (const Ndk::EntityHandle& entity : m_staticObjects) + { + CollisionComponent2D& collision = entity->GetComponent(); + NodeComponent& node = entity->GetComponent(); + + Nz::RigidBody2D* body = collision.GetStaticBody(); + + Nz::Vector2f oldPosition = body->GetPosition(); + Nz::Vector2f newPosition = Nz::Vector2f(node.GetPosition(Nz::CoordSys_Global)); + + // To move static objects and ensure their collisions, we have to specify them a velocity + // (/!\: the physical motor does not apply the speed on static objects) + if (newPosition != oldPosition) + { + body->SetPosition(newPosition); + body->SetVelocity((newPosition - oldPosition) * invElapsedTime); + } + else + body->SetVelocity(Nz::Vector2f::Zero()); + +/* + if (newRotation != oldRotation) + { + Nz::Quaternionf transition = newRotation * oldRotation.GetConjugate(); + Nz::EulerAnglesf angles = transition.ToEulerAngles(); + Nz::Vector3f angularVelocity(Nz::ToRadians(angles.pitch * invElapsedTime), + Nz::ToRadians(angles.yaw * invElapsedTime), + Nz::ToRadians(angles.roll * invElapsedTime)); + + physObj->SetRotation(oldRotation); + physObj->SetAngularVelocity(angularVelocity); + } + else + physObj->SetAngularVelocity(Nz::Vector3f::Zero()); +*/ + } + } + + SystemIndex PhysicsSystem2D::systemIndex; +} diff --git a/SDK/src/NDK/Systems/PhysicsSystem3D.cpp b/SDK/src/NDK/Systems/PhysicsSystem3D.cpp index fd5e05d66..c26c932e0 100644 --- a/SDK/src/NDK/Systems/PhysicsSystem3D.cpp +++ b/SDK/src/NDK/Systems/PhysicsSystem3D.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace Ndk @@ -27,6 +28,7 @@ namespace Ndk { Requires(); RequiresAny(); + Excludes(); } /*! @@ -90,7 +92,7 @@ namespace Ndk NodeComponent& node = entity->GetComponent(); PhysicsComponent3D& phys = entity->GetComponent(); - Nz::RigidBody3D& physObj = phys.GetPhysObject(); + Nz::RigidBody3D& physObj = phys.GetRigidBody(); node.SetRotation(physObj.GetRotation(), Nz::CoordSys_Global); node.SetPosition(physObj.GetPosition(), Nz::CoordSys_Global); } diff --git a/SDK/src/NDK/Systems/RenderSystem.cpp b/SDK/src/NDK/Systems/RenderSystem.cpp index d4754a619..bdbb6cb5b 100644 --- a/SDK/src/NDK/Systems/RenderSystem.cpp +++ b/SDK/src/NDK/Systems/RenderSystem.cpp @@ -35,7 +35,8 @@ namespace Ndk { ChangeRenderTechnique(); SetDefaultBackground(Nz::ColorBackground::New()); - SetUpdateRate(0.f); + SetUpdateOrder(100); //< Render last, after every movement is done + SetUpdateRate(0.f); //< We don't want any rate limit } /*! @@ -150,10 +151,8 @@ namespace Ndk * \param elapsedTime Delta time used for the update */ - void RenderSystem::OnUpdate(float elapsedTime) + void RenderSystem::OnUpdate(float /*elapsedTime*/) { - NazaraUnused(elapsedTime); - // Invalidate every renderable if the coordinate system changed if (m_coordinateSystemInvalidated) { diff --git a/SDK/src/NDK/Systems/VelocitySystem.cpp b/SDK/src/NDK/Systems/VelocitySystem.cpp index c1298bde3..4bc3b3a68 100644 --- a/SDK/src/NDK/Systems/VelocitySystem.cpp +++ b/SDK/src/NDK/Systems/VelocitySystem.cpp @@ -24,8 +24,9 @@ namespace Ndk VelocitySystem::VelocitySystem() { - Requires(); Excludes(); + Requires(); + SetUpdateOrder(10); //< Since some systems may want to stop us } /*! diff --git a/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index 6ba110aee..78b250aaf 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ namespace Ndk void World::AddDefaultSystems() { + AddSystem(); AddSystem(); AddSystem(); @@ -67,7 +69,7 @@ namespace Ndk else { // We allocate a new entity - id = m_entities.size(); + id = static_cast(m_entities.size()); // We can't use emplace_back due to the scope m_entities.push_back(Entity(this, id)); @@ -172,6 +174,9 @@ namespace Ndk void World::Update() { + if (!m_orderedSystemsUpdated) + ReorderSystems(); + // Handle killed entities before last call for (std::size_t i = m_killedEntities.FindFirst(); i != m_killedEntities.npos; i = m_killedEntities.FindNext(i)) { @@ -218,15 +223,11 @@ namespace Ndk Nz::Bitset<>& removedComponents = entity->GetRemovedComponentBits(); for (std::size_t j = removedComponents.FindFirst(); j != m_dirtyEntities.npos; j = removedComponents.FindNext(j)) - entity->DestroyComponent(j); + entity->DestroyComponent(static_cast(j)); removedComponents.Reset(); - for (auto& system : m_systems) + for (auto& system : m_orderedSystems) { - // Ignore non-existent systems - if (!system) - continue; - // Is our entity already part of this system? bool partOfSystem = system->HasEntity(entity); @@ -249,4 +250,22 @@ namespace Ndk } m_dirtyEntities.Reset(); } + + void World::ReorderSystems() + { + m_orderedSystems.clear(); + + for (auto& systemPtr : m_systems) + { + if (systemPtr) + m_orderedSystems.push_back(systemPtr.get()); + } + + std::sort(m_orderedSystems.begin(), m_orderedSystems.end(), [] (BaseSystem* first, BaseSystem* second) + { + return first->GetUpdateOrder() < second->GetUpdateOrder(); + }); + + m_orderedSystemsUpdated = true; + } } diff --git a/build/scripts/common.lua b/build/scripts/common.lua index bb1999e09..01b51562d 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -693,7 +693,10 @@ function NazaraBuild:PrepareGeneric() flags({ "C++14", "MultiProcessorCompile", - "NoMinimalRebuild" + "NoMinimalRebuild", + "RelativeLinks", + "ShadowedVariables", + "UndefinedIdentifiers" }) self:FilterLibDirectory("../extlibs/lib/", libdirs) @@ -727,7 +730,6 @@ function NazaraBuild:PrepareGeneric() filter("configurations:Release*") flags("NoFramePointer") optimize("Speed") - rtti("Off") vectorextensions("SSE2") filter("configurations:*Static") diff --git a/include/Nazara/Core/AbstractLogger.docx b/include/Nazara/Core/AbstractLogger.docx deleted file mode 100644 index 6ac06b95c..000000000 --- a/include/Nazara/Core/AbstractLogger.docx +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (C) 2015 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 - -/*! -* \ingroup core -* \class Nz::AbstractLogger -* \brief Logger interface -*/ - diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index 5bb461f26..a6d5e77a7 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -22,6 +22,7 @@ namespace Nz template decltype(auto) Apply(F&& fn, Tuple&& t); template decltype(auto) Apply(O& object, F&& fn, Tuple&& t); + template constexpr std::size_t BitCount(); template ByteArray ComputeHash(HashType hash, const T& v); template ByteArray ComputeHash(AbstractHash* hash, const T& v); template constexpr std::size_t CountOf(T(&name)[N]) noexcept; diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index b02924446..fea1fd964 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace Nz @@ -70,6 +71,17 @@ namespace Nz return Detail::ApplyImplMethod(object, std::forward(fn), std::forward(t), std::make_index_sequence()); } + /*! + * \ingroup core + * \brief Returns the number of bits occupied by the type T + * \return Number of bits occupied by the type + */ + template + constexpr std::size_t BitCount() + { + return CHAR_BIT * sizeof(T); + } + /*! * \ingroup core * \brief Computes the hash of a hashable object diff --git a/include/Nazara/Core/Bitset.hpp b/include/Nazara/Core/Bitset.hpp index 5c2746d16..622238854 100644 --- a/include/Nazara/Core/Bitset.hpp +++ b/include/Nazara/Core/Bitset.hpp @@ -8,6 +8,7 @@ #define NAZARA_BITSET_HPP #include +#include #include #include #include @@ -24,6 +25,7 @@ namespace Nz public: class Bit; + using PointerSequence = std::pair; //< Start pointer, bit offset Bitset(); explicit Bitset(std::size_t bitCount, bool val); @@ -35,6 +37,8 @@ namespace Nz Bitset(Bitset&& bitset) noexcept = default; ~Bitset() noexcept = default; + template void AppendBits(T bits, std::size_t bitCount); + void Clear() noexcept; std::size_t Count() const; void Flip(); @@ -47,6 +51,9 @@ namespace Nz std::size_t GetCapacity() const; std::size_t GetSize() const; + PointerSequence Read(const void* ptr, std::size_t bitCount); + PointerSequence Read(const PointerSequence& sequence, std::size_t bitCount); + void PerformsAND(const Bitset& a, const Bitset& b); void PerformsNOT(const Bitset& a); void PerformsOR(const Bitset& a, const Bitset& b); @@ -60,6 +67,8 @@ namespace Nz void Reset(); void Reset(std::size_t bit); + void Reverse(); + void Set(bool val = true); void Set(std::size_t bit, bool val = true); void SetBlock(std::size_t i, Block block); @@ -102,9 +111,11 @@ namespace Nz Bitset& operator^=(const Bitset& bitset); static constexpr Block fullBitMask = std::numeric_limits::max(); - static constexpr std::size_t bitsPerBlock = std::numeric_limits::digits; + static constexpr std::size_t bitsPerBlock = BitCount(); static constexpr std::size_t npos = std::numeric_limits::max(); + static Bitset FromPointer(const void* ptr, std::size_t bitCount, PointerSequence* sequence = nullptr); + private: std::size_t FindFirstFrom(std::size_t blockIndex) const; Block GetLastBlockMask() const; @@ -154,6 +165,9 @@ namespace Nz Block m_mask; }; + template + std::ostream& operator<<(std::ostream& out, const Bitset& bitset); + template bool operator==(const Bitset& lhs, const Nz::Bitset& rhs); diff --git a/include/Nazara/Core/Bitset.inl b/include/Nazara/Core/Bitset.inl index 6ddb252e7..afec6983a 100644 --- a/include/Nazara/Core/Bitset.inl +++ b/include/Nazara/Core/Bitset.inl @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -122,13 +121,13 @@ namespace Nz { if (sizeof(T) <= sizeof(Block)) { - m_bitCount = std::numeric_limits::digits; + m_bitCount = BitCount(); m_blocks.push_back(static_cast(value)); } else { // Note: I was kinda tired when I wrote this, there's probably a much easier method than checking bits to write bits - for (std::size_t bitPos = 0; bitPos < std::numeric_limits::digits; bitPos++) + for (std::size_t bitPos = 0; bitPos < BitCount(); bitPos++) { if (value & (T(1U) << bitPos)) UnboundedSet(bitPos, true); @@ -137,11 +136,63 @@ namespace Nz } /*! - * \brief Clears the content of the bitset, GetSize() is now equals to 0 + * \brief Appends bits to the bitset * - * \remark The memory allocated is not released + * This function extends the bitset with bits extracted from an integer value + * + * \param bits An integer value from where bits will be extracted + * \param bitCount Number of bits to extract from the value + * + * \remark This function does not require bitCount to be lower or equal to the number of bits of T, thus + * reading 32 bits from a UInt8 will work (by extracting the first 8 bits values and appending 24 zeros afterneath). + * + * \see AppendBits + * \see Read */ + template + template + void Bitset::AppendBits(T bits, std::size_t bitCount) + { + std::size_t bitShift = m_bitCount % bitsPerBlock; + m_bitCount += bitCount; + if (bitShift != 0) + { + std::size_t remainingBits = bitsPerBlock - bitShift; + m_blocks.back() |= Block(bits) << bitShift; + bits >>= bitsPerBlock - bitShift; + + bitCount -= std::min(remainingBits, bitCount); + } + + if (bitCount > 0) + { + std::size_t blockCount = ComputeBlockCount(bitCount); + for (std::size_t block = 0; block < blockCount - 1; ++block) + { + m_blocks.push_back(static_cast(bits)); + bits = (BitCount() < BitCount()) ? bits >> BitCount() : 0U; + bitCount -= BitCount(); + } + + // For the last iteration, mask out the bits we don't want + std::size_t remainingBits = bitCount; + + bits &= ((Block(1U) << remainingBits) - 1U); + m_blocks.push_back(static_cast(bits)); + } + } + + /*! + * \brief Clears the content of the bitset + * + * This function clears the bitset content, resetting its bit and block count at zero. + * + * \remark This does not changes the bits values to zero but empties the bitset, to reset the bits use the Reset() function + * \remark This call does not changes the bitset capacity + * + * \see Reset() + */ template void Bitset::Clear() noexcept { @@ -151,9 +202,9 @@ namespace Nz /*! * \brief Counts the number of bits set to 1 + * * \return Number of bits set to 1 */ - template std::size_t Bitset::Count() const { @@ -169,8 +220,9 @@ namespace Nz /*! * \brief Flips each bit of the bitset + * + * This function flips every bit of the bitset, which means every '1' turns into a '0' and conversely. */ - template void Bitset::Flip() { @@ -182,9 +234,9 @@ namespace Nz /*! * \brief Finds the first bit set to one in the bitset - * \return Index of the first bit + * + * \return The 0-based index of the first bit enabled */ - template std::size_t Bitset::FindFirst() const { @@ -192,14 +244,14 @@ namespace Nz } /*! - * \brief Finds the next bit set to one in the bitset - * \return Index of the next bit if exists or npos + * \brief Finds the next enabled in the bitset * - * \param bit Index of the bit, the search begin with bit + 1 + * \param bit Index of the last bit found, which will not be treated by this function * - * \remark Produce a NazaraAssert if bit is greather than number of bits in bitset + * \return Index of the next enabled bit or npos if all the following bits are disabled + * + * \remark This function is typically used in for-loops to iterate on bits */ - template std::size_t Bitset::FindNext(std::size_t bit) const { @@ -275,6 +327,76 @@ namespace Nz return m_bitCount; } + /*! + * \brief Read a byte sequence into a bitset + * + * This function extends the bitset with bits read from a byte sequence + * + * \param ptr A pointer to the start of the byte sequence + * \param bitCount Number of bits to read from the byte sequence + * + * \returns A pointer to the next byte to read along with the next bit index (useful when reading multiple times) + * + * \remark For technical reasons, ceil(bitCount / 8) bytes from the sequence will always be read (even with non-multiple-of-8 bitCount) + * + * \see AppendBits + * \see Read + */ + template + typename Bitset::PointerSequence Bitset::Read(const void* ptr, std::size_t bitCount) + { + return Read(PointerSequence(ptr, 0U), bitCount); + } + + /*! + * \brief Read a byte sequence into a bitset + * + * This function extends the bitset with bits read from a pointer sequence (made of a pointer and a bit index) + * + * \param sequence A pointer sequence to the start of the byte sequence + * \param bitCount Number of bits to read from the byte sequence + * + * \returns A pointer to the next byte to read along with the next bit index (useful when reading multiple times) + * + * \remark For technical reasons, ceil(bitCount / 8) bytes from the sequence will always be read (even with non-multiple-of-8 bitCount) + * + * \see AppendBits + * \see Read + */ + template + typename Bitset::PointerSequence Bitset::Read(const PointerSequence& sequence, std::size_t bitCount) + { + NazaraAssert(sequence.first, "Invalid pointer sequence"); + NazaraAssert(sequence.second < 8, "Invalid next bit index (must be < 8)"); + + std::size_t totalBitCount = sequence.second + bitCount; + + const UInt8* u8Ptr = static_cast(sequence.first); + const UInt8* endPtr = u8Ptr + ((totalBitCount != 0) ? (totalBitCount - 1) / 8 : 0); + const UInt8* nextPtr = endPtr + ((totalBitCount % 8 != 0) ? 0 : 1); + + // Read the first block apart to apply a mask on the first byte if necessary + if (sequence.second != 0) + { + UInt8 mask = ~((1U << sequence.second) - 1U); + + std::size_t readCount = std::min(bitCount, 8 - sequence.second); + AppendBits(Block(*u8Ptr++ & mask) >> sequence.second, readCount); + bitCount -= readCount; + } + + // And then read the remaining bytes + while (u8Ptr <= endPtr) + { + std::size_t bitToRead = std::min(bitCount, 8); + AppendBits(*u8Ptr++, bitToRead); + bitCount -= bitToRead; + } + + // Returns informations to continue reading + return PointerSequence(nextPtr, totalBitCount % 8); + } + /*! * \brief Performs the "AND" operator between two bitsets * @@ -289,15 +411,17 @@ namespace Nz { std::pair minmax = std::minmax(a.GetBlockCount(), b.GetBlockCount()); - // We reinitialise our blocks with zero - m_blocks.clear(); - m_blocks.resize(minmax.second, 0U); + m_blocks.resize(minmax.second); m_bitCount = std::max(a.GetSize(), b.GetSize()); // In case of the "AND", we can stop with the smallest size (because x & 0 = 0) for (std::size_t i = 0; i < minmax.first; ++i) m_blocks[i] = a.GetBlock(i) & b.GetBlock(i); + // And then reset every other block to zero + for (std::size_t i = minmax.first; i < minmax.second; ++i) + m_blocks[i] = 0U; + ResetExtraBits(); } @@ -458,6 +582,30 @@ namespace Nz Set(bit, false); } + /*! + * \brief Reverse the order of bits in a bitset + * + * Reverse the order of bits in the bitset (first bit swap with the last one, etc.) + */ + template + void Bitset::Reverse() + { + if (m_bitCount == 0) + return; + + std::size_t i = 0; + std::size_t j = m_bitCount - 1; + + while (i < j) + { + bool bit1 = Test(i); + bool bit2 = Test(j); + + Set(i++, bit2); + Set(j--, bit1); + } + } + /*! * \brief Sets the bitset to val * @@ -535,27 +683,28 @@ namespace Nz return; } - auto div = std::lldiv(pos, bitsPerBlock); - if (div.rem != 0) + std::size_t blockShift = pos / bitsPerBlock; + std::size_t remainder = pos % bitsPerBlock; + if (remainder != 0) { std::size_t lastIndex = m_blocks.size() - 1; - std::size_t remaining = bitsPerBlock - div.rem; + std::size_t remaining = bitsPerBlock - remainder; - for (std::size_t i = lastIndex - div.quot; i > 0; --i) - m_blocks[i + div.quot] = (m_blocks[i] << div.rem) | (m_blocks[i - 1] >> remaining); + for (std::size_t i = lastIndex - blockShift; i > 0; --i) + m_blocks[i + blockShift] = (m_blocks[i] << remainder) | (m_blocks[i - 1] >> remaining); - m_blocks[div.quot] = m_blocks[0] << div.rem; + m_blocks[blockShift] = m_blocks[0] << remainder; - std::fill_n(m_blocks.begin(), div.quot, Block(0)); + std::fill_n(m_blocks.begin(), blockShift, Block(0)); } else { for (auto it = m_blocks.rbegin(); it != m_blocks.rend(); ++it) { - if (static_cast(std::distance(m_blocks.rbegin(), it) + div.quot) < m_blocks.size()) + if (static_cast(std::distance(m_blocks.rbegin(), it) + blockShift) < m_blocks.size()) { auto shiftedIt = it; - std::advance(shiftedIt, div.quot); + std::advance(shiftedIt, blockShift); *it = *shiftedIt; } @@ -588,27 +737,28 @@ namespace Nz return; } - auto div = std::lldiv(pos, bitsPerBlock); - if (div.rem != 0) + std::size_t blockShift = pos / bitsPerBlock; + std::size_t remainder = pos % bitsPerBlock; + if (remainder != 0) { std::size_t lastIndex = m_blocks.size() - 1; - std::size_t remaining = bitsPerBlock - div.rem; + std::size_t remaining = bitsPerBlock - remainder; - for (std::size_t i = div.quot; i < lastIndex; ++i) - m_blocks[i - div.quot] = (m_blocks[i] >> div.rem) | (m_blocks[i + 1] << remaining); + for (std::size_t i = blockShift; i < lastIndex; ++i) + m_blocks[i - blockShift] = (m_blocks[i] >> remainder) | (m_blocks[i + 1] << remaining); - m_blocks[lastIndex - div.quot] = m_blocks[lastIndex] >> div.rem; + m_blocks[lastIndex - blockShift] = m_blocks[lastIndex] >> remainder; - std::fill_n(m_blocks.begin() + (m_blocks.size() - div.quot), div.quot, Block(0)); + std::fill_n(m_blocks.begin() + (m_blocks.size() - blockShift), blockShift, Block(0)); } else { for (auto it = m_blocks.begin(); it != m_blocks.end(); ++it) { - if (static_cast(std::distance(m_blocks.begin(), it) + div.quot) < m_blocks.size()) + if (static_cast(std::distance(m_blocks.begin(), it) + blockShift) < m_blocks.size()) { auto shiftedIt = it; - std::advance(shiftedIt, div.quot); + std::advance(shiftedIt, blockShift); *it = *shiftedIt; } @@ -716,7 +866,7 @@ namespace Nz { static_assert(std::is_integral() && std::is_unsigned(), "T must be a unsigned integral type"); - NazaraAssert(m_bitCount <= std::numeric_limits::digits, "Bit count cannot be greater than T bit count"); + NazaraAssert(m_bitCount <= BitCount(), "Bit count cannot be greater than T bit count"); T value = 0; for (std::size_t i = 0; i < m_blocks.size(); ++i) @@ -989,13 +1139,41 @@ namespace Nz return *this; } + /*! + * \brief Builds a bitset from a byte sequence + * + * This function builds a bitset using a byte sequence by reading bitCount bits from it + * + * \param ptr A pointer to the start of the byte sequence + * \param bitCount Number of bits to read from the byte sequence + * \param sequence Optional data to pass to a next call to Read + * + * \return The constructed bitset + * + * \remark For technical reasons, ceil(bitCount / 8) bytes from the sequence will always be read (even with non-multiple-of-8 bitCount) + * + * \see AppendBits + * \see Read + */ + template + Bitset Bitset::FromPointer(const void* ptr, std::size_t bitCount, PointerSequence* sequence) + { + Bitset bitset; + + if (sequence) + *sequence = bitset.Read(ptr, bitCount); + else + bitset.Read(ptr, bitCount); + + return bitset; + } + /*! * \brief Finds the position of the first bit set to true after the blockIndex * \return The position of the bit * * \param blockIndex Index of the block */ - template std::size_t Bitset::FindFirstFrom(std::size_t blockIndex) const { @@ -1124,7 +1302,7 @@ namespace Nz template bool Bitset::Bit::Test() const { - return m_block & m_mask; + return (m_block & m_mask) != 0; } /*! @@ -1269,6 +1447,14 @@ namespace Nz return *this; } + + template + std::ostream& operator<<(std::ostream& out, const Bitset& bitset) + { + return out << bitset.ToString(); + } + + /*! * \brief Compares two bitsets * \return true if the two bitsets are the same diff --git a/include/Nazara/Core/ByteArray.hpp b/include/Nazara/Core/ByteArray.hpp index 90f9c5d03..4bdc34150 100644 --- a/include/Nazara/Core/ByteArray.hpp +++ b/include/Nazara/Core/ByteArray.hpp @@ -88,7 +88,7 @@ namespace Nz inline void ShrinkToFit(); inline void Swap(ByteArray& other); - inline String ToHex() const; + String ToHex() const; inline String ToString() const; // STL interface diff --git a/include/Nazara/Core/ByteArray.inl b/include/Nazara/Core/ByteArray.inl index 068bee4b6..b5d8b1510 100644 --- a/include/Nazara/Core/ByteArray.inl +++ b/include/Nazara/Core/ByteArray.inl @@ -465,22 +465,6 @@ namespace Nz m_array.swap(other.m_array); } - /*! - * \brief Gives a string representation in base 16 - * \return String in base 16 - */ - - inline String ByteArray::ToHex() const - { - std::size_t length = m_array.size() * 2; - - String hexOutput(length, '\0'); - for (std::size_t i = 0; i < m_array.size(); ++i) - std::sprintf(&hexOutput[i * 2], "%02x", m_array[i]); - - return hexOutput; - } - /*! * \brief Gives a string representation * \return String where each byte is converted to char diff --git a/include/Nazara/Core/ParameterList.hpp b/include/Nazara/Core/ParameterList.hpp index 751746aea..b34f0eca0 100644 --- a/include/Nazara/Core/ParameterList.hpp +++ b/include/Nazara/Core/ParameterList.hpp @@ -60,10 +60,10 @@ namespace Nz { struct UserdataValue { - UserdataValue(Destructor Destructor, void* value) : + UserdataValue(Destructor func, void* ud) : counter(1), - destructor(Destructor), - ptr(value) + destructor(func), + ptr(ud) { } diff --git a/include/Nazara/Graphics/ForwardRenderQueue.hpp b/include/Nazara/Graphics/ForwardRenderQueue.hpp index 99be2743e..56474a642 100644 --- a/include/Nazara/Graphics/ForwardRenderQueue.hpp +++ b/include/Nazara/Graphics/ForwardRenderQueue.hpp @@ -87,7 +87,7 @@ namespace Nz struct SpriteChain_XYZ_Color_UV { const VertexStruct_XYZ_Color_UV* vertices; - unsigned int spriteCount; + std::size_t spriteCount; }; struct BatchedSpriteEntry @@ -160,7 +160,7 @@ namespace Nz const Material* material; }; - typedef std::vector TransparentModelContainer; + typedef std::vector TransparentModelContainer; struct Layer { diff --git a/include/Nazara/Graphics/ParticleDeclaration.hpp b/include/Nazara/Graphics/ParticleDeclaration.hpp index 278d25961..770cbe31d 100644 --- a/include/Nazara/Graphics/ParticleDeclaration.hpp +++ b/include/Nazara/Graphics/ParticleDeclaration.hpp @@ -36,10 +36,10 @@ namespace Nz ~ParticleDeclaration(); void DisableComponent(ParticleComponent component); - void EnableComponent(ParticleComponent component, ComponentType type, unsigned int offset); + void EnableComponent(ParticleComponent component, ComponentType type, std::size_t offset); - void GetComponent(ParticleComponent component, bool* enabled, ComponentType* type, unsigned int* offset) const; - unsigned int GetStride() const; + void GetComponent(ParticleComponent component, bool* enabled, ComponentType* type, std::size_t* offset) const; + std::size_t GetStride() const; void SetStride(unsigned int stride); @@ -60,7 +60,7 @@ namespace Nz { ComponentType type; bool enabled = false; - unsigned int offset; + std::size_t offset; /* ** -Lynix: @@ -71,7 +71,7 @@ namespace Nz }; std::array m_components; - unsigned int m_stride; + std::size_t m_stride; static std::array s_declarations; static ParticleDeclarationLibrary::LibraryMap s_library; diff --git a/include/Nazara/Graphics/ParticleEmitter.hpp b/include/Nazara/Graphics/ParticleEmitter.hpp index 8bd26a4bd..cfbb9e98a 100644 --- a/include/Nazara/Graphics/ParticleEmitter.hpp +++ b/include/Nazara/Graphics/ParticleEmitter.hpp @@ -28,12 +28,12 @@ namespace Nz void EnableLagCompensation(bool enable); - unsigned int GetEmissionCount() const; + std::size_t GetEmissionCount() const; float GetEmissionRate() const; bool IsLagCompensationEnabled() const; - void SetEmissionCount(unsigned int count); + void SetEmissionCount(std::size_t count); void SetEmissionRate(float rate); ParticleEmitter& operator=(const ParticleEmitter& emitter) = default; @@ -49,7 +49,7 @@ namespace Nz bool m_lagCompensationEnabled; mutable float m_emissionAccumulator; float m_emissionRate; - unsigned int m_emissionCount; + std::size_t m_emissionCount; }; } diff --git a/include/Nazara/Graphics/ParticleGroup.hpp b/include/Nazara/Graphics/ParticleGroup.hpp index 409090284..35feaa674 100644 --- a/include/Nazara/Graphics/ParticleGroup.hpp +++ b/include/Nazara/Graphics/ParticleGroup.hpp @@ -45,11 +45,11 @@ namespace Nz void* GenerateParticles(unsigned int count); const ParticleDeclarationConstRef& GetDeclaration() const; - unsigned int GetMaxParticleCount() const; - unsigned int GetParticleCount() const; - unsigned int GetParticleSize() const; + std::size_t GetMaxParticleCount() const; + std::size_t GetParticleCount() const; + std::size_t GetParticleSize() const; - void KillParticle(unsigned int index); + void KillParticle(std::size_t index); void KillParticles(); void RemoveController(ParticleController* controller); @@ -81,6 +81,9 @@ namespace Nz }; std::set> m_dyingParticles; + std::size_t m_maxParticleCount; + std::size_t m_particleCount; + std::size_t m_particleSize; mutable std::vector m_buffer; std::vector m_controllers; std::vector m_emitters; @@ -88,9 +91,6 @@ namespace Nz ParticleDeclarationConstRef m_declaration; ParticleRendererRef m_renderer; bool m_processing; - unsigned int m_maxParticleCount; - unsigned int m_particleCount; - unsigned int m_particleSize; }; } diff --git a/include/Nazara/Graphics/ParticleMapper.inl b/include/Nazara/Graphics/ParticleMapper.inl index 63c9c49ba..7d33bb655 100644 --- a/include/Nazara/Graphics/ParticleMapper.inl +++ b/include/Nazara/Graphics/ParticleMapper.inl @@ -23,7 +23,7 @@ namespace Nz // Then the component that are interesting bool enabled; ComponentType type; - unsigned int offset; + std::size_t offset; m_declaration->GetComponent(component, &enabled, &type, &offset); if (enabled) @@ -54,7 +54,7 @@ namespace Nz // Then the component that are interesting bool enabled; ComponentType type; - unsigned int offset; + std::size_t offset; m_declaration->GetComponent(component, &enabled, &type, &offset); if (enabled) diff --git a/include/Nazara/Graphics/RenderTechniques.hpp b/include/Nazara/Graphics/RenderTechniques.hpp index 1e006858a..a4642ffc8 100644 --- a/include/Nazara/Graphics/RenderTechniques.hpp +++ b/include/Nazara/Graphics/RenderTechniques.hpp @@ -29,7 +29,7 @@ namespace Nz static AbstractRenderTechnique* GetByName(const String& name, int* techniqueRanking = nullptr); static AbstractRenderTechnique* GetByRanking(int maxRanking, int* techniqueRanking = nullptr); - static unsigned int GetCount(); + static std::size_t GetCount(); static void Register(const String& name, int ranking, RenderTechniqueFactory factory); diff --git a/include/Nazara/Graphics/Sprite.hpp b/include/Nazara/Graphics/Sprite.hpp index 13bcc289b..2c42f4ce1 100644 --- a/include/Nazara/Graphics/Sprite.hpp +++ b/include/Nazara/Graphics/Sprite.hpp @@ -47,9 +47,11 @@ namespace Nz inline void SetCornerColor(RectCorner corner, const Color& color); inline void SetDefaultMaterial(); inline void SetMaterial(MaterialRef material, bool resizeSprite = true); + bool SetMaterial(String materialName, bool resizeSprite = true); inline void SetOrigin(const Vector3f& origin); inline void SetSize(const Vector2f& size); inline void SetSize(float sizeX, float sizeY); + bool SetTexture(String textureName, bool resizeSprite = true); inline void SetTexture(TextureRef texture, bool resizeSprite = true); inline void SetTextureCoords(const Rectf& coords); inline void SetTextureRect(const Rectui& rect); diff --git a/include/Nazara/Graphics/Sprite.inl b/include/Nazara/Graphics/Sprite.inl index 35885a94a..deec75959 100644 --- a/include/Nazara/Graphics/Sprite.inl +++ b/include/Nazara/Graphics/Sprite.inl @@ -184,12 +184,11 @@ namespace Nz } /*! - * \brief Sets the material of the sprite + * \brief Changes the material of the sprite * * \param material Material for the sprite - * \param resizeSprite Should sprite be resized to the material size (diffuse map) + * \param resizeSprite Should the sprite be resized to the texture size? */ - inline void Sprite::SetMaterial(MaterialRef material, bool resizeSprite) { m_material = std::move(material); @@ -249,16 +248,19 @@ namespace Nz /*! * \brief Sets the texture of the sprite * + * Assign a texture to the sprite material + * * \param texture Texture for the sprite - * \param resizeSprite Should sprite be resized to the texture size + * \param resizeSprite Should the sprite be resized to the texture size? + * + * \remark The sprite material gets copied to prevent accidentally changing other drawable materials */ - inline void Sprite::SetTexture(TextureRef texture, bool resizeSprite) { if (!m_material) SetDefaultMaterial(); else if (m_material->GetReferenceCount() > 1) - m_material = Material::New(*m_material); // Copie + m_material = Material::New(*m_material); // Copy the material if (resizeSprite && texture && texture->IsValid()) SetSize(Vector2f(Vector2ui(texture->GetSize()))); diff --git a/include/Nazara/Math/Algorithm.hpp b/include/Nazara/Math/Algorithm.hpp index 45281bb50..f138a8fc9 100644 --- a/include/Nazara/Math/Algorithm.hpp +++ b/include/Nazara/Math/Algorithm.hpp @@ -37,7 +37,7 @@ namespace Nz { template /*constexpr*/ T Approach(T value, T objective, T increment); template constexpr T Clamp(T value, T min, T max); - template /*constexpr*/ T CountBits(T value); + template /*constexpr*/ std::size_t CountBits(T value); template constexpr T FromDegrees(T degrees); template constexpr T FromRadians(T radians); template constexpr T DegreeToRadian(T degrees); diff --git a/include/Nazara/Math/Algorithm.inl b/include/Nazara/Math/Algorithm.inl index b61d82916..02ede739a 100644 --- a/include/Nazara/Math/Algorithm.inl +++ b/include/Nazara/Math/Algorithm.inl @@ -147,10 +147,10 @@ namespace Nz template //TODO: Mark as constexpr when supported by all major compilers - /*constexpr*/ inline T CountBits(T value) + /*constexpr*/ inline std::size_t CountBits(T value) { // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan - unsigned int count = 0; + std::size_t count = 0; while (value) { value &= value - 1; diff --git a/include/Nazara/Math/EulerAngles.inl b/include/Nazara/Math/EulerAngles.inl index 24bfd4630..3b12e7abe 100644 --- a/include/Nazara/Math/EulerAngles.inl +++ b/include/Nazara/Math/EulerAngles.inl @@ -17,11 +17,11 @@ namespace Nz { /*! - * \ingroup math + * \ingroup math * \class Nz::EulerAngles * \brief Math class that represents an Euler angle. Those describe a rotation transformation by rotating an object on its various axes in specified amounts per axis, and a specified axis order * - * \remark Rotation are "left-handed", it means that you take your left hand, put your thumb finger in the direction you want and you other fingers represent the way of rotating + * \remark Rotation are "right-handed", it means that you take your right hand, put your thumb finger in the direction you want and you other fingers represent the way of rotating */ /*! @@ -197,6 +197,7 @@ namespace Nz template Quaternion EulerAngles::ToQuaternion() const { + // XYZ T c1 = std::cos(ToRadians(yaw) / F(2.0)); T c2 = std::cos(ToRadians(roll) / F(2.0)); T c3 = std::cos(ToRadians(pitch) / F(2.0)); diff --git a/include/Nazara/Math/Quaternion.inl b/include/Nazara/Math/Quaternion.inl index 5c7df28cd..f7f7c693c 100644 --- a/include/Nazara/Math/Quaternion.inl +++ b/include/Nazara/Math/Quaternion.inl @@ -714,10 +714,10 @@ namespace Nz #endif Quaternion interpolated; - interpolated.w = Lerp(from.w, to.w, interpolation); - interpolated.x = Lerp(from.x, to.x, interpolation); - interpolated.y = Lerp(from.y, to.y, interpolation); - interpolated.z = Lerp(from.z, to.z, interpolation); + interpolated.w = Nz::Lerp(from.w, to.w, interpolation); + interpolated.x = Nz::Lerp(from.x, to.x, interpolation); + interpolated.y = Nz::Lerp(from.y, to.y, interpolation); + interpolated.z = Nz::Lerp(from.z, to.z, interpolation); return interpolated; } diff --git a/include/Nazara/Physics2D/Collider2D.hpp b/include/Nazara/Physics2D/Collider2D.hpp index f8cd7d6af..7bc1c7618 100644 --- a/include/Nazara/Physics2D/Collider2D.hpp +++ b/include/Nazara/Physics2D/Collider2D.hpp @@ -125,6 +125,33 @@ namespace Nz private: std::vector CreateShapes(RigidBody2D* body) const override; }; + + class SegmentCollider2D; + + using SegmentCollider2DConstRef = ObjectRef; + using SegmentCollider2DRef = ObjectRef; + + class NAZARA_PHYSICS2D_API SegmentCollider2D : public Collider2D + { + public: + inline SegmentCollider2D(const Vector2f& first, const Vector2f& second, float thickness = 1.f); + + float ComputeInertialMatrix(float mass) const override; + + inline const Vector2f& GetFirstPoint() const; + inline float GetLength() const; + inline const Vector2f& GetSecondPoint() const; + ColliderType2D GetType() const override; + + template static SegmentCollider2DRef New(Args&&... args); + + private: + std::vector CreateShapes(RigidBody2D* body) const override; + + Vector2f m_first; + Vector2f m_second; + float m_thickness; + }; } #include diff --git a/include/Nazara/Physics2D/Collider2D.inl b/include/Nazara/Physics2D/Collider2D.inl index 2cd44d326..5c3909cde 100644 --- a/include/Nazara/Physics2D/Collider2D.inl +++ b/include/Nazara/Physics2D/Collider2D.inl @@ -49,6 +49,36 @@ namespace Nz return object.release(); } + SegmentCollider2D::SegmentCollider2D(const Vector2f& first, const Vector2f& second, float thickness) : + m_first(first), + m_second(second), + m_thickness(thickness) + { + } + + inline const Vector2f& SegmentCollider2D::GetFirstPoint() const + { + return m_first; + } + + inline float SegmentCollider2D::GetLength() const + { + return m_first.Distance(m_second); + } + + inline const Vector2f& SegmentCollider2D::GetSecondPoint() const + { + return m_second; + } + + template + SegmentCollider2DRef SegmentCollider2D::New(Args&&... args) + { + std::unique_ptr object(new SegmentCollider2D(std::forward(args)...)); + object->SetPersistent(false); + + return object.release(); + } } #include diff --git a/include/Nazara/Physics2D/RigidBody2D.hpp b/include/Nazara/Physics2D/RigidBody2D.hpp index 7d521fbe6..79b7d64bc 100644 --- a/include/Nazara/Physics2D/RigidBody2D.hpp +++ b/include/Nazara/Physics2D/RigidBody2D.hpp @@ -49,6 +49,7 @@ namespace Nz bool IsSleeping() const; void SetAngularVelocity(float angularVelocity); + void SetGeom(Collider2DRef geom); void SetMass(float mass); void SetMassCenter(const Vector2f& center); void SetPosition(const Vector2f& position); @@ -59,8 +60,8 @@ namespace Nz RigidBody2D& operator=(RigidBody2D&& object); private: + void Create(float mass = 1.f, float moment = 1.f); void Destroy(); - void SetGeom(Collider2DRef geom); std::vector m_shapes; Collider2DRef m_geom; diff --git a/include/Nazara/Prerequesites.hpp b/include/Nazara/Prerequesites.hpp index bf9d1d75f..dbe478661 100644 --- a/include/Nazara/Prerequesites.hpp +++ b/include/Nazara/Prerequesites.hpp @@ -25,8 +25,7 @@ #ifndef NAZARA_PREREQUESITES_HPP #define NAZARA_PREREQUESITES_HPP -// Identification du compilateur -///TODO: Rajouter des tests d'identification de compilateurs +// Try to identify the compiler #if defined(__BORLANDC__) #define NAZARA_COMPILER_BORDLAND #define NAZARA_COMPILER_SUPPORTS_CPP11 (defined(__cplusplus) && __cplusplus >= 201103L) @@ -63,10 +62,10 @@ #pragma warning(disable: 4251) #else #define NAZARA_COMPILER_UNKNOWN + #define NAZARA_COMPILER_SUPPORTS_CPP11 (defined(__cplusplus) && __cplusplus >= 201103L) #define NAZARA_DEPRECATED(txt) - #define NAZARA_FUNCTION __func__ // __func__ est standard depuis le C++11 + #define NAZARA_FUNCTION __func__ // __func__ has been standardized in C++ 2011 - /// Cette ligne n'est là que pour prévenir, n'hésitez pas à la commenter si elle vous empêche de compiler #pragma message This compiler is not fully supported #endif @@ -76,20 +75,20 @@ // Nazara version macro #define NAZARA_VERSION_MAJOR 0 -#define NAZARA_VERSION_MINOR 1 +#define NAZARA_VERSION_MINOR 2 #define NAZARA_VERSION_PATCH 1 #include -// Identification de la plateforme +// Try to identify target platform via defines #if defined(_WIN32) #define NAZARA_PLATFORM_WINDOWS #define NAZARA_EXPORT __declspec(dllexport) #define NAZARA_IMPORT __declspec(dllimport) - // Des defines pour le header Windows - #if defined(NAZARA_BUILD) // Pour ne pas entrer en conflit avec les defines de l'application ou d'une autre bibliothèque + // Somes defines for windows.h include.. + #if defined(NAZARA_BUILD) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -99,13 +98,12 @@ #endif #if NAZARA_CORE_WINDOWS_NT6 - // Version de Windows minimale : Vista #define NAZARA_WINNT 0x0600 #else #define NAZARA_WINNT 0x0501 #endif - // Pour ne pas casser le define déjà en place s'il est applicable + // Keep the actual define if existing and greater than our requirement #if defined(_WIN32_WINNT) #if _WIN32_WINNT < NAZARA_WINNT #undef _WIN32_WINNT @@ -128,7 +126,6 @@ #define NAZARA_PLATFORM_MACOSX #define NAZARA_PLATFORM_POSIX*/ #else - // À commenter pour tenter quand même une compilation #error This operating system is not fully supported by the Nazara Engine #define NAZARA_PLATFORM_UNKNOWN @@ -141,12 +138,7 @@ #define NAZARA_PLATFORM_x64 #endif -// Définit NDEBUG si NAZARA_DEBUG n'est pas présent -#if !defined(NAZARA_DEBUG) && !defined(NDEBUG) - #define NDEBUG -#endif - -// Macros supplémentaires +// A bunch of useful macros #define NazaraPrefix(a, prefix) prefix ## a #define NazaraPrefixMacro(a, prefix) NazaraPrefix(a, prefix) #define NazaraSuffix(a, suffix) a ## suffix @@ -155,8 +147,11 @@ #define NazaraStringifyMacro(s) NazaraStringify(s) // http://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification #define NazaraUnused(a) (void) a +#include #include +static_assert(CHAR_BIT == 8, "CHAR_BIT is expected to be 8"); + static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" ); static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size"); static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size"); @@ -169,17 +164,17 @@ static_assert(sizeof(uint64_t) == 8, "uint64_t is not of the correct size"); namespace Nz { - typedef int8_t Int8; - typedef uint8_t UInt8; + typedef int8_t Int8; + typedef uint8_t UInt8; - typedef int16_t Int16; - typedef uint16_t UInt16; + typedef int16_t Int16; + typedef uint16_t UInt16; - typedef int32_t Int32; - typedef uint32_t UInt32; + typedef int32_t Int32; + typedef uint32_t UInt32; - typedef int64_t Int64; - typedef uint64_t UInt64; + typedef int64_t Int64; + typedef uint64_t UInt64; } #endif // NAZARA_PREREQUESITES_HPP diff --git a/include/Nazara/Utility/Config.hpp b/include/Nazara/Utility/Config.hpp index ee77405be..39aa014af 100644 --- a/include/Nazara/Utility/Config.hpp +++ b/include/Nazara/Utility/Config.hpp @@ -38,9 +38,6 @@ // Lors du parsage d'une ressource, déclenche un avertissement si une erreur non-critique est repérée dans une ressource (Plus lent) #define NAZARA_UTILITY_STRICT_RESOURCE_PARSING 1 -// Fait tourner chaque fenêtre dans un thread séparé si le système le supporte -#define NAZARA_UTILITY_THREADED_WINDOW 0 - // Protège les classes des accès concurrentiels //#define NAZARA_UTILITY_THREADSAFE 1 diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 3f32945c2..9390b7991 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -432,15 +432,17 @@ namespace Nz enum WindowStyleFlags { - WindowStyle_None = 0x0, - WindowStyle_Fullscreen = 0x1, + WindowStyle_None = 0x0, ///< Window has no border nor titlebar. + WindowStyle_Fullscreen = 0x1, ///< At the window creation, the OS tries to set it in fullscreen. - WindowStyle_Closable = 0x2, - WindowStyle_Resizable = 0x4, - WindowStyle_Titlebar = 0x8, + WindowStyle_Closable = 0x2, ///< Allows the window to be closed by a button in the titlebar, generating a Quit event. + WindowStyle_Resizable = 0x4, ///< Allows the window to be resized by dragging its corners or by a button of the titlebar. + WindowStyle_Titlebar = 0x8, ///< Adds a titlebar to the window, this option is automatically enabled if buttons of the titlebar are enabled. + + WindowStyle_Threaded = 0x10, ///< Runs the window into a thread, allowing the application to keep updating while resizing/dragging the window. WindowStyle_Default = WindowStyle_Closable | WindowStyle_Resizable | WindowStyle_Titlebar, - WindowStyle_Max = WindowStyle_Titlebar*2-1 + WindowStyle_Max = WindowStyle_Threaded*2-1 }; } diff --git a/include/Nazara/Utility/EventHandler.hpp b/include/Nazara/Utility/EventHandler.hpp index 2464d5e72..5bc47bdea 100644 --- a/include/Nazara/Utility/EventHandler.hpp +++ b/include/Nazara/Utility/EventHandler.hpp @@ -24,6 +24,9 @@ namespace Nz inline void Dispatch(const WindowEvent& event); + EventHandler& operator=(const EventHandler&) = delete; + EventHandler& operator=(EventHandler&&) = default; + NazaraSignal(OnEvent, const EventHandler* /*eventHandler*/, const WindowEvent& /*event*/); NazaraSignal(OnGainedFocus, const EventHandler* /*eventHandler*/); NazaraSignal(OnLostFocus, const EventHandler* /*eventHandler*/); diff --git a/include/Nazara/Utility/Image.hpp b/include/Nazara/Utility/Image.hpp index 029157885..e1712aed1 100644 --- a/include/Nazara/Utility/Image.hpp +++ b/include/Nazara/Utility/Image.hpp @@ -91,6 +91,8 @@ namespace Nz ImageType GetType() const; unsigned int GetWidth(UInt8 level = 0) const; + bool HasAlpha() const; + bool IsValid() const; // Load diff --git a/include/Nazara/Utility/PixelFormat.inl b/include/Nazara/Utility/PixelFormat.inl index 4d8676916..59ad2ab04 100644 --- a/include/Nazara/Utility/PixelFormat.inl +++ b/include/Nazara/Utility/PixelFormat.inl @@ -39,18 +39,8 @@ namespace Nz } inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, Bitset<> rMask, Bitset<> gMask, Bitset<> bMask, Bitset<> aMask, PixelFormatSubType subType) : - redMask(rMask), - greenMask(gMask), - blueMask(bMask), - alphaMask(aMask), - content(formatContent), - redType(subType), - greenType(subType), - blueType(subType), - alphaType(subType), - name(formatName) + PixelFormatInfo(formatName, formatContent, subType, rMask, subType, gMask, subType, bMask, subType, aMask) { - RecomputeBitsPerPixel(); } inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, PixelFormatSubType rType, Bitset<> rMask, PixelFormatSubType gType, Bitset<> gMask, PixelFormatSubType bType, Bitset<> bMask, PixelFormatSubType aType, Bitset<> aMask, UInt8 bpp) : @@ -65,6 +55,11 @@ namespace Nz alphaType(aType), name(formatName) { + redMask.Reverse(); + greenMask.Reverse(); + blueMask.Reverse(); + alphaMask.Reverse(); + if (bpp == 0) RecomputeBitsPerPixel(); } @@ -123,6 +118,9 @@ namespace Nz if (usedBits > bitsPerPixel) return false; + if (usedBits > 64) //< Currently, formats with over 64 bits per component are not supported + return false; + switch (types[i]) { case PixelFormatSubType_Half: diff --git a/include/Nazara/Utility/VideoMode.hpp b/include/Nazara/Utility/VideoMode.hpp index dae9a5410..3c2243817 100644 --- a/include/Nazara/Utility/VideoMode.hpp +++ b/include/Nazara/Utility/VideoMode.hpp @@ -19,6 +19,7 @@ namespace Nz { public: VideoMode(); + VideoMode(unsigned int w, unsigned int h); VideoMode(unsigned int w, unsigned int h, UInt8 bpp); bool IsFullscreenValid() const; diff --git a/include/Nazara/Utility/Window.hpp b/include/Nazara/Utility/Window.hpp index e544093c5..0f7688a81 100644 --- a/include/Nazara/Utility/Window.hpp +++ b/include/Nazara/Utility/Window.hpp @@ -10,6 +10,8 @@ #define NAZARA_WINDOW_HPP #include +#include +#include #include #include #include @@ -19,11 +21,6 @@ #include #include -#if NAZARA_UTILITY_THREADED_WINDOW -#include -#include -#endif - namespace Nz { class Cursor; @@ -114,23 +111,24 @@ namespace Nz private: void IgnoreNextMouseEvent(int mouseX, int mouseY) const; + inline void HandleEvent(const WindowEvent& event); inline void PushEvent(const WindowEvent& event); static bool Initialize(); static void Uninitialize(); std::queue m_events; - #if NAZARA_UTILITY_THREADED_WINDOW + std::vector m_pendingEvents; ConditionVariable m_eventCondition; + EventHandler m_eventHandler; Mutex m_eventMutex; Mutex m_eventConditionMutex; - bool m_waitForEvent; - #endif - EventHandler m_eventHandler; + bool m_asyncWindow; bool m_closed; bool m_closeOnQuit; bool m_eventPolling; bool m_ownsWindow; + bool m_waitForEvent; }; } diff --git a/include/Nazara/Utility/Window.inl b/include/Nazara/Utility/Window.inl index 08b23fc04..cceefebef 100644 --- a/include/Nazara/Utility/Window.inl +++ b/include/Nazara/Utility/Window.inl @@ -4,6 +4,7 @@ #include #include +#include #include namespace Nz @@ -13,11 +14,10 @@ namespace Nz */ inline Window::Window() : m_impl(nullptr), - #if NAZARA_UTILITY_THREADED_WINDOW - m_waitForEvent(false), - #endif + m_asyncWindow(false), m_closeOnQuit(true), - m_eventPolling(false) + m_eventPolling(false), + m_waitForEvent(false) { } @@ -41,16 +41,16 @@ namespace Nz inline Window::Window(Window&& window) noexcept : m_impl(window.m_impl), m_events(std::move(window.m_events)), - #if NAZARA_UTILITY_THREADED_WINDOW + m_pendingEvents(std::move(window.m_pendingEvents)), m_eventCondition(std::move(window.m_eventCondition)), + m_eventHandler(std::move(window.m_eventHandler)), m_eventMutex(std::move(window.m_eventMutex)), m_eventConditionMutex(std::move(window.m_eventConditionMutex)), - m_waitForEvent(window.m_waitForEvent), - #endif m_closed(window.m_closed), m_closeOnQuit(window.m_closeOnQuit), m_eventPolling(window.m_eventPolling), - m_ownsWindow(window.m_ownsWindow) + m_ownsWindow(window.m_ownsWindow), + m_waitForEvent(window.m_waitForEvent) { window.m_impl = nullptr; } @@ -104,12 +104,8 @@ namespace Nz return m_impl != nullptr; } - inline void Window::PushEvent(const WindowEvent& event) + inline void Window::HandleEvent(const WindowEvent& event) { - #if NAZARA_UTILITY_THREADED_WINDOW - m_eventMutex.Lock(); - #endif - if (m_eventPolling) m_events.push(event); @@ -120,17 +116,27 @@ namespace Nz if (event.type == WindowEventType_Quit && m_closeOnQuit) Close(); + } - #if NAZARA_UTILITY_THREADED_WINDOW - m_eventMutex.Unlock(); - - if (m_waitForEvent) + inline void Window::PushEvent(const WindowEvent& event) + { + if (!m_asyncWindow) + HandleEvent(event); + else { - m_eventConditionMutex.Lock(); - m_eventCondition.Signal(); - m_eventConditionMutex.Unlock(); + { + LockGuard eventLock(m_eventMutex); + + m_pendingEvents.push_back(event); + } + + if (m_waitForEvent) + { + m_eventConditionMutex.Lock(); + m_eventCondition.Signal(); + m_eventConditionMutex.Unlock(); + } } - #endif } /*! @@ -141,22 +147,21 @@ namespace Nz { Destroy(); - m_closed = window.m_closed; - m_closeOnQuit = window.m_closeOnQuit; - m_eventPolling = window.m_eventPolling; - m_impl = window.m_impl; - m_events = std::move(window.m_events); - m_ownsWindow = window.m_ownsWindow; + m_closed = window.m_closed; + m_closeOnQuit = window.m_closeOnQuit; + m_eventCondition = std::move(window.m_eventCondition); + m_eventConditionMutex = std::move(window.m_eventConditionMutex); + m_eventHandler = std::move(window.m_eventHandler); + m_eventMutex = std::move(window.m_eventMutex); + m_eventPolling = window.m_eventPolling; + m_impl = window.m_impl; + m_events = std::move(window.m_events); + m_pendingEvents = std::move(window.m_pendingEvents); + m_ownsWindow = window.m_ownsWindow; + m_waitForEvent = window.m_waitForEvent; window.m_impl = nullptr; - #if NAZARA_UTILITY_THREADED_WINDOW - m_eventCondition = std::move(window.m_eventCondition); - m_eventMutex = std::move(window.m_eventMutex); - m_eventConditionMutex = std::move(window.m_eventConditionMutex); - m_waitForEvent = window.m_waitForEvent; - #endif - return *this; } } diff --git a/src/Nazara/Audio/Music.cpp b/src/Nazara/Audio/Music.cpp index 1f0df6ba5..dfbb516e4 100644 --- a/src/Nazara/Audio/Music.cpp +++ b/src/Nazara/Audio/Music.cpp @@ -61,8 +61,6 @@ namespace Nz * \return true if creation was succesful * * \param soundStream Sound stream which is the source for the music - * - * \remark Produces a NazaraError if soundStream is invalid with NAZARA_AUDIO_SAFE defined */ bool Music::Create(SoundStream* soundStream) @@ -86,8 +84,9 @@ namespace Nz /*! * \brief Destroys the current music and frees resources + * + * \remark If the Music is playing, it is stopped first. */ - void Music::Destroy() { if (m_impl) @@ -104,18 +103,11 @@ namespace Nz * * \param loop Should music loop * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - void Music::EnableLooping(bool loop) { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return; - } - #endif + NazaraAssert(m_impl, "Music not created"); m_impl->loop = loop; } @@ -124,18 +116,11 @@ namespace Nz * \brief Gets the duration of the music * \return Duration of the music in milliseconds * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - UInt32 Music::GetDuration() const { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return 0; - } - #endif + NazaraAssert(m_impl, "Music not created"); return m_impl->stream->GetDuration(); } @@ -144,18 +129,11 @@ namespace Nz * \brief Gets the format of the music * \return Enumeration of type AudioFormat (mono, stereo, ...) * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - AudioFormat Music::GetFormat() const { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return AudioFormat_Unknown; - } - #endif + NazaraAssert(m_impl, "Music not created"); return m_impl->stream->GetFormat(); } @@ -164,7 +142,7 @@ namespace Nz * \brief Gets the current offset in the music * \return Offset in milliseconds (works with entire seconds) * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ UInt32 Music::GetPlayingOffset() const { @@ -183,7 +161,7 @@ namespace Nz * \brief Gets the number of samples in the music * \return Count of samples (number of seconds * sample rate * channel count) * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ UInt64 Music::GetSampleCount() const { @@ -196,7 +174,7 @@ namespace Nz * \brief Gets the rates of sample in the music * \return Rate of sample in Hertz (Hz) * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ UInt32 Music::GetSampleRate() const { @@ -209,8 +187,7 @@ namespace Nz * \brief Gets the status of the music * \return Enumeration of type SoundStatus (Playing, Stopped, ...) * - * \remark If the music is not playing, Stopped is returned - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ SoundStatus Music::GetStatus() const { @@ -229,44 +206,37 @@ namespace Nz * \brief Checks whether the music is looping * \return true if it is the case * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - bool Music::IsLooping() const { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return false; - } - #endif + NazaraAssert(m_impl, "Music not created"); return m_impl->loop; } /*! - * \brief Loads the music from file - * \return true if loading is successful + * \brief Opens the music from a file + * \return true if the file was successfully opened * * \param filePath Path to the file * \param params Parameters for the music */ - bool Music::OpenFromFile(const String& filePath, const MusicParams& params) { return MusicLoader::LoadFromFile(this, filePath, params); } /*! - * \brief Loads the music from memory + * \brief Opens the music from memory * \return true if loading is successful * * \param data Raw memory * \param size Size of the memory * \param params Parameters for the music + * + * \remark The memory pointer must stay valid (accessible) as long as the music is playing */ - bool Music::OpenFromMemory(const void* data, std::size_t size, const MusicParams& params) { return MusicLoader::LoadFromMemory(this, data, size, params); @@ -278,8 +248,9 @@ namespace Nz * * \param stream Stream to the music * \param params Parameters for the music + * + * \remark The stream must stay valid as long as the music is playing */ - bool Music::OpenFromStream(Stream& stream, const MusicParams& params) { return MusicLoader::LoadFromStream(this, stream, params); @@ -287,8 +258,9 @@ namespace Nz /*! * \brief Pauses the music + * + * \remark Music must be valid when calling this function */ - void Music::Pause() { alSourcePause(m_source); @@ -297,18 +269,16 @@ namespace Nz /*! * \brief Plays the music * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * Plays/Resume the music. + * If the music is currently playing, resets the playing offset to the beginning offset. + * If the music is currently paused, resumes the playing. + * If the music is currently stopped, starts the playing at the previously set playing offset. + * + * \remark Music must be valid when calling this function */ - void Music::Play() { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return; - } - #endif + NazaraAssert(m_impl, "Music not created"); // Maybe we are already playing if (m_impl->streaming) @@ -336,25 +306,20 @@ namespace Nz } /*! - * \brief Sets the playing offset for the music + * \brief Changes the playing offset of the music * - * \param offset Offset in the music in milliseconds + * If the music is not playing, this sets the playing offset for the next Play call * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \param offset The offset in milliseconds + * + * \remark Music must be valid when calling this function */ - void Music::SetPlayingOffset(UInt32 offset) { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return; - } - #endif + NazaraAssert(m_impl, "Music not created"); bool isPlaying = m_impl->streaming; - + if (isPlaying) Stop(); @@ -368,18 +333,11 @@ namespace Nz /*! * \brief Stops the music * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - void Music::Stop() { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return; - } - #endif + NazaraAssert(m_impl, "Music not created"); if (m_impl->streaming) { @@ -388,13 +346,6 @@ namespace Nz } } - /*! - * \brief Fills the buffer and queues it up - * \return true if operation was successful - * - * \param buffer Index of the buffer - */ - bool Music::FillAndQueueBuffer(unsigned int buffer) { std::size_t sampleCount = m_impl->chunkSamples.size(); @@ -425,10 +376,6 @@ namespace Nz return sampleRead != sampleCount; // End of stream (Does not happen when looping) } - /*! - * \brief Thread function for the music - */ - void Music::MusicThread() { // Allocation of streaming buffers @@ -463,11 +410,11 @@ namespace Nz { ALuint buffer; alSourceUnqueueBuffers(m_source, 1, &buffer); - + ALint bits, size; alGetBufferi(buffer, AL_BITS, &bits); alGetBufferi(buffer, AL_SIZE, &size); - + if (bits != 0) m_impl->processedSamples += (8 * size) / bits; diff --git a/src/Nazara/Core/ByteArray.cpp b/src/Nazara/Core/ByteArray.cpp index e505f13f2..592170e40 100644 --- a/src/Nazara/Core/ByteArray.cpp +++ b/src/Nazara/Core/ByteArray.cpp @@ -15,6 +15,22 @@ namespace Nz * \brief Core class that represents an array of bytes */ + /*! + * \brief Gives a string representation in base 16 + * \return String in base 16 + */ + + String ByteArray::ToHex() const + { + std::size_t length = m_array.size() * 2; + + String hexOutput(length, '\0'); + for (std::size_t i = 0; i < m_array.size(); ++i) + std::sprintf(&hexOutput[i * 2], "%02x", m_array[i]); + + return hexOutput; + } + /*! * \brief Output operator * \return The stream diff --git a/src/Nazara/Graphics/DeferredGeometryPass.cpp b/src/Nazara/Graphics/DeferredGeometryPass.cpp index 79e651926..e95bf250b 100644 --- a/src/Nazara/Graphics/DeferredGeometryPass.cpp +++ b/src/Nazara/Graphics/DeferredGeometryPass.cpp @@ -159,13 +159,13 @@ namespace Nz instanceBuffer->SetVertexDeclaration(VertexDeclaration::Get(VertexLayout_Matrix4)); const Matrix4f* instanceMatrices = &instances[0]; - unsigned int instanceCount = instances.size(); - unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // The number of matrices that can be hold in the buffer + std::size_t instanceCount = instances.size(); + std::size_t maxInstanceCount = instanceBuffer->GetVertexCount(); // The number of matrices that can be hold in the buffer while (instanceCount > 0) { // We compute the number of instances that we will be able to show this time (Depending on the instance buffer size) - unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount); + std::size_t renderedInstanceCount = std::min(instanceCount, maxInstanceCount); instanceCount -= renderedInstanceCount; // We fill the instancing buffer with our world matrices diff --git a/src/Nazara/Graphics/DepthRenderTechnique.cpp b/src/Nazara/Graphics/DepthRenderTechnique.cpp index bcae2eb57..60d344fb7 100644 --- a/src/Nazara/Graphics/DepthRenderTechnique.cpp +++ b/src/Nazara/Graphics/DepthRenderTechnique.cpp @@ -267,13 +267,13 @@ namespace Nz const Texture* overlay = overlayIt.first; auto& spriteChainVector = overlayIt.second.spriteChains; - unsigned int spriteChainCount = spriteChainVector.size(); + std::size_t spriteChainCount = spriteChainVector.size(); if (spriteChainCount > 0) { Renderer::SetTexture(overlayUnit, (overlay) ? overlay : &m_whiteTexture); - unsigned int spriteChain = 0; // Which chain of sprites are we treating - unsigned int spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain + std::size_t spriteChain = 0; // Which chain of sprites are we treating + std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain do { @@ -281,13 +281,13 @@ namespace Nz BufferMapper vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite); VertexStruct_XYZ_Color_UV* vertices = static_cast(vertexMapper.GetPointer()); - unsigned int spriteCount = 0; - unsigned int maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4); + std::size_t spriteCount = 0; + std::size_t maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4); do { ForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain]; - unsigned int count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset); + std::size_t count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset); std::memcpy(vertices, currentChain.vertices + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV)); vertices += count * 4; @@ -373,17 +373,17 @@ namespace Nz auto& entry = matIt.second; auto& billboardVector = entry.billboards; - unsigned int billboardCount = billboardVector.size(); + std::size_t billboardCount = billboardVector.size(); if (billboardCount > 0) { // We begin to apply the material (and get the shader activated doing so) material->Apply(pipelineInstance); const ForwardRenderQueue::BillboardData* data = &billboardVector[0]; - unsigned int maxBillboardPerDraw = instanceBuffer->GetVertexCount(); + std::size_t maxBillboardPerDraw = instanceBuffer->GetVertexCount(); do { - unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); + std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); billboardCount -= renderedBillboardCount; instanceBuffer->Fill(data, 0, renderedBillboardCount, true); @@ -435,12 +435,12 @@ namespace Nz auto& billboardVector = entry.billboards; const ForwardRenderQueue::BillboardData* data = &billboardVector[0]; - unsigned int maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4); + std::size_t maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4); - unsigned int billboardCount = billboardVector.size(); + std::size_t billboardCount = billboardVector.size(); do { - unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); + std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); billboardCount -= renderedBillboardCount; BufferMapper vertexMapper(m_billboardPointBuffer, BufferAccess_DiscardAndWrite, 0, renderedBillboardCount * 4); @@ -584,13 +584,13 @@ namespace Nz instanceBuffer->SetVertexDeclaration(VertexDeclaration::Get(VertexLayout_Matrix4)); const Matrix4f* instanceMatrices = &instances[0]; - unsigned int instanceCount = instances.size(); - unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch + std::size_t instanceCount = instances.size(); + std::size_t maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch while (instanceCount > 0) { // We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size) - unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount); + std::size_t renderedInstanceCount = std::min(instanceCount, maxInstanceCount); instanceCount -= renderedInstanceCount; // We fill the instancing buffer with our world matrices diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index a7b94a0cb..6c6915214 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -383,7 +383,7 @@ namespace Nz auto& transparentModelData = currentLayer.transparentModelData; // The material is transparent, we must draw this mesh using another way (after the rendering of opages objects while sorting them) - unsigned int index = transparentModelData.size(); + std::size_t index = transparentModelData.size(); transparentModelData.resize(index+1); TransparentModelData& data = transparentModelData.back(); @@ -621,7 +621,7 @@ namespace Nz { Layer& layer = pair.second; - std::sort(layer.transparentModels.begin(), layer.transparentModels.end(), [&layer, &nearPlane, &viewerNormal] (unsigned int index1, unsigned int index2) + std::sort(layer.transparentModels.begin(), layer.transparentModels.end(), [&layer, &nearPlane, &viewerNormal] (std::size_t index1, std::size_t index2) { const Spheref& sphere1 = layer.transparentModelData[index1].squaredBoundingSphere; const Spheref& sphere2 = layer.transparentModelData[index2].squaredBoundingSphere; @@ -690,7 +690,7 @@ namespace Nz BatchedBillboardEntry& entry = it->second; auto& billboardVector = entry.billboards; - unsigned int prevSize = billboardVector.size(); + std::size_t prevSize = billboardVector.size(); billboardVector.resize(prevSize + count); return &billboardVector[prevSize]; diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 3eda7d462..76541c982 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -33,8 +33,8 @@ namespace Nz Vector2f uv; }; - unsigned int s_maxQuads = std::numeric_limits::max() / 6; - unsigned int s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB + std::size_t s_maxQuads = std::numeric_limits::max() / 6; + std::size_t s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB } /*! @@ -347,13 +347,13 @@ namespace Nz const Texture* overlay = overlayIt.first; auto& spriteChainVector = overlayIt.second.spriteChains; - unsigned int spriteChainCount = spriteChainVector.size(); + std::size_t spriteChainCount = spriteChainVector.size(); if (spriteChainCount > 0) { Renderer::SetTexture(overlayUnit, (overlay) ? overlay : &m_whiteTexture); - unsigned int spriteChain = 0; // Which chain of sprites are we treating - unsigned int spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain + std::size_t spriteChain = 0; // Which chain of sprites are we treating + std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain do { @@ -361,13 +361,13 @@ namespace Nz BufferMapper vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite); VertexStruct_XYZ_Color_UV* vertices = static_cast(vertexMapper.GetPointer()); - unsigned int spriteCount = 0; - unsigned int maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4); + std::size_t spriteCount = 0; + std::size_t maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4); do { ForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain]; - unsigned int count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset); + std::size_t count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset); std::memcpy(vertices, currentChain.vertices + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV)); vertices += count * 4; @@ -450,17 +450,17 @@ namespace Nz auto& entry = matIt.second; auto& billboardVector = entry.billboards; - unsigned int billboardCount = billboardVector.size(); + std::size_t billboardCount = billboardVector.size(); if (billboardCount > 0) { // We begin to apply the material (and get the shader activated doing so) material->Apply(pipelineInstance); const ForwardRenderQueue::BillboardData* data = &billboardVector[0]; - unsigned int maxBillboardPerDraw = instanceBuffer->GetVertexCount(); + std::size_t maxBillboardPerDraw = instanceBuffer->GetVertexCount(); do { - unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); + std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); billboardCount -= renderedBillboardCount; instanceBuffer->Fill(data, 0, renderedBillboardCount, true); @@ -512,12 +512,12 @@ namespace Nz auto& billboardVector = entry.billboards; const ForwardRenderQueue::BillboardData* data = &billboardVector[0]; - unsigned int maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4); + std::size_t maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4); - unsigned int billboardCount = billboardVector.size(); + std::size_t billboardCount = billboardVector.size(); do { - unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); + std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw); billboardCount -= renderedBillboardCount; BufferMapper vertexMapper(m_billboardPointBuffer, BufferAccess_DiscardAndWrite, 0, renderedBillboardCount * 4); @@ -664,16 +664,16 @@ namespace Nz // With instancing, impossible to select the lights for each object // So, it's only activated for directional lights - unsigned int lightCount = m_renderQueue.directionalLights.size(); - unsigned int lightIndex = 0; + std::size_t lightCount = m_renderQueue.directionalLights.size(); + std::size_t lightIndex = 0; RendererComparison oldDepthFunc = Renderer::GetDepthFunc(); - unsigned int passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1; - for (unsigned int pass = 0; pass < passCount; ++pass) + std::size_t passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1; + for (std::size_t pass = 0; pass < passCount; ++pass) { if (shaderUniforms->hasLightUniforms) { - unsigned int renderedLightCount = std::min(lightCount, NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U)); + std::size_t renderedLightCount = std::min(lightCount, NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS); lightCount -= renderedLightCount; if (pass == 1) @@ -688,18 +688,18 @@ namespace Nz } // Sends the uniforms - for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) + for (std::size_t i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset * i, freeTextureUnit + i); } const Matrix4f* instanceMatrices = &instances[0]; - unsigned int instanceCount = instances.size(); - unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch + std::size_t instanceCount = instances.size(); + std::size_t maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch while (instanceCount > 0) { // We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size) - unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount); + std::size_t renderedInstanceCount = std::min(instanceCount, maxInstanceCount); instanceCount -= renderedInstanceCount; // We fill the instancing buffer with our world matrices @@ -724,16 +724,16 @@ namespace Nz // Choose the lights depending on an object position and apparent radius ChooseLights(Spheref(matrix.GetTranslation() + squaredBoundingSphere.GetPosition(), squaredBoundingSphere.radius)); - unsigned int lightCount = m_lights.size(); + std::size_t lightCount = m_lights.size(); Renderer::SetMatrix(MatrixType_World, matrix); - unsigned int lightIndex = 0; + std::size_t lightIndex = 0; RendererComparison oldDepthFunc = Renderer::GetDepthFunc(); // In the case where we have to change it - unsigned int passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1; - for (unsigned int pass = 0; pass < passCount; ++pass) + std::size_t passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1; + for (std::size_t pass = 0; pass < passCount; ++pass) { - lightCount -= std::min(lightCount, NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U)); + lightCount -= std::min(lightCount, NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS); if (pass == 1) { @@ -747,7 +747,7 @@ namespace Nz } // Sends the light uniforms to the shader - for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) + for (std::size_t i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset*i, freeTextureUnit + i); // And we draw @@ -832,7 +832,7 @@ namespace Nz { lightCount = std::min(m_renderQueue.directionalLights.size(), static_cast(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS)); - for (unsigned int i = 0; i < lightCount; ++i) + for (std::size_t i = 0; i < lightCount; ++i) SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset * i, freeTextureUnit++); } @@ -871,7 +871,7 @@ namespace Nz float radius = modelData.squaredBoundingSphere.radius; ChooseLights(Spheref(position, radius), false); - for (unsigned int i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) + for (std::size_t i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset*i, freeTextureUnit++); } diff --git a/src/Nazara/Graphics/ParticleDeclaration.cpp b/src/Nazara/Graphics/ParticleDeclaration.cpp index ebd84e95d..60786c1f1 100644 --- a/src/Nazara/Graphics/ParticleDeclaration.cpp +++ b/src/Nazara/Graphics/ParticleDeclaration.cpp @@ -100,7 +100,7 @@ namespace Nz * \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if type is not supported */ - void ParticleDeclaration::EnableComponent(ParticleComponent component, ComponentType type, unsigned int offset) + void ParticleDeclaration::EnableComponent(ParticleComponent component, ComponentType type, std::size_t offset) { #ifdef NAZARA_DEBUG if (component > ParticleComponent_Max) @@ -145,7 +145,7 @@ namespace Nz * \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if enumeration is equal to ParticleComponent_Unused */ - void ParticleDeclaration::GetComponent(ParticleComponent component, bool* enabled, ComponentType* type, unsigned int* offset) const + void ParticleDeclaration::GetComponent(ParticleComponent component, bool* enabled, ComponentType* type, std::size_t* offset) const { #ifdef NAZARA_DEBUG if (component > ParticleComponent_Max) @@ -180,7 +180,7 @@ namespace Nz * \return Stride of the declaration */ - unsigned int ParticleDeclaration::GetStride() const + std::size_t ParticleDeclaration::GetStride() const { return m_stride; } diff --git a/src/Nazara/Graphics/ParticleEmitter.cpp b/src/Nazara/Graphics/ParticleEmitter.cpp index fe27575e7..038e69ce9 100644 --- a/src/Nazara/Graphics/ParticleEmitter.cpp +++ b/src/Nazara/Graphics/ParticleEmitter.cpp @@ -74,11 +74,11 @@ namespace Nz if (emissionCount >= 1.f) { // We compute the maximum number of particles which can be emitted - unsigned int emissionCountInt = static_cast(emissionCount); - unsigned int maxParticleCount = emissionCountInt * m_emissionCount; + std::size_t emissionCountInt = static_cast(emissionCount); + std::size_t maxParticleCount = emissionCountInt * m_emissionCount; // We get the number of particles that we are able to create (depending on the free space) - unsigned int particleCount = std::min(maxParticleCount, system.GetMaxParticleCount() - system.GetParticleCount()); + std::size_t particleCount = std::min(maxParticleCount, system.GetMaxParticleCount() - system.GetParticleCount()); if (particleCount == 0) return; @@ -115,7 +115,7 @@ namespace Nz * \return Current emission count */ - unsigned int ParticleEmitter::GetEmissionCount() const + std::size_t ParticleEmitter::GetEmissionCount() const { return m_emissionCount; } @@ -146,7 +146,7 @@ namespace Nz * \param count Emission count */ - void ParticleEmitter::SetEmissionCount(unsigned int count) + void ParticleEmitter::SetEmissionCount(std::size_t count) { m_emissionCount = count; } diff --git a/src/Nazara/Graphics/ParticleGroup.cpp b/src/Nazara/Graphics/ParticleGroup.cpp index 5aca6c2b4..f2c46d91c 100644 --- a/src/Nazara/Graphics/ParticleGroup.cpp +++ b/src/Nazara/Graphics/ParticleGroup.cpp @@ -142,11 +142,10 @@ namespace Nz * \remark Produces a NazaraAssert if renderQueue is invalid */ - void ParticleGroup::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix) const + void ParticleGroup::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& /*transformMatrix*/) const { NazaraAssert(m_renderer, "Invalid particle renderer"); NazaraAssert(renderQueue, "Invalid renderqueue"); - NazaraUnused(transformMatrix); if (m_particleCount > 0) { @@ -215,7 +214,7 @@ namespace Nz if (m_particleCount + count > m_maxParticleCount) return nullptr; - unsigned int particlesIndex = m_particleCount; + std::size_t particlesIndex = m_particleCount; m_particleCount += count; return &m_buffer[particlesIndex * m_particleSize]; @@ -264,7 +263,7 @@ namespace Nz * \return Current maximum number */ - unsigned int ParticleGroup::GetMaxParticleCount() const + std::size_t ParticleGroup::GetMaxParticleCount() const { return m_maxParticleCount; } @@ -274,7 +273,7 @@ namespace Nz * \return Current number */ - unsigned int ParticleGroup::GetParticleCount() const + std::size_t ParticleGroup::GetParticleCount() const { return m_particleCount; } @@ -284,7 +283,7 @@ namespace Nz * \return Current size */ - unsigned int ParticleGroup::GetParticleSize() const + std::size_t ParticleGroup::GetParticleSize() const { return m_particleSize; } @@ -295,7 +294,7 @@ namespace Nz * \param index Index of the particle */ - void ParticleGroup::KillParticle(unsigned int index) + void ParticleGroup::KillParticle(std::size_t index) { ///FIXME: Verify the index @@ -402,10 +401,8 @@ namespace Nz * \param transformMatrix Matrix transformation for our bounding volume */ - void ParticleGroup::UpdateBoundingVolume(const Matrix4f& transformMatrix) + void ParticleGroup::UpdateBoundingVolume(const Matrix4f& /*transformMatrix*/) { - NazaraUnused(transformMatrix); - // Nothing to do here (our bounding volume is global) } diff --git a/src/Nazara/Graphics/RenderTechniques.cpp b/src/Nazara/Graphics/RenderTechniques.cpp index 46d84d9c4..8298245b7 100644 --- a/src/Nazara/Graphics/RenderTechniques.cpp +++ b/src/Nazara/Graphics/RenderTechniques.cpp @@ -170,7 +170,7 @@ namespace Nz * \return Number of techniques */ - unsigned int RenderTechniques::GetCount() + std::size_t RenderTechniques::GetCount() { return s_renderTechniques.size(); } diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index 1b14ab6de..d23fe4122 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -44,6 +44,64 @@ namespace Nz m_boundingVolume.Set(-origin, m_size.x*Vector3f::Right() + m_size.y*Vector3f::Down() - origin); } + /*! + * \brief Sets the material of the sprite from a name + * + * Tries to get a material from the MaterialLibrary and then the MaterialManager (which will treat the name as a path) + * Fails if the texture name is not a part of the MaterialLibrary nor the MaterialManager (which fails if it couldn't load the texture from its filepath) + * + * \param materialName Named texture for the material + * \param resizeSprite Should the sprite be resized to the material diffuse map size? + * + * \return True if the material was found or loaded from its name/path, false if it couldn't + */ + bool Sprite::SetMaterial(String materialName, bool resizeSprite) + { + MaterialRef material = MaterialLibrary::Query(materialName); + if (!material) + { + material = MaterialManager::Get(materialName); + if (!material) + { + NazaraError("Failed to get material \"" + materialName + "\""); + return false; + } + } + + SetMaterial(std::move(material), resizeSprite); + return true; + } + + /*! + * \brief Sets the texture of the sprite from a name + * + * Tries to get a texture from the TextureLibrary and then the TextureManager (which will treat the name as a path) + * Fails if the texture name is not a part of the TextureLibrary nor the TextureManager (which fails if it couldn't load the texture from its filepath) + * + * \param textureName Named texture for the sprite + * \param resizeSprite Should the sprite be resized to the texture size? + * + * \return True if the texture was found or loaded from its name/path, false if it couldn't + * + * \remark The sprite material gets copied to prevent accidentally changing other drawable materials + */ + bool Sprite::SetTexture(String textureName, bool resizeSprite) + { + TextureRef texture = TextureLibrary::Query(textureName); + if (!texture) + { + texture = TextureManager::Get(textureName); + if (!texture) + { + NazaraError("Failed to get texture \"" + textureName + "\""); + return false; + } + } + + SetTexture(std::move(texture), resizeSprite); + return true; + } + /*! * \brief Updates the data of the sprite * diff --git a/src/Nazara/Physics2D/Collider2D.cpp b/src/Nazara/Physics2D/Collider2D.cpp index a840393e8..986a03ccf 100644 --- a/src/Nazara/Physics2D/Collider2D.cpp +++ b/src/Nazara/Physics2D/Collider2D.cpp @@ -10,7 +10,7 @@ namespace Nz { Collider2D::~Collider2D() = default; - + /******************************** BoxCollider2D *********************************/ BoxCollider2D::BoxCollider2D(const Vector2f& size, float radius) : @@ -84,4 +84,25 @@ namespace Nz { return std::vector(); } + + /******************************** SegmentCollider2D *********************************/ + + float SegmentCollider2D::ComputeInertialMatrix(float mass) const + { + return static_cast(cpMomentForSegment(mass, cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness)); + } + + ColliderType2D SegmentCollider2D::GetType() const + { + return ColliderType2D_Segment; + } + + std::vector SegmentCollider2D::CreateShapes(RigidBody2D* body) 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/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index 5290abfcd..878a84400 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -24,7 +24,7 @@ namespace Nz Vector2f PhysWorld2D::GetGravity() const { cpVect gravity = cpSpaceGetGravity(m_handle); - return Vector2f(gravity.x, gravity.y); + return Vector2f(Vector2(gravity.x, gravity.y)); } cpSpace* PhysWorld2D::GetHandle() const diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index faa6223d1..9fdb34d50 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -22,13 +22,11 @@ namespace Nz m_geom(), m_world(world), m_gravityFactor(1.f), - m_mass(0.f) + m_mass(1.f) { NazaraAssert(m_world, "Invalid world"); - m_handle = cpBodyNew(0.f, 0.f); - cpBodySetUserData(m_handle, this); - cpSpaceAddBody(m_world->GetHandle(), m_handle); + Create(); SetGeom(geom); SetMass(mass); @@ -43,9 +41,7 @@ namespace Nz NazaraAssert(m_world, "Invalid world"); NazaraAssert(m_geom, "Invalid geometry"); - m_handle = cpBodyNew(0.f, 0.f); - cpBodySetUserData(m_handle, this); - cpSpaceAddBody(m_world->GetHandle(), m_handle); + Create(); SetGeom(object.GetGeom()); SetMass(object.GetMass()); @@ -77,7 +73,7 @@ namespace Nz switch (coordSys) { case CoordSys_Global: - cpBodyApplyForceAtWorldPoint(m_handle, cpv(force.x, force.y), cpv(force.x, force.y)); + cpBodyApplyForceAtWorldPoint(m_handle, cpv(force.x, force.y), cpv(point.x, point.y)); break; case CoordSys_Local: @@ -169,19 +165,60 @@ namespace Nz cpBodySetAngularVelocity(m_handle, angularVelocity); } + void RigidBody2D::SetGeom(Collider2DRef geom) + { + // We have no public way of getting rid of an existing geom without removing the whole body + // So let's save some attributes of the body, destroy it and rebuild it + if (m_geom) + { + cpVect pos = cpBodyGetPosition(m_handle); + cpFloat mass = cpBodyGetMass(m_handle); + cpFloat moment = cpBodyGetMoment(m_handle); + cpFloat rot = cpBodyGetAngle(m_handle); + cpVect vel = cpBodyGetVelocity(m_handle); + + Destroy(); + Create(mass, moment); + + cpBodySetAngle(m_handle, rot); + cpBodySetPosition(m_handle, pos); + cpBodySetVelocity(m_handle, vel); + } + + if (geom) + m_geom = geom; + else + m_geom = NullCollider2D::New(); + + m_shapes = m_geom->CreateShapes(this); + + cpSpace* space = m_world->GetHandle(); + for (cpShape* shape : m_shapes) + cpSpaceAddShape(space, shape); + + cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + } + void RigidBody2D::SetMass(float mass) { if (m_mass > 0.f) { if (mass > 0.f) + { cpBodySetMass(m_handle, mass); + cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + } else cpBodySetType(m_handle, CP_BODY_TYPE_STATIC); } else if (mass > 0.f) { if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC) + { cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC); + cpBodySetMass(m_handle, mass); + cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); + } } m_mass = mass; @@ -196,6 +233,8 @@ namespace Nz void RigidBody2D::SetPosition(const Vector2f& position) { cpBodySetPosition(m_handle, cpv(position.x, position.y)); + if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC) + cpSpaceReindexShapesForBody(m_world->GetHandle(), m_handle); } void RigidBody2D::SetRotation(float rotation) @@ -230,22 +269,26 @@ namespace Nz return *this; } + void RigidBody2D::Create(float mass, float moment) + { + m_handle = cpBodyNew(mass, moment); + cpBodySetUserData(m_handle, this); + cpSpaceAddBody(m_world->GetHandle(), m_handle); + } + void RigidBody2D::Destroy() { + cpSpace* space = m_world->GetHandle(); for (cpShape* shape : m_shapes) + { + cpSpaceRemoveShape(space, shape); cpShapeFree(shape); + } if (m_handle) + { + cpSpaceRemoveBody(space, m_handle); cpBodyFree(m_handle); - } - - void RigidBody2D::SetGeom(Collider2DRef geom) - { - if (geom) - m_geom = geom; - else - m_geom = NullCollider2D::New(); - - m_shapes = m_geom->CreateShapes(this); + } } } diff --git a/src/Nazara/Utility/AlgorithmUtility.cpp b/src/Nazara/Utility/AlgorithmUtility.cpp index d82af98af..90a3d53e3 100644 --- a/src/Nazara/Utility/AlgorithmUtility.cpp +++ b/src/Nazara/Utility/AlgorithmUtility.cpp @@ -742,7 +742,7 @@ namespace Nz Vector3f halfLengths = lengths/2.f; // Face +X - transform.MakeTransform(Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, 0.f, -90.f)); + transform.MakeTransform(Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, -90.f, 180.f)); GeneratePlane(Vector2ui(subdivision.z, subdivision.y), Vector2f(lengths.z, lengths.y), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += xVertexCount; indices += xIndexCount; @@ -776,7 +776,7 @@ namespace Nz vertexPointers.uvPtr += yVertexCount; // Face +Z - transform.MakeTransform(Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(-90.f, 90.f, 90.f)); + transform.MakeTransform(Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(90.f, 0.f, 0.f)); GeneratePlane(Vector2ui(subdivision.x, subdivision.y), Vector2f(lengths.x, lengths.y), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += zVertexCount; indices += zIndexCount; @@ -793,7 +793,7 @@ namespace Nz vertexPointers.uvPtr += zVertexCount; // Face -X - transform.MakeTransform(-Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, 0.f, 90.f)); + transform.MakeTransform(-Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, 90.f, 180.f)); GeneratePlane(Vector2ui(subdivision.z, subdivision.y), Vector2f(lengths.z, lengths.y), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += xVertexCount; indices += xIndexCount; @@ -810,7 +810,7 @@ namespace Nz vertexPointers.uvPtr += xVertexCount; // Face -Y - transform.MakeTransform(-Vector3f::UnitY() * halfLengths.y, EulerAnglesf(0.f, 0.f, 180.f)); + transform.MakeTransform(-Vector3f::UnitY() * halfLengths.y, EulerAnglesf(0.f, 180.f, 180.f)); GeneratePlane(Vector2ui(subdivision.x, subdivision.z), Vector2f(lengths.x, lengths.z), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += yVertexCount; indices += yIndexCount; @@ -827,7 +827,7 @@ namespace Nz vertexPointers.uvPtr += yVertexCount; // Face -Z - transform.MakeTransform(-Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(-90.f, -90.f, 90.f)); + transform.MakeTransform(-Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(90.f, 180.f, 0.f)); GeneratePlane(Vector2ui(subdivision.x, subdivision.y), Vector2f(lengths.x, lengths.y), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset); indexOffset += zVertexCount; indices += zIndexCount; diff --git a/src/Nazara/Utility/Formats/DDSLoader.cpp b/src/Nazara/Utility/Formats/DDSLoader.cpp index d9783115b..1e707e610 100644 --- a/src/Nazara/Utility/Formats/DDSLoader.cpp +++ b/src/Nazara/Utility/Formats/DDSLoader.cpp @@ -174,15 +174,15 @@ namespace Nz if (header.format.flags & DDPF_RGB) { // Reverse bits for our masks - info.redMask = ReverseBits(header.format.redMask); - info.greenMask = ReverseBits(header.format.greenMask); - info.blueMask = ReverseBits(header.format.blueMask); + info.redMask = header.format.redMask; + info.greenMask = header.format.greenMask; + info.blueMask = header.format.blueMask; } else if (header.format.flags & DDPF_LUMINANCE) - info.redMask = ReverseBits(header.format.redMask); + info.redMask = header.format.redMask; if (header.format.flags & (DDPF_ALPHA | DDPF_ALPHAPIXELS)) - info.alphaMask = ReverseBits(header.format.alphaMask); + info.alphaMask = header.format.alphaMask; *format = PixelFormat::IdentifyFormat(info); if (!PixelFormat::IsValid(*format)) diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 160c2ac90..39d99cdd1 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -825,6 +825,44 @@ namespace Nz return GetLevelSize(m_sharedImage->width, level); } + bool Image::HasAlpha() const + { + NazaraAssert(m_sharedImage != &emptyImage, "Image must be valid"); + + if (!PixelFormat::HasAlpha(m_sharedImage->format)) + return false; + + if (!PixelFormat::IsCompressed(m_sharedImage->format)) + { + const PixelFormatInfo& info = PixelFormat::GetInfo(m_sharedImage->format); + const UInt8* pixel = GetConstPixels(); + + Bitset<> workingBitset; + std::size_t pixelCount = m_sharedImage->width * m_sharedImage->height * ((m_sharedImage->type == ImageType_Cubemap) ? 6 : m_sharedImage->depth); + if (pixelCount == 0) + return false; + + auto seq = workingBitset.Read(GetConstPixels(), info.bitsPerPixel); + do + { + workingBitset &= info.alphaMask; + if (workingBitset.Count() != info.alphaMask.Count()) //< Means that at least one bit of the alpha mask of this pixel is disabled + return true; + + workingBitset.Clear(); + workingBitset.Read(seq, info.bitsPerPixel); + } + while (--pixelCount > 0); + + return false; + } + else + { + // FIXME: Currently, we assume the pixel format is already the right one + return true; + } + } + bool Image::IsValid() const { return m_sharedImage != &emptyImage; @@ -1441,7 +1479,7 @@ namespace Nz SharedImage::PixelContainer levels(m_sharedImage->levels.size()); for (unsigned int i = 0; i < levels.size(); ++i) { - unsigned int size = GetMemoryUsage(i); + std::size_t size = GetMemoryUsage(i); levels[i].reset(new UInt8[size]); std::memcpy(levels[i].get(), m_sharedImage->levels[i].get(), size); } diff --git a/src/Nazara/Utility/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp index 0bc890340..b196d723a 100644 --- a/src/Nazara/Utility/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -45,7 +45,7 @@ namespace Nz bool VertexBuffer::Fill(const void* data, unsigned int startVertex, unsigned int length, bool forceDiscard) { - unsigned int stride = m_vertexDeclaration->GetStride(); + std::size_t stride = m_vertexDeclaration->GetStride(); return FillRaw(data, startVertex*stride, length*stride, forceDiscard); } diff --git a/src/Nazara/Utility/VideoMode.cpp b/src/Nazara/Utility/VideoMode.cpp index 6313ff460..2c6a2f321 100644 --- a/src/Nazara/Utility/VideoMode.cpp +++ b/src/Nazara/Utility/VideoMode.cpp @@ -24,6 +24,11 @@ namespace Nz width(0) { } + + VideoMode::VideoMode(unsigned int w, unsigned int h) : + VideoMode(w, h, GetDesktopMode().bitsPerPixel) + { + } VideoMode::VideoMode(unsigned int w, unsigned int h, UInt8 bpp) : bitsPerPixel(bpp), diff --git a/src/Nazara/Utility/Win32/WindowImpl.cpp b/src/Nazara/Utility/Win32/WindowImpl.cpp index 0c193cfaa..558a44ddb 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.cpp +++ b/src/Nazara/Utility/Win32/WindowImpl.cpp @@ -83,6 +83,7 @@ namespace Nz bool WindowImpl::Create(const VideoMode& mode, const String& title, UInt32 style) { + bool async = (style & WindowStyle_Threaded) != 0; bool fullscreen = (style & WindowStyle_Fullscreen) != 0; DWORD win32Style, win32StyleEx; unsigned int x, y; @@ -147,19 +148,25 @@ namespace Nz m_callback = 0; - #if NAZARA_UTILITY_THREADED_WINDOW - Mutex mutex; - ConditionVariable condition; - m_threadActive = true; + m_eventListener = true; + m_ownsWindow = true; + m_sizemove = false; + m_style = style; - // On attend que la fenêtre soit créée - mutex.Lock(); - m_thread = Thread(WindowThread, &m_handle, win32StyleEx, title, win32Style, x, y, width, height, this, &mutex, &condition); - condition.Wait(&mutex); - mutex.Unlock(); - #else - m_handle = CreateWindowExW(win32StyleEx, className, title.GetWideString().data(), win32Style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), this); - #endif + if (async) + { + Mutex mutex; + ConditionVariable condition; + m_threadActive = true; + + // On attend que la fenêtre soit créée + mutex.Lock(); + m_thread = Thread(WindowThread, &m_handle, win32StyleEx, title, win32Style, fullscreen, Rectui(x, y, width, height), this, &mutex, &condition); + condition.Wait(&mutex); + mutex.Unlock(); + } + else + m_handle = CreateWindowExW(win32StyleEx, className, title.GetWideString().data(), win32Style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), this); if (!m_handle) { @@ -167,26 +174,8 @@ namespace Nz return false; } - if (fullscreen) - { - SetForegroundWindow(m_handle); - ShowWindow(m_handle, SW_SHOW); - } - - m_eventListener = true; - m_ownsWindow = true; - #if !NAZARA_UTILITY_THREADED_WINDOW - m_sizemove = false; - #endif - m_style = style; - - // Récupération de la position/taille de la fenêtre (Après sa création) - RECT clientRect, windowRect; - GetClientRect(m_handle, &clientRect); - GetWindowRect(m_handle, &windowRect); - - m_position.Set(windowRect.left, windowRect.top); - m_size.Set(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top); + if (!async) + PrepareWindow(fullscreen); return true; } @@ -203,9 +192,7 @@ namespace Nz m_eventListener = false; m_ownsWindow = false; - #if !NAZARA_UTILITY_THREADED_WINDOW m_sizemove = false; - #endif m_style = RetrieveStyle(m_handle); RECT clientRect, windowRect; @@ -222,18 +209,21 @@ namespace Nz { if (m_ownsWindow) { - #if NAZARA_UTILITY_THREADED_WINDOW - if (m_thread.IsJoinable()) + if (m_style & WindowStyle_Threaded) { - m_threadActive = false; - PostMessageW(m_handle, WM_NULL, 0, 0); // Pour réveiller le thread + if (m_thread.IsJoinable()) + { + m_threadActive = false; + PostMessageW(m_handle, WM_NULL, 0, 0); // Wake up our thread - m_thread.Join(); + m_thread.Join(); + } + } + else + { + if (m_handle) + DestroyWindow(m_handle); } - #else - if (m_handle) - DestroyWindow(m_handle); - #endif } else SetEventListener(false); @@ -280,7 +270,7 @@ namespace Nz if (titleSize == 0) return String(); - titleSize++; // Caractère nul + titleSize++; // \0 std::unique_ptr wTitle(new wchar_t[titleSize]); GetWindowTextW(m_handle, wTitle.get(), titleSize); @@ -525,7 +515,6 @@ namespace Nz return true; // Afin que Windows ne ferme pas la fenêtre automatiquement } - #if !NAZARA_UTILITY_THREADED_WINDOW case WM_ENTERSIZEMOVE: { m_sizemove = true; @@ -536,6 +525,10 @@ namespace Nz { m_sizemove = false; + // In case of threaded window, size and move events are not blocked + if (m_style & WindowStyle_Threaded) + break; + // On vérifie ce qui a changé RECT clientRect, windowRect; GetClientRect(m_handle, &clientRect); @@ -565,7 +558,6 @@ namespace Nz m_parent->PushEvent(event); } } - #endif case WM_KEYDOWN: case WM_SYSKEYDOWN: @@ -789,10 +781,8 @@ namespace Nz case WM_MOVE: { - #if !NAZARA_UTILITY_THREADED_WINDOW - if (m_sizemove) + if (m_sizemove && (m_style & WindowStyle_Threaded) == 0) break; - #endif RECT windowRect; GetWindowRect(m_handle, &windowRect); @@ -862,27 +852,26 @@ namespace Nz case WM_SIZE: { - #if NAZARA_UTILITY_THREADED_WINDOW - if (wParam != SIZE_MINIMIZED) - #else - if (!m_sizemove && wParam != SIZE_MINIMIZED) - #endif - { - RECT rect; - GetClientRect(m_handle, &rect); + if (m_sizemove && (m_style & WindowStyle_Threaded) == 0) + break; - Vector2ui size(rect.right-rect.left, rect.bottom-rect.top); // On récupère uniquement la taille de la zone client - if (m_size == size) - break; + if (wParam == SIZE_MINIMIZED) + break; - m_size = size; + RECT rect; + GetClientRect(m_handle, &rect); - WindowEvent event; - event.type = WindowEventType_Resized; - event.size.width = size.x; - event.size.height = size.y; - m_parent->PushEvent(event); - } + Vector2ui size(rect.right-rect.left, rect.bottom-rect.top); // On récupère uniquement la taille de la zone client + if (m_size == size) + break; + + m_size = size; + + WindowEvent event; + event.type = WindowEventType_Resized; + event.size.width = size.x; + event.size.height = size.y; + m_parent->PushEvent(event); break; } @@ -973,6 +962,23 @@ namespace Nz return false; } + void WindowImpl::PrepareWindow(bool fullscreen) + { + if (fullscreen) + { + SetForegroundWindow(m_handle); + ShowWindow(m_handle, SW_SHOW); + } + + // Cache window position/size after creation + RECT clientRect, windowRect; + GetClientRect(m_handle, &clientRect); + GetWindowRect(m_handle, &windowRect); + + m_position.Set(windowRect.left, windowRect.top); + m_size.Set(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top); + } + bool WindowImpl::Initialize() { // Nous devons faire un type Unicode pour que la fenêtre le soit également @@ -1187,15 +1193,17 @@ namespace Nz return style; } - #if NAZARA_UTILITY_THREADED_WINDOW - void WindowImpl::WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, unsigned int x, unsigned int y, unsigned int width, unsigned int height, WindowImpl* window, Mutex* mutex, ConditionVariable* condition) + void WindowImpl::WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition) { HWND& winHandle = *handle; - winHandle = CreateWindowExW(styleEx, className, title.GetWideString().data(), style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), window); + winHandle = CreateWindowExW(styleEx, className, title.GetWideString().data(), style, dimensions.x, dimensions.y, dimensions.width, dimensions.height, nullptr, nullptr, GetModuleHandle(nullptr), window); + + if (winHandle) + window->PrepareWindow(fullscreen); mutex->Lock(); condition->Signal(); - mutex->Unlock(); // mutex et condition sont considérés invalides à partir d'ici + mutex->Unlock(); // mutex and condition may be destroyed after this line if (!winHandle) return; @@ -1205,5 +1213,4 @@ namespace Nz DestroyWindow(winHandle); } -#endif } diff --git a/src/Nazara/Utility/Win32/WindowImpl.hpp b/src/Nazara/Utility/Win32/WindowImpl.hpp index 2e7078b32..bb718738a 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.hpp +++ b/src/Nazara/Utility/Win32/WindowImpl.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -22,10 +23,8 @@ namespace Nz { - #if NAZARA_UTILITY_THREADED_WINDOW class ConditionVariable; class Mutex; - #endif class Window; #undef IsMinimized // Conflit avec la méthode du même nom @@ -84,13 +83,12 @@ namespace Nz private: bool HandleMessage(HWND window, UINT message, WPARAM wParam, LPARAM lParam); + void PrepareWindow(bool fullscreen); static Keyboard::Key ConvertVirtualKey(WPARAM key, LPARAM flags); static LRESULT CALLBACK MessageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam); static UInt32 RetrieveStyle(HWND window); - #if NAZARA_UTILITY_THREADED_WINDOW - static void WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, unsigned int x, unsigned int y, unsigned int width, unsigned int height, WindowImpl* window, Mutex* mutex, ConditionVariable* condition); - #endif + static void WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition); HCURSOR m_cursor; HWND m_handle; @@ -101,21 +99,15 @@ namespace Nz Vector2i m_mousePos; Vector2i m_position; Vector2ui m_size; - #if NAZARA_UTILITY_THREADED_WINDOW Thread m_thread; - #endif Window* m_parent; bool m_eventListener; bool m_keyRepeat; bool m_mouseInside; bool m_ownsWindow; - #if !NAZARA_UTILITY_THREADED_WINDOW bool m_sizemove; - #endif bool m_smoothScrolling; - #if NAZARA_UTILITY_THREADED_WINDOW bool m_threadActive; - #endif short m_scrolling; }; } diff --git a/src/Nazara/Utility/Window.cpp b/src/Nazara/Utility/Window.cpp index 203ad7c71..803badb85 100644 --- a/src/Nazara/Utility/Window.cpp +++ b/src/Nazara/Utility/Window.cpp @@ -66,6 +66,8 @@ namespace Nz else if (style & WindowStyle_Closable || style & WindowStyle_Resizable) style |= WindowStyle_Titlebar; + m_asyncWindow = (style & WindowStyle_Threaded) != 0; + std::unique_ptr impl = std::make_unique(this); if (!impl->Create(mode, title, style)) { @@ -107,6 +109,7 @@ namespace Nz { Destroy(); + m_asyncWindow = false; m_impl = new WindowImpl(this); if (!m_impl->Create(handle)) { @@ -313,11 +316,8 @@ namespace Nz } #endif - #if NAZARA_UTILITY_THREADED_WINDOW - LockGuard lock(m_eventMutex); - #else - m_impl->ProcessEvents(false); - #endif + if (!m_asyncWindow) + m_impl->ProcessEvents(false); if (!m_events.empty()) { @@ -337,9 +337,17 @@ namespace Nz NazaraAssert(m_impl, "Window not created"); NazaraUnused(block); - #if !NAZARA_UTILITY_THREADED_WINDOW - m_impl->ProcessEvents(block); - #endif + if (!m_asyncWindow) + m_impl->ProcessEvents(block); + else + { + LockGuard eventLock(m_eventMutex); + + for (const WindowEvent& event : m_pendingEvents) + HandleEvent(event); + + m_pendingEvents.clear(); + } } void Window::SetCursor(WindowCursor cursor) @@ -384,25 +392,13 @@ namespace Nz } #endif - #if NAZARA_UTILITY_THREADED_WINDOW m_impl->SetEventListener(listener); if (!listener) { - // On vide la pile des évènements - LockGuard lock(m_eventMutex); + // Empty the event queue while (!m_events.empty()) m_events.pop(); } - #else - if (m_ownsWindow) - { - // Inutile de transmettre l'ordre dans ce cas-là - if (!listener) - NazaraError("A non-threaded window needs to listen to events"); - } - else - m_impl->SetEventListener(listener); - #endif } void Window::SetFocus() @@ -590,22 +586,11 @@ namespace Nz } #endif - #if NAZARA_UTILITY_THREADED_WINDOW - LockGuard lock(m_eventMutex); - - if (m_events.empty()) + if (!m_asyncWindow) { - m_waitForEvent = true; - m_eventConditionMutex.Lock(); - m_eventMutex.Unlock(); - m_eventCondition.Wait(&m_eventConditionMutex); - m_eventMutex.Lock(); - m_eventConditionMutex.Unlock(); - m_waitForEvent = false; - } + while (m_events.empty()) + m_impl->ProcessEvents(true); - if (!m_events.empty()) - { if (event) *event = m_events.front(); @@ -613,19 +598,33 @@ namespace Nz return true; } + else + { + LockGuard lock(m_eventMutex); - return false; - #else - while (m_events.empty()) - m_impl->ProcessEvents(true); + if (m_events.empty()) + { + m_waitForEvent = true; + m_eventConditionMutex.Lock(); + m_eventMutex.Unlock(); + m_eventCondition.Wait(&m_eventConditionMutex); + m_eventMutex.Lock(); + m_eventConditionMutex.Unlock(); + m_waitForEvent = false; + } - if (event) - *event = m_events.front(); + if (!m_events.empty()) + { + if (event) + *event = m_events.front(); - m_events.pop(); + m_events.pop(); - return true; - #endif + return true; + } + + return false; + } } bool Window::OnWindowCreated() diff --git a/src/Nazara/Utility/X11/InputImpl.cpp b/src/Nazara/Utility/X11/InputImpl.cpp index e21fdae96..7083100db 100644 --- a/src/Nazara/Utility/X11/InputImpl.cpp +++ b/src/Nazara/Utility/X11/InputImpl.cpp @@ -23,32 +23,32 @@ namespace Nz switch (key) { // Lettres - case Keyboard::A: keysym = XK_A; break; - case Keyboard::B: keysym = XK_B; break; - case Keyboard::C: keysym = XK_C; break; - case Keyboard::D: keysym = XK_D; break; - case Keyboard::E: keysym = XK_E; break; - case Keyboard::F: keysym = XK_F; break; - case Keyboard::G: keysym = XK_G; break; - case Keyboard::H: keysym = XK_H; break; - case Keyboard::I: keysym = XK_I; break; - case Keyboard::J: keysym = XK_J; break; - case Keyboard::K: keysym = XK_K; break; - case Keyboard::L: keysym = XK_L; break; - case Keyboard::M: keysym = XK_M; break; - case Keyboard::N: keysym = XK_N; break; - case Keyboard::O: keysym = XK_O; break; - case Keyboard::P: keysym = XK_P; break; - case Keyboard::Q: keysym = XK_Q; break; - case Keyboard::R: keysym = XK_R; break; - case Keyboard::S: keysym = XK_S; break; - case Keyboard::T: keysym = XK_T; break; - case Keyboard::U: keysym = XK_U; break; - case Keyboard::V: keysym = XK_V; break; - case Keyboard::W: keysym = XK_W; break; - case Keyboard::X: keysym = XK_X; break; - case Keyboard::Y: keysym = XK_Y; break; - case Keyboard::Z: keysym = XK_Z; break; + case Keyboard::A: keysym = XK_a; break; + case Keyboard::B: keysym = XK_b; break; + case Keyboard::C: keysym = XK_c; break; + case Keyboard::D: keysym = XK_d; break; + case Keyboard::E: keysym = XK_e; break; + case Keyboard::F: keysym = XK_f; break; + case Keyboard::G: keysym = XK_g; break; + case Keyboard::H: keysym = XK_h; break; + case Keyboard::I: keysym = XK_i; break; + case Keyboard::J: keysym = XK_j; break; + case Keyboard::K: keysym = XK_k; break; + case Keyboard::L: keysym = XK_l; break; + case Keyboard::M: keysym = XK_m; break; + case Keyboard::N: keysym = XK_n; break; + case Keyboard::O: keysym = XK_o; break; + case Keyboard::P: keysym = XK_p; break; + case Keyboard::Q: keysym = XK_q; break; + case Keyboard::R: keysym = XK_r; break; + case Keyboard::S: keysym = XK_s; break; + case Keyboard::T: keysym = XK_t; break; + case Keyboard::U: keysym = XK_u; break; + case Keyboard::V: keysym = XK_v; break; + case Keyboard::W: keysym = XK_w; break; + case Keyboard::X: keysym = XK_x; break; + case Keyboard::Y: keysym = XK_y; break; + case Keyboard::Z: keysym = XK_z; break; // Touches de fonction case Keyboard::F1: keysym = XK_F1; break; @@ -248,6 +248,8 @@ namespace Nz xcb_keysym_t keySym = GetKeySym(key); + xcb_keycode_t realKeyCode = XCB_NO_SYMBOL; + xcb_key_symbols_t* keySymbols = X11::XCBKeySymbolsAlloc(connection); if (!keySymbols) { @@ -261,6 +263,20 @@ namespace Nz NazaraError("Failed to get key code"); return false; } + + // One keysym is associated with multiple key codes, we have to find the matching one ... + int i = 0; + while (keyCode.get()[i] != XCB_NO_SYMBOL) + { + xcb_keycode_t toTry = keyCode.get()[i]; + if (keySym == xcb_key_symbols_get_keysym(keySymbols, toTry, 0)) + { + realKeyCode = toTry; + break; + } + ++i; + } + X11::XCBKeySymbolsFree(keySymbols); ScopedXCB error(nullptr); @@ -281,7 +297,7 @@ namespace Nz } // Check our keycode - return (keymap->keys[*keyCode.get() / 8] & (1 << (*keyCode.get() % 8))) != 0; + return (keymap->keys[realKeyCode / 8] & (1 << (realKeyCode % 8))) != 0; } bool EventImpl::IsMouseButtonPressed(Mouse::Button button) diff --git a/src/Nazara/Utility/X11/WindowImpl.cpp b/src/Nazara/Utility/X11/WindowImpl.cpp index 72b85912a..297583a0f 100644 --- a/src/Nazara/Utility/X11/WindowImpl.cpp +++ b/src/Nazara/Utility/X11/WindowImpl.cpp @@ -203,17 +203,18 @@ namespace Nz // Set the window's name SetTitle(title); - #if NAZARA_UTILITY_THREADED_WINDOW - Mutex mutex; - ConditionVariable condition; - m_threadActive = true; + if (m_style & WindowStyle_Threaded) + { + Mutex mutex; + ConditionVariable condition; + m_threadActive = true; - // We wait that thread is well launched - mutex.Lock(); - m_thread = Thread(WindowThread, this, &mutex, &condition); - condition.Wait(&mutex); - mutex.Unlock(); - #endif + // Wait until the thread is ready + mutex.Lock(); + m_thread = Thread(WindowThread, this, &mutex, &condition); + condition.Wait(&mutex); + mutex.Unlock(); + } // Set fullscreen video mode and switch to fullscreen if necessary if (fullscreen) @@ -275,13 +276,15 @@ namespace Nz { if (m_ownsWindow) { - #if NAZARA_UTILITY_THREADED_WINDOW - if (m_thread.IsJoinable()) + if (m_style & WindowStyle_Threaded) { - m_threadActive = false; - m_thread.Join(); + if (m_thread.IsJoinable()) + { + m_threadActive = false; + m_thread.Join(); + } } - #else + // Destroy the window if (m_window && m_ownsWindow) { @@ -293,13 +296,11 @@ namespace Nz xcb_destroy_window( connection, m_window - )) - ) + ))) NazaraError("Failed to destroy window"); xcb_flush(connection); } - #endif } else SetEventListener(false); @@ -1247,7 +1248,7 @@ namespace Nz char32_t codePoint = GetRepresentation(keysym); - // WTF if (std::isprint(codePoint, std::locale(""))) + handle combining ? + // if (std::isprint(codePoint)) Is not working ? + handle combining ? { WindowEvent event; event.type = Nz::WindowEventType_TextEntered; @@ -1405,7 +1406,7 @@ namespace Nz // Catch reparent events to properly apply fullscreen on // some "strange" window managers (like Awesome) which // seem to make use of temporary parents during mapping - if (m_style & Nz::WindowStyle_Fullscreen) + if (m_style & WindowStyle_Fullscreen) SwitchToFullscreen(); break; @@ -1685,12 +1686,11 @@ namespace Nz )); } - #if NAZARA_UTILITY_THREADED_WINDOW void WindowImpl::WindowThread(WindowImpl* window, Mutex* mutex, ConditionVariable* condition) { mutex->Lock(); condition->Signal(); - mutex->Unlock(); // mutex et condition sont considérés invalides à partir d'ici + mutex->Unlock(); // mutex and condition may be destroyed after this line if (!window->m_window) return; @@ -1700,5 +1700,4 @@ namespace Nz window->Destroy(); } - #endif } diff --git a/src/Nazara/Utility/X11/WindowImpl.hpp b/src/Nazara/Utility/X11/WindowImpl.hpp index 6096dcac2..70a699421 100644 --- a/src/Nazara/Utility/X11/WindowImpl.hpp +++ b/src/Nazara/Utility/X11/WindowImpl.hpp @@ -20,10 +20,8 @@ namespace Nz { - #if NAZARA_UTILITY_THREADED_WINDOW class ConditionVariable; class Mutex; - #endif class Cursor; class Icon; class VideoMode; @@ -103,25 +101,19 @@ namespace Nz bool UpdateNormalHints(); void UpdateEventQueue(xcb_generic_event_t* event); - #if NAZARA_UTILITY_THREADED_WINDOW static void WindowThread(WindowImpl* window, Mutex* mutex, ConditionVariable* condition); - #endif xcb_window_t m_window; xcb_screen_t* m_screen; xcb_randr_get_screen_info_reply_t m_oldVideoMode; xcb_size_hints_t m_size_hints; - UInt32 m_style; - #if NAZARA_UTILITY_THREADED_WINDOW Thread m_thread; - #endif + UInt32 m_style; Window* m_parent; bool m_eventListener; bool m_ownsWindow; bool m_smoothScrolling; - #if NAZARA_UTILITY_THREADED_WINDOW bool m_threadActive; - #endif short m_scrolling; Vector2i m_mousePos; bool m_keyRepeat; diff --git a/tests/Engine/Core/Bitset.cpp b/tests/Engine/Core/Bitset.cpp index 124556170..b06a38aa8 100644 --- a/tests/Engine/Core/Bitset.cpp +++ b/tests/Engine/Core/Bitset.cpp @@ -1,116 +1,308 @@ +#include #include #include - +#include #include +#include + +template void Check(const char* title); +template void CheckAppend(const char* title); +template void CheckBitOps(const char* title); +template void CheckConstructor(const char* title); +template void CheckCopyMoveSwap(const char* title); +template void CheckRead(const char* title); +template void CheckReverse(const char* title); SCENARIO("Bitset", "[CORE][BITSET]") { - GIVEN("Allocate and constructor") + Check("Bitset made of 8bits blocks"); + Check("Bitset made of 16bits blocks"); + Check("Bitset made of 32bits blocks"); + Check("Bitset made of 64bits blocks"); +} + +template +void Check(const char* title) +{ + CheckConstructor(title); + CheckCopyMoveSwap(title); + + CheckBitOps(title); + + CheckAppend(title); + CheckRead(title); + CheckReverse(title); +} + +template +void CheckAppend(const char* title) +{ + SECTION(title) { - Nz::Bitset<> bitset(3, false); - - THEN("Capacity is 3 and size is 3") + GIVEN("An empty bitset filled by bytes") { - CHECK(bitset.GetSize() == 3); - CHECK(bitset.GetCapacity() >= 3); - } - } + #define BitVal1 00110111 + #define BitVal2 11011110 + #define BitVal3 01000010 + std::array data = {{NazaraPrefixMacro(BitVal1, 0b), NazaraPrefixMacro(BitVal2, 0b), NazaraPrefixMacro(BitVal3, 0b)}}; + const char result[] = NazaraStringifyMacro(BitVal3) NazaraStringifyMacro(BitVal2) NazaraStringifyMacro(BitVal1); + std::size_t resultLength = Nz::CountOf(result) - 1; + std::size_t bitCount = data.size() * 8; + #undef BitVal1 + #undef BitVal2 + #undef BitVal3 - GIVEN("Iterator and default constructor") - { - Nz::String anotherDataString("0101"); - Nz::Bitset<> defaultByte; - Nz::Bitset<> anotherData(anotherDataString.GetConstBuffer()); - - WHEN("We assign 'anotherData'") - { - defaultByte = anotherDataString; - CHECK(anotherData == defaultByte); - CHECK(defaultByte.GetSize() == 4); - CHECK(defaultByte.GetCapacity() >= 4); - CHECK(anotherData.GetSize() == 4); - CHECK(anotherData.GetCapacity() >= 4); - } - } - - GIVEN("Copy and Move constructor") - { - Nz::Bitset<> originalArray(3, true); - - WHEN("We copy") - { - Nz::Bitset<> copyBitset(originalArray); - - THEN("We get a copy") - { - CHECK(copyBitset == originalArray); - - AND_WHEN("We modify one") + std::array, 7> tests = { { - for (std::size_t i = 0; i < copyBitset.GetSize(); ++i) - copyBitset[i] = false; - - THEN("They are no more equal") - { - CHECK(copyBitset != originalArray); - CHECK(copyBitset == Nz::Bitset<>(3, false)); - } + {"We append bits one by one", 1}, + {"We append bits two by two", 2}, + {"We append bits three by three", 3}, + {"We append bits four by four", 4}, + {"We append bits six by six", 6}, + {"We append bits byte by byte", 8}, + {"We append bits twelve by twelve", 12} } - } - } + }; - WHEN("We move") - { - Nz::Bitset<> moveBitset(std::move(originalArray)); - - THEN("These results are expected") + for (auto& pair : tests) { - REQUIRE(moveBitset == Nz::Bitset<>(3, true)); - REQUIRE(originalArray.GetCapacity() == 0); - } - } - } + WHEN(pair.first) + { + Nz::Bitset bitset; - GIVEN("Three bitsets") - { - Nz::Bitset<> first("01001"); - Nz::Bitset<> second("10110"); - Nz::Bitset<> third; + for (std::size_t i = 0; i < bitCount; i += pair.second) + { + Nz::UInt16 value = data[i / 8] >> (i % 8); + if ((i % 8) + pair.second > 8 && i/8 != data.size()-1) + value |= static_cast(data[i / 8 + 1]) << (8 - (i % 8)); - WHEN("We swap first and third, then second and third and finally third and first") - { - Nz::Bitset<> oldFirst(first); - Nz::Bitset<> oldSecond(second); + bitset.AppendBits(value, pair.second); + } - first.Swap(third); - std::swap(second, third); - third.Swap(first); + REQUIRE(bitset.GetSize() == bitCount); - THEN("First and second have been swapped and third is still empty.") - { - REQUIRE(oldFirst == second); - REQUIRE(oldSecond == first); - REQUIRE(third.GetSize() == 0); - } - } - } + Nz::Bitset expectedBitset(result); - GIVEN("Two bitsets") - { - Nz::Bitset<> first("01001"); - Nz::Bitset<> second("10111"); - - WHEN("We perform operators") - { - Nz::Bitset<> andBitset = first & second; - Nz::Bitset<> orBitset = first | second; - Nz::Bitset<> xorBitset = first ^ second; - - THEN("They should operate as logical operators") - { - REQUIRE(andBitset == Nz::Bitset<>("00001")); - REQUIRE(orBitset == Nz::Bitset<>("11111")); - REQUIRE(xorBitset == Nz::Bitset<>("11110")); + CHECK(bitset == expectedBitset); + CHECK(bitset.GetBlockCount() == (bitCount / bitset.bitsPerBlock + std::min(1, bitCount % bitset.bitsPerBlock))); + } + } + } + } +} + +template +void CheckBitOps(const char* title) +{ + SECTION(title) + { + GIVEN("Two bitsets") + { + Nz::Bitset first("01001"); + Nz::Bitset second("10111"); + + WHEN("We perform operators") + { + Nz::Bitset andBitset = first & second; + Nz::Bitset orBitset = first | second; + Nz::Bitset xorBitset = first ^ second; + + THEN("They should operate as logical operators") + { + CHECK(andBitset == Nz::Bitset("00001")); + CHECK(orBitset == Nz::Bitset("11111")); + CHECK(xorBitset == Nz::Bitset("11110")); + } + } + } + } +} + +template +void CheckConstructor(const char* title) +{ + SECTION(title) + { + GIVEN("Allocate and constructor") + { + Nz::Bitset bitset(3, false); + + THEN("Capacity is 3 and size is 3") + { + CHECK(bitset.GetSize() == 3); + CHECK(bitset.GetCapacity() >= 3); + } + } + + GIVEN("Iterator and default constructor") + { + Nz::String anotherDataString("0101"); + Nz::Bitset defaultByte; + Nz::Bitset anotherData(anotherDataString.GetConstBuffer()); + + WHEN("We assign 'anotherData'") + { + defaultByte = anotherDataString; + CHECK(anotherData == defaultByte); + CHECK(defaultByte.GetSize() == 4); + CHECK(defaultByte.GetCapacity() >= 4); + CHECK(anotherData.GetSize() == 4); + CHECK(anotherData.GetCapacity() >= 4); + } + } + } +} + +template +void CheckCopyMoveSwap(const char* title) +{ + SECTION(title) + { + GIVEN("Copy and Move constructor") + { + Nz::Bitset originalArray(3, true); + + WHEN("We copy") + { + Nz::Bitset copyBitset(originalArray); + + THEN("We get a copy") + { + CHECK(copyBitset == originalArray); + + AND_WHEN("We modify one") + { + for (std::size_t i = 0; i < copyBitset.GetSize(); ++i) + copyBitset[i] = false; + + THEN("They are no more equal") + { + CHECK(copyBitset != originalArray); + CHECK(copyBitset == Nz::Bitset(3, false)); + } + } + } + } + + WHEN("We move") + { + Nz::Bitset moveBitset(std::move(originalArray)); + + THEN("These results are expected") + { + CHECK(moveBitset == Nz::Bitset(3, true)); + CHECK(originalArray.GetCapacity() == 0); + } + } + } + + GIVEN("Three bitsets") + { + Nz::Bitset first("01001"); + Nz::Bitset second("10110"); + Nz::Bitset third; + + WHEN("We swap first and third, then second and third and finally third and first") + { + Nz::Bitset oldFirst(first); + Nz::Bitset oldSecond(second); + + first.Swap(third); + std::swap(second, third); + third.Swap(first); + + THEN("First and second have been swapped and third is still empty.") + { + CHECK(oldFirst == second); + CHECK(oldSecond == first); + CHECK(third.GetSize() == 0); + } + } + } + } +} + +template +void CheckRead(const char* title) +{ + SECTION(title) + { + GIVEN("An empty bitset filled by reading") + { + #define BitVal1 10010101 + #define BitVal2 11010010 + #define BitVal3 01101010 + std::array data = {{NazaraPrefixMacro(BitVal1, 0b), NazaraPrefixMacro(BitVal2, 0b), NazaraPrefixMacro(BitVal3, 0b)}}; + const char result[] = NazaraStringifyMacro(BitVal3) NazaraStringifyMacro(BitVal2) NazaraStringifyMacro(BitVal1); + std::size_t resultLength = Nz::CountOf(result) - 1; + std::size_t bitCount = data.size() * 8; + #undef BitVal1 + #undef BitVal2 + #undef BitVal3 + + std::array, 8> tests = { + { + {"We read bits one by one", 1}, + {"We read bits two by two", 2}, + {"We read bits three by three", 3}, + {"We read bits four by four", 4}, + {"We read bits six by six", 6}, + {"We read bits byte by byte", 8}, + {"We read bits twelve by twelve", 12}, + {"We read bits all at once", 24} + } + }; + + for (auto& pair : tests) + { + WHEN(pair.first) + { + Nz::Bitset bitset; + + auto seq = bitset.Read(data.data(), pair.second); + for (std::size_t i = pair.second; i < bitCount; i += pair.second) + seq = bitset.Read(seq, pair.second); + + REQUIRE(bitset.GetSize() == bitCount); + + Nz::Bitset expectedBitset(result); + + CHECK(bitset == expectedBitset); + CHECK(bitset.GetBlockCount() == (bitCount / bitset.bitsPerBlock + std::min(1, bitCount % bitset.bitsPerBlock))); + } + } + } + } +} + +template +void CheckReverse(const char* title) +{ + SECTION(title) + { + GIVEN("A bitset") + { + Nz::String bits = "010011100010001101001111"; + Nz::Bitset expected(bits); + + WHEN("We reverse the order of bits") + { + Nz::Bitset bitset(bits); + bitset.Reverse(); + + THEN("The order of bits should be reversed") + { + CHECK(bitset == Nz::Bitset(bits.Reversed())); + } + AND_WHEN("We reverse the bit order again") + { + bitset.Reverse(); + + THEN("It should be back to normal") + { + CHECK(bitset == expected); + } + } } } } diff --git a/tests/Engine/Graphics/ParticleDeclaration.cpp b/tests/Engine/Graphics/ParticleDeclaration.cpp index 1bc1739d3..4cde9c5d2 100644 --- a/tests/Engine/Graphics/ParticleDeclaration.cpp +++ b/tests/Engine/Graphics/ParticleDeclaration.cpp @@ -11,10 +11,10 @@ SCENARIO("ParticleDeclaration", "[GRAPHICS][PARTICLEDECLARATION]") { bool enabled; Nz::ComponentType type; - unsigned int offset; + std::size_t offset; particleDeclaration->GetComponent(Nz::ParticleComponent_Position, &enabled, &type, &offset); REQUIRE(enabled); - unsigned int oldStride = particleDeclaration->GetStride(); + std::size_t oldStride = particleDeclaration->GetStride(); particleDeclaration->DisableComponent(Nz::ParticleComponent_Position); REQUIRE(oldStride != particleDeclaration->GetStride());