diff --git a/.gitignore b/.gitignore index 6266c2b6b..a7b7a3c9c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,27 @@ # Nazara build build/config.lua + +# Nazara libraries +lib/* + +# Nazara package +package/* + +# Example files +>>>>>>> master examples/bin/*.exe examples/bin/*.pdb examples/bin/*.dll examples/bin/*.so + +# Unit tests tests/*.exe tests/*.pdb tests/*.dll tests/*.so -lib/* + +# Example generated files +examples/bin/HardwareInfo.txt # Example generated files examples/bin/HardwareInfo.txt diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..d1ed3ec6d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,49 @@ +language: + cpp + +dist: + trusty + +addons: + apt: + sources: + - llvm-toolchain-precise-3.7 + - ubuntu-toolchain-r-test + packages: + - clang-3.7 + - libassimp-dev + - libfreetype6-dev + - libgl1-mesa-dev + - libopenal-dev + - libsndfile1-dev + - libx11-dev + - libxcb-cursor-dev + - libxcb-ewmh-dev + - libxcb-icccm4-dev + - libxcb-keysyms1-dev + - libxcb-randr0-dev + - mesa-common-dev + +sudo: + required + +notifications: + email: true + +compiler: + - clang + +env: + - COMPILER=clang++-3.7 CONFIG=debug + - COMPILER=clang++-3.7 CONFIG=release + +script: + - cd build && + ./premake5-linux64 --cc=clang gmake + - cd gmake && + make -j4 -f NazaraEngine.make config=${CONFIG}dynamic_x64 + +after_script: + - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../lib/gmake/x64/:../extlibs/lib/gmake/x64/ && + cd ../../tests && + ./NazaraUnitTestsServer diff --git a/SDK/include/NDK/Components/CameraComponent.hpp b/SDK/include/NDK/Components/CameraComponent.hpp index af2245b11..b26901a79 100644 --- a/SDK/include/NDK/Components/CameraComponent.hpp +++ b/SDK/include/NDK/Components/CameraComponent.hpp @@ -34,21 +34,21 @@ namespace Ndk inline void EnsureViewMatrixUpdate() const; inline void EnsureViewportUpdate() const; - inline float GetAspectRatio() const override; - inline Nz::Vector3f GetEyePosition() const override; - inline Nz::Vector3f GetForward() const override; + float GetAspectRatio() const override; + Nz::Vector3f GetEyePosition() const override; + Nz::Vector3f GetForward() const override; inline float GetFOV() const; - inline const Nz::Frustumf& GetFrustum() const override; + const Nz::Frustumf& GetFrustum() const override; inline unsigned int GetLayer() const; - inline const Nz::Matrix4f& GetProjectionMatrix() const override; + const Nz::Matrix4f& GetProjectionMatrix() const override; inline Nz::ProjectionType GetProjectionType() const; inline const Nz::Vector2f& GetSize() const; - inline const Nz::RenderTarget* GetTarget() const override; + const Nz::RenderTarget* GetTarget() const override; inline const Nz::Rectf& GetTargetRegion() const; - inline const Nz::Matrix4f& GetViewMatrix() const override; - inline const Nz::Recti& GetViewport() const override; - inline float GetZFar() const override; - inline float GetZNear() const override; + const Nz::Matrix4f& GetViewMatrix() const override; + const Nz::Recti& GetViewport() const override; + float GetZFar() const override; + float GetZNear() const override; inline void SetFOV(float fov); inline void SetLayer(unsigned int layer); diff --git a/SDK/include/NDK/Components/CameraComponent.inl b/SDK/include/NDK/Components/CameraComponent.inl index d42d0e152..541096de5 100644 --- a/SDK/include/NDK/Components/CameraComponent.inl +++ b/SDK/include/NDK/Components/CameraComponent.inl @@ -95,40 +95,15 @@ namespace Ndk UpdateViewport(); } - /*! - * \brief Gets the aspect ratio of the camera - * \return Aspect ratio of the camera - */ - - inline float CameraComponent::GetAspectRatio() const - { - EnsureViewportUpdate(); - - return m_aspectRatio; - } - /*! * \brief Gets the field of view of the camera * \return Field of view of the camera */ - - inline float CameraComponent::GetFOV() const + float CameraComponent::GetFOV() const { return m_fov; } - /*! - * \brief Gets the frutum of the camera - * \return A constant reference to the frustum of the camera - */ - - inline const Nz::Frustumf& CameraComponent::GetFrustum() const - { - EnsureFrustumUpdate(); - - return m_frustum; - } - /*! * \brief Gets the layer of the camera * \return Layer of the camera @@ -139,18 +114,6 @@ namespace Ndk return m_layer; } - /*! - * \brief Gets the projection matrix of the camera - * \return A constant reference to the projection matrix of the camera - */ - - inline const Nz::Matrix4f& CameraComponent::GetProjectionMatrix() const - { - EnsureProjectionMatrixUpdate(); - - return m_projectionMatrix; - } - /*! * \brief Gets the projection type of the camera * \return Projection type of the camera @@ -171,16 +134,6 @@ namespace Ndk return m_size; } - /*! - * \brief Gets the target of the camera - * \return A constant reference to the render target of the camera - */ - - inline const Nz::RenderTarget* CameraComponent::GetTarget() const - { - return m_target; - } - /*! * \brief Gets the target region of the camera * \return A constant reference to the target region of the camera @@ -191,50 +144,6 @@ namespace Ndk return m_targetRegion; } - /*! - * \brief Gets the view matrix of the camera - * \return A constant reference to the view matrix of the camera - */ - - inline const Nz::Matrix4f& CameraComponent::GetViewMatrix() const - { - EnsureViewMatrixUpdate(); - - return m_viewMatrix; - } - - /*! - * \brief Gets the view port of the camera - * \return A constant reference to the view port of the camera - */ - - inline const Nz::Recti& CameraComponent::GetViewport() const - { - EnsureViewportUpdate(); - - return m_viewport; - } - - /*! - * \brief Gets the Z far distance of the camera - * \return Z far distance of the camera - */ - - inline float CameraComponent::GetZFar() const - { - return m_zFar; - } - - /*! - * \brief Gets the Z near distance of the camera - * \return Z near distance of the camera - */ - - inline float CameraComponent::GetZNear() const - { - return m_zNear; - } - /*! * \brief Sets the field of view of the camera * diff --git a/SDK/include/NDK/Console.hpp b/SDK/include/NDK/Console.hpp index 78caac3f2..1c007065f 100644 --- a/SDK/include/NDK/Console.hpp +++ b/SDK/include/NDK/Console.hpp @@ -51,7 +51,7 @@ namespace Ndk inline bool IsVisible() const; void SendCharacter(char32_t character); - void SendEvent(Nz::WindowEvent event); + void SendEvent(const Nz::WindowEvent& event); void SetCharacterSize(unsigned int size); void SetSize(const Nz::Vector2f& size); diff --git a/SDK/include/NDK/Prerequesites.hpp b/SDK/include/NDK/Prerequesites.hpp index f3532c70d..a2305c70f 100644 --- a/SDK/include/NDK/Prerequesites.hpp +++ b/SDK/include/NDK/Prerequesites.hpp @@ -27,32 +27,15 @@ #include -// Version of SDK -#define NDK_VERSION_MAJOR 0 -#define NDK_VERSION_MINOR 1 - // Importation/Exportation of the API -#if defined(NAZARA_PLATFORM_WINDOWS) - #if !defined(NDK_STATIC) - #ifdef NDK_BUILD - #define NDK_API NAZARA_EXPORT - #else - #define NDK_API NAZARA_IMPORT - #endif - #else - #define NDK_API - #endif -#elif defined(NAZARA_PLATFORM_LINUX) - #if !defined(NDK_STATIC) && defined(NAZARA_COMPILER_GCC) - #define NDK_API NAZARA_EXPORT - #else - #define NDK_API - #endif +#if defined(NAZARA_STATIC) + #define #define NDK_API #else - // To comment to force a compilation - #error This operating system is not fully supported by the Nazara Development Kit - - #define NDK_API + #ifdef NDK_BUILD + #define NDK_API NAZARA_EXPORT + #else + #define NDK_API NAZARA_IMPORT + #endif #endif namespace Ndk diff --git a/SDK/src/NDK/Application.cpp b/SDK/src/NDK/Application.cpp index 3cdff6978..46e1db13d 100644 --- a/SDK/src/NDK/Application.cpp +++ b/SDK/src/NDK/Application.cpp @@ -34,7 +34,7 @@ namespace Ndk * * \remark Only one Application instance can exist at a time */ - inline Application::Application(int argc, char* argv[]) : + Application::Application(int argc, char* argv[]) : Application() { std::regex optionRegex(R"(-(\w+))"); diff --git a/SDK/src/NDK/Components/CameraComponent.cpp b/SDK/src/NDK/Components/CameraComponent.cpp index 71c653823..28f4e31d5 100644 --- a/SDK/src/NDK/Components/CameraComponent.cpp +++ b/SDK/src/NDK/Components/CameraComponent.cpp @@ -35,6 +35,17 @@ namespace Ndk Nz::Renderer::SetViewport(m_viewport); } + /*! + * \brief Gets the aspect ratio of the camera + * \return Aspect ratio of the camera + */ + float CameraComponent::GetAspectRatio() const + { + EnsureViewportUpdate(); + + return m_aspectRatio; + } + /*! * \brief Gets the eye position of the camera * @@ -53,7 +64,6 @@ namespace Ndk * * \remark Produces a NazaraAssert if entity is invalid or has no NodeComponent */ - Nz::Vector3f CameraComponent::GetForward() const { NazaraAssert(m_entity && m_entity->HasComponent(), "CameraComponent requires NodeComponent"); @@ -61,6 +71,76 @@ namespace Ndk return m_entity->GetComponent().GetForward(); } + /*! + * \brief Gets the frutum of the camera + * \return A constant reference to the frustum of the camera + */ + const Nz::Frustumf& CameraComponent::GetFrustum() const + { + EnsureFrustumUpdate(); + + return m_frustum; + } + + /*! + * \brief Gets the projection matrix of the camera + * \return A constant reference to the projection matrix of the camera + */ + const Nz::Matrix4f& CameraComponent::GetProjectionMatrix() const + { + EnsureProjectionMatrixUpdate(); + + return m_projectionMatrix; + } + + /*! + * \brief Gets the target of the camera + * \return A constant reference to the render target of the camera + */ + const Nz::RenderTarget* CameraComponent::GetTarget() const + { + return m_target; + } + + /*! + * \brief Gets the view matrix of the camera + * \return A constant reference to the view matrix of the camera + */ + const Nz::Matrix4f& CameraComponent::GetViewMatrix() const + { + EnsureViewMatrixUpdate(); + + return m_viewMatrix; + } + + /*! + * \brief Gets the view port of the camera + * \return A constant reference to the view port of the camera + */ + const Nz::Recti& CameraComponent::GetViewport() const + { + EnsureViewportUpdate(); + + return m_viewport; + } + + /*! + * \brief Gets the Z far distance of the camera + * \return Z far distance of the camera + */ + float CameraComponent::GetZFar() const + { + return m_zFar; + } + + /*! + * \brief Gets the Z near distance of the camera + * \return Z near distance of the camera + */ + float CameraComponent::GetZNear() const + { + return m_zNear; + } /*! * \brief Sets the layer of the camera in case of multiples fields * diff --git a/SDK/src/NDK/Console.cpp b/SDK/src/NDK/Console.cpp index 94a80b749..122e2a125 100644 --- a/SDK/src/NDK/Console.cpp +++ b/SDK/src/NDK/Console.cpp @@ -168,7 +168,7 @@ namespace Ndk * \param event Event to be takin into consideration by the console */ - void Console::SendEvent(Nz::WindowEvent event) + void Console::SendEvent(const Nz::WindowEvent& event) { switch (event.type) { @@ -204,6 +204,9 @@ namespace Ndk } break; } + + default: + break; } } diff --git a/SDK/src/NDK/LuaBinding_Audio.cpp b/SDK/src/NDK/LuaBinding_Audio.cpp index b825b1876..ed1538a78 100644 --- a/SDK/src/NDK/LuaBinding_Audio.cpp +++ b/SDK/src/NDK/LuaBinding_Audio.cpp @@ -78,9 +78,10 @@ namespace Ndk }); /*********************************** Nz::SoundBuffer **********************************/ - soundBuffer.SetConstructor([] (Nz::LuaInstance& lua, Nz::SoundBufferRef* instance) + soundBuffer.SetConstructor([] (Nz::LuaInstance& lua, Nz::SoundBufferRef* instance, std::size_t argumentCount) { NazaraUnused(lua); + NazaraUnused(argumentCount); Nz::PlacementNew(instance, Nz::SoundBuffer::New()); return true; diff --git a/SDK/src/NDK/LuaBinding_Core.cpp b/SDK/src/NDK/LuaBinding_Core.cpp index 78c73eea1..d111a0266 100644 --- a/SDK/src/NDK/LuaBinding_Core.cpp +++ b/SDK/src/NDK/LuaBinding_Core.cpp @@ -13,7 +13,7 @@ namespace Ndk void LuaBinding::BindCore() { /*********************************** Nz::Clock **********************************/ - clockClass.SetConstructor([](Nz::LuaInstance& lua, Nz::Clock* clock) + clockClass.SetConstructor([](Nz::LuaInstance& lua, Nz::Clock* clock, std::size_t argumentCount) { int argIndex = 1; Nz::Int64 startingValue = lua.Check(&argIndex, 0); @@ -44,9 +44,9 @@ namespace Ndk }); /********************************* Nz::Directory ********************************/ - directoryClass.SetConstructor([](Nz::LuaInstance& lua, Nz::Directory* directory) + directoryClass.SetConstructor([](Nz::LuaInstance& lua, Nz::Directory* directory, std::size_t argumentCount) { - unsigned int argCount = std::min(lua.GetStackTop(), 1U); + std::size_t argCount = std::min(argumentCount, 1U); int argIndex = 1; switch (argCount) @@ -138,9 +138,9 @@ namespace Ndk /*********************************** Nz::File ***********************************/ fileClass.Inherit(streamClass); - fileClass.SetConstructor([](Nz::LuaInstance& lua, Nz::File* file) + fileClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::File* file, std::size_t argumentCount) { - unsigned int argCount = std::min(lua.GetStackTop(), 2U); + std::size_t argCount = std::min(argumentCount, 1U); int argIndex = 1; switch (argCount) diff --git a/SDK/src/NDK/LuaBinding_Graphics.cpp b/SDK/src/NDK/LuaBinding_Graphics.cpp index 4c9288428..7505c1d9a 100644 --- a/SDK/src/NDK/LuaBinding_Graphics.cpp +++ b/SDK/src/NDK/LuaBinding_Graphics.cpp @@ -20,8 +20,10 @@ namespace Ndk return reinterpret_cast(model); //TODO: Make a ObjectRefCast }); - modelClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::ModelRef* model) + modelClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::ModelRef* model, std::size_t argumentCount) { + NazaraUnused(argumentCount); + Nz::PlacementNew(model, Nz::Model::New()); return true; }); diff --git a/SDK/src/NDK/LuaBinding_Math.cpp b/SDK/src/NDK/LuaBinding_Math.cpp index 1c53caa69..f65259f50 100644 --- a/SDK/src/NDK/LuaBinding_Math.cpp +++ b/SDK/src/NDK/LuaBinding_Math.cpp @@ -14,9 +14,10 @@ namespace Ndk void LuaBinding::BindMath() { /*********************************** Nz::EulerAngles **********************************/ - eulerAnglesClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::EulerAnglesd* angles) + eulerAnglesClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::EulerAnglesd* angles, std::size_t argumentCount) { - unsigned int argCount = std::min(lua.GetStackTop(), 3U); + std::size_t argCount = std::min(argumentCount, 1U); + switch (argCount) { case 0: @@ -154,9 +155,10 @@ namespace Ndk }); /*********************************** Nz::Rect **********************************/ - rectClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Rectd* rect) + rectClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Rectd* rect, std::size_t argumentCount) { - unsigned int argCount = std::min(lua.GetStackTop(), 4U); + std::size_t argCount = std::min(argumentCount, 4U); + switch (argCount) { case 0: @@ -309,9 +311,10 @@ namespace Ndk }); /*********************************** Nz::Quaternion **********************************/ - quaternionClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Quaterniond* quaternion) + quaternionClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Quaterniond* quaternion, std::size_t argumentCount) { - unsigned int argCount = std::min(lua.GetStackTop(), 4U); + std::size_t argCount = std::min(argumentCount, 4U); + switch (argCount) { case 0: @@ -337,6 +340,9 @@ namespace Ndk case 4: Nz::PlacementNew(quaternion, lua.CheckNumber(1), lua.CheckNumber(2), lua.CheckNumber(3), lua.CheckNumber(4)); return true; + + default: + break; } lua.Error("No matching overload for Quaternion constructor"); @@ -411,9 +417,10 @@ namespace Ndk }); /*********************************** Nz::Vector2 **********************************/ - vector2dClass.SetConstructor([](Nz::LuaInstance& lua, Nz::Vector2d* vector) + vector2dClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Vector2d* vector, std::size_t argumentCount) { - unsigned int argCount = std::min(lua.GetStackTop(), 2U); + std::size_t argCount = std::min(argumentCount, 2U); + switch (argCount) { case 0: @@ -533,9 +540,10 @@ namespace Ndk }); /*********************************** Nz::Vector3 **********************************/ - vector3dClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Vector3d* vector) + vector3dClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Vector3d* vector, std::size_t argumentCount) { - unsigned int argCount = std::min(lua.GetStackTop(), 3U); + std::size_t argCount = std::min(argumentCount, 3U); + switch (argCount) { case 0: @@ -546,7 +554,7 @@ namespace Ndk case 1: { if (lua.IsOfType(1, Nz::LuaType_Number)) - Nz::PlacementNew(vector, lua.CheckNumber(1), *static_cast(lua.CheckUserdata(1, "Vector2"))); + Nz::PlacementNew(vector, lua.CheckNumber(1)); else if (lua.IsOfType(1, "Vector2")) Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1))); else if (lua.IsOfType(1, "Vector3")) @@ -560,7 +568,7 @@ namespace Ndk case 2: { if (lua.IsOfType(1, Nz::LuaType_Number)) - Nz::PlacementNew(vector, lua.CheckNumber(1), *static_cast(lua.CheckUserdata(1, "Vector2"))); + Nz::PlacementNew(vector, lua.CheckNumber(1), *static_cast(lua.CheckUserdata(2, "Vector2"))); else if (lua.IsOfType(1, "Vector2")) Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1)), lua.CheckNumber(2)); else diff --git a/SDK/src/NDK/LuaBinding_Network.cpp b/SDK/src/NDK/LuaBinding_Network.cpp index 67f40cb4d..689fc2d1d 100644 --- a/SDK/src/NDK/LuaBinding_Network.cpp +++ b/SDK/src/NDK/LuaBinding_Network.cpp @@ -21,9 +21,9 @@ namespace Ndk abstractSocketClass.BindMethod("QueryAvailableBytes", &Nz::AbstractSocket::QueryAvailableBytes); /*********************************** Nz::IpAddress **********************************/ - ipAddressClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::IpAddress* address) + ipAddressClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::IpAddress* address, std::size_t argumentCount) { - unsigned int argCount = std::min(lua.GetStackTop(), 9U); + std::size_t argCount = std::min(argumentCount, 9U); int argIndex = 1; switch (argCount) diff --git a/SDK/src/NDK/LuaBinding_SDK.cpp b/SDK/src/NDK/LuaBinding_SDK.cpp index 1ccd16342..af5cca5a8 100644 --- a/SDK/src/NDK/LuaBinding_SDK.cpp +++ b/SDK/src/NDK/LuaBinding_SDK.cpp @@ -233,6 +233,9 @@ namespace Ndk return &m_componentBinding[it->second]; } + + default: + break; } instance.Error("Invalid component index at #" + Nz::String::Number(argIndex)); diff --git a/SDK/src/NDK/LuaBinding_Utility.cpp b/SDK/src/NDK/LuaBinding_Utility.cpp index 416662b23..3d8dbdc18 100644 --- a/SDK/src/NDK/LuaBinding_Utility.cpp +++ b/SDK/src/NDK/LuaBinding_Utility.cpp @@ -93,8 +93,10 @@ namespace Ndk }); /*********************************** Nz::Font **********************************/ - fontClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::FontRef* font) + fontClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::FontRef* font, std::size_t argumentCount) { + NazaraUnused(argumentCount); + Nz::PlacementNew(font, Nz::Font::New()); return true; }); diff --git a/SDK/src/NDK/Sdk.cpp b/SDK/src/NDK/Sdk.cpp index bd3bf33e4..326eec502 100644 --- a/SDK/src/NDK/Sdk.cpp +++ b/SDK/src/NDK/Sdk.cpp @@ -59,6 +59,13 @@ namespace Ndk // Initialize the engine first // Shared modules + #ifdef NDK_SERVER + Nz::ParameterList parameters; + parameters.SetParameter("NoWindowSystem", true); + + Nz::Utility::SetParameters(parameters); + #endif + Nz::Lua::Initialize(); Nz::Noise::Initialize(); Nz::Physics::Initialize(); diff --git a/appveyor.yml b/appveyor.yml index 39ff8f7a8..b6f1df78f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,20 @@ version: '{branch}-rev{build}' shallow_clone: true +skip_commits: + files: + - .travis.yml + - Doxyfile + - LICENSE + - License-Cabin.txt + - Logo.png + - LogoMini.png + - readme.md + - readme_fr.md + - 'writing style.md' + - doc/* + - NazaraModuleTemplate/* + os: - Visual Studio 2015 @@ -16,5 +30,20 @@ configuration: - DebugDynamic - ReleaseDynamic +platform: + - Win32 + - x64 + build: - project: build/$(TOOLSET)/NazaraEngine.sln \ No newline at end of file + project: build/$(TOOLSET)/NazaraEngine.sln + +after_build: + - cd build && "./premake5.exe" package && cd ../package + - 7z a NazaraEngine.7z * && cd .. + +artifacts: + - path: package/NazaraEngine.7z + name: 'NazaraEngine-$(CONFIGURATION)-$(PLATFORM)-$(APPVEYOR_REPO_COMMIT)' + +on_success: + - cd tests && "./NazaraUnitTestsServer.exe" diff --git a/build/Package_AutoDetect.bat b/build/Package_AutoDetect.bat new file mode 100644 index 000000000..32a52470b --- /dev/null +++ b/build/Package_AutoDetect.bat @@ -0,0 +1,2 @@ +premake5 package +pause \ No newline at end of file diff --git a/build/Package_MSVC.bat b/build/Package_MSVC.bat new file mode 100644 index 000000000..0367ff7df --- /dev/null +++ b/build/Package_MSVC.bat @@ -0,0 +1,2 @@ +premake5 --pack-libdir=msvc package +pause \ No newline at end of file diff --git a/build/Package_MinGW.bat b/build/Package_MinGW.bat new file mode 100644 index 000000000..823c5e4ce --- /dev/null +++ b/build/Package_MinGW.bat @@ -0,0 +1,2 @@ +premake5 --pack-libdir=mingw package +pause \ No newline at end of file diff --git a/build/scripts/actions/package.lua b/build/scripts/actions/package.lua new file mode 100644 index 000000000..62d4792b3 --- /dev/null +++ b/build/scripts/actions/package.lua @@ -0,0 +1,207 @@ +newoption({ + trigger = "pack-libdir", + description = "Specifiy the subdirectory in lib/ to be used when packaging the project" +}) + +ACTION.Name = "Package" +ACTION.Description = "Pack Nazara binaries/include/lib together" + +ACTION.Function = function () + local libDir = _OPTIONS["pack-libdir"] + if (not libDir or #libDir == 0) then + local libDirs = os.matchdirs("../lib/*") + if (#libDirs > 1) then + error("More than one subdirectory was found in the lib directory, please use the --pack-libdir command to clarify which directory should be used") + elseif (#libDirs == 0) then + error("No subdirectory was found in the lib directory, have you built the engine yet?") + else + libDir = path.getname(libDirs[1]) + print("No directory was set by the --pack-libdir command, \"" .. libDir .. "\" will be used") + end + end + + local realLibDir = "../lib/" .. libDir .. "/" + if (not os.isdir(realLibDir)) then + error(string.format("\"%s\" doesn't seem to be an existing directory", realLibDir)) + end + + local archEnabled = { + ["x64"] = false, + ["x86"] = false + } + + local enabledArchs = {} + for k,v in pairs(os.matchdirs(realLibDir .. "*")) do + local arch = path.getname(v) + if (archEnabled[arch] ~= nil) then + archEnabled[arch] = true + table.insert(enabledArchs, arch) + else + print("Unknown directory " .. v .. " found, ignored") + end + end + enabledArchs = table.concat(enabledArchs, ", ") + print(enabledArchs .. " arch found") + + local packageDir = "../package/" + + local copyTargets = { + { -- Engine headers + Masks = {"**.hpp", "**.inl"}, + Source = "../include/", + Target = "include/" + }, + { -- SDK headers + Masks = {"**.hpp", "**.inl"}, + Source = "../SDK/include/", + Target = "include/" + }, + { -- Examples files + Masks = {"**.hpp", "**.inl", "**.cpp"}, + Source = "../examples/", + Target = "examples/" + }, + { -- Demo resources + Masks = {"**.*"}, + Source = "../examples/bin/resources/", + Target = "examples/bin/resources/" + }, + -- Unit test sources + { + Masks = {"**.hpp", "**.inl", "**.cpp"}, + Source = "../tests/", + Target = "tests/src/" + }, + -- Unit test resources + { + Masks = {"**.*"}, + Source = "../tests/resources/", + Target = "tests/resources/" + } + } + + local binFileMasks + local libFileMasks + local exeFileExt + local exeFilterFunc + if (os.is("windows")) then + binFileMasks = {"**.dll"} + libFileMasks = {"**.lib", "**.a"} + exeFileExt = ".exe" + exeFilterFunc = function (filePath) return true end + else + if (os.is("macosx")) then + binFileMasks = {"**.dynlib"} + else + binFileMasks = {"**.so"} + end + + libFileMasks = {"**.a"} + exeFileExt = "" + exeFilterFunc = function (filePath) return path.getextension(filePath):contains('/') end + end + + for arch, enabled in pairs(archEnabled) do + if (enabled) then + local archLibSrc = realLibDir .. arch .. "/" + local arch3rdPartyBinSrc = "../extlibs/lib/common/" .. arch .. "/" + local archBinDst = "bin/" .. arch .. "/" + local archLibDst = "lib/" .. arch .. "/" + + -- Engine/SDK binaries + table.insert(copyTargets, { + Masks = binFileMasks, + Source = archLibSrc, + Target = archBinDst + }) + + -- Engine/SDK libraries + table.insert(copyTargets, { + Masks = libFileMasks, + Source = archLibSrc, + Target = archLibDst + }) + + -- 3rd party binary dep + table.insert(copyTargets, { + Masks = binFileMasks, + Source = arch3rdPartyBinSrc, + Target = archBinDst + }) + end + end + + -- Demo executable + table.insert(copyTargets, { + Masks = {"Demo*" .. exeFileExt}, + Filter = exeFilterFunc, + Source = "../examples/bin/", + Target = "examples/bin/" + }) + + -- Unit test + table.insert(copyTargets, { + Masks = {"*" .. exeFileExt}, + Filter = exeFilterFunc, + Source = "../tests/", + Target = "tests/" + }) + + -- Processing + os.mkdir(packageDir) + + local size = 0 + for k,v in pairs(copyTargets) do + local target = packageDir .. v.Target + local includePrefix = v.Source + + local targetFiles = {} + for k, mask in pairs(v.Masks) do + print(includePrefix .. mask .. " => " .. target) + local files = os.matchfiles(includePrefix .. mask) + if (v.Filter) then + for k,path in pairs(files) do + if (not v.Filter(path)) then + files[k] = nil + end + end + end + + targetFiles = table.join(targetFiles, files) + end + + for k,v in pairs(targetFiles) do + local relPath = v:sub(#includePrefix + 1) + + local targetPath = target .. relPath + local targetDir = path.getdirectory(targetPath) + + if (not os.isdir(targetDir)) then + local ok, err = os.mkdir(targetDir) + if (not ok) then + print("Failed to create directory \"" .. targetDir .. "\": " .. err) + end + end + + local ok, err + if (os.is("windows")) then + ok, err = os.copyfile(v, targetPath) + else + -- Workaround: As premake is translating this to "cp %s %s", it fails if space are presents in source/destination paths. + ok, err = os.copyfile(string.format("\"%s\"", v), string.format("\"%s\"", targetPath)) + end + + if (not ok) then + print("Failed to copy \"" .. v .. "\" to \"" .. targetPath .. "\": " .. err) + end + + local stat = os.stat(targetPath) + if (stat) then + size = size + stat.size + end + end + end + + local config = libDir .. " - " .. enabledArchs + print(string.format("Package successfully created at \"%s\" (%u MB, %s)", packageDir, size / (1024 * 1024), config)) +end diff --git a/build/scripts/common.lua b/build/scripts/common.lua index cf6fa6560..30272acfd 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -141,7 +141,6 @@ function NazaraBuild:Execute() configuration("Release*") flags("NoFramePointer") optimize("Speed") - rtti("Off") vectorextensions("SSE2") configuration({"Release*", "codeblocks or codelite or gmake or xcode3 or xcode4"}) @@ -228,6 +227,7 @@ function NazaraBuild:Execute() targetdir("../lib/xcode/x64") configuration("*Static") + defines("NAZARA_STATIC") kind("StaticLib") configuration("*Dynamic") @@ -242,6 +242,9 @@ function NazaraBuild:Execute() configuration("DebugDynamic") targetsuffix("-d") + configuration("Release*") + rtti(moduleTable.EnableRTTI and "On" or "Off") + configuration({}) files(moduleTable.Files) @@ -357,6 +360,12 @@ function NazaraBuild:Execute() targetdir("../plugins/" .. toolTable.Name .. "/lib/xcode/x64") end + configuration("*Static") + defines("NAZARA_STATIC") + + configuration("Release*") + rtti(toolTable.EnableRTTI and "On" or "Off") + if (toolTable.Kind == "library" or toolTable.Kind == "plugin") then configuration("*Static") kind("StaticLib") @@ -430,6 +439,9 @@ function NazaraBuild:Execute() includedirs(exampleTable.Includes) links(exampleTable.Libraries) + configuration("Release*") + rtti(exampleTable.EnableRTTI and "On" or "Off") + configuration("x32") libdirs(exampleTable.LibraryPaths.x86) @@ -705,7 +717,7 @@ function NazaraBuild:MakeInstallCommands(infoTable) end if (os.is("windows")) then - configuration({}) + configuration("*Dynamic") for k,v in pairs(self.InstallDir) do local destPath = path.translate(path.isabsolute(k) and k or "../../" .. k) diff --git a/build/scripts/modules/network.lua b/build/scripts/modules/network.lua index 8cf8b068a..9245d72f3 100644 --- a/build/scripts/modules/network.lua +++ b/build/scripts/modules/network.lua @@ -14,6 +14,16 @@ MODULE.OsFiles.Posix = { "../src/Nazara/Network/Posix/**.cpp" } +MODULE.OsFiles.Linux = { + "../src/Nazara/Network/Linux/**.hpp", + "../src/Nazara/Network/Linux/**.cpp" +} + +MODULE.OsFilesExcluded.Linux = { + "../src/Nazara/Network/Posix/SocketPollerImpl.hpp", + "../src/Nazara/Network/Posix/SocketPollerImpl.cpp" +} + MODULE.OsLibraries.Windows = { "ws2_32" } diff --git a/build/scripts/modules/physics.lua b/build/scripts/modules/physics.lua index f6d485a67..0796c46fd 100644 --- a/build/scripts/modules/physics.lua +++ b/build/scripts/modules/physics.lua @@ -2,5 +2,5 @@ MODULE.Name = "Physics" MODULE.Libraries = { "NazaraCore", - "Newton" + "Newton" -- Newton Game Dynamics } diff --git a/build/scripts/tools/unittests.lua b/build/scripts/tools/unittests.lua index b423b390f..5dcf6e215 100644 --- a/build/scripts/tools/unittests.lua +++ b/build/scripts/tools/unittests.lua @@ -19,5 +19,6 @@ TOOL.Files = { } TOOL.Libraries = { + "NazaraNetwork", "NazaraSDK" } diff --git a/build/scripts/tools/unittests_server.lua b/build/scripts/tools/unittests_server.lua new file mode 100644 index 000000000..b3eab27c0 --- /dev/null +++ b/build/scripts/tools/unittests_server.lua @@ -0,0 +1,34 @@ +TOOL.Name = "UnitTestsServer" + +TOOL.Directory = "../tests" +TOOL.EnableConsole = true +TOOL.Kind = "Application" +TOOL.TargetDirectory = TOOL.Directory + +TOOL.Defines = { + "NDK_SERVER" +} + +TOOL.Includes = { + "../include" +} + +TOOL.Files = { + "../tests/main.cpp", + "../tests/Engine/**.cpp", + "../tests/SDK/**.cpp" +} + +-- Excludes client-only files +TOOL.FilesExcluded = { + "../tests/Engine/Audio/**", + "../tests/Engine/Graphics/**", + "../tests/SDK/NDK/Application.cpp", + "../tests/SDK/NDK/Systems/ListenerSystem.cpp", + "../tests/SDK/NDK/Systems/RenderSystem.cpp" +} + +TOOL.Libraries = { + "NazaraNetwork", + "NazaraSDKServer" +} diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index b8a3206af..be25f4773 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -38,11 +39,13 @@ namespace Nz struct TypeTag {}; inline bool Serialize(SerializationContext& context, bool value); + inline bool Serialize(SerializationContext& context, const std::string& value); template std::enable_if_t::value, bool> Serialize(SerializationContext& context, T value); inline bool Unserialize(SerializationContext& context, bool* value); + inline bool Unserialize(SerializationContext& context, std::string* value); template std::enable_if_t::value, bool> Unserialize(SerializationContext& context, T* value); diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index 0cadd1631..4008f8860 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -6,6 +6,7 @@ // Merci à Ryan "FullMetal Alchemist" Lahfa // Merci aussi à Freedom de siteduzero.com +#include #include #include #include @@ -192,7 +193,7 @@ namespace Nz /*! * \ingroup core * \brief Serializes a boolean - * \return true if serialization succedeed + * \return true if serialization succeeded * * \param context Context for the serialization * \param value Boolean to serialize @@ -216,10 +217,26 @@ namespace Nz return true; } + /*! + * \ingroup core + * \brief Serializes a std::string + * \return true if successful + * + * \param context Context for the serialization + * \param value String to serialize + */ + bool Serialize(SerializationContext& context, const std::string& value) + { + if (!Serialize(context, UInt32(value.size()))) + return false; + + return context.stream->Write(value.data(), value.size()) == value.size(); + } + /*! * \ingroup core * \brief Serializes an arithmetic type - * \return true if serialization succedeed + * \return true if serialization succeeded * * \param context Context for the serialization * \param value Arithmetic type to serialize @@ -266,6 +283,23 @@ namespace Nz return true; } + /*! + * \brief Unserializes a string + * \return true if successful + * + * \param context Context of unserialization + * \param string std::string to unserialize + */ + bool Unserialize(SerializationContext& context, std::string* string) + { + UInt32 size; + if (!Unserialize(context, &size)) + return false; + + string->resize(size); + return context.stream->Read(&string[0], size) == size; + } + /*! * \ingroup core * \brief Unserializes an arithmetic type diff --git a/include/Nazara/Core/Bitset.hpp b/include/Nazara/Core/Bitset.hpp index e4e2d8042..5c2746d16 100644 --- a/include/Nazara/Core/Bitset.hpp +++ b/include/Nazara/Core/Bitset.hpp @@ -64,6 +64,9 @@ namespace Nz void Set(std::size_t bit, bool val = true); void SetBlock(std::size_t i, Block block); + void ShiftLeft(std::size_t pos); + void ShiftRight(std::size_t pos); + void Swap(Bitset& bitset); bool Test(std::size_t bit) const; @@ -88,6 +91,12 @@ namespace Nz template Bitset& operator=(T value); Bitset& operator=(Bitset&& bitset) noexcept = default; + Bitset operator<<(std::size_t pos) const; + Bitset& operator<<=(std::size_t pos); + + Bitset operator>>(std::size_t pos) const; + Bitset& operator>>=(std::size_t pos); + Bitset& operator&=(const Bitset& bitset); Bitset& operator|=(const Bitset& bitset); Bitset& operator^=(const Bitset& bitset); diff --git a/include/Nazara/Core/Bitset.inl b/include/Nazara/Core/Bitset.inl index d29315afd..6ddb252e7 100644 --- a/include/Nazara/Core/Bitset.inl +++ b/include/Nazara/Core/Bitset.inl @@ -2,8 +2,10 @@ // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp +#include #include #include +#include #include #include #include @@ -512,12 +514,117 @@ namespace Nz ResetExtraBits(); } + /*! + * \brief Shift all the bits toward the left + * + * \param pos Bit shifting to be applied + * + * \remark This does not changes the size of the bitset. + * + * \see operator<<= + */ + template + void Bitset::ShiftLeft(std::size_t pos) + { + if (pos == 0) + return; + + if (pos >= m_bitCount) + { + Reset(); + return; + } + + auto div = std::lldiv(pos, bitsPerBlock); + if (div.rem != 0) + { + std::size_t lastIndex = m_blocks.size() - 1; + std::size_t remaining = bitsPerBlock - div.rem; + + 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); + + m_blocks[div.quot] = m_blocks[0] << div.rem; + + std::fill_n(m_blocks.begin(), div.quot, 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()) + { + auto shiftedIt = it; + std::advance(shiftedIt, div.quot); + + *it = *shiftedIt; + } + else + *it = 0U; + } + } + + ResetExtraBits(); + } + + /*! + * \brief Shift all the bits toward the right + * + * \param pos Bit shifting to be applied + * + * \remark This does not changes the size of the bitset. + * + * \see operator>>= + */ + template + void Bitset::ShiftRight(std::size_t pos) + { + if (pos == 0) + return; + + if (pos >= m_bitCount) + { + Reset(); + return; + } + + auto div = std::lldiv(pos, bitsPerBlock); + if (div.rem != 0) + { + std::size_t lastIndex = m_blocks.size() - 1; + std::size_t remaining = bitsPerBlock - div.rem; + + 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); + + m_blocks[lastIndex - div.quot] = m_blocks[lastIndex] >> div.rem; + + std::fill_n(m_blocks.begin() + (m_blocks.size() - div.quot), div.quot, 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()) + { + auto shiftedIt = it; + std::advance(shiftedIt, div.quot); + + *it = *shiftedIt; + } + else + *it = 0U; + } + } + + ResetExtraBits(); + } + /*! * \brief Swaps the two bitsets * * \param bitset Other bitset to swap */ - template void Bitset::Swap(Bitset& bitset) { @@ -763,6 +870,80 @@ namespace Nz return *this; } + /*! + * \brief Shift all the bits toward the left + * + * \param pos Bit shifting to be applied + * + * \return A copies of the bitset with shifted bits + * + * \remark This does not changes the size of the bitset. + * + * \see ShiftLeft + */ + template + Bitset Bitset::operator<<(std::size_t pos) const + { + Bitset bitset(*this); + return bitset <<= pos; + } + + /*! + * \brief Shift all the bits toward the left + * + * \param pos Bit shifting to be applied + * + * \return A reference to this + * + * \remark This does not changes the size of the bitset. + * + * \see ShiftLeft + */ + template + Bitset& Bitset::operator<<=(std::size_t pos) + { + ShiftLeft(pos); + + return *this; + } + + /*! + * \brief Shift all the bits toward the right + * + * \param pos Bit shifting to be applied + * + * \return A copies of the bitset with shifted bits + * + * \remark This does not changes the size of the bitset. + * + * \see ShiftRight + */ + template + Bitset Bitset::operator>>(std::size_t pos) const + { + Bitset bitset(*this); + return bitset >>= pos; + } + + /*! + * \brief Shift all the bits toward the right + * + * \param pos Bit shifting to be applied + * + * \return A reference to this + * + * \remark This does not changes the size of the bitset. + * + * \see ShiftRight + */ + template + Bitset& Bitset::operator>>=(std::size_t pos) + { + ShiftRight(pos); + + return *this; + } + /*! * \brief Performs an "AND" with another bitset * \return A reference to this diff --git a/include/Nazara/Core/Config.hpp b/include/Nazara/Core/Config.hpp index 955b98c75..2ad2513ac 100644 --- a/include/Nazara/Core/Config.hpp +++ b/include/Nazara/Core/Config.hpp @@ -72,8 +72,8 @@ // Number of spinlocks to use with the Windows critical sections (0 to disable) #define NAZARA_CORE_WINDOWS_CS_SPINLOCKS 4096 -// Optimize the Windows implementation with technologies of Windows vista (and greather) (Break the compatibility with XP) -#define NAZARA_CORE_WINDOWS_VISTA 0 +// Optimize the Windows implementation with technologies of Windows NT 6.0 (and greater) (Break the compatibility with Windows XP) +#define NAZARA_CORE_WINDOWS_NT6 0 /* diff --git a/include/Nazara/Core/Log.hpp b/include/Nazara/Core/Log.hpp index fa8e9b6d0..fc64c8a49 100644 --- a/include/Nazara/Core/Log.hpp +++ b/include/Nazara/Core/Log.hpp @@ -8,6 +8,7 @@ #define NAZARA_LOG_HPP #include +#include #include #include #include @@ -29,8 +30,6 @@ namespace Nz { - class AbstractLogger; - class NAZARA_CORE_API Log { friend class Core; diff --git a/include/Nazara/Core/MemoryHelper.hpp b/include/Nazara/Core/MemoryHelper.hpp index e2f295622..e2ed7fc3e 100644 --- a/include/Nazara/Core/MemoryHelper.hpp +++ b/include/Nazara/Core/MemoryHelper.hpp @@ -7,6 +7,27 @@ #ifndef NAZARA_MEMORYHELPER_HPP #define NAZARA_MEMORYHELPER_HPP +#if defined(NAZARA_COMPILER_MSVC) || defined(NAZARA_COMPILER_MINGW) + +#include + +#define NAZARA_ALLOCA(size) _alloca(size) +#define NAZARA_ALLOCA_SUPPORT + +#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL) +#include + +#define NAZARA_ALLOCA(size) alloca(size) +#define NAZARA_ALLOCA_SUPPORT + +#endif + +#ifdef NAZARA_ALLOCA_SUPPORT + #define NazaraStackAllocation(size) Nz::StackAllocation(NAZARA_ALLOCA(size)) +#else + #define NazaraStackAllocation(size) Nz::StackAllocation(Nz::OperatorNew(size)) +#endif + #include namespace Nz @@ -16,6 +37,20 @@ namespace Nz template T* PlacementNew(T* ptr, Args&&... args); + + class StackAllocation + { + public: + explicit StackAllocation(void* stackMemory); + ~StackAllocation(); + + void* GetPtr(); + + operator void*(); + + private: + void* m_ptr; + }; } #include diff --git a/include/Nazara/Core/MemoryHelper.inl b/include/Nazara/Core/MemoryHelper.inl index 23a745a44..d3fe43155 100644 --- a/include/Nazara/Core/MemoryHelper.inl +++ b/include/Nazara/Core/MemoryHelper.inl @@ -9,6 +9,7 @@ #define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION #endif +#include #include #include #include @@ -62,6 +63,51 @@ namespace Nz { return new (ptr) T(std::forward(args)...); } + + /*! + * \ingroup core + * \class Nz::StackAllocation + * \brief Core class that represents a stack allocation + */ + + + /*! + * \brief Constructs a StackAllocation object with a pointer to a memory allocated with NAZARA_ALLOCA or OperatorNew is alloca is not supported + * + * \param ptr Pointer to raw memory + */ + inline StackAllocation::StackAllocation(void* stackMemory) : + m_ptr(stackMemory) + { + } + + /*! + * \brief Destructs the object and release memory if necessary + */ + inline StackAllocation::~StackAllocation() + { + #ifndef NAZARA_ALLOCA_SUPPORT + OperatorDelete(m_ptr); + #endif + } + + /*! + * \brief Access the internal pointer + * \return internal memory pointer + */ + inline void* StackAllocation::GetPtr() + { + return m_ptr; + } + + /*! + * \brief Access the internal pointer + * \return internal memory pointer + */ + inline StackAllocation::operator void*() + { + return m_ptr; + } } #include diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index 0195c123c..c317001a1 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -1,4 +1,4 @@ -// This file was automatically generated on 20 Jul 2016 at 13:49:17 +// This file was automatically generated on 15 Sep 2016 at 00:43:26 /* Nazara Engine - Graphics module @@ -58,10 +58,14 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include #include #include #include @@ -77,5 +81,6 @@ #include #include #include +#include #endif // NAZARA_GLOBAL_GRAPHICS_HPP diff --git a/include/Nazara/Graphics/ForwardRenderTechnique.inl b/include/Nazara/Graphics/ForwardRenderTechnique.inl index 6490513f8..5f7ba181f 100644 --- a/include/Nazara/Graphics/ForwardRenderTechnique.inl +++ b/include/Nazara/Graphics/ForwardRenderTechnique.inl @@ -38,19 +38,25 @@ namespace Nz shader->SendVector(uniforms.locations.factors + uniformOffset, Vector2f(light.ambientFactor, light.diffuseFactor)); shader->SendVector(uniforms.locations.parameters1 + uniformOffset, Vector4f(light.direction)); - shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr); + if (uniforms.locations.shadowMapping != -1) + shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr); + if (light.shadowMap) { Renderer::SetTexture(availableTextureUnit, light.shadowMap); Renderer::SetTextureSampler(availableTextureUnit, s_shadowSampler); - shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix); - shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, availableTextureUnit); + if (uniforms.locations.lightViewProjMatrix != -1) + shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix); + + if (uniforms.locations.directionalSpotLightShadowMap != -1) + shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, availableTextureUnit); } - else + else if (uniforms.locations.directionalSpotLightShadowMap != -1) shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture); - shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); + if (uniforms.locations.directionalSpotLightShadowMap != -1) + shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); break; } @@ -63,18 +69,22 @@ namespace Nz shader->SendVector(uniforms.locations.parameters1 + uniformOffset, Vector4f(light.position, light.attenuation)); shader->SendVector(uniforms.locations.parameters2 + uniformOffset, Vector4f(0.f, 0.f, 0.f, light.invRadius)); - shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr); + if (uniforms.locations.shadowMapping != -1) + shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr); + if (light.shadowMap) { Renderer::SetTexture(availableTextureUnit, light.shadowMap); Renderer::SetTextureSampler(availableTextureUnit, s_shadowSampler); - shader->SendInteger(uniforms.locations.pointLightShadowMap + index, availableTextureUnit); + if (uniforms.locations.pointLightShadowMap != -1) + shader->SendInteger(uniforms.locations.pointLightShadowMap + index, availableTextureUnit); } - else + else if (uniforms.locations.pointLightShadowMap != -1) shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); - shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture); + if (uniforms.locations.directionalSpotLightShadowMap != -1) + shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture); break; } @@ -88,19 +98,25 @@ namespace Nz shader->SendVector(uniforms.locations.parameters2 + uniformOffset, Vector4f(light.direction, light.invRadius)); shader->SendVector(uniforms.locations.parameters3 + uniformOffset, Vector2f(light.innerAngleCosine, light.outerAngleCosine)); - shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr); + if (uniforms.locations.shadowMapping != -1) + shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr); + if (light.shadowMap) { Renderer::SetTexture(availableTextureUnit, light.shadowMap); Renderer::SetTextureSampler(availableTextureUnit, s_shadowSampler); - shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix); - shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, availableTextureUnit); + if (uniforms.locations.lightViewProjMatrix != -1) + shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix); + + if (uniforms.locations.directionalSpotLightShadowMap != -1) + shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, availableTextureUnit); } - else + else if (uniforms.locations.directionalSpotLightShadowMap != -1) shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture); - shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); + if (uniforms.locations.pointLightShadowMap != -1) + shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); break; } @@ -108,9 +124,14 @@ namespace Nz } else { - shader->SendInteger(uniforms.locations.type + uniformOffset, -1); //< Disable the light in the shader - shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture); - shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); + if (uniforms.locations.type != -1) + shader->SendInteger(uniforms.locations.type + uniformOffset, -1); //< Disable the light in the shader + + if (uniforms.locations.directionalSpotLightShadowMap != -1) + shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture); + + if (uniforms.locations.pointLightShadowMap != -1) + shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap); } } diff --git a/include/Nazara/Graphics/ParticleStruct.hpp b/include/Nazara/Graphics/ParticleStruct.hpp index 72ce961b9..895e8fca2 100644 --- a/include/Nazara/Graphics/ParticleStruct.hpp +++ b/include/Nazara/Graphics/ParticleStruct.hpp @@ -17,6 +17,7 @@ namespace Nz struct ParticleStruct_Billboard { Color color; + Vector2f size; Vector3f normal; Vector3f position; Vector3f velocity; diff --git a/include/Nazara/Graphics/TileMap.hpp b/include/Nazara/Graphics/TileMap.hpp index 89a901b9a..02371c33c 100644 --- a/include/Nazara/Graphics/TileMap.hpp +++ b/include/Nazara/Graphics/TileMap.hpp @@ -41,6 +41,8 @@ namespace Nz inline void DisableTiles(); inline void DisableTiles(const Vector2ui* tilesPos, std::size_t tileCount); + inline void EnableIsometricMode(bool isometric); + inline void EnableTile(const Vector2ui& tilePos, const Rectf& coords, const Color& color = Color::White, std::size_t materialIndex = 0U); inline void EnableTile(const Vector2ui& tilePos, const Rectui& rect, const Color& color = Color::White, std::size_t materialIndex = 0U); inline void EnableTiles(const Rectf& coords, const Color& color = Color::White, std::size_t materialIndex = 0U); @@ -55,6 +57,8 @@ namespace Nz inline const Tile& GetTile(const Vector2ui& tilePos) const; inline const Vector2f& GetTileSize() const; + inline bool IsIsometricModeEnabled() const; + inline void SetMaterial(std::size_t index, MaterialRef material); inline TileMap& operator=(const TileMap& TileMap); @@ -87,6 +91,7 @@ namespace Nz std::vector m_layers; Vector2ui m_mapSize; Vector2f m_tileSize; + bool m_isometricModeEnabled; static TileMapLibrary::LibraryMap s_library; }; diff --git a/include/Nazara/Graphics/TileMap.inl b/include/Nazara/Graphics/TileMap.inl index 405683f40..4473a8600 100644 --- a/include/Nazara/Graphics/TileMap.inl +++ b/include/Nazara/Graphics/TileMap.inl @@ -25,7 +25,8 @@ namespace Nz m_tiles(mapSize.x * mapSize.y), m_layers(materialCount), m_mapSize(mapSize), - m_tileSize(tileSize) + m_tileSize(tileSize), + m_isometricModeEnabled(false) { NazaraAssert(m_tiles.size() != 0U, "Invalid map size"); NazaraAssert(m_tileSize.x != 0U && m_tileSize.y != 0U, "Invalid tile size"); @@ -108,6 +109,22 @@ namespace Nz InvalidateInstanceData(invalidatedLayers); } + /*! + * \brief Enable/Disable isometric mode + * + * If enabled, every odd line will overlap by half the tile size with the upper line + * + * \param isometric Should the isometric mode be enabled for this TileMap + * + * \see IsIsometricModeEnabled + */ + inline void TileMap::EnableIsometricMode(bool isometric) + { + m_isometricModeEnabled = isometric; + + InvalidateInstanceData(0xFFFFFFFF); + } + /*! * \brief Enable and sets the tile at position tilePos * @@ -387,6 +404,17 @@ namespace Nz return m_tileSize; } + /*! + * \brief Gets the actual state of the isometric mode + * \return True if the isometric mode is enabled + * + * \see EnableIsometricMode + */ + inline bool TileMap::IsIsometricModeEnabled() const + { + return m_isometricModeEnabled; + } + /*! * \brief Sets a material of the TileMap * diff --git a/include/Nazara/Lua/LuaClass.hpp b/include/Nazara/Lua/LuaClass.hpp index b872ad2f7..567c3de7c 100644 --- a/include/Nazara/Lua/LuaClass.hpp +++ b/include/Nazara/Lua/LuaClass.hpp @@ -28,7 +28,7 @@ namespace Nz public: using ClassFunc = std::function; using ClassIndexFunc = std::function; - using ConstructorFunc = std::function; + using ConstructorFunc = std::function; template using ConvertToParent = std::function; using FinalizerFunc = std::function; using StaticIndexFunc = std::function; diff --git a/include/Nazara/Lua/LuaClass.inl b/include/Nazara/Lua/LuaClass.inl index 89487b653..ea53cf0cd 100644 --- a/include/Nazara/Lua/LuaClass.inl +++ b/include/Nazara/Lua/LuaClass.inl @@ -19,9 +19,10 @@ namespace Nz template inline void LuaClass::BindDefaultConstructor() { - SetConstructor([] (Nz::LuaInstance& lua, T* instance) + SetConstructor([] (Nz::LuaInstance& lua, T* instance, std::size_t argumentCount) { NazaraUnused(lua); + NazaraUnused(argumentCount); PlacementNew(instance); return true; @@ -334,9 +335,11 @@ namespace Nz lua.Remove(1); // On enlève l'argument "table" du stack + std::size_t argCount = lua.GetStackTop(); + T* instance = static_cast(lua.PushUserdata(sizeof(T))); - if (!constructor(lua, instance)) + if (!constructor(lua, instance, argCount)) { lua.Error("Constructor failed"); return 0; // Normalement jamais exécuté (l'erreur provoquant une exception) diff --git a/include/Nazara/Lua/LuaInstance.inl b/include/Nazara/Lua/LuaInstance.inl index e6a4b5482..c5cdc3b6b 100644 --- a/include/Nazara/Lua/LuaInstance.inl +++ b/include/Nazara/Lua/LuaInstance.inl @@ -16,11 +16,11 @@ namespace Nz inline LuaInstance::LuaInstance(LuaInstance&& instance) noexcept : m_memoryLimit(instance.m_memoryLimit), m_memoryUsage(instance.m_memoryUsage), - m_timeLimit(m_timeLimit), - m_clock(std::move(m_clock)), - m_lastError(std::move(m_lastError)), - m_state(m_state), - m_level(m_level) + m_timeLimit(instance.m_timeLimit), + m_clock(std::move(instance.m_clock)), + m_lastError(std::move(instance.m_lastError)), + m_state(instance.m_state), + m_level(instance.m_level) { instance.m_state = nullptr; } @@ -52,13 +52,13 @@ namespace Nz inline LuaInstance& LuaInstance::operator=(LuaInstance&& instance) noexcept { - m_clock = std::move(m_clock); - m_lastError = std::move(m_lastError); - m_level = m_level; + m_clock = std::move(instance.m_clock); + m_lastError = std::move(instance.m_lastError); + m_level = instance.m_level; m_memoryLimit = instance.m_memoryLimit; m_memoryUsage = instance.m_memoryUsage; - m_state = m_state; - m_timeLimit = m_timeLimit; + m_state = instance.m_state; + m_timeLimit = instance.m_timeLimit; instance.m_state = nullptr; diff --git a/include/Nazara/Network/SocketPoller.hpp b/include/Nazara/Network/SocketPoller.hpp new file mode 100644 index 000000000..0684ef41f --- /dev/null +++ b/include/Nazara/Network/SocketPoller.hpp @@ -0,0 +1,44 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Network module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SOCKETPOLLER_HPP +#define NAZARA_SOCKETPOLLER_HPP + +#include +#include +#include + +namespace Nz +{ + class SocketPollerImpl; + + class NAZARA_NETWORK_API SocketPoller + { + public: + SocketPoller(); + inline SocketPoller(SocketPoller&& socketPoller); + ~SocketPoller(); + + void Clear(); + + bool IsReady(const AbstractSocket& socket) const; + bool IsRegistered(const AbstractSocket& socket) const; + + bool RegisterSocket(AbstractSocket& socket); + void UnregisterSocket(AbstractSocket& socket); + + bool Wait(UInt64 msTimeout); + + inline SocketPoller& operator=(SocketPoller&& socketPoller); + + private: + SocketPollerImpl* m_impl; + }; +} + +#include + +#endif // NAZARA_SOCKETPOLLER_HPP \ No newline at end of file diff --git a/include/Nazara/Network/SocketPoller.inl b/include/Nazara/Network/SocketPoller.inl new file mode 100644 index 000000000..c3e415508 --- /dev/null +++ b/include/Nazara/Network/SocketPoller.inl @@ -0,0 +1,37 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Network module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + /*! + * \brief Constructs a SocketPoller object with another one by move semantic + * + * \param socketPoller SocketPoller to move into this + */ + inline SocketPoller::SocketPoller(SocketPoller&& socketPoller) : + m_impl(socketPoller.m_impl) + { + socketPoller.m_impl = nullptr; + } + + /*! + * \brief Moves the SocketPoller into this + * \return A reference to this + * + * \param socketPoller SocketPoller to move in this + */ + inline SocketPoller& SocketPoller::operator=(SocketPoller&& socketPoller) + { + m_impl = socketPoller.m_impl; + socketPoller.m_impl = nullptr; + + return *this; + } +} + +#include diff --git a/include/Nazara/Noise/Simplex.hpp b/include/Nazara/Noise/Simplex.hpp index ae018f7bf..4f33c24ff 100644 --- a/include/Nazara/Noise/Simplex.hpp +++ b/include/Nazara/Noise/Simplex.hpp @@ -2,8 +2,8 @@ // This file is part of the "Nazara Engine - Noise module" // For conditions of distribution and use, see copyright notice in Config.hpp -#ifndef SIMPLEX_HPP -#define SIMPLE_HPP +#ifndef NAZARA_SIMPLEX_HPP +#define NAZARA_SIMPLEX_HPP #include #include @@ -25,4 +25,4 @@ namespace Nz }; } -#endif // SIMPLEX_HPP +#endif // NAZARA_SIMPLEX_HPP diff --git a/include/Nazara/Prerequesites.hpp b/include/Nazara/Prerequesites.hpp index c2c83626a..bf9d1d75f 100644 --- a/include/Nazara/Prerequesites.hpp +++ b/include/Nazara/Prerequesites.hpp @@ -74,9 +74,10 @@ #error Nazara requires a C++11 compliant compiler #endif -// Version du moteur +// Nazara version macro #define NAZARA_VERSION_MAJOR 0 #define NAZARA_VERSION_MINOR 1 +#define NAZARA_VERSION_PATCH 1 #include @@ -97,7 +98,7 @@ #define NOMINMAX #endif - #if NAZARA_CORE_WINDOWS_VISTA + #if NAZARA_CORE_WINDOWS_NT6 // Version de Windows minimale : Vista #define NAZARA_WINNT 0x0600 #else diff --git a/include/Nazara/Utility/Formats/OBJParser.hpp b/include/Nazara/Utility/Formats/OBJParser.hpp index 6c0c35af4..82c1220bf 100644 --- a/include/Nazara/Utility/Formats/OBJParser.hpp +++ b/include/Nazara/Utility/Formats/OBJParser.hpp @@ -29,6 +29,8 @@ namespace Nz inline void Clear(); + bool Check(Stream& stream); + inline String* GetMaterials(); inline const String* GetMaterials() const; inline UInt32 GetMaterialCount() const; diff --git a/include/Nazara/Utility/Utility.hpp b/include/Nazara/Utility/Utility.hpp index 1beb98bcc..31ec543ee 100644 --- a/include/Nazara/Utility/Utility.hpp +++ b/include/Nazara/Utility/Utility.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -24,12 +25,15 @@ namespace Nz static bool IsInitialized(); + static void SetParameters(const ParameterList& parameters); + static void Uninitialize(); static unsigned int ComponentCount[ComponentType_Max+1]; static std::size_t ComponentStride[ComponentType_Max+1]; private: + static ParameterList s_initializationParameters; static unsigned int s_moduleReferenceCounter; }; } diff --git a/include/Nazara/Utility/Window.inl b/include/Nazara/Utility/Window.inl index 39c530e24..4eedf2d9e 100644 --- a/include/Nazara/Utility/Window.inl +++ b/include/Nazara/Utility/Window.inl @@ -55,11 +55,6 @@ namespace Nz window.m_impl = nullptr; } - inline Window::~Window() - { - Destroy(); - } - inline void Window::Close() { m_closed = true; // The window will be closed at the next non-const IsOpen() call @@ -85,6 +80,26 @@ namespace Nz return m_eventHandler; } + inline void Window::EnableCloseOnQuit(bool closeOnQuit) + { + m_closeOnQuit = closeOnQuit; + } + + inline void Window::EnableEventPolling(bool enable) + { + m_eventPolling = enable; + if (!m_eventPolling) + { + while (!m_events.empty()) + m_events.pop(); + } + } + + inline EventHandler& Nz::Window::GetEventHandler() + { + return m_eventHandler; + } + inline bool Window::IsOpen(bool checkClosed) { if (!m_impl) @@ -146,7 +161,7 @@ namespace Nz { Destroy(); - m_closed = window.m_closed; + m_closed = window.m_closed; m_closeOnQuit = window.m_closeOnQuit; m_eventPolling = window.m_eventPolling; m_impl = window.m_impl; diff --git a/readme.md b/readme.md index 90a30fda5..edb58080e 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,9 @@ -Nazara Engine -============= +Platform | Build Status +------------ | ------------- +Windows | [![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/dj5qx7axym4uakmy/branch/master?svg=true)](https://ci.appveyor.com/project/DPSLynix/nazaraengine/branch/master) +Linux | [![Travis CI Build Status](https://travis-ci.org/DigitalPulseSoftware/NazaraEngine.svg)](https://travis-ci.org/DigitalPulseSoftware/NazaraEngine) + +# Nazara Engine Nazara Engine is a fast, complete, cross-platform, object-oriented API which can help you in your daily developper life. Its goal is to provide a set of useful classes : Its core provides unicode strings, filesystem access, hashs, threads, ... @@ -8,26 +12,22 @@ It also provide a set of libraries, such as audio, network, physics, renderer, 2 You can use it in any kind of commercial/non-commercial applications without any restriction ([MIT license](http://opensource.org/licenses/MIT)). -Authors -------- +## Authors Jérôme "Lynix" Leclercq - main developper () Rémi "overdrivr" Bèges - developper & helper - Noise Module - () -Install -------- +## Install Use the premake build system in the build directory then compile the engine for your platform. -How to use ----------- +## How to use You can find tutorials on installation, compilation and use on the [official wiki](https://github.com/DigitalPulseSoftware/NazaraEngine/wiki) -Contribute ----------- +## Contribute -#####Don't hesitate to contribute to Nazara Engine by:##### +##### Don't hesitate to contribute to Nazara Engine by: - Extending the [wiki](https://github.com/DigitalPulseSoftware/NazaraEngine/wiki) - Submitting a patch to GitHub - Post suggestions/bugs on the forum or the [GitHub tracker](https://github.com/DigitalPulseSoftware/NazaraEngine/issues) @@ -35,14 +35,17 @@ Contribute - Talking about Nazara Engine to other people - Doing anything else that might help us -Links ------ -[Website](http://www.digitalpulsesoftware.net) -[Wiki](https://github.com/DigitalPulseSoftware/NazaraEngine/wiki) -[Forum](http://forum.digitalpulsesoftware.net) +## Links + +[Website](https://nazara.digitalpulsesoftware.net) +[Documentation](https://nazara.digitalpulsesoftware.net/doc) +[Mattermost](https://mattermost.digitalpulsesoftware.net) +[Wiki](https://github.com/DigitalPulseSoftware/NazaraEngine/wiki) +[Forum](https://forum.digitalpulsesoftware.net) + +## Thanks to: -###Thanks to:### - **RafBill** and **Raakz:** Finding bugs and/or testing - **Fissal "DrFisher" Hannoun**: Helping a lot in architecture design - **Alexandre "Danman" Janniaux**: Helping making the POSIX implementation -- **Youri "Gawaboumga" Hubaut**: Improving the engine code by merging on GitHub +- **Youri "Gawaboumga" Hubaut**: Improving the whole project by making the documentation, improving the code, and more. diff --git a/readme_fr.md b/readme_fr.md index fd0f42e7b..d7aff37b9 100644 --- a/readme_fr.md +++ b/readme_fr.md @@ -1,5 +1,9 @@ -Nazara Engine -============= +Platforme | Build Status +------------ | ------------- +Windows | [![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/dj5qx7axym4uakmy/branch/master?svg=true)](https://ci.appveyor.com/project/DPSLynix/nazaraengine/branch/master) +Linux | [![Travis CI Build Status](https://travis-ci.org/DigitalPulseSoftware/NazaraEngine.svg)](https://travis-ci.org/DigitalPulseSoftware/NazaraEngine) + +# Nazara Engine Nazara Engine est une API rapide, complète, portable et orientée-objet qui peut vous aider dans votre vie de développeur de tous les jours. Son objectif est de fournir un ensemble de classes utiles : Son noyau dispose de chaînes de caractères unicode, de gestion du système de fichiers, hashs, threads, ... @@ -8,26 +12,22 @@ Il propose aussi un ensemble de bibliothèques, comme audio, réseau, physique, Vous pouvez également l'utiliser pour toute application commerciale sans aucune contrainte ([Licence MIT](http://opensource.org/licenses/MIT)). -Auteurs -------- +## Auteurs Jérôme "Lynix" Leclercq - développeur principal () Rémi "overdrivr" Bèges - développeur & aide - module Noise - () -Installation ------------- +## Installation Utilisez le système premake pour construire le projet du moteur, dans le dossier build, pour ensuite compiler le moteur pour votre plateforme. -Utilisation ------------ +## Utilisation Vous pouvez lire des tutoriaux sur l'installation, la compilation et l'utilisation sur le [wiki officiel](https://github.com/DigitalPulseSoftware/NazaraEngine/wiki) (**\*En cours de rédaction***) -Contribution ----------- +## Contribution -#####N'hésitez pas à contribuer à Nazara Engine en :##### +##### N'hésitez pas à contribuer à Nazara Engine en : - Contribuant au [wiki](https://github.com/DigitalPulseSoftware/NazaraEngine/wiki) (**\*Lien brisé***) - Soumettant un patch sur GitHub - Postant des suggestions/bugs sur le forum ou sur le [tracker GitHub](https://github.com/DigitalPulseSoftware/NazaraEngine/issues) @@ -35,14 +35,17 @@ Contribution - Parlant du Nazara Engine à d'autres personnes - Faisant n'importe quoi d'autre qui pourrait nous aider -Liens ------ -[Website](http://www.digitalpulsesoftware.net) -[Wiki](https://github.com/DigitalPulseSoftware/NazaraEngine/wiki) -[Forum](http://forum.digitalpulsesoftware.net) +## Liens + +[Website](https://nazara.digitalpulsesoftware.net) +[Documentation](https://nazara.digitalpulsesoftware.net/doc) +[Mattermost](https://mattermost.digitalpulsesoftware.net) +[Wiki](https://github.com/DigitalPulseSoftware/NazaraEngine/wiki) +[Forum](https://forum.digitalpulsesoftware.net) + +###Remerciements: -###Remerciements:### - **RafBill** et **Raakz:** Recherche de bugs et/ou tests - **Fissal "DrFisher" Hannoun**: Aide et conseils lors de la conception de l'architecture du moteur - **Alexandre "Danman" Janniaux**: Aide sur l'implémentation POSIX -- **Youri "Gawaboumga" Hubaut**: Amélioration du code via le merging sur GitHub +- **Youri "Gawaboumga" Hubaut**: Amélioration du moteur tant au niveau du code que de sa documentation et du projet en général. diff --git a/src/Nazara/Core/Posix/HardwareInfoImpl.cpp b/src/Nazara/Core/Posix/HardwareInfoImpl.cpp index 0058832a8..20ea4950f 100644 --- a/src/Nazara/Core/Posix/HardwareInfoImpl.cpp +++ b/src/Nazara/Core/Posix/HardwareInfoImpl.cpp @@ -11,10 +11,22 @@ namespace Nz void HardwareInfoImpl::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4]) { #if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL) - // Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c - asm volatile ("cpuid" // Besoin d'être volatile ? - : "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output - : "a" (functionId), "c" (subFunctionId)); // input + // https://en.wikipedia.org/wiki/CPUID + asm volatile( + #ifdef NAZARA_PLATFORM_x64 + "pushq %%rbx \n\t" // save %rbx + #else + "pushl %%ebx \n\t" // save %ebx + #endif + "cpuid \n\t" + "movl %%ebx ,%[ebx] \n\t" // write the result into output var + #ifdef NAZARA_PLATFORM_x64 + "popq %%rbx \n\t" + #else + "popl %%ebx \n\t" + #endif + : "=a"(registers[0]), [ebx] "=r"(registers[1]), "=c"(registers[2]), "=d"(registers[3]) + : "a"(functionId), "c" (subFunctionId)); #else NazaraInternalError("Cpuid has been called although it is not supported"); #endif @@ -22,7 +34,7 @@ namespace Nz unsigned int HardwareInfoImpl::GetProcessorCount() { - // Plus simple (et plus portable) que de passer par le CPUID + // Simpler (and more portable) than using CPUID return sysconf(_SC_NPROCESSORS_CONF); } @@ -37,7 +49,7 @@ namespace Nz bool HardwareInfoImpl::IsCpuidSupported() { #ifdef NAZARA_PLATFORM_x64 - return true; // Toujours supporté sur un processeur 64 bits + return true; // cpuid is always supported on x64 arch #else #if defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL) int supported; diff --git a/src/Nazara/Core/Stream.cpp b/src/Nazara/Core/Stream.cpp index b36b67d85..f82591fed 100644 --- a/src/Nazara/Core/Stream.cpp +++ b/src/Nazara/Core/Stream.cpp @@ -44,14 +44,19 @@ namespace Nz } /*! - * \brief Reads characters in the stream + * \brief Reads a line from the stream + * + * Reads the stream until a line separator or the end of the stream is found. + * + * If lineSize does not equal zero, it represents the maximum character count to be read from the stream. + * + * \param lineSize Maximum number of characters to read, or zero for no limit + * * \return Line containing characters * - * \param lineSize Number of characters to read, if lineSize is 0, read as much as possible - * - * \remark Produces a NazaraWarning if cursor position could not be reset + * \remark With the text stream option, "\r\n" is treated as "\n" + * \remark The line separator character is not returned as part of the string */ - String Stream::ReadLine(unsigned int lineSize) { String line; @@ -71,19 +76,33 @@ namespace Nz if (ptr) { std::ptrdiff_t pos = ptr - buffer; - - if (m_streamOptions & StreamOption_Text && pos > 0 && buffer[pos - 1] == '\r') - line.Append(buffer, pos - 1); - else - line.Append(buffer, pos); + if (ptr != buffer) + { + if (m_streamOptions & StreamOption_Text && buffer[pos - 1] == '\r') + line.Append(buffer, pos - 1); + else + line.Append(buffer, pos); + } if (!SetCursorPos(GetCursorPos() - readSize + pos + 1)) - NazaraWarning("Failed to reset cursos pos"); + NazaraWarning("Failed to reset cursor pos"); - break; + if (!line.IsEmpty()) + break; } else - line.Append(buffer, readSize); + { + std::size_t length = readSize; + if (m_streamOptions & StreamOption_Text && buffer[length - 1] == '\r') + { + if (!SetCursorPos(GetCursorPos() - 1)) + NazaraWarning("Failed to reset cursor pos"); + + length--; + } + + line.Append(buffer, length); + } } while (readSize == bufferSize); } diff --git a/src/Nazara/Core/String.cpp b/src/Nazara/Core/String.cpp index fbd29c97c..5019f0885 100644 --- a/src/Nazara/Core/String.cpp +++ b/src/Nazara/Core/String.cpp @@ -3461,6 +3461,7 @@ namespace Nz p--; *p = '\0'; + newString->size = p - str; return String(std::move(newString)); } @@ -4552,7 +4553,7 @@ namespace Nz String& String::operator=(String&& string) noexcept { - return Set(string); + return Set(std::move(string)); } /*! @@ -5851,7 +5852,7 @@ namespace Nz if (!m_sharedString.unique()) { auto newSharedString = std::make_shared(GetSize(), GetCapacity()); - if (!discardContent) + if (!discardContent && newSharedString->size > 0) std::memcpy(newSharedString->string.get(), GetConstBuffer(), GetSize()+1); m_sharedString = std::move(newSharedString); @@ -5878,7 +5879,7 @@ namespace Nz */ bool Serialize(SerializationContext& context, const String& string) { - if (!Serialize(context, string.GetSize())) + if (!Serialize(context, UInt32(string.GetSize()))) return false; return context.stream->Write(string.GetConstBuffer(), string.GetSize()) == string.GetSize(); diff --git a/src/Nazara/Core/Win32/ConditionVariableImpl.cpp b/src/Nazara/Core/Win32/ConditionVariableImpl.cpp index 388a7f587..a387a7638 100644 --- a/src/Nazara/Core/Win32/ConditionVariableImpl.cpp +++ b/src/Nazara/Core/Win32/ConditionVariableImpl.cpp @@ -12,7 +12,7 @@ namespace Nz { ConditionVariableImpl::ConditionVariableImpl() { - #if NAZARA_CORE_WINDOWS_VISTA + #if NAZARA_CORE_WINDOWS_NT6 InitializeConditionVariable(&m_cv); #else m_count = 0; @@ -21,7 +21,7 @@ namespace Nz #endif } - #if !NAZARA_CORE_WINDOWS_VISTA + #if !NAZARA_CORE_WINDOWS_NT6 ConditionVariableImpl::~ConditionVariableImpl() { CloseHandle(m_events[BROADCAST]); @@ -31,7 +31,7 @@ namespace Nz void ConditionVariableImpl::Signal() { - #if NAZARA_CORE_WINDOWS_VISTA + #if NAZARA_CORE_WINDOWS_NT6 WakeConditionVariable(&m_cv); #else if (m_count > 0) @@ -41,7 +41,7 @@ namespace Nz void ConditionVariableImpl::SignalAll() { - #if NAZARA_CORE_WINDOWS_VISTA + #if NAZARA_CORE_WINDOWS_NT6 WakeAllConditionVariable(&m_cv); #else if (m_count > 0) @@ -56,8 +56,8 @@ namespace Nz bool ConditionVariableImpl::Wait(MutexImpl* mutex, UInt32 timeout) { - #if NAZARA_CORE_WINDOWS_VISTA - return SleepConditionVariableCS(&m_cv, &mutex->m_criticalSection, timeout); + #if NAZARA_CORE_WINDOWS_NT6 + return SleepConditionVariableCS(&m_cv, &mutex->m_criticalSection, timeout) == TRUE; #else m_count++; diff --git a/src/Nazara/Core/Win32/ConditionVariableImpl.hpp b/src/Nazara/Core/Win32/ConditionVariableImpl.hpp index a1bb70deb..469cf6099 100644 --- a/src/Nazara/Core/Win32/ConditionVariableImpl.hpp +++ b/src/Nazara/Core/Win32/ConditionVariableImpl.hpp @@ -21,7 +21,7 @@ namespace Nz { public: ConditionVariableImpl(); - #if NAZARA_CORE_WINDOWS_VISTA + #if NAZARA_CORE_WINDOWS_NT6 ~ConditionVariableImpl() = default; #else ~ConditionVariableImpl(); @@ -34,7 +34,7 @@ namespace Nz bool Wait(MutexImpl* mutex, UInt32 timeout); private: - #if NAZARA_CORE_WINDOWS_VISTA + #if NAZARA_CORE_WINDOWS_NT6 CONDITION_VARIABLE m_cv; #else enum diff --git a/src/Nazara/Core/Win32/HardwareInfoImpl.cpp b/src/Nazara/Core/Win32/HardwareInfoImpl.cpp index 62b86bf91..542c58d79 100644 --- a/src/Nazara/Core/Win32/HardwareInfoImpl.cpp +++ b/src/Nazara/Core/Win32/HardwareInfoImpl.cpp @@ -22,10 +22,22 @@ namespace Nz // Visual propose une fonction intrinsèque pour le cpuid __cpuidex(reinterpret_cast(registers), static_cast(functionId), static_cast(subFunctionId)); #elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL) - // Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c - asm volatile ("cpuid" // Besoin d'être volatile ? - : "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output - : "a" (functionId), "c" (subFunctionId)); // input + // https://en.wikipedia.org/wiki/CPUID + asm volatile( + #ifdef NAZARA_PLATFORM_x64 + "pushq %%rbx \n\t" // save %rbx + #else + "pushl %%ebx \n\t" // save %ebx + #endif + "cpuid \n\t" + "movl %%ebx ,%[ebx] \n\t" // write the result into output var + #ifdef NAZARA_PLATFORM_x64 + "popq %%rbx \n\t" + #else + "popl %%ebx \n\t" + #endif + : "=a"(registers[0]), [ebx] "=r"(registers[1]), "=c"(registers[2]), "=d"(registers[3]) // output + : "a"(functionId), "c" (subFunctionId)); // input #else NazaraInternalError("Cpuid has been called although it is not supported"); #endif @@ -33,7 +45,7 @@ namespace Nz unsigned int HardwareInfoImpl::GetProcessorCount() { - // Plus simple (et plus portable) que de passer par le CPUID + // Simpler (and more portable) than using CPUID SYSTEM_INFO infos; GetNativeSystemInfo(&infos); @@ -52,7 +64,7 @@ namespace Nz bool HardwareInfoImpl::IsCpuidSupported() { #ifdef NAZARA_PLATFORM_x64 - return true; // Toujours supporté sur un processeur 64 bits + return true; // cpuid is always supported on x64 arch #else #if defined(NAZARA_COMPILER_MSVC) int supported; diff --git a/src/Nazara/Graphics/ParticleDeclaration.cpp b/src/Nazara/Graphics/ParticleDeclaration.cpp index dff382d2c..ebd84e95d 100644 --- a/src/Nazara/Graphics/ParticleDeclaration.cpp +++ b/src/Nazara/Graphics/ParticleDeclaration.cpp @@ -291,6 +291,7 @@ namespace Nz declaration->EnableComponent(ParticleComponent_Normal, ComponentType_Float3, NazaraOffsetOf(ParticleStruct_Billboard, normal)); declaration->EnableComponent(ParticleComponent_Position, ComponentType_Float3, NazaraOffsetOf(ParticleStruct_Billboard, position)); declaration->EnableComponent(ParticleComponent_Rotation, ComponentType_Float1, NazaraOffsetOf(ParticleStruct_Billboard, rotation)); + declaration->EnableComponent(ParticleComponent_Size, ComponentType_Float2, NazaraOffsetOf(ParticleStruct_Billboard, size)); declaration->EnableComponent(ParticleComponent_Velocity, ComponentType_Float3, NazaraOffsetOf(ParticleStruct_Billboard, velocity)); NazaraAssert(declaration->GetStride() == sizeof(ParticleStruct_Billboard), "Invalid stride for declaration ParticleLayout_Billboard"); diff --git a/src/Nazara/Graphics/TileMap.cpp b/src/Nazara/Graphics/TileMap.cpp index 255685f43..ab035a7e4 100644 --- a/src/Nazara/Graphics/TileMap.cpp +++ b/src/Nazara/Graphics/TileMap.cpp @@ -68,7 +68,12 @@ namespace Nz std::size_t x = tileIndex % m_mapSize.x; std::size_t y = tileIndex / m_mapSize.x; - Vector3f tileLeftCorner(x * m_tileSize.x, y * -m_tileSize.y, 0.f); + + Vector3f tileLeftCorner; + if (m_isometricModeEnabled) + tileLeftCorner.Set(x * m_tileSize.x + m_tileSize.x/2.f * (y % 2), y/2.f * -m_tileSize.y, 0.f); + else + tileLeftCorner.Set(x * m_tileSize.x, y * -m_tileSize.y, 0.f); *colorPtr++ = tile.color; *posPtr++ = instanceData->transformMatrix.Transform(tileLeftCorner); diff --git a/src/Nazara/Network/Linux/SocketPollerImpl.cpp b/src/Nazara/Network/Linux/SocketPollerImpl.cpp new file mode 100644 index 000000000..ec6b8235e --- /dev/null +++ b/src/Nazara/Network/Linux/SocketPollerImpl.cpp @@ -0,0 +1,112 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Network module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + SocketPollerImpl::SocketPollerImpl() + { + m_handle = epoll_create1(0); + } + + SocketPollerImpl::~SocketPollerImpl() + { + close(m_handle); + } + + void SocketPollerImpl::Clear() + { + m_activeSockets.clear(); + m_sockets.clear(); + } + + bool SocketPollerImpl::IsReady(SocketHandle socket) const + { + return m_activeSockets.count(socket) != 0; + } + + bool SocketPollerImpl::IsRegistered(SocketHandle socket) const + { + return m_sockets.count(socket) != 0; + } + + bool SocketPollerImpl::RegisterSocket(SocketHandle socket) + { + NazaraAssert(!IsRegistered(socket), "Socket is already registered"); + + epoll_event event; + event.events = EPOLLIN; + event.data.fd = socket; + + if (epoll_ctl(m_handle, EPOLL_CTL_ADD, socket, &event) != 0) + { + NazaraError("Failed to add socket to epoll structure (errno " + String::Number(errno) + ": " + Error::GetLastSystemError() + ')'); + return false; + } + + m_sockets.insert(socket); + + return true; + } + + void SocketPollerImpl::UnregisterSocket(SocketHandle socket) + { + NazaraAssert(IsRegistered(socket), "Socket is not registered"); + + m_activeSockets.erase(socket); + m_sockets.erase(socket); + + if (epoll_ctl(m_handle, EPOLL_CTL_DEL, socket, nullptr) != 0) + NazaraWarning("An error occured while removing socket from epoll structure (errno " + String::Number(errno) + ": " + Error::GetLastSystemError() + ')'); + } + + int SocketPollerImpl::Wait(UInt64 msTimeout, SocketError* error) + { + int activeSockets; + + // Reset status of sockets + m_events.resize(m_sockets.size()); + std::memset(m_events.data(), 0, m_events.size() * sizeof(epoll_event)); + + activeSockets = epoll_wait(m_handle, m_events.data(), static_cast(m_events.size()), static_cast(msTimeout)); + if (activeSockets == -1) + { + if (error) + *error = SocketImpl::TranslateErrnoToResolveError(errno); + + return 0; + } + + m_activeSockets.clear(); + if (activeSockets > 0U) + { + int socketCount = activeSockets; + for (int i = 0; i < socketCount; ++i) + { + if (m_events[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)) + { + m_activeSockets.insert(m_events[i].data.fd); + if (m_events[i].events & EPOLLERR) + NazaraWarning("Descriptor " + String::Number(m_events[i].data.fd) + " was returned by epoll with EPOLLERR status"); + } + else + { + NazaraWarning("Descriptor " + String::Number(m_events[i].data.fd) + " was returned by epoll without EPOLLIN (events: 0x" + String::Number(m_events[i].events, 16) + ')'); + activeSockets--; + } + } + } + + if (error) + *error = SocketError_NoError; + + return activeSockets; + } +} diff --git a/src/Nazara/Network/Linux/SocketPollerImpl.hpp b/src/Nazara/Network/Linux/SocketPollerImpl.hpp new file mode 100644 index 000000000..1c54471fc --- /dev/null +++ b/src/Nazara/Network/Linux/SocketPollerImpl.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Network module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SOCKETPOLLERIMPL_HPP +#define NAZARA_SOCKETPOLLERIMPL_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class SocketPollerImpl + { + public: + SocketPollerImpl(); + ~SocketPollerImpl(); + + void Clear(); + + bool IsReady(SocketHandle socket) const; + bool IsRegistered(SocketHandle socket) const; + + bool RegisterSocket(SocketHandle socket); + void UnregisterSocket(SocketHandle socket); + + int Wait(UInt64 msTimeout, SocketError* error); + + private: + std::unordered_set m_activeSockets; + std::unordered_set m_sockets; + std::vector m_events; + int m_handle; + }; +} + +#endif // NAZARA_SOCKETPOLLERIMPL_HPP diff --git a/src/Nazara/Network/Posix/IpAddressImpl.hpp b/src/Nazara/Network/Posix/IpAddressImpl.hpp index 6ca919e78..fb435f9e1 100644 --- a/src/Nazara/Network/Posix/IpAddressImpl.hpp +++ b/src/Nazara/Network/Posix/IpAddressImpl.hpp @@ -2,6 +2,11 @@ // This file is part of the "Nazara Engine - Network module" // For conditions of distribution and use, see copyright notice in Config.hpp +#pragma once + +#ifndef NAZARA_IPADDRESSIMPL_HPP +#define NAZARA_IPADDRESSIMPL_HPP + #include #include #include @@ -30,3 +35,5 @@ namespace Nz static ResolveError TranslateEAIErrorToResolveError(int error); }; } + +#endif // NAZARA_IPADDRESSIMPL_HPP \ No newline at end of file diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index c2cf3a6f8..954ac4f43 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -397,6 +398,23 @@ namespace Nz return IpAddressImpl::FromSockAddr(reinterpret_cast(nameBuffer.data())); } + int SocketImpl::Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error) + { + NazaraAssert(fdarray && nfds > 0, "Invalid fdarray"); + + static_assert(sizeof(PollSocket) == sizeof(pollfd), "PollSocket size must match WSAPOLLFD size"); + + int result = poll(reinterpret_cast(fdarray), static_cast(nfds), timeout); + if (result < 0) + { + if (error) + *error = TranslateErrnoToResolveError(GetLastErrorCode()); + + return 0; + } + + return result; + } bool SocketImpl::Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error) { diff --git a/src/Nazara/Network/Posix/SocketImpl.hpp b/src/Nazara/Network/Posix/SocketImpl.hpp index 8896ce597..c120bd19a 100644 --- a/src/Nazara/Network/Posix/SocketImpl.hpp +++ b/src/Nazara/Network/Posix/SocketImpl.hpp @@ -2,12 +2,26 @@ // This file is part of the "Nazara Engine - Network module" // For conditions of distribution and use, see copyright notice in Config.hpp +#pragma once + +#ifndef NAZARA_SOCKETIMPL_HPP +#define NAZARA_SOCKETIMPL_HPP + #include #include #include +#define NAZARA_NETWORK_POLL_SUPPORT 1 + namespace Nz { + struct PollSocket + { + SocketHandle fd; + short events; + short revents; + }; + class SocketImpl { public: @@ -42,6 +56,8 @@ namespace Nz static IpAddress QueryPeerAddress(SocketHandle handle, SocketError* error = nullptr); static IpAddress QuerySocketAddress(SocketHandle handle, SocketError* error = nullptr); + static int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error); + static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error); static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error); @@ -66,3 +82,5 @@ namespace Nz static socketID s_socket; }; } + +#endif // NAZARA_SOCKETIMPL_HPP \ No newline at end of file diff --git a/src/Nazara/Network/Posix/SocketPollerImpl.cpp b/src/Nazara/Network/Posix/SocketPollerImpl.cpp new file mode 100644 index 000000000..4242e79a9 --- /dev/null +++ b/src/Nazara/Network/Posix/SocketPollerImpl.cpp @@ -0,0 +1,93 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Network module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + void SocketPollerImpl::Clear() + { + m_activeSockets.clear(); + m_allSockets.clear(); + m_sockets.clear(); + } + + bool SocketPollerImpl::IsReady(SocketHandle socket) const + { + return m_activeSockets.count(socket) != 0; + } + + bool SocketPollerImpl::IsRegistered(SocketHandle socket) const + { + return m_allSockets.count(socket) != 0; + } + + bool SocketPollerImpl::RegisterSocket(SocketHandle socket) + { + NazaraAssert(!IsRegistered(socket), "Socket is already registered"); + + PollSocket entry = { + socket, + POLLRDNORM, + 0 + }; + + m_allSockets[socket] = m_sockets.size(); + m_sockets.emplace_back(entry); + + return true; + } + + void SocketPollerImpl::UnregisterSocket(SocketHandle socket) + { + NazaraAssert(IsRegistered(socket), "Socket is not registered"); + + if (m_sockets.size() > 1U) + { + // Instead of using vector::erase, let's move the last element to the now unoccupied position + std::size_t entry = m_allSockets[socket]; + + // Get the last element and update it's position + const PollSocket& lastElement = m_sockets.back(); + m_allSockets[lastElement.fd] = entry; + + // Now move it properly (lastElement is invalid after the following line) and pop it + m_sockets[entry] = std::move(m_sockets.back()); + } + + m_sockets.pop_back(); + m_activeSockets.erase(socket); + m_allSockets.erase(socket); + } + + int SocketPollerImpl::Wait(UInt64 msTimeout, SocketError* error) + { + int activeSockets; + + // Reset status of sockets + for (PollSocket& entry : m_sockets) + entry.revents = 0; + + activeSockets = SocketImpl::Poll(m_sockets.data(), m_sockets.size(), static_cast(msTimeout), error); + + m_activeSockets.clear(); + if (activeSockets > 0U) + { + int socketRemaining = activeSockets; + for (PollSocket& entry : m_sockets) + { + if (entry.revents & POLLRDNORM) + { + m_activeSockets.insert(entry.fd); + if (--socketRemaining == 0) + break; + } + } + } + + return activeSockets; + } +} diff --git a/src/Nazara/Network/Posix/SocketPollerImpl.hpp b/src/Nazara/Network/Posix/SocketPollerImpl.hpp new file mode 100644 index 000000000..3472c3265 --- /dev/null +++ b/src/Nazara/Network/Posix/SocketPollerImpl.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Network module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SOCKETPOLLERIMPL_HPP +#define NAZARA_SOCKETPOLLERIMPL_HPP + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class SocketPollerImpl + { + public: + SocketPollerImpl() = default; + ~SocketPollerImpl() = default; + + void Clear(); + + bool IsReady(SocketHandle socket) const; + bool IsRegistered(SocketHandle socket) const; + + bool RegisterSocket(SocketHandle socket); + void UnregisterSocket(SocketHandle socket); + + int Wait(UInt64 msTimeout, SocketError* error); + + private: + std::unordered_set m_activeSockets; + std::unordered_map m_allSockets; + std::vector m_sockets; + }; +} + +#endif // NAZARA_SOCKETPOLLERIMPL_HPP diff --git a/src/Nazara/Network/SocketPoller.cpp b/src/Nazara/Network/SocketPoller.cpp new file mode 100644 index 000000000..049970433 --- /dev/null +++ b/src/Nazara/Network/SocketPoller.cpp @@ -0,0 +1,170 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include + +#if defined(NAZARA_PLATFORM_WINDOWS) +#include +#elif defined(NAZARA_PLATFORM_LINUX) +#include +#elif defined(NAZARA_PLATFORM_POSIX) +#include +#else +#error Missing implementation: SocketPoller +#endif + +#include + +namespace Nz +{ + /*! + * \ingroup network + * \class Nz::SocketPoller + * \brief Network class allowing an application to wait on multiples sockets for them to become active (readable) + */ + + /*! + * \brief Constructs an empty SocketPoller object + */ + SocketPoller::SocketPoller() : + m_impl(new SocketPollerImpl) + { + } + + /*! + * \brief Destructs the SocketPoller + * + * \remark When the SocketPoller gets destroyed, all sockets are automatically unregistered from it. + */ + SocketPoller::~SocketPoller() + { + delete m_impl; + } + + /*! + * \brief Clears the SocketPoller + * + * This function reverts the SocketPoller to the initial state, unregistering every socket from the SocketPoller. + * + * \see Unregister + */ + void SocketPoller::Clear() + { + m_impl->Clear(); + } + + /*! + * \brief Checks if a specific socket is ready to read data + * + * This function allows you to read the results of the last Wait operation and if a specific socket is ready. + * + * A socket in the ready state (with the exception of TcpServer) has incoming data and can be read without blocking. + * + * \remark When used on a TcpServer socket, this function returns true if the server is ready to accept a new client. + * \remark You must call Wait before using this function in order to refresh the state. + * + * \param socket Reference to the socket to check + * + * \return True if the socket is available for reading without blocking, false otherwise + * + * \see Wait + */ + bool SocketPoller::IsReady(const AbstractSocket& socket) const + { + NazaraAssert(IsRegistered(socket), "Socket is not registered in the poller"); + + return m_impl->IsReady(socket.GetNativeHandle()); + } + + /*! + * \brief Checks if a specific socket is registered in the SocketPoller + * + * A registered socket is part of the SocketPoller and will be checked by the next Wait operations. + * + * \param socket Reference to the socket to check + * + * \return True if the socket is registered, false otherwise + * + * \see RegisterSocket + * \see UnregisterSocket + */ + bool SocketPoller::IsRegistered(const AbstractSocket& socket) const + { + return m_impl->IsRegistered(socket.GetNativeHandle()); + } + + /*! + * \brief Register a socket in the SocketPoller + * + * A registered socket is part of the SocketPoller and will be checked by the next Wait operations. + * + * The SocketPoller keeps a reference to the internal handle of registered socket, which should not be freed while it is registered in the SocketPooler. + * + * It is possible for this function to fail if too many sockets are registered in the SocketPoller, the maximum number of socket handled limit is OS-dependent. + * + * \remark It is an error to register a socket twice in the same SocketPoller. + * \remark The socket should not be freed while it is registered in the SocketPooler. + * + * \param socket Reference to the socket to register + * + * \return True if the socket is registered, false otherwise + * + * \see IsRegistered + * \see UnregisterSocket + */ + bool SocketPoller::RegisterSocket(AbstractSocket& socket) + { + NazaraAssert(!IsRegistered(socket), "This socket is already registered in this SocketPoller"); + + return m_impl->RegisterSocket(socket.GetNativeHandle()); + } + + /*! + * \brief Unregister a socket from the SocketPoller + * + * After calling UnregisterSocket, the socket is no longer part of the SocketPoller and thus, not taken into account by any further Wait call until registered again. + * + * This function must be called before destroying a socket part of the SocketPoller. + * + * \remark It is an error to try to unregister a non-registered socket from a SocketPoller. + * + * \param socket Reference to the socket to unregister + * + * \see IsRegistered + * \see RegisterSocket + */ + void SocketPoller::UnregisterSocket(AbstractSocket& socket) + { + NazaraAssert(IsRegistered(socket), "This socket is not registered in this SocketPoller"); + + return m_impl->UnregisterSocket(socket.GetNativeHandle()); + } + + /*! + * \brief Wait until any registered socket switches to a ready state + * + * Waits a specific/undetermined amount of time until at least one socket part of the SocketPoller becomes ready. + * To query the ready state of the registered socket, use the IsReady function. + * + * \param msTimeout Maximum time to wait in milliseconds, 0 for infinity + * + * \remark It is an error to try to unregister a non-registered socket from a SocketPoller. + * + * \see IsReady + * \see RegisterSocket + */ + bool SocketPoller::Wait(UInt64 msTimeout) + { + SocketError error; + + int readySockets = m_impl->Wait(msTimeout, &error); + if (error != SocketError_NoError) + { + NazaraError("SocketPoller encountered an error (code: 0x" + String::Number(error, 16) + ')'); + return false; + } + + return readySockets > 0; + } +} diff --git a/src/Nazara/Network/TcpClient.cpp b/src/Nazara/Network/TcpClient.cpp index cf123ff89..1c84dc498 100644 --- a/src/Nazara/Network/TcpClient.cpp +++ b/src/Nazara/Network/TcpClient.cpp @@ -262,6 +262,17 @@ namespace Nz if (m_pendingPacket.headerReceived) { UInt16 packetSize = static_cast(m_pendingPacket.data.GetSize()); //< Total packet size + if (packetSize == 0) + { + // Special case: our packet carry no data + packet->Reset(m_pendingPacket.netcode); + + // And reset every state + m_pendingPacket.data.Clear(); + m_pendingPacket.headerReceived = false; + m_pendingPacket.received = 0; + return true; + } std::size_t received; if (!Receive(&m_pendingPacket.data[m_pendingPacket.received], packetSize - m_pendingPacket.received, &received)) diff --git a/src/Nazara/Network/Win32/IpAddressImpl.cpp b/src/Nazara/Network/Win32/IpAddressImpl.cpp index 0097227ef..2dac156ce 100644 --- a/src/Nazara/Network/Win32/IpAddressImpl.cpp +++ b/src/Nazara/Network/Win32/IpAddressImpl.cpp @@ -13,12 +13,12 @@ namespace Nz { namespace Detail { - #if NAZARA_CORE_WINDOWS_VISTA + #if NAZARA_CORE_WINDOWS_NT6 using addrinfoImpl = addrinfoW; int GetAddressInfo(const String& hostname, const String& service, const addrinfoImpl* hints, addrinfoImpl** results) { - return GetAddrInfoW(hostname.GetWideString().c_str(), service.GetWideString().c_str(), &hints, &servinfo); + return GetAddrInfoW(hostname.GetWideString().c_str(), service.GetWideString().c_str(), hints, results); } int GetHostnameInfo(sockaddr* socketAddress, socklen_t socketLen, String* hostname, String* service, INT flags) @@ -26,14 +26,14 @@ namespace Nz std::array hostnameBuffer; std::array serviceBuffer; - int result = GetNameInfoW(socketAddress, socketLen, hostnameBuffer.data(), hostnameBuffer.size(), serviceBuffer.data(), serviceBuffer.size(), flags); + int result = GetNameInfoW(socketAddress, socketLen, hostnameBuffer.data(), static_cast(hostnameBuffer.size()), serviceBuffer.data(), static_cast(serviceBuffer.size()), flags); if (result == 0) { if (hostname) - hostname->Set(hostnameBuffer.data()); + *hostname = std::move(String::Unicode(hostnameBuffer.data())); if (service) - service->Set(serviceBuffer.data()); + *service = std::move(String::Unicode(serviceBuffer.data())); } return result; @@ -105,7 +105,7 @@ namespace Nz return IpAddress::Invalid; } - #if NAZARA_CORE_WINDOWS_VISTA + #if NAZARA_CORE_WINDOWS_NT6 IpAddress IpAddressImpl::FromAddrinfo(const addrinfoW* info) { switch (info->ai_family) diff --git a/src/Nazara/Network/Win32/IpAddressImpl.hpp b/src/Nazara/Network/Win32/IpAddressImpl.hpp index 960092839..e85dc7411 100644 --- a/src/Nazara/Network/Win32/IpAddressImpl.hpp +++ b/src/Nazara/Network/Win32/IpAddressImpl.hpp @@ -2,6 +2,11 @@ // This file is part of the "Nazara Engine - Network module" // For conditions of distribution and use, see copyright notice in Config.hpp +#pragma once + +#ifndef NAZARA_IPADDRESSIMPL_HPP +#define NAZARA_IPADDRESSIMPL_HPP + #include #include #include @@ -17,7 +22,7 @@ namespace Nz ~IpAddressImpl() = delete; static IpAddress FromAddrinfo(const addrinfo* info); - #if NAZARA_CORE_WINDOWS_VISTA + #if NAZARA_CORE_WINDOWS_NT6 static IpAddress FromAddrinfo(const addrinfoW* info); #endif static IpAddress FromSockAddr(const sockaddr* address); @@ -33,3 +38,5 @@ namespace Nz static ResolveError TranslateWSAErrorToResolveError(int error); }; } + +#endif // NAZARA_IPADDRESSIMPL_HPP \ No newline at end of file diff --git a/src/Nazara/Network/Win32/SocketImpl.cpp b/src/Nazara/Network/Win32/SocketImpl.cpp index f35a4a078..628d29807 100644 --- a/src/Nazara/Network/Win32/SocketImpl.cpp +++ b/src/Nazara/Network/Win32/SocketImpl.cpp @@ -7,18 +7,21 @@ #include #include -#include - +#if defined(NAZARA_COMPILER_MINGW) && __GNUC__ < 5 // Some compilers (olders versions of MinGW) are lacking Mstcpip.h which defines the following struct/#define -// Define them ourself for now struct tcp_keepalive { - u_long onoff; - u_long keepalivetime; - u_long keepaliveinterval; + u_long onoff; + u_long keepalivetime; + u_long keepaliveinterval; }; #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) +#else +#include +#endif + +#include #include @@ -412,6 +415,34 @@ namespace Nz return IpAddressImpl::FromSockAddr(reinterpret_cast(nameBuffer.data())); } + int SocketImpl::Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error) + { + NazaraAssert(fdarray && nfds > 0, "Invalid fdarray"); + + #if NAZARA_NETWORK_POLL_SUPPORT + static_assert(sizeof(PollSocket) == sizeof(WSAPOLLFD), "PollSocket size must match WSAPOLLFD size"); + + int result = WSAPoll(reinterpret_cast(fdarray), static_cast(nfds), timeout); + if (result == SOCKET_ERROR) + { + int errorCode = WSAGetLastError(); + if (error) + *error = TranslateWSAErrorToSocketError(errorCode); + + return 0; + } + + if (error) + *error = SocketError_NoError; + + return result; + #else + if (error) + *error = SocketError_NotSupported; + + return 0; + #endif + } bool SocketImpl::Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error) { diff --git a/src/Nazara/Network/Win32/SocketImpl.hpp b/src/Nazara/Network/Win32/SocketImpl.hpp index dc0d77e73..94e2e9a8c 100644 --- a/src/Nazara/Network/Win32/SocketImpl.hpp +++ b/src/Nazara/Network/Win32/SocketImpl.hpp @@ -2,13 +2,27 @@ // This file is part of the "Nazara Engine - Network module" // For conditions of distribution and use, see copyright notice in Config.hpp +#pragma once + +#ifndef NAZARA_SOCKETIMPL_HPP +#define NAZARA_SOCKETIMPL_HPP + #include #include #include #include +#define NAZARA_NETWORK_POLL_SUPPORT NAZARA_CORE_WINDOWS_NT6 + namespace Nz { + struct PollSocket + { + SocketHandle fd; + short events; + short revents; + }; + class SocketImpl { public: @@ -43,6 +57,8 @@ namespace Nz static IpAddress QueryPeerAddress(SocketHandle handle, SocketError* error = nullptr); static IpAddress QuerySocketAddress(SocketHandle handle, SocketError* error = nullptr); + static int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error); + static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error); static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error); @@ -66,3 +82,5 @@ namespace Nz static WSADATA s_WSA; }; } + +#endif // NAZARA_SOCKETIMPL_HPP \ No newline at end of file diff --git a/src/Nazara/Network/Win32/SocketPollerImpl.cpp b/src/Nazara/Network/Win32/SocketPollerImpl.cpp new file mode 100644 index 000000000..dd80c233d --- /dev/null +++ b/src/Nazara/Network/Win32/SocketPollerImpl.cpp @@ -0,0 +1,149 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Network module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + SocketPollerImpl::SocketPollerImpl() + { + #if !NAZARA_NETWORK_POLL_SUPPORT + FD_ZERO(&m_activeSockets); + FD_ZERO(&m_sockets); + #endif + } + + void SocketPollerImpl::Clear() + { + #if NAZARA_NETWORK_POLL_SUPPORT + m_activeSockets.clear(); + m_allSockets.clear(); + m_sockets.clear(); + #else + FD_ZERO(&m_activeSockets); + FD_ZERO(&m_sockets); + #endif + } + + bool SocketPollerImpl::IsReady(SocketHandle socket) const + { + #if NAZARA_NETWORK_POLL_SUPPORT + return m_activeSockets.count(socket) != 0; + #else + return FD_ISSET(socket, &m_activeSockets) != 0; + #endif + } + + bool SocketPollerImpl::IsRegistered(SocketHandle socket) const + { + #if NAZARA_NETWORK_POLL_SUPPORT + return m_allSockets.count(socket) != 0; + #else + return FD_ISSET(socket, &m_sockets) != 0; + #endif + } + + bool SocketPollerImpl::RegisterSocket(SocketHandle socket) + { + NazaraAssert(!IsRegistered(socket), "Socket is already registered"); + + #if NAZARA_NETWORK_POLL_SUPPORT + PollSocket entry = { + socket, + POLLRDNORM, + 0 + }; + + m_allSockets[socket] = m_sockets.size(); + m_sockets.emplace_back(entry); + #else + if (m_sockets.fd_count > FD_SETSIZE) + { + NazaraError("Socket count exceeding FD_SETSIZE (" + String::Number(FD_SETSIZE) + ")"); + return false; + } + + FD_SET(socket, &m_sockets); + #endif + + return true; + } + + void SocketPollerImpl::UnregisterSocket(SocketHandle socket) + { + NazaraAssert(IsRegistered(socket), "Socket is not registered"); + + #if NAZARA_NETWORK_POLL_SUPPORT + if (m_sockets.size() > 1U) + { + // Instead of using vector::erase, let's move the last element to the now unoccupied position + std::size_t entry = m_allSockets[socket]; + + // Get the last element and update it's position + const PollSocket& lastElement = m_sockets.back(); + m_allSockets[lastElement.fd] = entry; + + // Now move it properly (lastElement is invalid after the following line) and pop it + m_sockets[entry] = std::move(m_sockets.back()); + } + + m_sockets.pop_back(); + m_activeSockets.erase(socket); + m_allSockets.erase(socket); + #else + FD_CLR(socket, &m_activeSockets); + FD_CLR(socket, &m_sockets); + #endif + } + + int SocketPollerImpl::Wait(UInt64 msTimeout, SocketError* error) + { + int activeSockets; + + #if NAZARA_NETWORK_POLL_SUPPORT + // Reset status of sockets + for (PollSocket& entry : m_sockets) + entry.revents = 0; + + activeSockets = SocketImpl::Poll(m_sockets.data(), m_sockets.size(), static_cast(msTimeout), error); + + m_activeSockets.clear(); + if (activeSockets > 0U) + { + int socketRemaining = activeSockets; + for (PollSocket& entry : m_sockets) + { + if (entry.revents & POLLRDNORM) + { + m_activeSockets.insert(entry.fd); + if (--socketRemaining == 0) + break; + } + } + } + #else + + m_activeSockets = m_sockets; + + timeval tv; + tv.tv_sec = static_cast(msTimeout / 1000ULL); + tv.tv_usec = static_cast((msTimeout % 1000ULL) * 1000ULL); + + activeSockets = ::select(0xDEADBEEF, &m_activeSockets, nullptr, nullptr, (msTimeout > 0) ? &tv : nullptr); //< The first argument is ignored on Windows + if (activeSockets == SOCKET_ERROR) + { + if (error) + *error = SocketImpl::TranslateWSAErrorToSocketError(WSAGetLastError()); + + return 0; + } + + if (error) + *error = SocketError_NoError; + #endif + + return activeSockets; + } +} diff --git a/src/Nazara/Network/Win32/SocketPollerImpl.hpp b/src/Nazara/Network/Win32/SocketPollerImpl.hpp new file mode 100644 index 000000000..a8a45a7de --- /dev/null +++ b/src/Nazara/Network/Win32/SocketPollerImpl.hpp @@ -0,0 +1,48 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Network module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SOCKETPOLLERIMPL_HPP +#define NAZARA_SOCKETPOLLERIMPL_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class SocketPollerImpl + { + public: + SocketPollerImpl(); + ~SocketPollerImpl() = default; + + void Clear(); + + bool IsReady(SocketHandle socket) const; + bool IsRegistered(SocketHandle socket) const; + + bool RegisterSocket(SocketHandle socket); + void UnregisterSocket(SocketHandle socket); + + int Wait(UInt64 msTimeout, SocketError* error); + + private: + #if NAZARA_NETWORK_POLL_SUPPORT + std::unordered_set m_activeSockets; + std::unordered_map m_allSockets; + std::vector m_sockets; + #else + fd_set m_sockets; + fd_set m_activeSockets; + #endif + }; +} + +#endif // NAZARA_SOCKETPOLLERIMPL_HPP \ No newline at end of file diff --git a/src/Nazara/Renderer/UberShaderPreprocessor.cpp b/src/Nazara/Renderer/UberShaderPreprocessor.cpp index 2a08088f5..f0e46c7d3 100644 --- a/src/Nazara/Renderer/UberShaderPreprocessor.cpp +++ b/src/Nazara/Renderer/UberShaderPreprocessor.cpp @@ -76,7 +76,7 @@ namespace Nz code << "#define GLSL_VERSION " << glslVersion << "\n\n"; - code << "#define EARLY_FRAGMENT_TEST " << (glslVersion >= 420 || OpenGL::IsSupported(OpenGLExtension_Shader_ImageLoadStore)) << "\n\n"; + code << "#define EARLY_FRAGMENT_TEST " << ((glslVersion >= 420 || OpenGL::IsSupported(OpenGLExtension_Shader_ImageLoadStore)) ? '1' : '0') << "\n\n"; for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it) code << "#define " << it->first << ' ' << ((stageFlags & it->second) ? '1' : '0') << '\n'; diff --git a/src/Nazara/Utility/Formats/OBJLoader.cpp b/src/Nazara/Utility/Formats/OBJLoader.cpp index 11029bada..2a59ba703 100644 --- a/src/Nazara/Utility/Formats/OBJLoader.cpp +++ b/src/Nazara/Utility/Formats/OBJLoader.cpp @@ -37,6 +37,10 @@ namespace Nz if (parameters.custom.GetBooleanParameter("SkipNativeOBJLoader", &skip) && skip) return Ternary_False; + OBJParser parser; + if (!parser.Check(stream)) + return Ternary_False; + return Ternary_Unknown; } diff --git a/src/Nazara/Utility/Formats/OBJParser.cpp b/src/Nazara/Utility/Formats/OBJParser.cpp index a520d6be1..3b03b7f78 100644 --- a/src/Nazara/Utility/Formats/OBJParser.cpp +++ b/src/Nazara/Utility/Formats/OBJParser.cpp @@ -13,9 +13,87 @@ namespace Nz { + bool OBJParser::Check(Stream& stream) + { + m_currentStream = &stream; + m_errorCount = 0; + m_keepLastLine = false; + m_lineCount = 0; + + // Force stream in text mode, reset it at the end + Nz::CallOnExit resetTextMode; + if ((stream.GetStreamOptions() & StreamOption_Text) == 0) + { + stream.EnableTextMode(true); + + resetTextMode.Reset([&stream] () + { + stream.EnableTextMode(false); + }); + } + + unsigned int failureCount = 0; + while (Advance(false)) + { + switch (std::tolower(m_currentLine[0])) + { + case '#': //< Comment + failureCount--; + break; + + case 'f': //< Face + case 'g': //< Group (inside a mesh) + case 'o': //< Object (defines a mesh) + case 's': //< Smooth + { + if (m_currentLine.GetSize() > 1 && m_currentLine[1] == ' ') + return true; + + break; + } + + case 'm': //< MTLLib + if (m_currentLine.GetWord(0).ToLower() == "mtllib") + return true; + + break; + + case 'u': //< Usemtl + if (m_currentLine.GetWord(0).ToLower() == "usemtl") + return true; + + break; + + case 'v': //< Position/Normal/Texcoords + { + String word = m_currentLine.GetWord(0).ToLower(); + if (word == 'v') + return true; + else if (word == "vn") + return true; + else if (word == "vt") + return true; + + break; + } + + default: + break; + } + + if (++failureCount > 20U) + return false; + } + + return false; + } + bool OBJParser::Parse(Nz::Stream& stream, UInt32 reservedVertexCount) { m_currentStream = &stream; + m_errorCount = 0; + m_keepLastLine = false; + m_lineCount = 0; // Force stream in text mode, reset it at the end Nz::CallOnExit resetTextMode; @@ -31,9 +109,6 @@ namespace Nz String matName, meshName; matName = meshName = "default"; - m_errorCount = 0; - m_keepLastLine = false; - m_lineCount = 0; m_meshes.clear(); m_mtlLib.Clear(); diff --git a/src/Nazara/Utility/PixelFormat.cpp b/src/Nazara/Utility/PixelFormat.cpp index a9b740b8f..77f6bdbb2 100644 --- a/src/Nazara/Utility/PixelFormat.cpp +++ b/src/Nazara/Utility/PixelFormat.cpp @@ -1284,6 +1284,9 @@ namespace Nz bool PixelFormat::Initialize() { + Bitset<> b32(0xFFFFFFFF); + b32.Resize(128); + // Setup informations about every pixel format s_pixelFormatInfos[PixelFormatType_A8] = PixelFormatInfo("A8", PixelFormatContent_ColorRGBA, 0, 0, 0, 0xFF, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormatType_BGR8] = PixelFormatInfo("BGR8", PixelFormatContent_ColorRGBA, 0x0000FF, 0x00FF00, 0xFF0000, 0, PixelFormatSubType_Unsigned); @@ -1317,18 +1320,18 @@ namespace Nz s_pixelFormatInfos[PixelFormatType_RGB16F] = PixelFormatInfo("RGB16F", PixelFormatContent_ColorRGBA, 0xFFFF00000000, 0x0000FFFF0000, 0x00000000FFFF, 0, PixelFormatSubType_Half); s_pixelFormatInfos[PixelFormatType_RGB16I] = PixelFormatInfo("RGB16I", PixelFormatContent_ColorRGBA, 0xFFFF00000000, 0x0000FFFF0000, 0x00000000FFFF, 0, PixelFormatSubType_Int); s_pixelFormatInfos[PixelFormatType_RGB16UI] = PixelFormatInfo("RGB16UI", PixelFormatContent_ColorRGBA, 0xFFFF000000000000, 0x0000FFFF00000000, 0x00000000FFFF0000, 0, PixelFormatSubType_Unsigned); - s_pixelFormatInfos[PixelFormatType_RGB32F] = PixelFormatInfo("RGB32F", PixelFormatContent_ColorRGBA, 0, 0, 0, 0, PixelFormatSubType_Half); - s_pixelFormatInfos[PixelFormatType_RGB32I] = PixelFormatInfo("RGB32I", PixelFormatContent_ColorRGBA, 0, 0, 0, 0, PixelFormatSubType_Int); - s_pixelFormatInfos[PixelFormatType_RGB32UI] = PixelFormatInfo("RGB32UI", PixelFormatContent_ColorRGBA, 0, 0, 0, 0, PixelFormatSubType_Unsigned); + s_pixelFormatInfos[PixelFormatType_RGB32F] = PixelFormatInfo("RGB32F", PixelFormatContent_ColorRGBA, b32, b32 >> 32, b32 >> 64, 0, PixelFormatSubType_Float); + s_pixelFormatInfos[PixelFormatType_RGB32I] = PixelFormatInfo("RGB32I", PixelFormatContent_ColorRGBA, b32, b32 >> 32, b32 >> 64, 0, PixelFormatSubType_Int); + s_pixelFormatInfos[PixelFormatType_RGB32UI] = PixelFormatInfo("RGB32UI", PixelFormatContent_ColorRGBA, b32, b32 >> 32, b32 >> 64, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormatType_RGBA4] = PixelFormatInfo("RGBA4", PixelFormatContent_ColorRGBA, 0xF000, 0x0F00, 0x00F0, 0x000F, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormatType_RGB5A1] = PixelFormatInfo("RGB5A1", PixelFormatContent_ColorRGBA, 0xF800, 0x07C0, 0x003E, 0x0001, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormatType_RGBA8] = PixelFormatInfo("RGBA8", PixelFormatContent_ColorRGBA, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormatType_RGBA16F] = PixelFormatInfo("RGBA16F", PixelFormatContent_ColorRGBA, 0xFFFF000000000000, 0x0000FFFF00000000, 0x00000000FFFF0000, 0x000000000000FFFF, PixelFormatSubType_Half); s_pixelFormatInfos[PixelFormatType_RGBA16I] = PixelFormatInfo("RGBA16I", PixelFormatContent_ColorRGBA, 0xFFFF000000000000, 0x0000FFFF00000000, 0x00000000FFFF0000, 0x000000000000FFFF, PixelFormatSubType_Int); s_pixelFormatInfos[PixelFormatType_RGBA16UI] = PixelFormatInfo("RGBA16UI", PixelFormatContent_ColorRGBA, 0xFFFF000000000000, 0x0000FFFF00000000, 0x00000000FFFF0000, 0x000000000000FFFF, PixelFormatSubType_Unsigned); - s_pixelFormatInfos[PixelFormatType_RGBA32F] = PixelFormatInfo("RGBA32F", PixelFormatContent_ColorRGBA, 0, 0, 0, 0, PixelFormatSubType_Half); - s_pixelFormatInfos[PixelFormatType_RGBA32I] = PixelFormatInfo("RGBA32I", PixelFormatContent_ColorRGBA, 0, 0, 0, 0, PixelFormatSubType_Int); - s_pixelFormatInfos[PixelFormatType_RGBA32UI] = PixelFormatInfo("RGBA32UI", PixelFormatContent_ColorRGBA, 0, 0, 0, 0, PixelFormatSubType_Unsigned); + s_pixelFormatInfos[PixelFormatType_RGBA32F] = PixelFormatInfo("RGBA32F", PixelFormatContent_ColorRGBA, b32, b32 >> 32, b32 >> 64, b32 >> 96, PixelFormatSubType_Float); + s_pixelFormatInfos[PixelFormatType_RGBA32I] = PixelFormatInfo("RGBA32I", PixelFormatContent_ColorRGBA, b32, b32 >> 32, b32 >> 64, b32 >> 96, PixelFormatSubType_Int); + s_pixelFormatInfos[PixelFormatType_RGBA32UI] = PixelFormatInfo("RGBA32UI", PixelFormatContent_ColorRGBA, b32, b32 >> 32, b32 >> 64, b32 >> 96, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormatType_Depth16] = PixelFormatInfo("Depth16", PixelFormatContent_DepthStencil, 0xFFFF, 0, 0, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormatType_Depth24] = PixelFormatInfo("Depth24", PixelFormatContent_DepthStencil, 0xFFFFFF, 0, 0, 0, PixelFormatSubType_Unsigned); s_pixelFormatInfos[PixelFormatType_Depth24Stencil8] = PixelFormatInfo("Depth24Stencil8", PixelFormatContent_DepthStencil, 0xFFFFFF00, 0x000000FF, 0, 0, PixelFormatSubType_Unsigned); diff --git a/src/Nazara/Utility/Utility.cpp b/src/Nazara/Utility/Utility.cpp index 6b2f66353..87b154157 100644 --- a/src/Nazara/Utility/Utility.cpp +++ b/src/Nazara/Utility/Utility.cpp @@ -102,10 +102,14 @@ namespace Nz return false; } - if (!Window::Initialize()) + bool bParam; + if (!s_initializationParameters.GetBooleanParameter("NoWindowSystem", &bParam) || !bParam) { - NazaraError("Failed to initialize window's system"); - return false; + if (!Window::Initialize()) + { + NazaraError("Failed to initialize window's system"); + return false; + } } // On enregistre les loaders pour les extensions @@ -147,6 +151,11 @@ namespace Nz return s_moduleReferenceCounter != 0; } + void Utility::SetParameters(const ParameterList& parameters) + { + s_initializationParameters = parameters; + } + void Utility::Uninitialize() { if (s_moduleReferenceCounter != 1) @@ -227,5 +236,6 @@ namespace Nz static_assert(ComponentType_Max+1 == 14, "Component stride array is incomplete"); + ParameterList Utility::s_initializationParameters; unsigned int Utility::s_moduleReferenceCounter = 0; } diff --git a/src/Nazara/Utility/Window.cpp b/src/Nazara/Utility/Window.cpp index 7ba78dcb9..078ff2bc5 100644 --- a/src/Nazara/Utility/Window.cpp +++ b/src/Nazara/Utility/Window.cpp @@ -29,6 +29,11 @@ namespace Nz Window* fullscreenWindow = nullptr; } + Window::~Window() + { + Destroy(); + } + bool Window::Create(VideoMode mode, const String& title, UInt32 style) { // Si la fenêtre est déjà ouverte, nous conservons sa position diff --git a/src/Nazara/Utility/X11/CursorImpl.cpp b/src/Nazara/Utility/X11/CursorImpl.cpp index 8cdde5170..d09f51a1f 100644 --- a/src/Nazara/Utility/X11/CursorImpl.cpp +++ b/src/Nazara/Utility/X11/CursorImpl.cpp @@ -9,7 +9,17 @@ #include #include #include -#include + +// Some older versions of xcb/util-renderutil (notably the one available on Travis CI) use `template` as an argument name +// This is a fixed bug (https://cgit.freedesktop.org/xcb/util-renderutil/commit/?id=8d15acc45a47dc4c922eee5b99885db42bc62c17) but until Travis-CI +// has upgraded their Ubuntu version, I'm forced to use this ugly trick. +#define template ptemplate +extern "C" +{ + #include +} +#undef template + #include namespace Nz diff --git a/tests/Engine/Graphics/Model.cpp b/tests/Engine/Graphics/Model.cpp index b363a0be2..270d15a0e 100644 --- a/tests/Engine/Graphics/Model.cpp +++ b/tests/Engine/Graphics/Model.cpp @@ -15,12 +15,12 @@ SCENARIO("Model", "[GRAPHICS][MODEL]") Nz::ModelRef model = Nz::Model::New(); REQUIRE(model->LoadFromFile("resources/Engine/Graphics/dragon_recon/dragon_vrip_res4.obj", params)); - REQUIRE(model->GetMaterialCount() == 2); + REQUIRE(model->GetMaterialCount() == 1); REQUIRE(model->GetSkin() == 0); REQUIRE(model->GetSkinCount() == 1); Nz::Material* material = model->GetMaterial(0); - REQUIRE(material->GetAmbientColor() == Nz::Color(128)); + REQUIRE(material->GetAmbientColor() == Nz::Color::Black); } } } diff --git a/tests/Engine/Network/IpAddress.cpp b/tests/Engine/Network/IpAddress.cpp index 8bb3e7d16..c87880d7b 100644 --- a/tests/Engine/Network/IpAddress.cpp +++ b/tests/Engine/Network/IpAddress.cpp @@ -40,7 +40,7 @@ SCENARIO("IpAddress", "[NETWORK][IPADDRESS]") Nz::IpAddress google(8, 8, 8, 8); THEN("Google (DNS) is 8.8.8.8") { - REQUIRE(Nz::IpAddress::ResolveAddress(google) == "google-public-dns-a.google.com"); + REQUIRE(Nz::IpAddress::ResolveAddress(google) == "google-public-dns-a.google.com"); } } } diff --git a/tests/Engine/Network/RUdpConnection.cpp b/tests/Engine/Network/RUdpConnection.cpp index a39100e94..cd30b3e1e 100644 --- a/tests/Engine/Network/RUdpConnection.cpp +++ b/tests/Engine/Network/RUdpConnection.cpp @@ -7,13 +7,18 @@ SCENARIO("RUdpConnection", "[NETWORK][RUDPCONNECTION]") { GIVEN("Two RUdpConnection, one client, one server") { - Nz::UInt16 port = 64266; + // Disabled for now + + /*Nz::UInt16 port = 64266; Nz::RUdpConnection server; REQUIRE(server.Listen(Nz::NetProtocol_IPv4, port)); - Nz::IpAddress serverIP = server.GetBoundAddress(); + + Nz::IpAddress serverIP(Nz::IpAddress::LoopbackIpV4.ToIPv4(), port); REQUIRE(serverIP.IsValid()); + Nz::RUdpConnection client; REQUIRE(client.Listen(Nz::NetProtocol_IPv4, port + 1)); + Nz::IpAddress clientIP = client.GetBoundAddress(); REQUIRE(client.Connect(serverIP)); REQUIRE(clientIP.IsValid()); @@ -30,11 +35,13 @@ SCENARIO("RUdpConnection", "[NETWORK][RUDPCONNECTION]") { Nz::RUdpMessage rudpMessage; server.Update(); + REQUIRE(server.PollMessage(&rudpMessage)); + Nz::Vector3f result; rudpMessage.data >> result; REQUIRE(result == vector123); } - } + }*/ } } diff --git a/tests/Engine/Network/SocketPoller.cpp b/tests/Engine/Network/SocketPoller.cpp new file mode 100644 index 000000000..d44c5f65d --- /dev/null +++ b/tests/Engine/Network/SocketPoller.cpp @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include +#include + +SCENARIO("SocketPoller", "[NETWORK][SOCKETPOLLER]") +{ + GIVEN("A TcpServer and a TcpClient in a selector") + { + std::random_device rd; + std::uniform_int_distribution dis(1025, 65535); + + Nz::UInt16 port = dis(rd); + Nz::TcpServer server; + server.EnableBlocking(false); + + REQUIRE(server.Listen(Nz::NetProtocol_IPv4, port) == Nz::SocketState_Bound); + + Nz::IpAddress serverIP(Nz::IpAddress::LoopbackIpV4.ToIPv4(), port); + REQUIRE(serverIP.IsValid()); + + Nz::SocketPoller serverPoller; + Nz::TcpClient clientToServer; + + WHEN("We register the server socket to the poller") + { + REQUIRE(serverPoller.RegisterSocket(server)); + + THEN("The poller should have registered our socket") + { + REQUIRE(serverPoller.IsRegistered(server)); + } + AND_THEN("We connect using a TcpClient") + { + Nz::SocketState state = clientToServer.Connect(serverIP); + + REQUIRE(state != Nz::SocketState_NotConnected); + + AND_THEN("We wait on our selector, it should return true") + { + REQUIRE(serverPoller.Wait(1000)); + + Nz::TcpClient serverToClient; + REQUIRE(server.AcceptClient(&serverToClient)); + + WHEN("We register the client socket to the poller") + { + REQUIRE(serverPoller.RegisterSocket(serverToClient)); + + THEN("The poller should have registered our socket") + { + REQUIRE(serverPoller.IsRegistered(serverToClient)); + } + + AND_WHEN("We test sending data from the client to the server and checking the poller") + { + std::array buffer = {"Data"}; + + std::size_t sent; + REQUIRE(clientToServer.Send(buffer.data(), buffer.size(), &sent)); + REQUIRE(sent == buffer.size()); + + REQUIRE(serverPoller.Wait(1000)); + + REQUIRE(serverPoller.IsReady(serverToClient)); + + REQUIRE(serverToClient.Read(buffer.data(), buffer.size()) == sent); + + AND_THEN("Our selector should report no socket ready") + { + REQUIRE(!serverPoller.Wait(100)); + + REQUIRE(!serverPoller.IsReady(serverToClient)); + } + } + } + } + } + } + } +} diff --git a/tests/Engine/Network/TCP.cpp b/tests/Engine/Network/TCP.cpp index a613cf0c6..7d24fc835 100644 --- a/tests/Engine/Network/TCP.cpp +++ b/tests/Engine/Network/TCP.cpp @@ -1,33 +1,36 @@ +#include +#include +#include #include #include #include - -#include -#include - #include SCENARIO("TCP", "[NETWORK][TCP]") { GIVEN("Two TCP, one client, one server") { - // Avoid reusing the same socket std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1025, 64245); + std::uniform_int_distribution dis(1025, 65535); + + Nz::UInt16 port = dis(rd); - Nz::UInt16 port = dis(gen); Nz::TcpServer server; server.EnableBlocking(false); REQUIRE(server.Listen(Nz::NetProtocol_IPv4, port) == Nz::SocketState_Bound); - Nz::IpAddress serverIP = server.GetBoundAddress(); + + Nz::IpAddress serverIP(Nz::IpAddress::LoopbackIpV4.ToIPv4(), port); REQUIRE(serverIP.IsValid()); + Nz::TcpClient client; REQUIRE(client.Connect(serverIP) == Nz::SocketState_Connecting); + Nz::IpAddress clientIP = client.GetRemoteAddress(); REQUIRE(clientIP.IsValid()); + Nz::Thread::Sleep(100); + Nz::TcpClient serverToClient; REQUIRE(server.AcceptClient(&serverToClient)); diff --git a/tests/Engine/Network/UdpSocket.cpp b/tests/Engine/Network/UdpSocket.cpp index 3f199f09e..00d793e7a 100644 --- a/tests/Engine/Network/UdpSocket.cpp +++ b/tests/Engine/Network/UdpSocket.cpp @@ -1,20 +1,26 @@ -#include -#include - #include +#include #include +#include +#include SCENARIO("UdpSocket", "[NETWORK][UDPSOCKET]") { GIVEN("Two UdpSocket, one client, one server") { - Nz::UInt16 port = 64256; + std::random_device rd; + std::uniform_int_distribution dis(1025, 65535); + + Nz::UInt16 port = dis(rd); Nz::UdpSocket server(Nz::NetProtocol_IPv4); REQUIRE(server.Bind(port) == Nz::SocketState_Bound); - Nz::IpAddress serverIP = server.GetBoundAddress(); + + Nz::IpAddress serverIP(Nz::IpAddress::LoopbackIpV4.ToIPv4(), port); REQUIRE(serverIP.IsValid()); + Nz::UdpSocket client(Nz::NetProtocol_IPv4); REQUIRE(client.Bind(port + 1) == Nz::SocketState_Bound); + Nz::IpAddress clientIP = client.GetBoundAddress(); REQUIRE(clientIP.IsValid()); @@ -30,6 +36,7 @@ SCENARIO("UdpSocket", "[NETWORK][UDPSOCKET]") Nz::NetPacket resultPacket; Nz::IpAddress fromIp; REQUIRE(server.ReceivePacket(&resultPacket, &fromIp)); + Nz::Vector3f result; resultPacket >> result; REQUIRE(result == vector123); diff --git a/tests/SDK/NDK/Application.cpp b/tests/SDK/NDK/Application.cpp index 994bd022b..3eab5645e 100644 --- a/tests/SDK/NDK/Application.cpp +++ b/tests/SDK/NDK/Application.cpp @@ -5,17 +5,20 @@ SCENARIO("Application", "[NDK][APPLICATION]") { GIVEN("An application") { - Ndk::Application application; - application.AddWorld(); - Nz::Window& window = application.AddWindow(); + Nz::Window& window = Ndk::Application::Instance()->AddWindow(); - WHEN("We close the open window") + WHEN("We open a window") { - window.Close(); + REQUIRE(window.Create(Nz::VideoMode(800, 600, 32), "Nazara Unit Tests")); - THEN("Application should close") + AND_WHEN("We close the open window") { - REQUIRE(!application.Run()); + window.Close(); + + THEN("Application should close") + { + REQUIRE(!Ndk::Application::Instance()->Run()); + } } } } diff --git a/tests/SDK/NDK/Component.cpp b/tests/SDK/NDK/Component.cpp index f00bb9006..c41f541be 100644 --- a/tests/SDK/NDK/Component.cpp +++ b/tests/SDK/NDK/Component.cpp @@ -6,6 +6,18 @@ namespace class TestComponent : public Ndk::Component { public: + TestComponent(int value) : + m_value(value) + { + } + + int GetValue() const + { + return m_value; + } + + int m_value; + static Ndk::ComponentIndex componentIndex; }; @@ -16,7 +28,7 @@ SCENARIO("Component", "[NDK][COMPONENT]") { GIVEN("Our TestComponent") { - TestComponent testComponent; + TestComponent testComponent(42); WHEN("We clone it") { @@ -24,7 +36,7 @@ SCENARIO("Component", "[NDK][COMPONENT]") THEN("We should get a copy") { - REQUIRE(dynamic_cast(clone.get()) != nullptr); + REQUIRE(static_cast(clone.get())->GetValue() == 42); } } } diff --git a/tests/SDK/NDK/System.cpp b/tests/SDK/NDK/System.cpp index ca1917124..623b4a96f 100644 --- a/tests/SDK/NDK/System.cpp +++ b/tests/SDK/NDK/System.cpp @@ -6,15 +6,23 @@ namespace class TestSystem : public Ndk::System { public: - TestSystem() + TestSystem(int value) : + m_value(value) { } + int GetValue() const + { + return m_value; + } + ~TestSystem() = default; static Ndk::SystemIndex systemIndex; private: + int m_value; + void OnUpdate(float elapsedTime) override { } @@ -27,7 +35,7 @@ SCENARIO("System", "[NDK][SYSTEM]") { GIVEN("Our TestSystem") { - TestSystem testSystem; + TestSystem testSystem(666); WHEN("We clone it") { @@ -35,7 +43,7 @@ SCENARIO("System", "[NDK][SYSTEM]") THEN("We should get a copy") { - REQUIRE(dynamic_cast(clone.get()) != nullptr); + REQUIRE(static_cast(clone.get())->GetValue() == 666); } } } diff --git a/tests/main.cpp b/tests/main.cpp index 5ba9e8e01..112b7498c 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,14 +1,16 @@ #define CATCH_CONFIG_RUNNER #include -#include -#include -#include +#include +#include #include -int main(int argc, char* const argv[]) +int main(int argc, char* argv[]) { - Nz::Initializer modules; + Ndk::Application application(argc, argv); + Nz::Initializer modules; + + Nz::Log::GetLogger()->EnableStdReplication(false); int result = Catch::Session().run(argc, argv);