Merge remote-tracking branch 'refs/remotes/origin/master' into reflection-mapping
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/FileLogger.hpp>
|
||||
#include <Nazara/Core/Flags.hpp>
|
||||
#include <Nazara/Core/Functor.hpp>
|
||||
#include <Nazara/Core/GuillotineBinPack.hpp>
|
||||
#include <Nazara/Core/HandledObject.hpp>
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Nz
|
||||
{
|
||||
ParameterType_Boolean,
|
||||
ParameterType_Color,
|
||||
ParameterType_Float,
|
||||
ParameterType_Double,
|
||||
ParameterType_Integer,
|
||||
ParameterType_None,
|
||||
ParameterType_Pointer,
|
||||
|
||||
@@ -54,12 +54,20 @@ namespace Nz
|
||||
private:
|
||||
BitField m_value;
|
||||
};
|
||||
|
||||
// Little hack to have them in both Nz and global scope
|
||||
namespace DetailFlagOperators
|
||||
{
|
||||
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator~(E lhs);
|
||||
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator|(E lhs, E rhs);
|
||||
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator&(E lhs, E rhs);
|
||||
template<typename E> constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator^(E lhs, E rhs);
|
||||
}
|
||||
|
||||
using namespace DetailFlagOperators;
|
||||
}
|
||||
|
||||
template<typename E> constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator~(E lhs);
|
||||
template<typename E> constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator|(E lhs, E rhs);
|
||||
template<typename E> constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator&(E lhs, E rhs);
|
||||
template<typename E> constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator^(E lhs, E rhs);
|
||||
using namespace Nz::DetailFlagOperators;
|
||||
|
||||
#include <Nazara/Core/Flags.inl>
|
||||
|
||||
|
||||
@@ -209,67 +209,71 @@ namespace Nz
|
||||
{
|
||||
return 1U << static_cast<BitField>(enumValue);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Override binary NOT operator on enum to turns into a Flags object.
|
||||
* \return A Flags object with reversed bits.
|
||||
*
|
||||
* \param lhs Enumeration value to reverse.
|
||||
*
|
||||
* Returns a Flags object with all state enabled except for the enum one.
|
||||
*/
|
||||
template<typename E>
|
||||
constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator~(E lhs)
|
||||
{
|
||||
return ~Nz::Flags<E>(lhs);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Override binary OR operator on enum to turns into a Flags object.
|
||||
* \return A Flags object with combined enum states.
|
||||
*
|
||||
* \param lhs First enumeration value to combine.
|
||||
* \param rhs Second enumeration value to combine.
|
||||
*
|
||||
* Returns a Flags object with combined states from the two enumeration values.
|
||||
*/
|
||||
template<typename E>
|
||||
constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator|(E lhs, E rhs)
|
||||
{
|
||||
return Nz::Flags<E>(lhs) | rhs;
|
||||
}
|
||||
namespace DetailFlagOperators
|
||||
{
|
||||
/*!
|
||||
* \brief Override binary NOT operator on enum to turns into a Flags object.
|
||||
* \return A Flags object with reversed bits.
|
||||
*
|
||||
* \param lhs Enumeration value to reverse.
|
||||
*
|
||||
* Returns a Flags object with all state enabled except for the enum one.
|
||||
*/
|
||||
template<typename E>
|
||||
constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator~(E lhs)
|
||||
{
|
||||
return ~Flags<E>(lhs);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Override binary AND operator on enum to turns into a Flags object.
|
||||
* \return A Flags object with compare enum states.
|
||||
*
|
||||
* \param lhs First enumeration value to compare.
|
||||
* \param rhs Second enumeration value to compare.
|
||||
*
|
||||
* Returns a Flags object with compared states from the two enumeration values.
|
||||
* In this case, only one flag will be enabled if both enumeration values are the same.
|
||||
*/
|
||||
template<typename E>
|
||||
constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator&(E lhs, E rhs)
|
||||
{
|
||||
return Nz::Flags<E>(lhs) & rhs;
|
||||
}
|
||||
/*!
|
||||
* \brief Override binary OR operator on enum to turns into a Flags object.
|
||||
* \return A Flags object with combined enum states.
|
||||
*
|
||||
* \param lhs First enumeration value to combine.
|
||||
* \param rhs Second enumeration value to combine.
|
||||
*
|
||||
* Returns a Flags object with combined states from the two enumeration values.
|
||||
*/
|
||||
template<typename E>
|
||||
constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator|(E lhs, E rhs)
|
||||
{
|
||||
return Flags<E>(lhs) | rhs;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Override binary XOR operator on enum to turns into a Flags object.
|
||||
* \return A Flags object with XORed enum states.
|
||||
*
|
||||
* \param lhs First enumeration value to compare.
|
||||
* \param rhs Second enumeration value to compare.
|
||||
*
|
||||
* Returns a Flags object with XORed states from the two enumeration values.
|
||||
* In this case, two flags will be enabled if both the enumeration values are different.
|
||||
*/
|
||||
template<typename E>
|
||||
constexpr std::enable_if_t<Nz::EnumAsFlags<E>::value, Nz::Flags<E>> operator^(E lhs, E rhs)
|
||||
{
|
||||
return Nz::Flags<E>(lhs) ^ rhs;
|
||||
/*!
|
||||
* \brief Override binary AND operator on enum to turns into a Flags object.
|
||||
* \return A Flags object with compare enum states.
|
||||
*
|
||||
* \param lhs First enumeration value to compare.
|
||||
* \param rhs Second enumeration value to compare.
|
||||
*
|
||||
* Returns a Flags object with compared states from the two enumeration values.
|
||||
* In this case, only one flag will be enabled if both enumeration values are the same.
|
||||
*/
|
||||
template<typename E>
|
||||
constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator&(E lhs, E rhs)
|
||||
{
|
||||
return Flags<E>(lhs) & rhs;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Override binary XOR operator on enum to turns into a Flags object.
|
||||
* \return A Flags object with XORed enum states.
|
||||
*
|
||||
* \param lhs First enumeration value to compare.
|
||||
* \param rhs Second enumeration value to compare.
|
||||
*
|
||||
* Returns a Flags object with XORed states from the two enumeration values.
|
||||
* In this case, two flags will be enabled if both the enumeration values are different.
|
||||
*/
|
||||
template<typename E>
|
||||
constexpr std::enable_if_t<EnumAsFlags<E>::value, Flags<E>> operator^(E lhs, E rhs)
|
||||
{
|
||||
return Flags<E>(lhs) ^ rhs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Core/DebugOff.hpp>
|
||||
|
||||
@@ -27,10 +27,13 @@ namespace Nz
|
||||
|
||||
void Clear();
|
||||
|
||||
inline void ForEach(const std::function<bool(const ParameterList& list, const String& name)>& callback);
|
||||
inline void ForEach(const std::function<void(const ParameterList& list, const String& name)>& callback) const;
|
||||
|
||||
bool GetBooleanParameter(const String& name, bool* value) const;
|
||||
bool GetColorParameter(const String& name, Color* value) const;
|
||||
bool GetFloatParameter(const String& name, float* value) const;
|
||||
bool GetIntegerParameter(const String& name, int* value) const;
|
||||
bool GetDoubleParameter(const String& name, double* value) const;
|
||||
bool GetIntegerParameter(const String& name, long long* value) const;
|
||||
bool GetParameterType(const String& name, ParameterType* type) const;
|
||||
bool GetPointerParameter(const String& name, void** value) const;
|
||||
bool GetStringParameter(const String& name, String* value) const;
|
||||
@@ -45,8 +48,8 @@ namespace Nz
|
||||
void SetParameter(const String& name, const String& value);
|
||||
void SetParameter(const String& name, const char* value);
|
||||
void SetParameter(const String& name, bool value);
|
||||
void SetParameter(const String& name, float value);
|
||||
void SetParameter(const String& name, int value);
|
||||
void SetParameter(const String& name, double value);
|
||||
void SetParameter(const String& name, long long value);
|
||||
void SetParameter(const String& name, void* value);
|
||||
void SetParameter(const String& name, void* value, Destructor destructor);
|
||||
|
||||
@@ -81,8 +84,8 @@ namespace Nz
|
||||
~Value() {}
|
||||
|
||||
bool boolVal;
|
||||
float floatVal;
|
||||
int intVal;
|
||||
double doubleVal;
|
||||
long long intVal;
|
||||
void* ptrVal;
|
||||
Color colorVal;
|
||||
String stringVal;
|
||||
@@ -102,4 +105,6 @@ namespace Nz
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::ParameterList& parameterList);
|
||||
|
||||
#include <Nazara/Core/ParameterList.inl>
|
||||
|
||||
#endif // NAZARA_PARAMETERLIST_HPP
|
||||
|
||||
42
include/Nazara/Core/ParameterList.inl
Normal file
42
include/Nazara/Core/ParameterList.inl
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/ParameterList.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \brief Iterates over every value of the parameter list
|
||||
*
|
||||
* \param callback Callback function called with every parameter contained in the list, which can return true to remove the key (or false to keep it)
|
||||
*
|
||||
* \remark Changing the ParameterList while iterating on it may cause bugs, but querying data is safe.
|
||||
*/
|
||||
inline void ParameterList::ForEach(const std::function<bool(const ParameterList& list, const String& name)>& callback)
|
||||
{
|
||||
for (auto it = m_parameters.begin(); it != m_parameters.end();)
|
||||
{
|
||||
if (callback(*this, it->first))
|
||||
it = m_parameters.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Iterates over every value of the parameter list
|
||||
*
|
||||
* \param callback Callback function called with every parameter contained in the list
|
||||
*
|
||||
* \remark Changing the ParameterList while iterating on it may cause bugs, but querying data is safe.
|
||||
*/
|
||||
inline void ParameterList::ForEach(const std::function<void(const ParameterList& list, const String& name)>& callback) const
|
||||
{
|
||||
for (auto& pair : m_parameters)
|
||||
callback(*this, pair.first);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Core/DebugOff.hpp>
|
||||
@@ -33,6 +33,8 @@
|
||||
#include <Nazara/Lua/Enums.hpp>
|
||||
#include <Nazara/Lua/Lua.hpp>
|
||||
#include <Nazara/Lua/LuaClass.hpp>
|
||||
#include <Nazara/Lua/LuaCoroutine.hpp>
|
||||
#include <Nazara/Lua/LuaInstance.hpp>
|
||||
#include <Nazara/Lua/LuaState.hpp>
|
||||
|
||||
#endif // NAZARA_GLOBAL_LUA_HPP
|
||||
|
||||
@@ -26,13 +26,13 @@ namespace Nz
|
||||
friend class LuaClass;
|
||||
|
||||
public:
|
||||
using ClassFunc = std::function<int(LuaInstance& lua, T& instance, std::size_t argumentCount)>;
|
||||
using ClassIndexFunc = std::function<bool(LuaInstance& lua, T& instance)>;
|
||||
using ConstructorFunc = std::function<bool(LuaInstance& lua, T* instance, std::size_t argumentCount)>;
|
||||
using ClassFunc = std::function<int(LuaState& state, T& instance, std::size_t argumentCount)>;
|
||||
using ClassIndexFunc = std::function<bool(LuaState& state, T& instance)>;
|
||||
using ConstructorFunc = std::function<bool(LuaState& state, T* instance, std::size_t argumentCount)>;
|
||||
template<typename P> using ConvertToParent = std::function<P*(T*)>;
|
||||
using FinalizerFunc = std::function<bool(LuaInstance& lua, T& instance)>;
|
||||
using StaticIndexFunc = std::function<bool(LuaInstance& lua)>;
|
||||
using StaticFunc = std::function<int(LuaInstance& lua)>;
|
||||
using FinalizerFunc = std::function<bool(LuaState& state, T& instance)>;
|
||||
using StaticIndexFunc = std::function<bool(LuaState& state)>;
|
||||
using StaticFunc = std::function<int(LuaState& state)>;
|
||||
|
||||
LuaClass() = default;
|
||||
LuaClass(const String& name);
|
||||
@@ -54,9 +54,9 @@ namespace Nz
|
||||
void Reset();
|
||||
void Reset(const String& name);
|
||||
|
||||
void Register(LuaInstance& lua);
|
||||
void Register(LuaState& state);
|
||||
|
||||
void PushGlobalTable(LuaInstance& lua);
|
||||
void PushGlobalTable(LuaState& state);
|
||||
|
||||
void SetConstructor(ConstructorFunc constructor);
|
||||
void SetFinalizer(FinalizerFunc finalizer);
|
||||
@@ -69,18 +69,18 @@ namespace Nz
|
||||
template<typename U, bool HasDestructor>
|
||||
friend struct LuaClassImplFinalizerSetupProxy;
|
||||
|
||||
void PushClassInfo(LuaInstance& lua);
|
||||
void SetupConstructor(LuaInstance& lua);
|
||||
void SetupDefaultToString(LuaInstance& lua);
|
||||
void SetupFinalizer(LuaInstance& lua);
|
||||
void SetupGetter(LuaInstance& lua, LuaCFunction proxy);
|
||||
void SetupGlobalTable(LuaInstance& lua);
|
||||
void SetupMetatable(LuaInstance& lua);
|
||||
void SetupMethod(LuaInstance& lua, LuaCFunction proxy, const String& name, std::size_t methodIndex);
|
||||
void SetupSetter(LuaInstance& lua, LuaCFunction proxy);
|
||||
void PushClassInfo(LuaState& state);
|
||||
void SetupConstructor(LuaState& state);
|
||||
void SetupDefaultToString(LuaState& state);
|
||||
void SetupFinalizer(LuaState& state);
|
||||
void SetupGetter(LuaState& state, LuaCFunction proxy);
|
||||
void SetupGlobalTable(LuaState& state);
|
||||
void SetupMetatable(LuaState& state);
|
||||
void SetupMethod(LuaState& state, LuaCFunction proxy, const String& name, std::size_t methodIndex);
|
||||
void SetupSetter(LuaState& state, LuaCFunction proxy);
|
||||
|
||||
using ParentFunc = std::function<void(LuaInstance& lua, T* instance)>;
|
||||
using InstanceGetter = std::function<T*(LuaInstance& lua)>;
|
||||
using ParentFunc = std::function<void(LuaState& state, T* instance)>;
|
||||
using InstanceGetter = std::function<T*(LuaState& state)>;
|
||||
|
||||
struct ClassInfo
|
||||
{
|
||||
@@ -98,17 +98,17 @@ namespace Nz
|
||||
int globalTableRef = -1;
|
||||
};
|
||||
|
||||
static int ConstructorProxy(lua_State* state);
|
||||
static int FinalizerProxy(lua_State* state);
|
||||
static int InfoDestructor(lua_State* state);
|
||||
static void Get(const std::shared_ptr<ClassInfo>& info, LuaInstance& lua, T* instance);
|
||||
static int GetterProxy(lua_State* state);
|
||||
static int MethodProxy(lua_State* state);
|
||||
static int SetterProxy(lua_State* state);
|
||||
static int StaticGetterProxy(lua_State* state);
|
||||
static int StaticMethodProxy(lua_State* state);
|
||||
static int StaticSetterProxy(lua_State* state);
|
||||
static int ToStringProxy(lua_State* state);
|
||||
static int ConstructorProxy(lua_State* internalState);
|
||||
static int FinalizerProxy(lua_State* internalState);
|
||||
static int InfoDestructor(lua_State* internalState);
|
||||
static void Get(const std::shared_ptr<ClassInfo>& info, LuaState& state, T* instance);
|
||||
static int GetterProxy(lua_State* internalState);
|
||||
static int MethodProxy(lua_State* internalState);
|
||||
static int SetterProxy(lua_State* internalState);
|
||||
static int StaticGetterProxy(lua_State* internalState);
|
||||
static int StaticMethodProxy(lua_State* internalState);
|
||||
static int StaticSetterProxy(lua_State* internalState);
|
||||
static int ToStringProxy(lua_State* internalState);
|
||||
|
||||
std::map<String, ClassFunc> m_methods;
|
||||
std::map<String, StaticFunc> m_staticMethods;
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace Nz
|
||||
template<class T>
|
||||
inline void LuaClass<T>::BindDefaultConstructor()
|
||||
{
|
||||
SetConstructor([] (Nz::LuaInstance& lua, T* instance, std::size_t argumentCount)
|
||||
SetConstructor([] (Nz::LuaState& state, T* instance, std::size_t argumentCount)
|
||||
{
|
||||
NazaraUnused(lua);
|
||||
NazaraUnused(state);
|
||||
NazaraUnused(argumentCount);
|
||||
|
||||
PlacementNew(instance);
|
||||
@@ -47,14 +47,14 @@ namespace Nz
|
||||
|
||||
std::shared_ptr<typename LuaClass<P>::ClassInfo>& parentInfo = parent.m_info;
|
||||
|
||||
parentInfo->instanceGetters[m_info->name] = [info = m_info, convertFunc] (LuaInstance& lua) -> P*
|
||||
parentInfo->instanceGetters[m_info->name] = [info = m_info, convertFunc] (LuaState& state) -> P*
|
||||
{
|
||||
return convertFunc(static_cast<T*>(lua.CheckUserdata(1, info->name)));
|
||||
return convertFunc(static_cast<T*>(state.CheckUserdata(1, info->name)));
|
||||
};
|
||||
|
||||
m_info->parentGetters.emplace_back([parentInfo, convertFunc] (LuaInstance& lua, T* instance)
|
||||
m_info->parentGetters.emplace_back([parentInfo, convertFunc] (LuaState& state, T* instance)
|
||||
{
|
||||
LuaClass<P>::Get(parentInfo, lua, convertFunc(instance));
|
||||
LuaClass<P>::Get(parentInfo, state, convertFunc(instance));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -71,30 +71,30 @@ namespace Nz
|
||||
m_info = std::make_shared<ClassInfo>();
|
||||
m_info->name = name;
|
||||
|
||||
m_info->instanceGetters[m_info->name] = [info = m_info] (LuaInstance& instance)
|
||||
m_info->instanceGetters[m_info->name] = [info = m_info] (LuaState& state)
|
||||
{
|
||||
return static_cast<T*>(instance.CheckUserdata(1, info->name));
|
||||
return static_cast<T*>(state.CheckUserdata(1, info->name));
|
||||
};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::Register(LuaInstance& lua)
|
||||
void LuaClass<T>::Register(LuaState& state)
|
||||
{
|
||||
PushClassInfo(lua);
|
||||
PushClassInfo(state);
|
||||
|
||||
// Let's create the metatable which will be associated with every instance.
|
||||
SetupMetatable(lua);
|
||||
// Let's create the metatable which will be associated with every state.
|
||||
SetupMetatable(state);
|
||||
|
||||
if (m_info->constructor || m_info->staticGetter || m_info->staticSetter || !m_staticMethods.empty())
|
||||
SetupGlobalTable(lua);
|
||||
SetupGlobalTable(state);
|
||||
|
||||
lua.Pop(); // Pop our ClassInfo, which is now referenced by all our functions
|
||||
state.Pop(); // Pop our ClassInfo, which is now referenced by all our functions
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::PushGlobalTable(LuaInstance& lua)
|
||||
void LuaClass<T>::PushGlobalTable(LuaState& state)
|
||||
{
|
||||
lua.PushReference(m_info->globalTableRef);
|
||||
state.PushReference(m_info->globalTableRef);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@@ -127,11 +127,11 @@ namespace Nz
|
||||
{
|
||||
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
|
||||
|
||||
BindMethod(name, [func, handler] (LuaInstance& lua, T& object, std::size_t /*argumentCount*/) -> int
|
||||
BindMethod(name, [func, handler] (LuaState& state, T& object, std::size_t /*argumentCount*/) -> int
|
||||
{
|
||||
handler.ProcessArguments(lua);
|
||||
handler.ProcessArguments(state);
|
||||
|
||||
return handler.Invoke(lua, object, func);
|
||||
return handler.Invoke(state, object, func);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -141,11 +141,11 @@ namespace Nz
|
||||
{
|
||||
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
|
||||
|
||||
BindMethod(name, [func, handler] (LuaInstance& lua, T& object, std::size_t /*argumentCount*/) -> int
|
||||
BindMethod(name, [func, handler] (LuaState& state, T& object, std::size_t /*argumentCount*/) -> int
|
||||
{
|
||||
handler.ProcessArguments(lua);
|
||||
handler.ProcessArguments(state);
|
||||
|
||||
return handler.Invoke(lua, object, func);
|
||||
return handler.Invoke(state, object, func);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -155,11 +155,11 @@ namespace Nz
|
||||
{
|
||||
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
|
||||
|
||||
BindMethod(name, [func, handler] (LuaInstance& lua, T& object, std::size_t /*argumentCount*/) -> int
|
||||
BindMethod(name, [func, handler] (LuaState& state, T& object, std::size_t /*argumentCount*/) -> int
|
||||
{
|
||||
handler.ProcessArguments(lua);
|
||||
handler.ProcessArguments(state);
|
||||
|
||||
return handler.Invoke(lua, object, func);
|
||||
return handler.Invoke(state, object, func);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -169,11 +169,11 @@ namespace Nz
|
||||
{
|
||||
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
|
||||
|
||||
BindMethod(name, [func, handler] (LuaInstance& lua, T& object, std::size_t /*argumentCount*/) -> int
|
||||
BindMethod(name, [func, handler] (LuaState& state, T& object, std::size_t /*argumentCount*/) -> int
|
||||
{
|
||||
handler.ProcessArguments(lua);
|
||||
handler.ProcessArguments(state);
|
||||
|
||||
return handler.Invoke(lua, object, func);
|
||||
return handler.Invoke(state, object, func);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -201,11 +201,11 @@ namespace Nz
|
||||
{
|
||||
typename LuaImplFunctionProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
|
||||
|
||||
BindStaticMethod(name, [func, handler] (LuaInstance& lua) -> int
|
||||
BindStaticMethod(name, [func, handler] (LuaState& state) -> int
|
||||
{
|
||||
handler.ProcessArguments(lua);
|
||||
handler.ProcessArguments(state);
|
||||
|
||||
return handler.Invoke(lua, func);
|
||||
return handler.Invoke(state, func);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -216,37 +216,37 @@ namespace Nz
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::PushClassInfo(LuaInstance& lua)
|
||||
void LuaClass<T>::PushClassInfo(LuaState& state)
|
||||
{
|
||||
// Our ClassInfo has to outlive the LuaClass, because we don't want to force the user to keep the LuaClass alive
|
||||
// To do that, each Registration creates a tiny shared_ptr wrapper whose life is directly managed by Lua.
|
||||
// This shared_ptr object gets pushed as a up-value for every proxy function set in the metatable.
|
||||
// This way, there is no way our ClassInfo gets freed before any instance and the global class gets destroyed.
|
||||
std::shared_ptr<ClassInfo>* info = static_cast<std::shared_ptr<ClassInfo>*>(lua.PushUserdata(sizeof(std::shared_ptr<ClassInfo>)));
|
||||
std::shared_ptr<ClassInfo>* info = static_cast<std::shared_ptr<ClassInfo>*>(state.PushUserdata(sizeof(std::shared_ptr<ClassInfo>)));
|
||||
PlacementNew(info, m_info);
|
||||
|
||||
// Setup a tiny metatable to let Lua know how to destroy our ClassInfo
|
||||
lua.PushTable(0, 1);
|
||||
lua.PushLightUserdata(info);
|
||||
lua.PushCFunction(InfoDestructor, 1);
|
||||
lua.SetField("__gc");
|
||||
lua.SetMetatable(-2);
|
||||
state.PushTable(0, 1);
|
||||
state.PushLightUserdata(info);
|
||||
state.PushCFunction(InfoDestructor, 1);
|
||||
state.SetField("__gc");
|
||||
state.SetMetatable(-2);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetupConstructor(LuaInstance& lua)
|
||||
void LuaClass<T>::SetupConstructor(LuaState& state)
|
||||
{
|
||||
lua.PushValue(1); // ClassInfo
|
||||
lua.PushCFunction(ConstructorProxy, 1);
|
||||
lua.SetField("__call"); // ClassMeta.__call = ConstructorProxy
|
||||
state.PushValue(1); // ClassInfo
|
||||
state.PushCFunction(ConstructorProxy, 1);
|
||||
state.SetField("__call"); // ClassMeta.__call = ConstructorProxy
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetupDefaultToString(LuaInstance& lua)
|
||||
void LuaClass<T>::SetupDefaultToString(LuaState& state)
|
||||
{
|
||||
lua.PushValue(1); // shared_ptr on UserData
|
||||
lua.PushCFunction(ToStringProxy, 1);
|
||||
lua.SetField("__tostring");
|
||||
state.PushValue(1); // shared_ptr on UserData
|
||||
state.PushCFunction(ToStringProxy, 1);
|
||||
state.SetField("__tostring");
|
||||
}
|
||||
|
||||
template<typename T, bool HasDestructor>
|
||||
@@ -255,61 +255,61 @@ namespace Nz
|
||||
template<typename T>
|
||||
struct LuaClassImplFinalizerSetupProxy<T, true>
|
||||
{
|
||||
static void Setup(LuaInstance& lua)
|
||||
static void Setup(LuaState& state)
|
||||
{
|
||||
lua.PushValue(1); // ClassInfo
|
||||
lua.PushCFunction(LuaClass<T>::FinalizerProxy, 1);
|
||||
lua.SetField("__gc");
|
||||
state.PushValue(1); // ClassInfo
|
||||
state.PushCFunction(LuaClass<T>::FinalizerProxy, 1);
|
||||
state.SetField("__gc");
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LuaClassImplFinalizerSetupProxy<T, false>
|
||||
{
|
||||
static void Setup(LuaInstance&)
|
||||
static void Setup(LuaState&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetupFinalizer(LuaInstance& lua)
|
||||
void LuaClass<T>::SetupFinalizer(LuaState& state)
|
||||
{
|
||||
LuaClassImplFinalizerSetupProxy<T, std::is_destructible<T>::value>::Setup(lua);
|
||||
LuaClassImplFinalizerSetupProxy<T, std::is_destructible<T>::value>::Setup(state);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetupGetter(LuaInstance& lua, LuaCFunction proxy)
|
||||
void LuaClass<T>::SetupGetter(LuaState& state, LuaCFunction proxy)
|
||||
{
|
||||
lua.PushValue(1); // ClassInfo
|
||||
lua.PushValue(-2); // Metatable
|
||||
lua.PushCFunction(proxy, 2);
|
||||
state.PushValue(1); // ClassInfo
|
||||
state.PushValue(-2); // Metatable
|
||||
state.PushCFunction(proxy, 2);
|
||||
|
||||
lua.SetField("__index"); // Getter
|
||||
state.SetField("__index"); // Getter
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetupGlobalTable(LuaInstance& lua)
|
||||
void LuaClass<T>::SetupGlobalTable(LuaState& state)
|
||||
{
|
||||
// Create the global table
|
||||
lua.PushTable(); // Class = {}
|
||||
state.PushTable(); // Class = {}
|
||||
|
||||
// Create a metatable which will be used for our global table
|
||||
lua.PushTable(); // ClassMeta = {}
|
||||
state.PushTable(); // ClassMeta = {}
|
||||
|
||||
if (m_info->constructor)
|
||||
SetupConstructor(lua);
|
||||
SetupConstructor(state);
|
||||
|
||||
if (m_info->staticGetter)
|
||||
SetupGetter(lua, StaticGetterProxy);
|
||||
SetupGetter(state, StaticGetterProxy);
|
||||
else
|
||||
{
|
||||
// Optimize by assigning the metatable instead of a search function
|
||||
lua.PushValue(-1); // Metatable
|
||||
lua.SetField("__index");
|
||||
state.PushValue(-1); // Metatable
|
||||
state.SetField("__index");
|
||||
}
|
||||
|
||||
if (m_info->staticSetter)
|
||||
SetupSetter(lua, StaticSetterProxy);
|
||||
SetupSetter(state, StaticSetterProxy);
|
||||
|
||||
m_info->staticMethods.reserve(m_staticMethods.size());
|
||||
for (auto& pair : m_staticMethods)
|
||||
@@ -317,41 +317,41 @@ namespace Nz
|
||||
std::size_t methodIndex = m_info->staticMethods.size();
|
||||
m_info->staticMethods.push_back(pair.second);
|
||||
|
||||
SetupMethod(lua, StaticMethodProxy, pair.first, methodIndex);
|
||||
SetupMethod(state, StaticMethodProxy, pair.first, methodIndex);
|
||||
}
|
||||
|
||||
lua.SetMetatable(-2); // setmetatable(Class, ClassMeta), pops ClassMeta
|
||||
state.SetMetatable(-2); // setmetatable(Class, ClassMeta), pops ClassMeta
|
||||
|
||||
lua.PushValue(-1); // As CreateReference() pops the table, push a copy
|
||||
m_info->globalTableRef = lua.CreateReference();
|
||||
state.PushValue(-1); // As CreateReference() pops the table, push a copy
|
||||
m_info->globalTableRef = state.CreateReference();
|
||||
|
||||
lua.SetGlobal(m_info->name); // _G["Class"] = Class
|
||||
state.SetGlobal(m_info->name); // _G["Class"] = Class
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetupMetatable(LuaInstance& lua)
|
||||
void LuaClass<T>::SetupMetatable(LuaState& state)
|
||||
{
|
||||
if (!lua.NewMetatable(m_info->name))
|
||||
if (!state.NewMetatable(m_info->name))
|
||||
NazaraWarning("Class \"" + m_info->name + "\" already registred in this instance");
|
||||
{
|
||||
SetupFinalizer(lua);
|
||||
SetupFinalizer(state);
|
||||
|
||||
if (m_info->getter || !m_info->parentGetters.empty())
|
||||
SetupGetter(lua, GetterProxy);
|
||||
SetupGetter(state, GetterProxy);
|
||||
else
|
||||
{
|
||||
// Optimize by assigning the metatable instead of a search function
|
||||
// This is only possible if we have no custom getter nor parent
|
||||
lua.PushValue(-1); // Metatable
|
||||
lua.SetField("__index");
|
||||
state.PushValue(-1); // Metatable
|
||||
state.SetField("__index");
|
||||
}
|
||||
|
||||
if (m_info->setter)
|
||||
SetupSetter(lua, SetterProxy);
|
||||
SetupSetter(state, SetterProxy);
|
||||
|
||||
// In case a __tostring method is missing, add a default implementation returning the class name
|
||||
if (m_methods.find("__tostring") == m_methods.end())
|
||||
SetupDefaultToString(lua);
|
||||
SetupDefaultToString(state);
|
||||
|
||||
m_info->methods.reserve(m_methods.size());
|
||||
for (auto& pair : m_methods)
|
||||
@@ -359,80 +359,80 @@ namespace Nz
|
||||
std::size_t methodIndex = m_info->methods.size();
|
||||
m_info->methods.push_back(pair.second);
|
||||
|
||||
SetupMethod(lua, MethodProxy, pair.first, methodIndex);
|
||||
SetupMethod(state, MethodProxy, pair.first, methodIndex);
|
||||
}
|
||||
}
|
||||
lua.Pop(); //< Pops the metatable, it won't be collected before it's referenced by the Lua registry.
|
||||
state.Pop(); //< Pops the metatable, it won't be collected before it's referenced by the Lua registry.
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetupMethod(LuaInstance& lua, LuaCFunction proxy, const String& name, std::size_t methodIndex)
|
||||
void LuaClass<T>::SetupMethod(LuaState& state, LuaCFunction proxy, const String& name, std::size_t methodIndex)
|
||||
{
|
||||
lua.PushValue(1); // ClassInfo
|
||||
lua.PushInteger(methodIndex);
|
||||
lua.PushCFunction(proxy, 2);
|
||||
state.PushValue(1); // ClassInfo
|
||||
state.PushInteger(methodIndex);
|
||||
state.PushCFunction(proxy, 2);
|
||||
|
||||
lua.SetField(name); // Method name
|
||||
state.SetField(name); // Method name
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::SetupSetter(LuaInstance& lua, LuaCFunction proxy)
|
||||
void LuaClass<T>::SetupSetter(LuaState& state, LuaCFunction proxy)
|
||||
{
|
||||
lua.PushValue(1); // ClassInfo
|
||||
lua.PushCFunction(proxy, 1);
|
||||
state.PushValue(1); // ClassInfo
|
||||
state.PushCFunction(proxy, 1);
|
||||
|
||||
lua.SetField("__newindex"); // Setter
|
||||
state.SetField("__newindex"); // Setter
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::ConstructorProxy(lua_State* state)
|
||||
int LuaClass<T>::ConstructorProxy(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
const ConstructorFunc& constructor = info->constructor;
|
||||
|
||||
lua.Remove(1); // On enlève l'argument "table" du stack
|
||||
state.Remove(1); // On enlève l'argument "table" du stack
|
||||
|
||||
std::size_t argCount = lua.GetStackTop();
|
||||
std::size_t argCount = state.GetStackTop();
|
||||
|
||||
T* instance = static_cast<T*>(lua.PushUserdata(sizeof(T)));
|
||||
T* instance = static_cast<T*>(state.PushUserdata(sizeof(T)));
|
||||
|
||||
if (!constructor(lua, instance, argCount))
|
||||
if (!constructor(state, instance, argCount))
|
||||
{
|
||||
lua.Error("Constructor failed");
|
||||
state.Error("Constructor failed");
|
||||
return 0; // Normalement jamais exécuté (l'erreur provoquant une exception)
|
||||
}
|
||||
|
||||
lua.SetMetatable(info->name);
|
||||
state.SetMetatable(info->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::FinalizerProxy(lua_State* state)
|
||||
int LuaClass<T>::FinalizerProxy(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
const FinalizerFunc& finalizer = info->finalizer;
|
||||
|
||||
T* instance = static_cast<T*>(lua.CheckUserdata(1, info->name));
|
||||
lua.Remove(1); //< Remove the instance from the Lua stack
|
||||
T* instance = static_cast<T*>(state.CheckUserdata(1, info->name));
|
||||
state.Remove(1); //< Remove the instance from the Lua stack
|
||||
|
||||
if (!finalizer || finalizer(lua, *instance))
|
||||
if (!finalizer || finalizer(state, *instance))
|
||||
instance->~T();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::InfoDestructor(lua_State* state)
|
||||
int LuaClass<T>::InfoDestructor(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
lua.DestroyReference(info->globalTableRef);
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
state.DestroyReference(info->globalTableRef);
|
||||
|
||||
using namespace std; // Obligatoire pour le destructeur
|
||||
info.~shared_ptr(); // Si vous voyez une autre façon de faire, je suis preneur
|
||||
@@ -441,27 +441,27 @@ namespace Nz
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void LuaClass<T>::Get(const std::shared_ptr<ClassInfo>& info, LuaInstance& lua, T* instance)
|
||||
void LuaClass<T>::Get(const std::shared_ptr<ClassInfo>& info, LuaState& state, T* instance)
|
||||
{
|
||||
const ClassIndexFunc& getter = info->getter;
|
||||
|
||||
if (!getter || !getter(lua, *instance))
|
||||
if (!getter || !getter(state, *instance))
|
||||
{
|
||||
// Query from the metatable
|
||||
lua.GetMetatable(info->name); //< Metatable
|
||||
lua.PushValue(2); //< Field
|
||||
lua.GetTable(); // Metatable[Field]
|
||||
state.GetMetatable(info->name); //< Metatable
|
||||
state.PushValue(2); //< Field
|
||||
state.GetTable(); // Metatable[Field]
|
||||
|
||||
lua.Remove(-2); // Remove Metatable
|
||||
state.Remove(-2); // Remove Metatable
|
||||
|
||||
if (!lua.IsValid(-1))
|
||||
if (!state.IsValid(-1))
|
||||
{
|
||||
for (const ParentFunc& parentGetter : info->parentGetters)
|
||||
{
|
||||
lua.Pop(); //< Pop the last nil value
|
||||
state.Pop(); //< Pop the last nil value
|
||||
|
||||
parentGetter(lua, instance);
|
||||
if (lua.IsValid(-1))
|
||||
parentGetter(state, instance);
|
||||
if (state.IsValid(-1))
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -469,131 +469,131 @@ namespace Nz
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::GetterProxy(lua_State* state)
|
||||
int LuaClass<T>::GetterProxy(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
|
||||
T* instance = static_cast<T*>(lua.CheckUserdata(1, info->name));
|
||||
T* instance = static_cast<T*>(state.CheckUserdata(1, info->name));
|
||||
|
||||
Get(info, lua, instance);
|
||||
Get(info, state, instance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::MethodProxy(lua_State* state)
|
||||
int LuaClass<T>::MethodProxy(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
|
||||
T* instance = nullptr;
|
||||
if (lua.GetMetatable(1))
|
||||
if (state.GetMetatable(1))
|
||||
{
|
||||
LuaType type = lua.GetField("__name");
|
||||
LuaType type = state.GetField("__name");
|
||||
if (type == LuaType_String)
|
||||
{
|
||||
String name = lua.ToString(-1);
|
||||
String name = state.ToString(-1);
|
||||
auto it = info->instanceGetters.find(name);
|
||||
if (it != info->instanceGetters.end())
|
||||
instance = it->second(lua);
|
||||
instance = it->second(state);
|
||||
}
|
||||
lua.Pop(2);
|
||||
state.Pop(2);
|
||||
}
|
||||
|
||||
if (!instance)
|
||||
{
|
||||
lua.Error("Method cannot be called without an object");
|
||||
state.Error("Method cannot be called without an object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t argCount = lua.GetStackTop() - 1U;
|
||||
std::size_t argCount = state.GetStackTop() - 1U;
|
||||
|
||||
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
|
||||
unsigned int index = static_cast<unsigned int>(state.ToInteger(state.GetIndexOfUpValue(2)));
|
||||
const ClassFunc& method = info->methods[index];
|
||||
return method(lua, *instance, argCount);
|
||||
return method(state, *instance, argCount);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::SetterProxy(lua_State* state)
|
||||
int LuaClass<T>::SetterProxy(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
const ClassIndexFunc& setter = info->setter;
|
||||
|
||||
T& instance = *static_cast<T*>(lua.CheckUserdata(1, info->name));
|
||||
T& instance = *static_cast<T*>(state.CheckUserdata(1, info->name));
|
||||
|
||||
if (!setter(lua, instance))
|
||||
if (!setter(state, instance))
|
||||
{
|
||||
std::size_t length;
|
||||
const char* str = lua.ToString(2, &length);
|
||||
const char* str = state.ToString(2, &length);
|
||||
|
||||
lua.Error("Class \"" + info->name + "\" has no field \"" + String(str, length) + "\")");
|
||||
state.Error("Class \"" + info->name + "\" has no field \"" + String(str, length) + "\")");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::StaticGetterProxy(lua_State* state)
|
||||
int LuaClass<T>::StaticGetterProxy(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
const StaticIndexFunc& getter = info->staticGetter;
|
||||
|
||||
if (!getter(lua))
|
||||
if (!getter(state))
|
||||
{
|
||||
// On accède alors à la table
|
||||
lua.PushValue(lua.GetIndexOfUpValue(2));
|
||||
lua.PushValue(-2);
|
||||
lua.GetTable();
|
||||
state.PushValue(state.GetIndexOfUpValue(2));
|
||||
state.PushValue(-2);
|
||||
state.GetTable();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::StaticMethodProxy(lua_State* state)
|
||||
int LuaClass<T>::StaticMethodProxy(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
unsigned int index = static_cast<unsigned int>(state.ToInteger(state.GetIndexOfUpValue(2)));
|
||||
const StaticFunc& method = info->staticMethods[index];
|
||||
|
||||
return method(lua);
|
||||
return method(state);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::StaticSetterProxy(lua_State* state)
|
||||
int LuaClass<T>::StaticSetterProxy(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
const StaticIndexFunc& setter = info->staticSetter;
|
||||
|
||||
if (!setter(lua))
|
||||
if (!setter(state))
|
||||
{
|
||||
std::size_t length;
|
||||
const char* str = lua.ToString(2, &length);
|
||||
const char* str = state.ToString(2, &length);
|
||||
|
||||
lua.Error("Class \"" + info->name + "\" has no static field \"" + String(str, length) + ')');
|
||||
state.Error("Class \"" + info->name + "\" has no static field \"" + String(str, length) + ')');
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int LuaClass<T>::ToStringProxy(lua_State* state)
|
||||
int LuaClass<T>::ToStringProxy(lua_State* internalState)
|
||||
{
|
||||
LuaInstance& lua = *LuaInstance::GetInstance(state);
|
||||
LuaState state = LuaInstance::GetState(internalState);
|
||||
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
|
||||
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(state.ToUserdata(state.GetIndexOfUpValue(1)));
|
||||
|
||||
lua.PushString(info->name);
|
||||
state.PushString(info->name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
44
include/Nazara/Lua/LuaCoroutine.hpp
Normal file
44
include/Nazara/Lua/LuaCoroutine.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Lua scripting module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_LUACOROUTINE_HPP
|
||||
#define NAZARA_LUACOROUTINE_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Lua/LuaState.hpp>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_LUA_API LuaCoroutine : public LuaState
|
||||
{
|
||||
friend class LuaState;
|
||||
|
||||
public:
|
||||
LuaCoroutine(const LuaCoroutine&) = delete;
|
||||
inline LuaCoroutine(LuaCoroutine&& instance);
|
||||
~LuaCoroutine();
|
||||
|
||||
bool CanResume() const;
|
||||
|
||||
Ternary Resume(unsigned int argCount = 0);
|
||||
|
||||
LuaCoroutine& operator=(const LuaCoroutine&) = delete;
|
||||
inline LuaCoroutine& operator=(LuaCoroutine&& instance);
|
||||
|
||||
private:
|
||||
LuaCoroutine(lua_State* internalState, int refIndex);
|
||||
|
||||
bool Run(int argCount, int resultCount) override;
|
||||
|
||||
int m_ref;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Lua/LuaCoroutine.inl>
|
||||
|
||||
#endif // NAZARA_LUACOROUTINE_HPP
|
||||
25
include/Nazara/Lua/LuaCoroutine.inl
Normal file
25
include/Nazara/Lua/LuaCoroutine.inl
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Lua scripting module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Lua/LuaCoroutine.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline LuaCoroutine::LuaCoroutine(LuaCoroutine&& instance) :
|
||||
LuaState(std::move(instance)),
|
||||
m_ref(instance.m_ref)
|
||||
{
|
||||
instance.m_ref = -1;
|
||||
}
|
||||
|
||||
inline LuaCoroutine& LuaCoroutine::operator=(LuaCoroutine&& instance)
|
||||
{
|
||||
LuaState::operator=(std::move(instance));
|
||||
|
||||
m_ref = instance.m_ref;
|
||||
instance.m_ref = -1;
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
@@ -4,198 +4,51 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_LUASTATE_HPP
|
||||
#define NAZARA_LUASTATE_HPP
|
||||
#ifndef NAZARA_LUAINSTANCE_HPP
|
||||
#define NAZARA_LUAINSTANCE_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Core/Stream.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Lua/Config.hpp>
|
||||
#include <Nazara/Lua/Enums.hpp>
|
||||
#include <Nazara/Lua/LuaState.hpp>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
struct lua_Debug;
|
||||
struct lua_State;
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class LuaInstance;
|
||||
|
||||
using LuaCFunction = int (*)(lua_State* state);
|
||||
using LuaFunction = std::function<int(LuaInstance& instance)>;
|
||||
|
||||
class NAZARA_LUA_API LuaInstance
|
||||
class NAZARA_LUA_API LuaInstance : public LuaState
|
||||
{
|
||||
friend class LuaCoroutine;
|
||||
friend class LuaState;
|
||||
|
||||
public:
|
||||
LuaInstance();
|
||||
LuaInstance(const LuaInstance&) = delete;
|
||||
LuaInstance(LuaInstance&& instance) noexcept;
|
||||
LuaInstance(LuaInstance&& instance) = default;
|
||||
~LuaInstance();
|
||||
|
||||
void ArgCheck(bool condition, unsigned int argNum, const char* error) const;
|
||||
void ArgCheck(bool condition, unsigned int argNum, const String& error) const;
|
||||
int ArgError(unsigned int argNum, const char* error) const;
|
||||
int ArgError(unsigned int argNum, const String& error) const;
|
||||
|
||||
bool Call(unsigned int argCount);
|
||||
bool Call(unsigned int argCount, unsigned int resultCount);
|
||||
|
||||
template<typename T> T Check(int* index) const;
|
||||
template<typename T> T Check(int* index, T defValue) const;
|
||||
void CheckAny(int index) const;
|
||||
bool CheckBoolean(int index) const;
|
||||
bool CheckBoolean(int index, bool defValue) const;
|
||||
template<typename T> T CheckBoundInteger(int index) const;
|
||||
template<typename T> T CheckBoundInteger(int index, T defValue) const;
|
||||
template<typename T> T CheckField(const char* fieldName, int tableIndex = -1) const;
|
||||
template<typename T> T CheckField(const String& fieldName, int tableIndex = -1) const;
|
||||
template<typename T> T CheckField(const char* fieldName, T defValue, int tableIndex = -1) const;
|
||||
template<typename T> T CheckField(const String& fieldName, T defValue, int tableIndex = -1) const;
|
||||
long long CheckInteger(int index) const;
|
||||
long long CheckInteger(int index, long long defValue) const;
|
||||
template<typename T> T CheckGlobal(const char* fieldName) const;
|
||||
template<typename T> T CheckGlobal(const String& fieldName) const;
|
||||
template<typename T> T CheckGlobal(const char* fieldName, T defValue) const;
|
||||
template<typename T> T CheckGlobal(const String& fieldName, T defValue) const;
|
||||
double CheckNumber(int index) const;
|
||||
double CheckNumber(int index, double defValue) const;
|
||||
void CheckStack(int space, const char* error = nullptr) const;
|
||||
void CheckStack(int space, const String& error) const;
|
||||
const char* CheckString(int index, std::size_t* length = nullptr) const;
|
||||
const char* CheckString(int index, const char* defValue, std::size_t* length = nullptr) const;
|
||||
void CheckType(int index, LuaType type) const;
|
||||
void* CheckUserdata(int index, const char* tname) const;
|
||||
void* CheckUserdata(int index, const String& tname) const;
|
||||
|
||||
bool Compare(int index1, int index2, LuaComparison comparison) const;
|
||||
void Compute(LuaOperation operation) const;
|
||||
|
||||
void Concatenate(int count) const;
|
||||
|
||||
int CreateReference();
|
||||
void DestroyReference(int ref);
|
||||
|
||||
String DumpStack() const;
|
||||
|
||||
void Error(const char* message) const;
|
||||
void Error(const String& message) const;
|
||||
|
||||
bool Execute(const String& code);
|
||||
bool ExecuteFromFile(const String& filePath);
|
||||
bool ExecuteFromMemory(const void* data, std::size_t size);
|
||||
bool ExecuteFromStream(Stream& stream);
|
||||
|
||||
int GetAbsIndex(int index) const;
|
||||
LuaType GetField(const char* fieldName, int tableIndex = -1) const;
|
||||
LuaType GetField(const String& fieldName, int tableIndex = -1) const;
|
||||
LuaType GetGlobal(const char* name) const;
|
||||
LuaType GetGlobal(const String& name) const;
|
||||
inline lua_State* GetInternalState() const;
|
||||
inline String GetLastError() const;
|
||||
inline std::size_t GetMemoryLimit() const;
|
||||
inline std::size_t GetMemoryUsage() const;
|
||||
LuaType GetMetatable(const char* tname) const;
|
||||
LuaType GetMetatable(const String& tname) const;
|
||||
bool GetMetatable(int index) const;
|
||||
unsigned int GetStackTop() const;
|
||||
LuaType GetTable(int index = -2) const;
|
||||
inline UInt32 GetTimeLimit() const;
|
||||
LuaType GetType(int index) const;
|
||||
const char* GetTypeName(LuaType type) const;
|
||||
|
||||
void Insert(int index) const;
|
||||
|
||||
bool IsOfType(int index, LuaType type) const;
|
||||
bool IsOfType(int index, const char* tname) const;
|
||||
bool IsOfType(int index, const String& tname) const;
|
||||
bool IsValid(int index) const;
|
||||
|
||||
long long Length(int index) const;
|
||||
|
||||
void MoveTo(LuaInstance* instance, int n) const;
|
||||
|
||||
bool NewMetatable(const char* str);
|
||||
bool NewMetatable(const String& str);
|
||||
bool Next(int index = -2) const;
|
||||
|
||||
void Pop(unsigned int n = 1U) const;
|
||||
|
||||
template<typename T> int Push(T arg) const;
|
||||
template<typename T, typename T2, typename... Args> int Push(T firstArg, T2 secondArg, Args... args) const;
|
||||
void PushBoolean(bool value) const;
|
||||
void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0) const;
|
||||
template<typename T> void PushField(const char* name, T&& arg, int tableIndex = -2) const;
|
||||
template<typename T> void PushField(const String& name, T&& arg, int tableIndex = -2) const;
|
||||
void PushFunction(LuaFunction func) const;
|
||||
template<typename R, typename... Args, typename... DefArgs> void PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const;
|
||||
template<typename T> void PushGlobal(const char* name, T&& arg);
|
||||
template<typename T> void PushGlobal(const String& name, T&& arg);
|
||||
template<typename T> void PushInstance(const char* tname, const T& instance) const;
|
||||
template<typename T> void PushInstance(const char* tname, T&& instance) const;
|
||||
template<typename T, typename... Args> void PushInstance(const char* tname, Args&&... args) const;
|
||||
void PushInteger(long long value) const;
|
||||
void PushLightUserdata(void* value) const;
|
||||
void PushMetatable(const char* str) const;
|
||||
void PushMetatable(const String& str) const;
|
||||
void PushNil() const;
|
||||
void PushNumber(double value) const;
|
||||
void PushReference(int ref) const;
|
||||
void PushString(const char* str) const;
|
||||
void PushString(const char* str, std::size_t size) const;
|
||||
void PushString(const String& str) const;
|
||||
void PushTable(std::size_t sequenceElementCount = 0, std::size_t arrayElementCount = 0) const;
|
||||
void* PushUserdata(std::size_t size) const;
|
||||
void PushValue(int index) const;
|
||||
|
||||
void Remove(int index) const;
|
||||
void Replace(int index) const;
|
||||
|
||||
void SetField(const char* name, int tableIndex = -2) const;
|
||||
void SetField(const String& name, int tableIndex = -2) const;
|
||||
void SetGlobal(const char* name);
|
||||
void SetGlobal(const String& name);
|
||||
void SetMetatable(const char* tname) const;
|
||||
void SetMetatable(const String& tname) const;
|
||||
void SetMetatable(int index) const;
|
||||
void SetMemoryLimit(std::size_t memoryLimit);
|
||||
void SetTable(int index = -3) const;
|
||||
void SetTimeLimit(UInt32 timeLimit);
|
||||
|
||||
bool ToBoolean(int index) const;
|
||||
long long ToInteger(int index, bool* succeeded = nullptr) const;
|
||||
double ToNumber(int index, bool* succeeded = nullptr) const;
|
||||
const void* ToPointer(int index) const;
|
||||
const char* ToString(int index, std::size_t* length = nullptr) const;
|
||||
void* ToUserdata(int index) const;
|
||||
void* ToUserdata(int index, const char* tname) const;
|
||||
void* ToUserdata(int index, const String& tname) const;
|
||||
inline void SetMemoryLimit(std::size_t memoryLimit);
|
||||
inline void SetTimeLimit(UInt32 limit);
|
||||
|
||||
LuaInstance& operator=(const LuaInstance&) = delete;
|
||||
LuaInstance& operator=(LuaInstance&& instance) noexcept;
|
||||
|
||||
static int GetIndexOfUpValue(int upValue);
|
||||
static LuaInstance* GetInstance(lua_State* state);
|
||||
LuaInstance& operator=(LuaInstance&& instance) = default;
|
||||
|
||||
private:
|
||||
template<typename T> T CheckBounds(int index, long long value) const;
|
||||
bool Run(int argCount, int resultCount);
|
||||
inline void SetMemoryUsage(std::size_t memoryUsage);
|
||||
|
||||
static void* MemoryAllocator(void *ud, void *ptr, std::size_t osize, std::size_t nsize);
|
||||
static int ProxyFunc(lua_State* state);
|
||||
static void TimeLimiter(lua_State* state, lua_Debug* debug);
|
||||
static void TimeLimiter(lua_State* internalState, lua_Debug* debug);
|
||||
|
||||
std::size_t m_memoryLimit;
|
||||
std::size_t m_memoryUsage;
|
||||
UInt32 m_timeLimit;
|
||||
Clock m_clock;
|
||||
String m_lastError;
|
||||
lua_State* m_state;
|
||||
unsigned int m_level;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Lua/LuaInstance.inl>
|
||||
|
||||
#endif // NAZARA_LUASTATE_HPP
|
||||
#endif // NAZARA_LUAINSTANCE_HPP
|
||||
|
||||
@@ -3,28 +3,10 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Lua/LuaInstance.hpp>
|
||||
#include <Nazara/Core/Algorithm.hpp>
|
||||
#include <Nazara/Core/Flags.hpp>
|
||||
#include <Nazara/Core/MemoryHelper.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <Nazara/Math/Algorithm.hpp>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include <Nazara/Lua/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline lua_State* LuaInstance::GetInternalState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
inline String LuaInstance::GetLastError() const
|
||||
{
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
inline std::size_t LuaInstance::GetMemoryLimit() const
|
||||
{
|
||||
return m_memoryLimit;
|
||||
@@ -40,758 +22,15 @@ namespace Nz
|
||||
return m_timeLimit;
|
||||
}
|
||||
|
||||
// Functions args
|
||||
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, bool* arg, TypeTag<bool>)
|
||||
inline void LuaInstance::SetMemoryLimit(std::size_t memoryLimit)
|
||||
{
|
||||
*arg = instance.CheckBoolean(index);
|
||||
return 1;
|
||||
m_memoryLimit = m_memoryLimit;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, bool* arg, bool defValue, TypeTag<bool>)
|
||||
inline void LuaInstance::SetTimeLimit(UInt32 limit)
|
||||
{
|
||||
*arg = instance.CheckBoolean(index, defValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, std::string* arg, TypeTag<std::string>)
|
||||
{
|
||||
std::size_t strLength = 0;
|
||||
const char* str = instance.CheckString(index, &strLength);
|
||||
|
||||
arg->assign(str, strLength);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, String* arg, TypeTag<String>)
|
||||
{
|
||||
std::size_t strLength = 0;
|
||||
const char* str = instance.CheckString(index, &strLength);
|
||||
|
||||
arg->Set(str, strLength);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<T>)
|
||||
{
|
||||
using UnderlyingT = std::underlying_type_t<T>;
|
||||
return LuaImplQueryArg(instance, index, reinterpret_cast<UnderlyingT*>(arg), TypeTag<UnderlyingT>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag<T>)
|
||||
{
|
||||
using UnderlyingT = std::underlying_type_t<T>;
|
||||
return LuaImplQueryArg(instance, index, reinterpret_cast<UnderlyingT*>(arg), static_cast<UnderlyingT>(defValue), TypeTag<UnderlyingT>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<T>)
|
||||
{
|
||||
using UnderlyingT = std::underlying_type_t<T>;
|
||||
|
||||
UnderlyingT pot2Val;
|
||||
unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, TypeTag<UnderlyingT>());
|
||||
|
||||
*arg = static_cast<T>(IntegralLog2Pot(pot2Val));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag<T>)
|
||||
{
|
||||
using UnderlyingT = std::underlying_type_t<T>;
|
||||
|
||||
UnderlyingT pot2Val;
|
||||
unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, 1U << static_cast<UnderlyingT>(defValue), TypeTag<UnderlyingT>());
|
||||
|
||||
*arg = static_cast<T>(IntegralLog2Pot(pot2Val));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Flags<E>* arg, TypeTag<Flags<E>>)
|
||||
{
|
||||
*arg = Flags<E>(instance.CheckBoundInteger<UInt32>(index));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<T>)
|
||||
{
|
||||
*arg = static_cast<T>(instance.CheckNumber(index));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag<T>)
|
||||
{
|
||||
*arg = static_cast<T>(instance.CheckNumber(index, static_cast<double>(defValue)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_integral<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<T>)
|
||||
{
|
||||
*arg = instance.CheckBoundInteger<T>(index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_integral<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag<T>)
|
||||
{
|
||||
*arg = instance.CheckBoundInteger<T>(index, defValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<!std::is_integral<T>::value && !std::is_enum<T>::value && !std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, const T& defValue, TypeTag<T> tag)
|
||||
{
|
||||
if (instance.IsValid(index))
|
||||
return LuaImplQueryArg(instance, index, arg, tag);
|
||||
else
|
||||
{
|
||||
*arg = defValue;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<const T&>)
|
||||
{
|
||||
return LuaImplQueryArg(instance, index, arg, TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, const T& defValue, TypeTag<const T&>)
|
||||
{
|
||||
return LuaImplQueryArg(instance, index, arg, defValue, TypeTag<T>());
|
||||
}
|
||||
|
||||
// Function returns
|
||||
inline int LuaImplReplyVal(const LuaInstance& instance, bool val, TypeTag<bool>)
|
||||
{
|
||||
instance.PushBoolean(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaInstance& instance, double val, TypeTag<double>)
|
||||
{
|
||||
instance.PushNumber(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaInstance& instance, float val, TypeTag<float>)
|
||||
{
|
||||
instance.PushNumber(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T>)
|
||||
{
|
||||
using EnumT = typename std::underlying_type<T>::type;
|
||||
return LuaImplReplyVal(instance, static_cast<EnumT>(val), TypeTag<EnumT>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T>)
|
||||
{
|
||||
Flags<T> flags(val);
|
||||
return LuaImplReplyVal(instance, flags, TypeTag<decltype(flags)>());
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
int LuaImplReplyVal(const LuaInstance& instance, Flags<E> val, TypeTag<Flags<E>>)
|
||||
{
|
||||
instance.PushInteger(UInt32(val));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_integral<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T>)
|
||||
{
|
||||
instance.PushInteger(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value || std::is_enum<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, val, TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value || std::is_enum<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<const T&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, val, TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<T&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(val), TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag<const T&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(val), TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int LuaImplReplyVal(const LuaInstance& instance, T&& val, TypeTag<T&&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::forward<T>(val), TypeTag<T>());
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaInstance& instance, std::string&& val, TypeTag<std::string>)
|
||||
{
|
||||
instance.PushString(val.c_str(), val.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline int LuaImplReplyVal(const LuaInstance& instance, std::vector<T>&& valContainer, TypeTag<std::vector<T>>)
|
||||
{
|
||||
std::size_t index = 1;
|
||||
instance.PushTable(valContainer.size());
|
||||
for (T& val : valContainer)
|
||||
{
|
||||
instance.PushInteger(index++);
|
||||
if (LuaImplReplyVal(instance, std::move(val), TypeTag<T>()) != 1)
|
||||
{
|
||||
instance.Error("Couldn't create table: type need more than one place to store");
|
||||
return 0;
|
||||
}
|
||||
instance.SetTable();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaInstance& instance, ByteArray&& val, TypeTag<ByteArray>)
|
||||
{
|
||||
instance.PushString(reinterpret_cast<const char*>(val.GetConstBuffer()), val.GetSize());
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaInstance& instance, String&& val, TypeTag<String>)
|
||||
{
|
||||
instance.PushString(std::move(val));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
int LuaImplReplyVal(const LuaInstance& instance, std::pair<T1, T2>&& val, TypeTag<std::pair<T1, T2>>)
|
||||
{
|
||||
int retVal = 0;
|
||||
|
||||
retVal += LuaImplReplyVal(instance, std::move(val.first), TypeTag<T1>());
|
||||
retVal += LuaImplReplyVal(instance, std::move(val.second), TypeTag<T2>());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template<bool HasDefault>
|
||||
struct LuaImplArgProcesser;
|
||||
|
||||
template<>
|
||||
struct LuaImplArgProcesser<true>
|
||||
{
|
||||
template<std::size_t N, std::size_t FirstDefArg, typename ArgType, typename ArgContainer, typename DefArgContainer>
|
||||
static unsigned int Process(const LuaInstance& instance, unsigned int argIndex, ArgContainer& args, DefArgContainer& defArgs)
|
||||
{
|
||||
return LuaImplQueryArg(instance, argIndex, &std::get<N>(args), std::get<FirstDefArg + std::tuple_size<DefArgContainer>() - N - 1>(defArgs), TypeTag<ArgType>());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct LuaImplArgProcesser<false>
|
||||
{
|
||||
template<std::size_t N, std::size_t FirstDefArg, typename ArgType, typename ArgContainer, typename DefArgContainer>
|
||||
static unsigned int Process(const LuaInstance& instance, unsigned int argIndex, ArgContainer& args, DefArgContainer& defArgs)
|
||||
{
|
||||
NazaraUnused(defArgs);
|
||||
|
||||
return LuaImplQueryArg(instance, argIndex, &std::get<N>(args), TypeTag<ArgType>());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
class LuaImplFunctionProxy
|
||||
{
|
||||
public:
|
||||
template<typename... DefArgs>
|
||||
class Impl
|
||||
{
|
||||
static constexpr std::size_t ArgCount = sizeof...(Args);
|
||||
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
|
||||
|
||||
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
|
||||
|
||||
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
|
||||
|
||||
public:
|
||||
Impl(DefArgs... defArgs) :
|
||||
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
|
||||
{
|
||||
}
|
||||
|
||||
void ProcessArguments(const LuaInstance& instance) const
|
||||
{
|
||||
m_index = 1;
|
||||
ProcessArgs<0, Args...>(instance);
|
||||
}
|
||||
|
||||
int Invoke(const LuaInstance& instance, void(*func)(Args...)) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
Apply(func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Ret>
|
||||
int Invoke(const LuaInstance& instance, Ret(*func)(Args...)) const
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(Apply(func, m_args)), TypeTag<decltype(Apply(func, m_args))>());
|
||||
}
|
||||
|
||||
private:
|
||||
using ArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
|
||||
using DefArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<DefArgs>>...>;
|
||||
|
||||
template<std::size_t N>
|
||||
void ProcessArgs(const LuaInstance& instance) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
// No argument to process
|
||||
}
|
||||
|
||||
template<std::size_t N, typename ArgType>
|
||||
void ProcessArgs(const LuaInstance& instance) const
|
||||
{
|
||||
LuaImplArgProcesser<(N >= FirstDefArg)>::template Process<N, FirstDefArg, ArgType>(instance, m_index, m_args, m_defaultArgs);
|
||||
}
|
||||
|
||||
template<std::size_t N, typename ArgType1, typename ArgType2, typename... Rest>
|
||||
void ProcessArgs(const LuaInstance& instance) const
|
||||
{
|
||||
ProcessArgs<N, ArgType1>(instance);
|
||||
ProcessArgs<N + 1, ArgType2, Rest...>(instance);
|
||||
}
|
||||
|
||||
mutable ArgContainer m_args;
|
||||
DefArgContainer m_defaultArgs;
|
||||
mutable unsigned int m_index;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
class LuaImplMethodProxy
|
||||
{
|
||||
public:
|
||||
template<typename... DefArgs>
|
||||
class Impl
|
||||
{
|
||||
static constexpr std::size_t ArgCount = sizeof...(Args);
|
||||
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
|
||||
|
||||
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
|
||||
|
||||
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
|
||||
|
||||
public:
|
||||
Impl(DefArgs... defArgs) :
|
||||
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
|
||||
{
|
||||
}
|
||||
|
||||
void ProcessArguments(const LuaInstance& instance) const
|
||||
{
|
||||
m_index = 2; //< 1 being the instance
|
||||
ProcessArgs<0, Args...>(instance);
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, T& object, void(P::*func)(Args...)) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
Apply(object, func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename P, typename Ret>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, T& object, Ret(P::*func)(Args...)) const
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(Apply(object, func, m_args)), TypeTag<decltype(Apply(object, func, m_args))>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, T& object, T&(P::*func)(Args...)) const
|
||||
{
|
||||
T& r = Apply(object, func, m_args);
|
||||
if (&r == &object)
|
||||
{
|
||||
instance.PushValue(1); //< Userdata
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return LuaImplReplyVal(instance, r, TypeTag<T&>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, const T& object, void(P::*func)(Args...) const) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
Apply(object, func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename P, typename Ret>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, const T& object, Ret(P::*func)(Args...) const) const
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(Apply(object, func, m_args)), TypeTag<decltype(Apply(object, func, m_args))>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaInstance& instance, const T& object, const T&(P::*func)(Args...) const) const
|
||||
{
|
||||
const T& r = Apply(object, func, m_args);
|
||||
if (&r == &object)
|
||||
{
|
||||
instance.PushValue(1); //< Userdata
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return LuaImplReplyVal(instance, r, TypeTag<T&>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, T& object, void(P::*func)(Args...)) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Apply(*object, func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename P, typename Ret>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, T& object, Ret(P::*func)(Args...)) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return LuaImplReplyVal(instance, std::move(Apply(*object, func, m_args)), TypeTag<decltype(Apply(*object, func, m_args))>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, T& object, typename PointedType<T>::type&(P::*func)(Args...) const) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const typename PointedType<T>::type& r = Apply(*object, func, m_args);
|
||||
if (&r == &*object)
|
||||
{
|
||||
instance.PushValue(1); //< Userdata
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return LuaImplReplyVal(instance, r, TypeTag<T&>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, const T& object, void(P::*func)(Args...) const) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Apply(*object, func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename P, typename Ret>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, const T& object, Ret(P::*func)(Args...) const) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return LuaImplReplyVal(instance, std::move(Apply(*object, func, m_args)), TypeTag<decltype(Apply(*object, func, m_args))>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, const T& object, const typename PointedType<T>::type&(P::*func)(Args...) const) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const typename PointedType<T>::type& r = Apply(*object, func, m_args);
|
||||
if (&r == &*object)
|
||||
{
|
||||
instance.PushValue(1); //< Userdata
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return LuaImplReplyVal(instance, r, TypeTag<T&>());
|
||||
}
|
||||
|
||||
private:
|
||||
using ArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
|
||||
using DefArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<DefArgs>>...>;
|
||||
|
||||
template<std::size_t N>
|
||||
void ProcessArgs(const LuaInstance& instance) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
// No argument to process
|
||||
}
|
||||
|
||||
template<std::size_t N, typename ArgType>
|
||||
void ProcessArgs(const LuaInstance& instance) const
|
||||
{
|
||||
m_index += LuaImplArgProcesser<(N >= FirstDefArg)>::template Process<N, FirstDefArg, ArgType>(instance, m_index, m_args, m_defaultArgs);
|
||||
}
|
||||
|
||||
template<std::size_t N, typename ArgType1, typename ArgType2, typename... Rest>
|
||||
void ProcessArgs(const LuaInstance& instance) const
|
||||
{
|
||||
ProcessArgs<N, ArgType1>(instance);
|
||||
ProcessArgs<N + 1, ArgType2, Rest...>(instance);
|
||||
}
|
||||
|
||||
mutable ArgContainer m_args;
|
||||
DefArgContainer m_defaultArgs;
|
||||
mutable unsigned int m_index;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::Check(int* index) const
|
||||
{
|
||||
NazaraAssert(index, "Invalid index pointer");
|
||||
|
||||
T object;
|
||||
*index += LuaImplQueryArg(*this, *index, &object, TypeTag<T>());
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::Check(int* index, T defValue) const
|
||||
{
|
||||
NazaraAssert(index, "Invalid index pointer");
|
||||
|
||||
T object;
|
||||
*index += LuaImplQueryArg(*this, *index, &object, defValue, TypeTag<T>());
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T LuaInstance::CheckBoundInteger(int index) const
|
||||
{
|
||||
return CheckBounds<T>(index, CheckInteger(index));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T LuaInstance::CheckBoundInteger(int index, T defValue) const
|
||||
{
|
||||
return CheckBounds<T>(index, CheckInteger(index, defValue));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::CheckField(const char* fieldName, int tableIndex) const
|
||||
{
|
||||
T object;
|
||||
|
||||
GetField(fieldName, tableIndex);
|
||||
tableIndex += LuaImplQueryArg(*this, -1, &object, TypeTag<T>());
|
||||
Pop();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::CheckField(const String& fieldName, int tableIndex) const
|
||||
{
|
||||
return CheckField<T>(fieldName.GetConstBuffer(), tableIndex);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::CheckField(const char* fieldName, T defValue, int tableIndex) const
|
||||
{
|
||||
T object;
|
||||
|
||||
GetField(fieldName, tableIndex);
|
||||
tableIndex += LuaImplQueryArg(*this, -1, &object, defValue, TypeTag<T>());
|
||||
Pop();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::CheckField(const String& fieldName, T defValue, int tableIndex) const
|
||||
{
|
||||
return CheckField<T>(fieldName.GetConstBuffer(), defValue, tableIndex);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::CheckGlobal(const char* fieldName) const
|
||||
{
|
||||
T object;
|
||||
|
||||
GetGlobal(fieldName);
|
||||
LuaImplQueryArg(*this, -1, &object, TypeTag<T>());
|
||||
Pop();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::CheckGlobal(const String& fieldName) const
|
||||
{
|
||||
return CheckGlobal<T>(fieldName.GetConstBuffer());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::CheckGlobal(const char* fieldName, T defValue) const
|
||||
{
|
||||
T object;
|
||||
|
||||
GetGlobal(fieldName);
|
||||
LuaImplQueryArg(*this, -1, &object, defValue, TypeTag<T>());
|
||||
Pop();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::CheckGlobal(const String& fieldName, T defValue) const
|
||||
{
|
||||
return CheckGlobal<T>(fieldName.GetConstBuffer(), defValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int LuaInstance::Push(T arg) const
|
||||
{
|
||||
return LuaImplReplyVal(*this, std::move(arg), TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename... Args>
|
||||
int LuaInstance::Push(T firstArg, T2 secondArg, Args... args) const
|
||||
{
|
||||
int valCount = 0;
|
||||
valCount += Push(std::move(firstArg));
|
||||
valCount += Push(secondArg, std::forward<Args>(args)...);
|
||||
|
||||
return valCount;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaInstance::PushField(const char* name, T&& arg, int tableIndex) const
|
||||
{
|
||||
Push<T>(std::forward<T>(arg));
|
||||
SetField(name, tableIndex);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaInstance::PushField(const String& name, T&& arg, int tableIndex) const
|
||||
{
|
||||
PushField(name.GetConstBuffer(), std::forward<T>(arg), tableIndex);
|
||||
}
|
||||
|
||||
template<typename R, typename... Args, typename... DefArgs>
|
||||
void LuaInstance::PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const
|
||||
{
|
||||
typename LuaImplFunctionProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
|
||||
|
||||
PushFunction([func, handler] (LuaInstance& lua) -> int
|
||||
{
|
||||
handler.ProcessArguments(lua);
|
||||
|
||||
return handler.Invoke(lua, func);
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaInstance::PushGlobal(const char* name, T&& arg)
|
||||
{
|
||||
Push<T>(std::forward<T>(arg));
|
||||
SetGlobal(name);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaInstance::PushGlobal(const String& name, T&& arg)
|
||||
{
|
||||
PushGlobal(name.GetConstBuffer(), std::forward<T>(arg));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaInstance::PushInstance(const char* tname, const T& instance) const
|
||||
{
|
||||
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
|
||||
PlacementNew(userdata, instance);
|
||||
|
||||
SetMetatable(tname);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaInstance::PushInstance(const char* tname, T&& instance) const
|
||||
{
|
||||
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
|
||||
PlacementNew(userdata, std::move(instance));
|
||||
|
||||
SetMetatable(tname);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void LuaInstance::PushInstance(const char* tname, Args&&... args) const
|
||||
{
|
||||
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
|
||||
PlacementNew(userdata, std::forward<Args>(args)...);
|
||||
|
||||
SetMetatable(tname);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaInstance::CheckBounds(int index, long long value) const
|
||||
{
|
||||
constexpr long long minBounds = std::numeric_limits<T>::min();
|
||||
constexpr long long maxBounds = std::numeric_limits<T>::max();
|
||||
if (value < minBounds || value > maxBounds)
|
||||
{
|
||||
Nz::StringStream stream;
|
||||
stream << "Argument #" << index << " is outside value range [" << minBounds << ", " << maxBounds << "] (" << value << ')';
|
||||
Error(stream);
|
||||
}
|
||||
|
||||
return static_cast<T>(value);
|
||||
m_timeLimit = limit;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Lua/DebugOff.hpp>
|
||||
|
||||
197
include/Nazara/Lua/LuaState.hpp
Normal file
197
include/Nazara/Lua/LuaState.hpp
Normal file
@@ -0,0 +1,197 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Lua scripting module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_LUASTATE_HPP
|
||||
#define NAZARA_LUASTATE_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Core/Stream.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Lua/Config.hpp>
|
||||
#include <Nazara/Lua/Enums.hpp>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
struct lua_Debug;
|
||||
struct lua_State;
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class LuaCoroutine;
|
||||
class LuaInstance;
|
||||
class LuaState;
|
||||
|
||||
using LuaCFunction = int (*)(lua_State* internalState);
|
||||
using LuaFunction = std::function<int(LuaState& state)>;
|
||||
|
||||
class NAZARA_LUA_API LuaState
|
||||
{
|
||||
public:
|
||||
LuaState(const LuaState&) = default;
|
||||
LuaState(LuaState&& instance) noexcept;
|
||||
~LuaState() = default;
|
||||
|
||||
void ArgCheck(bool condition, unsigned int argNum, const char* error) const;
|
||||
void ArgCheck(bool condition, unsigned int argNum, const String& error) const;
|
||||
int ArgError(unsigned int argNum, const char* error) const;
|
||||
int ArgError(unsigned int argNum, const String& error) const;
|
||||
|
||||
bool Call(unsigned int argCount);
|
||||
bool Call(unsigned int argCount, unsigned int resultCount);
|
||||
|
||||
template<typename T> T Check(int* index) const;
|
||||
template<typename T> T Check(int* index, T defValue) const;
|
||||
void CheckAny(int index) const;
|
||||
bool CheckBoolean(int index) const;
|
||||
bool CheckBoolean(int index, bool defValue) const;
|
||||
template<typename T> T CheckBoundInteger(int index) const;
|
||||
template<typename T> T CheckBoundInteger(int index, T defValue) const;
|
||||
template<typename T> T CheckField(const char* fieldName, int tableIndex = -1) const;
|
||||
template<typename T> T CheckField(const String& fieldName, int tableIndex = -1) const;
|
||||
template<typename T> T CheckField(const char* fieldName, T defValue, int tableIndex = -1) const;
|
||||
template<typename T> T CheckField(const String& fieldName, T defValue, int tableIndex = -1) const;
|
||||
long long CheckInteger(int index) const;
|
||||
long long CheckInteger(int index, long long defValue) const;
|
||||
template<typename T> T CheckGlobal(const char* fieldName) const;
|
||||
template<typename T> T CheckGlobal(const String& fieldName) const;
|
||||
template<typename T> T CheckGlobal(const char* fieldName, T defValue) const;
|
||||
template<typename T> T CheckGlobal(const String& fieldName, T defValue) const;
|
||||
double CheckNumber(int index) const;
|
||||
double CheckNumber(int index, double defValue) const;
|
||||
void CheckStack(int space, const char* error = nullptr) const;
|
||||
void CheckStack(int space, const String& error) const;
|
||||
const char* CheckString(int index, std::size_t* length = nullptr) const;
|
||||
const char* CheckString(int index, const char* defValue, std::size_t* length = nullptr) const;
|
||||
void CheckType(int index, LuaType type) const;
|
||||
void* CheckUserdata(int index, const char* tname) const;
|
||||
void* CheckUserdata(int index, const String& tname) const;
|
||||
|
||||
bool Compare(int index1, int index2, LuaComparison comparison) const;
|
||||
void Compute(LuaOperation operation) const;
|
||||
|
||||
void Concatenate(int count) const;
|
||||
|
||||
int CreateReference();
|
||||
void DestroyReference(int ref);
|
||||
|
||||
String DumpStack() const;
|
||||
|
||||
void Error(const char* message) const;
|
||||
void Error(const String& message) const;
|
||||
|
||||
bool Execute(const String& code);
|
||||
bool ExecuteFromFile(const String& filePath);
|
||||
bool ExecuteFromMemory(const void* data, std::size_t size);
|
||||
bool ExecuteFromStream(Stream& stream);
|
||||
|
||||
int GetAbsIndex(int index) const;
|
||||
LuaType GetField(const char* fieldName, int tableIndex = -1) const;
|
||||
LuaType GetField(const String& fieldName, int tableIndex = -1) const;
|
||||
LuaType GetGlobal(const char* name) const;
|
||||
LuaType GetGlobal(const String& name) const;
|
||||
inline lua_State* GetInternalState() const;
|
||||
inline String GetLastError() const;
|
||||
LuaType GetMetatable(const char* tname) const;
|
||||
LuaType GetMetatable(const String& tname) const;
|
||||
bool GetMetatable(int index) const;
|
||||
unsigned int GetStackTop() const;
|
||||
LuaType GetTable(int index = -2) const;
|
||||
LuaType GetTableRaw(int index = -2) const;
|
||||
LuaType GetType(int index) const;
|
||||
const char* GetTypeName(LuaType type) const;
|
||||
|
||||
void Insert(int index) const;
|
||||
|
||||
bool IsOfType(int index, LuaType type) const;
|
||||
bool IsOfType(int index, const char* tname) const;
|
||||
bool IsOfType(int index, const String& tname) const;
|
||||
bool IsValid(int index) const;
|
||||
|
||||
long long Length(int index) const;
|
||||
std::size_t LengthRaw(int index) const;
|
||||
|
||||
void MoveTo(LuaState* instance, int n) const;
|
||||
|
||||
LuaCoroutine NewCoroutine();
|
||||
bool NewMetatable(const char* str);
|
||||
bool NewMetatable(const String& str);
|
||||
bool Next(int index = -2) const;
|
||||
|
||||
void Pop(unsigned int n = 1U) const;
|
||||
|
||||
template<typename T> int Push(T arg) const;
|
||||
template<typename T, typename T2, typename... Args> int Push(T firstArg, T2 secondArg, Args... args) const;
|
||||
void PushBoolean(bool value) const;
|
||||
void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0) const;
|
||||
template<typename T> void PushField(const char* name, T&& arg, int tableIndex = -2) const;
|
||||
template<typename T> void PushField(const String& name, T&& arg, int tableIndex = -2) const;
|
||||
void PushFunction(LuaFunction func) const;
|
||||
template<typename R, typename... Args, typename... DefArgs> void PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const;
|
||||
template<typename T> void PushGlobal(const char* name, T&& arg);
|
||||
template<typename T> void PushGlobal(const String& name, T&& arg);
|
||||
template<typename T> void PushInstance(const char* tname, const T& instance) const;
|
||||
template<typename T> void PushInstance(const char* tname, T&& instance) const;
|
||||
template<typename T, typename... Args> void PushInstance(const char* tname, Args&&... args) const;
|
||||
void PushInteger(long long value) const;
|
||||
void PushLightUserdata(void* value) const;
|
||||
void PushMetatable(const char* str) const;
|
||||
void PushMetatable(const String& str) const;
|
||||
void PushNil() const;
|
||||
void PushNumber(double value) const;
|
||||
void PushReference(int ref) const;
|
||||
void PushString(const char* str) const;
|
||||
void PushString(const char* str, std::size_t size) const;
|
||||
void PushString(const String& str) const;
|
||||
void PushTable(std::size_t sequenceElementCount = 0, std::size_t arrayElementCount = 0) const;
|
||||
void* PushUserdata(std::size_t size) const;
|
||||
void PushValue(int index) const;
|
||||
|
||||
void Remove(int index) const;
|
||||
void Replace(int index) const;
|
||||
|
||||
void SetField(const char* name, int tableIndex = -2) const;
|
||||
void SetField(const String& name, int tableIndex = -2) const;
|
||||
void SetGlobal(const char* name);
|
||||
void SetGlobal(const String& name);
|
||||
void SetMetatable(const char* tname) const;
|
||||
void SetMetatable(const String& tname) const;
|
||||
void SetMetatable(int index) const;
|
||||
void SetTable(int index = -3) const;
|
||||
void SetTableRaw(int index = -3) const;
|
||||
|
||||
bool ToBoolean(int index) const;
|
||||
long long ToInteger(int index, bool* succeeded = nullptr) const;
|
||||
double ToNumber(int index, bool* succeeded = nullptr) const;
|
||||
const void* ToPointer(int index) const;
|
||||
const char* ToString(int index, std::size_t* length = nullptr) const;
|
||||
void* ToUserdata(int index) const;
|
||||
void* ToUserdata(int index, const char* tname) const;
|
||||
void* ToUserdata(int index, const String& tname) const;
|
||||
|
||||
LuaState& operator=(const LuaState&) = default;
|
||||
LuaState& operator=(LuaState&& instance) noexcept;
|
||||
|
||||
static int GetIndexOfUpValue(int upValue);
|
||||
static LuaInstance& GetInstance(lua_State* internalState);
|
||||
static inline LuaState GetState(lua_State* internalState);
|
||||
|
||||
protected:
|
||||
LuaState(lua_State* internalState);
|
||||
|
||||
template<typename T> T CheckBounds(int index, long long value) const;
|
||||
virtual bool Run(int argCount, int resultCount);
|
||||
|
||||
static int ProxyFunc(lua_State* internalState);
|
||||
|
||||
String m_lastError;
|
||||
lua_State* m_state;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Lua/LuaState.inl>
|
||||
|
||||
#endif // NAZARA_LUASTATE_HPP
|
||||
792
include/Nazara/Lua/LuaState.inl
Normal file
792
include/Nazara/Lua/LuaState.inl
Normal file
@@ -0,0 +1,792 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Lua scripting module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Lua/LuaState.hpp>
|
||||
#include <Nazara/Core/Algorithm.hpp>
|
||||
#include <Nazara/Core/Flags.hpp>
|
||||
#include <Nazara/Core/MemoryHelper.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <Nazara/Math/Algorithm.hpp>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline LuaState::LuaState(lua_State* internalState) :
|
||||
m_state(internalState)
|
||||
{
|
||||
}
|
||||
|
||||
inline lua_State* LuaState::GetInternalState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
inline String LuaState::GetLastError() const
|
||||
{
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
// Functions args
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& instance, int index, bool* arg, TypeTag<bool>)
|
||||
{
|
||||
*arg = instance.CheckBoolean(index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& instance, int index, bool* arg, bool defValue, TypeTag<bool>)
|
||||
{
|
||||
*arg = instance.CheckBoolean(index, defValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& instance, int index, std::string* arg, TypeTag<std::string>)
|
||||
{
|
||||
std::size_t strLength = 0;
|
||||
const char* str = instance.CheckString(index, &strLength);
|
||||
|
||||
arg->assign(str, strLength);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& instance, int index, String* arg, TypeTag<String>)
|
||||
{
|
||||
std::size_t strLength = 0;
|
||||
const char* str = instance.CheckString(index, &strLength);
|
||||
|
||||
arg->Set(str, strLength);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<T>)
|
||||
{
|
||||
using UnderlyingT = std::underlying_type_t<T>;
|
||||
return LuaImplQueryArg(instance, index, reinterpret_cast<UnderlyingT*>(arg), TypeTag<UnderlyingT>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag<T>)
|
||||
{
|
||||
using UnderlyingT = std::underlying_type_t<T>;
|
||||
return LuaImplQueryArg(instance, index, reinterpret_cast<UnderlyingT*>(arg), static_cast<UnderlyingT>(defValue), TypeTag<UnderlyingT>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<T>)
|
||||
{
|
||||
using UnderlyingT = std::underlying_type_t<T>;
|
||||
|
||||
UnderlyingT pot2Val;
|
||||
unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, TypeTag<UnderlyingT>());
|
||||
|
||||
*arg = static_cast<T>(IntegralLog2Pot(pot2Val));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag<T>)
|
||||
{
|
||||
using UnderlyingT = std::underlying_type_t<T>;
|
||||
|
||||
UnderlyingT pot2Val;
|
||||
unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, 1U << static_cast<UnderlyingT>(defValue), TypeTag<UnderlyingT>());
|
||||
|
||||
*arg = static_cast<T>(IntegralLog2Pot(pot2Val));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
unsigned int LuaImplQueryArg(const LuaState& instance, int index, Flags<E>* arg, TypeTag<Flags<E>>)
|
||||
{
|
||||
*arg = Flags<E>(instance.CheckBoundInteger<UInt32>(index));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<T>)
|
||||
{
|
||||
*arg = static_cast<T>(instance.CheckNumber(index));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag<T>)
|
||||
{
|
||||
*arg = static_cast<T>(instance.CheckNumber(index, static_cast<double>(defValue)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_integral<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<T>)
|
||||
{
|
||||
*arg = instance.CheckBoundInteger<T>(index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_integral<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, T defValue, TypeTag<T>)
|
||||
{
|
||||
*arg = instance.CheckBoundInteger<T>(index, defValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<!std::is_integral<T>::value && !std::is_enum<T>::value && !std::is_floating_point<T>::value, unsigned int> LuaImplQueryArg(const LuaState& instance, int index, T* arg, const T& defValue, TypeTag<T> tag)
|
||||
{
|
||||
if (instance.IsValid(index))
|
||||
return LuaImplQueryArg(instance, index, arg, tag);
|
||||
else
|
||||
{
|
||||
*arg = defValue;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unsigned int LuaImplQueryArg(const LuaState& instance, int index, T* arg, TypeTag<const T&>)
|
||||
{
|
||||
return LuaImplQueryArg(instance, index, arg, TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unsigned int LuaImplQueryArg(const LuaState& instance, int index, T* arg, const T& defValue, TypeTag<const T&>)
|
||||
{
|
||||
return LuaImplQueryArg(instance, index, arg, defValue, TypeTag<T>());
|
||||
}
|
||||
|
||||
// Function returns
|
||||
inline int LuaImplReplyVal(const LuaState& instance, bool val, TypeTag<bool>)
|
||||
{
|
||||
instance.PushBoolean(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& instance, double val, TypeTag<double>)
|
||||
{
|
||||
instance.PushNumber(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& instance, float val, TypeTag<float>)
|
||||
{
|
||||
instance.PushNumber(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && !EnumAsFlags<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T>)
|
||||
{
|
||||
using EnumT = typename std::underlying_type<T>::type;
|
||||
return LuaImplReplyVal(instance, static_cast<EnumT>(val), TypeTag<EnumT>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_enum<T>::value && EnumAsFlags<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T>)
|
||||
{
|
||||
Flags<T> flags(val);
|
||||
return LuaImplReplyVal(instance, flags, TypeTag<decltype(flags)>());
|
||||
}
|
||||
|
||||
template<typename E>
|
||||
int LuaImplReplyVal(const LuaState& instance, Flags<E> val, TypeTag<Flags<E>>)
|
||||
{
|
||||
instance.PushInteger(UInt32(val));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_integral<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T>)
|
||||
{
|
||||
instance.PushInteger(val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value || std::is_enum<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, val, TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value || std::is_enum<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<const T&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, val, TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<T&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(val), TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<!std::is_arithmetic<T>::value && !std::is_enum<T>::value, int> LuaImplReplyVal(const LuaState& instance, T val, TypeTag<const T&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(val), TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int LuaImplReplyVal(const LuaState& instance, T&& val, TypeTag<T&&>)
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::forward<T>(val), TypeTag<T>());
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& instance, std::string&& val, TypeTag<std::string>)
|
||||
{
|
||||
instance.PushString(val.c_str(), val.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline int LuaImplReplyVal(const LuaState& instance, std::vector<T>&& valContainer, TypeTag<std::vector<T>>)
|
||||
{
|
||||
std::size_t index = 1;
|
||||
instance.PushTable(valContainer.size());
|
||||
for (T& val : valContainer)
|
||||
{
|
||||
instance.PushInteger(index++);
|
||||
if (LuaImplReplyVal(instance, std::move(val), TypeTag<T>()) != 1)
|
||||
{
|
||||
instance.Error("Couldn't create table: type need more than one place to store");
|
||||
return 0;
|
||||
}
|
||||
instance.SetTable();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& instance, ByteArray&& val, TypeTag<ByteArray>)
|
||||
{
|
||||
instance.PushString(reinterpret_cast<const char*>(val.GetConstBuffer()), val.GetSize());
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& instance, String&& val, TypeTag<String>)
|
||||
{
|
||||
instance.PushString(std::move(val));
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
int LuaImplReplyVal(const LuaState& instance, std::pair<T1, T2>&& val, TypeTag<std::pair<T1, T2>>)
|
||||
{
|
||||
int retVal = 0;
|
||||
|
||||
retVal += LuaImplReplyVal(instance, std::move(val.first), TypeTag<T1>());
|
||||
retVal += LuaImplReplyVal(instance, std::move(val.second), TypeTag<T2>());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template<bool HasDefault>
|
||||
struct LuaImplArgProcesser;
|
||||
|
||||
template<>
|
||||
struct LuaImplArgProcesser<true>
|
||||
{
|
||||
template<std::size_t N, std::size_t FirstDefArg, typename ArgType, typename ArgContainer, typename DefArgContainer>
|
||||
static unsigned int Process(const LuaState& instance, unsigned int argIndex, ArgContainer& args, DefArgContainer& defArgs)
|
||||
{
|
||||
return LuaImplQueryArg(instance, argIndex, &std::get<N>(args), std::get<FirstDefArg + std::tuple_size<DefArgContainer>() - N - 1>(defArgs), TypeTag<ArgType>());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct LuaImplArgProcesser<false>
|
||||
{
|
||||
template<std::size_t N, std::size_t FirstDefArg, typename ArgType, typename ArgContainer, typename DefArgContainer>
|
||||
static unsigned int Process(const LuaState& instance, unsigned int argIndex, ArgContainer& args, DefArgContainer& defArgs)
|
||||
{
|
||||
NazaraUnused(defArgs);
|
||||
|
||||
return LuaImplQueryArg(instance, argIndex, &std::get<N>(args), TypeTag<ArgType>());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
class LuaImplFunctionProxy
|
||||
{
|
||||
public:
|
||||
template<typename... DefArgs>
|
||||
class Impl
|
||||
{
|
||||
static constexpr std::size_t ArgCount = sizeof...(Args);
|
||||
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
|
||||
|
||||
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
|
||||
|
||||
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
|
||||
|
||||
public:
|
||||
Impl(DefArgs... defArgs) :
|
||||
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
|
||||
{
|
||||
}
|
||||
|
||||
void ProcessArguments(const LuaState& instance) const
|
||||
{
|
||||
m_index = 1;
|
||||
ProcessArgs<0, Args...>(instance);
|
||||
}
|
||||
|
||||
int Invoke(const LuaState& instance, void(*func)(Args...)) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
Apply(func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Ret>
|
||||
int Invoke(const LuaState& instance, Ret(*func)(Args...)) const
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(Apply(func, m_args)), TypeTag<decltype(Apply(func, m_args))>());
|
||||
}
|
||||
|
||||
private:
|
||||
using ArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
|
||||
using DefArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<DefArgs>>...>;
|
||||
|
||||
template<std::size_t N>
|
||||
void ProcessArgs(const LuaState& instance) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
// No argument to process
|
||||
}
|
||||
|
||||
template<std::size_t N, typename ArgType>
|
||||
void ProcessArgs(const LuaState& instance) const
|
||||
{
|
||||
LuaImplArgProcesser<(N >= FirstDefArg)>::template Process<N, FirstDefArg, ArgType>(instance, m_index, m_args, m_defaultArgs);
|
||||
}
|
||||
|
||||
template<std::size_t N, typename ArgType1, typename ArgType2, typename... Rest>
|
||||
void ProcessArgs(const LuaState& instance) const
|
||||
{
|
||||
ProcessArgs<N, ArgType1>(instance);
|
||||
ProcessArgs<N + 1, ArgType2, Rest...>(instance);
|
||||
}
|
||||
|
||||
mutable ArgContainer m_args;
|
||||
DefArgContainer m_defaultArgs;
|
||||
mutable unsigned int m_index;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
class LuaImplMethodProxy
|
||||
{
|
||||
public:
|
||||
template<typename... DefArgs>
|
||||
class Impl
|
||||
{
|
||||
static constexpr std::size_t ArgCount = sizeof...(Args);
|
||||
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
|
||||
|
||||
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
|
||||
|
||||
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
|
||||
|
||||
public:
|
||||
Impl(DefArgs... defArgs) :
|
||||
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
|
||||
{
|
||||
}
|
||||
|
||||
void ProcessArguments(const LuaState& instance) const
|
||||
{
|
||||
m_index = 2; //< 1 being the instance
|
||||
ProcessArgs<0, Args...>(instance);
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, T& object, void(P::*func)(Args...)) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
Apply(object, func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename P, typename Ret>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, T& object, Ret(P::*func)(Args...)) const
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(Apply(object, func, m_args)), TypeTag<decltype(Apply(object, func, m_args))>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, T& object, T&(P::*func)(Args...)) const
|
||||
{
|
||||
T& r = Apply(object, func, m_args);
|
||||
if (&r == &object)
|
||||
{
|
||||
instance.PushValue(1); //< Userdata
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return LuaImplReplyVal(instance, r, TypeTag<T&>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, const T& object, void(P::*func)(Args...) const) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
Apply(object, func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename P, typename Ret>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, const T& object, Ret(P::*func)(Args...) const) const
|
||||
{
|
||||
return LuaImplReplyVal(instance, std::move(Apply(object, func, m_args)), TypeTag<decltype(Apply(object, func, m_args))>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(const LuaState& instance, const T& object, const T&(P::*func)(Args...) const) const
|
||||
{
|
||||
const T& r = Apply(object, func, m_args);
|
||||
if (&r == &object)
|
||||
{
|
||||
instance.PushValue(1); //< Userdata
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return LuaImplReplyVal(instance, r, TypeTag<T&>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, T& object, void(P::*func)(Args...)) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Apply(*object, func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename P, typename Ret>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, T& object, Ret(P::*func)(Args...)) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return LuaImplReplyVal(instance, std::move(Apply(*object, func, m_args)), TypeTag<decltype(Apply(*object, func, m_args))>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, T& object, typename PointedType<T>::type&(P::*func)(Args...) const) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const typename PointedType<T>::type& r = Apply(*object, func, m_args);
|
||||
if (&r == &*object)
|
||||
{
|
||||
instance.PushValue(1); //< Userdata
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return LuaImplReplyVal(instance, r, TypeTag<T&>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, const T& object, void(P::*func)(Args...) const) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Apply(*object, func, m_args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename P, typename Ret>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, const T& object, Ret(P::*func)(Args...) const) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return LuaImplReplyVal(instance, std::move(Apply(*object, func, m_args)), TypeTag<decltype(Apply(*object, func, m_args))>());
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value, int> Invoke(const LuaState& instance, const T& object, const typename PointedType<T>::type&(P::*func)(Args...) const) const
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
instance.Error("Invalid object");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const typename PointedType<T>::type& r = Apply(*object, func, m_args);
|
||||
if (&r == &*object)
|
||||
{
|
||||
instance.PushValue(1); //< Userdata
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return LuaImplReplyVal(instance, r, TypeTag<T&>());
|
||||
}
|
||||
|
||||
private:
|
||||
using ArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
|
||||
using DefArgContainer = std::tuple<std::remove_cv_t<std::remove_reference_t<DefArgs>>...>;
|
||||
|
||||
template<std::size_t N>
|
||||
void ProcessArgs(const LuaState& instance) const
|
||||
{
|
||||
NazaraUnused(instance);
|
||||
|
||||
// No argument to process
|
||||
}
|
||||
|
||||
template<std::size_t N, typename ArgType>
|
||||
void ProcessArgs(const LuaState& instance) const
|
||||
{
|
||||
m_index += LuaImplArgProcesser<(N >= FirstDefArg)>::template Process<N, FirstDefArg, ArgType>(instance, m_index, m_args, m_defaultArgs);
|
||||
}
|
||||
|
||||
template<std::size_t N, typename ArgType1, typename ArgType2, typename... Rest>
|
||||
void ProcessArgs(const LuaState& instance) const
|
||||
{
|
||||
ProcessArgs<N, ArgType1>(instance);
|
||||
ProcessArgs<N + 1, ArgType2, Rest...>(instance);
|
||||
}
|
||||
|
||||
mutable ArgContainer m_args;
|
||||
DefArgContainer m_defaultArgs;
|
||||
mutable unsigned int m_index;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T LuaState::Check(int* index) const
|
||||
{
|
||||
NazaraAssert(index, "Invalid index pointer");
|
||||
|
||||
T object;
|
||||
*index += LuaImplQueryArg(*this, *index, &object, TypeTag<T>());
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::Check(int* index, T defValue) const
|
||||
{
|
||||
NazaraAssert(index, "Invalid index pointer");
|
||||
|
||||
T object;
|
||||
*index += LuaImplQueryArg(*this, *index, &object, defValue, TypeTag<T>());
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T LuaState::CheckBoundInteger(int index) const
|
||||
{
|
||||
return CheckBounds<T>(index, CheckInteger(index));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T LuaState::CheckBoundInteger(int index, T defValue) const
|
||||
{
|
||||
return CheckBounds<T>(index, CheckInteger(index, defValue));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::CheckField(const char* fieldName, int tableIndex) const
|
||||
{
|
||||
T object;
|
||||
|
||||
GetField(fieldName, tableIndex);
|
||||
tableIndex += LuaImplQueryArg(*this, -1, &object, TypeTag<T>());
|
||||
Pop();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::CheckField(const String& fieldName, int tableIndex) const
|
||||
{
|
||||
return CheckField<T>(fieldName.GetConstBuffer(), tableIndex);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::CheckField(const char* fieldName, T defValue, int tableIndex) const
|
||||
{
|
||||
T object;
|
||||
|
||||
GetField(fieldName, tableIndex);
|
||||
tableIndex += LuaImplQueryArg(*this, -1, &object, defValue, TypeTag<T>());
|
||||
Pop();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::CheckField(const String& fieldName, T defValue, int tableIndex) const
|
||||
{
|
||||
return CheckField<T>(fieldName.GetConstBuffer(), defValue, tableIndex);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::CheckGlobal(const char* fieldName) const
|
||||
{
|
||||
T object;
|
||||
|
||||
GetGlobal(fieldName);
|
||||
LuaImplQueryArg(*this, -1, &object, TypeTag<T>());
|
||||
Pop();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::CheckGlobal(const String& fieldName) const
|
||||
{
|
||||
return CheckGlobal<T>(fieldName.GetConstBuffer());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::CheckGlobal(const char* fieldName, T defValue) const
|
||||
{
|
||||
T object;
|
||||
|
||||
GetGlobal(fieldName);
|
||||
LuaImplQueryArg(*this, -1, &object, defValue, TypeTag<T>());
|
||||
Pop();
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::CheckGlobal(const String& fieldName, T defValue) const
|
||||
{
|
||||
return CheckGlobal<T>(fieldName.GetConstBuffer(), defValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int LuaState::Push(T arg) const
|
||||
{
|
||||
return LuaImplReplyVal(*this, std::move(arg), TypeTag<T>());
|
||||
}
|
||||
|
||||
template<typename T, typename T2, typename... Args>
|
||||
int LuaState::Push(T firstArg, T2 secondArg, Args... args) const
|
||||
{
|
||||
int valCount = 0;
|
||||
valCount += Push(std::move(firstArg));
|
||||
valCount += Push(secondArg, std::forward<Args>(args)...);
|
||||
|
||||
return valCount;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaState::PushField(const char* name, T&& arg, int tableIndex) const
|
||||
{
|
||||
Push<T>(std::forward<T>(arg));
|
||||
SetField(name, tableIndex);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaState::PushField(const String& name, T&& arg, int tableIndex) const
|
||||
{
|
||||
PushField(name.GetConstBuffer(), std::forward<T>(arg), tableIndex);
|
||||
}
|
||||
|
||||
template<typename R, typename... Args, typename... DefArgs>
|
||||
void LuaState::PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const
|
||||
{
|
||||
typename LuaImplFunctionProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
|
||||
|
||||
PushFunction([func, handler] (LuaState& lua) -> int
|
||||
{
|
||||
handler.ProcessArguments(lua);
|
||||
|
||||
return handler.Invoke(lua, func);
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaState::PushGlobal(const char* name, T&& arg)
|
||||
{
|
||||
Push<T>(std::forward<T>(arg));
|
||||
SetGlobal(name);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaState::PushGlobal(const String& name, T&& arg)
|
||||
{
|
||||
PushGlobal(name.GetConstBuffer(), std::forward<T>(arg));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaState::PushInstance(const char* tname, const T& instance) const
|
||||
{
|
||||
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
|
||||
PlacementNew(userdata, instance);
|
||||
|
||||
SetMetatable(tname);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void LuaState::PushInstance(const char* tname, T&& instance) const
|
||||
{
|
||||
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
|
||||
PlacementNew(userdata, std::move(instance));
|
||||
|
||||
SetMetatable(tname);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void LuaState::PushInstance(const char* tname, Args&&... args) const
|
||||
{
|
||||
T* userdata = static_cast<T*>(PushUserdata(sizeof(T)));
|
||||
PlacementNew(userdata, std::forward<Args>(args)...);
|
||||
|
||||
SetMetatable(tname);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T LuaState::CheckBounds(int index, long long value) const
|
||||
{
|
||||
constexpr long long minBounds = std::numeric_limits<T>::min();
|
||||
constexpr long long maxBounds = std::numeric_limits<T>::max();
|
||||
if (value < minBounds || value > maxBounds)
|
||||
{
|
||||
Nz::StringStream stream;
|
||||
stream << "Argument #" << index << " is outside value range [" << minBounds << ", " << maxBounds << "] (" << value << ')';
|
||||
Error(stream);
|
||||
}
|
||||
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
|
||||
inline LuaState LuaState::GetState(lua_State* internalState)
|
||||
{
|
||||
return LuaState(internalState);
|
||||
}
|
||||
}
|
||||
@@ -133,9 +133,9 @@ namespace Nz
|
||||
template<typename T>
|
||||
bool Box<T>::Contains(T X, T Y, T Z) const
|
||||
{
|
||||
return X >= x && X <= x + width &&
|
||||
Y >= y && Y <= y + height &&
|
||||
Z >= z && Z <= z + depth;
|
||||
return X >= x && X < x + width &&
|
||||
Y >= y && Y < y + height &&
|
||||
Z >= z && Z < z + depth;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -117,8 +117,8 @@ namespace Nz
|
||||
template<typename T>
|
||||
bool Rect<T>::Contains(T X, T Y) const
|
||||
{
|
||||
return X >= x && X <= (x + width) &&
|
||||
Y >= y && Y <= (y + height);
|
||||
return X >= x && X < (x + width) &&
|
||||
Y >= y && Y < (y + height);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <Nazara/Network/Config.hpp>
|
||||
#include <Nazara/Network/Enums.hpp>
|
||||
#include <Nazara/Network/IpAddress.hpp>
|
||||
#include <Nazara/Network/NetBuffer.hpp>
|
||||
#include <Nazara/Network/NetPacket.hpp>
|
||||
#include <Nazara/Network/Network.hpp>
|
||||
#include <Nazara/Network/RUdpConnection.hpp>
|
||||
|
||||
@@ -9,12 +9,23 @@
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Network/Config.hpp>
|
||||
#include <Nazara/Network/Enums.hpp>
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
NAZARA_NETWORK_API const char* ErrorToString(Nz::ResolveError resolveError);
|
||||
NAZARA_NETWORK_API const char* ErrorToString(Nz::SocketError socketError);
|
||||
|
||||
NAZARA_NETWORK_API bool ParseIPAddress(const char* addressPtr, UInt8 result[16], UInt16* port = nullptr, bool* isIPv6 = nullptr, const char** endOfRead = nullptr);
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, T> HostToNet(T value);
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, T> NetToHost(T value);
|
||||
}
|
||||
|
||||
#include <Nazara/Network/Algorithm.inl>
|
||||
|
||||
@@ -2,6 +2,31 @@
|
||||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Network/Algorithm.hpp>
|
||||
#include <Nazara/Core/Endianness.hpp>
|
||||
#include <Nazara/Network/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, T> HostToNet(T value)
|
||||
{
|
||||
#ifdef NAZARA_LITTLE_ENDIAN
|
||||
return SwapBytes(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, T> NetToHost(T value)
|
||||
{
|
||||
#ifdef NAZARA_LITTLE_ENDIAN
|
||||
return SwapBytes(value);
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Network/DebugOff.hpp>
|
||||
|
||||
166
include/Nazara/Network/ENetHost.hpp
Normal file
166
include/Nazara/Network/ENetHost.hpp
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
Copyright(c) 2002 - 2016 Lee Salzman
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Copyright (C) 2017 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_ENETHOST_HPP
|
||||
#define NAZARA_ENETHOST_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Bitset.hpp>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Core/MemoryPool.hpp>
|
||||
#include <Nazara/Network/ENetPeer.hpp>
|
||||
#include <Nazara/Network/ENetProtocol.hpp>
|
||||
#include <Nazara/Network/IpAddress.hpp>
|
||||
#include <Nazara/Network/NetBuffer.hpp>
|
||||
#include <Nazara/Network/NetPacket.hpp>
|
||||
#include <Nazara/Network/SocketPoller.hpp>
|
||||
#include <Nazara/Network/UdpSocket.hpp>
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
#include <random>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_NETWORK_API ENetHost
|
||||
{
|
||||
friend ENetPeer;
|
||||
friend class Network;
|
||||
|
||||
public:
|
||||
inline ENetHost();
|
||||
ENetHost(const ENetHost&) = delete;
|
||||
ENetHost(ENetHost&&) = default;
|
||||
inline ~ENetHost();
|
||||
|
||||
void Broadcast(UInt8 channelId, ENetPacketFlags flags, NetPacket&& packet);
|
||||
|
||||
bool CheckEvents(ENetEvent* event);
|
||||
|
||||
ENetPeer* Connect(const IpAddress& remoteAddress, std::size_t channelCount = 0, UInt32 data = 0);
|
||||
ENetPeer* Connect(const String& hostName, NetProtocol protocol = NetProtocol_Any, const String& service = "http", ResolveError* error = nullptr, std::size_t channelCount = 0, UInt32 data = 0);
|
||||
|
||||
inline bool Create(NetProtocol protocol, UInt16 port, std::size_t peerCount, std::size_t channelCount = 0);
|
||||
bool Create(const IpAddress& address, std::size_t peerCount, std::size_t channelCount = 0);
|
||||
bool Create(const IpAddress& address, std::size_t peerCount, std::size_t channelCount, UInt32 incomingBandwidth, UInt32 outgoingBandwidth);
|
||||
void Destroy();
|
||||
|
||||
void Flush();
|
||||
|
||||
inline Nz::IpAddress GetBoundAddress() const;
|
||||
inline UInt32 GetServiceTime() const;
|
||||
|
||||
int Service(ENetEvent* event, UInt32 timeout);
|
||||
|
||||
void SimulateNetwork(double packetLossProbability, UInt16 minDelay, UInt16 maxDelay);
|
||||
|
||||
ENetHost& operator=(const ENetHost&) = delete;
|
||||
ENetHost& operator=(ENetHost&&) = default;
|
||||
|
||||
private:
|
||||
ENetPacketRef AllocatePacket(ENetPacketFlags flags);
|
||||
inline ENetPacketRef AllocatePacket(ENetPacketFlags flags, NetPacket&& data);
|
||||
|
||||
bool InitSocket(const IpAddress& address);
|
||||
|
||||
void AddToDispatchQueue(ENetPeer* peer);
|
||||
void RemoveFromDispatchQueue(ENetPeer* peer);
|
||||
|
||||
bool DispatchIncomingCommands(ENetEvent* event);
|
||||
|
||||
ENetPeer* HandleConnect(ENetProtocolHeader* header, ENetProtocol* command);
|
||||
bool HandleIncomingCommands(ENetEvent* event);
|
||||
|
||||
int ReceiveIncomingCommands(ENetEvent* event);
|
||||
|
||||
void NotifyConnect(ENetPeer* peer, ENetEvent* event, bool incoming);
|
||||
void NotifyDisconnect(ENetPeer*, ENetEvent* event);
|
||||
|
||||
void SendAcknowledgements(ENetPeer* peer);
|
||||
bool SendReliableOutgoingCommands(ENetPeer* peer);
|
||||
int SendOutgoingCommands(ENetEvent* event, bool checkForTimeouts);
|
||||
void SendUnreliableOutgoingCommands(ENetPeer* peer);
|
||||
|
||||
void ThrottleBandwidth();
|
||||
|
||||
static std::size_t GetCommandSize(UInt8 commandNumber);
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
||||
struct PendingIncomingPacket
|
||||
{
|
||||
IpAddress from;
|
||||
NetPacket data;
|
||||
UInt32 deliveryTime;
|
||||
};
|
||||
|
||||
struct PendingOutgoingPacket
|
||||
{
|
||||
IpAddress to;
|
||||
NetPacket data;
|
||||
UInt32 deliveryTime;
|
||||
};
|
||||
|
||||
std::array<ENetProtocol, ENetConstants::ENetProtocol_MaximumPacketCommands> m_commands;
|
||||
std::array<NetBuffer, ENetConstants::ENetProtocol_MaximumPacketCommands * 2 + 1> m_buffers;
|
||||
std::array<UInt8, ENetConstants::ENetProtocol_MaximumMTU> m_packetData[2];
|
||||
std::bernoulli_distribution m_packetLossProbability;
|
||||
std::size_t m_bandwidthLimitedPeers;
|
||||
std::size_t m_bufferCount;
|
||||
std::size_t m_channelLimit;
|
||||
std::size_t m_commandCount;
|
||||
std::size_t m_duplicatePeers;
|
||||
std::size_t m_maximumPacketSize;
|
||||
std::size_t m_maximumWaitingData;
|
||||
std::size_t m_packetSize;
|
||||
std::size_t m_peerCount;
|
||||
std::size_t m_receivedDataLength;
|
||||
std::uniform_int_distribution<UInt16> m_packetDelayDistribution;
|
||||
std::vector<ENetPeer> m_peers;
|
||||
std::vector<PendingIncomingPacket> m_pendingIncomingPackets;
|
||||
std::vector<PendingOutgoingPacket> m_pendingOutgoingPackets;
|
||||
UInt8* m_receivedData;
|
||||
Bitset<UInt64> m_dispatchQueue;
|
||||
MemoryPool m_packetPool;
|
||||
IpAddress m_address;
|
||||
IpAddress m_receivedAddress;
|
||||
SocketPoller m_poller;
|
||||
UdpSocket m_socket;
|
||||
UInt16 m_headerFlags;
|
||||
UInt32 m_bandwidthThrottleEpoch;
|
||||
UInt32 m_connectedPeers;
|
||||
UInt32 m_mtu;
|
||||
UInt32 m_randomSeed;
|
||||
UInt32 m_incomingBandwidth;
|
||||
UInt32 m_outgoingBandwidth;
|
||||
UInt32 m_serviceTime;
|
||||
UInt32 m_totalSentPackets;
|
||||
UInt32 m_totalReceivedPackets;
|
||||
UInt64 m_totalSentData;
|
||||
UInt64 m_totalReceivedData;
|
||||
bool m_continueSending;
|
||||
bool m_isSimulationEnabled;
|
||||
bool m_recalculateBandwidthLimits;
|
||||
|
||||
static std::mt19937 s_randomGenerator;
|
||||
static std::mt19937_64 s_randomGenerator64;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Network/ENetHost.inl>
|
||||
|
||||
#endif // NAZARA_ENETHOST_HPP
|
||||
74
include/Nazara/Network/ENetHost.inl
Normal file
74
include/Nazara/Network/ENetHost.inl
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2017 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 <Nazara/Network/ENetHost.hpp>
|
||||
#include <utility>
|
||||
#include <Nazara/Network/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline ENetHost::ENetHost() :
|
||||
m_packetPool(sizeof(ENetPacket)),
|
||||
m_isSimulationEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
inline ENetHost::~ENetHost()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
inline bool ENetHost::Create(NetProtocol protocol, UInt16 port, std::size_t peerCount, std::size_t channelCount)
|
||||
{
|
||||
NazaraAssert(protocol != NetProtocol_Any, "Any protocol not supported for Listen"); //< TODO
|
||||
NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");
|
||||
|
||||
IpAddress any;
|
||||
switch (protocol)
|
||||
{
|
||||
case NetProtocol_Any:
|
||||
case NetProtocol_Unknown:
|
||||
NazaraInternalError("Invalid protocol Any at this point");
|
||||
return false;
|
||||
|
||||
case NetProtocol_IPv4:
|
||||
any = IpAddress::AnyIpV4;
|
||||
break;
|
||||
|
||||
case NetProtocol_IPv6:
|
||||
any = IpAddress::AnyIpV6;
|
||||
break;
|
||||
}
|
||||
|
||||
any.SetPort(port);
|
||||
return Create(any, peerCount, channelCount);
|
||||
}
|
||||
|
||||
inline void ENetHost::Destroy()
|
||||
{
|
||||
m_poller.Clear();
|
||||
m_peers.clear();
|
||||
m_socket.Close();
|
||||
}
|
||||
|
||||
inline Nz::IpAddress ENetHost::GetBoundAddress() const
|
||||
{
|
||||
return m_address;
|
||||
}
|
||||
|
||||
inline UInt32 Nz::ENetHost::GetServiceTime() const
|
||||
{
|
||||
return m_serviceTime;
|
||||
}
|
||||
|
||||
inline ENetPacketRef ENetHost::AllocatePacket(ENetPacketFlags flags, NetPacket&& data)
|
||||
{
|
||||
ENetPacketRef ref = AllocatePacket(flags);
|
||||
ref->data = std::move(data);
|
||||
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Network/DebugOff.hpp>
|
||||
107
include/Nazara/Network/ENetPacket.hpp
Normal file
107
include/Nazara/Network/ENetPacket.hpp
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright (C) 2017 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_ENETPACKET_HPP
|
||||
#define NAZARA_ENETPACKET_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Network/NetPacket.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
enum ENetPacketFlag
|
||||
{
|
||||
ENetPacketFlag_Reliable,
|
||||
ENetPacketFlag_Unsequenced,
|
||||
ENetPacketFlag_UnreliableFragment
|
||||
};
|
||||
|
||||
template<>
|
||||
struct EnumAsFlags<ENetPacketFlag>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
static constexpr int max = ENetPacketFlag_UnreliableFragment;
|
||||
};
|
||||
|
||||
using ENetPacketFlags = Flags<ENetPacketFlag>;
|
||||
|
||||
constexpr ENetPacketFlags ENetPacketFlag_Unreliable = 0;
|
||||
|
||||
class MemoryPool;
|
||||
|
||||
struct ENetPacket
|
||||
{
|
||||
MemoryPool* owner;
|
||||
ENetPacketFlags flags;
|
||||
NetPacket data;
|
||||
std::size_t referenceCount = 0;
|
||||
};
|
||||
|
||||
struct NAZARA_NETWORK_API ENetPacketRef
|
||||
{
|
||||
ENetPacketRef() = default;
|
||||
|
||||
ENetPacketRef(ENetPacket* packet)
|
||||
{
|
||||
Reset(packet);
|
||||
}
|
||||
|
||||
ENetPacketRef(const ENetPacketRef& packet) :
|
||||
ENetPacketRef()
|
||||
{
|
||||
Reset(packet);
|
||||
}
|
||||
|
||||
ENetPacketRef(ENetPacketRef&& packet) :
|
||||
m_packet(packet.m_packet)
|
||||
{
|
||||
packet.m_packet = nullptr;
|
||||
}
|
||||
|
||||
~ENetPacketRef()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset(ENetPacket* packet = nullptr);
|
||||
|
||||
operator ENetPacket*() const
|
||||
{
|
||||
return m_packet;
|
||||
}
|
||||
|
||||
ENetPacket* operator->() const
|
||||
{
|
||||
return m_packet;
|
||||
}
|
||||
|
||||
ENetPacketRef& operator=(ENetPacket* packet)
|
||||
{
|
||||
Reset(packet);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ENetPacketRef& operator=(const ENetPacketRef& packet)
|
||||
{
|
||||
Reset(packet);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ENetPacketRef& operator=(ENetPacketRef&& packet)
|
||||
{
|
||||
m_packet = packet.m_packet;
|
||||
packet.m_packet = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ENetPacket* m_packet = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_ENETPACKET_HPP
|
||||
248
include/Nazara/Network/ENetPeer.hpp
Normal file
248
include/Nazara/Network/ENetPeer.hpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
Copyright(c) 2002 - 2016 Lee Salzman
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Copyright (C) 2017 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_ENETPEER_HPP
|
||||
#define NAZARA_ENETPEER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Bitset.hpp>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Network/ENetPacket.hpp>
|
||||
#include <Nazara/Network/ENetProtocol.hpp>
|
||||
#include <Nazara/Network/IpAddress.hpp>
|
||||
#include <Nazara/Network/NetPacket.hpp>
|
||||
#include <Nazara/Network/UdpSocket.hpp>
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class ENetHost;
|
||||
|
||||
class NAZARA_NETWORK_API ENetPeer
|
||||
{
|
||||
friend ENetHost;
|
||||
friend struct PacketRef;
|
||||
|
||||
public:
|
||||
inline ENetPeer(ENetHost* host, UInt16 peerId);
|
||||
ENetPeer(const ENetPeer&) = delete;
|
||||
ENetPeer(ENetPeer&&) = default;
|
||||
~ENetPeer() = default;
|
||||
|
||||
void Disconnect(UInt32 data);
|
||||
void DisconnectLater(UInt32 data);
|
||||
void DisconnectNow(UInt32 data);
|
||||
|
||||
inline const IpAddress& GetAddress() const;
|
||||
inline UInt32 GetMtu() const;
|
||||
inline UInt32 GetPacketThrottleAcceleration() const;
|
||||
inline UInt32 GetPacketThrottleDeceleration() const;
|
||||
inline UInt32 GetPacketThrottleInterval() const;
|
||||
inline UInt16 GetPeerId() const;
|
||||
inline UInt32 GetRoundTripTime() const;
|
||||
inline ENetPeerState GetState() const;
|
||||
|
||||
inline bool HasPendingCommands();
|
||||
|
||||
inline bool IsConnected() const;
|
||||
inline bool IsSimulationEnabled() const;
|
||||
|
||||
void Ping();
|
||||
|
||||
bool Receive(ENetPacketRef* packet, UInt8* channelId);
|
||||
void Reset();
|
||||
|
||||
bool Send(UInt8 channelId, ENetPacketRef packetRef);
|
||||
bool Send(UInt8 channelId, ENetPacketFlags flags, NetPacket&& packet);
|
||||
|
||||
void SimulateNetwork(double packetLossProbability, UInt16 minDelay, UInt16 maxDelay);
|
||||
|
||||
void ThrottleConfigure(UInt32 interval, UInt32 acceleration, UInt32 deceleration);
|
||||
|
||||
ENetPeer& operator=(const ENetPeer&) = delete;
|
||||
ENetPeer& operator=(ENetPeer&&) = default;
|
||||
|
||||
private:
|
||||
void InitIncoming(std::size_t channelCount, const IpAddress& address, ENetProtocolConnect& incomingCommand);
|
||||
void InitOutgoing(std::size_t channelCount, const IpAddress& address, UInt32 connectId, UInt32 windowSize);
|
||||
|
||||
struct Acknowledgement;
|
||||
struct Channel;
|
||||
struct IncomingCommmand;
|
||||
struct OutgoingCommand;
|
||||
|
||||
inline void ChangeState(ENetPeerState state);
|
||||
|
||||
bool CheckTimeouts(ENetEvent* event);
|
||||
|
||||
void DispatchState(ENetPeerState state);
|
||||
|
||||
void DispatchIncomingReliableCommands(Channel& channel);
|
||||
void DispatchIncomingUnreliableCommands(Channel& channel);
|
||||
|
||||
bool HandleAcknowledge(const ENetProtocol* command, ENetEvent* event);
|
||||
bool HandleBandwidthLimit(const ENetProtocol* command);
|
||||
bool HandleDisconnect(const ENetProtocol* command);
|
||||
bool HandlePing(const ENetProtocol* command);
|
||||
bool HandleSendFragment(const ENetProtocol* command, UInt8** data);
|
||||
bool HandleSendReliable(const ENetProtocol* command, UInt8** data);
|
||||
bool HandleSendUnreliable(const ENetProtocol* command, UInt8** data);
|
||||
bool HandleSendUnreliableFragment(const ENetProtocol* command, UInt8** data);
|
||||
bool HandleSendUnsequenced(const ENetProtocol* command, UInt8** data);
|
||||
bool HandleThrottleConfigure(const ENetProtocol* command);
|
||||
bool HandleVerifyConnect(const ENetProtocol* command, ENetEvent* event);
|
||||
|
||||
void OnConnect();
|
||||
void OnDisconnect();
|
||||
|
||||
ENetProtocolCommand RemoveSentReliableCommand(UInt16 reliableSequenceNumber, UInt8 channelId);
|
||||
void RemoveSentUnreliableCommands();
|
||||
|
||||
void ResetQueues();
|
||||
|
||||
bool QueueAcknowledgement(ENetProtocol* command, UInt16 sentTime);
|
||||
IncomingCommmand* QueueIncomingCommand(const ENetProtocol& command, const void* data, std::size_t dataLength, UInt32 flags, UInt32 fragmentCount);
|
||||
inline void QueueOutgoingCommand(ENetProtocol& command);
|
||||
void QueueOutgoingCommand(ENetProtocol& command, ENetPacketRef packet, UInt32 offset, UInt16 length);
|
||||
|
||||
void SetupOutgoingCommand(OutgoingCommand& outgoingCommand);
|
||||
|
||||
int Throttle(UInt32 rtt);
|
||||
|
||||
struct Acknowledgement
|
||||
{
|
||||
ENetProtocol command;
|
||||
UInt32 sentTime;
|
||||
};
|
||||
|
||||
struct Channel
|
||||
{
|
||||
Channel()
|
||||
{
|
||||
incomingReliableSequenceNumber = 0;
|
||||
incomingUnreliableSequenceNumber = 0;
|
||||
outgoingReliableSequenceNumber = 0;
|
||||
outgoingUnreliableSequenceNumber = 0;
|
||||
usedReliableWindows = 0;
|
||||
reliableWindows.fill(0);
|
||||
}
|
||||
|
||||
std::array<UInt16, ENetPeer_ReliableWindows> reliableWindows;
|
||||
std::list<IncomingCommmand> incomingReliableCommands;
|
||||
std::list<IncomingCommmand> incomingUnreliableCommands;
|
||||
UInt16 incomingReliableSequenceNumber;
|
||||
UInt16 incomingUnreliableSequenceNumber;
|
||||
UInt16 outgoingReliableSequenceNumber;
|
||||
UInt16 outgoingUnreliableSequenceNumber;
|
||||
UInt16 usedReliableWindows;
|
||||
};
|
||||
|
||||
struct IncomingCommmand
|
||||
{
|
||||
ENetProtocol command;
|
||||
Bitset<> fragments;
|
||||
ENetPacketRef packet;
|
||||
UInt16 reliableSequenceNumber;
|
||||
UInt16 unreliableSequenceNumber;
|
||||
UInt32 fragmentsRemaining;
|
||||
};
|
||||
|
||||
struct OutgoingCommand
|
||||
{
|
||||
ENetProtocol command;
|
||||
ENetPacketRef packet;
|
||||
UInt16 fragmentLength;
|
||||
UInt16 reliableSequenceNumber;
|
||||
UInt16 sendAttempts;
|
||||
UInt16 unreliableSequenceNumber;
|
||||
UInt32 fragmentOffset;
|
||||
UInt32 roundTripTimeout;
|
||||
UInt32 roundTripTimeoutLimit;
|
||||
UInt32 sentTime;
|
||||
};
|
||||
|
||||
static constexpr std::size_t unsequencedWindow = ENetPeer_ReliableWindowSize / 32;
|
||||
|
||||
ENetHost* m_host;
|
||||
IpAddress m_address; /**< Internet address of the peer */
|
||||
std::array<UInt32, unsequencedWindow> m_unsequencedWindow;
|
||||
std::bernoulli_distribution m_packetLossProbability;
|
||||
std::list<IncomingCommmand> m_dispatchedCommands;
|
||||
std::list<OutgoingCommand> m_outgoingReliableCommands;
|
||||
std::list<OutgoingCommand> m_outgoingUnreliableCommands;
|
||||
std::list<OutgoingCommand> m_sentReliableCommands;
|
||||
std::list<OutgoingCommand> m_sentUnreliableCommands;
|
||||
std::size_t m_totalWaitingData;
|
||||
std::uniform_int_distribution<UInt16> m_packetDelayDistribution;
|
||||
std::vector<Acknowledgement> m_acknowledgements;
|
||||
std::vector<Channel> m_channels;
|
||||
ENetPeerState m_state;
|
||||
UInt8 m_incomingSessionID;
|
||||
UInt8 m_outgoingSessionID;
|
||||
UInt16 m_incomingPeerID;
|
||||
UInt16 m_incomingUnsequencedGroup;
|
||||
UInt16 m_outgoingPeerID;
|
||||
UInt16 m_outgoingReliableSequenceNumber;
|
||||
UInt16 m_outgoingUnsequencedGroup;
|
||||
UInt32 m_connectID;
|
||||
UInt32 m_earliestTimeout;
|
||||
UInt32 m_eventData;
|
||||
UInt32 m_highestRoundTripTimeVariance;
|
||||
UInt32 m_incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */
|
||||
UInt32 m_incomingBandwidthThrottleEpoch;
|
||||
UInt32 m_incomingDataTotal;
|
||||
UInt32 m_lastReceiveTime;
|
||||
UInt32 m_lastRoundTripTime;
|
||||
UInt32 m_lastRoundTripTimeVariance;
|
||||
UInt32 m_lastSendTime;
|
||||
UInt32 m_lowestRoundTripTime;
|
||||
UInt32 m_mtu;
|
||||
UInt32 m_nextTimeout;
|
||||
UInt32 m_outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */
|
||||
UInt32 m_outgoingBandwidthThrottleEpoch;
|
||||
UInt32 m_outgoingDataTotal;
|
||||
UInt32 m_packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */
|
||||
UInt32 m_packetLossEpoch;
|
||||
UInt32 m_packetLossVariance;
|
||||
UInt32 m_packetThrottle;
|
||||
UInt32 m_packetThrottleAcceleration;
|
||||
UInt32 m_packetThrottleCounter;
|
||||
UInt32 m_packetThrottleDeceleration;
|
||||
UInt32 m_packetThrottleEpoch;
|
||||
UInt32 m_packetThrottleInterval;
|
||||
UInt32 m_packetThrottleLimit;
|
||||
UInt32 m_packetsLost;
|
||||
UInt32 m_packetsSent;
|
||||
UInt32 m_pingInterval;
|
||||
UInt32 m_reliableDataInTransit;
|
||||
UInt32 m_roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgment */
|
||||
UInt32 m_roundTripTimeVariance;
|
||||
UInt32 m_timeoutLimit;
|
||||
UInt32 m_timeoutMaximum;
|
||||
UInt32 m_timeoutMinimum;
|
||||
UInt32 m_windowSize;
|
||||
UInt64 m_totalPacketLost;
|
||||
UInt64 m_totalPacketSent;
|
||||
bool m_isSimulationEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Network/ENetPeer.inl>
|
||||
|
||||
#endif // NAZARA_ENETPEER_HPP
|
||||
92
include/Nazara/Network/ENetPeer.inl
Normal file
92
include/Nazara/Network/ENetPeer.inl
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2017 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 <Nazara/Network/ENetPeer.hpp>
|
||||
#include <utility>
|
||||
#include <Nazara/Network/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline ENetPeer::ENetPeer(ENetHost* host, UInt16 peerId) :
|
||||
m_host(host),
|
||||
m_incomingSessionID(0xFF),
|
||||
m_outgoingSessionID(0xFF),
|
||||
m_incomingPeerID(peerId),
|
||||
m_isSimulationEnabled(false)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
inline const IpAddress& ENetPeer::GetAddress() const
|
||||
{
|
||||
return m_address;
|
||||
}
|
||||
|
||||
inline UInt32 ENetPeer::GetMtu() const
|
||||
{
|
||||
return m_mtu;
|
||||
}
|
||||
|
||||
inline UInt32 ENetPeer::GetPacketThrottleAcceleration() const
|
||||
{
|
||||
return m_packetThrottleAcceleration;
|
||||
}
|
||||
|
||||
inline UInt32 ENetPeer::GetPacketThrottleDeceleration() const
|
||||
{
|
||||
return m_packetThrottleDeceleration;
|
||||
}
|
||||
|
||||
inline UInt32 ENetPeer::GetPacketThrottleInterval() const
|
||||
{
|
||||
return m_packetThrottleInterval;
|
||||
}
|
||||
|
||||
inline UInt16 ENetPeer::GetPeerId() const
|
||||
{
|
||||
return m_incomingPeerID;
|
||||
}
|
||||
|
||||
inline UInt32 ENetPeer::GetRoundTripTime() const
|
||||
{
|
||||
return m_roundTripTime;
|
||||
}
|
||||
|
||||
inline ENetPeerState ENetPeer::GetState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
inline bool ENetPeer::HasPendingCommands()
|
||||
{
|
||||
return m_outgoingReliableCommands.empty() && m_outgoingUnreliableCommands.empty() && m_sentReliableCommands.empty();
|
||||
}
|
||||
|
||||
inline bool ENetPeer::IsConnected() const
|
||||
{
|
||||
return m_state == ENetPeerState::Connected || m_state == ENetPeerState::DisconnectLater;
|
||||
}
|
||||
|
||||
inline bool ENetPeer::IsSimulationEnabled() const
|
||||
{
|
||||
return m_isSimulationEnabled;
|
||||
}
|
||||
|
||||
inline void ENetPeer::ChangeState(ENetPeerState state)
|
||||
{
|
||||
if (state == ENetPeerState::Connected || state == ENetPeerState::DisconnectLater)
|
||||
OnConnect();
|
||||
else
|
||||
OnDisconnect();
|
||||
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
inline void ENetPeer::QueueOutgoingCommand(ENetProtocol& command)
|
||||
{
|
||||
QueueOutgoingCommand(command, ENetPacketRef(), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Network/DebugOff.hpp>
|
||||
311
include/Nazara/Network/ENetProtocol.hpp
Normal file
311
include/Nazara/Network/ENetProtocol.hpp
Normal file
@@ -0,0 +1,311 @@
|
||||
// Copyright (C) 2017 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_ENETPROTOCOL_HPP
|
||||
#define NAZARA_ENETPROTOCOL_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Network/ENetPacket.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
constexpr UInt32 ENetTimeOverflow = 24 * 60 * 60 * 1000;
|
||||
|
||||
inline UInt32 ENetTimeDifference(UInt32 a, UInt32 b);
|
||||
inline bool ENetTimeLess(UInt32 a, UInt32 b);
|
||||
inline bool ENetTimeLessEqual(UInt32 a, UInt32 b);
|
||||
inline bool ENetTimeGreater(UInt32 a, UInt32 b);
|
||||
inline bool ENetTimeGreaterEqual(UInt32 a, UInt32 b);
|
||||
|
||||
class ENetPeer;
|
||||
|
||||
// Constants for the ENet implementation and protocol
|
||||
enum ENetConstants
|
||||
{
|
||||
ENetHost_BandwidthThrottleInterval = 1000,
|
||||
ENetHost_DefaultMaximumPacketSize = 32 * 1024 * 1024,
|
||||
ENetHost_DefaultMaximumWaitingData = 32 * 1024 * 1024,
|
||||
ENetHost_DefaultMTU = 1400,
|
||||
ENetHost_ReceiveBufferSize = 256 * 1024,
|
||||
ENetHost_SendBufferSize = 256 * 1024,
|
||||
|
||||
ENetPeer_DefaultPacketThrottle = 32,
|
||||
ENetPeer_DefaultRoundTripTime = 500,
|
||||
ENetPeer_FreeReliableWindows = 8,
|
||||
ENetPeer_FreeUnsequencedWindows = 32,
|
||||
ENetPeer_PacketLossInterval = 10000,
|
||||
ENetPeer_PacketLossScale = (1 << 16),
|
||||
ENetPeer_PacketThrottleAcceleration = 2,
|
||||
ENetPeer_PacketThrottleCounter = 7,
|
||||
ENetPeer_PacketThrottleDeceleration = 2,
|
||||
ENetPeer_PacketThrottleInterval = 5000,
|
||||
ENetPeer_PacketThrottleScale = 32,
|
||||
ENetPeer_PingInterval = 500,
|
||||
ENetPeer_ReliableWindows = 16,
|
||||
ENetPeer_ReliableWindowSize = 0x1000,
|
||||
ENetPeer_TimeoutLimit = 32,
|
||||
ENetPeer_TimeoutMaximum = 30000,
|
||||
ENetPeer_TimeoutMinimum = 5000,
|
||||
ENetPeer_UnsequencedWindows = 64,
|
||||
ENetPeer_UnsequencedWindowSize = 1024,
|
||||
ENetPeer_WindowSizeScale = 64 * 1024,
|
||||
|
||||
ENetProtocol_MaximumChannelCount = 255,
|
||||
ENetProtocol_MaximumFragmentCount = 1024 * 1024,
|
||||
ENetProtocol_MaximumMTU = 4096,
|
||||
ENetProtocol_MaximumPacketCommands = 32,
|
||||
ENetProtocol_MaximumPeerId = 0xFFF,
|
||||
ENetProtocol_MaximumWindowSize = 65536,
|
||||
ENetProtocol_MinimumChannelCount = 1,
|
||||
ENetProtocol_MinimumMTU = 576,
|
||||
ENetProtocol_MinimumWindowSize = 4096
|
||||
};
|
||||
|
||||
enum class ENetPeerState
|
||||
{
|
||||
AcknowledgingConnect = 2,
|
||||
AcknowledgingDisconnect = 8,
|
||||
Connecting = 1,
|
||||
ConnectionPending = 3,
|
||||
ConnectionSucceeded = 4,
|
||||
Connected = 5,
|
||||
Disconnected = 0,
|
||||
Disconnecting = 7,
|
||||
DisconnectLater = 6,
|
||||
Zombie = 9
|
||||
};
|
||||
|
||||
enum ENetProtocolCommand
|
||||
{
|
||||
// Keeping the values is important for compatibility with the native ENet protocol
|
||||
ENetProtocolCommand_Acknowledge = 1,
|
||||
ENetProtocolCommand_BandwidthLimit = 10,
|
||||
ENetProtocolCommand_Connect = 2,
|
||||
ENetProtocolCommand_Disconnect = 4,
|
||||
ENetProtocolCommand_None = 0,
|
||||
ENetProtocolCommand_Ping = 5,
|
||||
ENetProtocolCommand_SendFragment = 8,
|
||||
ENetProtocolCommand_SendReliable = 6,
|
||||
ENetProtocolCommand_SendUnreliable = 7,
|
||||
ENetProtocolCommand_SendUnreliableFragment = 12,
|
||||
ENetProtocolCommand_SendUnsequenced = 9,
|
||||
ENetProtocolCommand_ThrottleConfigure = 11,
|
||||
ENetProtocolCommand_VerifyConnect = 3,
|
||||
ENetProtocolCommand_Count = 13,
|
||||
|
||||
ENetProtocolCommand_Mask = 0x0F
|
||||
};
|
||||
|
||||
enum ENetProtocolFlag
|
||||
{
|
||||
ENetProtocolFlag_Acknowledge = (1 << 7),
|
||||
ENetProtocolFlag_Unsequenced = (1 << 6),
|
||||
|
||||
ENetProtocolHeaderFlag_Compressed = (1 << 14),
|
||||
ENetProtocolHeaderFlag_SentTime = (1 << 15),
|
||||
ENetProtocolHeaderFlag_Mask = ENetProtocolHeaderFlag_Compressed | ENetProtocolHeaderFlag_SentTime,
|
||||
|
||||
ENetProtocolHeaderSessionMask = (3 << 12),
|
||||
ENetProtocolHeaderSessionShift = 12
|
||||
};
|
||||
|
||||
enum class ENetEventType
|
||||
{
|
||||
/** no event occurred within the specified time limit */
|
||||
None,
|
||||
|
||||
/** a peer has disconnected. This event is generated on a successful
|
||||
* completion of a disconnect initiated by enet_peer_disconnect, if
|
||||
* a peer has timed out, or if a connection request initialized by
|
||||
* enet_host_connect has timed out. The peer field contains the peer
|
||||
* which disconnected. The data field contains user supplied data
|
||||
* describing the disconnection, or 0, if none is available.
|
||||
*/
|
||||
Disconnect,
|
||||
|
||||
/** a connection request initiated by enet_host_connect from this host has completed.
|
||||
* The peer field contains the peer which successfully connected.
|
||||
*/
|
||||
OutgoingConnect,
|
||||
|
||||
/** a connection request initiated by enet_host_connect from another host has completed.
|
||||
* The peer field contains the peer which successfully connected.
|
||||
*/
|
||||
IncomingConnect,
|
||||
|
||||
/** a packet has been received from a peer. The peer field specifies the
|
||||
* peer which sent the packet. The channelID field specifies the channel
|
||||
* number upon which the packet was received. The packet field contains
|
||||
* the packet that was received;
|
||||
*/
|
||||
Receive
|
||||
};
|
||||
|
||||
struct ENetEvent
|
||||
{
|
||||
ENetEventType type;
|
||||
ENetPeer* peer;
|
||||
UInt8 channelId;
|
||||
UInt32 data;
|
||||
ENetPacketRef packet;
|
||||
};
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#define NAZARA_PACKED
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define NAZARA_PACKED __attribute__ ((packed))
|
||||
#else
|
||||
#define NAZARA_PACKED
|
||||
#endif
|
||||
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolHeader
|
||||
{
|
||||
UInt16 peerID;
|
||||
UInt16 sentTime;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolCommandHeader
|
||||
{
|
||||
UInt8 command;
|
||||
UInt8 channelID;
|
||||
UInt16 reliableSequenceNumber;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolAcknowledge
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt16 receivedReliableSequenceNumber;
|
||||
UInt16 receivedSentTime;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolConnect
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt16 outgoingPeerID;
|
||||
UInt8 incomingSessionID;
|
||||
UInt8 outgoingSessionID;
|
||||
UInt32 mtu;
|
||||
UInt32 windowSize;
|
||||
UInt32 channelCount;
|
||||
UInt32 incomingBandwidth;
|
||||
UInt32 outgoingBandwidth;
|
||||
UInt32 packetThrottleInterval;
|
||||
UInt32 packetThrottleAcceleration;
|
||||
UInt32 packetThrottleDeceleration;
|
||||
UInt32 connectID;
|
||||
UInt32 data;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolBandwidthLimit
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt32 incomingBandwidth;
|
||||
UInt32 outgoingBandwidth;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolDisconnect
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt32 data;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolPing
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolSendFragment
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt16 startSequenceNumber;
|
||||
UInt16 dataLength;
|
||||
UInt32 fragmentCount;
|
||||
UInt32 fragmentNumber;
|
||||
UInt32 totalLength;
|
||||
UInt32 fragmentOffset;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolSendReliable
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt16 dataLength;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolSendUnreliable
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt16 unreliableSequenceNumber;
|
||||
UInt16 dataLength;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolSendUnsequenced
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt16 unsequencedGroup;
|
||||
UInt16 dataLength;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolThrottleConfigure
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt32 packetThrottleInterval;
|
||||
UInt32 packetThrottleAcceleration;
|
||||
UInt32 packetThrottleDeceleration;
|
||||
};
|
||||
|
||||
struct NAZARA_PACKED ENetProtocolVerifyConnect
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
UInt16 outgoingPeerID;
|
||||
UInt8 incomingSessionID;
|
||||
UInt8 outgoingSessionID;
|
||||
UInt32 mtu;
|
||||
UInt32 windowSize;
|
||||
UInt32 channelCount;
|
||||
UInt32 incomingBandwidth;
|
||||
UInt32 outgoingBandwidth;
|
||||
UInt32 packetThrottleInterval;
|
||||
UInt32 packetThrottleAcceleration;
|
||||
UInt32 packetThrottleDeceleration;
|
||||
UInt32 connectID;
|
||||
};
|
||||
|
||||
union NAZARA_PACKED ENetProtocol
|
||||
{
|
||||
ENetProtocol() = default;
|
||||
|
||||
ENetProtocol(UInt8 command, UInt8 channel)
|
||||
{
|
||||
header.command = command;
|
||||
header.channelID = channel;
|
||||
}
|
||||
|
||||
ENetProtocolCommandHeader header;
|
||||
ENetProtocolAcknowledge acknowledge;
|
||||
ENetProtocolBandwidthLimit bandwidthLimit;
|
||||
ENetProtocolConnect connect;
|
||||
ENetProtocolDisconnect disconnect;
|
||||
ENetProtocolPing ping;
|
||||
ENetProtocolSendReliable sendReliable;
|
||||
ENetProtocolSendUnreliable sendUnreliable;
|
||||
ENetProtocolSendUnsequenced sendUnsequenced;
|
||||
ENetProtocolSendFragment sendFragment;
|
||||
ENetProtocolThrottleConfigure throttleConfigure;
|
||||
ENetProtocolVerifyConnect verifyConnect;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <Nazara/Network/ENetProtocol.inl>
|
||||
|
||||
#endif // NAZARA_ENETPROTOCOL_HPP
|
||||
34
include/Nazara/Network/ENetProtocol.inl
Normal file
34
include/Nazara/Network/ENetProtocol.inl
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (C) 2017 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 <Nazara/Network/ENetProtocol.hpp>
|
||||
#include <Nazara/Network/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
UInt32 ENetTimeDifference(UInt32 a, UInt32 b)
|
||||
{
|
||||
return (ENetTimeLess(a, b)) ? b - a : a - b;
|
||||
}
|
||||
|
||||
bool ENetTimeLess(UInt32 a, UInt32 b)
|
||||
{
|
||||
return (a - b >= ENetTimeOverflow);
|
||||
}
|
||||
|
||||
bool ENetTimeLessEqual(UInt32 a, UInt32 b)
|
||||
{
|
||||
return !ENetTimeGreater(a, b);
|
||||
}
|
||||
|
||||
bool ENetTimeGreater(UInt32 a, UInt32 b)
|
||||
{
|
||||
return ENetTimeLess(b, a);
|
||||
}
|
||||
|
||||
bool ENetTimeGreaterEqual(UInt32 a, UInt32 b)
|
||||
{
|
||||
return !ENetTimeLess(a, b);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
#ifndef NAZARA_ENUMS_NETWORK_HPP
|
||||
#define NAZARA_ENUMS_NETWORK_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Flags.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
@@ -91,6 +91,23 @@ namespace Nz
|
||||
SocketError_Max = SocketError_UnreachableHost
|
||||
};
|
||||
|
||||
enum SocketPollEvent
|
||||
{
|
||||
SocketPollEvent_Read, //< One or more sockets is ready for a read operation
|
||||
SocketPollEvent_Write, //< One or more sockets is ready for a write operation
|
||||
|
||||
SocketPollEvent_Max = SocketPollEvent_Write
|
||||
};
|
||||
|
||||
template<>
|
||||
struct EnumAsFlags<SocketPollEvent>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
static constexpr int max = SocketPollEvent_Max;
|
||||
};
|
||||
|
||||
using SocketPollEventFlags = Flags<SocketPollEvent>;
|
||||
|
||||
enum SocketState
|
||||
{
|
||||
SocketState_Bound, //< The socket is currently bound
|
||||
|
||||
@@ -155,7 +155,9 @@ namespace Nz
|
||||
{
|
||||
InitStream(HeaderSize + size, HeaderSize, OpenMode_ReadOnly);
|
||||
m_buffer->Resize(HeaderSize + size);
|
||||
std::memcpy(m_buffer->GetBuffer() + HeaderSize, ptr, size);
|
||||
|
||||
if (ptr)
|
||||
std::memcpy(m_buffer->GetBuffer() + HeaderSize, ptr, size);
|
||||
|
||||
m_netCode = netCode;
|
||||
}
|
||||
|
||||
@@ -24,10 +24,11 @@ namespace Nz
|
||||
|
||||
void Clear();
|
||||
|
||||
bool IsReady(const AbstractSocket& socket) const;
|
||||
bool IsReadyToRead(const AbstractSocket& socket) const;
|
||||
bool IsReadyToWrite(const AbstractSocket& socket) const;
|
||||
bool IsRegistered(const AbstractSocket& socket) const;
|
||||
|
||||
bool RegisterSocket(AbstractSocket& socket);
|
||||
bool RegisterSocket(AbstractSocket& socket, SocketPollEventFlags eventFlags);
|
||||
void UnregisterSocket(AbstractSocket& socket);
|
||||
|
||||
bool Wait(UInt64 msTimeout);
|
||||
@@ -41,4 +42,4 @@ namespace Nz
|
||||
|
||||
#include <Nazara/Network/SocketPoller.inl>
|
||||
|
||||
#endif // NAZARA_SOCKETPOLLER_HPP
|
||||
#endif // NAZARA_SOCKETPOLLER_HPP
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace Nz
|
||||
|
||||
inline IpAddress GetBoundAddress() const;
|
||||
inline UInt16 GetBoundPort() const;
|
||||
inline SocketState GetState() const;
|
||||
|
||||
inline bool IsBroadcastingEnabled() const;
|
||||
|
||||
|
||||
@@ -103,16 +103,6 @@ namespace Nz
|
||||
return m_boundAddress.GetPort();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the state of the socket
|
||||
* \return State of the socket
|
||||
*/
|
||||
|
||||
inline SocketState UdpSocket::GetState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the broadcasting is enabled
|
||||
* \return true If it is the case
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <Nazara/Utility/Config.hpp>
|
||||
#include <Nazara/Utility/CubemapParams.hpp>
|
||||
#include <Nazara/Utility/Cursor.hpp>
|
||||
#include <Nazara/Utility/CursorController.hpp>
|
||||
#include <Nazara/Utility/Enums.hpp>
|
||||
#include <Nazara/Utility/Event.hpp>
|
||||
#include <Nazara/Utility/EventHandler.hpp>
|
||||
@@ -65,6 +66,7 @@
|
||||
#include <Nazara/Utility/SimpleTextDrawer.hpp>
|
||||
#include <Nazara/Utility/SkeletalMesh.hpp>
|
||||
#include <Nazara/Utility/Skeleton.hpp>
|
||||
#include <Nazara/Utility/SoftwareBuffer.hpp>
|
||||
#include <Nazara/Utility/StaticMesh.hpp>
|
||||
#include <Nazara/Utility/SubMesh.hpp>
|
||||
#include <Nazara/Utility/TriangleIterator.hpp>
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Nz
|
||||
static inline bool Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* src, void* dst);
|
||||
static inline bool Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* start, const void* end, void* dst);
|
||||
|
||||
static inline bool Flip(PixelFlipping flipping, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst);
|
||||
static bool Flip(PixelFlipping flipping, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst);
|
||||
|
||||
static inline UInt8 GetBitsPerPixel(PixelFormatType format);
|
||||
static inline PixelFormatContent GetContent(PixelFormatType format);
|
||||
|
||||
@@ -227,102 +227,6 @@ namespace Nz
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool PixelFormat::Flip(PixelFlipping flipping, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, const void* src, void* dst)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!IsValid(format))
|
||||
{
|
||||
NazaraError("Invalid pixel format");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto it = s_flipFunctions[flipping].find(format);
|
||||
if (it != s_flipFunctions[flipping].end())
|
||||
it->second(width, height, depth, reinterpret_cast<const UInt8*>(src), reinterpret_cast<UInt8*>(dst));
|
||||
else
|
||||
{
|
||||
// Flipping générique
|
||||
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (IsCompressed(format))
|
||||
{
|
||||
NazaraError("No function to flip compressed format");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
UInt8 bpp = GetBytesPerPixel(format);
|
||||
unsigned int lineStride = width*bpp;
|
||||
switch (flipping)
|
||||
{
|
||||
case PixelFlipping_Horizontally:
|
||||
{
|
||||
if (src == dst)
|
||||
{
|
||||
for (unsigned int z = 0; z < depth; ++z)
|
||||
{
|
||||
UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
|
||||
for (unsigned int y = 0; y < height/2; ++y)
|
||||
std::swap_ranges(&ptr[y*lineStride], &ptr[(y+1)*lineStride-1], &ptr[(height-y-1)*lineStride]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int z = 0; z < depth; ++z)
|
||||
{
|
||||
const UInt8* srcPtr = reinterpret_cast<const UInt8*>(src);
|
||||
UInt8* dstPtr = reinterpret_cast<UInt8*>(dst) + (width-1)*height*depth*bpp;
|
||||
for (unsigned int y = 0; y < height; ++y)
|
||||
{
|
||||
std::memcpy(dstPtr, srcPtr, lineStride);
|
||||
|
||||
srcPtr += lineStride;
|
||||
dstPtr -= lineStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PixelFlipping_Vertically:
|
||||
{
|
||||
if (src == dst)
|
||||
{
|
||||
for (unsigned int z = 0; z < depth; ++z)
|
||||
{
|
||||
UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
|
||||
for (unsigned int y = 0; y < height; ++y)
|
||||
{
|
||||
for (unsigned int x = 0; x < width/2; ++x)
|
||||
std::swap_ranges(&ptr[x*bpp], &ptr[(x+1)*bpp], &ptr[(width-x)*bpp]);
|
||||
|
||||
ptr += lineStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int z = 0; z < depth; ++z)
|
||||
{
|
||||
UInt8* ptr = reinterpret_cast<UInt8*>(dst) + width*height*z;
|
||||
for (unsigned int y = 0; y < height; ++y)
|
||||
{
|
||||
for (unsigned int x = 0; x < width; ++x)
|
||||
std::memcpy(&ptr[x*bpp], &ptr[(width-x)*bpp], bpp);
|
||||
|
||||
ptr += lineStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline UInt8 PixelFormat::GetBitsPerPixel(PixelFormatType format)
|
||||
{
|
||||
return s_pixelFormatInfos[format].bitsPerPixel;
|
||||
|
||||
Reference in New Issue
Block a user