Merge branch 'master' into NDK-ShadowMapping

Former-commit-id: e2be28b65207dfbb81efe58f31ca31548afecee7
This commit is contained in:
Lynix
2016-04-17 19:57:15 +02:00
354 changed files with 24993 additions and 2830 deletions

View File

@@ -12,10 +12,11 @@
#include <Nazara/Audio/SoundEmitter.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
namespace Nz
{
struct MusicParams
struct MusicParams : ResourceParameters
{
bool forceMono = false;

View File

@@ -73,8 +73,8 @@ namespace Nz
static bool IsInitialized();
static unsigned int QueryInputDevices(std::vector<String>& devices);
static unsigned int QueryOutputDevices(std::vector<String>& devices);
static std::size_t QueryInputDevices(std::vector<String>& devices);
static std::size_t QueryOutputDevices(std::vector<String>& devices);
static bool SetDevice(const String& deviceName);
@@ -87,7 +87,6 @@ namespace Nz
static bool OpenDevice();
static OpenALFunc LoadEntry(const char* name, bool throwException = false);
};
}
// al
NAZARA_AUDIO_API extern OpenALDetail::LPALBUFFER3F alBuffer3f;
@@ -186,6 +185,8 @@ NAZARA_AUDIO_API extern OpenALDetail::LPALCOPENDEVICE alcOpenDevice;
NAZARA_AUDIO_API extern OpenALDetail::LPALCPROCESSCONTEXT alcProcessContext;
NAZARA_AUDIO_API extern OpenALDetail::LPALCSUSPENDCONTEXT alcSuspendContext;
}
#endif // NAZARA_AUDIO_OPENAL
#endif // NAZARA_OPENAL_HPP

View File

@@ -16,12 +16,13 @@
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceManager.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Core/Stream.hpp>
namespace Nz
{
struct SoundBufferParams
struct SoundBufferParams : ResourceParameters
{
bool forceMono = false;

View File

@@ -1,4 +1,4 @@
// This file was automatically generated on 20 Nov 2015 at 14:22:32
// This file was automatically generated on 03 Feb 2016 at 00:06:56
/*
Nazara Engine - Core module
@@ -30,9 +30,11 @@
#define NAZARA_GLOBAL_CORE_HPP
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/AbstractLogger.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Bitset.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Color.hpp>
@@ -46,6 +48,7 @@
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/FileLogger.hpp>
#include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/GuillotineBinPack.hpp>
#include <Nazara/Core/HardwareInfo.hpp>
@@ -55,6 +58,7 @@
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/Core/MemoryManager.hpp>
#include <Nazara/Core/MemoryPool.hpp>
#include <Nazara/Core/MemoryStream.hpp>
#include <Nazara/Core/MemoryView.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/ObjectLibrary.hpp>
@@ -70,16 +74,15 @@
#include <Nazara/Core/ResourceManager.hpp>
#include <Nazara/Core/Semaphore.hpp>
#include <Nazara/Core/Serialization.hpp>
#include <Nazara/Core/Serializer.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Core/SparsePtr.hpp>
#include <Nazara/Core/StdLogger.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Core/TaskScheduler.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Core/Unicode.hpp>
#include <Nazara/Core/Unserializer.hpp>
#include <Nazara/Core/Updatable.hpp>
#endif // NAZARA_GLOBAL_CORE_HPP

View File

@@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
/*!
* \ingroup core
* \class Nz::AbstractLogger
* \brief Logger interface
*/

View File

@@ -23,8 +23,16 @@ namespace Nz
template<typename O, typename F, typename Tuple> auto Apply(O& object, F&& fn, Tuple&& t);
template<typename T> ByteArray ComputeHash(HashType hash, const T& v);
template<typename T> ByteArray ComputeHash(AbstractHash* hash, const T& v);
template<typename T, std::size_t N> constexpr std::size_t CountOf(T(&name)[N]) noexcept;
template<typename T> std::size_t CountOf(const T& c);
template<typename T> void HashCombine(std::size_t& seed, const T& v);
template<typename T>
struct PointedType
{
using type = void; //< FIXME: I can't make SFINAE work
};
template<typename T>
struct TypeTag {};
@@ -33,10 +41,10 @@ namespace Nz
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(SerializationContext& context, T value);
inline bool Unserialize(UnserializationContext& context, bool* value);
inline bool Unserialize(SerializationContext& context, bool* value);
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(UnserializationContext& context, T* value);
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(SerializationContext& context, T* value);
}
#include <Nazara/Core/Algorithm.inl>

View File

@@ -30,6 +30,16 @@ namespace Nz
}
}
/*!
* \ingroup core
* \brief Applies the tuple to the function (e.g. calls the function using the tuple content as arguments)
* \return The result of the function
*
* \param fn Function
* \param t Tuple of arguments for the function
*
* \see Apply
*/
template<typename F, typename Tuple>
auto Apply(F&& fn, Tuple&& t)
{
@@ -38,6 +48,17 @@ namespace Nz
return Detail::ApplyImplFunc(std::forward<F>(fn), std::forward<Tuple>(t), std::make_index_sequence<tSize>());
}
/*!
* \ingroup core
* \brief Applies the tuple to the member function on an object (e.g. calls the member function using the tuple content as arguments)
* \return The result of the member function called
*
* \param object Object of a class
* \param fn Member function
* \param t Tuple of arguments for the member function
*
* \see Apply
*/
template<typename O, typename F, typename Tuple>
auto Apply(O& object, F&& fn, Tuple&& t)
{
@@ -46,15 +67,42 @@ namespace Nz
return Detail::ApplyImplMethod(object, std::forward<F>(fn), std::forward<Tuple>(t), std::make_index_sequence<tSize>());
}
/*!
* \ingroup core
* \brief Computes the hash of a hashable object
* \return A bytearray which represents the hash
*
* \param hash Enumeration of type HashType
* \param v Object to hash
*
* \remark a HashAppend specialization for type T is required
*
* \see ComputeHash
*/
template<typename T>
ByteArray ComputeHash(HashType hash, const T& v)
{
return ComputeHash(AbstractHash::Get(hash).get(), v);
}
/*!
* \ingroup core
* \brief Computes the hash of a hashable object
* \return A bytearray which represents the hash
*
* \param hash Pointer to abstract hash
* \param v Object to hash
*
* \remark Produce a NazaraAssert if pointer to Abstracthash is invalid
* \remark a HashAppend specialization for type T is required
*
* \see ComputeHash
*/
template<typename T>
ByteArray ComputeHash(AbstractHash* hash, const T& v)
{
NazaraAssert(hash != nullptr, "Invalid abstracthash pointer");
hash->Begin();
HashAppend(hash, v);
@@ -62,7 +110,44 @@ namespace Nz
return hash->End();
}
// Algorithme venant de CityHash par Google
/*!
* \ingroup core
* \brief Returns the number of elements in a C-array
* \return The number of elements
*
* \param name C-array
*
* \see CountOf
*/
template<typename T, std::size_t N>
constexpr std::size_t CountOf(T(&name)[N]) noexcept
{
return N;
}
/*!
* \ingroup core
* \brief Returns the number of elements in a container
* \return The number of elements
*
* \param c Container with the member function "size()"
*
* \see CountOf
*/
template<typename T>
std::size_t CountOf(const T& c)
{
return c.size();
}
/*!
* \ingroup core
* \brief Combines two hash in one
*
* \param seed First value that will be modified (expected to be 64bits)
* \param v Second value to hash
*/
// Algorithm from CityHash by Google
// http://stackoverflow.com/questions/8513911/how-to-create-a-good-hash-combine-with-64-bit-output-inspired-by-boosthash-co
template<typename T>
void HashCombine(std::size_t& seed, const T& v)
@@ -79,6 +164,21 @@ namespace Nz
seed = static_cast<std::size_t>(b * kMul);
}
template<typename T> struct PointedType<T*> {typedef T type;};
template<typename T> struct PointedType<T* const> {typedef T type;};
template<typename T> struct PointedType<T* volatile> {typedef T type;};
template<typename T> struct PointedType<T* const volatile> {typedef T type;};
/*!
* \ingroup core
* \brief Serializes a boolean
* \return true if serialization succedeed
*
* \param context Context for the serialization
* \param value Boolean to serialize
*
* \see Serialize, Unserialize
*/
inline bool Serialize(SerializationContext& context, bool value)
{
if (context.currentBitPos == 8)
@@ -96,6 +196,16 @@ namespace Nz
return true;
}
/*!
* \ingroup core
* \brief Serializes an arithmetic type
* \return true if serialization succedeed
*
* \param context Context for the serialization
* \param value Arithmetic type to serialize
*
* \see Serialize, Unserialize
*/
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(SerializationContext& context, T value)
{
@@ -114,10 +224,18 @@ namespace Nz
return context.stream->Write(&value, sizeof(T)) == sizeof(T);
}
inline bool Unserialize(UnserializationContext& context, bool* value)
/*!
* \ingroup core
* \brief Unserializes a boolean
* \return true if unserialization succedeed
*
* \param context Context for the unserialization
* \param value Pointer to boolean to unserialize
*
* \see Serialize, Unserialize
*/
inline bool Unserialize(SerializationContext& context, bool* value)
{
NazaraAssert(value, "Invalid data pointer");
if (context.currentBitPos == 8)
{
if (!Unserialize(context, &context.currentByte))
@@ -134,8 +252,20 @@ namespace Nz
return true;
}
/*!
* \ingroup core
* \brief Unserializes an arithmetic type
* \return true if unserialization succedeed
*
* \param context Context for the unserialization
* \param value Pointer to arithmetic type to serialize
*
* \remark Produce a NazaraAssert if pointer to value is invalid
*
* \see Serialize, Unserialize
*/
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(UnserializationContext& context, T* value)
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(SerializationContext& context, T* value)
{
NazaraAssert(value, "Invalid data pointer");

View File

@@ -9,6 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
#include <limits>
#include <memory>
#include <type_traits>
@@ -31,9 +32,9 @@ namespace Nz
Bitset(const Bitset& bitset) = default;
explicit Bitset(const String& bits);
Bitset(Bitset&& bitset) noexcept = default;
~Bitset() = default;
~Bitset() noexcept = default;
void Clear();
void Clear() noexcept;
unsigned int Count() const;
void Flip();
@@ -89,9 +90,9 @@ namespace Nz
Bitset& operator|=(const Bitset& bitset);
Bitset& operator^=(const Bitset& bitset);
static Block fullBitMask;
static unsigned int bitsPerBlock;
static unsigned int npos;
static constexpr Block fullBitMask = std::numeric_limits<Block>::max();
static constexpr unsigned int bitsPerBlock = std::numeric_limits<Block>::digits;
static constexpr unsigned int npos = std::numeric_limits<unsigned int>::max();
private:
unsigned int FindFirstFrom(unsigned int blockIndex) const;

File diff suppressed because it is too large Load Diff

View File

@@ -3,62 +3,146 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp>
#include <cstdio>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \brief Constructs a ByteArray object with a reserved size
*
* \param n Space reserved
*/
inline ByteArray::ByteArray(size_type n) :
m_array()
{
m_array.reserve(n);
}
/*!
* \brief Constructs a ByteArray object with a raw memory and a size
*
* \param ptr Pointer to raw memory
* \param n Size that can be accessed
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*/
inline ByteArray::ByteArray(const void* buffer, size_type n) :
m_array(static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n)
{
}
/*!
* \brief Constructs a ByteArray object with n times the same value
*
* \param n Number of repetitions
* \param value Value to repeat
*/
inline ByteArray::ByteArray(size_type n, const value_type value) :
m_array(n, value)
{
}
/*!
* \brief Constructs a ByteArray object from two iterators
*
* \param first First iterator
* \param last Second iterator
*/
template <class InputIterator>
ByteArray::ByteArray(InputIterator first, InputIterator last) :
m_array(first, last)
{
}
/*!
* \brief Appends the content of raw memory
*
* \param ptr Constant pointer to raw memory
* \param n Size that can be read
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*
* \see Insert
*/
inline ByteArray::iterator ByteArray::Append(const void* buffer, size_type n)
{
return Insert(end(), static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n);
}
/*!
* \brief Appends another array of bytes
*
* \param other ByteArray to add
*
* \see Insert
*/
inline ByteArray::iterator ByteArray::Append(const ByteArray& other)
{
return Insert(end(), other.begin(), other.end());
}
/*!
* \brief Assigns this with n times the same value
*
* \param n Number of repetitions
* \param value Value to repeat
*/
inline void ByteArray::Assign(size_type n, value_type value)
{
m_array.assign(n, value);
}
/*!
* \brief Assigns this with the content between two iterators
*
* \param first First iterator
* \param last Second iterator
*/
template <class InputIterator>
void ByteArray::Assign(InputIterator first, InputIterator last)
{
m_array.assign(first, last);
}
/*!
* \brief Gets last element
* \return A reference to last element
*
* \remark If ByteArray is empty, behaviour is undefined
*/
inline ByteArray::reference ByteArray::Back()
{
return m_array.back();
}
/*!
* \brief Gets last element
* \return A constant reference to last element
*
* \remark If ByteArray is empty, behaviour is undefined
*/
inline ByteArray::const_reference ByteArray::Back() const
{
return m_array.back();
}
/*!
* \brief Clears the content of the string
*
* \param keepBuffer Should the buffer be kept
*/
inline void ByteArray::Clear(bool keepBuffer)
{
m_array.clear();
@@ -66,142 +150,326 @@ namespace Nz
m_array.shrink_to_fit();
}
/*!
* \brief Erases an element from the byte array
*
* \param pos Iterator to the element
*/
inline ByteArray::iterator ByteArray::Erase(const_iterator pos)
{
return m_array.erase(pos);
}
/*!
* \brief Erases the elements between the two pointers from the byte array
*
* \param first First iterator
* \param last Second iterator
*/
inline ByteArray::iterator ByteArray::Erase(const_iterator first, const_iterator last)
{
return m_array.erase(first, last);
}
/*!
* \brief Gets first element
* \return A reference to first element
*
* \remark If ByteArray is empty, behaviour is undefined
*/
inline ByteArray::reference ByteArray::Front()
{
return m_array.front();
}
/*!
* \brief Gets first element
* \return A constant reference to first element
*
* \remark If ByteArray is empty, behaviour is undefined
*/
inline ByteArray::const_reference ByteArray::Front() const
{
return m_array.front();
}
/*!
* \brief Gets the internal allocator of the byte array
* \return Allocator
*/
inline ByteArray::allocator_type ByteArray::GetAllocator() const
{
return m_array.get_allocator();
}
/*!
* \brief Gets the raw buffer
* \return Raw buffer
*/
inline ByteArray::pointer ByteArray::GetBuffer()
{
return m_array.data();
}
/*!
* \brief Gets the capacity of the byte array
* \return Capacity of the byte array
*/
inline ByteArray::size_type ByteArray::GetCapacity() const noexcept
{
return m_array.capacity();
}
/*!
* \brief Gets the raw buffer
* \return Raw buffer
*/
inline ByteArray::const_pointer ByteArray::GetConstBuffer() const
{
return m_array.data();
}
/*!
* \brief Gets the maximal size supported by the byte array
* \return Biggest size handled
*/
inline ByteArray::size_type ByteArray::GetMaxSize() const noexcept
{
return m_array.max_size();
}
/*!
* \brief Gets the size of the byte array
* \return Size of the byte array
*/
inline ByteArray::size_type ByteArray::GetSize() const noexcept
{
return m_array.size();
}
/*!
* \brief Returns a sub byte array of the byte array
* \return Sub byte array
*
* \param startPos First iterator
* \param endPos Second iterator
*/
inline ByteArray ByteArray::GetSubArray(const_iterator startPos, const_iterator endPos) const
{
return ByteArray(startPos, endPos);
}
/*!
* \brief Inserts the content of raw memory at the iterator position
*
* \param pos Iterator to the position
* \param buffer Constant pointer to raw memory
* \param n Size that can be read
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*/
inline ByteArray::iterator ByteArray::Insert(const_iterator pos, const void* buffer, size_type n)
{
return m_array.insert(pos, static_cast<const_pointer>(buffer), static_cast<const_pointer>(buffer) + n);
}
/*!
* \brief Inserts the content of another byte array at the iterator position
*
* \param pos Iterator to the position
* \param other Other byte array
*/
inline ByteArray::iterator ByteArray::Insert(const_iterator pos, const ByteArray& other)
{
return m_array.insert(pos, other.begin(), other.end());
}
/*!
* \brief Inserts n times the same value at the iterator position
*
* \param pos Iterator to the position
* \param n Number of repetitions
* \param value Value to repeat
*/
inline ByteArray::iterator ByteArray::Insert(const_iterator pos, size_type n, value_type byte)
{
return m_array.insert(pos, n, byte);
}
/*!
* \brief Inserts the content from two iterators at the iterator position
*
* \param pos Iterator to the position
* \param first First iterator
* \param last Second iterator
*/
template <class InputIterator>
ByteArray::iterator ByteArray::Insert(const_iterator pos, InputIterator first, InputIterator last)
{
return m_array.insert(pos, first, last);
}
/*!
* \brief Checks whether the byte array is empty
* \return true if byte array is empty
*/
inline bool ByteArray::IsEmpty() const noexcept
{
return m_array.empty();
}
/*!
* \brief Erases the last element
*
* \remark If byte array is empty, the behaviour is undefined
*/
inline void ByteArray::PopBack()
{
Erase(end() - 1);
}
/*!
* \brief Erases the first element
*
* \remark If byte array is empty, the behaviour is undefined
*/
inline void ByteArray::PopFront()
{
Erase(begin());
}
/*!
* \brief Prepends the content of raw memory
*
* \param ptr Constant pointer to raw memory
* \param n Size that can be read
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*
* \see Insert
*/
inline ByteArray::iterator ByteArray::Prepend(const void* buffer, size_type n)
{
return Insert(begin(), buffer, n);
}
/*!
* \brief Prepends another array of bytes
*
* \param other ByteArray to add
*
* \see Insert
*/
inline ByteArray::iterator ByteArray::Prepend(const ByteArray& other)
{
return Insert(begin(), other);
}
/*!
* \brief Pushes the byte at the end
*
* \param byte Byte to add
*/
inline void ByteArray::PushBack(const value_type byte)
{
m_array.push_back(byte);
}
/*!
* \brief Pushes the byte at the beginning
*
* \param byte Byte to add
*/
inline void ByteArray::PushFront(const value_type byte)
{
m_array.insert(begin(), 1, byte);
}
/*!
* \brief Reserves enough memory for the buffer size
*
* \param bufferSize Size of the buffer to allocate
*
* \remark If bufferSize is smaller than the old one, nothing is done
*/
inline void ByteArray::Reserve(size_type bufferSize)
{
m_array.reserve(bufferSize);
}
/*!
* \brief Resizes the string
* \return A reference to this
*
* \param newSize Target size
*/
inline void ByteArray::Resize(size_type newSize)
{
m_array.resize(newSize);
}
/*!
* \brief Resizes the string
* \return A reference to this
*
* \param newSize Target size
* \param byte Byte to add if newSize is greather than actual size
*/
inline void ByteArray::Resize(size_type newSize, const value_type byte)
{
m_array.resize(newSize, byte);
}
/*!
* \brief Releases the excedent memory
*/
inline void ByteArray::ShrinkToFit()
{
m_array.shrink_to_fit();
}
/*!
* \brief Swaps the content with the other byte array
*
* \param other Other byte array to swap with
*/
inline void ByteArray::Swap(ByteArray& other)
{
m_array.swap(other.m_array);
}
/*!
* \brief Gives a string representation in base 16
* \return String in base 16
*/
inline String ByteArray::ToHex() const
{
std::size_t length = m_array.size() * 2;
@@ -213,76 +481,153 @@ namespace Nz
return hexOutput;
}
/*!
* \brief Gives a string representation
* \return String where each byte is converted to char
*/
inline String ByteArray::ToString() const
{
return String(reinterpret_cast<const char*>(GetConstBuffer()), GetSize());
}
/*!
* \brief Returns an iterator pointing to the beggining of the string
* \return Beggining of the string
*/
inline ByteArray::iterator ByteArray::begin() noexcept
{
return m_array.begin();
}
/*!
* \brief Returns an iterator pointing to the beggining of the string
* \return Beggining of the string
*/
inline ByteArray::const_iterator ByteArray::begin() const noexcept
{
return m_array.begin();
}
/*!
* \brief Returns a constant iterator pointing to the beggining of the string
* \return Beggining of the string
*/
inline ByteArray::const_iterator ByteArray::cbegin() const noexcept
{
return m_array.cbegin();
}
/*!
* \brief Returns a constant iterator pointing to the end of the string
* \return End of the string
*/
inline ByteArray::const_iterator ByteArray::cend() const noexcept
{
return m_array.cend();
}
/*!
* \brief Returns a constant reversed iterator pointing to the beggining of the string
* \return Beggining of the string
*/
inline ByteArray::const_reverse_iterator ByteArray::crbegin() const noexcept
{
return m_array.crbegin();
}
/*!
* \brief Returns a constant reversed iterator pointing to the end of the string
* \return End of the string
*/
inline ByteArray::const_reverse_iterator ByteArray::crend() const noexcept
{
return m_array.crend();
}
/*!
* \brief Checks whether the byte array is empty
* \return true if byte array is empty
*/
inline bool ByteArray::empty() const noexcept
{
return m_array.empty();
}
/*!
* \brief Returns an iterator pointing to the end of the string
* \return End of the string
*/
inline ByteArray::iterator ByteArray::end() noexcept
{
return m_array.end();
}
/*!
* \brief Returns an iterator pointing to the end of the string
* \return End of the string
*/
inline ByteArray::const_iterator ByteArray::end() const noexcept
{
return m_array.end();
}
/*!
* \brief Returns a reversed iterator pointing to the beggining of the string
* \return Beggining of the string
*/
inline ByteArray::reverse_iterator ByteArray::rbegin() noexcept
{
return m_array.rbegin();
}
/*!
* \brief Returns a reversed iterator pointing to the beggining of the string
* \return Beggining of the string
*/
inline ByteArray::const_reverse_iterator ByteArray::rbegin() const noexcept
{
return m_array.rbegin();
}
/*!
* \brief Returns a reversed iterator pointing to the end of the string
* \return End of the string
*/
inline ByteArray::reverse_iterator ByteArray::rend() noexcept
{
return m_array.rend();
}
/*!
* \brief Gets the size of the byte array
* \return Size of the byte array
*/
inline ByteArray::size_type ByteArray::size() const noexcept
{
return GetSize();
}
/*!
* \brief Gets the ith byte
* \return A reference to the byte at the ith position
*
* \remark Produces a NazaraAssert if pos is greather than the size
*/
inline ByteArray::reference ByteArray::operator[](size_type pos)
{
NazaraAssert(pos < GetSize(), "Index out of range");
@@ -290,6 +635,13 @@ namespace Nz
return m_array[pos];
}
/*!
* \brief Gets the ith byte
* \return A constant reference to the byte at the ith position
*
* \remark Produces a NazaraAssert if pos is greather than the size
*/
inline ByteArray::const_reference ByteArray::operator[](size_type pos) const
{
NazaraAssert(pos < GetSize(), "Index out of range");
@@ -297,6 +649,13 @@ namespace Nz
return m_array[pos];
}
/*!
* \brief Concatenates the byte array to another
* \return ByteArray which is the result of the concatenation
*
* \param other ByteArray to add
*/
inline ByteArray ByteArray::operator+(const ByteArray& other) const
{
ByteArray tmp(*this);
@@ -305,6 +664,13 @@ namespace Nz
return tmp;
}
/*!
* \brief Concatenates the byte array to this byte array
* \return A reference to this
*
* \param other ByteArray to add
*/
inline ByteArray& ByteArray::operator+=(const ByteArray& other)
{
Append(other);
@@ -312,31 +678,79 @@ namespace Nz
return *this;
}
/*!
* \brief Checks whether the first byte array is equal to the second byte array
* \return true if it is the case
*
* \param first ByteArray to compare in left hand side
* \param second ByteArray to compare in right hand side
*/
inline bool ByteArray::operator==(const ByteArray& rhs) const
{
return m_array == rhs.m_array;
}
/*!
* \brief Checks whether the first byte array is equal to the second byte array
* \return false if it is the case
*
* \param first ByteArray to compare in left hand side
* \param second ByteArray to compare in right hand side
*/
inline bool ByteArray::operator!=(const ByteArray& rhs) const
{
return !operator==(rhs);
}
/*!
* \brief Checks whether the first byte array is less than the second byte array
* \return true if it is the case
*
* \param first ByteArray to compare in left hand side
* \param second ByteArray to compare in right hand side
*/
inline bool ByteArray::operator<(const ByteArray& rhs) const
{
return m_array < rhs.m_array;
}
/*!
* \brief Checks whether the first byte array is less or equal than the second byte array
* \return true if it is the case
*
* \param first ByteArray to compare in left hand side
* \param second ByteArray to compare in right hand side
*/
inline bool ByteArray::operator<=(const ByteArray& rhs) const
{
return m_array <= rhs.m_array;
}
/*!
* \brief Checks whether the first byte array is greather than the second byte array
* \return true if it is the case
*
* \param first ByteArray to compare in left hand side
* \param second ByteArray to compare in right hand side
*/
inline bool ByteArray::operator>(const ByteArray& rhs) const
{
return m_array > rhs.m_array;
}
/*!
* \brief Checks whether the first byte array is greather or equal than the second byte array
* \return true if it is the case
*
* \param first ByteArray to compare in left hand side
* \param second ByteArray to compare in right hand side
*/
inline bool ByteArray::operator>=(const ByteArray& rhs) const
{
return m_array >= rhs.m_array;
@@ -351,8 +765,17 @@ namespace Nz
namespace std
{
/*!
* \brief Swaps two byte arrays, specialisation of std
*
* \param lhs First byte array
* \param rhs Second byte array
*/
inline void swap(Nz::ByteArray& lhs, Nz::ByteArray& rhs)
{
lhs.Swap(rhs);
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -0,0 +1,64 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_BYTESTREAM_HPP
#define NAZARA_BYTESTREAM_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/Serialization.hpp>
#include <Nazara/Core/Stream.hpp>
#include <memory>
namespace Nz
{
class NAZARA_CORE_API ByteStream
{
public:
inline ByteStream(Stream* stream = nullptr);
ByteStream(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite);
ByteStream(void* ptr, Nz::UInt64 size);
ByteStream(const void* ptr, Nz::UInt64 size);
ByteStream(const ByteStream&) = delete;
inline ByteStream(ByteStream&& stream);
~ByteStream();
inline Endianness GetDataEndianness() const;
inline Nz::UInt64 GetSize() const;
inline Stream* GetStream() const;
inline bool FlushBits();
inline std::size_t Read(void* ptr, std::size_t size);
inline void SetDataEndianness(Endianness endiannes);
inline void SetStream(Stream* stream);
void SetStream(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite);
void SetStream(void* ptr, Nz::UInt64 size);
void SetStream(const void* ptr, Nz::UInt64 size);
inline void Write(const void* data, std::size_t size);
template<typename T>
ByteStream& operator>>(T& value);
template<typename T>
ByteStream& operator<<(const T& value);
ByteStream& operator=(const ByteStream&) = delete;
inline ByteStream& operator=(ByteStream&&);
private:
virtual void OnEmptyStream();
std::unique_ptr<Stream> m_ownedStream;
SerializationContext m_context;
};
}
#include <Nazara/Core/ByteStream.inl>
#endif // NAZARA_BYTESTREAM_HPP

View File

@@ -0,0 +1,226 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \brief Constructs a ByteStream object with a stream
*/
inline ByteStream::ByteStream(Stream* stream)
{
m_context.stream = stream;
}
/*!
* \brief Constructs a ByteStream object by move semantic
*
* \param stream ByteStream to move into this
*/
inline ByteStream::ByteStream(ByteStream&& stream) :
m_ownedStream(std::move(stream.m_ownedStream)),
m_context(stream.m_context)
{
stream.m_context.stream = nullptr;
}
/*!
* \brief Destructs the object and calls FlushBits
*
* \remark Produces a NazaraWarning if flush did not work
*
* \see FlushBits
*/
inline ByteStream::~ByteStream()
{
if (!FlushBits())
NazaraWarning("Failed to flush bits at serializer destruction");
}
/*!
* \brief Gets the stream endianness
* \return Type of the endianness
*/
inline Endianness ByteStream::GetDataEndianness() const
{
return m_context.endianness;
}
/*!
* \brief Gets the size of the byte stream
* \return Size of the stream
*/
inline Nz::UInt64 ByteStream::GetSize() const
{
if (m_context.stream)
return m_context.stream->GetSize();
else
return 0;
}
/*!
* \brief Gets the internal stream
* \return Internal stream
*/
inline Stream* ByteStream::GetStream() const
{
return m_context.stream;
}
/*!
* \brief Flushes the stream
* \return true if flushing is successful
*/
inline bool ByteStream::FlushBits()
{
if (!m_context.stream)
return true;
if (m_context.currentBitPos != 8)
{
m_context.currentBitPos = 8; //< To prevent Serialize to flush bits itself
if (!Serialize<UInt8>(m_context, m_context.currentByte))
return false;
}
return true;
}
/*!
* \brief Reads data
* \return Number of data read
*
* \param buffer Preallocated buffer to contain information read
* \param size Size of the read and thus of the buffer
*/
inline std::size_t ByteStream::Read(void* ptr, std::size_t size)
{
if (!m_context.stream)
OnEmptyStream();
FlushBits();
return m_context.stream->Read(ptr, size);
}
/*!
* \brief Sets the stream endianness
*
* \param Type of the endianness
*/
inline void ByteStream::SetDataEndianness(Endianness endiannes)
{
m_context.endianness = endiannes;
}
/*!
* \brief Sets this with a stream
*
* \param stream Stream existing
*
* \remark Produces a NazaraAssert if stream is invalid
*/
inline void ByteStream::SetStream(Stream* stream)
{
NazaraAssert(stream, "Invalid stream");
// We don't want to lose some bits..
FlushBits();
m_context.stream = stream;
m_ownedStream.reset();
}
/*!
* \brief Writes data
* \return Number of data written
*
* \param buffer Preallocated buffer containing information to write
* \param size Size of the writting and thus of the buffer
*
* \remark Produces a NazaraAssert if buffer is nullptr
*/
inline void ByteStream::Write(const void* data, std::size_t size)
{
if (!m_context.stream)
OnEmptyStream();
FlushBits();
m_context.stream->Write(data, size);
}
/*!
* \brief Outputs a data from the stream
* \return A reference to this
*
* \param value Value to unserialize
*
* \remark Produces a NazaraError if unserialization failed
*/
template<typename T>
ByteStream& ByteStream::operator>>(T& value)
{
if (!m_context.stream)
OnEmptyStream();
if (!Unserialize(m_context, &value))
NazaraError("Failed to serialize value");
return *this;
}
/*!
* \brief Adds the data to the stream
* \return A reference to this
*
* \param value Value to serialize
*
* \remark Produces a NazaraError if serialization failed
*/
template<typename T>
ByteStream& ByteStream::operator<<(const T& value)
{
if (!m_context.stream)
OnEmptyStream();
if (!Serialize(m_context, value))
NazaraError("Failed to serialize value");
return *this;
}
/*!
* \brief Moves the other byte stream into this
* \return A reference to this
*
* \param stream ByteStream to move in this
*/
inline ByteStream& ByteStream::operator=(ByteStream&& stream)
{
m_context = stream.m_context;
m_ownedStream = std::move(stream.m_ownedStream);
stream.m_context.stream = nullptr;
return *this;
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -7,17 +7,39 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::CallOnExit
* \brief Core class that represents a function to call at the end of the scope
*/
/*!
* \brief Constructs a CallOnExit object with a function
*
* \param func Function to call on exit
*/
inline CallOnExit::CallOnExit(Func func) :
m_func(func)
{
}
/*!
* \brief Destructs the object and calls the function
*/
inline CallOnExit::~CallOnExit()
{
if (m_func)
m_func();
}
/*!
* \brief Calls the function and sets the new callback
*
* \param func Function to call on exit
*/
inline void CallOnExit::CallAndReset(Func func)
{
if (m_func)
@@ -26,6 +48,12 @@ namespace Nz
Reset(func);
}
/*!
* \brief Resets the function
*
* \param func Function to call on exit
*/
inline void CallOnExit::Reset(Func func)
{
m_func = func;

View File

@@ -13,6 +13,8 @@
namespace Nz
{
struct SerializationContext;
class Color
{
public:
@@ -62,6 +64,9 @@ namespace Nz
private:
static float Hue2RGB(float v1, float v2, float vH);
};
inline bool Serialize(SerializationContext& context, const Color& color);
inline bool Unserialize(SerializationContext& context, Color* color);
}
std::ostream& operator<<(std::ostream& out, const Nz::Color& color);

View File

@@ -2,6 +2,7 @@
// 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/Algorithm.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <algorithm>
#include <cmath>
@@ -11,10 +12,29 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::Color
* \brief Core class that represents a color
*/
/*!
* \brief Constructs a Color object by default
*/
inline Color::Color()
{
}
/*!
* \brief Constructs a Color object with values
*
* \param red Red value
* \param green Green value
* \param blue Blue value
* \param alpha Alpha value
*/
inline Color::Color(UInt8 red, UInt8 green, UInt8 blue, UInt8 alpha) :
r(red),
g(green),
@@ -23,6 +43,12 @@ namespace Nz
{
}
/*!
* \brief Constructs a Color object with a light level
*
* \param lightness Value for r, g and b
*/
inline Color::Color(UInt8 lightness) :
r(lightness),
g(lightness),
@@ -31,6 +57,13 @@ namespace Nz
{
}
/*!
* \brief Constructs a Color object with values
*
* \param vec[3] vec[0] = red value, vec[1] = green value, vec[2] = blue value
* \param alpha Alpha value
*/
inline Color::Color(UInt8 vec[3], UInt8 alpha) :
r(vec[0]),
g(vec[1]),
@@ -39,6 +72,11 @@ namespace Nz
{
}
/*!
* \brief Converts this to string
* \return String representation of the object "Color(r, g, b[, a])"
*/
inline String Color::ToString() const
{
StringStream ss;
@@ -52,6 +90,13 @@ namespace Nz
return ss;
}
/*!
* \brief Adds two colors together
* \return Color which is the sum
*
* \param color Other color
*/
inline Color Color::operator+(const Color& color) const
{
///TODO: Improve this shit
@@ -64,6 +109,13 @@ namespace Nz
return c;
}
/*!
* \brief Multiplies two colors together
* \return Color which is the product
*
* \param color Other color
*/
inline Color Color::operator*(const Color& color) const
{
///TODO: Improve this shit
@@ -76,48 +128,104 @@ namespace Nz
return c;
}
/*!
* \brief Adds the color to this
* \return Color which is the sum
*
* \param color Other color
*/
inline Color Color::operator+=(const Color& color)
{
return operator=(operator+(color));
}
/*!
* \brief Multiplies the color to this
* \return Color which is the product
*
* \param color Other color
*/
inline Color Color::operator*=(const Color& color)
{
return operator=(operator*(color));
}
/*!
* \brief Checks whether the two colors are equal
* \return true if it is the case
*
* \param color Color to compare
*/
inline bool Color::operator==(const Color& color) const
{
return r == color.r && g == color.g && b == color.b && a == color.a;
}
/*!
* \brief Checks whether the two colors are equal
* \return false if it is the case
*
* \param color Color to compare
*/
inline bool Color::operator!=(const Color& color) const
{
return !operator==(color);
}
// Algorithmes venant de http://www.easyrgb.com/index.php?X=MATH
// Algorithm coming from http://www.easyrgb.com/index.php?X=MATH
/*!
* \brief Converts CMY representation to RGB
* \return Color resulting
*
* \param cyan Cyan component
* \param magenta Magenta component
* \param yellow Yellow component
*/
inline Color Color::FromCMY(float cyan, float magenta, float yellow)
{
return Color(static_cast<UInt8>((1.f-cyan)*255.f), static_cast<UInt8>((1.f-magenta)*255.f), static_cast<UInt8>((1.f-yellow)*255.f));
}
/*!
* \brief Converts CMYK representation to RGB
* \return Color resulting
*
* \param cyan Cyan component
* \param magenta Magenta component
* \param yellow Yellow component
* \param black Black component
*/
inline Color Color::FromCMYK(float cyan, float magenta, float yellow, float black)
{
return FromCMY(cyan * (1.f - black) + black,
magenta * (1.f - black) + black,
yellow * (1.f - black) + black);
magenta * (1.f - black) + black,
yellow * (1.f - black) + black);
}
/*!
* \brief Converts HSL representation to RGB
* \return Color resulting
*
* \param hue Hue component
* \param saturation Saturation component
* \param lightness Lightness component
*/
inline Color Color::FromHSL(UInt8 hue, UInt8 saturation, UInt8 lightness)
{
if (saturation == 0)
{
// RGB results from 0 to 255
return Color(lightness * 255,
lightness * 255,
lightness * 255);
lightness * 255,
lightness * 255);
}
else
{
@@ -135,11 +243,20 @@ namespace Nz
float v1 = 2.f * l - v2;
return Color(static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h + (1.f/3.f))),
static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h)),
static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h - (1.f/3.f))));
static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h)),
static_cast<UInt8>(255.f * Hue2RGB(v1, v2, h - (1.f/3.f))));
}
}
/*!
* \brief Converts HSV representation to RGB
* \return Color resulting
*
* \param hue Hue component
* \param saturation Saturation component
* \param value Value component
*/
inline Color Color::FromHSV(float hue, float saturation, float value)
{
if (NumberEquals(saturation, 0.f))
@@ -201,11 +318,28 @@ namespace Nz
return Color(static_cast<UInt8>(r*255.f), static_cast<UInt8>(g*255.f), static_cast<UInt8>(b*255.f));
}
}
/*!
* \brief Converts XYZ representation to RGB
* \return Color resulting
*
* \param vec Vector3 representing the space color
*/
inline Color Color::FromXYZ(const Vector3f& vec)
{
return FromXYZ(vec.x, vec.y, vec.z);
}
/*!
* \brief Converts XYZ representation to RGB
* \return Color resulting
*
* \param x X component
* \param y Y component
* \param z Z component
*/
inline Color Color::FromXYZ(float x, float y, float z)
{
x /= 100.f; // X from 0 to 95.047
@@ -234,6 +368,15 @@ namespace Nz
return Color(static_cast<UInt8>(r * 255.f), static_cast<UInt8>(g * 255.f), static_cast<UInt8>(b * 255.f));
}
/*!
* \brief Converts RGB representation to CMYK
*
* \param color Color to transform
* \param cyan Cyan component
* \param magenta Magenta component
* \param yellow Yellow component
*/
inline void Color::ToCMY(const Color& color, float* cyan, float* magenta, float* yellow)
{
*cyan = 1.f - color.r/255.f;
@@ -241,6 +384,15 @@ namespace Nz
*yellow = 1.f - color.b/255.f;
}
/*!
* \brief Converts RGB representation to CMYK
*
* \param color Color to transform
* \param cyan Cyan component
* \param magenta Magenta component
* \param yellow Yellow component
*/
inline void Color::ToCMYK(const Color& color, float* cyan, float* magenta, float* yellow, float* black)
{
float c, m, y;
@@ -265,6 +417,15 @@ namespace Nz
*black = k;
}
/*!
* \brief Converts RGB representation to HSL
*
* \param color Color to transform
* \param hue Hue component
* \param saturation Saturation component
* \param lightness Lightness component
*/
inline void Color::ToHSL(const Color& color, UInt8* hue, UInt8* saturation, UInt8* lightness)
{
float r = color.r / 255.f;
@@ -315,6 +476,15 @@ namespace Nz
}
}
/*!
* \brief Converts RGB representation to HSV
*
* \param color Color to transform
* \param hue Hue component
* \param saturation Saturation component
* \param value Value component
*/
inline void Color::ToHSV(const Color& color, float* hue, float* saturation, float* value)
{
float r = color.r / 255.f;
@@ -361,11 +531,27 @@ namespace Nz
}
}
/*!
* \brief Converts RGB representation to XYZ
*
* \param color Color to transform
* \param vec Vector3 representing the space color
*/
inline void Color::ToXYZ(const Color& color, Vector3f* vec)
{
return ToXYZ(color, &vec->x, &vec->y, &vec->z);
}
/*!
* \brief Converts RGB representation to XYZ
*
* \param color Color to transform
* \param x X component
* \param y Y component
* \param z Z component
*/
inline void Color::ToXYZ(const Color& color, float* x, float* y, float* z)
{
float r = color.r/255.f; //R from 0 to 255
@@ -397,6 +583,15 @@ namespace Nz
*z = r*0.0193f + g*0.1192f + b*0.9505f;
}
/*!
* \brief Converts HUE representation to RGV
* \return RGB corresponding
*
* \param v1 V1 component
* \param v2 V2 component
* \param vH VH component
*/
inline float Color::Hue2RGB(float v1, float v2, float vH)
{
if (vH < 0.f)
@@ -415,8 +610,64 @@ namespace Nz
return v1 + (v2 - v1)*(2.f/3.f - vH)*6;
return v1;
}
/*!
* \brief Serializes a Color
* \return true if successfully serialized
*
* \param context Serialization context
* \param color Input color
*/
inline bool Serialize(SerializationContext& context, const Color& color)
{
if (!Serialize(context, color.r))
return false;
if (!Serialize(context, color.g))
return false;
if (!Serialize(context, color.b))
return false;
if (!Serialize(context, color.a))
return false;
return true;
}
/*!
* \brief Unserializes a Color
* \return true if successfully unserialized
*
* \param context Serialization context
* \param color Output color
*/
inline bool Unserialize(SerializationContext& context, Color* color)
{
if (!Unserialize(context, &color->r))
return false;
if (!Unserialize(context, &color->g))
return false;
if (!Unserialize(context, &color->b))
return false;
if (!Unserialize(context, &color->a))
return false;
return true;
}
}
}
/*!
* \brief Output operator
* \return The stream
*
* \param out The stream
* \param color The color to output
*/
inline std::ostream& operator<<(std::ostream& out, const Nz::Color& color)
{

View File

@@ -19,7 +19,7 @@ namespace Nz
public:
ConditionVariable();
ConditionVariable(const ConditionVariable&) = delete;
ConditionVariable(ConditionVariable&&) = delete; ///TODO
inline ConditionVariable(ConditionVariable&& condition) noexcept;
~ConditionVariable();
void Signal();
@@ -29,11 +29,13 @@ namespace Nz
bool Wait(Mutex* mutex, UInt32 timeout);
ConditionVariable& operator=(const ConditionVariable&) = delete;
ConditionVariable& operator=(ConditionVariable&&) = delete; ///TODO
inline ConditionVariable& operator=(ConditionVariable&& condition) noexcept;
private:
ConditionVariableImpl* m_impl;
};
}
#include <Nazara/Core/ConditionVariable.inl>
#endif // NAZARA_CONDITIONVARIABLE_HPP

View File

@@ -0,0 +1,25 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/ConditionVariable.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \class Nz::ConditionVariable
*/
/*!
* \brief Constructs a ConditionVariable object by moving another one
*/
inline ConditionVariable::ConditionVariable(ConditionVariable&& condition) noexcept :
m_impl(condition.m_impl)
{
condition.m_impl = nullptr;
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -27,36 +27,41 @@
#ifndef NAZARA_CONFIG_CORE_HPP
#define NAZARA_CONFIG_CORE_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
/*!
* \defgroup core (NazaraCore) Core module
* Core/System module including classes to handle threading, time, hardware info, memory management, etc...
*/
// Précision des réels lors de la transformation en chaîne de caractère (Max. chiffres après la virgule)
/// Each modification of a parameter needs a recompilation of the module
// Precision of reals when transformed into string (Max. numbers after the coma)
#define NAZARA_CORE_DECIMAL_DIGITS 6
// Duplique la sortie du log sur le flux de sortie standard (cout)
// Duplicate the log output on the standard output flux (cout)
#define NAZARA_CORE_DUPLICATE_LOG_TO_COUT 0
// Teste les assertions
// Checks the assertions
#define NAZARA_CORE_ENABLE_ASSERTS 0
// Appelle exit dès qu'une assertion est invalide
// Call exit when an assertion is invalid
#define NAZARA_CORE_EXIT_ON_ASSERT_FAILURE 1
// Taille du buffer lors d'une lecture complète d'un fichier (ex: Hash)
// Size of buffer when reading entirely a file (ex: Hash)
#define NAZARA_CORE_FILE_BUFFERSIZE 4096
// Incorpore la table Unicode Character Data (Nécessaires pour faire fonctionner le flag String::HandleUTF8)
// Incorporate the Unicode Character Data table (Necessary to make it work with the flag String::HandleUTF8)
#define NAZARA_CORE_INCLUDE_UNICODEDATA 0
// Utilise le MemoryManager pour gérer les allocations dynamiques (détecte les leaks au prix d'allocations/libérations dynamiques plus lentes)
// Use the MemoryManager to manage dynamic allocations (can detect memory leak but allocations/frees are slower)
#define NAZARA_CORE_MANAGE_MEMORY 0
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
// Activate the security tests based on the code (Advised for development)
#define NAZARA_CORE_SAFE 1
// Protège les classes des accès concurrentiels
// Protect the classes against data race
#define NAZARA_CORE_THREADSAFE 1
// Les classes à protéger des accès concurrentiels
// Classes to protect against data race
#define NAZARA_THREADSAFETY_CLOCK 0 // Clock
#define NAZARA_THREADSAFETY_DIRECTORY 1 // Directory
#define NAZARA_THREADSAFETY_DYNLIB 1 // DynLib
@@ -64,18 +69,19 @@
#define NAZARA_THREADSAFETY_LOG 1 // Log
#define NAZARA_THREADSAFETY_REFCOUNTED 1 // RefCounted
// Le nombre de spinlocks à utiliser avec les sections critiques de Windows (0 pour désactiver)
// Number of spinlocks to use with the Windows critical sections (0 to disable)
#define NAZARA_CORE_WINDOWS_CS_SPINLOCKS 4096
// Optimise l'implémentation Windows avec certaines avancées de Windows vista (Casse la compatibilité XP)
// Optimize the Windows implementation with technologies of Windows vista (and greather) (Break the compatibility with XP)
#define NAZARA_CORE_WINDOWS_VISTA 0
/*
// Règle le temps entre le réveil du thread des timers et l'activation d'un timer (En millisecondes)
// Sets the time between waking thread timers and activating a timer (in milliseconds)
#define NAZARA_CORE_TIMER_WAKEUPTIME 10
*/
/// Vérification des valeurs et types de certaines constantes
/// Checking the values and types of certain constants
#include <Nazara/Core/ConfigCheck.hpp>
#if defined(NAZARA_STATIC)

View File

@@ -7,12 +7,12 @@
#ifndef NAZARA_CONFIG_CHECK_CORE_HPP
#define NAZARA_CONFIG_CHECK_CORE_HPP
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
/// This file is used to check the constant values defined in Config.hpp
#include <type_traits>
#define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
// On force la valeur de MANAGE_MEMORY en mode debug
// We fore the value of MANAGE_MEMORY in debug
#if defined(NAZARA_DEBUG) && !NAZARA_CORE_MANAGE_MEMORY
#undef NAZARA_CORE_MANAGE_MEMORY
#define NAZARA_CORE_MANAGE_MEMORY 0

View File

@@ -2,7 +2,7 @@
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// On suppose que Debug.hpp a déjà été inclus, tout comme Config.hpp
// We assume that Debug.hpp has already been included, same thing for Config.hpp
#if NAZARA_CORE_MANAGE_MEMORY
#undef delete
#undef new

View File

@@ -28,7 +28,7 @@
namespace Nz
{
using DynLibFunc = int (*)(); // Type "générique" de pointeur sur fonction
using DynLibFunc = int (*)(); // "Generic" type of poiter to function
class DynLibImpl;
@@ -56,7 +56,7 @@ namespace Nz
mutable String m_lastError;
DynLibImpl* m_impl;
};
};
}
#endif // NAZARA_DYNLIB_HPP

View File

@@ -11,12 +11,12 @@
#include <Nazara/Core/Enums.hpp>
#if !defined(NAZARA_BIG_ENDIAN) && !defined(NAZARA_LITTLE_ENDIAN)
// Détection automatique selon les macros du compilateur
// Automatic detection following macroes of compiler
#if defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || (defined(__MIPS__) && defined(__MISPEB__)) || \
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || defined(__sparc__) || defined(__hppa__)
#define NAZARA_BIG_ENDIAN
#elif defined(__i386__) || defined(__i386) || defined(__X86__) || defined (__x86_64) || defined(_M_I86) || \
defined(_M_IX86) || defined(_M_X64)
defined(_M_IX86) || defined(_M_X64)
#define NAZARA_LITTLE_ENDIAN
#else
#error Failed to identify endianness, you must define either NAZARA_BIG_ENDIAN or NAZARA_LITTLE_ENDIAN

View File

@@ -7,6 +7,12 @@
namespace Nz
{
/*!
* \ingroup core
* \brief Gets the platform endianness
* \return Type of the endianness
*/
inline constexpr Endianness GetPlatformEndianness()
{
#if defined(NAZARA_BIG_ENDIAN)
@@ -16,11 +22,21 @@ namespace Nz
#endif
}
/*!
* \ingroup core
* \brief Swaps the byte for endianness operations
*
* \param buffer Raw memory
* \param size Size to change endianness
*
* \remark If size is greather than the preallocated buffer, the behaviour is undefined
*/
inline void SwapBytes(void* buffer, unsigned int size)
{
UInt8* bytes = reinterpret_cast<UInt8*>(buffer);
UInt8* bytes = static_cast<UInt8*>(buffer);
unsigned int i = 0;
unsigned int j = size-1;
unsigned int j = size - 1;
while (i < j)
std::swap(bytes[i++], bytes[j--]);

View File

@@ -19,9 +19,9 @@ namespace Nz
enum CursorPosition
{
CursorPosition_AtBegin, // Début du fichier
CursorPosition_AtCurrent, // Position du pointeur
CursorPosition_AtEnd, // Fin du fichier
CursorPosition_AtBegin, // beginning of the file
CursorPosition_AtCurrent, // Position of the cursor
CursorPosition_AtEnd, // End of the file
CursorPosition_Max = CursorPosition_AtEnd
};
@@ -45,7 +45,7 @@ namespace Nz
ErrorFlag_ThrowException = 0x4,
ErrorFlag_ThrowExceptionDisabled = 0x8,
ErrorFlag_Max = ErrorFlag_ThrowExceptionDisabled*2-1
ErrorFlag_Max = ErrorFlag_ThrowExceptionDisabled * 2 - 1
};
enum ErrorType
@@ -75,18 +75,18 @@ namespace Nz
enum OpenModeFlags
{
OpenMode_NotOpen = 0x00, // Utilise le mode d'ouverture actuel
OpenMode_NotOpen = 0x00, // Use the current mod of opening
OpenMode_Append = 0x01, // Empêche l'écriture sur la partie déjà existante et met le curseur à la fin
OpenMode_Lock = 0x02, // Empêche le fichier d'être modifié tant qu'il est ouvert
OpenMode_ReadOnly = 0x04, // Ouvre uniquement en lecture
OpenMode_Text = 0x10, // Ouvre en mode texte
OpenMode_Truncate = 0x20, // Créé le fichier s'il n'existe pas et le vide s'il existe
OpenMode_WriteOnly = 0x40, // Ouvre uniquement en écriture, créé le fichier s'il n'existe pas
OpenMode_Append = 0x01, // Disable writing on existing parts and put the cursor at the end
OpenMode_Lock = 0x02, // Disable modifying the file before it is open
OpenMode_ReadOnly = 0x04, // Open in read only
OpenMode_Text = 0x10, // Open in text mod
OpenMode_Truncate = 0x20, // Create the file if it doesn't exist and empty it if it exists
OpenMode_WriteOnly = 0x40, // Open in write only, create the file if it doesn't exist
OpenMode_ReadWrite = OpenMode_ReadOnly | OpenMode_WriteOnly, // Ouvre en lecture/écriture
OpenMode_ReadWrite = OpenMode_ReadOnly | OpenMode_WriteOnly, // Open in read and write
OpenMode_Max = OpenMode_WriteOnly
OpenMode_Max = OpenMode_WriteOnly * 2 - 1
};
enum ParameterType
@@ -177,7 +177,7 @@ namespace Nz
StreamOption_Sequential = 0x1,
StreamOption_Text = 0x2,
StreamOption_Max = StreamOption_Text*2-1
StreamOption_Max = StreamOption_Text * 2 - 1
};
enum Ternary

View File

@@ -9,19 +9,18 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/String.hpp>
#if NAZARA_CORE_ENABLE_ASSERTS || defined(NAZARA_DEBUG)
#define NazaraAssert(a, err) if (!(a)) Nz::Error::Trigger(Nz::ErrorType_AssertFailed, err, __LINE__, Nz::Directory::GetCurrentFileRelativeToEngine(__FILE__), NAZARA_FUNCTION)
#define NazaraAssert(a, err) if (!(a)) Nz::Error::Trigger(Nz::ErrorType_AssertFailed, err, __LINE__, __FILE__, NAZARA_FUNCTION)
#else
#define NazaraAssert(a, err) for (;;) break
#endif
#define NazaraError(err) Nz::Error::Trigger(Nz::ErrorType_Normal, err, __LINE__, Nz::Directory::GetCurrentFileRelativeToEngine(__FILE__), NAZARA_FUNCTION)
#define NazaraInternalError(err) Nz::Error::Trigger(Nz::ErrorType_Internal, err, __LINE__, Nz::Directory::GetCurrentFileRelativeToEngine(__FILE__), NAZARA_FUNCTION)
#define NazaraWarning(err) Nz::Error::Trigger(Nz::ErrorType_Warning, err, __LINE__, Nz::Directory::GetCurrentFileRelativeToEngine(__FILE__), NAZARA_FUNCTION)
#define NazaraError(err) Nz::Error::Trigger(Nz::ErrorType_Normal, err, __LINE__, __FILE__, NAZARA_FUNCTION)
#define NazaraInternalError(err) Nz::Error::Trigger(Nz::ErrorType_Internal, err, __LINE__, __FILE__, NAZARA_FUNCTION)
#define NazaraWarning(err) Nz::Error::Trigger(Nz::ErrorType_Warning, err, __LINE__, __FILE__, NAZARA_FUNCTION)
namespace Nz
{

View File

@@ -8,11 +8,27 @@
namespace Nz
{
/*!
* \brief Computes the hash for the file
* \return ByteArray represing the result of the hash of the file
*
* \param hash Hash to execute
* \param filePath Path for the file
*/
inline ByteArray File::ComputeHash(HashType hash, const String& filePath)
{
return ComputeHash(AbstractHash::Get(hash).get(), filePath);
}
/*!
* \brief Computes the hash for the file
* \return ByteArray represing the result of the hash of the file
*
* \param hash Hash to execute
* \param filePath Path for the file
*/
inline ByteArray File::ComputeHash(AbstractHash* hash, const String& filePath)
{
return Nz::ComputeHash(hash, File(filePath));

View File

@@ -9,7 +9,7 @@
#include <Nazara/Core/Algorithm.hpp>
// Inspiré du code de la SFML par Laurent Gomila
// Inspired from the of code of the SFML by Laurent Gomila
namespace Nz
{

View File

@@ -6,18 +6,44 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::FunctorWithoutArgs
* \brief Core class that represents a functor using a function without argument
*/
/*!
* \brief Constructs a FunctorWithoutArgs object with a function
*
* \param func Function to execute
*/
template<typename F>
FunctorWithoutArgs<F>::FunctorWithoutArgs(F func) :
m_func(func)
{
}
/*!
* \brief Runs the function
*/
template<typename F>
void FunctorWithoutArgs<F>::Run()
{
m_func();
}
/*!
* \ingroup core
* \class Nz::FunctorWithArgs
* \brief Core class that represents a functor using a function with arguments
*/
/*!
* \brief Constructs a FunctorWithArgs object with a function and its arguments
*
* \param func Function to execute
* \param args Arguments for the function
*/
template<typename F, typename... Args>
FunctorWithArgs<F, Args...>::FunctorWithArgs(F func, Args&&... args) :
m_func(func),
@@ -25,13 +51,27 @@ namespace Nz
{
}
/*!
* \brief Runs the function
*/
template<typename F, typename... Args>
void FunctorWithArgs<F, Args...>::Run()
{
Apply(m_func, m_args);
}
/*!
* \ingroup core
* \class Nz::MemberWithoutArgs
* \brief Core class that represents a functor using a member function
*/
/*!
* \brief Constructs a MemberWithoutArgs object with a member function and an object
*
* \param func Member function to execute
* \param object Object to execute on
*/
template<typename C>
MemberWithoutArgs<C>::MemberWithoutArgs(void (C::*func)(), C* object) :
m_func(func),
@@ -39,6 +79,9 @@ namespace Nz
{
}
/*!
* \brief Runs the function
*/
template<typename C>
void MemberWithoutArgs<C>::Run()
{

View File

@@ -0,0 +1,47 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
#pragma once
#ifndef NAZARA_OBJECTHANDLER_HPP
#define NAZARA_OBJECTHANDLER_HPP
#include <Nazara/Core/Bitset.hpp>
#include <memory>
#include <vector>
namespace Nz
{
template<typename T> class ObjectHandle;
template<typename T>
class HandledObject
{
friend ObjectHandle<T>;
public:
HandledObject() = default;
HandledObject(const HandledObject& object);
HandledObject(HandledObject&& object);
~HandledObject();
ObjectHandle<T> CreateHandle();
HandledObject& operator=(const HandledObject& object);
HandledObject& operator=(HandledObject&& object);
protected:
void UnregisterAllHandles();
private:
void RegisterHandle(ObjectHandle<T>* handle);
void UnregisterHandle(ObjectHandle<T>* handle);
std::vector<ObjectHandle<T>*> m_handles;
};
}
#include <Nazara/Core/HandledObject.inl>
#endif // NAZARA_OBJECTHANDLER_HPP

View File

@@ -0,0 +1,84 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ObjectHandle.hpp>
#include <algorithm>
#include <type_traits>
#include <utility>
namespace Nz
{
template<typename T>
HandledObject<T>::HandledObject(const HandledObject& object)
{
// Don't copy anything, we're a copy of the object, we have no handle right now
}
template<typename T>
HandledObject<T>::HandledObject(HandledObject&& object) :
m_handles(std::move(object.m_handles))
{
for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectMoved(static_cast<T*>(this));
}
template<typename T>
HandledObject<T>::~HandledObject()
{
UnregisterAllHandles();
}
template<typename T>
ObjectHandle<T> HandledObject<T>::CreateHandle()
{
return ObjectHandle<T>(static_cast<T*>(this));
}
template<typename T>
HandledObject<T>& HandledObject<T>::operator=(const HandledObject& object)
{
// Nothing to do
return *this;
}
template<typename T>
HandledObject<T>& HandledObject<T>::operator=(HandledObject&& object)
{
m_handles = std::move(object.m_handles);
for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectMoved(static_cast<T*>(this));
return *this;
}
template<typename T>
void HandledObject<T>::RegisterHandle(ObjectHandle<T>* handle)
{
///DOC: Un handle ne doit être enregistré qu'une fois, des erreurs se produisent s'il l'est plus d'une fois
m_handles.push_back(handle);
}
template<typename T>
void HandledObject<T>::UnregisterAllHandles()
{
// Tell every handle we got destroyed, to null them
for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectDestroyed();
m_handles.clear();
}
template<typename T>
void HandledObject<T>::UnregisterHandle(ObjectHandle<T>* handle)
{
///DOC: Un handle ne doit être libéré qu'une fois, et doit faire partie de la liste, sous peine de crash
auto it = std::find(m_handles.begin(), m_handles.end(), handle);
NazaraAssert(it != m_handles.end(), "Handle not registred");
// On échange cet élément avec le dernier, et on diminue la taille du vector de 1
std::swap(*it, m_handles.back());
m_handles.pop_back();
}
}

View File

@@ -23,8 +23,8 @@ namespace Nz
void Begin() override;
ByteArray End() override;
std::size_t GetDigestLength() const;
const char* GetHashName() const;
std::size_t GetDigestLength() const override;
const char* GetHashName() const override;
private:
HashWhirlpool_state* m_state;

View File

@@ -47,7 +47,17 @@ namespace Nz
};
}
/*!
* \ingroup core
* \class Nz::Initializer
* \brief Core class that represents a module initializer
*/
/*!
* \brief Constructs a Initializer object with a boolean
*
* \param initialize Initialize the module
*/
template<typename... Args>
Initializer<Args...>::Initializer(bool initialize) :
m_initialized(false)
@@ -56,12 +66,22 @@ namespace Nz
Initialize();
}
/*!
* \brief Destructs the object and call Uninitialize
*
* \see Uninitialize
*/
template<typename... Args>
Initializer<Args...>::~Initializer()
{
Uninitialize();
}
/*!
* \brief Initialize the module
*
* \see Uninitialize
*/
template<typename... Args>
bool Initializer<Args...>::Initialize()
{
@@ -71,12 +91,21 @@ namespace Nz
return m_initialized;
}
/*!
* \brief Checks whether the module is initialized
* \return true if initialized
*/
template<typename... Args>
bool Initializer<Args...>::IsInitialized() const
{
return m_initialized;
}
/*!
* \brief Uninitialize the module
*
* \see Initialize
*/
template<typename... Args>
void Initializer<Args...>::Uninitialize()
{
@@ -84,6 +113,10 @@ namespace Nz
Detail::Initializer<Args...>::Uninit();
}
/*!
* \brief Converts the initializer to boolean
* \return true if initialized
*/
template<typename... Args>
Initializer<Args...>::operator bool() const
{

View File

@@ -13,15 +13,22 @@ namespace Nz
{
class Mutex;
class NAZARA_CORE_API LockGuard
class LockGuard
{
public:
LockGuard(Mutex& mutex);
~LockGuard();
inline LockGuard(Mutex& mutex, bool lock = true);
inline ~LockGuard();
inline void Lock();
inline bool TryLock();
inline void Unlock();
private:
Mutex& m_mutex;
bool m_locked;
};
}
#include <Nazara/Core/LockGuard.inl>
#endif // NAZARA_LOCKGUARD_HPP

View File

@@ -0,0 +1,83 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::LockGuard
* \brief Core class that represents a mutex wrapper that provides a convenient RAII-style mechanism
*/
/*!
* \brief Constructs a LockGuard object with a mutex
*
* \param mutex Mutex to lock
* \param lock Should the mutex be locked by the constructor
*/
inline LockGuard::LockGuard(Mutex& mutex, bool lock) :
m_mutex(mutex),
m_locked(false)
{
if (lock)
{
m_mutex.Lock();
m_locked = true;
}
}
/*!
* \brief Destructs a LockGuard object and unlocks the mutex if it was previously locked
*/
inline LockGuard::~LockGuard()
{
if (m_locked)
m_mutex.Unlock();
}
/*!
* \brief Locks the underlying mutex
*
* \see Mutex::Lock
*/
inline void LockGuard::Lock()
{
NazaraAssert(!m_locked, "Mutex is already locked");
m_mutex.Lock();
}
/*!
* \brief Tries to lock the underlying mutex
*
* \see Mutex::TryLock
*
* \return true if the lock was acquired successfully
*/
inline bool LockGuard::TryLock()
{
NazaraAssert(!m_locked, "Mutex is already locked");
return m_mutex.TryLock();
}
/*!
* \brief Unlocks the underlying mutex
*
* \see Mutex::Unlock
*/
inline void LockGuard::Unlock()
{
NazaraAssert(m_locked, "Mutex is not locked");
m_mutex.Unlock();
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -2,7 +2,7 @@
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Je ne suis pas fier des cinq lignes qui suivent mais difficile de faire autrement pour le moment...
// I'm not proud of those five following lines but ti's hard to do with another way now
#ifdef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION
#define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED
#else
@@ -16,6 +16,17 @@
namespace Nz
{
/*!
* \ingroup core
* \fn Nz::MemoryHelper
* \brief Core functions that helps the handle of memory in the engine
*/
/*!
* \brief Calls the operator delete on the pointer
*
* \remark Uses MemoryManager with NAZARA_CORE_MANAGE_MEMORY defined else operator delete
*/
inline void OperatorDelete(void* ptr)
{
#if NAZARA_CORE_MANAGE_MEMORY
@@ -25,6 +36,11 @@ namespace Nz
#endif
}
/*!
* \brief Calls the operator new on the pointer
*
* \remark Uses MemoryManager with NAZARA_CORE_MANAGE_MEMORY defined else operator new
*/
inline void* OperatorNew(std::size_t size)
{
#if NAZARA_CORE_MANAGE_MEMORY
@@ -34,6 +50,13 @@ namespace Nz
#endif
}
/*!
* \brief Constructs the object inplace
* \return Pointer to the constructed object
*
* \param ptr Pointer to raw memory allocated
* \param args Arguments for the constructor
*/
template<typename T, typename... Args>
T* PlacementNew(void* ptr, Args&&... args)
{
@@ -43,7 +66,7 @@ namespace Nz
#include <Nazara/Core/DebugOff.hpp>
// Si c'est nous qui avons défini la constante, alors il nous faut l'enlever (Pour éviter que le moteur entier n'en souffre)
// If we have defined the constant, then we have to undefine it (to avoid bloating in the engine)
#ifndef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED
#undef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION
#endif

View File

@@ -37,7 +37,7 @@ namespace Nz
private:
MemoryPool(MemoryPool* pool);
std::unique_ptr<void*[]> m_freeList;
std::unique_ptr<void* []> m_freeList;
std::unique_ptr<UInt8[]> m_pool;
std::unique_ptr<MemoryPool> m_next;
std::atomic_uint m_freeCount;

View File

@@ -4,10 +4,25 @@
#include <Nazara/Core/MemoryHelper.hpp>
#include <utility>
#include <stdexcept>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::MemoryPool
* \brief Core class that represents a memory pool
*/
/*!
* \brief Constructs a MemoryPool object
*
* \param blockSize Size of blocks that will be allocated
* \param size Size of the pool
* \param canGrow Determine if the pool can allocate more memory
*/
inline MemoryPool::MemoryPool(unsigned int blockSize, unsigned int size, bool canGrow) :
m_freeCount(size),
m_previous(nullptr),
@@ -16,27 +31,47 @@ namespace Nz
m_size(size)
{
m_pool.reset(new UInt8[blockSize * size]);
m_freeList.reset(new void*[size]);
m_freeList.reset(new void* [size]);
// Remplissage de la free list
for (unsigned int i = 0; i < size; ++i)
m_freeList[i] = &m_pool[m_blockSize * (size-i-1)];
}
/*!
* \brief Constructs a MemoryPool object by move semantic
*
* \param pool MemoryPool to move into this
*/
inline MemoryPool::MemoryPool(MemoryPool&& pool) noexcept
{
operator=(std::move(pool));
}
/*!
* \brief Constructs a MemoryPool object by chaining memory pool
*
* \param pool Previous MemoryPool
*/
inline MemoryPool::MemoryPool(MemoryPool* pool) :
MemoryPool(pool->m_blockSize, pool->m_size, pool->m_canGrow)
{
m_previous = pool;
}
/*!
* \brief Allocates enough memory for the size and returns a pointer to it
* \return A pointer to memory allocated
*
* \param size Size to allocate
*
* \remark If the size is greather than the blockSize of pool, new operator is called
*/
inline void* MemoryPool::Allocate(unsigned int size)
{
///DOC: Si la taille est supérieure à celle d'un bloc du pool, l'opérateur new est utilisé
if (size <= m_blockSize)
{
if (m_freeCount > 0)
@@ -53,10 +88,17 @@ namespace Nz
return OperatorNew(size);
}
/*!
* \brief Deletes the memory represented by the poiner
*
* Calls the destructor of the object before releasing it
*
* \remark If ptr is null, nothing is done
*/
template<typename T>
inline void MemoryPool::Delete(T* ptr)
{
///DOC: Va appeler le destructeur de l'objet avant de le libérer
if (ptr)
{
ptr->~T();
@@ -64,12 +106,20 @@ namespace Nz
}
}
/*!
* \brief Frees the memory represented by the poiner
*
* If the pool gets empty after the call and we are the child of another pool, we commit suicide. If the pointer does not own to a block of the pool, operator delete is called
*
* \remark Throws a std::runtime_error if pointer does not point to an element of the pool with NAZARA_CORE_SAFE defined
* \remark If ptr is null, nothing is done
*/
inline void MemoryPool::Free(void* ptr)
{
///DOC: Si appelé avec un pointeur ne faisant pas partie du pool, l'opérateur delete est utilisé
if (ptr)
{
// Le pointeur nous appartient-il ?
// Does the pointer belong to us ?
UInt8* freePtr = static_cast<UInt8*>(ptr);
UInt8* poolPtr = m_pool.get();
if (freePtr >= poolPtr && freePtr < poolPtr + m_blockSize*m_size)
@@ -81,7 +131,7 @@ namespace Nz
m_freeList[m_freeCount++] = ptr;
// Si nous sommes vide et l'extension d'un autre pool, nous nous suicidons
// If we are empty and the extension of another pool, we commit suicide
if (m_freeCount == m_size && m_previous && !m_next)
{
m_previous->m_next.release();
@@ -98,31 +148,61 @@ namespace Nz
}
}
/*!
* \brief Gets the block size
* \return Size of the blocks
*/
inline unsigned int MemoryPool::GetBlockSize() const
{
return m_blockSize;
}
/*!
* \brief Gets the number of free blocks
* \return Number of free blocks in the pool
*/
inline unsigned int MemoryPool::GetFreeBlocks() const
{
return m_freeCount;
}
/*!
* \brief Gets the pool size
* \return Size of the pool
*/
inline unsigned int MemoryPool::GetSize() const
{
return m_size;
}
/*!
* \brief Creates a new value of type T with arguments
* \return Pointer to the allocated object
*
* \param args Arguments for the new object
*
* \remark Constructs inplace in the pool
*/
template<typename T, typename... Args>
inline T* MemoryPool::New(Args&&... args)
{
///DOC: Permet de construire un objet directement dans le pook
T* object = static_cast<T*>(Allocate(sizeof(T)));
PlacementNew<T>(object, std::forward<Args>(args)...);
return object;
}
/*!
* \brief Assigns the content of another pool by move semantic
* \return A reference to this
*
* \param pool Other pool to move into this
*/
inline MemoryPool& MemoryPool::operator=(MemoryPool&& pool) noexcept
{
m_blockSize = pool.m_blockSize;
@@ -134,7 +214,7 @@ namespace Nz
m_next = std::move(pool.m_next);
m_size = pool.m_size;
// Si nous avons été créés par un autre pool, nous devons le faire pointer vers nous de nouveau
// If we have been created by another pool, we must make it point to us again
if (m_previous)
{
m_previous->m_next.release();

View File

@@ -0,0 +1,53 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_MEMORYSTREAM_HPP
#define NAZARA_MEMORYSTREAM_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Stream.hpp>
namespace Nz
{
class ByteArray;
class NAZARA_CORE_API MemoryStream : public Stream
{
public:
inline MemoryStream();
inline MemoryStream(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite);
MemoryStream(const MemoryStream&) = default;
MemoryStream(MemoryStream&&) = default;
~MemoryStream() = default;
void Clear();
bool EndOfStream() const override;
inline ByteArray& GetBuffer();
inline const ByteArray& GetBuffer() const;
UInt64 GetCursorPos() const override;
UInt64 GetSize() const override;
void SetBuffer(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite);
bool SetCursorPos(UInt64 offset) override;
MemoryStream& operator=(const MemoryStream&) = default;
MemoryStream& operator=(MemoryStream&&) = default;
private:
void FlushStream() override;
std::size_t ReadBlock(void* buffer, std::size_t size) override;
std::size_t WriteBlock(const void* buffer, std::size_t size) override;
ByteArray* m_buffer;
UInt64 m_pos;
};
}
#include <Nazara/Core/MemoryStream.inl>
#endif // NAZARA_MEMORYSTREAM_HPP

View File

@@ -0,0 +1,60 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::MemoryStream
* \brief Constructs a MemoryStream object by default
*/
inline MemoryStream::MemoryStream() :
Stream(StreamOption_None, OpenMode_ReadWrite),
m_pos(0)
{
}
/*!
* \brief Constructs a MemoryStream object with a byte array
*
* \param byteArray Bytes to stream
* \param openMode Reading/writing mode for the stream
*/
inline MemoryStream::MemoryStream(ByteArray* byteArray, UInt32 openMode) :
MemoryStream()
{
SetBuffer(byteArray, openMode);
}
/*!
* \brief Gets the internal buffer
* \return Buffer of bytes
*
* \remark Produces a NazaraAssert if buffer is invalid
*/
inline ByteArray& MemoryStream::GetBuffer()
{
NazaraAssert(m_buffer, "Invalid buffer");
return *m_buffer;
}
/*!
* \brief Gets the internal buffer
* \return Buffer of bytes
*
* \remark Produces a NazaraAssert if buffer is invalid
*/
inline const ByteArray& MemoryStream::GetBuffer() const
{
NazaraAssert(m_buffer, "Invalid buffer");
return *m_buffer;
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -15,6 +15,7 @@ namespace Nz
class NAZARA_CORE_API MemoryView : public Stream
{
public:
MemoryView(void* ptr, UInt64 size);
MemoryView(const void* ptr, UInt64 size);
MemoryView(const MemoryView&) = delete;
MemoryView(MemoryView&&) = delete; ///TODO
@@ -31,11 +32,11 @@ namespace Nz
MemoryView& operator=(MemoryView&&) = delete; ///TODO
private:
void FlushStream() override;
void FlushStream() override;
std::size_t ReadBlock(void* buffer, std::size_t size) override;
std::size_t WriteBlock(const void* buffer, std::size_t size) override;
const UInt8* m_ptr;
UInt8* m_ptr;
UInt64 m_pos;
UInt64 m_size;
};

View File

@@ -20,7 +20,7 @@ namespace Nz
public:
Mutex();
Mutex(const Mutex&) = delete;
Mutex(Mutex&&) = delete; ///TODO
inline Mutex(Mutex&& mutex) noexcept;
~Mutex();
void Lock();
@@ -28,11 +28,13 @@ namespace Nz
void Unlock();
Mutex& operator=(const Mutex&) = delete;
Mutex& operator=(Mutex&&) = delete; ///TODO
Mutex& operator=(Mutex&& mutex) noexcept;
private:
MutexImpl* m_impl;
};
}
#include <Nazara/Core/Mutex.inl>
#endif // NAZARA_MUTEX_HPP

View File

@@ -0,0 +1,26 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::Mutex
*/
/*!
* \brief Constructs a Mutex object by moving another one
*/
inline Mutex::Mutex(Mutex&& mutex) noexcept :
m_impl(mutex.m_impl)
{
mutex.m_impl = nullptr;
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -0,0 +1,93 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_OBJECTHANDLE_HPP
#define NAZARA_OBJECTHANDLE_HPP
#include <Nazara/Core/Algorithm.hpp>
#include <ostream>
namespace Nz
{
template<typename T> class HandledObject;
template<typename T>
class ObjectHandle
{
friend HandledObject<T>;
public:
ObjectHandle();
explicit ObjectHandle(T* object);
ObjectHandle(const ObjectHandle& handle);
~ObjectHandle();
T* GetObject() const;
bool IsValid() const;
void Reset(T* object = nullptr);
void Reset(const ObjectHandle& handle);
ObjectHandle& Swap(ObjectHandle& handle);
Nz::String ToString() const;
operator bool() const;
operator T*() const;
T* operator->() const;
ObjectHandle& operator=(T* object);
ObjectHandle& operator=(const ObjectHandle& handle);
static const ObjectHandle InvalidHandle;
protected:
void OnObjectDestroyed();
void OnObjectMoved(T* newObject);
T* m_object;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const ObjectHandle<T>& handle);
template<typename T> bool operator==(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator==(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator==(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator!=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator!=(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator!=(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator<(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator<(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator<(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator<=(const ObjectHandle<T>, const ObjectHandle<T>& rhs);
template<typename T> bool operator<=(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator<=(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator>(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>=(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> struct PointedType<ObjectHandle<T>> { typedef T type; };
template<typename T> struct PointedType<const ObjectHandle<T>> { typedef T type; };
}
namespace std
{
template<typename T>
void swap(Nz::ObjectHandle<T>& lhs, Nz::ObjectHandle<T>& rhs);
}
#include <Nazara/Core/ObjectHandle.inl>
#endif // NAZARA_OBJECTHANDLE_HPP

View File

@@ -0,0 +1,280 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/ObjectHandle.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <functional>
#include <limits>
namespace Nz
{
template<typename T>
ObjectHandle<T>::ObjectHandle() :
m_object(nullptr)
{
}
template<typename T>
ObjectHandle<T>::ObjectHandle(T* object) :
ObjectHandle()
{
Reset(object);
}
template<typename T>
ObjectHandle<T>::ObjectHandle(const ObjectHandle<T>& handle) :
ObjectHandle()
{
Reset(handle);
}
template<typename T>
ObjectHandle<T>::~ObjectHandle()
{
Reset(nullptr);
}
template<typename T>
T* ObjectHandle<T>::GetObject() const
{
return m_object;
}
template<typename T>
bool ObjectHandle<T>::IsValid() const
{
return m_object != nullptr;
}
template<typename T>
void ObjectHandle<T>::Reset(T* object)
{
// Si nous avions déjà une entité, nous devons l'informer que nous ne pointons plus sur elle
if (m_object)
m_object->UnregisterHandle(this);
m_object = object;
if (m_object)
// On informe la nouvelle entité que nous pointons sur elle
m_object->RegisterHandle(this);
}
template<typename T>
void ObjectHandle<T>::Reset(const ObjectHandle<T>& handle)
{
Reset(handle.GetObject());
}
template<typename T>
ObjectHandle<T>& ObjectHandle<T>::Swap(ObjectHandle<T>& handle)
{
// Comme nous inversons les handles, nous devons prévenir les entités
// La version par défaut de swap (à base de move) aurait fonctionné,
// mais en enregistrant les handles une fois de plus que nécessaire (à cause de la copie temporaire).
if (m_object)
{
m_object->UnregisterHandle(this);
m_object->RegisterHandle(&handle);
}
if (handle.m_object)
{
handle.m_object->UnregisterHandle(&handle);
handle.m_object->RegisterHandle(this);
}
// On effectue l'échange
std::swap(m_object, handle.m_object);
return *this;
}
template<typename T>
Nz::String ObjectHandle<T>::ToString() const
{
Nz::StringStream ss;
ss << "ObjectHandle(";
if (IsValid())
ss << m_object->ToString();
else
ss << "Null";
ss << ')';
return ss;
}
template<typename T>
ObjectHandle<T>::operator bool() const
{
return IsValid();
}
template<typename T>
ObjectHandle<T>::operator T*() const
{
return m_object;
}
template<typename T>
T* ObjectHandle<T>::operator->() const
{
return m_object;
}
template<typename T>
ObjectHandle<T>& ObjectHandle<T>::operator=(T* entity)
{
Reset(entity);
return *this;
}
template<typename T>
ObjectHandle<T>& ObjectHandle<T>::operator=(const ObjectHandle<T>& handle)
{
Reset(handle);
return *this;
}
template<typename T>
void ObjectHandle<T>::OnObjectDestroyed()
{
// Shortcut
m_object = nullptr;
}
template<typename T>
void ObjectHandle<T>::OnObjectMoved(T* newObject)
{
// The object has been moved, update our pointer
m_object = newObject;
}
template<typename T>
std::ostream& operator<<(std::ostream& out, const ObjectHandle<T>& handle)
{
return handle.ToString();
}
template<typename T>
bool operator==(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return lhs.GetObject() == rhs.GetObject();
}
template<typename T>
bool operator==(const T& lhs, const ObjectHandle<T>& rhs)
{
return &lhs == rhs.GetObject();
}
template<typename T>
bool operator==(const ObjectHandle<T>& lhs, const T& rhs)
{
return lhs.GetObject() == &rhs;
}
template<typename T>
bool operator!=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs == rhs);
}
template<typename T>
bool operator!=(const T& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs == rhs);
}
template<typename T>
bool operator!=(const ObjectHandle<T>& lhs, const T& rhs)
{
return !(lhs == rhs);
}
template<typename T>
bool operator<(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return lhs.m_object < rhs.m_object;
}
template<typename T>
bool operator<(const T& lhs, const ObjectHandle<T>& rhs)
{
return &lhs < rhs.m_object;
}
template<typename T>
bool operator<(const ObjectHandle<T>& lhs, const T& rhs)
{
return lhs.m_object < &rhs;
}
template<typename T>
bool operator<=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs > rhs);
}
template<typename T>
bool operator<=(const T& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs > rhs);
}
template<typename T>
bool operator<=(const ObjectHandle<T>& lhs, const T& rhs)
{
return !(lhs > rhs);
}
template<typename T>
bool operator>(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return rhs < lhs;
}
template<typename T>
bool operator>(const T& lhs, const ObjectHandle<T>& rhs)
{
return rhs < lhs;
}
template<typename T>
bool operator>(const ObjectHandle<T>& lhs, const T& rhs)
{
return rhs < lhs;
}
template<typename T>
bool operator>=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs < rhs);
}
template<typename T>
bool operator>=(const T& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs < rhs);
}
template<typename T>
bool operator>=(const ObjectHandle<T>& lhs, const T& rhs)
{
return !(lhs < rhs);
}
template<typename T>
const ObjectHandle<T> ObjectHandle<T>::InvalidHandle;
}
namespace std
{
template<typename T>
void swap(Nz::ObjectHandle<T>& lhs, Nz::ObjectHandle<T>& rhs)
{
lhs.Swap(rhs);
}
}

View File

@@ -7,6 +7,20 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::ObjectRef
* \brief Core class that represents a reference to an object
*/
/*!
* \brief Gets the ObjectRef object by name
* \return Optional reference
*
* \param name Name of the object
*
* \remark Produces a NazaraError if object not found
*/
template<typename Type>
ObjectRef<Type> ObjectLibrary<Type>::Get(const String& name)
{
@@ -17,18 +31,34 @@ namespace Nz
return ref;
}
/*!
* \brief Checks whether the library has the object with that name
* \return true if it the case
*/
template<typename Type>
bool ObjectLibrary<Type>::Has(const String& name)
{
return Type::s_library.find(name) != Type::s_library.end();
}
/*!
* \brief Registers the ObjectRef object with that name
*
* \param name Name of the object
* \param object Object to stock
*/
template<typename Type>
void ObjectLibrary<Type>::Register(const String& name, ObjectRef<Type> object)
{
Type::s_library.emplace(name, object);
}
/*!
* \brief Gets the ObjectRef object by name
* \return Optional reference
*
* \param name Name of the object
*/
template<typename Type>
ObjectRef<Type> ObjectLibrary<Type>::Query(const String& name)
{
@@ -39,6 +69,11 @@ namespace Nz
return nullptr;
}
/*!
* \brief Unregisters the ObjectRef object with that name
*
* \param name Name of the object
*/
template<typename Type>
void ObjectLibrary<Type>::Unregister(const String& name)
{
@@ -48,7 +83,7 @@ namespace Nz
template<typename Type>
bool ObjectLibrary<Type>::Initialize()
{
return true; // Que faire
return true; // Nothing to do
}
template<typename Type>

View File

@@ -8,6 +8,7 @@
#define NAZARA_RESOURCEREF_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/RefCounted.hpp>
#include <type_traits>
@@ -42,6 +43,9 @@ namespace Nz
private:
T* m_object;
};
template<typename T> struct PointedType<ObjectRef<T>> {typedef T type;};
template<typename T> struct PointedType<ObjectRef<T> const> {typedef T type;};
}
#include <Nazara/Core/ObjectRef.inl>

View File

@@ -7,12 +7,26 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::ObjectRef
* \brief Core class that represents a reference to an object
*/
/*!
* \brief Constructs a ObjectRef object by default
*/
template<typename T>
ObjectRef<T>::ObjectRef() :
m_object(nullptr)
{
}
/*!
* \brief Constructs a ObjectRef object with a pointer to an object
*
* \param object Pointer to handle like a reference (can be nullptr)
*/
template<typename T>
ObjectRef<T>::ObjectRef(T* object) :
m_object(object)
@@ -21,6 +35,11 @@ namespace Nz
m_object->AddReference();
}
/*!
* \brief Constructs a ObjectRef object by assignation
*
* \param ref ObjectRef to assign into this
*/
template<typename T>
ObjectRef<T>::ObjectRef(const ObjectRef& ref) :
m_object(ref.m_object)
@@ -29,6 +48,11 @@ namespace Nz
m_object->AddReference();
}
/*!
* \brief Constructs a ObjectRef<U> object from another type of ObjectRef
*
* \param ref ObjectRef of type U to convert to type T
*/
template<typename T>
template<typename U>
ObjectRef<T>::ObjectRef(const ObjectRef<U>& ref) :
@@ -36,13 +60,21 @@ namespace Nz
{
}
/*!
* \brief Constructs a ObjectRef object by move semantic
*
* \param ref ObjectRef to move into this
*/
template<typename T>
ObjectRef<T>::ObjectRef(ObjectRef&& ref) noexcept :
m_object(ref.m_object)
{
ref.m_object = nullptr; // On vole la référence
ref.m_object = nullptr; // We steal the reference
}
/*!
* \brief Destructs the object (remove a reference to the object when shared)
*/
template<typename T>
ObjectRef<T>::~ObjectRef()
{
@@ -50,27 +82,46 @@ namespace Nz
m_object->RemoveReference();
}
/*!
* \brief Gets the underlying pointer
* \return Underlying pointer
*/
template<typename T>
T* ObjectRef<T>::Get() const
{
return m_object;
}
/*!
* \brief Checks whether the reference is valid
* \return true if reference is not nullptr
*/
template<typename T>
bool ObjectRef<T>::IsValid() const
{
return m_object != nullptr;
}
/*!
* \brief Releases the handle of the pointer
* \return Underlying pointer
*/
template<typename T>
T* ObjectRef<T>::Release()
{
if (m_object)
m_object->RemoveReference();
T* object = m_object;
m_object = nullptr;
return object;
}
/*!
* \brief Resets the content of the ObjectRef with another pointer
* \return true if old handle is destroyed
*/
template<typename T>
bool ObjectRef<T>::Reset(T* object)
{
@@ -88,6 +139,12 @@ namespace Nz
return destroyed;
}
/*!
* \brief Swaps the content of the two ObjectRef
* \return A reference to this
*
* \param ref ObjectRef to swap
*/
template<typename T>
ObjectRef<T>& ObjectRef<T>::Swap(ObjectRef& ref)
{
@@ -96,24 +153,44 @@ namespace Nz
return *this;
}
/*!
* \brief Converts the ObjectRef to bool
* \return true if reference is not nullptr
*
* \see IsValid
*/
template<typename T>
ObjectRef<T>::operator bool() const
{
return IsValid();
}
/*!
* \brief Dereferences the ObjectRef
* \return Underlying pointer
*/
template<typename T>
ObjectRef<T>::operator T*() const
{
return m_object;
}
/*!
* \brief Dereferences the ObjectRef
* \return Underlying pointer
*/
template<typename T>
T* ObjectRef<T>::operator->() const
{
return m_object;
}
/*!
* \brief Assigns the object into this
* \return A reference to this
*
* \param object Pointer to handle like a reference (can be nullptr)
*/
template<typename T>
ObjectRef<T>& ObjectRef<T>::operator=(T* object)
{
@@ -122,6 +199,12 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the reference of the ObjectRef with the handle from another
* \return A reference to this
*
* \param ref The other ObjectRef
*/
template<typename T>
ObjectRef<T>& ObjectRef<T>::operator=(const ObjectRef& ref)
{
@@ -130,6 +213,12 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the reference of the ObjectRef from another type of ObjectRef
* \return A reference to this
*
* \param ref ObjectRef of type U to convert
*/
template<typename T>
template<typename U>
ObjectRef<T>& ObjectRef<T>::operator=(const ObjectRef<U>& ref)
@@ -141,6 +230,12 @@ namespace Nz
return *this;
}
/*!
* \brief Moves the ObjectRef into this
* \return A reference to this
*
* \param ref ObjectRef to move in this
*/
template<typename T>
ObjectRef<T>& ObjectRef<T>::operator=(ObjectRef&& ref) noexcept
{
@@ -152,4 +247,24 @@ namespace Nz
}
}
namespace std
{
/*!
* \ingroup core
* \brief Gives a hash representation of the object, specialisation of std
* \return Hash of the ObjectRef
*
* \param object Object to hash
*/
template<typename T>
struct hash<Nz::ObjectRef<T>>
{
size_t operator()(const Nz::ObjectRef<T>& object) const
{
hash<T*> h;
return h(object.Get());
}
};
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -7,7 +7,7 @@
#ifndef NAZARA_OFFSETOF_HPP
#define NAZARA_OFFSETOF_HPP
// Par "Jesse Good" de SO:
// By "Jesse Good" from SO:
// http://stackoverflow.com/questions/12811330/c-compile-time-offsetof-inside-a-template?answertab=votes#tab-top
namespace Nz

View File

@@ -86,10 +86,10 @@ namespace Nz
Value value;
};
using ParameterMap = std::unordered_map<String, Parameter>;
Parameter& CreateValue(const String& name);
void DestroyValue(Parameter& parameter);
using ParameterMap = std::unordered_map<String, Parameter>;
ParameterMap m_parameters;
};
}

View File

@@ -13,7 +13,7 @@
#include <set>
#include <unordered_map>
///TODO: Révision
///TODO: Revision
namespace Nz
{
class DynLib;

View File

@@ -6,6 +6,20 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::PrimitiveList
* \brief Core class that represents a geometric primitive
*/
/*!
* \brief Makes a box centered
*
* \param lengths (Width, Height, Depht)
* \param subdivision Number of subdivision for the axis
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeBox(const Vector3f& lengths, const Vector3ui& subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
matrix = transformMatrix;
@@ -15,11 +29,29 @@ namespace Nz
box.subdivision = subdivision;
}
/*!
* \brief Makes a box centered
*
* \param lengths (Width, Height, Depht)
* \param subdivision Number of subdivision for the axis
* \param position Position of the box
* \param rotation Rotation of the box
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeBox(const Vector3f& lengths, const Vector3ui& subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
MakeBox(lengths, subdivision, Matrix4f::Transform(position, rotation), uvCoords);
}
/*!
* \brief Makes a cone, centered in (0, 0, 0) and circle in (0, -length, 0)
*
* \param length Height of the cone
* \param radius Width of the radius
* \param subdivision Number of sides for the circle
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeCone(float length, float radius, unsigned int subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
matrix = transformMatrix;
@@ -30,11 +62,29 @@ namespace Nz
cone.subdivision = subdivision;
}
/*!
* \brief Makes a cone, centered in (0, 0, 0) and circle in (0, -length, 0)
*
* \param length Height of the cone
* \param radius Width of the radius
* \param subdivision Number of sides for the circle
* \param position Position of the cone
* \param rotation Rotation of the cone
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeCone(float length, float radius, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
MakeCone(length, radius, subdivision, Matrix4f::Transform(position, rotation), uvCoords);
}
/*!
* \brief Makes a cubic sphere, centered in (0, 0, 0)
*
* \param size Radius of the cubic sphere
* \param subdivision Number of subdivision for the box
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeCubicSphere(float size, unsigned int subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
matrix = transformMatrix;
@@ -45,11 +95,28 @@ namespace Nz
sphere.cubic.subdivision = subdivision;
}
/*!
* \brief Adds a cubic sphere, centered in (0, 0, 0)
*
* \param size Radius of the cubic sphere
* \param subdivision Number of subdivision for the box
* \param position Position of the cubic sphere
* \param rotation Rotation of the cubic sphere
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeCubicSphere(float size, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
MakeCubicSphere(size, subdivision, Matrix4f::Transform(position, rotation), uvCoords);
}
/*!
* \brief Makes a icosphere, centered in (0, 0, 0)
*
* \param size Radius of the icosphere
* \param recursionLevel Number of recursion for the icosphere
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeIcoSphere(float size, unsigned int recursionLevel, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
matrix = transformMatrix;
@@ -60,11 +127,28 @@ namespace Nz
sphere.ico.recursionLevel = recursionLevel;
}
/*!
* \brief Makes a icosphere, centered in (0, 0, 0)
*
* \param size Radius of the sphere
* \param recursionLevel Number of recursion for the icosphere
* \param position Position of the icosphere
* \param rotation Rotation of the icosphere
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeIcoSphere(float size, unsigned int recursionLevel, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
MakeIcoSphere(size, recursionLevel, Matrix4f::Transform(position, rotation), uvCoords);
}
/*!
* \brief Makes a plane, centered in (0, 0, 0)
*
* \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakePlane(const Vector2f& size, const Vector2ui& subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
matrix = transformMatrix;
@@ -74,16 +158,42 @@ namespace Nz
plane.subdivision = subdivision;
}
/*!
* \brief Makes a plane, centered in (0, 0, 0)
*
* \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis
* \param planeInfo Information for the plane
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakePlane(const Vector2f& size, const Vector2ui& subdivision, const Planef& planeInfo, const Rectf& uvCoords)
{
MakePlane(size, subdivision, Matrix4f::Transform(planeInfo.distance * planeInfo.normal, Quaternionf::RotationBetween(Vector3f::Up(), planeInfo.normal)), uvCoords);
}
/*!
* \brief Makes a plane, centered in (0, 0, 0)
*
* \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis
* \param position Position of the plane
* \param rotation Rotation of the plane
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakePlane(const Vector2f& size, const Vector2ui& subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
MakePlane(size, subdivision, Matrix4f::Transform(position, rotation), uvCoords);
}
/*!
* \brief Makes a UV sphere, centered in (0, 0, 0)
*
* \param size Radius of the sphere
* \param sliceCount Number of slices
* \param stackCount Number of stacks
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
matrix = transformMatrix;
@@ -95,11 +205,30 @@ namespace Nz
sphere.uv.stackCount = stackCount;
}
/*!
* \brief Makes a UV sphere, centered in (0, 0, 0)
*
* \param size Radius of the sphere
* \param sliceCount Number of slices
* \param stackCount Number of stacks
* \param position Position of the box
* \param rotation Rotation of the box
* \param uvCoords Coordinates for texture
*/
inline void Primitive::MakeUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
MakeUVSphere(size, sliceCount, stackCount, Matrix4f::Transform(position, rotation), uvCoords);
}
/*!
* \brief Creates a box centered
* \return Primitive which is a box
*
* \param lengths (Width, Height, Depht)
* \param subdivision Number of subdivision for the axis
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::Box(const Vector3f& lengths, const Vector3ui& subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
Primitive primitive;
@@ -108,6 +237,16 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a box centered
* \return Primitive which is a box
*
* \param lengths (Width, Height, Depht)
* \param subdivision Number of subdivision for the axis
* \param position Position of the box
* \param rotation Rotation of the box
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::Box(const Vector3f& lengths, const Vector3ui& subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
Primitive primitive;
@@ -116,6 +255,16 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a cone, centered in (0, 0, 0) and circle in (0, -length, 0)
* \return Primitive which is a cone
*
* \param length Height of the cone
* \param radius Width of the radius
* \param subdivision Number of sides for the circle
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::Cone(float length, float radius, unsigned int subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
Primitive primitive;
@@ -124,6 +273,17 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a cone, centered in (0, 0, 0) and circle in (0, -length, 0)
* \return Primitive which is a cone
*
* \param length Height of the cone
* \param radius Width of the radius
* \param subdivision Number of sides for the circle
* \param position Position of the cone
* \param rotation Rotation of the cone
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::Cone(float length, float radius, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
Primitive primitive;
@@ -132,6 +292,15 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a cubic sphere, centered in (0, 0, 0)
* \return Primitive which is a cubic sphere
*
* \param size Radius of the cubic sphere
* \param subdivision Number of subdivision for the box
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::CubicSphere(float size, unsigned int subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
Primitive primitive;
@@ -140,6 +309,16 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a cubic sphere, centered in (0, 0, 0)
* \return Primitive which is a cubic sphere
*
* \param size Radius of the cubic sphere
* \param subdivision Number of subdivision for the box
* \param position Position of the cubic sphere
* \param rotation Rotation of the cubic sphere
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::CubicSphere(float size, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
Primitive primitive;
@@ -148,6 +327,15 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a icosphere, centered in (0, 0, 0)
* \return Primitive which is a icosphere
*
* \param size Radius of the icosphere
* \param recursionLevel Number of recursion for the icosphere
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::IcoSphere(float size, unsigned int recursionLevel, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
Primitive primitive;
@@ -156,6 +344,16 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a icosphere, centered in (0, 0, 0)
* \return Primitive which is a icosphere
*
* \param size Radius of the sphere
* \param recursionLevel Number of recursion for the icosphere
* \param position Position of the icosphere
* \param rotation Rotation of the icosphere
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::IcoSphere(float size, unsigned int recursionLevel, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
Primitive primitive;
@@ -164,6 +362,15 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a plane, centered in (0, 0, 0)
* \return Primitive which is a plane
*
* \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::Plane(const Vector2f& size, const Vector2ui& subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
Primitive primitive;
@@ -172,6 +379,15 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a plane, centered in (0, 0, 0)
* \return Primitive which is a plane
*
* \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis
* \param planeInfo Information for the plane
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::Plane(const Vector2f& size, const Vector2ui& subdivision, const Planef& plane, const Rectf& uvCoords)
{
Primitive primitive;
@@ -180,6 +396,16 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a plane, centered in (0, 0, 0)
* \return Primitive which is a plane
*
* \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis
* \param position Position of the plane
* \param rotation Rotation of the plane
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::Plane(const Vector2f& size, const Vector2ui& subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
Primitive primitive;
@@ -188,6 +414,16 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a UV sphere, centered in (0, 0, 0)
* \return Primitive which is a uv sphere
*
* \param size Radius of the sphere
* \param sliceCount Number of slices
* \param stackCount Number of stacks
* \param transformMatrix Matrix to apply
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::UVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Matrix4f& transformMatrix, const Rectf& uvCoords)
{
Primitive primitive;
@@ -196,6 +432,17 @@ namespace Nz
return primitive;
}
/*!
* \brief Creates a UV sphere, centered in (0, 0, 0)
* \return Primitive which is a uv sphere
*
* \param size Radius of the sphere
* \param sliceCount Number of slices
* \param stackCount Number of stacks
* \param position Position of the box
* \param rotation Rotation of the box
* \param uvCoords Coordinates for texture
*/
inline Primitive Primitive::UVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords)
{
Primitive primitive;

View File

@@ -9,6 +9,7 @@
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Core/String.hpp>
#include <list>
#include <tuple>
@@ -21,6 +22,8 @@ namespace Nz
template<typename Type, typename Parameters>
class ResourceLoader
{
static_assert(std::is_base_of<ResourceParameters, Parameters>::value, "ResourceParameters must be a base of Parameters");
friend Type;
public:

View File

@@ -11,6 +11,18 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::ResourceLoader
* \brief Core class that represents a loader of resources
*/
/*!
* \brief Checks whether the extension of the file is supported
* \return true if supported
*
* \param extension Extension of the file
*/
template<typename Type, typename Parameters>
bool ResourceLoader<Type, Parameters>::IsExtensionSupported(const String& extension)
{
@@ -25,16 +37,26 @@ namespace Nz
return false;
}
/*!
* \brief Loads a resource from a file
* \return true if successfully loaded
*
* \param resource Resource to load
* \param filePath Path to the resource
* \param parameters Parameters for the load
*
* \remark Produces a NazaraError if resource is nullptr with NAZARA_CORE_SAFE defined
* \remark Produces a NazaraError if parameters are invalid with NAZARA_CORE_SAFE defined
* \remark Produces a NazaraError if filePath has no extension
* \remark Produces a NazaraError if file count not be opened
* \remark Produces a NazaraWarning if loader failed
* \remark Produces a NazaraError if all loaders failed or no loader was found
*/
template<typename Type, typename Parameters>
bool ResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const String& filePath, const Parameters& parameters)
{
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid parameters");
return false;
}
#endif
NazaraAssert(resource, "Invalid resource");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
String path = File::NormalizePath(filePath);
String ext = path.SubStringFrom('.', -1, true).ToLower();
@@ -122,22 +144,28 @@ namespace Nz
return false;
}
/*!
* \brief Loads a resource from a raw memory, a size and parameters
* \return true if successfully loaded
*
* \param resource Resource to load
* \param data Raw memory of the resource
* \param size Size available for the read
* \param parameters Parameters for the load
*
* \remark Produces a NazaraError if resource is nullptr with NAZARA_CORE_SAFE defined
* \remark Produces a NazaraError if size is 0 with NAZARA_CORE_SAFE defined
* \remark Produces a NazaraError if parameters are invalid with NAZARA_CORE_SAFE defined
* \remark Produces a NazaraWarning if loader failed
* \remark Produces a NazaraError if all loaders failed or no loader was found
*/
template<typename Type, typename Parameters>
bool ResourceLoader<Type, Parameters>::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters)
{
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid parameters");
return false;
}
if (size == 0)
{
NazaraError("No data to load");
return false;
}
#endif
NazaraAssert(resource, "Invalid resource");
NazaraAssert(data, "Invalid data pointer");
NazaraAssert(size, "No data to load");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
MemoryView stream(data, size);
@@ -198,22 +226,26 @@ namespace Nz
return false;
}
/*!
* \brief Loads a resource from a stream and parameters
* \return true if successfully loaded
*
* \param resource Resource to load
* \param stream Stream of the resource
* \param parameters Parameters for the load
*
* \remark Produces a NazaraError if resource is nullptr with NAZARA_CORE_SAFE defined
* \remark Produces a NazaraError if stream has no data with NAZARA_CORE_SAFE defined
* \remark Produces a NazaraError if parameters are invalid with NAZARA_CORE_SAFE defined
* \remark Produces a NazaraWarning if loader failed
* \remark Produces a NazaraError if all loaders failed or no loader was found
*/
template<typename Type, typename Parameters>
bool ResourceLoader<Type, Parameters>::LoadFromStream(Type* resource, Stream& stream, const Parameters& parameters)
{
#if NAZARA_CORE_SAFE
if (!parameters.IsValid())
{
NazaraError("Invalid parameters");
return false;
}
if (stream.GetSize() == 0 || stream.GetCursorPos() >= stream.GetSize())
{
NazaraError("No data to load");
return false;
}
#endif
NazaraAssert(resource, "Invalid resource");
NazaraAssert(stream.GetCursorPos() < stream.GetSize(), "No data to load");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
UInt64 streamPos = stream.GetCursorPos();
bool found = false;
@@ -224,17 +256,17 @@ namespace Nz
stream.SetCursorPos(streamPos);
// Le loader supporte-t-il les données ?
// Does the loader support these data ?
Ternary recognized = checkFunc(stream, parameters);
if (recognized == Ternary_False)
continue;
else if (recognized == Ternary_True)
found = true;
// On repositionne le stream à son ancienne position
// We move the stream to its old position
stream.SetCursorPos(streamPos);
// Chargement de la ressource
// Load of the resource
if (streamLoader(resource, stream, parameters))
return true;
@@ -250,28 +282,33 @@ namespace Nz
return false;
}
/*!
* \brief Registers the loader
*
* \param extensionGetter A function to test whether the extension (as a string) is supported by this loader
* \param checkFunc A function to check the stream with the parser
* \param streamLoader A function to load the data from a stream in the resource
* \param fileLoader Optional function to load the data from a file in the resource
* \param memoryLoader Optional function to load the data from a raw memory in the resource
*/
template<typename Type, typename Parameters>
void ResourceLoader<Type, Parameters>::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader)
{
#if NAZARA_CORE_SAFE
if (streamLoader)
{
if (!checkFunc)
{
NazaraError("StreamLoader present without StreamChecker");
return;
}
}
else if (!fileLoader && !memoryLoader)
{
NazaraError("Neither FileLoader nor MemoryLoader nor StreamLoader were present");
return;
}
#endif
NazaraAssert(checkFunc || !streamLoader, "StreamLoader present without StreamChecker");
NazaraAssert(fileLoader || memoryLoader || streamLoader, "A loader function is mandatory");
Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader));
}
/*!
* \brief Unregisters the loader
*
* \param extensionGetter A function to test whether the extension (as a string) is supported by this loader
* \param checkFunc A function to check the stream with the parser
* \param streamLoader A function to load the data from a stream in the resource
* \param fileLoader Optional function to load the data from a file in the resource
* \param memoryLoader Optional function to load the data from a raw memory in the resource
*/
template<typename Type, typename Parameters>
void ResourceLoader<Type, Parameters>::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader)
{

View File

@@ -8,6 +8,7 @@
#define NAZARA_RESOURCEMANAGER_HPP
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Core/String.hpp>
#include <unordered_map>

View File

@@ -9,12 +9,27 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::ResourceManager
* \brief Core class that represents a resource manager
*/
/*!
* \brief Clears the content of the manager
*/
template<typename Type, typename Parameters>
void ResourceManager<Type, Parameters>::Clear()
{
Type::s_managerMap.clear();
}
/*!
* \brief Gets a reference to the object loaded from file
* \return Reference to the object
*
* \param filePath Path to the asset that will be loaded
*/
template<typename Type, typename Parameters>
ObjectRef<Type> ResourceManager<Type, Parameters>::Get(const String& filePath)
{
@@ -43,12 +58,19 @@ namespace Nz
return it->second;
}
/*!
* \brief Gets the defaults parameters for the load
* \return Default parameters for loading from file
*/
template<typename Type, typename Parameters>
const Parameters& ResourceManager<Type, Parameters>::GetDefaultParameters()
{
return Type::s_managerParameters;
}
/*!
* \brief Purges the resource manager from every asset whose it is the only owner
*/
template<typename Type, typename Parameters>
void ResourceManager<Type, Parameters>::Purge()
{
@@ -56,16 +78,22 @@ namespace Nz
while (it != Type::s_managerMap.end())
{
const ObjectRef<Type>& ref = it->second;
if (ref.GetReferenceCount() == 1) // Sommes-nous les seuls à détenir la ressource ?
if (ref.GetReferenceCount() == 1) // Are we the only ones to own the resource ?
{
NazaraDebug("Purging resource from file " + ref->GetFilePath());
Type::s_managerMap.erase(it++); // Alors on la supprime
Type::s_managerMap.erase(it++); // Then we erase it
}
else
++it;
}
}
/*!
* \brief Registers the resource under the filePath
*
* \param filePath Path for the resource
* \param resource Object to associate with
*/
template<typename Type, typename Parameters>
void ResourceManager<Type, Parameters>::Register(const String& filePath, ObjectRef<Type> resource)
{
@@ -74,12 +102,22 @@ namespace Nz
Type::s_managerMap[absolutePath] = resource;
}
/*!
* \brief Sets the defaults parameters for the load
*
* \param params Default parameters for loading from file
*/
template<typename Type, typename Parameters>
void ResourceManager<Type, Parameters>::SetDefaultParameters(const Parameters& params)
{
Type::s_managerParameters = params;
}
/*!
* \brief Unregisters the resource under the filePath
*
* \param filePath Path for the resource
*/
template<typename Type, typename Parameters>
void ResourceManager<Type, Parameters>::Unregister(const String& filePath)
{
@@ -88,12 +126,19 @@ namespace Nz
Type::s_managerMap.erase(absolutePath);
}
/*!
* \brief Initializes the resource manager
* \return true
*/
template<typename Type, typename Parameters>
bool ResourceManager<Type, Parameters>::Initialize()
{
return true;
}
/*!
* \brief Uninitialize the resource manager
*/
template<typename Type, typename Parameters>
void ResourceManager<Type, Parameters>::Uninitialize()
{

View File

@@ -0,0 +1,20 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RESOURCEPARAMETERS_HPP
#define NAZARA_RESOURCEPARAMETERS_HPP
#include <Nazara/Core/ParameterList.hpp>
namespace Nz
{
struct ResourceParameters
{
ParameterList custom;
};
}
#endif // NAZARA_RESOURCEPARAMETERS_HPP

View File

@@ -0,0 +1,54 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RESOURCESAVER_HPP
#define NAZARA_RESOURCESAVER_HPP
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Core/String.hpp>
#include <list>
#include <tuple>
#include <type_traits>
namespace Nz
{
class Stream;
template<typename Type, typename Parameters>
class ResourceSaver
{
static_assert(std::is_base_of<ResourceParameters, Parameters>::value, "ResourceParameters must be a base of Parameters");
friend Type;
public:
using ExtensionGetter = bool (*)(const String& extension);
using FormatQuerier = bool (*)(const String& format);
using FileSaver = bool (*)(const Type& resource, const String& filePath, const Parameters& parameters);
using StreamSaver = bool (*)(const Type& resource, const String& format, Stream& stream, const Parameters& parameters);
ResourceSaver() = delete;
~ResourceSaver() = delete;
static bool IsFormatSupported(const String& extension);
static bool SaveToFile(const Type& resource, const String& filePath, const Parameters& parameters = Parameters());
static bool SaveToStream(const Type& resource, Stream& stream, const String& format, const Parameters& parameters = Parameters());
static void RegisterSaver(FormatQuerier formatQuerier, StreamSaver streamSaver, FileSaver fileSaver = nullptr);
static void UnregisterSaver(FormatQuerier formatQuerier, StreamSaver streamSaver, FileSaver fileSaver = nullptr);
private:
using Saver = std::tuple<FormatQuerier, StreamSaver, FileSaver>;
using SaverList = std::list<Saver>;
};
}
#include <Nazara/Core/ResourceSaver.inl>
#endif // NAZARA_RESOURCESAVER_HPP

View File

@@ -0,0 +1,190 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/MemoryView.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::ResourceSaver
* \brief Core class that represents a list of saver functions for a specific resource type
*/
/*!
* \brief Checks whether the extension of the file is supported
* \return true if supported
*
* \param extension Extension of the file
*/
template<typename Type, typename Parameters>
bool ResourceSaver<Type, Parameters>::IsFormatSupported(const String& extension)
{
for (Saver& saver : Type::s_savers)
{
ExtensionGetter isExtensionSupported = std::get<0>(saver);
if (isExtensionSupported && isExtensionSupported(extension))
return true;
}
return false;
}
/*!
* \brief Saves a resource to a file
* \return true if successfully saved
*
* \param resource Resource to save
* \param filePath Path to the file where the resource will be written
* \param parameters Parameters for the save
*
* \remark The previous file content will be discarded, to prevent this behavior you should use SaveToStream
* \remark The file extension will be used as format for the saver ("image.png" => "png", to write a specified format to a user-specified extension you should use SaveToStream
*
* \seealso SaveToStream
*/
template<typename Type, typename Parameters>
bool ResourceSaver<Type, Parameters>::SaveToFile(const Type& resource, const String& filePath, const Parameters& parameters)
{
NazaraAssert(parameters.IsValid(), "Invalid parameters");
String path = File::NormalizePath(filePath);
String ext = path.SubStringFrom('.', -1, true).ToLower();
if (ext.IsEmpty())
{
NazaraError("Failed to get file extension from \"" + filePath + '"');
return false;
}
File file(path); // Opened only is required
bool found = false;
for (Saver& saver : Type::s_savers)
{
FormatQuerier formatQuerier = std::get<0>(saver);
if (!formatQuerier || !formatQuerier(ext))
continue;
found = true;
StreamSaver streamSeaver = std::get<1>(saver);
FileSaver fileSaver = std::get<2>(saver);
if (fileSaver)
{
if (fileSaver(resource, filePath, parameters))
return true;
}
else
{
if (!file.Open(OpenMode_WriteOnly))
{
NazaraError("Failed to save to file: unable to open \"" + filePath + "\" in write mode");
return false;
}
if (streamSeaver(resource, ext, file, parameters))
return true;
}
NazaraWarning("Saver failed");
}
if (found)
NazaraError("Failed to save resource: all savers failed");
else
NazaraError("Failed to save resource: no saver found for extension \"" + ext + '"');
return false;
}
/*!
* \brief Saves a resource to a stream
* \return true if successfully saved
*
* \param resource Resource to load
* \param stream Stream with write access where the resource data will be written
* \param format Data format to save the resource to
* \param parameters Parameters for the saving
*
* \seealso SaveToFile
*/
template<typename Type, typename Parameters>
bool ResourceSaver<Type, Parameters>::SaveToStream(const Type& resource, Stream& stream, const String& format, const Parameters& parameters)
{
NazaraAssert(stream.IsWritable(), "Stream is not writable");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
UInt64 streamPos = stream.GetCursorPos();
bool found = false;
for (Saver& saver : Type::s_savers)
{
FormatQuerier formatQuerier = std::get<0>(saver);
if (!formatQuerier || !formatQuerier(format))
continue;
found = true;
StreamSaver streamSeaver = std::get<1>(saver);
// We move the stream to its old position
stream.SetCursorPos(streamPos);
// Load of the resource
if (streamSeaver(resource, format, stream, parameters))
return true;
NazaraWarning("Saver failed");
}
if (found)
NazaraError("Failed to save resource: all savers failed");
else
NazaraError("Failed to save resource: no saver found for format \"" + format + '"');
return false;
}
/*!
* \brief Registers a saver
*
* \param formatQuerier A function to test whether the format (as a string) is supported by this saver
* \param streamSaver A function which saves the resource to a stream
* \param fileSaver Optional function which saves the resource directly to a file given a file path
*
* \remark The fileSaver argument is only present for compatibility with external savers which cannot be interfaced with streams
* \remark At least one saver is required
*/
template<typename Type, typename Parameters>
void ResourceSaver<Type, Parameters>::RegisterSaver(FormatQuerier formatQuerier, StreamSaver streamSaver, FileSaver fileSaver)
{
NazaraAssert(formatQuerier, "A format querier is mandaroty");
NazaraAssert(streamSaver || fileSaver, "A saver function is mandaroty");
Type::s_savers.push_front(std::make_tuple(formatQuerier, streamSaver, fileSaver));
}
/*!
* \brief Unregisters a saver
*
* \param formatQuerier A function to test whether the format (as a string) is supported by this saver
* \param streamSaver A function which saves the resource to a stream
* \param fileSaver A function function which saves the resource directly to a file given a file path
*
* \remark The saver will only be unregistered if the function pointers are exactly the same
*/
template<typename Type, typename Parameters>
void ResourceSaver<Type, Parameters>::UnregisterSaver(FormatQuerier formatQuerier, StreamSaver streamSaver, FileSaver fileSaver)
{
Type::s_savers.remove(std::make_tuple(formatQuerier, streamSaver, fileSaver));
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -20,17 +20,9 @@ namespace Nz
struct SerializationContext
{
Stream* stream;
Endianness endianness;
UInt8 currentBitPos;
UInt8 currentByte;
};
struct UnserializationContext
{
Stream* stream;
Endianness endianness;
UInt8 currentBitPos;
UInt8 currentByte;
Endianness endianness = Endianness_BigEndian; //< Default to Big Endian encoding
UInt8 currentBitPos = 8; //< 8 means no bit is currently wrote
UInt8 currentByte; //< Undefined value, will be initialized at the first bit write
};
}

View File

@@ -1,46 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SERIALIZER_HPP
#define NAZARA_SERIALIZER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Serialization.hpp>
namespace Nz
{
class Stream;
class Serializer
{
public:
inline Serializer(Stream& stream);
Serializer(const Serializer&) = default;
Serializer(Serializer&&) = default;
~Serializer();
inline Endianness GetDataEndianness() const;
inline Stream& GetStream() const;
inline bool FlushBits();
inline void SetDataEndianness(Endianness endiannes);
inline void SetStream(Stream& stream);
template<typename T>
Serializer& operator<<(const T& value);
Serializer& operator=(const Serializer&) = default;
Serializer& operator=(Serializer&&) = default;
private:
SerializationContext m_serializationContext;
};
}
#include <Nazara/Core/Serializer.inl>
#endif // NAZARA_SERIALIZER_HPP

View File

@@ -1,67 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
inline Serializer::Serializer(Stream& stream)
{
m_serializationContext.currentBitPos = 8;
m_serializationContext.endianness = Endianness_BigEndian;
m_serializationContext.stream = &stream;
}
inline Serializer::~Serializer()
{
if (!FlushBits())
NazaraWarning("Failed to flush bits at serializer destruction");
}
inline Endianness Serializer::GetDataEndianness() const
{
return m_serializationContext.endianness;
}
inline Stream& Serializer::GetStream() const
{
return *m_serializationContext.stream;
}
inline bool Serializer::FlushBits()
{
if (m_serializationContext.currentBitPos != 8)
{
m_serializationContext.currentBitPos = 8; //< To prevent Serialize to flush bits itself
if (!Serialize<UInt8>(m_serializationContext, m_serializationContext.currentByte))
return false;
}
return true;
}
inline void Serializer::SetDataEndianness(Endianness endiannes)
{
m_serializationContext.endianness = endiannes;
}
inline void Serializer::SetStream(Stream& stream)
{
m_serializationContext.stream = &stream;
}
template<typename T>
Serializer& Serializer::operator<<(const T& value)
{
if (!Serialize(m_serializationContext, value))
NazaraError("Failed to serialize value");
return *this;
}
}
#include <Nazara/Core/DebugOff.hpp>
#include "Serializer.hpp"

View File

@@ -8,18 +8,38 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::Signal
* \brief Core class that represents a signal, a list of objects waiting for its message
*/
/*!
* \brief Constructs a Signal object by default
*/
template<typename... Args>
Signal<Args...>::Signal() :
m_slotIterator(0)
{
}
/*!
* \brief Constructs a Signal object by move semantic
*
* \param signal Signal to move in this
*/
template<typename... Args>
Signal<Args...>::Signal(Signal&& signal)
{
operator=(std::move(signal));
}
/*!
* \brief Clears the list of actions attached to the signal
*/
template<typename... Args>
void Signal<Args...>::Clear()
{
@@ -27,12 +47,26 @@ namespace Nz
m_slotIterator = 0;
}
/*!
* \brief Connects a function to the signal
* \return Connection attached to the signal
*
* \param func Non-member function
*/
template<typename... Args>
typename Signal<Args...>::Connection Signal<Args...>::Connect(const Callback& func)
{
return Connect(Callback(func));
}
/*!
* \brief Connects a function to the signal
* \return Connection attached to the signal
*
* \param func Non-member function
*/
template<typename... Args>
typename Signal<Args...>::Connection Signal<Args...>::Connect(Callback&& func)
{
@@ -54,6 +88,14 @@ namespace Nz
return Connection(m_slots.back());
}
/*!
* \brief Connects a member function and its object to the signal
* \return Connection attached to the signal
*
* \param object Object to send the message
* \param method Member function
*/
template<typename... Args>
template<typename O>
typename Signal<Args...>::Connection Signal<Args...>::Connect(O& object, void (O::*method) (Args...))
@@ -64,6 +106,14 @@ namespace Nz
});
}
/*!
* \brief Connects a member function and its object to the signal
* \return Connection attached to the signal
*
* \param object Object to send the message
* \param method Member function
*/
template<typename... Args>
template<typename O>
typename Signal<Args...>::Connection Signal<Args...>::Connect(O* object, void (O::*method)(Args...))
@@ -74,6 +124,14 @@ namespace Nz
});
}
/*!
* \brief Connects a member function and its object to the signal
* \return Connection attached to the signal
*
* \param object Object to send the message
* \param method Member function
*/
template<typename... Args>
template<typename O>
typename Signal<Args...>::Connection Signal<Args...>::Connect(const O& object, void (O::*method) (Args...) const)
@@ -84,6 +142,14 @@ namespace Nz
});
}
/*!
* \brief Connects a member function and its object to the signal
* \return Connection attached to the signal
*
* \param object Object to send the message
* \param method Member function
*/
template<typename... Args>
template<typename O>
typename Signal<Args...>::Connection Signal<Args...>::Connect(const O* object, void (O::*method)(Args...) const)
@@ -94,6 +160,12 @@ namespace Nz
});
}
/*!
* \brief Applies the list of arguments to every callback functions
*
* \param args Arguments to send with the message
*/
template<typename... Args>
void Signal<Args...>::operator()(Args... args) const
{
@@ -101,6 +173,13 @@ namespace Nz
m_slots[m_slotIterator]->callback(args...);
}
/*!
* \brief Moves the signal into this
* \return A reference to this
*
* \param signal Signal to move in this
*/
template<typename... Args>
Signal<Args...>& Signal<Args...>::operator=(Signal&& signal)
{
@@ -114,17 +193,28 @@ namespace Nz
return *this;
}
/*!
* \brief Disconnects a listener from this signal
*
* \param slot Pointer to the ith listener of the signal
*
* \remark Produces a NazaraAssert if slot is invalid (nullptr)
* \remark Produces a NazaraAssert if index of slot is invalid
* \remark Produces a NazaraAssert if slot is not attached to this signal
*/
template<typename... Args>
void Signal<Args...>::Disconnect(const SlotPtr& slot)
{
NazaraAssert(slot, "Invalid slot pointer");
NazaraAssert(slot->index < m_slots.size(), "Invalid slot index");
NazaraAssert(slot->signal == this, "Slot is not attached to this signal");
// "Swap this slot with the last one and pop" idiom
// This will preserve slot indexes
// Can we safely "remove" this slot?
if (m_slotIterator >= m_slots.size()-1 || slot->index > m_slotIterator)
if (m_slotIterator >= (m_slots.size() - 1) || slot->index > m_slotIterator)
{
// Yes we can
SlotPtr& newSlot = m_slots[slot->index];
@@ -150,6 +240,16 @@ namespace Nz
m_slots.pop_back();
}
/*!
* \class Nz::Signal::Connection
* \brief Core class that represents a connection attached to a signal
*/
/*!
* \brief Constructs a Signal::Connection object with a slot
*
* \param slot Slot of the listener
*/
template<typename... Args>
Signal<Args...>::Connection::Connection(const SlotPtr& slot) :
@@ -157,6 +257,13 @@ namespace Nz
{
}
/*!
* \brief Connects to a signal with arguments
*
* \param signal New signal to listen
* \param args Arguments for the signal
*/
template<typename... Args>
template<typename... ConnectArgs>
void Signal<Args...>::Connection::Connect(BaseClass& signal, ConnectArgs&&... args)
@@ -164,6 +271,10 @@ namespace Nz
operator=(signal.Connect(std::forward<ConnectArgs>(args)...));
}
/*!
* \brief Disconnects the connection from the signal
*/
template<typename... Args>
void Signal<Args...>::Connection::Disconnect()
{
@@ -171,12 +282,27 @@ namespace Nz
ptr->signal->Disconnect(ptr);
}
/*!
* \brief Checks whether the connection is still active with the signal
* \return true if signal is still active
*/
template<typename... Args>
bool Signal<Args...>::Connection::IsConnected() const
{
return !m_ptr.expired();
}
/*!
* \class Nz::Signal::ConnectionGuard
* \brief Core class that represents a RAII for a connection attached to a signal
*/
/*!
* \brief Constructs a Signal::ConnectionGuard object with a connection
*
* \param connection Connection for the scope
*/
template<typename... Args>
Signal<Args...>::ConnectionGuard::ConnectionGuard(const Connection& connection) :
@@ -184,18 +310,35 @@ namespace Nz
{
}
/*!
* \brief Constructs a Signal::ConnectionGuard object with a connection by move semantic
*
* \param connection Connection for the scope
*/
template<typename... Args>
Signal<Args...>::ConnectionGuard::ConnectionGuard(Connection&& connection) :
m_connection(std::move(connection))
{
}
/*!
* \brief Destructs the object and disconnects the connection
*/
template<typename... Args>
Signal<Args...>::ConnectionGuard::~ConnectionGuard()
{
m_connection.Disconnect();
}
/*!
* \brief Connects to a signal with arguments
*
* \param signal New signal to listen
* \param args Arguments for the signal
*/
template<typename... Args>
template<typename... ConnectArgs>
void Signal<Args...>::ConnectionGuard::Connect(BaseClass& signal, ConnectArgs&&... args)
@@ -204,24 +347,45 @@ namespace Nz
m_connection.Connect(signal, std::forward<ConnectArgs>(args)...);
}
/*!
* \brief Disconnects the connection from the signal
*/
template<typename... Args>
void Signal<Args...>::ConnectionGuard::Disconnect()
{
m_connection.Disconnect();
}
/*!
* \brief Gets the connection attached to the signal
* \return Connection of the signal
*/
template<typename... Args>
typename Signal<Args...>::Connection& Signal<Args...>::ConnectionGuard::GetConnection()
{
return m_connection;
}
/*!
* \brief Checks whether the connection is still active with the signal
* \return true if signal is still active
*/
template<typename... Args>
bool Signal<Args...>::ConnectionGuard::IsConnected() const
{
return m_connection.IsConnected();
}
/*!
* \brief Assigns the connection into this
* \return A reference to this
*
* \param connection Connection to assign into this
*/
template<typename... Args>
typename Signal<Args...>::ConnectionGuard& Signal<Args...>::ConnectionGuard::operator=(const Connection& connection)
{
@@ -231,6 +395,13 @@ namespace Nz
return *this;
}
/*!
* \brief Moves the Connection into this
* \return A reference to this
*
* \param connection Connection to move in this
*/
template<typename... Args>
typename Signal<Args...>::ConnectionGuard& Signal<Args...>::ConnectionGuard::operator=(Connection&& connection)
{
@@ -240,6 +411,13 @@ namespace Nz
return *this;
}
/*!
* \brief Moves the ConnectionGuard into this
* \return A reference to this
*
* \param connection ConnectionGuard to move in this
*/
template<typename... Args>
typename Signal<Args...>::ConnectionGuard& Signal<Args...>::ConnectionGuard::operator=(ConnectionGuard&& connection)
{

View File

@@ -7,7 +7,7 @@
#ifndef NAZARA_SPARSEPTR_HPP
#define NAZARA_SPARSEPTR_HPP
///FIXME: Est-ce que SparsePtr est vraiment le meilleur nom pour cette classe ?
///FIXME: Is SparsePtr a really good name for this class ?
#include <Nazara/Prerequesites.hpp>
#include <cstddef>

View File

@@ -7,24 +7,53 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::SparsePtr
* \brief Core class that represents a pointer and the step between two elements
*/
/*!
* \brief Constructs a SparsePtr object by default
*/
template<typename T>
SparsePtr<T>::SparsePtr()
{
Reset();
}
/*!
* \brief Constructs a SparsePtr object with a pointer
*
* \param ptr Pointer to data
*/
template<typename T>
SparsePtr<T>::SparsePtr(T* ptr)
{
Reset(ptr);
}
/*!
* \brief Constructs a SparsePtr object with a pointer and a step
*
* \param ptr Pointer to data
* \param stride Step between two elements
*/
template<typename T>
SparsePtr<T>::SparsePtr(VoidPtr ptr, int stride)
{
Reset(ptr, stride);
}
/*!
* \brief Constructs a SparsePtr object from another type of SparsePtr
*
* \param ptr Pointer to data of type U to convert to type T
*/
template<typename T>
template<typename U>
SparsePtr<T>::SparsePtr(const SparsePtr<U>& ptr)
@@ -32,18 +61,32 @@ namespace Nz
Reset(ptr);
}
/*!
* \brief Gets the original pointer
* \return Pointer to the first data
*/
template<typename T>
typename SparsePtr<T>::VoidPtr SparsePtr<T>::GetPtr() const
{
return m_ptr;
}
/*!
* \brief Gets the stride
* \return Step between two elements
*/
template<typename T>
int SparsePtr<T>::GetStride() const
{
return m_stride;
}
/*!
* \brief Resets the SparsePtr
*/
template<typename T>
void SparsePtr<T>::Reset()
{
@@ -51,6 +94,14 @@ namespace Nz
SetStride(0);
}
/*!
* \brief Resets the SparsePtr with a pointer
*
* \param ptr Pointer to data
*
* \remark stride is set to sizeof(T)
*/
template<typename T>
void SparsePtr<T>::Reset(T* ptr)
{
@@ -58,6 +109,13 @@ namespace Nz
SetStride(sizeof(T));
}
/*!
* \brief Resets the SparsePtr with a pointer and its stride
*
* \param ptr Pointer to data
* \param stride Step between two elements
*/
template<typename T>
void SparsePtr<T>::Reset(VoidPtr ptr, int stride)
{
@@ -65,6 +123,12 @@ namespace Nz
SetStride(stride);
}
/*!
* \brief Resets the SparsePtr with another SparsePtr
*
* \param ptr Another sparsePtr
*/
template<typename T>
void SparsePtr<T>::Reset(const SparsePtr& ptr)
{
@@ -72,6 +136,12 @@ namespace Nz
SetStride(ptr.GetStride());
}
/*!
* \brief Resets the SparsePtr with another type of SparsePtr
*
* \param ptr Another sparsePtr
*/
template<typename T>
template<typename U>
void SparsePtr<T>::Reset(const SparsePtr<U>& ptr)
@@ -82,94 +152,187 @@ namespace Nz
SetStride(ptr.GetStride());
}
/*!
* \brief Sets the pointer
*
* \param ptr Pointer to data
*/
template<typename T>
void SparsePtr<T>::SetPtr(VoidPtr ptr)
{
m_ptr = reinterpret_cast<BytePtr>(ptr);
m_ptr = static_cast<BytePtr>(ptr);
}
/*!
* \brief Sets the stride
*
* \param stride Step between two elements
*/
template<typename T>
void SparsePtr<T>::SetStride(int stride)
{
m_stride = stride;
}
/*!
* \brief Converts the pointer to bool
* \return true if pointer is not nullptr
*/
template<typename T>
SparsePtr<T>::operator bool() const
{
return m_ptr != nullptr;
}
/*!
* \brief Converts the pointer to a pointer to the value
* \return The value of the pointer
*/
template<typename T>
SparsePtr<T>::operator T*() const
{
return reinterpret_cast<T*>(m_ptr);
}
/*!
* \brief Dereferences the pointer
* \return The dereferencing of the pointer
*/
template<typename T>
T& SparsePtr<T>::operator*() const
{
return *reinterpret_cast<T*>(m_ptr);
}
/*!
* \brief Dereferences the pointer
* \return The dereferencing of the pointer
*/
template<typename T>
T* SparsePtr<T>::operator->() const
{
return reinterpret_cast<T*>(m_ptr);
}
/*!
* \brief Gets the ith element of the stride pointer
* \return A reference to the ith value
*
* \param index Number of stride to do
*/
template<typename T>
T& SparsePtr<T>::operator[](int index) const
{
return *reinterpret_cast<T*>(m_ptr + index*m_stride);
return *reinterpret_cast<T*>(m_ptr + index * m_stride);
}
/*!
* \brief Gets the SparsePtr with an offset
* \return A SparsePtr with the new stride
*
* \param count Number of stride to do
*/
template<typename T>
SparsePtr<T> SparsePtr<T>::operator+(int count) const
{
return SparsePtr(m_ptr + count*m_stride, m_stride);
return SparsePtr(m_ptr + count * m_stride, m_stride);
}
/*!
* \brief Gets the SparsePtr with an offset
* \return A SparsePtr with the new stride
*
* \param count Number of stride to do
*/
template<typename T>
SparsePtr<T> SparsePtr<T>::operator+(unsigned int count) const
{
return SparsePtr(m_ptr + count*m_stride, m_stride);
return SparsePtr(m_ptr + count * m_stride, m_stride);
}
/*!
* \brief Gets the SparsePtr with an offset
* \return A SparsePtr with the new stride
*
* \param count Number of stride to do
*/
template<typename T>
SparsePtr<T> SparsePtr<T>::operator-(int count) const
{
return SparsePtr(m_ptr - count*m_stride, m_stride);
return SparsePtr(m_ptr - count * m_stride, m_stride);
}
/*!
* \brief Gets the SparsePtr with an offset
* \return A SparsePtr with the new stride
*
* \param count Number of stride to do
*/
template<typename T>
SparsePtr<T> SparsePtr<T>::operator-(unsigned int count) const
{
return SparsePtr(m_ptr - count*m_stride, m_stride);
return SparsePtr(m_ptr - count * m_stride, m_stride);
}
/*!
* \brief Gets the difference between the two SparsePtr
* \return The difference of elements: ptr - this->ptr
*
* \param ptr Other ptr
*/
template<typename T>
std::ptrdiff_t SparsePtr<T>::operator-(const SparsePtr& ptr) const
{
return (m_ptr - ptr.m_ptr)/m_stride;
return (m_ptr - ptr.m_ptr) / m_stride;
}
/*!
* \brief Gets the SparsePtr with an offset
* \return A reference to this pointer with the new stride
*
* \param count Number of stride to do
*/
template<typename T>
SparsePtr<T>& SparsePtr<T>::operator+=(int count)
{
m_ptr += count*m_stride;
m_ptr += count * m_stride;
return *this;
}
/*!
* \brief Gets the SparsePtr with an offset
* \return A reference to this pointer with the new stride
*
* \param count Number of stride to do
*/
template<typename T>
SparsePtr<T>& SparsePtr<T>::operator-=(int count)
{
m_ptr -= count*m_stride;
m_ptr -= count * m_stride;
return *this;
}
/*!
* \brief Gets the SparsePtr with the next element
* \return A reference to this pointer updated
*/
template<typename T>
SparsePtr<T>& SparsePtr<T>::operator++()
{
@@ -178,19 +341,29 @@ namespace Nz
return *this;
}
/*!
* \brief Gets the SparsePtr with the next element
* \return A SparsePtr not updated
*/
template<typename T>
SparsePtr<T> SparsePtr<T>::operator++(int)
{
// On fait une copie de l'objet
// We copy the object
SparsePtr tmp(*this);
// On modifie l'objet
// We modify it
operator++();
// On retourne la copie
// We return the copy
return tmp;
}
/*!
* \brief Gets the SparsePtr with the previous element
* \return A reference to this pointer updated
*/
template<typename T>
SparsePtr<T>& SparsePtr<T>::operator--()
{
@@ -198,49 +371,96 @@ namespace Nz
return *this;
}
/*!
* \brief Gets the SparsePtr with the previous element
* \return A SparsePtr not updated
*/
template<typename T>
SparsePtr<T> SparsePtr<T>::operator--(int)
{
// On fait une copie de l'objet
// We copy the object
SparsePtr tmp(*this);
// On modifie l'objet
// We modify it
operator--();
// On retourne la copie
// We return the copy
return tmp;
}
/*!
* \brief Compares the SparsePtr to another one
* \return true if the two SparsePtr are pointing to the same memory
*
* \param ptr Other SparsePtr to compare with
*/
template<typename T>
bool SparsePtr<T>::operator==(const SparsePtr& ptr) const
{
return m_ptr == ptr.m_ptr;
}
/*!
* \brief Compares the SparsePtr to another one
* \return false if the two SparsePtr are pointing to the same memory
*
* \param ptr Other SparsePtr to compare with
*/
template<typename T>
bool SparsePtr<T>::operator!=(const SparsePtr& ptr) const
{
return m_ptr != ptr.m_ptr;
}
/*!
* \brief Compares the SparsePtr to another one
* \return true if the first SparsePtr is pointing to memory inferior to the second one
*
* \param ptr Other SparsePtr to compare with
*/
template<typename T>
bool SparsePtr<T>::operator<(const SparsePtr& ptr) const
{
return m_ptr < ptr.m_ptr;
}
/*!
* \brief Compares the SparsePtr to another one
* \return true if the first SparsePtr is pointing to memory superior to the second one
*
* \param ptr Other SparsePtr to compare with
*/
template<typename T>
bool SparsePtr<T>::operator>(const SparsePtr& ptr) const
{
return m_ptr > ptr.m_ptr;
}
/*!
* \brief Compares the SparsePtr to another one
* \return true if the first SparsePtr is pointing to memory inferior or equal to the second one
*
* \param ptr Other SparsePtr to compare with
*/
template<typename T>
bool SparsePtr<T>::operator<=(const SparsePtr& ptr) const
{
return m_ptr <= ptr.m_ptr;
}
/*!
* \brief Compares the SparsePtr to another one
* \return true if the first SparsePtr is pointing to memory superior or equal to the second one
*
* \param ptr Other SparsePtr to compare with
*/
template<typename T>
bool SparsePtr<T>::operator>=(const SparsePtr& ptr) const
{

View File

@@ -7,12 +7,26 @@
namespace Nz
{
/*!
* \ingroup core
* \brief Constructs a Stream object with options
*
* \param streamOptions Options for the stream
* \param openMode Reading/writing mode for the stream
*/
inline Stream::Stream(UInt32 streamOptions, UInt32 openMode) :
m_openMode(openMode),
m_streamOptions(streamOptions)
{
}
/*!
* \brief Enables the text mode
*
* \param textMode Enables the mode or disables
*/
inline void Stream::EnableTextMode(bool textMode)
{
if (textMode)
@@ -21,6 +35,12 @@ namespace Nz
m_streamOptions &= ~StreamOption_Text;
}
/*!
* \brief Flushes the stream
*
* \remark Produces a NazaraAssert if file is not writable
*/
inline void Stream::Flush()
{
NazaraAssert(IsWritable(), "Stream is not writable");
@@ -28,36 +48,77 @@ namespace Nz
FlushStream();
}
/*!
* \brief Gets the open mode of the stream
* \return Reading/writing mode for the stream
*/
inline UInt32 Stream::GetOpenMode() const
{
return m_openMode;
}
/*!
* \brief Gets the options of the stream
* \return Options of the stream
*/
inline UInt32 Stream::GetStreamOptions() const
{
return m_streamOptions;
}
/*!
* \brief Checks whether the stream is readable
* \return true if it is the case
*/
inline bool Stream::IsReadable() const
{
return (m_openMode & OpenMode_ReadOnly) != 0;
}
/*!
* \brief Checks whether the stream is sequential
* \return true if it is the case
*/
inline bool Stream::IsSequential() const
{
return (m_streamOptions & StreamOption_Sequential) != 0;
}
/*!
* \brief Checks whether the stream has text mode enabled
* \return true if it is the case
*/
inline bool Stream::IsTextModeEnabled() const
{
return (m_streamOptions & StreamOption_Text) != 0;
}
/*!
* \brief Checks whether the stream can be written
* \return true if it is the case
*/
inline bool Stream::IsWritable() const
{
return (m_openMode & OpenMode_WriteOnly) != 0;
}
/*!
* \brief Reads the stream and puts the result in a buffer
* \return Size of the read
*
* \param buffer Buffer to stock data
* \param size Size meant to be read
*
* \remark Produces a NazaraAssert if stream is not readable
* \remark If preallocated space of buffer is less than the size, the behaviour is undefined
*/
inline std::size_t Stream::Read(void* buffer, std::size_t size)
{
NazaraAssert(IsReadable(), "Stream is not readable");
@@ -65,6 +126,17 @@ namespace Nz
return ReadBlock(buffer, size);
}
/*!
* \brief Writes in the stream the content of a buffer
* \return Size of the writing
*
* \param buffer Buffer to get data from
* \param size Size meant to be written
*
* \remark Produces a NazaraAssert if stream is not writable
* \remark If preallocated space of buffer is less than the size, the behaviour is undefined
*/
inline std::size_t Stream::Write(const void* buffer, std::size_t size)
{
NazaraAssert(IsWritable(), "Stream is not writable");

View File

@@ -23,11 +23,11 @@ namespace Nz
public:
enum Flags
{
None = 0x00, // Mode par défaut
CaseInsensitive = 0x01, // Insensible à la casse
HandleUtf8 = 0x02, // Traite les octets comme une suite de caractères UTF-8
TrimOnlyLeft = 0x04, // Trim(med), ne coupe que la partie gauche de la chaîne
TrimOnlyRight = 0x08 // Trim(med), ne coupe que la partie droite de la chaîne
None = 0x00, // Default mode
CaseInsensitive = 0x01, // Case insensitive
HandleUtf8 = 0x02, // Considers bytes as a list of UTF-8 characters
TrimOnlyLeft = 0x04, // Trim(med), only cut the left part of the string
TrimOnlyRight = 0x08 // Trim(med), only cut the right part of the string
};
String();
@@ -71,7 +71,7 @@ namespace Nz
std::size_t FindAny(const char* string, std::intmax_t start = 0, UInt32 flags = None) const;
std::size_t FindAny(const String& string, std::intmax_t start = 0, UInt32 flags = None) const;
std::size_t FindLast(char character, std::intmax_t start = -1, UInt32 flags = None) const;
std::size_t FindLast(const char *string, std::intmax_t start = -1, UInt32 flags = None) const;
std::size_t FindLast(const char* string, std::intmax_t start = -1, UInt32 flags = None) const;
std::size_t FindLast(const String& string, std::intmax_t start = -1, UInt32 flags = None) const;
std::size_t FindLastAny(const char* string, std::intmax_t start = -1, UInt32 flags = None) const;
std::size_t FindLastAny(const String& string, std::intmax_t start = -1, UInt32 flags = None) const;
@@ -119,8 +119,8 @@ namespace Nz
void Reserve(std::size_t bufferSize);
String& Resize(std::intmax_t size, char character = ' ');
String Resized(std::intmax_t size, char character = ' ') const;
String& Resize(std::intmax_t size, UInt32 flags = None);
String Resized(std::intmax_t size, UInt32 flags = None) const;
String& Reverse();
String Reversed() const;
@@ -326,7 +326,7 @@ namespace Nz
inline bool HashAppend(AbstractHash* hash, const String& string);
NAZARA_CORE_API bool Serialize(SerializationContext& context, const String& string);
NAZARA_CORE_API bool Unserialize(UnserializationContext& context, String* string);
NAZARA_CORE_API bool Unserialize(SerializationContext& context, String* string);
}
namespace std

View File

@@ -7,22 +7,43 @@
namespace Nz
{
/*!
* \ingroup core
* \brief Constructs a String object with a shared string by move semantic
*
* \param sharedString Shared string to move into this
*/
inline String::String(std::shared_ptr<SharedString>&& sharedString) :
m_sharedString(std::move(sharedString))
{
}
/*!
* \brief Releases the content to the string
*/
inline void String::ReleaseString()
{
m_sharedString = std::move(GetEmptyString());
}
/*!
* \brief Constructs a SharedString object by default
*/
inline String::SharedString::SharedString() : // Special case: empty string
capacity(0),
size(0)
{
}
/*!
* \brief Constructs a SharedString object with a size
*
* \param strSize Number of characters in the string
*/
inline String::SharedString::SharedString(std::size_t strSize) :
capacity(strSize),
size(strSize),
@@ -31,6 +52,13 @@ namespace Nz
string[strSize] = '\0';
}
/*!
* \brief Constructs a SharedString object with a size and a capacity
*
* \param strSize Number of characters in the string
* \param strCapacity Capacity in characters in the string
*/
inline String::SharedString::SharedString(std::size_t strSize, std::size_t strCapacity) :
capacity(strCapacity),
size(strSize),
@@ -39,6 +67,14 @@ namespace Nz
string[strSize] = '\0';
}
/*!
* \brief Appends the string to the hash
* \return true if hash is successful
*
* \param hash Hash to append data of the file
* \param string String to hash
*/
inline bool HashAppend(AbstractHash* hash, const String& string)
{
hash->Append(reinterpret_cast<const UInt8*>(string.GetConstBuffer()), string.GetSize());
@@ -48,6 +84,13 @@ namespace Nz
namespace std
{
/*!
* \brief Specialisation of std to hash
* \return Result of the hash
*
* \param str String to hash
*/
template<>
struct hash<Nz::String>
{

View File

@@ -6,18 +6,44 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::TaskScheduler
* \brief Core class that represents a thread pool
*/
/*!
* \brief Adds a task to the pending list
*
* \param function Task that the pool will execute
*/
template<typename F>
void TaskScheduler::AddTask(F function)
{
AddTaskFunctor(new FunctorWithoutArgs<F>(function));
}
/*!
* \brief Adds a task to the pending list
*
* \param function Task that the pool will execute
* \param args Arguments of the function
*/
template<typename F, typename... Args>
void TaskScheduler::AddTask(F function, Args&&... args)
{
AddTaskFunctor(new FunctorWithArgs<F, Args...>(function, std::forward<Args>(args)...));
}
/*!
* \brief Adds a task to the pending list
*
* \param function Task that the pool will execute
* \param object Object on which the method will be called
*/
template<typename C>
void TaskScheduler::AddTask(void (C::*function)(), C* object)
{

View File

@@ -7,18 +7,44 @@
namespace Nz
{
/*!
* \ingroup core
* \class Nz::Thread
* \brief Core class that represents a thread
*/
/*!
* \brief Constructs a Thread object with a function
*
* \param function Task the thread will execute in parallel
*/
template<typename F>
Thread::Thread(F function)
{
CreateImpl(new FunctorWithoutArgs<F>(function));
}
/*!
* \brief Constructs a Thread object with a function and its parameters
*
* \param function Task the thread will execute in parallel
* \param args Arguments of the function
*/
template<typename F, typename... Args>
Thread::Thread(F function, Args&&... args)
{
CreateImpl(new FunctorWithArgs<F, Args...>(function, std::forward<Args>(args)...));
}
/*!
* \brief Constructs a Thread object with a member function and its object
*
* \param function Task the thread will execute in parallel
* \param object Object on which the method will be called
*/
template<typename C>
Thread::Thread(void (C::*function)(), C* object)
{

View File

@@ -2,12 +2,12 @@
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Pas de header guard
// No header guard
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Mutex.hpp>
// Ces macros peuvent changer pour n'importe quel fichier qui l'utilise dans une même unité de compilation
// These macroes can change for any file which uses it in the same unit of compilation
#undef NazaraLock
#undef NazaraMutex
#undef NazaraMutexAttrib

View File

@@ -2,9 +2,9 @@
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Pas de header guard
// No header guard
// Ces macros peuvent changer pour n'importe quel fichier qui l'utilise dans une même unité de compilation
// These macroes can change for any file which uses it in the same unit of compilation
#undef NazaraLock
#undef NazaraMutex
#undef NazaraMutexAttrib

View File

@@ -18,16 +18,16 @@ namespace Nz
Unicode() = delete;
~Unicode() = delete;
/*
Catégorie Unicode:
-Les valeurs de 0x01 à 0x80 indiquent la catégorie.
-Les valeurs de 0x100 à 0x10000 indiquent la sous-catégorie.
Unicode category:
-Values between 0x01 and 0x80 specify the category
-Values between 0x100 and 0x10000 specify the subcategory
*/
enum Category : UInt16
{
// Catégorie non-reconnue par Nazara
// Category not handled by Nazara
Category_NoCategory = 0,
// Lettres
// Letters
Category_Letter = 0x01, // L
Category_Letter_Lowercase = Category_Letter | 0x0100, // Ll
Category_Letter_Modifier = Category_Letter | 0x0200, // Lm
@@ -35,19 +35,19 @@ namespace Nz
Category_Letter_Titlecase = Category_Letter | 0x0800, // Lt
Category_Letter_Uppercase = Category_Letter | 0x1000, // Lu
// Marques
// Marks
Category_Mark = 0x02, // M
Category_Mark_Enclosing = Category_Mark | 0x100, // Me
Category_Mark_NonSpacing = Category_Mark | 0x200, // Mn
Category_Mark_SpacingCombining = Category_Mark | 0x400, // Mc
// Nombres
// Numbers
Category_Number = 0x04, // N
Category_Number_DecimalDigit = Category_Number | 0x100, // Nd
Category_Number_Letter = Category_Number | 0x200, // Nl
Category_Number_Other = Category_Number | 0x400, // No
// Autres
// Others
Category_Other = 0x08, // C
Category_Other_Control = Category_Other | 0x0100, // Cc
Category_Other_Format = Category_Other | 0x0200, // Cf
@@ -65,13 +65,13 @@ namespace Nz
Category_Punctuation_Open = Category_Punctuation | 0x2000, // Ps
Category_Punctuation_Other = Category_Punctuation | 0x4000, // Po
// Espacements
// Spaces
Category_Separator = 0x20, // Z
Category_Separator_Line = Category_Separator | 0x0100, // Zl
Category_Separator_Paragraph = Category_Separator | 0x0200, // Zp
Category_Separator_Space = Category_Separator | 0x0400, // Zs
// Symboles
// Symbols
Category_Symbol = 0x40, // S
Category_Symbol_Currency = Category_Symbol | 0x0100, // Sc
Category_Symbol_Math = Category_Symbol | 0x0200, // Sm

View File

@@ -1,44 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_UNSERIALIZER_HPP
#define NAZARA_UNSERIALIZER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Serialization.hpp>
namespace Nz
{
class Stream;
class Unserializer
{
public:
inline Unserializer(Stream& stream);
Unserializer(const Unserializer&) = default;
Unserializer(Unserializer&&) = default;
~Unserializer() = default;
inline Endianness GetDataEndianness() const;
inline Stream& GetStream() const;
inline void SetDataEndianness(Endianness endiannes);
inline void SetStream(Stream& stream);
template<typename T>
Unserializer& operator>>(T& value);
Unserializer& operator=(const Unserializer&) = default;
Unserializer& operator=(Unserializer&&) = default;
private:
UnserializationContext m_unserializationContext;
};
}
#include <Nazara/Core/Unserializer.inl>
#endif // NAZARA_UNSERIALIZER_HPP

View File

@@ -1,46 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
inline Unserializer::Unserializer(Stream& stream)
{
m_unserializationContext.currentBitPos = 8;
m_unserializationContext.endianness = Endianness_BigEndian;
m_unserializationContext.stream = &stream;
}
inline Endianness Unserializer::GetDataEndianness() const
{
return m_unserializationContext.endianness;
}
inline Stream& Unserializer::GetStream() const
{
return *m_unserializationContext.stream;
}
inline void Unserializer::SetDataEndianness(Endianness endiannes)
{
m_unserializationContext.endianness = endiannes;
}
inline void Unserializer::SetStream(Stream& stream)
{
m_unserializationContext.stream = &stream;
}
template<typename T>
Unserializer& Unserializer::operator>>(T& value)
{
if (!Unserialize(m_unserializationContext, &value))
NazaraError("Failed to serialize value");
return *this;
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -28,6 +28,7 @@ namespace Nz
AbstractRenderTechnique(AbstractRenderTechnique&&) = default;
virtual ~AbstractRenderTechnique();
virtual void Clear(const SceneData& sceneData) const = 0;
virtual bool Draw(const SceneData& sceneData) const = 0;
virtual void EnableInstancing(bool instancing);

View File

@@ -42,7 +42,7 @@ namespace Nz
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override;
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay = nullptr) override;
void Clear(bool fully = false);
void Clear(bool fully = false) override;
struct MeshDataComparator
{

View File

@@ -32,6 +32,7 @@ namespace Nz
DeferredRenderTechnique();
~DeferredRenderTechnique();
void Clear(const SceneData& sceneData) const override;
bool Draw(const SceneData& sceneData) const override;
void EnablePass(RenderPassType renderPass, int position, bool enable);

View File

@@ -44,7 +44,7 @@ namespace Nz
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override;
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, unsigned int spriteCount, const Texture* overlay = nullptr) override;
void Clear(bool fully = false);
void Clear(bool fully = false) override;
void Sort(const AbstractViewer* viewer);

View File

@@ -24,6 +24,7 @@ namespace Nz
ForwardRenderTechnique();
~ForwardRenderTechnique() = default;
void Clear(const SceneData& sceneData) const override;
bool Draw(const SceneData& sceneData) const override;
unsigned int GetMaxLightPassPerObject() const;

View File

@@ -19,7 +19,7 @@ namespace Nz
GuillotineTextureAtlas() = default;
~GuillotineTextureAtlas() = default;
UInt32 GetStorage() const;
UInt32 GetStorage() const override;
private:
AbstractImage* ResizeImage(AbstractImage* oldImage, const Vector2ui& size) const override;

View File

@@ -68,6 +68,16 @@ namespace Nz
return m_innerAngle;
}
inline float Light::GetInnerAngleCosine() const
{
return m_innerAngleCosine;
}
inline float Light::GetInvRadius() const
{
return m_invRadius;
}
inline LightType Light::GetLightType() const
{
return m_type;

View File

@@ -15,6 +15,7 @@
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceManager.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Graphics/Config.hpp>
@@ -26,7 +27,7 @@
namespace Nz
{
struct NAZARA_GRAPHICS_API MaterialParams
struct NAZARA_GRAPHICS_API MaterialParams : ResourceParameters
{
bool loadAlphaMap = true;
bool loadDiffuseMap = true;

View File

@@ -10,13 +10,14 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Utility/Mesh.hpp>
namespace Nz
{
struct NAZARA_GRAPHICS_API ModelParameters
struct NAZARA_GRAPHICS_API ModelParameters : ResourceParameters
{
ModelParameters();

View File

@@ -33,7 +33,7 @@ namespace Nz
void AddController(ParticleControllerRef controller);
void AddEmitter(ParticleEmitter* emitter);
void AddGenerator(ParticleGeneratorRef generator);
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix) const;
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix) const override;
void ApplyControllers(ParticleMapper& mapper, unsigned int particleCount, float elapsedTime);

View File

@@ -18,7 +18,7 @@
namespace Nz
{
struct NAZARA_GRAPHICS_API SkeletalModelParameters : public ModelParameters
struct NAZARA_GRAPHICS_API SkeletalModelParameters : ModelParameters
{
bool loadAnimation = true;
AnimationParams animation;
@@ -54,7 +54,7 @@ namespace Nz
bool HasAnimation() const;
bool IsAnimated() const;
bool IsAnimated() const override;
bool IsAnimationEnabled() const;
bool LoadFromFile(const String& filePath, const SkeletalModelParameters& params = SkeletalModelParameters());

View File

@@ -30,13 +30,17 @@ namespace Nz
SkyboxBackground(TextureRef cubemapTexture = TextureRef());
~SkyboxBackground() = default;
void Draw(const AbstractViewer* viewer) const;
void Draw(const AbstractViewer* viewer) const override;
BackgroundType GetBackgroundType() const;
BackgroundType GetBackgroundType() const override;
inline const Vector3f& GetMovementOffset() const;
inline float GetMovementScale() const;
inline const TextureRef& GetTexture() const;
inline TextureSampler& GetTextureSampler();
inline const TextureSampler& GetTextureSampler() const;
inline void SetMovementOffset(const Vector3f& offset);
inline void SetMovementScale(float scale);
inline void SetTexture(TextureRef cubemapTexture);
inline void SetTextureSampler(const TextureSampler& sampler);
@@ -48,6 +52,8 @@ namespace Nz
TextureRef m_texture;
TextureSampler m_sampler;
Vector3f m_movementOffset;
float m_movementScale;
};
}

View File

@@ -7,6 +7,16 @@
namespace Nz
{
inline const Vector3f& Nz::SkyboxBackground::GetMovementOffset() const
{
return m_movementOffset;
}
inline float SkyboxBackground::GetMovementScale() const
{
return m_movementScale;
}
inline const TextureRef& SkyboxBackground::GetTexture() const
{
return m_texture;
@@ -22,6 +32,20 @@ namespace Nz
return m_sampler;
}
inline void SkyboxBackground::SetMovementOffset(const Vector3f& offset)
{
NazaraAssert(std::isfinite(offset.x) && std::isfinite(offset.y) && std::isfinite(offset.z), "Offset must be a finite vector");
m_movementOffset = offset;
}
inline void SkyboxBackground::SetMovementScale(float scale)
{
NazaraAssert(std::isfinite(scale), "Scale must be a finite value");
m_movementScale = scale;
}
inline void SkyboxBackground::SetTexture(TextureRef cubemapTexture)
{
NazaraAssert(!cubemapTexture || cubemapTexture->IsValid(), "Invalid texture");

View File

@@ -23,6 +23,9 @@ namespace Nz
class NAZARA_GRAPHICS_API Sprite : public InstancedRenderable
{
friend SpriteLibrary;
friend class Graphics;
public:
inline Sprite();
inline Sprite(MaterialRef material);
@@ -57,6 +60,9 @@ namespace Nz
void MakeBoundingVolume() const override;
void UpdateData(InstanceData* instanceData) const override;
static bool Initialize();
static void Uninitialize();
Color m_color;
MaterialRef m_material;
Rectf m_textureCoords;

View File

@@ -28,6 +28,7 @@ namespace Nz
{
public:
inline TextSprite();
inline TextSprite(const AbstractTextDrawer& drawer);
inline TextSprite(const TextSprite& sprite);
~TextSprite() = default;
@@ -65,6 +66,7 @@ namespace Nz
struct AtlasSlots
{
bool used;
NazaraSlot(AbstractAtlas, OnAtlasCleared, clearSlot);
NazaraSlot(AbstractAtlas, OnAtlasLayerChange, layerChangeSlot);
NazaraSlot(AbstractAtlas, OnAtlasRelease, releaseSlot);

View File

@@ -14,6 +14,12 @@ namespace Nz
SetDefaultMaterial();
}
inline TextSprite::TextSprite(const AbstractTextDrawer& drawer) :
TextSprite()
{
Update(drawer);
}
inline TextSprite::TextSprite(const TextSprite& sprite) :
InstancedRenderable(sprite),
m_renderInfos(sprite.m_renderInfos),

View File

@@ -8,31 +8,45 @@
#define NAZARA_LUACLASS_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Lua/LuaInstance.hpp>
#include <functional>
#include <map>
#include <memory>
//#include <type_traits>
#include <unordered_map>
#include <vector>
namespace Nz
{
template<class T/*, class P = void*/>
template<class T>
class LuaClass
{
//static_assert(std::is_same<P, void>::value || std::is_base_of<P, T>::value, "P must be a base of T");
template<class U>
friend class LuaClass;
public:
using ClassFunc = std::function<int(LuaInstance& lua, T& instance)>;
using ClassIndexFunc = std::function<bool(LuaInstance& lua, T& instance)>;
using ConstructorFunc = std::function<T*(LuaInstance& lua)>;
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)>;
LuaClass(const String& name);
//void Inherit(LuaClass<P>& parent);
void BindMethod(const String& name, ClassFunc method);
template<typename R, typename P, typename... Args, typename... DefArgs> std::enable_if_t<std::is_base_of<P, T>::value> BindMethod(const String& name, R(P::*func)(Args...), DefArgs&&... defArgs);
template<typename R, typename P, typename... Args, typename... DefArgs> std::enable_if_t<std::is_base_of<P, T>::value> BindMethod(const String& name, R(P::*func)(Args...) const, DefArgs&&... defArgs);
template<typename R, typename P, typename... Args, typename... DefArgs> std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value> BindMethod(const String& name, R(P::*func)(Args...), DefArgs&&... defArgs);
template<typename R, typename P, typename... Args, typename... DefArgs> std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value> BindMethod(const String& name, R(P::*func)(Args...) const, DefArgs&&... defArgs);
void BindStaticMethod(const String& name, StaticFunc func);
template<typename R, typename... Args, typename... DefArgs> void BindStaticMethod(const String& name, R(*func)(Args...), DefArgs&&... defArgs);
template<class P> void Inherit(LuaClass<P>& parent);
template<class P> void Inherit(LuaClass<P>& parent, ConvertToParent<P> convertFunc);
void Register(LuaInstance& lua);
@@ -41,39 +55,41 @@ namespace Nz
void SetConstructor(ConstructorFunc constructor);
void SetFinalizer(FinalizerFunc finalizer);
void SetGetter(ClassIndexFunc getter);
void SetMethod(const String& name, ClassFunc method);
template<typename R, typename P, typename... Args> std::enable_if_t<std::is_base_of<P, T>::value> SetMethod(const String& name, R(P::*func)(Args...));
template<typename R, typename P, typename... Args> std::enable_if_t<std::is_base_of<P, T>::value> SetMethod(const String& name, R(P::*func)(Args...) const);
void SetSetter(ClassIndexFunc setter);
void SetStaticGetter(StaticIndexFunc getter);
void SetStaticMethod(const String& name, StaticFunc func);
template<typename R, typename... Args> void SetStaticMethod(const String& name, R(*func)(Args...));
void SetStaticSetter(StaticIndexFunc getter);
private:
using ParentFunc = std::function<void(LuaInstance& lua, T* instance)>;
using InstanceGetter = std::function<T*(LuaInstance& lua)>;
struct ClassInfo
{
std::vector<ClassFunc> methods;
std::vector<ParentFunc> parentGetters;
std::vector<StaticFunc> staticMethods;
std::unordered_map<String, InstanceGetter> instanceGetters;
ClassIndexFunc getter;
ClassIndexFunc setter;
ConstructorFunc constructor;
FinalizerFunc finalizer;
StaticIndexFunc staticGetter;
StaticIndexFunc staticSetter;
String name;
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);
struct ClassInfo
{
std::vector<ClassFunc> methods;
std::vector<StaticFunc> staticMethods;
ClassIndexFunc getter = nullptr;
ClassIndexFunc setter = nullptr;
ConstructorFunc constructor = nullptr;
FinalizerFunc finalizer = nullptr;
StaticIndexFunc staticGetter = nullptr;
StaticIndexFunc staticSetter = nullptr;
String name;
int globalTableRef = -1;
};
static int ToStringProxy(lua_State* state);
std::map<String, ClassFunc> m_methods;
std::map<String, StaticFunc> m_staticMethods;

View File

@@ -4,6 +4,7 @@
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/MemoryHelper.hpp>
#include <type_traits>
#include <Nazara/Lua/Debug.hpp>
namespace Nz
@@ -14,15 +15,36 @@ namespace Nz
{
m_info->name = name;
}
/*
template<class T>
void LuaClass<T>::Inherit(LuaClass<P>& parent)
{
static_assert(std::is_base_of<P, T>::value, "P must be a base of T");
m_info->parentInfo = parent.m_info;
template<class T>
template<class P>
inline void LuaClass<T>::Inherit(LuaClass<P>& parent)
{
Inherit<P>(parent, [] (T* instance) -> P*
{
return static_cast<P*>(instance);
});
}
*/
template<class T>
template<class P>
inline void LuaClass<T>::Inherit(LuaClass<P>& parent, ConvertToParent<P> convertFunc)
{
static_assert(!std::is_same<P, T>::value || std::is_base_of<P, T>::value, "P must be a base of T");
std::shared_ptr<typename LuaClass<P>::ClassInfo>& parentInfo = parent.m_info;
parentInfo->instanceGetters[m_info->name] = [info = m_info, convertFunc] (LuaInstance& lua) -> P*
{
return convertFunc(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
};
m_info->parentGetters.emplace_back([parentInfo, convertFunc] (LuaInstance& lua, T* instance)
{
LuaClass<P>::Get(parentInfo, lua, convertFunc(instance));
});
}
template<class T>
void LuaClass<T>::Register(LuaInstance& lua)
{
@@ -48,27 +70,41 @@ namespace Nz
if (!lua.NewMetatable(m_info->name))
NazaraWarning("Class \"" + m_info->name + "\" already registred in this instance");
{
lua.PushValue(1); // On associe l'UserData avec la fonction
lua.PushCFunction(FinalizerProxy, 1);
lua.SetField("__gc"); // Finalizer
// Set the type in a __type field
lua.PushString(m_info->name);
lua.SetField("__type");
if (m_info->getter)
// In case a __tostring method is missing, add a default implementation returning the type
if (m_methods.find("__tostring") == m_methods.end())
{
lua.PushValue(1);
lua.PushValue(-2);
// Define the Finalizer
lua.PushValue(1); // shared_ptr on UserData
lua.PushCFunction(ToStringProxy, 1);
lua.SetField("__tostring");
}
// Define the Finalizer
lua.PushValue(1);
lua.PushCFunction(FinalizerProxy, 1);
lua.SetField("__gc");
if (m_info->getter || !m_info->parentGetters.empty())
{
lua.PushValue(1); // shared_ptr on UserData
lua.PushValue(-2); // Metatable
lua.PushCFunction(GetterProxy, 2);
}
else
// Optimisation, plutôt que de rediriger vers une fonction C qui ne fera rien d'autre que rechercher
// dans la table, nous envoyons directement la table, de sorte que Lua fasse directement la recherche
// Ceci n'est possible que si nous n'avons ni getter, ni parent
lua.PushValue(-1);
lua.PushValue(-1); // Metatable
lua.SetField("__index"); // Getter
if (m_info->setter)
{
lua.PushValue(1);
lua.PushValue(1); // shared_ptr on UserData
lua.PushCFunction(SetterProxy, 1);
lua.SetField("__newindex"); // Setter
}
@@ -76,14 +112,20 @@ namespace Nz
m_info->methods.reserve(m_methods.size());
for (auto& pair : m_methods)
{
std::size_t methodIndex = m_info->methods.size();
m_info->methods.push_back(pair.second);
lua.PushValue(1);
lua.PushInteger(m_info->methods.size() - 1);
lua.PushValue(1); // shared_ptr on UserData
lua.PushInteger(methodIndex);
lua.PushCFunction(MethodProxy, 2);
lua.SetField(pair.first); // Méthode
lua.SetField(pair.first); // Method name
}
m_info->instanceGetters[m_info->name] = [info = m_info] (LuaInstance& lua)
{
return *static_cast<T**>(lua.CheckUserdata(1, info->name));
};
}
lua.Pop(); // On pop la metatable
@@ -104,21 +146,21 @@ namespace Nz
if (m_info->staticGetter)
{
lua.PushValue(1);
lua.PushValue(-2);
lua.PushValue(1); // shared_ptr on UserData
lua.PushValue(-2); // ClassMeta
lua.PushCFunction(StaticGetterProxy, 2);
}
else
// Optimisation, plutôt que de rediriger vers une fonction C qui ne fera rien d'autre que rechercher
// dans la table, nous envoyons directement la table, de sorte que Lua fasse directement la recherche
// Ceci n'est possible que si nous n'avons ni getter, ni parent
lua.PushValue(-1);
lua.PushValue(-1); // ClassMeta
lua.SetField("__index"); // ClassMeta.__index = StaticGetterProxy/ClassMeta
if (m_info->staticSetter)
{
lua.PushValue(1);
lua.PushValue(1); // shared_ptr on UserData
lua.PushCFunction(StaticSetterProxy, 1);
lua.SetField("__newindex"); // ClassMeta.__newindex = StaticSetterProxy
}
@@ -126,10 +168,11 @@ namespace Nz
m_info->staticMethods.reserve(m_staticMethods.size());
for (auto& pair : m_staticMethods)
{
std::size_t methodIndex = m_info->staticMethods.size();
m_info->staticMethods.push_back(pair.second);
lua.PushValue(1);
lua.PushInteger(m_info->staticMethods.size() - 1);
lua.PushValue(1); // shared_ptr on UserData
lua.PushInteger(methodIndex);
lua.PushCFunction(StaticMethodProxy, 2);
lua.SetField(pair.first); // ClassMeta.method = StaticMethodProxy
@@ -170,34 +213,64 @@ namespace Nz
}
template<class T>
void LuaClass<T>::SetMethod(const String& name, ClassFunc method)
void LuaClass<T>::BindMethod(const String& name, ClassFunc method)
{
m_methods[name] = method;
}
template<class T>
template<typename R, typename P, typename... Args>
std::enable_if_t<std::is_base_of<P, T>::value> LuaClass<T>::SetMethod(const String& name, R(P::*func)(Args...))
{
SetMethod(name, [func] (LuaInstance& instance, T& object) -> int
{
LuaImplMethodProxy<T, Args...> handler(instance, object);
handler.ProcessArgs();
return handler.Invoke(func);
template<class T>
template<typename R, typename P, typename... Args, typename... DefArgs>
std::enable_if_t<std::is_base_of<P, T>::value> LuaClass<T>::BindMethod(const String& name, R(P::*func)(Args...), DefArgs&&... defArgs)
{
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
BindMethod(name, [func, handler] (LuaInstance& lua, T& object) -> int
{
handler.ProcessArgs(lua);
return handler.Invoke(lua, object, func);
});
}
template<class T>
template<typename R, typename P, typename... Args>
std::enable_if_t<std::is_base_of<P, T>::value> LuaClass<T>::SetMethod(const String& name, R(P::*func)(Args...) const)
template<typename R, typename P, typename... Args, typename... DefArgs>
std::enable_if_t<std::is_base_of<P, T>::value> LuaClass<T>::BindMethod(const String& name, R(P::*func)(Args...) const, DefArgs&&... defArgs)
{
SetMethod(name, [func] (LuaInstance& instance, T& object) -> int
{
LuaImplMethodProxy<T, Args...> handler(instance, object);
handler.ProcessArgs();
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
return handler.Invoke(func);
BindMethod(name, [func, handler] (LuaInstance& lua, T& object) -> int
{
handler.ProcessArgs(lua);
return handler.Invoke(lua, object, func);
});
}
template<class T>
template<typename R, typename P, typename... Args, typename... DefArgs>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value> LuaClass<T>::BindMethod(const String& name, R(P::*func)(Args...), DefArgs&&... defArgs)
{
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
BindMethod(name, [func, handler] (LuaInstance& lua, T& object) -> int
{
handler.ProcessArgs(lua);
return handler.Invoke(lua, object, func);
});
}
template<class T>
template<typename R, typename P, typename... Args, typename... DefArgs>
std::enable_if_t<std::is_base_of<P, typename PointedType<T>::type>::value> LuaClass<T>::BindMethod(const String& name, R(P::*func)(Args...) const, DefArgs&&... defArgs)
{
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
BindMethod(name, [func, handler] (LuaInstance& lua, T& object) -> int
{
handler.ProcessArgs(lua);
return handler.Invoke(lua, object, func);
});
}
@@ -214,21 +287,22 @@ namespace Nz
}
template<class T>
void LuaClass<T>::SetStaticMethod(const String& name, StaticFunc method)
void LuaClass<T>::BindStaticMethod(const String& name, StaticFunc method)
{
m_staticMethods[name] = method;
}
template<class T>
template<typename R, typename... Args>
void LuaClass<T>::SetStaticMethod(const String& name, R(*func)(Args...))
template<typename R, typename... Args, typename... DefArgs>
void LuaClass<T>::BindStaticMethod(const String& name, R(*func)(Args...), DefArgs&&... defArgs)
{
SetStaticMethod(name, [func] (LuaInstance& instance) -> int
{
LuaImplFunctionProxy<Args...> handler(instance);
handler.ProcessArgs();
typename LuaImplFunctionProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
return handler.Invoke(func);
BindStaticMethod(name, [func, handler] (LuaInstance& lua) -> int
{
handler.ProcessArgs(lua);
return handler.Invoke(lua, func);
});
}
@@ -243,8 +317,8 @@ namespace Nz
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
ConstructorFunc constructor = info->constructor;
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
const ConstructorFunc& constructor = info->constructor;
lua.Remove(1); // On enlève l'argument "table" du stack
@@ -255,10 +329,7 @@ namespace Nz
return 0; // Normalement jamais exécuté (l'erreur provoquant une exception)
}
T** ud = static_cast<T**>(lua.PushUserdata(sizeof(T*)));
*ud = instance;
lua.SetMetatable(info->name);
lua.PushInstance(info->name.GetConstBuffer(), instance);
return 1;
}
@@ -267,10 +338,11 @@ namespace Nz
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
FinalizerFunc finalizer = info->finalizer;
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.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
if (!finalizer || finalizer(lua, *instance))
delete instance;
@@ -283,33 +355,54 @@ namespace Nz
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
std::shared_ptr<ClassInfo>& infoPtr = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
lua.DestroyReference(infoPtr->globalTableRef);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
lua.DestroyReference(info->globalTableRef);
using namespace std; // Obligatoire pour le destructeur
infoPtr.~shared_ptr(); // Si vous voyez une autre façon de faire, je suis preneur
info.~shared_ptr(); // Si vous voyez une autre façon de faire, je suis preneur
return 0;
}
template<class T>
void LuaClass<T>::Get(const std::shared_ptr<ClassInfo>& info, LuaInstance& lua, T* instance)
{
const ClassIndexFunc& getter = info->getter;
if (!getter || !getter(lua, *instance))
{
// Query from the metatable
lua.GetMetatable(info->name); //< Metatable
lua.PushValue(1); //< Field
lua.GetTable(); // Metatable[Field]
lua.Remove(-2); // Remove Metatable
if (!lua.IsValid(-1))
{
for (const ParentFunc& getter : info->parentGetters)
{
lua.Pop(); //< Pop the last nil value
getter(lua, instance);
if (lua.IsValid(-1))
return;
}
}
}
}
template<class T>
int LuaClass<T>::GetterProxy(lua_State* state)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
ClassIndexFunc getter = info->getter;
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
if (!getter(lua, instance))
{
// On accède alors à la table
lua.PushValue(lua.GetIndexOfUpValue(2));
lua.PushValue(-2);
lua.GetTable();
}
T* instance = *static_cast<T**>(lua.CheckUserdata(1, info->name));
lua.Remove(1); //< Remove the instance from the Lua stack
Get(info, lua, instance);
return 1;
}
@@ -318,15 +411,33 @@ namespace Nz
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
T* instance = nullptr;
if (lua.GetMetatable(1))
{
LuaType type = lua.GetField("__type");
if (type == LuaType_String)
{
String name = lua.ToString(-1);
auto it = info->instanceGetters.find(name);
if (it != info->instanceGetters.end())
instance = it->second(lua);
}
lua.Pop(2);
lua.Remove(1); //< Remove the instance from the Lua stack
}
if (!instance)
{
lua.Error("Method cannot be called without an object");
return 0;
}
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
ClassFunc method = info->methods[index];
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
lua.Remove(1); // On enlève l'argument "userdata" du stack
return method(lua, instance);
const ClassFunc& method = info->methods[index];
return method(lua, *instance);
}
template<class T>
@@ -334,17 +445,18 @@ namespace Nz
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
ClassIndexFunc setter = info->setter;
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
const ClassIndexFunc& setter = info->setter;
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
lua.Remove(1); //< Remove the instance from the Lua stack
if (!setter(lua, instance))
{
std::size_t length;
const char* str = lua.ToString(2, &length);
lua.Error("Class \"" + info->name + "\" has no field \"" + String(str, length) + ')');
lua.Error("Class \"" + info->name + "\" has no field \"" + String(str, length) + "\")");
}
return 1;
@@ -355,8 +467,8 @@ namespace Nz
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
StaticIndexFunc getter = info->staticGetter;
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
const StaticIndexFunc& getter = info->staticGetter;
if (!getter(lua))
{
@@ -374,9 +486,9 @@ namespace Nz
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
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)));
StaticFunc method = info->staticMethods[index];
const StaticFunc& method = info->staticMethods[index];
return method(lua);
}
@@ -386,8 +498,8 @@ namespace Nz
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
ClassInfo* info = *static_cast<ClassInfo**>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
StaticIndexFunc setter = info->staticSetter;
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
const StaticIndexFunc& setter = info->staticSetter;
if (!setter(lua))
{
@@ -399,6 +511,17 @@ namespace Nz
return 1;
}
template<class T>
int LuaClass<T>::ToStringProxy(lua_State* state)
{
LuaInstance& lua = *LuaInstance::GetInstance(state);
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
lua.PushString(info->name);
return 1;
}
}
#include <Nazara/Lua/DebugOff.hpp>

View File

@@ -42,12 +42,23 @@ namespace Nz
bool Call(unsigned int argCount);
bool Call(unsigned int argCount, unsigned int resultCount);
template<typename T> T Check(int index);
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;
@@ -59,17 +70,17 @@ namespace Nz
void* CheckUserdata(int index, const String& tname) const;
bool Compare(int index1, int index2, LuaComparison comparison) const;
void Compute(LuaOperation operation);
void Compute(LuaOperation operation) const;
void Concatenate(int count);
void Concatenate(int count) const;
int CreateReference();
void DestroyReference(int ref);
String DumpStack() const;
void Error(const char* message);
void Error(const String& message);
void Error(const char* message) const;
void Error(const String& message) const;
bool Execute(const String& code);
bool ExecuteFromFile(const String& filePath);
@@ -77,8 +88,8 @@ namespace Nz
bool ExecuteFromStream(Stream& stream);
int GetAbsIndex(int index) const;
LuaType GetField(const char* fieldName, int index = -1) const;
LuaType GetField(const String& fieldName, int index = -1) 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;
lua_State* GetInternalState() const;
@@ -94,7 +105,7 @@ namespace Nz
LuaType GetType(int index) const;
const char* GetTypeName(LuaType type) const;
void Insert(int index);
void Insert(int index) const;
bool IsOfType(int index, LuaType type) const;
bool IsOfType(int index, const char* tname) const;
@@ -103,45 +114,51 @@ namespace Nz
long long Length(int index) const;
void MoveTo(LuaInstance* instance, int n);
void MoveTo(LuaInstance* instance, int n) const;
bool NewMetatable(const char* str);
bool NewMetatable(const String& str);
bool Next(int index = -2);
bool Next(int index = -2) const;
void Pop(unsigned int n = 1U);
void Pop(unsigned int n = 1U) const;
template<typename T> int Push(T arg);
void PushBoolean(bool value);
void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0);
void PushFunction(LuaFunction func);
template<typename R, typename... Args> void PushFunction(R(*func)(Args...));
void PushInteger(long long value);
void PushLightUserdata(void* value);
void PushMetatable(const char* str);
void PushMetatable(const String& str);
void PushNil();
void PushNumber(double value);
void PushReference(int ref);
void PushString(const char* str);
void PushString(const char* str, unsigned int size);
void PushString(const String& str);
void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0);
void* PushUserdata(unsigned int size);
void PushValue(int index);
template<typename T> int Push(T arg) const;
void PushBoolean(bool value) const;
void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0) 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 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, unsigned int size) const;
void PushString(const String& str) const;
void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0) const;
void* PushUserdata(unsigned int size) const;
void PushValue(int index) const;
void Remove(int index);
void Replace(int index);
void Remove(int index) const;
void Replace(int index) const;
template<typename T> void SetField(const char* name, T&& arg, int tableIndex = -2);
template<typename T> void SetField(const String& name, T&& arg, int tableIndex = -2);
void SetField(const char* name, int tableIndex = -2);
void SetField(const String& name, int tableIndex = -2);
template<typename T> void SetGlobal(const char* name, T&& arg);
template<typename T> void SetGlobal(const String& name, T&& arg);
void SetGlobal(const char* name);
void SetGlobal(const String& name);
void SetMetatable(const char* tname);
void SetMetatable(const String& tname);
void SetMetatable(int index);
void SetMetatable(const char* tname) const;
void SetMetatable(const String& tname) const;
void SetMetatable(int index) const;
void SetMemoryLimit(UInt32 memoryLimit);
void SetTable(int index = -3);
void SetTable(int index = -3) const;
void SetTimeLimit(UInt32 timeLimit);
bool ToBoolean(int index) const;
@@ -160,6 +177,7 @@ namespace Nz
static LuaInstance* GetInstance(lua_State* state);
private:
template<typename T> T CheckBounds(int index, long long value) const;
bool Run(int argCount, int resultCount);
static void* MemoryAllocator(void *ud, void *ptr, std::size_t osize, std::size_t nsize);

View File

@@ -2,123 +2,187 @@
// 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/LuaInstance.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <limits>
#include <string>
#include <vector>
#include <type_traits>
namespace Nz
{
// Functions args
inline bool LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<bool>)
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, bool* arg, TypeTag<bool>)
{
return instance.CheckBoolean(index);
*arg = instance.CheckBoolean(index);
return 1;
}
inline double LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<double>)
inline unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, bool* arg, bool defValue, TypeTag<bool>)
{
return instance.CheckNumber(index);
*arg = instance.CheckBoolean(index, defValue);
return 1;
}
inline float LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<float>)
{
return static_cast<float>(instance.CheckNumber(index));
}
template<typename T>
std::enable_if_t<std::is_enum<T>::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<T>)
{
return static_cast<T>(LuaImplQueryArg(instance, index, TypeTag<typename std::underlying_type<T>::type>()));
}
template<typename T>
std::enable_if_t<std::is_integral<T>::value && !std::is_unsigned<T>::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<T>)
{
return static_cast<T>(instance.CheckInteger(index));
}
template<typename T>
std::enable_if_t<std::is_unsigned<T>::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<T>)
{
return static_cast<T>(LuaImplQueryArg(instance, index, TypeTag<typename std::make_signed<T>::type>()));
}
inline std::string LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<std::string>)
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);
return std::string(str, strLength);
arg->assign(str, strLength);
return 1;
}
inline String LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<String>)
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);
return String(str, strLength);
arg->Set(str, strLength);
return 1;
}
template<typename T>
T LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<const T&>)
std::enable_if_t<std::is_enum<T>::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag<T>)
{
return LuaImplQueryArg(instance, index, 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, 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_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(LuaInstance& instance, bool val, TypeTag<bool>)
inline int LuaImplReplyVal(const LuaInstance& instance, bool val, TypeTag<bool>)
{
instance.PushBoolean(val);
return 1;
}
inline int LuaImplReplyVal(LuaInstance& instance, double val, TypeTag<double>)
inline int LuaImplReplyVal(const LuaInstance& instance, double val, TypeTag<double>)
{
instance.PushNumber(val);
return 1;
}
inline int LuaImplReplyVal(LuaInstance& instance, float val, TypeTag<float>)
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, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag<T>)
std::enable_if_t<std::is_enum<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_integral<T>::value && !std::is_unsigned<T>::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag<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_unsigned<T>::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag<T>)
{
using SignedT = typename std::make_signed<T>::type;
return LuaImplReplyVal(instance, static_cast<SignedT>(val), TypeTag<SignedT>());
}
inline int LuaImplReplyVal(LuaInstance& instance, std::string val, TypeTag<std::string>)
inline int LuaImplReplyVal(const LuaInstance& instance, std::string val, TypeTag<std::string>)
{
instance.PushString(val.c_str(), val.size());
return 1;
}
inline int LuaImplReplyVal(LuaInstance& instance, String val, TypeTag<String>)
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 (const T& val : valContainer)
{
instance.PushInteger(index++);
if (LuaImplReplyVal(instance, 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(LuaInstance& instance, std::pair<T1, T2> val, TypeTag<std::pair<T1, T2>>)
int LuaImplReplyVal(const LuaInstance& instance, std::pair<T1, T2> val, TypeTag<std::pair<T1, T2>>)
{
int retVal = 0;
@@ -128,143 +192,420 @@ namespace Nz
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<std::tuple_size<DefArgContainer>() - N + FirstDefArg - 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:
LuaImplFunctionProxy(LuaInstance& instance) :
m_instance(instance)
template<typename... DefArgs>
class Impl
{
}
static constexpr std::size_t ArgCount = sizeof...(Args);
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
template<unsigned int N>
void ProcessArgs()
{
// No argument to process
}
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
template<unsigned int N, typename ArgType>
void ProcessArgs()
{
std::get<N>(m_args) = std::move(LuaImplQueryArg(m_instance, N+1, TypeTag<ArgType>()));
}
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
template<int N, typename ArgType1, typename ArgType2, typename... Rest>
void ProcessArgs()
{
ProcessArgs<N, ArgType1>();
ProcessArgs<N+1, ArgType2, Rest...>();
}
public:
Impl(DefArgs... defArgs) :
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
{
}
void ProcessArgs()
{
ProcessArgs<0, Args...>();
}
void ProcessArgs(const LuaInstance& instance) const
{
m_index = 1;
ProcessArgs<0, Args...>(instance);
}
int Invoke(void (*func)(Args...))
{
Apply(func, m_args);
return 0;
}
int Invoke(const LuaInstance& instance, void(*func)(Args...)) const
{
NazaraUnused(instance);
template<typename Ret>
int Invoke(Ret (*func)(Args...))
{
return LuaImplReplyVal(m_instance, std::move(Apply(func, m_args)), TypeTag<decltype(Apply(func, m_args))>());
}
Apply(func, m_args);
return 0;
}
private:
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> m_args;
LuaInstance& m_instance;
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 T, typename... Args>
template<typename... Args>
class LuaImplMethodProxy
{
public:
LuaImplMethodProxy(LuaInstance& instance, T& object) :
m_instance(instance),
m_object(object)
template<typename... DefArgs>
class Impl
{
}
static constexpr std::size_t ArgCount = sizeof...(Args);
static constexpr std::size_t DefArgCount = sizeof...(DefArgs);
template<unsigned int N>
void ProcessArgs()
{
// No argument to process
}
static_assert(ArgCount >= DefArgCount, "There cannot be more default arguments than argument");
template<unsigned int N, typename ArgType>
void ProcessArgs()
{
std::get<N>(m_args) = std::move(LuaImplQueryArg(m_instance, N + 1, TypeTag<ArgType>()));
}
static constexpr std::size_t FirstDefArg = ArgCount - DefArgCount;
template<unsigned int N, typename ArgType1, typename ArgType2, typename... Rest>
void ProcessArgs()
{
ProcessArgs<N, ArgType1>();
ProcessArgs<N + 1, ArgType2, Rest...>();
}
public:
Impl(DefArgs... defArgs) :
m_defaultArgs(std::forward<DefArgs>(defArgs)...)
{
}
void ProcessArgs()
{
ProcessArgs<0, Args...>();
}
void ProcessArgs(const LuaInstance& instance) const
{
m_index = 1;
ProcessArgs<0, Args...>(instance);
}
template<typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(void(P::*func)(Args...))
{
Apply(m_object, func, m_args);
return 0;
}
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);
template<typename P, typename Ret>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(Ret(P::*func)(Args...))
{
return LuaImplReplyVal(m_instance, std::move(Apply(m_object, func, m_args)), TypeTag<decltype(Apply(m_object, func, m_args))>());
}
Apply(object, func, m_args);
return 0;
}
template<typename P>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(void(P::*func)(Args...) const)
{
Apply(m_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 P, typename Ret>
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(Ret(P::*func)(Args...) const)
{
return LuaImplReplyVal(m_instance, std::move(Apply(m_object, func, m_args)), TypeTag<decltype(Apply(m_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, void(P::*func)(Args...) const) const
{
NazaraUnused(instance);
private:
std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> m_args;
LuaInstance& m_instance;
T& m_object;
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, typename PointedType<T>::type>::value, int> Invoke(const LuaInstance& instance, T& object, void(P::*func)(Args...)) const
{
NazaraUnused(instance);
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, const T& object, void(P::*func)(Args...) const) const
{
NazaraUnused(instance);
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))>());
}
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)
T LuaInstance::Check(int* index) const
{
return LuaImplQueryArg(*this, index, TypeTag<T>());
NazaraAssert(index, "Invalid index pointer");
T object;
*index += LuaImplQueryArg(*this, *index, &object, TypeTag<T>());
return object;
}
template<typename T>
int LuaInstance::Push(T arg)
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 R, typename... Args>
void LuaInstance::PushFunction(R (*func)(Args...))
template<typename R, typename... Args, typename... DefArgs>
void LuaInstance::PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const
{
PushFunction([func](LuaInstance& instance) -> int
{
LuaImplFunctionProxy<Args...> handler(instance);
handler.ProcessArgs();
typename LuaImplFunctionProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
return handler.Invoke(func);
PushFunction([func, handler] (LuaInstance& lua) -> int
{
handler.ProcessArgs(lua);
return handler.Invoke(lua, func);
});
}
template<typename T>
void LuaInstance::PushInstance(const char* tname, T* instance) const
{
T** userdata = static_cast<T**>(PushUserdata(sizeof(T*)));
*userdata = instance;
SetMetatable(tname);
}
template<typename T, typename... Args>
void LuaInstance::PushInstance(const char* tname, Args&&... args) const
{
PushInstance(tname, new T(std::forward<Args>(args)...));
}
template<typename T>
void LuaInstance::SetField(const char* name, T&& arg, int tableIndex)
{
Push<T>(std::forward<T>(arg));
SetField(name, tableIndex);
}
template<typename T>
void LuaInstance::SetField(const String& name, T&& arg, int tableIndex)
{
SetField(name.GetConstBuffer(), std::forward<T>(arg), tableIndex);
}
template<typename T>
void LuaInstance::SetGlobal(const char* name, T&& arg)
{
Push<T>(std::forward<T>(arg));
SetGlobal(name);
}
template<typename T>
void LuaInstance::SetGlobal(const String& name, T&& arg)
{
SetGlobal(name.GetConstBuffer(), std::forward<T>(arg));
}
template<typename T>
T LuaInstance::CheckBounds(int index, long long value) const
{
long long minBounds = std::numeric_limits<T>::min();
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);
}
}

View File

@@ -30,32 +30,32 @@
namespace Nz
{
template<typename T> T Approach(T value, T objective, T increment);
template<typename T> /*constexpr*/ T Approach(T value, T objective, T increment);
template<typename T> constexpr T Clamp(T value, T min, T max);
template<typename T> T CountBits(T value);
template<typename T> /*constexpr*/ T CountBits(T value);
template<typename T> constexpr T FromDegrees(T degrees);
template<typename T> constexpr T FromRadians(T radians);
template<typename T> constexpr T DegreeToRadian(T degrees);
template<typename T> T GetNearestPowerOfTwo(T number);
unsigned int GetNumberLength(signed char number);
unsigned int GetNumberLength(unsigned char number);
template<typename T> /*constexpr*/ T GetNearestPowerOfTwo(T number);
/*constexpr*/ unsigned int GetNumberLength(signed char number);
/*constexpr*/ unsigned int GetNumberLength(unsigned char number);
unsigned int GetNumberLength(int number);
unsigned int GetNumberLength(unsigned int number);
/*constexpr*/ unsigned int GetNumberLength(unsigned int number);
unsigned int GetNumberLength(long long number);
unsigned int GetNumberLength(unsigned long long number);
/*constexpr*/ unsigned int GetNumberLength(unsigned long long number);
unsigned int GetNumberLength(float number, UInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
unsigned int GetNumberLength(double number, UInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
unsigned int GetNumberLength(long double number, UInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
template<typename T> unsigned int IntegralLog2(T number);
template<typename T> unsigned int IntegralLog2Pot(T pot);
unsigned int IntegralPow(unsigned int base, unsigned int exponent);
template<typename T, typename T2> T Lerp(T from, T to, T2 interpolation);
template<typename T> T MultiplyAdd(T x, T y, T z);
template<typename T> T NormalizeAngle(T angle);
template<typename T> bool NumberEquals(T a, T b);
template<typename T> bool NumberEquals(T a, T b, T maxDifference);
template<typename T> /*constexpr*/ unsigned int IntegralLog2(T number);
template<typename T> /*constexpr*/ unsigned int IntegralLog2Pot(T pot);
/*constexpr*/ unsigned int IntegralPow(unsigned int base, unsigned int exponent);
template<typename T, typename T2> constexpr T Lerp(const T& from, const T& to, const T2& interpolation);
template<typename T> constexpr T MultiplyAdd(T x, T y, T z);
template<typename T> /*constexpr*/ T NormalizeAngle(T angle);
template<typename T> /*constexpr*/ bool NumberEquals(T a, T b);
template<typename T> /*constexpr*/ bool NumberEquals(T a, T b, T maxDifference);
String NumberToString(long long number, UInt8 radix = 10);
template<typename T> T RadianToDegree(T radians);
template<typename T> constexpr T RadianToDegree(T radians);
long long StringToNumber(String str, UInt8 radix = 10, bool* ok = nullptr);
template<typename T> constexpr T ToDegrees(T angle);
template<typename T> constexpr T ToRadians(T angle);

View File

@@ -98,10 +98,20 @@ namespace Nz
}
}
/*!
* \ingroup math
* \brief Approaches the objective, beginning with value and with increment
* \return The nearest value of the objective you can get with the value and the increment for one step
*
* \param value Initial value
* \param objective Target value
* \parma increment One step value
*/
template<typename T>
T Approach(T value, T objective, T increment)
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline T Approach(T value, T objective, T increment)
{
///TODO: Marquer comme constexpr en C++14
if (value < objective)
return std::min(value + increment, objective);
else if (value > objective)
@@ -110,14 +120,33 @@ namespace Nz
return value;
}
/*!
* \ingroup math
* \brief Clamps value between min and max and returns the expected value
* \return If value is not in the interval of min..max, value obtained is the nearest limit of this interval
*
* \param value Value to clamp
* \param min Minimum of the interval
* \param max Maximum of the interval
*/
template<typename T>
constexpr T Clamp(T value, T min, T max)
{
return std::max(std::min(value, max), min);
}
/*!
* \ingroup math
* \brief Gets number of bits set in the number
* \return The number of bits set to 1
*
* \param value The value to count bits
*/
template<typename T>
T CountBits(T value)
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline T CountBits(T value)
{
// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
unsigned int count = 0;
@@ -130,12 +159,28 @@ namespace Nz
return count;
}
/*!
* \ingroup math
* \brief Converts degree to radian
* \return The representation in radian of the angle in degree (0..2*pi)
*
* \param degrees Angle in degree (this is expected between 0..360)
*/
template<typename T>
constexpr T DegreeToRadian(T degrees)
{
return degrees * T(M_PI/180.0);
}
/*!
* \ingroup math
* \brief Gets the unit from degree and convert it according to NAZARA_MATH_ANGLE_RADIAN
* \return Express the degrees
*
* \param degrees Convert degree to NAZARA_MATH_ANGLE_RADIAN unit
*/
template<typename T>
constexpr T FromDegrees(T degrees)
{
@@ -146,6 +191,14 @@ namespace Nz
#endif
}
/*!
* \ingroup math
* \brief Gets the unit from radian and convert it according to NAZARA_MATH_ANGLE_RADIAN
* \return Express the radians
*
* \param radians Convert radian to NAZARA_MATH_ANGLE_RADIAN unit
*/
template<typename T>
constexpr T FromRadians(T radians)
{
@@ -156,22 +209,37 @@ namespace Nz
#endif
}
/*!
* \ingroup math
* \brief Gets the nearest power of two for the number
* \return First power of two containing the number
*
* \param number Number to get nearest power
*/
template<typename T>
T GetNearestPowerOfTwo(T number)
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline T GetNearestPowerOfTwo(T number)
{
///TODO: Marquer comme constexpr en C++14
T x = 1;
// Tant que x est plus petit que n, on décale ses bits vers la gauche, ce qui revient à multiplier par deux
while (x < number)
x <<= 1;
x <<= 1; // We multiply by 2
return x;
}
inline unsigned int GetNumberLength(signed char number)
/*!
* \ingroup math
* \brief Gets the number of digits to represent the number in base 10
* \return Number of digits
*
* \param number Number to get number of digits
*/
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline unsigned int GetNumberLength(signed char number)
{
///TODO: Marquer comme constexpr en C++14
// Le standard définit le char comme étant codé sur un octet
// Char is expected to be 1 byte
static_assert(sizeof(number) == 1, "Signed char must be one byte-sized");
if (number >= 100)
@@ -188,10 +256,18 @@ namespace Nz
return 4;
}
inline unsigned int GetNumberLength(unsigned char number)
/*!
* \ingroup math
* \brief Gets the number of digits to represent the number in base 10
* \return Number of digits
*
* \param number Number to get number of digits
*/
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline unsigned int GetNumberLength(unsigned char number)
{
///TODO: Marquer comme constexpr en C++14
// Le standard définit le char comme étant codé sur un octet
// Char is expected to be 1 byte
static_assert(sizeof(number) == 1, "Unsigned char must be one byte-sized");
if (number >= 100)
@@ -202,6 +278,14 @@ namespace Nz
return 1;
}
/*!
* \ingroup math
* \brief Gets the number of digits to represent the number in base 10
* \return Number of digits
*
* \param number Number to get number of digits
*/
inline unsigned int GetNumberLength(int number)
{
if (number == 0)
@@ -210,7 +294,16 @@ namespace Nz
return static_cast<unsigned int>(std::log10(std::abs(number))) + (number < 0 ? 2 : 1);
}
inline unsigned int GetNumberLength(unsigned int number)
/*!
* \ingroup math
* \brief Gets the number of digits to represent the number in base 10
* \return Number of digits
*
* \param number Number to get number of digits
*/
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline unsigned int GetNumberLength(unsigned int number)
{
if (number == 0)
return 1;
@@ -218,6 +311,14 @@ namespace Nz
return static_cast<unsigned int>(std::log10(number))+1;
}
/*!
* \ingroup math
* \brief Gets the number of digits to represent the number in base 10
* \return Number of digits
*
* \param number Number to get number of digits
*/
inline unsigned int GetNumberLength(long long number)
{
if (number == 0)
@@ -226,7 +327,16 @@ namespace Nz
return static_cast<unsigned int>(std::log10(std::abs(number))) + (number < 0 ? 2 : 1);
}
inline unsigned int GetNumberLength(unsigned long long number)
/*!
* \ingroup math
* \brief Gets the number of digits to represent the number in base 10
* \return Number of digits
*
* \param number Number to get number of digits
*/
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline unsigned int GetNumberLength(unsigned long long number)
{
if (number == 0)
return 1;
@@ -234,40 +344,99 @@ namespace Nz
return static_cast<unsigned int>(std::log10(number)) + 1;
}
/*!
* \ingroup math
* \brief Gets the number of digits to represent the number in base 10
* \return Number of digits + 1 for the dot
*
* \param number Number to get number of digits
* \param precision Number of digit after the dot
*/
inline unsigned int GetNumberLength(float number, UInt8 precision)
{
// L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999)
return GetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
// The imprecision of floats need a cast (log10(9.99999) = 0.99999)
return GetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus one for the dot
}
/*!
* \ingroup math
* \brief Gets the number of digits to represent the number in base 10
* \return Number of digits + 1 for the dot
*
* \param number Number to get number of digits
* \param precision Number of digit after the dot
*/
inline unsigned int GetNumberLength(double number, UInt8 precision)
{
// L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999)
return GetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
// The imprecision of floats need a cast (log10(9.99999) = 0.99999)
return GetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus one for the dot
}
/*!
* \ingroup math
* \brief Gets the number of digits to represent the number in base 10
* \return Number of digits + 1 for the dot
*
* \param number Number to get number of digits
* \param precision Number of digit after the dot
*/
inline unsigned int GetNumberLength(long double number, UInt8 precision)
{
// L'imprécision des flottants nécessite un cast (log10(9.99999) = 0.99999)
return GetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus un pour le point
// The imprecision of floats need a cast (log10(9.99999) = 0.99999)
return GetNumberLength(static_cast<long long>(number)) + precision + 1; // Plus one for the dot
}
/*!
* \ingroup math
* \brief Gets the log in base 2 of integral number
* \return Log of the number (floor)
*
* \param number To get log in base 2
*
* \remark If number is 0, 0 is returned
*/
template<typename T>
unsigned int IntegralLog2(T number)
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline unsigned int IntegralLog2(T number)
{
// Proxy nécessaire pour éviter un problème de surcharge
// Proxy needed to avoid an overload problem
return Detail::IntegralLog2<T>(number);
}
/*!
* \ingroup math
* \brief Gets the log in base 2 of integral number, only works for power of two !
* \return Log of the number
*
* \param number To get log in base 2
*
* \remark Only works for power of two
* \remark If number is 0, 0 is returned
*/
template<typename T>
unsigned int IntegralLog2Pot(T pot)
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline unsigned int IntegralLog2Pot(T pot)
{
return Detail::IntegralLog2Pot<T>(pot);
}
inline unsigned int IntegralPow(unsigned int base, unsigned int exponent)
/*!
* \ingroup math
* \brief Gets the power of integrals
* \return base^exponent for integral
*
* \param base Base of the exponentation
* \parma exponent Power for the base
*/
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline unsigned int IntegralPow(unsigned int base, unsigned int exponent)
{
///TODO: Marquer comme constexpr en C++14
unsigned int r = 1;
for (unsigned int i = 0; i < exponent; ++i)
r *= base;
@@ -275,26 +444,48 @@ namespace Nz
return r;
}
template<typename T, typename T2>
T Lerp(T from, T to, T2 interpolation)
{
#ifdef NAZARA_DEBUG
if (interpolation < T2(0.0) || interpolation > T2(1.0))
NazaraWarning("Interpolation should be in range [0..1] (Got " + String::Number(interpolation) + ')');
#endif
/*!
* \ingroup math
* \brief Interpolates the value to other one with a factor of interpolation
* \return A new value which is the interpolation of two values
*
* \param from Initial value
* \param to Target value
* \param interpolation Factor of interpolation
*
* \remark interpolation is meant to be between 0 and 1, other values are potentially undefined behavior
* \remark With NAZARA_DEBUG, a NazaraWarning is produced
*
* \see Lerp
*/
template<typename T, typename T2>
constexpr T Lerp(const T& from, const T& to, const T2& interpolation)
{
return from + interpolation * (to - from);
}
/*!
* \ingroup math
* \brief Multiplies X and Y, then add Z
* \return The result of X * Y + Z
*
* \param x is X
* \param y is Y
* \param z is Z
*
* \remark This function is meant to use a special faster instruction in CPU if possible
*/
template<typename T>
T MultiplyAdd(T x, T y, T z)
constexpr T MultiplyAdd(T x, T y, T z)
{
return x*y + z;
return x * y + z;
}
#ifdef FP_FAST_FMAF
template<>
inline float MultiplyAdd(float x, float y, float z)
constexpr float MultiplyAdd(float x, float y, float z)
{
return std::fmaf(x, y, z);
}
@@ -302,7 +493,7 @@ namespace Nz
#ifdef FP_FAST_FMA
template<>
inline double MultiplyAdd(double x, double y, double z)
constexpr double MultiplyAdd(double x, double y, double z)
{
return std::fma(x, y, z);
}
@@ -310,14 +501,23 @@ namespace Nz
#ifdef FP_FAST_FMAL
template<>
inline long double MultiplyAdd(long double x, long double y, long double z)
constexpr long double MultiplyAdd(long double x, long double y, long double z)
{
return std::fmal(x, y, z);
}
#endif
/*!
* \ingroup math
* \brief Normalizes the angle
* \return Normalized value between 0..2*(pi if radian or 180 if degrees)
*
* \param angle Angle to normalize
*/
template<typename T>
T NormalizeAngle(T angle)
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline T NormalizeAngle(T angle)
{
#if NAZARA_MATH_ANGLE_RADIAN
const T limit = T(M_PI);
@@ -333,14 +533,35 @@ namespace Nz
return angle - limit;
}
/*!
* \ingroup math
* \brief Checks whether two numbers are equal
* \return true if they are equal within a certain epsilon
*
* \param a First value
* \param b Second value
*/
template<typename T>
bool NumberEquals(T a, T b)
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline bool NumberEquals(T a, T b)
{
return NumberEquals(a, b, std::numeric_limits<T>::epsilon());
}
/*!
* \ingroup math
* \brief Checks whether two numbers are equal
* \return true if they are equal within the max difference
*
* \param a First value
* \param b Second value
* \param maxDifference Epsilon of comparison (expected to be positive)
*/
template<typename T>
bool NumberEquals(T a, T b, T maxDifference)
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline bool NumberEquals(T a, T b, T maxDifference)
{
if (b > a)
std::swap(a, b);
@@ -349,6 +570,18 @@ namespace Nz
return diff <= maxDifference;
}
/*!
* \ingroup math
* \brief Converts the number to String
* \return String representation of the number
*
* \param number Number to represent
* \param radix Base of the number
*
* \remark radix is meant to be between 2 and 36, other values are potentially undefined behavior
* \remark With NAZARA_MATH_SAFE, a NazaraError is produced and String() is returned
*/
inline String NumberToString(long long number, UInt8 radix)
{
#if NAZARA_MATH_SAFE
@@ -389,12 +622,33 @@ namespace Nz
return str.Reverse();
}
/*!
* \ingroup math
* \brief Converts radian to degree
* \return The representation in degree of the angle in radian (0..360)
*
* \param radians Angle in radian (this is expected between 0..2*pi)
*/
template<typename T>
T RadianToDegree(T radians)
constexpr T RadianToDegree(T radians)
{
return radians * T(180.0/M_PI);
}
/*!
* \ingroup math
* \brief Converts the string to number
* \return Number which is represented by the string
*
* \param str String representation
* \param radix Base of the number
* \param ok Optional argument to know if convertion is correct
*
* \remark radix is meant to be between 2 and 36, other values are potentially undefined behavior
* \remark With NAZARA_MATH_SAFE, a NazaraError is produced and 0 is returned
*/
inline long long StringToNumber(String str, UInt8 radix, bool* ok)
{
#if NAZARA_MATH_SAFE
@@ -444,6 +698,14 @@ namespace Nz
return (negative) ? -static_cast<long long>(total) : total;
}
/*!
* \ingroup math
* \brief Gets the degree from unit and convert it according to NAZARA_MATH_ANGLE_RADIAN
* \return Express in degrees
*
* \param angle Convert degree from NAZARA_MATH_ANGLE_RADIAN unit to degrees
*/
template<typename T>
constexpr T ToDegrees(T angle)
{
@@ -454,6 +716,14 @@ namespace Nz
#endif
}
/*!
* \ingroup math
* \brief Gets the radian from unit and convert it according to NAZARA_MATH_ANGLE_RADIAN
* \return Express in radians
*
* \param angle Convert degree from NAZARA_MATH_ANGLE_RADIAN unit to radians
*/
template<typename T>
constexpr T ToRadians(T angle)
{
@@ -461,8 +731,8 @@ namespace Nz
return angle;
#else
return DegreeToRadian(angle);
#endif
}
#endif
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -14,6 +14,8 @@
namespace Nz
{
struct SerializationContext;
template<typename T>
class BoundingVolume
{
@@ -28,6 +30,8 @@ namespace Nz
BoundingVolume(const BoundingVolume& volume) = default;
~BoundingVolume() = default;
BoundingVolume& ExtendTo(const BoundingVolume& volume);
bool IsFinite() const;
bool IsInfinite() const;
bool IsNull() const;
@@ -66,6 +70,9 @@ namespace Nz
typedef BoundingVolume<double> BoundingVolumed;
typedef BoundingVolume<float> BoundingVolumef;
template<typename T> bool Serialize(SerializationContext& context, const BoundingVolume<T>& boundingVolume);
template<typename T> bool Unserialize(SerializationContext& context, BoundingVolume<T>* boundingVolume);
}
template<typename T>

View File

@@ -1,7 +1,8 @@
// Copyright (C) 2015 Jérôme Leclercq
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Math/Algorithm.hpp>
@@ -13,42 +14,109 @@
namespace Nz
{
/*!
* \ingroup math
* \class Nz::BoundingVolume
* \brief Math class that represents a bounding volume, a combination of a box and an oriented box
*
* \remark You need to call Update not to have undefined behaviour
*/
/*!
* \brief Constructs a BoundingVolume object by default
*
* \remark extend is set to Extend_Null, aabb and obb are uninitialized
*/
template<typename T>
BoundingVolume<T>::BoundingVolume() :
extend(Extend_Null)
{
}
/*!
* \brief Constructs a BoundingVolume object from Extend
* \param Extend Extend of the volume part of enumeration Extend
*
* \remark Aabb and obb are uninitialized
*/
template<typename T>
BoundingVolume<T>::BoundingVolume(Extend Extend)
{
Set(Extend);
}
/*!
* \brief Constructs a BoundingVolume object from its position and sizes
*
* \param X X component of position
* \param Y Y component of position
* \param Z Z component of position
* \param Width Width of the box (following X)
* \param Height Height of the box (following Y)
* \param Depth Depth of the box (following Z)
*
* \remark Aabb is uninitialized
*/
template<typename T>
BoundingVolume<T>::BoundingVolume(T X, T Y, T Z, T Width, T Height, T Depth)
{
Set(X, Y, Z, Width, Height, Depth);
}
/*!
* \brief Constructs a BoundingVolume object from a box
*
* \param box Box<T> object
*
* \remark Aabb is uninitialized
*/
template<typename T>
BoundingVolume<T>::BoundingVolume(const Box<T>& box)
{
Set(box);
}
/*!
* \brief Constructs a BoundingVolume object from an oriented box
*
* \param orientedBox OrientedBox<T> object
*
* \remark Aabb is uninitialized
*/
template<typename T>
BoundingVolume<T>::BoundingVolume(const OrientedBox<T>& orientedBox)
{
Set(orientedBox);
}
/*!
* \brief Constructs a BoundingVolume object from two vectors representing point of the space
* (X, Y, Z) will be the components minimum of the two vectors and the (width, height, depth) will be the components maximum - minimum
*
* \param vec1 First point
* \param vec2 Second point
*
* \remark Aabb is uninitialized
*/
template<typename T>
BoundingVolume<T>::BoundingVolume(const Vector3<T>& vec1, const Vector3<T>& vec2)
{
Set(vec1, vec2);
}
/*!
* \brief Constructs a BoundingVolume object from another type of BoundingVolume
*
* \param volume BoundingVolume of type U to convert to type T
*/
template<typename T>
template<typename U>
BoundingVolume<T>::BoundingVolume(const BoundingVolume<U>& volume)
@@ -56,24 +124,92 @@ namespace Nz
Set(volume);
}
/*!
* \brief Extends the bounding volume to contain another bounding volume
* \return A reference to the the bounding volume
*
* \param volume Other volume to contain
*
* \remark Extending to a null bounding volume has no effect while extending to a infinite bounding volume will set it as infinite
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::ExtendTo(const BoundingVolume& volume)
{
switch (extend)
{
case Extend_Finite:
{
switch (volume.extend)
{
case Extend_Finite:
{
// Extend the OBB local box
obb.localBox.ExtendTo(volume.obb.localBox);
break;
}
case Extend_Infinite:
MakeInfinite();
break;
case Extend_Null:
break;
}
break;
}
case Extend_Infinite:
break; //< We already contain the bounding volume
case Extend_Null:
Set(volume);
break;
}
return *this;
}
/*!
* \brief Checks whether the volume is finite
* \return true if extend is Extend_Finite
*/
template<typename T>
bool BoundingVolume<T>::IsFinite() const
{
return extend == Extend_Finite;
}
/*!
* \brief Checks whether the volume is infinite
* \return true if extend is Extend_Infinite
*/
template<typename T>
bool BoundingVolume<T>::IsInfinite() const
{
return extend == Extend_Infinite;
}
/*!
* \brief Checks whether the volume is null
* \return true if extend is Extend_Null
*/
template<typename T>
bool BoundingVolume<T>::IsNull() const
{
return extend == Extend_Null;
}
/*!
* \brief Makes the bounding volume infinite
* \return A reference to this bounding volume with Extend_Infinite for extend
*
* \see Infinite
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::MakeInfinite()
{
@@ -82,6 +218,13 @@ namespace Nz
return *this;
}
/*!
* \brief Makes the bounding volume null
* \return A reference to this bounding volume with Extend_Null for extend
*
* \see Null
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::MakeNull()
{
@@ -90,6 +233,15 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the extend of the bounding volume from Extend
* \return A reference to this bounding volume
*
* \param Extend New extend
*
* \remark This method is meant to be called with Extend_Infinite or Extend_Null
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::Set(Extend Extend)
{
@@ -98,6 +250,18 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the bounding volume
* \return A reference to this bounding volume
*
* \param X X position
* \param Y Y position
* \param Z Z position
* \param Width Width of the oriented box (following X)
* \param Height Height of the oriented box (following Y)
* \param Depth Depth of the oriented box (following Z)
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::Set(T X, T Y, T Z, T Width, T Height, T Depth)
{
@@ -107,15 +271,29 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the bounding volume from another bounding volume
* \return A reference to this bounding volume
*
* \param volume The other bounding volume
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::Set(const BoundingVolume<T>& volume)
{
obb.Set(volume.obb); // Seul l'OBB est importante pour la suite
obb.Set(volume.obb); // Only OBB is important for the moment
extend = volume.extend;
return *this;
}
/*!
* \brief Sets the components of the bounding volume from a box
* \return A reference to this bounding volume
*
* \param box Box<T> object
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::Set(const Box<T>& box)
{
@@ -125,6 +303,13 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the bounding volume from an oriented box
* \return A reference to this bounding volume
*
* \param orientedBox OrientedBox<T> object
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::Set(const OrientedBox<T>& orientedBox)
{
@@ -134,6 +319,14 @@ namespace Nz
return *this;
}
/*!
* \brief Sets a BoundingVolume object from two vectors representing point of the space
* (X, Y, Z) will be the components minimum of the two vectors and the (width, height, depth) will be the components maximum - minimum
*
* \param vec1 First point
* \param vec2 Second point
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::Set(const Vector3<T>& vec1, const Vector3<T>& vec2)
{
@@ -143,6 +336,13 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the bounding volume from another type of BoundingVolume
* \return A reference to this bounding volume
*
* \param volume BoundingVolume of type U to convert its components
*/
template<typename T>
template<typename U>
BoundingVolume<T>& BoundingVolume<T>::Set(const BoundingVolume<U>& volume)
@@ -153,6 +353,13 @@ namespace Nz
return *this;
}
/*!
* \brief Gives a string representation
* \return A string representation of the object: "BoundingVolume(localBox="")" if finite, or "BoundingVolume(Infinite)" or "BoundingVolume(Null)"
*
* \remark If enumeration is not defined in Extend, a NazaraError is thrown and "BoundingVolume(ERROR)" is returned
*/
template<typename T>
String BoundingVolume<T>::ToString() const
{
@@ -173,6 +380,12 @@ namespace Nz
return "BoundingVolume(ERROR)";
}
/*!
* \brief Updates the obb and the aabb of the bounding volume
*
* \param transformMatrix Matrix4 which represents the transformation to apply
*/
template<typename T>
void BoundingVolume<T>::Update(const Matrix4<T>& transformMatrix)
{
@@ -183,6 +396,12 @@ namespace Nz
aabb.ExtendTo(obb(i));
}
/*!
* \brief Updates the obb and the aabb of the bounding volume
*
* \param translation Vector3 which represents the translation to apply
*/
template<typename T>
void BoundingVolume<T>::Update(const Vector3<T>& translation)
{
@@ -193,6 +412,13 @@ namespace Nz
aabb.ExtendTo(obb(i));
}
/*!
* \brief Multiplies the lengths of the obb with the scalar
* \return A BoundingVolume where the position is the same and width, height and depth are the product of the old width, height and depth and the scalar
*
* \param scale The scalar to multiply width, height and depth with
*/
template<typename T>
BoundingVolume<T> BoundingVolume<T>::operator*(T scalar) const
{
@@ -202,6 +428,13 @@ namespace Nz
return volume;
}
/*!
* \brief Multiplies the lengths of this bounding volume with the scalar
* \return A reference to this bounding volume where lengths are the product of these lengths and the scalar
*
* \param scalar The scalar to multiply width, height and depth with
*/
template<typename T>
BoundingVolume<T>& BoundingVolume<T>::operator*=(T scalar)
{
@@ -210,6 +443,13 @@ namespace Nz
return *this;
}
/*!
* \brief Compares the bounding volume to other one
* \return true if the two bounding volumes are the same
*
* \param volume Other bounding volume to compare with
*/
template<typename T>
bool BoundingVolume<T>::operator==(const BoundingVolume& volume) const
{
@@ -222,12 +462,26 @@ namespace Nz
return false;
}
/*!
* \brief Compares the bounding volume to other one
* \return false if the two bounding volumes are the same
*
* \param volume Other bounding volume to compare with
*/
template<typename T>
bool BoundingVolume<T>::operator!=(const BoundingVolume& volume) const
{
return !operator==(volume);
}
/*!
* \brief Shorthand for the bounding volume (Extend_Infinite)
* \return A bounding volume with Extend_Infinite
*
* \see MakeInfinite
*/
template<typename T>
BoundingVolume<T> BoundingVolume<T>::Infinite()
{
@@ -237,6 +491,21 @@ namespace Nz
return volume;
}
/*!
* \brief Interpolates the bounding volume to other one with a factor of interpolation
* \return A new bounding volume box which is the interpolation of two bounding volumes
*
* \param from Initial bounding volume
* \param to Target bounding volume
* \param interpolation Factor of interpolation
*
* \remark interpolation is meant to be between 0 and 1, other values are potentially undefined behavior
* \remark With NAZARA_DEBUG, a NazaraError is thrown and Null() is returned
* \remark If enumeration is not defined in Extend, a NazaraError is thrown and Null() is returned
*
* \see Lerp
*/
template<typename T>
BoundingVolume<T> BoundingVolume<T>::Lerp(const BoundingVolume& from, const BoundingVolume& to, T interpolation)
{
@@ -275,13 +544,13 @@ namespace Nz
return from.obb * interpolation;
}
// Si nous arrivons ici c'est que l'extend est invalide
// If we arrive here, the extend is invalid
NazaraError("Invalid extend type (From) (0x" + String::Number(from.extend, 16) + ')');
return Null();
}
case Extend_Infinite:
return Infinite(); // Un petit peu d'infini est infini quand même ;)
return Infinite(); // A little bit of infinity is already too much ;)
case Extend_Null:
{
@@ -297,17 +566,24 @@ namespace Nz
return Null();
}
// Si nous arrivons ici c'est que l'extend est invalide
// If we arrive here, the extend is invalid
NazaraError("Invalid extend type (From) (0x" + String::Number(from.extend, 16) + ')');
return Null();
}
}
// Si nous arrivons ici c'est que l'extend est invalide
// If we arrive here, the extend is invalid
NazaraError("Invalid extend type (To) (0x" + String::Number(to.extend, 16) + ')');
return Null();
}
/*!
* \brief Shorthand for the bounding volume (Extend_Null)
* \return A bounding volume with Extend_Null
*
* \see MakeNull
*/
template<typename T>
BoundingVolume<T> BoundingVolume<T>::Null()
{
@@ -317,12 +593,74 @@ namespace Nz
return volume;
}
/*!
* \brief Serializes a BoundingVolume
* \return true if successfully serialized
*
* \param context Serialization context
* \param boundingVolume Input bounding volume
*
* \remark Does not save OBB corners
*/
template<typename T>
std::ostream& operator<<(std::ostream& out, const BoundingVolume<T>& volume)
bool Serialize(SerializationContext& context, const BoundingVolume<T>& boundingVolume)
{
out << volume.ToString();
return out;
if (!Serialize(context, static_cast<UInt8>(boundingVolume.extend)))
return false;
if (!Serialize(context, boundingVolume.aabb))
return false;
if (!Serialize(context, boundingVolume.obb))
return false;
return true;
}
/*!
* \brief Unserializes a BoundingVolume
* \return true if successfully unserialized
*
* \param context Serialization context
* \param boundingVolume Output bounding volume
*
* \remark The resulting oriented box corners will *not* be updated, a call to Update is required
*/
template<typename T>
bool Unserialize(SerializationContext& context, BoundingVolume<T>* boundingVolume)
{
UInt8 extend;
if (!Unserialize(context, &extend))
return false;
if (extend > Extend_Max)
return false;
boundingVolume->extend = static_cast<Extend>(extend);
if (!Unserialize(context, &boundingVolume->aabb))
return false;
if (!Unserialize(context, &boundingVolume->obb))
return false;
return true;
}
}
/*!
* \brief Output operator
* \return The stream
*
* \param out The stream
* \param volume The bounding volume to output
*/
template<typename T>
std::ostream& operator<<(std::ostream& out, const Nz::BoundingVolume<T>& volume)
{
out << volume.ToString();
return out;
}
#undef F

View File

@@ -16,6 +16,8 @@
namespace Nz
{
struct SerializationContext;
template<typename T>
class Box
{
@@ -40,8 +42,8 @@ namespace Nz
Box& ExtendTo(const Vector3<T>& point);
Sphere<T> GetBoundingSphere() const;
Vector3<T> GetCorner(BoxCorner corner) const;
Vector3<T> GetCenter() const;
Vector3<T> GetCorner(BoxCorner corner) const;
Vector3<T> GetLengths() const;
Vector3<T> GetMaximum() const;
Vector3<T> GetMinimum() const;
@@ -96,6 +98,9 @@ namespace Nz
typedef Box<unsigned int> Boxui;
typedef Box<Int32> Boxi32;
typedef Box<UInt32> Boxui32;
template<typename T> bool Serialize(SerializationContext& context, const Box<T>& box);
template<typename T> bool Unserialize(SerializationContext& context, Box<T>* box);
}
template<typename T>

View File

@@ -2,6 +2,7 @@
// This file is part of the "Nazara Engine - Mathematics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <algorithm>
@@ -12,41 +13,104 @@
namespace Nz
{
/*!
* \ingroup math
* \class Nz::Box
* \brief Math class that represents a three dimensional box
*/
/*!
* \brief Constructs a Box object from its width, height and depth
*
* \param Width Width of the box (following X)
* \param Height Height of the box (following Y)
* \param Depth Depth of the box (following Z)
*
* \remark Position will be (0, 0, 0)
*/
template<typename T>
Box<T>::Box(T Width, T Height, T Depth)
{
Set(Width, Height, Depth);
}
/*!
* \brief Constructs a Rect<T> object from its position, width, height and depth
*
* \param X X position
* \param Y Y position
* \param Z Z position
* \param Width Width of the box (following X)
* \param Height Height of the box (following Y)
* \param Depth Depth of the box (following Z)
*/
template<typename T>
Box<T>::Box(T X, T Y, T Z, T Width, T Height, T Depth)
{
Set(X, Y, Z, Width, Height, Depth);
}
/*!
* \brief Constructs a Box object from an array of six elements
*
* \param vec[6] vec[0] is X position, vec[1] is Y position, vec[2] is Z position, vec[3] is width, vec[4] is height and vec[5] is depth
*/
template<typename T>
Box<T>::Box(const T vec[6])
{
Set(vec);
}
/*!
* \brief Constructs a Box object from a Rect
*
* \param rect Rectangle which describes (X, Y) position and (width, height) lenghts
*
* \remark Z position is 0 and depth is 1
*/
template<typename T>
Box<T>::Box(const Rect<T>& rect)
{
Set(rect);
}
/*!
* \brief Constructs a Box object from a vector representing width, height and depth
*
* \param lengths (Width, Height, Depth) of the box
*
* \remark Positions will be (0, 0, 0)
*/
template<typename T>
Box<T>::Box(const Vector3<T>& lengths)
{
Set(lengths);
}
/*!
* \brief Constructs a Box object from two vectors representing point of the space
* (X, Y, Z) will be the components minimum of the two vectors and the (width, height, depth) will be the components maximum - minimum
*
* \param vec1 First point
* \param vec2 Second point
*/
template<typename T>
Box<T>::Box(const Vector3<T>& vec1, const Vector3<T>& vec2)
{
Set(vec1, vec2);
}
template<typename T>
Box<T>::Box(const T vec[6])
{
Set(vec);
}
/*!
* \brief Constructs a Box object from another type of Box
*
* \param box Box of type U to convert to type T
*/
template<typename T>
template<typename U>
@@ -55,27 +119,67 @@ namespace Nz
Set(box);
}
/*!
* \brief Tests whether the box contains the provided point inclusive of the edge of the box
* \return true if inclusive
*
* \param X X position of the point
* \param Y Y position of the point
* \param Z Z position of the point
*
* \see Contains
*/
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;
}
/*!
* \brief Tests whether the box contains the provided box inclusive of the edge of the box
* \return true if inclusive
*
* \param box Other box to test
*
* \see Contains
*/
template<typename T>
bool Box<T>::Contains(const Box<T>& box) const
{
return Contains(box.x, box.y, box.z) &&
Contains(box.x + box.width, box.y + box.height, box.z + box.depth);
Contains(box.x + box.width, box.y + box.height, box.z + box.depth);
}
/*!
* \brief Tests whether the box contains the provided point inclusive of the edge of the box
* \return true if inclusive
*
* \param point Position of the point
*
* \see Contains
*/
template<typename T>
bool Box<T>::Contains(const Vector3<T>& point) const
{
return Contains(point.x, point.y, point.z);
}
/*!
* \brief Extends the box to contain the point in the boundary
* \return A reference to this box extended
*
* \param X X position of the point
* \param Y Y position of the point
* \param Z Z position of the point
*
* \see ExtendTo
*/
template<typename T>
Box<T>& Box<T>::ExtendTo(T X, T Y, T Z)
{
@@ -94,6 +198,15 @@ namespace Nz
return *this;
}
/*!
* \brief Extends the box to contain the box
* \return A reference to this box extended
*
* \param box Other box to contain
*
* \see ExtendTo
*/
template<typename T>
Box<T>& Box<T>::ExtendTo(const Box& box)
{
@@ -112,12 +225,54 @@ namespace Nz
return *this;
}
/*!
* \brief Extends the box to contain the point in the boundary
* \return A reference to this box extended
*
* \param point Position of the point
*
* \see ExtendTo
*/
template<typename T>
Box<T>& Box<T>::ExtendTo(const Vector3<T>& point)
{
return ExtendTo(point.x, point.y, point.z);
}
/*!
* \brief Gets the bounding sphere for the box
* \return A sphere containing the box
*
* \see GetSquaredBoundingSphere
*/
template<typename T>
Sphere<T> Box<T>::GetBoundingSphere() const
{
return Sphere<T>(GetCenter(), GetRadius());
}
/*!
* \brief Gets a Vector3 for the center
* \return The position of the center of the box
*/
template<typename T>
Vector3<T> Box<T>::GetCenter() const
{
return GetPosition() + GetLengths() / F(2.0);
}
/*!
* \brief Gets the Vector3 for the corner
* \return The position of the corner of the box according to enum BoxCorner
*
* \param corner Enumeration of type BoxCorner
*
* \remark If enumeration is not defined in BoxCorner, a NazaraError is thrown and a Vector3 uninitialised is returned
*/
template<typename T>
Vector3<T> Box<T>::GetCorner(BoxCorner corner) const
{
@@ -152,17 +307,10 @@ namespace Nz
return Vector3<T>();
}
template<typename T>
Sphere<T> Box<T>::GetBoundingSphere() const
{
return Sphere<T>(GetCenter(), GetRadius());
}
template<typename T>
Vector3<T> Box<T>::GetCenter() const
{
return GetPosition() + GetLengths()/F(2.0);
}
/*!
* \brief Gets a Vector3 for the lengths
* \return The lengths of the box (width, height, depth)
*/
template<typename T>
Vector3<T> Box<T>::GetLengths() const
@@ -170,19 +318,41 @@ namespace Nz
return Vector3<T>(width, height, depth);
}
/*!
* \brief Gets a Vector3 for the maximum point
* \return The BoxCorner_NearRightTop of the box
*
* \see GetCorner
*/
template<typename T>
Vector3<T> Box<T>::GetMaximum() const
{
return GetPosition() + GetLengths();
}
/*!
* \brief Gets a Vector3 for the minimum point
* \return The BoxCorner_FarLeftBottom of the box
*
* \see GetCorner, GetPosition
*/
template<typename T>
Vector3<T> Box<T>::GetMinimum() const
{
///DOC: Alias de GetPosition()
return GetPosition();
}
/*!
* \brief Computes the negative vertex of one direction
* \return The position of the vertex on the box in the opposite way of the normal while considering the center. It means that if the normal has one component negative, the component is set to width, height or depth corresponding to the sign
*
* \param normal Vector indicating a direction
*
* \see GetPositiveVertex
*/
template<typename T>
Vector3<T> Box<T>::GetNegativeVertex(const Vector3<T>& normal) const
{
@@ -200,12 +370,28 @@ namespace Nz
return neg;
}
/*!
* \brief Gets a Vector3 for the position
* \return The BoxCorner_FarLeftBottom of the box
*
* \see GetCorner, GetMinimum
*/
template<typename T>
Vector3<T> Box<T>::GetPosition() const
{
return Vector3<T>(x, y, z);
}
/*!
* \brief Computes the positive vertex of one direction
* \return The position of the vertex on the box in the same way of the normal while considering the center. It means that if the normal has one component positive, the component is set to width or height corresponding to the sign
*
* \param normal Vector indicating a direction
*
* \see GetNegativeVertex
*/
template<typename T>
Vector3<T> Box<T>::GetPositiveVertex(const Vector3<T>& normal) const
{
@@ -223,27 +409,52 @@ namespace Nz
return pos;
}
/*!
* \brief Gets the radius of the box
* \return Value of the radius which is the biggest distance between a corner and the center
*/
template<typename T>
T Box<T>::GetRadius() const
{
return std::sqrt(GetSquaredRadius());
}
/*!
* \brief Gets the squared bounding sphere for the box
* \return A sphere containing the box
*
* \see GetBoundingSphere
*/
template<typename T>
Sphere<T> Box<T>::GetSquaredBoundingSphere() const
{
return Sphere<T>(GetCenter(), GetSquaredRadius());
}
/*!
* \brief Gets the squared radius of the box
* \return Value of the squared radius which is the squared of biggest distance between a corner and the center
*/
template<typename T>
T Box<T>::GetSquaredRadius() const
{
Vector3<T> size(GetLengths());
size /= F(2.0); // La taille étant relative à la position (minimum) de la boite et non pas à son centre
size /= F(2.0); // The size only depends on the lengths and not the center
return size.GetSquaredLength();
}
/*!
* \brief Checks whether or not this box intersects another one
* \return true if the box intersects
*
* \param box Box to check
* \param intersection Optional argument for the box which represent the intersection
*/
template<typename T>
bool Box<T>::Intersect(const Box& box, Box* intersection) const
{
@@ -275,12 +486,24 @@ namespace Nz
return true;
}
/*!
* \brief Checks whether this box is valid
* \return true if the box has a strictly positive width, height and depth
*/
template<typename T>
bool Box<T>::IsValid() const
{
return width > F(0.0) && height > F(0.0) && depth > F(0.0);
}
/*!
* \brief Makes the box position (0, 0, 0) and lengths (0, 0, 0)
* \return A reference to this box with position (0, 0, 0) and lengths (0, 0, 0)
*
* \see Zero
*/
template<typename T>
Box<T>& Box<T>::MakeZero()
{
@@ -294,6 +517,17 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the box with width, height and depth
* \return A reference to this box
*
* \param Width Width of the box (following X)
* \param Height Height of the box (following Y)
* \param Depth Depth of the box (following Z)
*
* \remark Position will be (0, 0, 0)
*/
template<typename T>
Box<T>& Box<T>::Set(T Width, T Height, T Depth)
{
@@ -307,6 +541,17 @@ namespace Nz
return *this;
}
/*!
* \brief Constructs a Box object from its position and sizes
*
* \param X X component of position
* \param Y Y component of position
* \param Z Z component of position
* \param Width Width of the box (following X)
* \param Height Height of the box (following Y)
* \param Depth Depth of the box (following Z)
*/
template<typename T>
Box<T>& Box<T>::Set(T X, T Y, T Z, T Width, T Height, T Depth)
{
@@ -320,6 +565,13 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the box from an array of six elements
* \return A reference to this box
*
* \param box[6] box[0] is X position, box[1] is Y position, box[2] is Z position, box[3] is width, box[4] is height and box[5] is depth
*/
template<typename T>
Box<T>& Box<T>::Set(const T box[6])
{
@@ -333,6 +585,13 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the box with components from another
* \return A reference to this box
*
* \param box The other box
*/
template<typename T>
Box<T>& Box<T>::Set(const Box& box)
{
@@ -341,6 +600,15 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the box with components from a Rect
* \return A reference to this box
*
* \param rect Rectangle which describes (X, Y) position and (width, height) lenghts
*
* \remark Z position is 0 and depth is 1
*/
template<typename T>
Box<T>& Box<T>::Set(const Rect<T>& rect)
{
@@ -354,25 +622,50 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the box from a vector representing width, height and depth
* \return A reference to this box
*
* \param lengths (Width, Height, depth) of the box
*
* \remark Position will be (0, 0, 0)
*/
template<typename T>
Box<T>& Box<T>::Set(const Vector3<T>& lengths)
{
return Set(lengths.x, lengths.y, lengths.z);
}
/*!
* \brief Sets the components of the box from two vectors representing point of the space
* (X, Y, Z) will be the components minimum of the two vectors and the (width, height, depth) will be the components maximum - minimum
* \return A reference to this box
*
* \param vec1 First point
* \param vec2 Second point
*/
template<typename T>
Box<T>& Box<T>::Set(const Vector3<T>& vec1, const Vector3<T>& vec2)
{
x = std::min(vec1.x, vec2.x);
y = std::min(vec1.y, vec2.y);
z = std::min(vec1.z, vec2.z);
width = (vec2.x > vec1.x) ? vec2.x-vec1.x : vec1.x-vec2.x;
height = (vec2.y > vec1.y) ? vec2.y-vec1.y : vec1.y-vec2.y;
depth = (vec2.z > vec1.z) ? vec2.z-vec1.z : vec1.z-vec2.z;
width = (vec2.x > vec1.x) ? vec2.x - vec1.x : vec1.x - vec2.x;
height = (vec2.y > vec1.y) ? vec2.y - vec1.y : vec1.y - vec2.y;
depth = (vec2.z > vec1.z) ? vec2.z - vec1.z : vec1.z - vec2.z;
return *this;
}
/*!
* \brief Sets the components of the box from another type of Box
* \return A reference to this box
*
* \param box Box of type U to convert its components
*/
template<typename T>
template<typename U>
Box<T>& Box<T>::Set(const Box<U>& box)
@@ -387,6 +680,11 @@ namespace Nz
return *this;
}
/*!
* \brief Gives a string representation
* \return A string representation of the object: "Box(x, y, z, width, height, depth)"
*/
template<typename T>
String Box<T>::ToString() const
{
@@ -395,19 +693,34 @@ namespace Nz
return ss << "Box(" << x << ", " << y << ", " << z << ", " << width << ", " << height << ", " << depth << ')';
}
/*!
* \brief Transforms the box according to the matrix
* \return A reference to this box transformed
*
* \param matrix Matrix4 representing the transformation
* \param applyTranslation Should transform the position or the direction
*/
template<typename T>
Box<T>& Box<T>::Transform(const Matrix4<T>& matrix, bool applyTranslation)
{
Vector3<T> center = matrix.Transform(GetCenter(), (applyTranslation) ? F(1.0) : F(0.0)); // Valeur multipliant la translation
Vector3<T> halfSize = GetLengths()/F(2.0);
Vector3<T> center = matrix.Transform(GetCenter(), (applyTranslation) ? F(1.0) : F(0.0)); // Value multiplying the translation
Vector3<T> halfSize = GetLengths() / F(2.0);
halfSize.Set(std::abs(matrix(0,0))*halfSize.x + std::abs(matrix(1,0))*halfSize.y + std::abs(matrix(2,0))*halfSize.z,
std::abs(matrix(0,1))*halfSize.x + std::abs(matrix(1,1))*halfSize.y + std::abs(matrix(2,1))*halfSize.z,
std::abs(matrix(0,2))*halfSize.x + std::abs(matrix(1,2))*halfSize.y + std::abs(matrix(2,2))*halfSize.z);
halfSize.Set(std::abs(matrix(0,0)) * halfSize.x + std::abs(matrix(1,0)) * halfSize.y + std::abs(matrix(2,0)) * halfSize.z,
std::abs(matrix(0,1)) * halfSize.x + std::abs(matrix(1,1)) * halfSize.y + std::abs(matrix(2,1)) * halfSize.z,
std::abs(matrix(0,2)) * halfSize.x + std::abs(matrix(1,2)) * halfSize.y + std::abs(matrix(2,2)) * halfSize.z);
return Set(center - halfSize, center + halfSize);
}
/*!
* \brief Translates the box
* \return A reference to this box translated
*
* \param translation Vector3 which is the translation for the position
*/
template<typename T>
Box<T>& Box<T>::Translate(const Vector3<T>& translation)
{
@@ -418,6 +731,15 @@ namespace Nz
return *this;
}
/*!
* \brief Returns the ith element of the box
* \return A reference to the ith element of the box
*
* \remark Access to index greather than 6 is undefined behavior
* \remark Produce a NazaraError if you try to acces to index greather than 6 with NAZARA_MATH_SAFE defined
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and one of you try to acces to index greather than 6
*/
template<typename T>
T& Box<T>::operator[](unsigned int i)
{
@@ -435,6 +757,15 @@ namespace Nz
return *(&x+i);
}
/*!
* \brief Returns the ith element of the box
* \return A value to the ith element of the box
*
* \remark Access to index greather than 6 is undefined behavior
* \remark Produce a NazaraError if you try to acces to index greather than 6 with NAZARA_MATH_SAFE defined
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and one of you try to acces to index greather than 6
*/
template<typename T>
T Box<T>::operator[](unsigned int i) const
{
@@ -452,18 +783,39 @@ namespace Nz
return *(&x+i);
}
/*!
* \brief Multiplies the lengths with the scalar
* \return A box where the position is the same and width, height and depth are the product of the old width, height and depth and the scalar
*
* \param scale The scalar to multiply width, height and depth with
*/
template<typename T>
Box<T> Box<T>::operator*(T scalar) const
{
return Box(x, y, z, width*scalar, height*scalar, depth*scalar);
return Box(x, y, z, width * scalar, height * scalar, depth * scalar);
}
/*!
* \brief Multiplies the lengths with the vector
* \return A box where the position is the same and width, height and depth are the product of the old width, height and depth with the vec
*
* \param vec The vector where component one multiply width, two height and three depth
*/
template<typename T>
Box<T> Box<T>::operator*(const Vector3<T>& vec) const
{
return Box(x, y, z, width*vec.x, height*vec.y, depth*vec.z);
return Box(x, y, z, width * vec.x, height * vec.y, depth * vec.z);
}
/*!
* \brief Multiplies the lengths of this box with the scalar
* \return A reference to this box where lengths are the product of these lengths and the scalar
*
* \param scalar The scalar to multiply width, height and depth with
*/
template<typename T>
Box<T>& Box<T>::operator*=(T scalar)
{
@@ -474,6 +826,13 @@ namespace Nz
return *this;
}
/*!
* \brief Multiplies the lengths of this box with the vector
* \return A reference to this box where width, height and depth are the product of the old width, height and depth with the vec
*
* \param vec The vector where component one multiply width, two height and three depth
*/
template<typename T>
Box<T>& Box<T>::operator*=(const Vector3<T>& vec)
{
@@ -484,19 +843,47 @@ namespace Nz
return *this;
}
/*!
* \brief Compares the box to other one
* \return true if the boxes are the same
*
* \param box Other box to compare with
*/
template<typename T>
bool Box<T>::operator==(const Box& box) const
{
return NumberEquals(x, box.x) && NumberEquals(y, box.y) && NumberEquals(z, box.z) &&
NumberEquals(width, box.width) && NumberEquals(height, box.height) && NumberEquals(depth, box.depth);
NumberEquals(width, box.width) && NumberEquals(height, box.height) && NumberEquals(depth, box.depth);
}
/*!
* \brief Compares the box to other one
* \return false if the boxes are the same
*
* \param box Other box to compare with
*/
template<typename T>
bool Box<T>::operator!=(const Box& box) const
{
return !operator==(box);
}
/*!
* \brief Interpolates the box to other one with a factor of interpolation
* \return A new box which is the interpolation of two rectangles
*
* \param from Initial box
* \param to Target box
* \param interpolation Factor of interpolation
*
* \remark interpolation is meant to be between 0 and 1, other values are potentially undefined behavior
* \remark With NAZARA_DEBUG, a NazaraError is thrown and Zero() is returned
*
* \see Lerp
*/
template<typename T>
Box<T> Box<T>::Lerp(const Box& from, const Box& to, T interpolation)
{
@@ -519,6 +906,13 @@ namespace Nz
return box;
}
/*!
* \brief Shorthand for the box (0, 0, 0, 0, 0, 0)
* \return A box with position (0, 0, 0) and lengths (0, 0, 0)
*
* \see MakeZero
*/
template<typename T>
Box<T> Box<T>::Zero()
{
@@ -527,8 +921,78 @@ namespace Nz
return box;
}
/*!
* \brief Serializes a Box
* \return true if successfully serialized
*
* \param context Serialization context
* \param box Input Box
*/
template<typename T>
bool Serialize(SerializationContext& context, const Box<T>& box)
{
if (!Serialize(context, box.x))
return false;
if (!Serialize(context, box.y))
return false;
if (!Serialize(context, box.z))
return false;
if (!Serialize(context, box.width))
return false;
if (!Serialize(context, box.height))
return false;
if (!Serialize(context, box.depth))
return false;
return true;
}
/*!
* \brief Unserializes a Box
* \return true if successfully unserialized
*
* \param context Serialization context
* \param box Output Box
*/
template<typename T>
bool Unserialize(SerializationContext& context, Box<T>* box)
{
if (!Unserialize(context, &box->x))
return false;
if (!Unserialize(context, &box->y))
return false;
if (!Unserialize(context, &box->z))
return false;
if (!Unserialize(context, &box->width))
return false;
if (!Unserialize(context, &box->height))
return false;
if (!Unserialize(context, &box->depth))
return false;
return true;
}
}
/*!
* \brief Output operator
* \return The stream
*
* \param out The stream
* \param box The box to output
*/
template<typename T>
std::ostream& operator<<(std::ostream& out, const Nz::Box<T>& box)
{

Some files were not shown because too many files have changed in this diff Show More