From b5f237b58f4a98e4fee47081e26aa62a0a0f609c Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 24 Apr 2016 04:38:18 +0200 Subject: [PATCH 01/15] Fix some errors Former-commit-id: df7db9ab69395ca969779817fcdc17acb711967d --- SDK/include/NDK/LuaAPI.inl | 4 +++- src/Nazara/Utility/Font.cpp | 9 +++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/SDK/include/NDK/LuaAPI.inl b/SDK/include/NDK/LuaAPI.inl index d80652780..1652d5719 100644 --- a/SDK/include/NDK/LuaAPI.inl +++ b/SDK/include/NDK/LuaAPI.inl @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -67,7 +69,7 @@ namespace Nz inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, FontRef* fontRef, TypeTag) { *fontRef = *(*static_cast(instance.CheckUserdata(index, "Font"))); - + return 1; } diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index 9e26d28bb..a29d28671 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -359,13 +359,10 @@ namespace Nz if (!s_defaultFont) { FontRef cabin = Font::New(); - if (!cabin->OpenFromMemory(r_cabinRegular, sizeof(r_cabinRegular))) - { + if (cabin->OpenFromMemory(r_cabinRegular, sizeof(r_cabinRegular))) + s_defaultFont = cabin; + else NazaraError("Failed to open default font"); - return nullptr; - } - - s_defaultFont = cabin; } return s_defaultFont; From 6d66063b2c798a3cfbe2fdc4437e56bb1d84dbd7 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 24 Apr 2016 19:48:12 +0200 Subject: [PATCH 02/15] Core/MemoryHelper: Improve PlacementNew interface Make it possible to deduce type from arguments Former-commit-id: ed25b667fcacefcc39fddcb941ea11c40e6ce22b --- include/Nazara/Core/MemoryHelper.hpp | 2 +- include/Nazara/Core/MemoryHelper.inl | 2 +- include/Nazara/Core/MemoryPool.inl | 2 +- include/Nazara/Lua/LuaClass.inl | 4 ++-- src/Nazara/Core/ParameterList.cpp | 6 +++--- src/Nazara/Lua/LuaInstance.cpp | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/Nazara/Core/MemoryHelper.hpp b/include/Nazara/Core/MemoryHelper.hpp index 880418bec..e2f295622 100644 --- a/include/Nazara/Core/MemoryHelper.hpp +++ b/include/Nazara/Core/MemoryHelper.hpp @@ -15,7 +15,7 @@ namespace Nz void* OperatorNew(std::size_t size); template - T* PlacementNew(void* ptr, Args&&... args); + T* PlacementNew(T* ptr, Args&&... args); } #include diff --git a/include/Nazara/Core/MemoryHelper.inl b/include/Nazara/Core/MemoryHelper.inl index 7f77dd041..23a745a44 100644 --- a/include/Nazara/Core/MemoryHelper.inl +++ b/include/Nazara/Core/MemoryHelper.inl @@ -58,7 +58,7 @@ namespace Nz * \param args Arguments for the constructor */ template - T* PlacementNew(void* ptr, Args&&... args) + T* PlacementNew(T* ptr, Args&&... args) { return new (ptr) T(std::forward(args)...); } diff --git a/include/Nazara/Core/MemoryPool.inl b/include/Nazara/Core/MemoryPool.inl index 14c3868dd..732c50fa9 100644 --- a/include/Nazara/Core/MemoryPool.inl +++ b/include/Nazara/Core/MemoryPool.inl @@ -191,7 +191,7 @@ namespace Nz inline T* MemoryPool::New(Args&&... args) { T* object = static_cast(Allocate(sizeof(T))); - PlacementNew(object, std::forward(args)...); + PlacementNew(object, std::forward(args)...); return object; } diff --git a/include/Nazara/Lua/LuaClass.inl b/include/Nazara/Lua/LuaClass.inl index 913382f99..edb7103b6 100644 --- a/include/Nazara/Lua/LuaClass.inl +++ b/include/Nazara/Lua/LuaClass.inl @@ -54,8 +54,8 @@ namespace Nz // cette UserData disposera d'un finalizer qui libérera le ClassInfo // Ainsi c'est Lua qui va s'occuper de la destruction pour nous :-) // De même, l'utilisation d'un shared_ptr permet de garder la structure en vie même si l'instance est libérée avant le LuaClass - void* info = lua.PushUserdata(sizeof(std::shared_ptr)); - PlacementNew>(info, m_info); + std::shared_ptr* info = static_cast*>(lua.PushUserdata(sizeof(std::shared_ptr))); + PlacementNew(info, m_info); // On créé la table qui contiendra une méthode (Le finalizer) pour libérer le ClassInfo lua.PushTable(0, 1); diff --git a/src/Nazara/Core/ParameterList.cpp b/src/Nazara/Core/ParameterList.cpp index 5edd8f976..f9a24d4cc 100644 --- a/src/Nazara/Core/ParameterList.cpp +++ b/src/Nazara/Core/ParameterList.cpp @@ -449,7 +449,7 @@ namespace Nz Parameter& parameter = CreateValue(name); parameter.type = ParameterType_String; - PlacementNew(¶meter.value.stringVal, value); + PlacementNew(¶meter.value.stringVal, value); } /*! @@ -464,7 +464,7 @@ namespace Nz Parameter& parameter = CreateValue(name); parameter.type = ParameterType_String; - PlacementNew(¶meter.value.stringVal, value); + PlacementNew(¶meter.value.stringVal, value); } /*! @@ -565,7 +565,7 @@ namespace Nz case ParameterType_String: parameter.type = ParameterType_String; - PlacementNew(¶meter.value.stringVal, it->second.value.stringVal); + PlacementNew(¶meter.value.stringVal, it->second.value.stringVal); break; case ParameterType_Userdata: diff --git a/src/Nazara/Lua/LuaInstance.cpp b/src/Nazara/Lua/LuaInstance.cpp index a93013567..23f852921 100644 --- a/src/Nazara/Lua/LuaInstance.cpp +++ b/src/Nazara/Lua/LuaInstance.cpp @@ -634,7 +634,7 @@ namespace Nz void LuaInstance::PushFunction(LuaFunction func) const { LuaFunction* luaFunc = static_cast(lua_newuserdata(m_state, sizeof(LuaFunction))); - PlacementNew(luaFunc, std::move(func)); + PlacementNew(luaFunc, std::move(func)); lua_pushcclosure(m_state, ProxyFunc, 1); } From 24a8fcee01855c207ff0033c80ac9da247f2dc73 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 24 Apr 2016 19:54:46 +0200 Subject: [PATCH 03/15] Optimize Lua binding Optimize binding by removing a useless extra indirection and allowing to move replying variables Former-commit-id: 76728df1c3ab9a38a4304ae2b9f2fc6a000e0ebb --- SDK/include/NDK/LuaAPI.inl | 38 +++++++-------- SDK/src/NDK/LuaBinding_Audio.cpp | 16 +++---- SDK/src/NDK/LuaBinding_Core.cpp | 38 ++++++++++----- SDK/src/NDK/LuaBinding_Graphics.cpp | 5 +- SDK/src/NDK/LuaBinding_Math.cpp | 74 ++++++++++++++++++----------- SDK/src/NDK/LuaBinding_Network.cpp | 50 ++++++++++++++----- SDK/src/NDK/LuaBinding_Utility.cpp | 5 +- include/Nazara/Lua/LuaClass.hpp | 4 +- include/Nazara/Lua/LuaClass.inl | 29 +++++++---- include/Nazara/Lua/LuaInstance.hpp | 3 +- include/Nazara/Lua/LuaInstance.inl | 35 +++++++++----- 11 files changed, 190 insertions(+), 107 deletions(-) diff --git a/SDK/include/NDK/LuaAPI.inl b/SDK/include/NDK/LuaAPI.inl index 1652d5719..a0a180ff9 100644 --- a/SDK/include/NDK/LuaAPI.inl +++ b/SDK/include/NDK/LuaAPI.inl @@ -271,25 +271,25 @@ namespace Nz - inline int LuaImplReplyVal(const LuaInstance& instance, EulerAnglesd val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, EulerAnglesd&& val, TypeTag) { instance.PushInstance("EulerAngles", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, EulerAnglesf val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, EulerAnglesf&& val, TypeTag) { instance.PushInstance("EulerAngles", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, FontRef val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, FontRef&& val, TypeTag) { instance.PushInstance("Font", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Font::SizeInfo val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Font::SizeInfo&& val, TypeTag) { instance.PushTable(); instance.PushField("LineHeight", val.lineHeight); @@ -300,55 +300,55 @@ namespace Nz return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Quaterniond val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Quaterniond&& val, TypeTag) { instance.PushInstance("Quaternion", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Quaternionf val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Quaternionf&& val, TypeTag) { instance.PushInstance("Quaternion", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, IpAddress val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, IpAddress&& val, TypeTag) { instance.PushInstance("IpAddress", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Vector2d val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Vector2d&& val, TypeTag) { instance.PushInstance("Vector2", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Vector2f val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Vector2f&& val, TypeTag) { instance.PushInstance("Vector2", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Vector2ui val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Vector2ui&& val, TypeTag) { instance.PushInstance("Vector2", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Vector3d val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Vector3d&& val, TypeTag) { instance.PushInstance("Vector3", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Vector3f val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Vector3f&& val, TypeTag) { instance.PushInstance("Vector3", val); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Vector3ui val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Vector3ui&& val, TypeTag) { instance.PushInstance("Vector3", val); return 1; @@ -366,19 +366,19 @@ namespace Nz return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::EntityHandle handle, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::EntityHandle&& handle, TypeTag) { instance.PushInstance("Entity", handle); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::NodeComponentHandle handle, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::NodeComponentHandle&& handle, TypeTag) { instance.PushInstance("NodeComponent", handle); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::VelocityComponentHandle handle, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::VelocityComponentHandle&& handle, TypeTag) { instance.PushInstance("VelocityComponent", handle); return 1; @@ -390,20 +390,20 @@ namespace Nz return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::WorldHandle handle, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::WorldHandle&& handle, TypeTag) { instance.PushInstance("World", handle); return 1; } #ifndef NDK_SERVER - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::ConsoleHandle handle, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::ConsoleHandle&& handle, TypeTag) { instance.PushInstance("Console", handle); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::GraphicsComponentHandle handle, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, Ndk::GraphicsComponentHandle&& handle, TypeTag) { instance.PushInstance("GraphicsComponent", handle); return 1; diff --git a/SDK/src/NDK/LuaBinding_Audio.cpp b/SDK/src/NDK/LuaBinding_Audio.cpp index 7c204b833..d75c8215e 100644 --- a/SDK/src/NDK/LuaBinding_Audio.cpp +++ b/SDK/src/NDK/LuaBinding_Audio.cpp @@ -1,6 +1,7 @@ // This file was automatically generated on 26 May 2014 at 01:05:31 #include +#include #include namespace Ndk @@ -10,10 +11,7 @@ namespace Ndk /*********************************** Nz::Music **********************************/ musicClass.Inherit(soundEmitter); - musicClass.SetConstructor([] (Nz::LuaInstance& lua) -> Nz::Music* - { - return new Nz::Music; - }); + musicClass.BindDefaultConstructor(); //musicClass.SetMethod("Create", &Nz::Music::Create); //musicClass.SetMethod("Destroy", &Nz::Music::Destroy); @@ -51,10 +49,7 @@ namespace Ndk /*********************************** Nz::Sound **********************************/ soundClass.Inherit(soundEmitter); - soundClass.SetConstructor([] (Nz::LuaInstance& lua) -> Nz::Sound* - { - return new Nz::Sound; - }); + soundClass.BindDefaultConstructor(); soundClass.BindMethod("GetBuffer", &Nz::Sound::GetBuffer); @@ -79,9 +74,10 @@ namespace Ndk }); /*********************************** Nz::SoundBuffer **********************************/ - soundBuffer.SetConstructor([] (Nz::LuaInstance& lua) -> Nz::SoundBufferRef* + soundBuffer.SetConstructor([] (Nz::LuaInstance& lua, Nz::SoundBufferRef* instance) { - return new Nz::SoundBufferRef(new Nz::SoundBuffer); + Nz::PlacementNew(instance, Nz::SoundBuffer::New()); + return true; }); soundBuffer.BindMethod("Destroy", &Nz::SoundBuffer::Destroy); diff --git a/SDK/src/NDK/LuaBinding_Core.cpp b/SDK/src/NDK/LuaBinding_Core.cpp index 16e8f66f6..09cbda604 100644 --- a/SDK/src/NDK/LuaBinding_Core.cpp +++ b/SDK/src/NDK/LuaBinding_Core.cpp @@ -1,6 +1,7 @@ // This file was automatically generated on 26 May 2014 at 01:05:31 #include +#include #include namespace Ndk @@ -8,10 +9,14 @@ namespace Ndk void LuaBinding::BindCore() { /*********************************** Nz::Clock **********************************/ - clockClass.SetConstructor([](Nz::LuaInstance& lua) -> Nz::Clock* + clockClass.SetConstructor([](Nz::LuaInstance& lua, Nz::Clock* clock) { int argIndex = 1; - return new Nz::Clock(lua.Check(&argIndex, 0), lua.Check(&argIndex, false)); + Nz::Int64 startingValue = lua.Check(&argIndex, 0); + bool paused = lua.Check(&argIndex, false); + + Nz::PlacementNew(clock, startingValue, paused); + return true; }); clockClass.BindMethod("GetMicroseconds", &Nz::Clock::GetMicroseconds); @@ -35,7 +40,7 @@ namespace Ndk }); /********************************* Nz::Directory ********************************/ - directoryClass.SetConstructor([](Nz::LuaInstance& lua) -> Nz::Directory* + directoryClass.SetConstructor([](Nz::LuaInstance& lua, Nz::Directory* directory) { unsigned int argCount = std::min(lua.GetStackTop(), 1U); @@ -43,13 +48,15 @@ namespace Ndk switch (argCount) { case 0: - return new Nz::Directory; + Nz::PlacementNew(directory); + return true; case 1: - return new Nz::Directory(lua.Check(&argIndex)); + Nz::PlacementNew(directory, lua.Check(&argIndex)); + return true; } - return nullptr; + return false; }); directoryClass.BindMethod("Close", &Nz::Directory::Close); @@ -127,7 +134,7 @@ namespace Ndk /*********************************** Nz::File ***********************************/ fileClass.Inherit(streamClass); - fileClass.SetConstructor([](Nz::LuaInstance& lua) -> Nz::File* + fileClass.SetConstructor([](Nz::LuaInstance& lua, Nz::File* file) { unsigned int argCount = std::min(lua.GetStackTop(), 2U); @@ -135,20 +142,29 @@ namespace Ndk switch (argCount) { case 0: - return new Nz::File; + Nz::PlacementNew(file); + return true; case 1: - return new Nz::File(lua.Check(&argIndex)); + { + Nz::String filePath = lua.Check(&argIndex); + + Nz::PlacementNew(file, filePath); + return true; + } case 2: { Nz::String filePath = lua.Check(&argIndex); Nz::UInt32 openMode = lua.Check(&argIndex); - return new Nz::File(filePath, openMode); + + Nz::PlacementNew(file, filePath, openMode); + return true; } } - return nullptr; + lua.Error("No matching overload for File constructor"); + return false; }); fileClass.BindMethod("Close", &Nz::File::Close); diff --git a/SDK/src/NDK/LuaBinding_Graphics.cpp b/SDK/src/NDK/LuaBinding_Graphics.cpp index 3d7597dd5..289002746 100644 --- a/SDK/src/NDK/LuaBinding_Graphics.cpp +++ b/SDK/src/NDK/LuaBinding_Graphics.cpp @@ -16,9 +16,10 @@ namespace Ndk return reinterpret_cast(model); //TODO: Make a ObjectRefCast }); - modelClass.SetConstructor([] (Nz::LuaInstance& lua) -> Nz::ModelRef* + modelClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::ModelRef* model) { - return new Nz::ModelRef(new Nz::Model); + Nz::PlacementNew(model, Nz::Model::New()); + return true; }); //modelClass.SetMethod("GetMaterial", &Nz::Model::GetMaterial); diff --git a/SDK/src/NDK/LuaBinding_Math.cpp b/SDK/src/NDK/LuaBinding_Math.cpp index 808c93f86..001eb1c73 100644 --- a/SDK/src/NDK/LuaBinding_Math.cpp +++ b/SDK/src/NDK/LuaBinding_Math.cpp @@ -1,6 +1,7 @@ // This file was automatically generated on 26 May 2014 at 01:05:31 #include +#include #include #include @@ -9,23 +10,26 @@ namespace Ndk void LuaBinding::BindMath() { /*********************************** Nz::EulerAngles **********************************/ - eulerAnglesClass.SetConstructor([] (Nz::LuaInstance& lua) -> Nz::EulerAnglesd* + eulerAnglesClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::EulerAnglesd* angles) { unsigned int argCount = std::min(lua.GetStackTop(), 3U); switch (argCount) { case 0: - return new Nz::EulerAnglesd(0.0, 0.0, 0.0); + Nz::PlacementNew(angles, Nz::EulerAnglesd::Zero()); + return true; case 1: - return new Nz::EulerAnglesd(*(*static_cast(lua.CheckUserdata(1, "EulerAngles")))); + Nz::PlacementNew(angles, *static_cast(lua.CheckUserdata(1, "EulerAngles"))); + return true; case 3: - return new Nz::EulerAnglesd(lua.CheckNumber(1), lua.CheckNumber(2), lua.CheckNumber(3)); + Nz::PlacementNew(angles, lua.CheckNumber(1), lua.CheckNumber(2), lua.CheckNumber(3)); + return true; } lua.Error("No matching overload for EulerAngles constructor"); - return nullptr; + return false; }); eulerAnglesClass.BindMethod("__tostring", &Nz::EulerAnglesd::ToString); @@ -146,31 +150,38 @@ namespace Ndk }); /*********************************** Nz::Quaternion **********************************/ - quaternionClass.SetConstructor([] (Nz::LuaInstance& lua) -> Nz::Quaterniond* + quaternionClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Quaterniond* quaternion) { unsigned int argCount = std::min(lua.GetStackTop(), 4U); switch (argCount) { case 0: - return new Nz::Quaterniond(1.0, 0.0, 0.0, 0.0); + Nz::PlacementNew(quaternion, Nz::Quaterniond::Zero()); + return true; case 1: { if (lua.IsOfType(1, "EulerAngles")) - return new Nz::Quaterniond(*(*static_cast(lua.ToUserdata(1)))); + Nz::PlacementNew(quaternion, *static_cast(lua.ToUserdata(1))); else if (lua.IsOfType(1, "Quaternion")) - return new Nz::Quaterniond(*(*static_cast(lua.ToUserdata(1)))); + Nz::PlacementNew(quaternion, *static_cast(lua.ToUserdata(1))); + else + break; + + return true; } case 2: - return new Nz::Quaterniond(lua.CheckNumber(1), *(*static_cast(lua.CheckUserdata(2, "Vector3")))); + Nz::PlacementNew(quaternion, lua.CheckNumber(1), *(*static_cast(lua.CheckUserdata(2, "Vector3")))); + return true; case 4: - return new Nz::Quaterniond(lua.CheckNumber(1), lua.CheckNumber(2), lua.CheckNumber(3), lua.CheckNumber(4)); + Nz::PlacementNew(quaternion, lua.CheckNumber(1), lua.CheckNumber(2), lua.CheckNumber(3), lua.CheckNumber(4)); + return true; } lua.Error("No matching overload for Quaternion constructor"); - return nullptr; + return false; }); quaternionClass.BindMethod("__tostring", &Nz::Quaterniond::ToString); @@ -238,28 +249,31 @@ namespace Ndk }); /*********************************** Nz::Vector2 **********************************/ - vector2dClass.SetConstructor([](Nz::LuaInstance& lua) -> Nz::Vector2d* + vector2dClass.SetConstructor([](Nz::LuaInstance& lua, Nz::Vector2d* vector) { unsigned int argCount = std::min(lua.GetStackTop(), 2U); switch (argCount) { case 0: case 2: - return new Nz::Vector2d(lua.CheckNumber(1, 0.0), lua.CheckNumber(2, 0.0)); + Nz::PlacementNew(vector, lua.CheckNumber(1, 0.0), lua.CheckNumber(2, 0.0)); + return true; case 1: { if (lua.IsOfType(1, Nz::LuaType_Number)) - return new Nz::Vector2d(lua.CheckNumber(1)); + Nz::PlacementNew(vector, lua.CheckNumber(1)); else if (lua.IsOfType(1, "Vector2")) - return new Nz::Vector2d(*(*static_cast(lua.ToUserdata(1)))); + Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1))); + else + break; - break; + return true; } } lua.Error("No matching overload for Vector2 constructor"); - return nullptr; + return false; }); vector2dClass.BindMethod("__tostring", &Nz::Vector2d::ToString); @@ -345,40 +359,44 @@ namespace Ndk }); /*********************************** Nz::Vector3 **********************************/ - vector3dClass.SetConstructor([] (Nz::LuaInstance& lua) -> Nz::Vector3d* + vector3dClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Vector3d* vector) { unsigned int argCount = std::min(lua.GetStackTop(), 3U); switch (argCount) { case 0: case 3: - return new Nz::Vector3d(lua.CheckNumber(1, 0.0), lua.CheckNumber(2, 0.0), lua.CheckNumber(3, 0.0)); + Nz::PlacementNew(vector, lua.CheckNumber(1, 0.0), lua.CheckNumber(2, 0.0), lua.CheckNumber(3, 0.0)); case 1: { if (lua.IsOfType(1, Nz::LuaType_Number)) - return new Nz::Vector3d(lua.CheckNumber(1), *(*static_cast(lua.ToUserdata(1)))); + Nz::PlacementNew(vector, lua.CheckNumber(1), *static_cast(lua.ToUserdata(1))); else if (lua.IsOfType(1, "Vector2")) - return new Nz::Vector3d(*(*static_cast(lua.ToUserdata(1)))); + Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1))); else if (lua.IsOfType(1, "Vector3")) - return new Nz::Vector3d(*(*static_cast(lua.ToUserdata(1)))); + Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1))); + else + break; - break; + return true; } case 2: { if (lua.IsOfType(1, Nz::LuaType_Number)) - return new Nz::Vector3d(lua.CheckNumber(1), *(*static_cast(lua.CheckUserdata(1, "Vector2")))); + Nz::PlacementNew(vector, lua.CheckNumber(1), *static_cast(lua.CheckUserdata(1, "Vector2"))); else if (lua.IsOfType(1, "Vector2")) - return new Nz::Vector3d(*(*static_cast(lua.ToUserdata(1))), lua.CheckNumber(2)); + Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1)), lua.CheckNumber(2)); + else + break; - break; + return true; } } lua.Error("No matching overload for constructor"); - return nullptr; + return false; }); vector3dClass.BindMethod("__tostring", &Nz::Vector3d::ToString); diff --git a/SDK/src/NDK/LuaBinding_Network.cpp b/SDK/src/NDK/LuaBinding_Network.cpp index e7673b86c..dc17c5d00 100644 --- a/SDK/src/NDK/LuaBinding_Network.cpp +++ b/SDK/src/NDK/LuaBinding_Network.cpp @@ -17,7 +17,7 @@ namespace Ndk abstractSocketClass.BindMethod("QueryAvailableBytes", &Nz::AbstractSocket::QueryAvailableBytes); /*********************************** Nz::IpAddress **********************************/ - ipAddressClass.SetConstructor([] (Nz::LuaInstance& lua) -> Nz::IpAddress* + ipAddressClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::IpAddress* address) { unsigned int argCount = std::min(lua.GetStackTop(), 9U); @@ -25,30 +25,54 @@ namespace Ndk switch (argCount) { case 0: - return new Nz::IpAddress; + Nz::PlacementNew(address); + return true; case 1: - return new Nz::IpAddress(lua.CheckString(argIndex)); + Nz::PlacementNew(address, lua.CheckString(argIndex)); + return true; case 4: case 5: - return new Nz::IpAddress(lua.Check(&argIndex), lua.Check(&argIndex), lua.Check(&argIndex), lua.Check(&argIndex), lua.Check(&argIndex, 0)); + { + Nz::UInt8 a = lua.Check(&argIndex); + Nz::UInt8 b = lua.Check(&argIndex); + Nz::UInt8 c = lua.Check(&argIndex); + Nz::UInt8 d = lua.Check(&argIndex); + Nz::UInt16 port = lua.Check(&argIndex, 0); + + Nz::PlacementNew(address, a, b, c, d, port); + return true; + } case 8: case 9: - return new Nz::IpAddress(lua.Check(&argIndex), lua.Check(&argIndex), lua.Check(&argIndex), lua.Check(&argIndex), - lua.Check(&argIndex), lua.Check(&argIndex), lua.Check(&argIndex), lua.Check(&argIndex), lua.Check(&argIndex, 0)); + { + Nz::UInt16 a = lua.Check(&argIndex); + Nz::UInt16 b = lua.Check(&argIndex); + Nz::UInt16 c = lua.Check(&argIndex); + Nz::UInt16 d = lua.Check(&argIndex); + Nz::UInt16 e = lua.Check(&argIndex); + Nz::UInt16 f = lua.Check(&argIndex); + Nz::UInt16 g = lua.Check(&argIndex); + Nz::UInt16 h = lua.Check(&argIndex); + Nz::UInt16 port = lua.Check(&argIndex, 0); + + Nz::PlacementNew(address, a, b, c, d, e, f, g, h, port); + return true; + } } - return nullptr; + lua.Error("No matching overload for constructor"); + return false; }); - ipAddressClass.BindMethod("GetPort", &Nz::IpAddress::GetPort); + ipAddressClass.BindMethod("GetPort", &Nz::IpAddress::GetPort); ipAddressClass.BindMethod("GetProtocol", &Nz::IpAddress::GetProtocol); - ipAddressClass.BindMethod("IsLoopback", &Nz::IpAddress::IsLoopback); - ipAddressClass.BindMethod("IsValid", &Nz::IpAddress::IsValid); - ipAddressClass.BindMethod("ToUInt32", &Nz::IpAddress::ToUInt32); - ipAddressClass.BindMethod("__tostring", &Nz::IpAddress::ToString); + ipAddressClass.BindMethod("IsLoopback", &Nz::IpAddress::IsLoopback); + ipAddressClass.BindMethod("IsValid", &Nz::IpAddress::IsValid); + ipAddressClass.BindMethod("ToUInt32", &Nz::IpAddress::ToUInt32); + ipAddressClass.BindMethod("__tostring", &Nz::IpAddress::ToString); ipAddressClass.BindStaticMethod("ResolveAddress", [] (Nz::LuaInstance& instance) -> int { @@ -79,7 +103,7 @@ namespace Ndk int argIndex = 1; Nz::NetProtocol protocol = instance.Check(&argIndex); Nz::String hostname = instance.Check(&argIndex); - Nz::String service = instance.Check(&argIndex, "http"); + Nz::String service = instance.Check(&argIndex, "http"); std::vector addresses = Nz::IpAddress::ResolveHostname(protocol, hostname, service, &error); if (error == Nz::ResolveError_NoError) diff --git a/SDK/src/NDK/LuaBinding_Utility.cpp b/SDK/src/NDK/LuaBinding_Utility.cpp index 8ffa7824d..4ccb18fa6 100644 --- a/SDK/src/NDK/LuaBinding_Utility.cpp +++ b/SDK/src/NDK/LuaBinding_Utility.cpp @@ -89,9 +89,10 @@ namespace Ndk }); /*********************************** Nz::Font **********************************/ - fontClass.SetConstructor([] (Nz::LuaInstance& lua) -> Nz::FontRef* + fontClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::FontRef* font) { - return new Nz::FontRef(new Nz::Font); + Nz::PlacementNew(font, Nz::Font::New()); + return true; }); fontClass.BindMethod("ClearGlyphCache", &Nz::Font::ClearGlyphCache); diff --git a/include/Nazara/Lua/LuaClass.hpp b/include/Nazara/Lua/LuaClass.hpp index 8f9990bef..b872ad2f7 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; @@ -36,6 +36,8 @@ namespace Nz LuaClass(const String& name); + void BindDefaultConstructor(); + void BindMethod(const String& name, ClassFunc method); template std::enable_if_t::value> BindMethod(const String& name, R(P::*func)(Args...), DefArgs&&... defArgs); template std::enable_if_t::value> BindMethod(const String& name, R(P::*func)(Args...) const, DefArgs&&... defArgs); diff --git a/include/Nazara/Lua/LuaClass.inl b/include/Nazara/Lua/LuaClass.inl index edb7103b6..710b50416 100644 --- a/include/Nazara/Lua/LuaClass.inl +++ b/include/Nazara/Lua/LuaClass.inl @@ -16,6 +16,16 @@ namespace Nz m_info->name = name; } + template + inline void LuaClass::BindDefaultConstructor() + { + SetConstructor([] (Nz::LuaInstance& lua, T* instance) + { + PlacementNew(instance); + return true; + }); + } + template template inline void LuaClass::Inherit(LuaClass

& parent) @@ -36,7 +46,7 @@ namespace Nz parentInfo->instanceGetters[m_info->name] = [info = m_info, convertFunc] (LuaInstance& lua) -> P* { - return convertFunc(*static_cast(lua.CheckUserdata(1, info->name))); + return convertFunc(static_cast(lua.CheckUserdata(1, info->name))); }; m_info->parentGetters.emplace_back([parentInfo, convertFunc] (LuaInstance& lua, T* instance) @@ -124,7 +134,7 @@ namespace Nz m_info->instanceGetters[m_info->name] = [info = m_info] (LuaInstance& lua) { - return *static_cast(lua.CheckUserdata(1, info->name)); + return static_cast(lua.CheckUserdata(1, info->name)); }; } lua.Pop(); // On pop la metatable @@ -322,14 +332,15 @@ namespace Nz lua.Remove(1); // On enlève l'argument "table" du stack - T* instance = constructor(lua); - if (!instance) + T* instance = static_cast(lua.PushUserdata(sizeof(T))); + + if (!constructor(lua, instance)) { lua.Error("Constructor failed"); return 0; // Normalement jamais exécuté (l'erreur provoquant une exception) } - lua.PushInstance(info->name.GetConstBuffer(), instance); + lua.SetMetatable(info->name); return 1; } @@ -341,11 +352,11 @@ namespace Nz std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); const FinalizerFunc& finalizer = info->finalizer; - T* instance = *static_cast(lua.CheckUserdata(1, info->name)); + T* instance = static_cast(lua.CheckUserdata(1, info->name)); lua.Remove(1); //< Remove the instance from the Lua stack if (!finalizer || finalizer(lua, *instance)) - delete instance; + instance->~T(); return 0; } @@ -399,7 +410,7 @@ namespace Nz std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); - T* instance = *static_cast(lua.CheckUserdata(1, info->name)); + T* instance = static_cast(lua.CheckUserdata(1, info->name)); lua.Remove(1); //< Remove the instance from the Lua stack Get(info, lua, instance); @@ -448,7 +459,7 @@ namespace Nz std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); const ClassIndexFunc& setter = info->setter; - T& instance = *(*static_cast(lua.CheckUserdata(1, info->name))); + T& instance = *static_cast(lua.CheckUserdata(1, info->name)); lua.Remove(1); //< Remove the instance from the Lua stack if (!setter(lua, instance)) diff --git a/include/Nazara/Lua/LuaInstance.hpp b/include/Nazara/Lua/LuaInstance.hpp index e2d15958f..b924f6a05 100644 --- a/include/Nazara/Lua/LuaInstance.hpp +++ b/include/Nazara/Lua/LuaInstance.hpp @@ -131,7 +131,8 @@ namespace Nz template void PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const; template void PushGlobal(const char* name, T&& arg); template void PushGlobal(const String& name, T&& arg); - template void PushInstance(const char* tname, T* instance) const; + template void PushInstance(const char* tname, const T& instance) const; + template void PushInstance(const char* tname, T&& instance) const; template void PushInstance(const char* tname, Args&&... args) const; void PushInteger(long long value) const; void PushLightUserdata(void* value) const; diff --git a/include/Nazara/Lua/LuaInstance.inl b/include/Nazara/Lua/LuaInstance.inl index 199efa38f..4c5685322 100644 --- a/include/Nazara/Lua/LuaInstance.inl +++ b/include/Nazara/Lua/LuaInstance.inl @@ -156,21 +156,21 @@ namespace Nz return LuaImplReplyVal(instance, val, TypeTag()); } - inline int LuaImplReplyVal(const LuaInstance& instance, std::string val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, std::string&& val, TypeTag) { instance.PushString(val.c_str(), val.size()); return 1; } template - inline int LuaImplReplyVal(const LuaInstance& instance, std::vector valContainer, TypeTag>) + inline int LuaImplReplyVal(const LuaInstance& instance, std::vector&& valContainer, TypeTag>) { std::size_t index = 1; instance.PushTable(valContainer.size()); - for (const T& val : valContainer) + for (T& val : valContainer) { instance.PushInteger(index++); - if (LuaImplReplyVal(instance, val, TypeTag()) != 1) + if (LuaImplReplyVal(instance, std::move(val), TypeTag()) != 1) { instance.Error("Couldn't create table: type need more than one place to store"); return 0; @@ -181,20 +181,20 @@ namespace Nz return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, ByteArray val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, ByteArray&& val, TypeTag) { instance.PushString(reinterpret_cast(val.GetConstBuffer()), val.GetSize()); return 1; } - inline int LuaImplReplyVal(const LuaInstance& instance, String val, TypeTag) + inline int LuaImplReplyVal(const LuaInstance& instance, String&& val, TypeTag) { instance.PushString(std::move(val)); return 1; } template - int LuaImplReplyVal(const LuaInstance& instance, std::pair val, TypeTag>) + int LuaImplReplyVal(const LuaInstance& instance, std::pair&& val, TypeTag>) { int retVal = 0; @@ -593,17 +593,30 @@ namespace Nz } template - void LuaInstance::PushInstance(const char* tname, T* instance) const + void LuaInstance::PushInstance(const char* tname, const T& instance) const { - T** userdata = static_cast(PushUserdata(sizeof(T*))); - *userdata = instance; + T* userdata = static_cast(PushUserdata(sizeof(T*))); + PlacementNew(userdata, instance); + + SetMetatable(tname); + } + + template + void LuaInstance::PushInstance(const char* tname, T&& instance) const + { + T* userdata = static_cast(PushUserdata(sizeof(T*))); + PlacementNew(userdata, std::move(instance)); + SetMetatable(tname); } template void LuaInstance::PushInstance(const char* tname, Args&&... args) const { - PushInstance(tname, new T(std::forward(args)...)); + T* userdata = static_cast(PushUserdata(sizeof(T*))); + PlacementNew(userdata, std::forward(args)...); + + SetMetatable(tname); } template From 1bdcdb36fafa3d8472f1feaccb3ec10b32c42c1d Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 24 Apr 2016 20:04:43 +0200 Subject: [PATCH 04/15] Sdk/LuaBinding: Fix issues with optimisation Former-commit-id: 5bc419c9e35055810f162501cb3f465e737739c2 --- SDK/include/NDK/LuaAPI.inl | 18 +++++++++--------- SDK/src/NDK/LuaBinding_Math.cpp | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/SDK/include/NDK/LuaAPI.inl b/SDK/include/NDK/LuaAPI.inl index a0a180ff9..69b69f7ed 100644 --- a/SDK/include/NDK/LuaAPI.inl +++ b/SDK/include/NDK/LuaAPI.inl @@ -48,9 +48,9 @@ namespace Nz default: { if (instance.IsOfType(index, "EulerAngles")) - angles->Set(*(*static_cast(instance.ToUserdata(index)))); + angles->Set(*static_cast(instance.ToUserdata(index))); else - angles->Set(*(*static_cast(instance.CheckUserdata(index, "Quaternion")))); + angles->Set(*static_cast(instance.CheckUserdata(index, "Quaternion"))); return 1; } @@ -68,7 +68,7 @@ namespace Nz inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, FontRef* fontRef, TypeTag) { - *fontRef = *(*static_cast(instance.CheckUserdata(index, "Font"))); + *fontRef = *static_cast(instance.CheckUserdata(index, "Font")); return 1; } @@ -104,9 +104,9 @@ namespace Nz default: { if (instance.IsOfType(index, "EulerAngles")) - quat->Set(*(*static_cast(instance.ToUserdata(index)))); + quat->Set(*static_cast(instance.ToUserdata(index))); else - quat->Set(*(*static_cast(instance.CheckUserdata(index, "Quaternion")))); + quat->Set(*static_cast(instance.CheckUserdata(index, "Quaternion"))); return 1; } @@ -152,7 +152,7 @@ namespace Nz return 1; default: - vec->Set(*(*static_cast(instance.CheckUserdata(index, "Vector2")))); + vec->Set(*static_cast(instance.CheckUserdata(index, "Vector2"))); return 1; } } @@ -191,7 +191,7 @@ namespace Nz return 1; default: - vec->Set(*(*static_cast(instance.CheckUserdata(index, "Vector3")))); + vec->Set(*static_cast(instance.CheckUserdata(index, "Vector3"))); return 1; } } @@ -218,9 +218,9 @@ namespace Nz inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, InstancedRenderableRef* renderable, TypeTag) { if (instance.IsOfType(index, "InstancedRenderable")) - *renderable = *(*static_cast(instance.CheckUserdata(index, "InstancedRenderable"))); + *renderable = *static_cast(instance.CheckUserdata(index, "InstancedRenderable")); else - *renderable = *(*static_cast(instance.CheckUserdata(index, "Model"))); + *renderable = *static_cast(instance.CheckUserdata(index, "Model")); return 1; } diff --git a/SDK/src/NDK/LuaBinding_Math.cpp b/SDK/src/NDK/LuaBinding_Math.cpp index 001eb1c73..99767a1e2 100644 --- a/SDK/src/NDK/LuaBinding_Math.cpp +++ b/SDK/src/NDK/LuaBinding_Math.cpp @@ -172,7 +172,7 @@ namespace Ndk } case 2: - Nz::PlacementNew(quaternion, lua.CheckNumber(1), *(*static_cast(lua.CheckUserdata(2, "Vector3")))); + Nz::PlacementNew(quaternion, lua.CheckNumber(1), *static_cast(lua.CheckUserdata(2, "Vector3"))); return true; case 4: From 44e20a5ba9bb2aa4e0bdac60445e969e92dd6302 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 24 Apr 2016 20:05:42 +0200 Subject: [PATCH 05/15] Sdk/LuaBinding: Add EntityHandle and WorldHandle queriers As requested Former-commit-id: 20e3d0621243caccd0d3283f077a33c03ab4d2a3 --- SDK/include/NDK/LuaAPI.inl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/SDK/include/NDK/LuaAPI.inl b/SDK/include/NDK/LuaAPI.inl index 69b69f7ed..5a6f9d147 100644 --- a/SDK/include/NDK/LuaAPI.inl +++ b/SDK/include/NDK/LuaAPI.inl @@ -214,6 +214,20 @@ namespace Nz return ret; } + inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Ndk::EntityHandle* handle, TypeTag) + { + *handle = std::move(*static_cast(instance.CheckUserdata(index, "Entity"))); + + return 1; + } + + inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Ndk::WorldHandle* handle, TypeTag) + { + *handle = std::move(*static_cast(instance.CheckUserdata(index, "World"))); + + return 1; + } + #ifndef NDK_SERVER inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, InstancedRenderableRef* renderable, TypeTag) { From fa90d3fd69f0c9660512dffba68a5e9db299e08f Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 24 Apr 2016 20:08:01 +0200 Subject: [PATCH 06/15] Sdk/LuaAPI: Add accessor to internal LuaBinding Former-commit-id: 3e93330d789cd5566cc50e26acb49970bde2c2bc --- SDK/include/NDK/LuaAPI.hpp | 2 ++ SDK/include/NDK/LuaAPI.inl | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/SDK/include/NDK/LuaAPI.hpp b/SDK/include/NDK/LuaAPI.hpp index 277948bd5..e19458d3f 100644 --- a/SDK/include/NDK/LuaAPI.hpp +++ b/SDK/include/NDK/LuaAPI.hpp @@ -24,6 +24,8 @@ namespace Ndk LuaAPI() = delete; ~LuaAPI() = delete; + static inline LuaBinding* GetBinding(); + static bool Initialize(); static void RegisterClasses(Nz::LuaInstance& instance); diff --git a/SDK/include/NDK/LuaAPI.inl b/SDK/include/NDK/LuaAPI.inl index 5a6f9d147..708577e0e 100644 --- a/SDK/include/NDK/LuaAPI.inl +++ b/SDK/include/NDK/LuaAPI.inl @@ -2,6 +2,7 @@ // This file is part of the "Nazara Development Kit" // For conditions of distribution and use, see copyright notice in Prerequesites.hpp +#include #include #include #include @@ -23,6 +24,14 @@ #include #endif +namespace Ndk +{ + inline LuaBinding* LuaAPI::GetBinding() + { + return s_binding; + } +} + namespace Nz { inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Color* color, TypeTag) From 98867fee1948b88c63161a0c47183d14d119c187 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 24 Apr 2016 21:14:10 +0200 Subject: [PATCH 07/15] Sdk/Binding: Bind Rect As requested Former-commit-id: 97fcb06de0505341f39418147c57d240e4210159 --- SDK/include/NDK/LuaAPI.inl | 48 +++++++++++ SDK/include/NDK/LuaBinding.hpp | 1 + SDK/src/NDK/LuaBinding.cpp | 1 + SDK/src/NDK/LuaBinding_Math.cpp | 147 ++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+) diff --git a/SDK/include/NDK/LuaAPI.inl b/SDK/include/NDK/LuaAPI.inl index 708577e0e..903e76c05 100644 --- a/SDK/include/NDK/LuaAPI.inl +++ b/SDK/include/NDK/LuaAPI.inl @@ -102,6 +102,36 @@ namespace Nz return 1; } + inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Rectd* rect, TypeTag) + { + instance.CheckType(index, LuaType_Table); + + rect->x = instance.CheckField("x", index); + rect->y = instance.CheckField("y", index); + rect->width = instance.CheckField("width", index); + rect->height = instance.CheckField("height", index); + + return 1; + } + + inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Rectf* rect, TypeTag) + { + Rectd rectDouble; + unsigned int ret = LuaImplQueryArg(instance, index, &rectDouble, TypeTag()); + + rect->Set(rectDouble); + return ret; + } + + inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Rectui* rect, TypeTag) + { + Rectd rectDouble; + unsigned int ret = LuaImplQueryArg(instance, index, &rectDouble, TypeTag()); + + rect->Set(rectDouble); + return ret; + } + inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Quaterniond* quat, TypeTag) { switch (instance.GetType(index)) @@ -341,6 +371,24 @@ namespace Nz return 1; } + inline int LuaImplReplyVal(const LuaInstance& instance, Rectd&& val, TypeTag) + { + instance.PushInstance("Rect", val); + return 1; + } + + inline int LuaImplReplyVal(const LuaInstance& instance, Rectf&& val, TypeTag) + { + instance.PushInstance("Rect", val); + return 1; + } + + inline int LuaImplReplyVal(const LuaInstance& instance, Rectui&& val, TypeTag) + { + instance.PushInstance("Rect", val); + return 1; + } + inline int LuaImplReplyVal(const LuaInstance& instance, Vector2d&& val, TypeTag) { instance.PushInstance("Vector2", val); diff --git a/SDK/include/NDK/LuaBinding.hpp b/SDK/include/NDK/LuaBinding.hpp index 66bb88978..265e9e452 100644 --- a/SDK/include/NDK/LuaBinding.hpp +++ b/SDK/include/NDK/LuaBinding.hpp @@ -69,6 +69,7 @@ namespace Ndk // Math Nz::LuaClass eulerAnglesClass; Nz::LuaClass quaternionClass; + Nz::LuaClass rectClass; Nz::LuaClass vector2dClass; Nz::LuaClass vector3dClass; diff --git a/SDK/src/NDK/LuaBinding.cpp b/SDK/src/NDK/LuaBinding.cpp index a23311075..33c70dbe1 100644 --- a/SDK/src/NDK/LuaBinding.cpp +++ b/SDK/src/NDK/LuaBinding.cpp @@ -14,6 +14,7 @@ namespace Ndk // Math eulerAnglesClass("EulerAngles"), quaternionClass("Quaternion"), + rectClass("Rect"), vector2dClass("Vector2"), vector3dClass("Vector3"), diff --git a/SDK/src/NDK/LuaBinding_Math.cpp b/SDK/src/NDK/LuaBinding_Math.cpp index 99767a1e2..cf5454450 100644 --- a/SDK/src/NDK/LuaBinding_Math.cpp +++ b/SDK/src/NDK/LuaBinding_Math.cpp @@ -149,6 +149,152 @@ namespace Ndk return false; }); + /*********************************** Nz::Rect **********************************/ + rectClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Rectd* rect) + { + unsigned int argCount = std::min(lua.GetStackTop(), 4U); + switch (argCount) + { + case 0: + case 4: + PlacementNew(rect, lua.CheckNumber(1, 0.0), lua.CheckNumber(2, 0.0), lua.CheckNumber(3, 0.0), lua.CheckNumber(4, 0.0)); + return true; + + case 1: + { + if (lua.IsOfType(1, "Rect")) + PlacementNew(rect, *static_cast(lua.ToUserdata(1))); + else if (lua.IsOfType(1, Nz::LuaType_Table)) + { + // TODO => Faire sans avoir à mettre de nom dans la table et prendre les éléments un à un pour créer le Rectd + PlacementNew(rect, lua.CheckField("x", 1), + lua.CheckField("y", 1), + lua.CheckField("width", 1), + lua.CheckField("height", 1)); + } + else if (lua.IsOfType(1, "Vector2")) + PlacementNew(rect, *static_cast(lua.ToUserdata(1))); + else + break; + + return true; + } + + case 2: + { + if (lua.IsOfType(1, Nz::LuaType_Number) && lua.IsOfType(2, Nz::LuaType_Number)) + PlacementNew(rect, lua.CheckNumber(1), lua.CheckNumber(2)); + else if (lua.IsOfType(1, "Vector2") && lua.IsOfType(2, "Vector2")) + PlacementNew(rect, *static_cast(lua.ToUserdata(1)), *static_cast(lua.ToUserdata(2))); + else + break; + + return true; + } + } + + lua.Error("No matching overload for Rect constructor"); + return false; + }); + + rectClass.BindMethod("__tostring", &Nz::Rectd::ToString); + + rectClass.SetGetter([] (Nz::LuaInstance& lua, Nz::Rectd& instance) + { + switch (lua.GetType(1)) + { + case Nz::LuaType_Number: + { + long long index = lua.CheckInteger(1); + if (index < 1 || index > 4) + return false; + + lua.Push(instance[index - 1]); + return true; + } + + case Nz::LuaType_String: + { + std::size_t length; + const char* xywh = lua.CheckString(1, &length); + + if (length != 1) + break; + + switch (xywh[0]) + { + case 'x': + lua.Push(instance.x); + return true; + + case 'y': + lua.Push(instance.y); + return true; + + case 'w': + lua.Push(instance.width); + return true; + + case 'h': + lua.Push(instance.height); + return true; + } + break; + } + } + + return false; + }); + + rectClass.SetSetter([] (Nz::LuaInstance& lua, Nz::Rectd& instance) + { + switch (lua.GetType(1)) + { + case Nz::LuaType_Number: + { + long long index = lua.CheckInteger(1); + if (index < 1 || index > 4) + return false; + + instance[index - 1] = lua.CheckNumber(2); + return true; + } + + case Nz::LuaType_String: + { + std::size_t length; + const char* xywh = lua.CheckString(1, &length); + + if (length != 1) + break; + + double value = lua.CheckNumber(2); + + switch (xywh[0]) + { + case 'x': + instance.x = value; + return true; + + case 'y': + instance.y = value; + return true; + + case 'w': + instance.width = value; + return true; + + case 'h': + instance.height = value; + return true; + } + break; + } + } + + return false; + }); + /*********************************** Nz::Quaternion **********************************/ quaternionClass.SetConstructor([] (Nz::LuaInstance& lua, Nz::Quaterniond* quaternion) { @@ -494,6 +640,7 @@ namespace Ndk { eulerAnglesClass.Register(instance); quaternionClass.Register(instance); + rectClass.Register(instance); vector2dClass.Register(instance); vector3dClass.Register(instance); } From 8700b21a96d007cab9745a343aefa85d734849b0 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 25 Apr 2016 18:33:28 +0200 Subject: [PATCH 08/15] Lua/LuaInstance: Add missing include Former-commit-id: b2156b2c9cf515900c0e37f379104ffc6767a7e7 --- include/Nazara/Lua/LuaInstance.inl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/Nazara/Lua/LuaInstance.inl b/include/Nazara/Lua/LuaInstance.inl index 4c5685322..24d4fcf34 100644 --- a/include/Nazara/Lua/LuaInstance.inl +++ b/include/Nazara/Lua/LuaInstance.inl @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -622,8 +623,8 @@ namespace Nz template T LuaInstance::CheckBounds(int index, long long value) const { - long long minBounds = std::numeric_limits::min(); - long long maxBounds = std::numeric_limits::max(); + constexpr long long minBounds = std::numeric_limits::min(); + constexpr long long maxBounds = std::numeric_limits::max(); if (value < minBounds || value > maxBounds) { Nz::StringStream stream; From 73f648616f2528db0bdb02d23409b7b3e34f62c2 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 25 Apr 2016 18:33:40 +0200 Subject: [PATCH 09/15] Sdk/State: Fix linker errors Former-commit-id: e9a23daa5f5b0bb2964541ed7def2422703a541b --- SDK/include/NDK/State.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SDK/include/NDK/State.hpp b/SDK/include/NDK/State.hpp index 0a113def3..613a504ab 100644 --- a/SDK/include/NDK/State.hpp +++ b/SDK/include/NDK/State.hpp @@ -16,8 +16,8 @@ namespace Ndk class State { public: - State(); - ~State(); + State() = default; + ~State() = default; virtual void Enter(StateMachine& fsm) = 0; virtual void Leave(StateMachine& fsm) = 0; From 0d6727e746caf9c92aca536ee235bd5c7f110764 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 25 Apr 2016 18:34:00 +0200 Subject: [PATCH 10/15] Core/ByteStream: Fix SetStream pointer overloads Former-commit-id: ca35afb6e7257df7097d6aa39e99ccc9b3c0085a --- src/Nazara/Core/ByteStream.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Nazara/Core/ByteStream.cpp b/src/Nazara/Core/ByteStream.cpp index cf5a045a9..bca3db240 100644 --- a/src/Nazara/Core/ByteStream.cpp +++ b/src/Nazara/Core/ByteStream.cpp @@ -71,7 +71,7 @@ namespace Nz { std::unique_ptr stream(new MemoryStream(byteArray, openMode)); - SetStream(m_ownedStream.get()); + SetStream(stream.get()); // SetStream reset our smart pointer, set it after calling it m_ownedStream = std::move(stream); } @@ -89,7 +89,7 @@ namespace Nz { std::unique_ptr stream(new MemoryView(ptr, size)); - SetStream(m_ownedStream.get()); + SetStream(stream.get()); // SetStream reset our smart pointer, set it after calling it m_ownedStream = std::move(stream); } @@ -107,7 +107,7 @@ namespace Nz { std::unique_ptr stream(new MemoryView(ptr, size)); - SetStream(m_ownedStream.get()); + SetStream(stream.get()); // SetStream reset our smart pointer, set it after calling it m_ownedStream = std::move(stream); } From 78469266fd2f4d469e450b84128b0e915ae8c449 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 27 Apr 2016 18:10:45 +0200 Subject: [PATCH 11/15] Core/File: Add OpenMode_MustExit Former-commit-id: 1df10e230d3c6ef71244060845b1fc02f7b5a8e9 --- include/Nazara/Core/Enums.hpp | 6 ++++-- src/Nazara/Core/Win32/FileImpl.cpp | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index 0c0530489..02039811b 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -79,7 +79,8 @@ namespace Nz OpenMode_Append = 0x01, // Disable writing on existing parts and put the cursor at the end OpenMode_Lock = 0x02, // Disable modifying the file before it is open - OpenMode_ReadOnly = 0x04, // Open in read only + OpenMode_MustExit = 0x04, // Fail if the file doesn't exists, even if opened in write mode + OpenMode_ReadOnly = 0x08, // Open in read only OpenMode_Text = 0x10, // Open in text mod OpenMode_Truncate = 0x20, // Create the file if it doesn't exist and empty it if it exists OpenMode_WriteOnly = 0x40, // Open in write only, create the file if it doesn't exist @@ -105,7 +106,8 @@ namespace Nz enum Plugin { Plugin_Assimp, - Plugin_FreeType + + Plugin_Count }; enum PrimitiveType diff --git a/src/Nazara/Core/Win32/FileImpl.cpp b/src/Nazara/Core/Win32/FileImpl.cpp index 8c479c798..688b87c99 100644 --- a/src/Nazara/Core/Win32/FileImpl.cpp +++ b/src/Nazara/Core/Win32/FileImpl.cpp @@ -64,7 +64,7 @@ namespace Nz { access |= GENERIC_READ; - if ((mode & OpenMode_WriteOnly) == 0) + if (mode & OpenMode_MustExit || (mode & OpenMode_WriteOnly) == 0) openMode |= OPEN_EXISTING; } @@ -77,6 +77,8 @@ namespace Nz if (mode & OpenMode_Truncate) openMode |= CREATE_ALWAYS; + else if (mode & OpenMode_MustExit) + openMode |= OPEN_EXISTING; else openMode |= OPEN_ALWAYS; } From 95cb384897acf5e8c4156268a249414e3c49e9a3 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 29 Apr 2016 09:03:05 +0200 Subject: [PATCH 12/15] Build: Add support for OS-specific defines Former-commit-id: 7181f755cfc2640e862e496db96909fdbe485072 --- build/scripts/common.lua | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/build/scripts/common.lua b/build/scripts/common.lua index 1018890b8..7c66bd7ec 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -787,6 +787,23 @@ function NazaraBuild:Process(infoTable) end infoTable.Libraries = libraries + for platform, defineTable in pairs(infoTable.OsDefines) do + platform = string.lower(platform) + if (platform == "posix") then + local osname = os.get() + if (PosixOSes[osname]) then + platform = osname + end + end + + if (os.is(platform)) then + for k,v in ipairs(defineTable) do + table.insert(infoTable.Defines, v) + end + end + end + infoTable.OsDefines = nil + for platform, fileTable in pairs(infoTable.OsFiles) do platform = string.lower(platform) if (platform == "posix") then @@ -838,6 +855,7 @@ function NazaraBuild:SetupInfoTable(infoTable) infoTable.Flags = {} infoTable.Includes = {} infoTable.Libraries = {} + infoTable.OsDefines = {} infoTable.OsFiles = {} infoTable.OsLibraries = {} end \ No newline at end of file From 019c1f4a3689f12b03d898c3686714721b9a57fa Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 29 Apr 2016 14:20:22 +0200 Subject: [PATCH 14/15] Core/File: Add SetSize method (currently missing Posix implementation!) Former-commit-id: c9ffb545485d90940d620e94fd25a7256d62ab58 --- include/Nazara/Core/File.hpp | 1 + src/Nazara/Core/File.cpp | 19 +++++++++++++++++++ src/Nazara/Core/Win32/FileImpl.cpp | 26 ++++++++++++++++++++++++++ src/Nazara/Core/Win32/FileImpl.hpp | 1 + 4 files changed, 47 insertions(+) diff --git a/include/Nazara/Core/File.hpp b/include/Nazara/Core/File.hpp index 6b905fbac..59b2b5457 100644 --- a/include/Nazara/Core/File.hpp +++ b/include/Nazara/Core/File.hpp @@ -65,6 +65,7 @@ namespace Nz bool SetCursorPos(CursorPosition pos, Int64 offset = 0); bool SetCursorPos(UInt64 offset) override; bool SetFile(const String& filePath); + bool SetSize(UInt64 size); File& operator=(const String& filePath); File& operator=(const File&) = delete; diff --git a/src/Nazara/Core/File.cpp b/src/Nazara/Core/File.cpp index c03fb7b7f..8505e42f9 100644 --- a/src/Nazara/Core/File.cpp +++ b/src/Nazara/Core/File.cpp @@ -454,6 +454,25 @@ namespace Nz return true; } + /*! + * \brief Sets the size of the file + * \return true if the file size has correctly changed + * + * \param size The size the file should have after this call + * + * \remark The cursor position is not affected by this call + * \remark The file must be open in write mode + */ + bool File::SetSize(UInt64 size) + { + NazaraLock(m_mutex) + + NazaraAssert(IsOpen(), "File is not open"); + NazaraAssert(IsWritable(), "File is not writable"); + + return m_impl->SetSize(size); + } + /*! * \brief Sets the file path * \return A reference to this diff --git a/src/Nazara/Core/Win32/FileImpl.cpp b/src/Nazara/Core/Win32/FileImpl.cpp index 688b87c99..dcce3d29a 100644 --- a/src/Nazara/Core/Win32/FileImpl.cpp +++ b/src/Nazara/Core/Win32/FileImpl.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -158,6 +159,31 @@ namespace Nz return SetFilePointerEx(m_handle, distance, nullptr, moveMethod) != 0; } + bool FileImpl::SetSize(UInt64 size) + { + UInt64 cursorPos = GetCursorPos(); + + CallOnExit resetCursor([this, cursorPos] () + { + if (!SetCursorPos(CursorPosition_AtBegin, cursorPos)) + NazaraWarning("Failed to reset cursor position to previous position: " + Error::GetLastSystemError()); + }); + + if (!SetCursorPos(CursorPosition_AtBegin, size)) + { + NazaraError("Failed to set file size: failed to move cursor position: " + Error::GetLastSystemError()); + return false; + } + + if (!SetEndOfFile(m_handle)) + { + NazaraError("Failed to set file size: " + Error::GetLastSystemError()); + return false; + } + + return true; + } + std::size_t FileImpl::Write(const void* buffer, std::size_t size) { DWORD written = 0; diff --git a/src/Nazara/Core/Win32/FileImpl.hpp b/src/Nazara/Core/Win32/FileImpl.hpp index 0f3745abc..9a669cb19 100644 --- a/src/Nazara/Core/Win32/FileImpl.hpp +++ b/src/Nazara/Core/Win32/FileImpl.hpp @@ -32,6 +32,7 @@ namespace Nz bool Open(const String& filePath, UInt32 mode); std::size_t Read(void* buffer, std::size_t size); bool SetCursorPos(CursorPosition pos, Int64 offset); + bool SetSize(UInt64 size); std::size_t Write(const void* buffer, std::size_t size); FileImpl& operator=(const FileImpl&) = delete; From 34b7260d54edb684f38c69d4a62b30af0477e42b Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 29 Apr 2016 14:22:14 +0200 Subject: [PATCH 15/15] Plugins: Add Assimp plugin (WIP) Currently load only static meshes Former-commit-id: 61dee8f53a423d6d170bd3bfe72e71daa63e8c5b --- build/scripts/common.lua | 27 +++- build/scripts/tools/assimp.lua | 21 +++ plugins/Assimp/CustomStream.cpp | 140 ++++++++++++++++++ plugins/Assimp/CustomStream.hpp | 31 ++++ plugins/Assimp/Plugin.cpp | 250 ++++++++++++++++++++++++++++++++ 5 files changed, 464 insertions(+), 5 deletions(-) create mode 100644 build/scripts/tools/assimp.lua create mode 100644 plugins/Assimp/CustomStream.cpp create mode 100644 plugins/Assimp/CustomStream.hpp create mode 100644 plugins/Assimp/Plugin.cpp diff --git a/build/scripts/common.lua b/build/scripts/common.lua index 1018890b8..d88333746 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -243,12 +243,17 @@ function NazaraBuild:Execute() -- Tools for k, toolTable in ipairs(self.OrderedTools) do - project("Nazara" .. toolTable.Name) + local prefix = "Nazara" + if (toolTable.Kind == "plugin") then + prefix = "Plugin" + end + + project(prefix .. toolTable.Name) location(_ACTION .. "/tools") targetdir(toolTable.Directory) - if (toolTable.Kind == "library") then + if (toolTable.Kind == "plugin" or toolTable.Kind == "library") then kind("SharedLib") elseif (toolTable.Kind == "consoleapp") then debugdir(toolTable.Directory) @@ -257,7 +262,7 @@ function NazaraBuild:Execute() debugdir(toolTable.Directory) kind("WindowedApp") else - assert(false, "wut") + assert(false, "Invalid tool Kind") end includedirs({ @@ -280,6 +285,8 @@ function NazaraBuild:Execute() libdirs("../lib/" .. makeLibDir .. "/x86") if (toolTable.Kind == "library") then targetdir("../lib/" .. makeLibDir .. "/x86") + elseif (toolTable.Kind == "plugin") then + targetdir("../plugins/" .. toolTable.Name .. "/lib/" .. makeLibDir .. "/x32") end configuration({"codeblocks or codelite or gmake", "x64"}) @@ -287,6 +294,8 @@ function NazaraBuild:Execute() libdirs("../lib/" .. makeLibDir .. "/x64") if (toolTable.Kind == "library") then targetdir("../lib/" .. makeLibDir .. "/x64") + elseif (toolTable.Kind == "plugin") then + targetdir("../plugins/" .. toolTable.Name .. "/lib/" .. makeLibDir .. "/x64") end configuration({"vs*", "x32"}) @@ -294,6 +303,8 @@ function NazaraBuild:Execute() libdirs("../lib/msvc/x86") if (toolTable.Kind == "library") then targetdir("../lib/msvc/x86") + elseif (toolTable.Kind == "plugin") then + targetdir("../plugins/" .. toolTable.Name .. "/lib/msvc/x86") end configuration({"vs*", "x64"}) @@ -301,6 +312,8 @@ function NazaraBuild:Execute() libdirs("../lib/msvc/x64") if (toolTable.Kind == "library") then targetdir("../lib/msvc/x64") + elseif (toolTable.Kind == "plugin") then + targetdir("../plugins/" .. toolTable.Name .. "/lib/msvc/x64") end configuration({"xcode3 or xcode4", "x32"}) @@ -308,6 +321,8 @@ function NazaraBuild:Execute() libdirs("../lib/xcode/x86") if (toolTable.Kind == "library") then targetdir("../lib/xcode/x86") + elseif (toolTable.Kind == "plugin") then + targetdir("../plugins/" .. toolTable.Name .. "/lib/xcode/x86") end configuration({"xcode3 or xcode4", "x64"}) @@ -315,9 +330,11 @@ function NazaraBuild:Execute() libdirs("../lib/xcode/x64") if (toolTable.Kind == "library") then targetdir("../lib/xcode/x64") + elseif (toolTable.Kind == "plugin") then + targetdir("../plugins/" .. toolTable.Name .. "/lib/xcode/x64") end - if (toolTable.Kind == "library") then + if (toolTable.Kind == "library" or toolTable.Kind == "plugin") then configuration("*Static") kind("StaticLib") @@ -719,7 +736,7 @@ function NazaraBuild:RegisterTool(toolTable) end local lowerCaseKind = toolTable.Kind:lower() - if (lowerCaseKind == "library" or lowerCaseKind == "consoleapp" or lowerCaseKind == "windowapp") then + if (lowerCaseKind == "library" or lowerCaseKind == "plugin" or lowerCaseKind == "consoleapp" or lowerCaseKind == "windowapp") then toolTable.Kind = lowerCaseKind else return false, "Invalid tool type" diff --git a/build/scripts/tools/assimp.lua b/build/scripts/tools/assimp.lua new file mode 100644 index 000000000..0eecbcd54 --- /dev/null +++ b/build/scripts/tools/assimp.lua @@ -0,0 +1,21 @@ +TOOL.Name = "Assimp" + +TOOL.Directory = "../SDK/lib" +TOOL.Kind = "Plugin" + +TOOL.Includes = { + "../include", + "../plugins/Assimp" +} + +TOOL.Files = { + "../plugins/Assimp/**.hpp", + "../plugins/Assimp/**.inl", + "../plugins/Assimp/**.cpp" +} + +TOOL.Libraries = { + "NazaraCore", + "NazaraUtility", + "assimp" +} diff --git a/plugins/Assimp/CustomStream.cpp b/plugins/Assimp/CustomStream.cpp new file mode 100644 index 000000000..9a010b0b2 --- /dev/null +++ b/plugins/Assimp/CustomStream.cpp @@ -0,0 +1,140 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Assimp Plugin" +// For conditions of distribution and use, see copyright notice in Plugin.cpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Nz; + +void StreamFlush(aiFile* file) +{ + Stream* stream = reinterpret_cast(file->UserData); + stream->Flush(); +} + +size_t StreamRead(aiFile* file, char* buffer, size_t size, size_t count) +{ + Stream* stream = reinterpret_cast(file->UserData); + return stream->Read(buffer, size * count); +} + +aiReturn StreamSeek(aiFile* file, size_t offset, aiOrigin origin) +{ + Stream* stream = reinterpret_cast(file->UserData); + switch (origin) + { + case aiOrigin_CUR: + return (stream->SetCursorPos(stream->GetCursorPos() + offset)) ? aiReturn_SUCCESS : aiReturn_FAILURE; + + case aiOrigin_END: + return (stream->SetCursorPos(stream->GetSize() - offset)) ? aiReturn_SUCCESS : aiReturn_FAILURE; + + case aiOrigin_SET: + return (stream->SetCursorPos(offset)) ? aiReturn_SUCCESS : aiReturn_FAILURE; + } + + NazaraWarning("Unhandled aiOrigin enum (value: 0x" + String(origin, 16) + ')'); + return aiReturn_FAILURE; +} + +size_t StreamSize(aiFile* file) +{ + Stream* stream = reinterpret_cast(file->UserData); + return static_cast(stream->GetSize()); +} + +size_t StreamTell(aiFile* file) +{ + Stream* stream = reinterpret_cast(file->UserData); + return static_cast(stream->GetCursorPos()); +} + +size_t StreamWrite(aiFile* file, const char* buffer, size_t size, size_t count) +{ + Stream* stream = reinterpret_cast(file->UserData); + return stream->Write(buffer, size * count); +} + +aiFile* StreamOpener(aiFileIO* fileIO, const char* filePath, const char* openMode) +{ + FileIOUserdata* fileIOUserdata = reinterpret_cast(fileIO->UserData); + + bool isOriginalStream = (std::strcmp(filePath, fileIOUserdata->originalFilePath) == 0); + if (!isOriginalStream && strstr(filePath, StreamPath) != 0) + return nullptr; + + aiUserData stream; + if (isOriginalStream) + stream = reinterpret_cast(fileIOUserdata->originalStream); + else + { + ErrorFlags errFlags(ErrorFlag_ThrowExceptionDisabled, true); + + ///TODO: Move to File::DecodeOpenMode + UInt32 openModeEnum = 0; + + if (std::strchr(openMode, 'r')) + { + openModeEnum |= OpenMode_ReadOnly; + if (std::strchr(openMode, '+')) + openModeEnum |= OpenMode_ReadWrite | OpenMode_MustExit; + } + else if (std::strchr(openMode, 'w')) + { + openModeEnum |= OpenMode_WriteOnly | OpenMode_Truncate; + if (std::strchr(openMode, '+')) + openModeEnum |= OpenMode_ReadOnly; + } + else if (std::strchr(openMode, 'a')) + { + openModeEnum |= OpenMode_WriteOnly | OpenMode_Append; + if (std::strchr(openMode, '+')) + openModeEnum |= OpenMode_ReadOnly; + } + else + { + NazaraError(String("Unhandled/Invalid openmode: ") + openMode + String(" for file ") + filePath); + return nullptr; + } + + if (!std::strchr(openMode, 'b')) + openModeEnum |= OpenMode_Text; + + std::unique_ptr file = std::make_unique(); + if (!file->Open(filePath, openModeEnum)) + return nullptr; + + stream = reinterpret_cast(file.release()); + } + + std::unique_ptr file = std::make_unique(); + file->FileSizeProc = StreamSize; + file->FlushProc = StreamFlush; + file->ReadProc = StreamRead; + file->SeekProc = StreamSeek; + file->TellProc = StreamTell; + file->WriteProc = StreamWrite; + file->UserData = stream; + + return file.release(); +} + +void StreamCloser(aiFileIO* fileIO, aiFile* file) +{ + FileIOUserdata* fileIOUserdata = reinterpret_cast(fileIO->UserData); + Stream* fileUserdata = reinterpret_cast(file->UserData); + + if (fileUserdata != fileIOUserdata->originalStream) + delete reinterpret_cast(file->UserData); + + delete file; +} diff --git a/plugins/Assimp/CustomStream.hpp b/plugins/Assimp/CustomStream.hpp new file mode 100644 index 000000000..9cb155e7c --- /dev/null +++ b/plugins/Assimp/CustomStream.hpp @@ -0,0 +1,31 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Assimp Plugin" +// For conditions of distribution and use, see copyright notice in Plugin.cpp + +#pragma once + +#ifndef NAZARA_ASSIMP_CUSTOM_STREAM_HPP +#define NAZARA_ASSIMP_CUSTOM_STREAM_HPP + +#include +#include + +constexpr const char StreamPath[] = ""; + +void StreamFlush(aiFile* file); +size_t StreamRead(aiFile* file, char* buffer, size_t size, size_t count); +aiReturn StreamSeek(aiFile* file, size_t offset, aiOrigin origin); +size_t StreamSize(aiFile* file); +size_t StreamTell(aiFile* file); +size_t StreamWrite(aiFile* file, const char* buffer, size_t size, size_t count); + +struct FileIOUserdata +{ + Nz::Stream* originalStream; + const char* originalFilePath; +}; + +aiFile* StreamOpener(aiFileIO* fileIO, const char* filePath, const char* openMode); +void StreamCloser(aiFileIO* fileIO, aiFile* file); + +#endif // NAZARA_ASSIMP_CUSTOM_STREAM_HPP \ No newline at end of file diff --git a/plugins/Assimp/Plugin.cpp b/plugins/Assimp/Plugin.cpp new file mode 100644 index 000000000..0e754ea70 --- /dev/null +++ b/plugins/Assimp/Plugin.cpp @@ -0,0 +1,250 @@ +/* +Nazara Engine - Assimp Plugin + +Copyright (C) 2015 Jérôme "Lynix" Leclercq (lynix680@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Nz; + +void ProcessJoints(aiNode* node, Skeleton* skeleton, const std::set& joints) +{ + Nz::String jointName(node->mName.data, node->mName.length); + if (joints.count(jointName)) + { + Joint* joint = skeleton->GetJoint(jointName); + if (joint) + { + if (node->mParent) + joint->SetParent(skeleton->GetJoint(node->mParent->mName.C_Str())); + + Matrix4f transformMatrix(node->mTransformation.a1, node->mTransformation.a2, node->mTransformation.a3, node->mTransformation.a4, + node->mTransformation.b1, node->mTransformation.b2, node->mTransformation.b3, node->mTransformation.b4, + node->mTransformation.c1, node->mTransformation.c2, node->mTransformation.c3, node->mTransformation.c4, + node->mTransformation.d1, node->mTransformation.d2, node->mTransformation.d3, node->mTransformation.d4); + + transformMatrix.InverseAffine(); + + joint->SetInverseBindMatrix(transformMatrix); + } + } + + for (unsigned int i = 0; i < node->mNumChildren; ++i) + ProcessJoints(node->mChildren[i], skeleton, joints); +} + +bool IsSupported(const String& extension) +{ + String dotExt = '.' + extension; + return (aiIsExtensionSupported(dotExt.GetConstBuffer()) == AI_TRUE); +} + +Ternary Check(Stream& stream, const MeshParams& parameters) +{ + bool skip; + if (parameters.custom.GetBooleanParameter("SkipAssimpLoader", &skip) && skip) + return Ternary_False; + + return Ternary_Unknown; +} + +bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters) +{ + Nz::String streamPath = stream.GetPath(); + + FileIOUserdata userdata; + userdata.originalFilePath = (!streamPath.IsEmpty()) ? streamPath.GetConstBuffer() : StreamPath; + userdata.originalStream = &stream; + + aiFileIO fileIO; + fileIO.CloseProc = StreamCloser; + fileIO.OpenProc = StreamOpener; + fileIO.UserData = reinterpret_cast(&userdata); + + unsigned int postProcess = aiProcess_CalcTangentSpace | aiProcess_JoinIdenticalVertices + | aiProcess_MakeLeftHanded | aiProcess_Triangulate + | aiProcess_RemoveComponent | aiProcess_GenSmoothNormals + | aiProcess_SplitLargeMeshes | aiProcess_LimitBoneWeights + | aiProcess_ImproveCacheLocality | aiProcess_RemoveRedundantMaterials + | aiProcess_FixInfacingNormals | aiProcess_SortByPType + | aiProcess_FindInvalidData | aiProcess_GenUVCoords + | aiProcess_TransformUVCoords | aiProcess_OptimizeMeshes + | aiProcess_OptimizeGraph | aiProcess_FlipWindingOrder + | aiProcess_Debone; + + if (!parameters.flipUVs) + postProcess |= aiProcess_FlipUVs; + + if (parameters.optimizeIndexBuffers) + postProcess |= aiProcess_ImproveCacheLocality; + + float smoothingAngle = 80.f; + parameters.custom.GetFloatParameter("AssimpLoader_SmoothingAngle", &smoothingAngle); + + int triangleLimit = 1'000'000; + parameters.custom.GetIntegerParameter("AssimpLoader_TriangleLimit", &triangleLimit); + + int vertexLimit = 1'000'000; + parameters.custom.GetIntegerParameter("AssimpLoader_VertexLimit", &vertexLimit); + + aiPropertyStore* properties = aiCreatePropertyStore(); + aiSetImportPropertyFloat(properties, AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, smoothingAngle); + aiSetImportPropertyInteger(properties, AI_CONFIG_PP_LBW_MAX_WEIGHTS, 4); + aiSetImportPropertyInteger(properties, AI_CONFIG_PP_SBP_REMOVE, ~aiPrimitiveType_TRIANGLE); //< We only want triangles + aiSetImportPropertyInteger(properties, AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, triangleLimit); + aiSetImportPropertyInteger(properties, AI_CONFIG_PP_SLM_VERTEX_LIMIT, vertexLimit); + aiSetImportPropertyInteger(properties, AI_CONFIG_PP_RVC_FLAGS, aiComponent_COLORS); + + const aiScene* scene = aiImportFileExWithProperties(userdata.originalFilePath, postProcess, &fileIO, properties); + aiReleasePropertyStore(properties); + + std::set joints; + + bool animatedMesh = false; + if (parameters.animated) + { + for (unsigned int i = 0; i < scene->mNumMeshes; ++i) + { + aiMesh* mesh = scene->mMeshes[i]; + if (mesh->HasBones()) // Inline functions can be safely called + { + animatedMesh = true; + for (unsigned int j = 0; j < mesh->mNumBones; ++j) + joints.insert(mesh->mBones[j]->mName.C_Str()); + } + } + } + + if (animatedMesh) + { + mesh->CreateSkeletal(joints.size()); + + Skeleton* skeleton = mesh->GetSkeleton(); + + // First, assign names + unsigned int jointIndex = 0; + for (const Nz::String& jointName : joints) + skeleton->GetJoint(jointIndex++)->SetName(jointName); + + ProcessJoints(scene->mRootNode, skeleton, joints); + + return false; + } + else + { + mesh->CreateStatic(); + + for (unsigned int i = 0; i < scene->mNumMeshes; ++i) + { + aiMesh* iMesh = scene->mMeshes[i]; + if (!iMesh->HasBones()) // Don't process skeletal meshs + { + unsigned int indexCount = iMesh->mNumFaces * 3; + unsigned int vertexCount = iMesh->mNumVertices; + + // Index buffer + bool largeIndices = (vertexCount > std::numeric_limits::max()); + + IndexBufferRef indexBuffer = IndexBuffer::New(largeIndices, indexCount, parameters.storage); + + IndexMapper indexMapper(indexBuffer, BufferAccess_DiscardAndWrite); + IndexIterator index = indexMapper.begin(); + + for (unsigned int j = 0; j < iMesh->mNumFaces; ++j) + { + aiFace& face = iMesh->mFaces[j]; + if (face.mNumIndices != 3) + NazaraWarning("Assimp plugin: This face is not a triangle!"); + + *index++ = face.mIndices[0]; + *index++ = face.mIndices[1]; + *index++ = face.mIndices[2]; + } + indexMapper.Unmap(); + + // Vertex buffer + VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.storage); + BufferMapper vertexMapper(vertexBuffer, BufferAccess_WriteOnly); + + MeshVertex* vertex = static_cast(vertexMapper.GetPointer()); + for (unsigned int j = 0; j < vertexCount; ++j) + { + aiVector3D position = iMesh->mVertices[j]; + aiVector3D normal = iMesh->mNormals[j]; + aiVector3D tangent = iMesh->mTangents[j]; + aiVector3D uv = iMesh->mTextureCoords[0][j]; + + vertex->position = parameters.scale * Vector3f(position.x, position.y, position.z); + vertex->normal.Set(normal.x, normal.y, normal.z); + vertex->tangent.Set(tangent.x, tangent.y, tangent.z); + vertex->uv.Set(uv.x, uv.y); + vertex++; + } + + vertexMapper.Unmap(); + + // Submesh + StaticMeshRef subMesh = StaticMesh::New(mesh); + subMesh->Create(vertexBuffer); + + subMesh->SetIndexBuffer(indexBuffer); + subMesh->GenerateAABB(); + subMesh->SetMaterialIndex(iMesh->mMaterialIndex); + + mesh->AddSubMesh(subMesh); + } + } + + if (parameters.center) + mesh->Recenter(); + } + + aiReleaseImport(scene); + + return true; +} + +extern "C" +{ + NAZARA_EXPORT int PluginLoad() + { + Nz::MeshLoader::RegisterLoader(IsSupported, Check, Load); + return 1; + } + + NAZARA_EXPORT void PluginUnload() + { + Nz::MeshLoader::UnregisterLoader(IsSupported, Check, Load); + } +}