Merge branch 'master' into vulkan

This commit is contained in:
Lynix
2020-02-23 00:46:48 +01:00
382 changed files with 50494 additions and 5037 deletions

View File

@@ -10,31 +10,15 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Audio/SoundEmitter.hpp>
#include <Nazara/Audio/SoundStream.hpp>
#include <Nazara/Core/MovablePtr.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
namespace Nz
{
struct MusicParams : ResourceParameters
{
bool forceMono = false;
bool IsValid() const;
};
class Music;
class SoundStream;
using MusicLoader = ResourceLoader<Music, MusicParams>;
struct MusicImpl;
class NAZARA_AUDIO_API Music : public Resource, public SoundEmitter
{
friend MusicLoader;
public:
Music() = default;
Music(const Music&) = delete;
@@ -55,9 +39,9 @@ namespace Nz
bool IsLooping() const override;
bool OpenFromFile(const String& filePath, const MusicParams& params = MusicParams());
bool OpenFromMemory(const void* data, std::size_t size, const MusicParams& params = MusicParams());
bool OpenFromStream(Stream& stream, const MusicParams& params = MusicParams());
bool OpenFromFile(const String& filePath, const SoundStreamParams& params = SoundStreamParams());
bool OpenFromMemory(const void* data, std::size_t size, const SoundStreamParams& params = SoundStreamParams());
bool OpenFromStream(Stream& stream, const SoundStreamParams& params = SoundStreamParams());
void Pause() override;
void Play() override;
@@ -75,8 +59,6 @@ namespace Nz
bool FillAndQueueBuffer(unsigned int buffer);
void MusicThread();
void StopThread();
static MusicLoader::LoaderList s_loaders;
};
}

View File

@@ -66,16 +66,17 @@ namespace Nz
bool IsValid() const;
bool LoadFromFile(const String& filePath, const SoundBufferParams& params = SoundBufferParams());
bool LoadFromMemory(const void* data, std::size_t size, const SoundBufferParams& params = SoundBufferParams());
bool LoadFromStream(Stream& stream, const SoundBufferParams& params = SoundBufferParams());
static bool IsFormatSupported(AudioFormat format);
template<typename... Args> static SoundBufferRef New(Args&&... args);
SoundBuffer& operator=(const SoundBuffer&) = delete;
SoundBuffer& operator=(SoundBuffer&&) = delete;
static bool IsFormatSupported(AudioFormat format);
static SoundBufferRef LoadFromFile(const String& filePath, const SoundBufferParams& params = SoundBufferParams());
static SoundBufferRef LoadFromMemory(const void* data, std::size_t size, const SoundBufferParams& params = SoundBufferParams());
static SoundBufferRef LoadFromStream(Stream& stream, const SoundBufferParams& params = SoundBufferParams());
template<typename... Args> static SoundBufferRef New(Args&&... args);
// Signals:
NazaraSignal(OnSoundBufferDestroy, const SoundBuffer* /*soundBuffer*/);
NazaraSignal(OnSoundBufferRelease, const SoundBuffer* /*soundBuffer*/);

View File

@@ -10,22 +10,50 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Audio/Config.hpp>
#include <Nazara/Audio/Enums.hpp>
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
namespace Nz
{
class NAZARA_AUDIO_API SoundStream
struct SoundStreamParams : public ResourceParameters
{
bool forceMono = false;
bool IsValid() const;
};
class Mutex;
class SoundStream;
using SoundStreamLoader = ResourceLoader<SoundStream, SoundStreamParams>;
using SoundStreamRef = Nz::ObjectRef<SoundStream>;
class NAZARA_AUDIO_API SoundStream : public RefCounted, public Resource
{
friend SoundStreamLoader;
public:
SoundStream() = default;
virtual ~SoundStream();
virtual UInt32 GetDuration() const = 0;
virtual AudioFormat GetFormat() const = 0;
virtual Mutex& GetMutex() = 0;
virtual UInt64 GetSampleCount() const = 0;
virtual UInt32 GetSampleRate() const = 0;
virtual UInt64 Read(void* buffer, UInt64 sampleCount) = 0;
virtual void Seek(UInt64 offset) = 0;
virtual UInt64 Tell() = 0;
static SoundStreamRef OpenFromFile(const String& filePath, const SoundStreamParams& params = SoundStreamParams());
static SoundStreamRef OpenFromMemory(const void* data, std::size_t size, const SoundStreamParams& params = SoundStreamParams());
static SoundStreamRef OpenFromStream(Stream& stream, const SoundStreamParams& params = SoundStreamParams());
private:
static SoundStreamLoader::LoaderList s_loaders;
};
}

View File

@@ -43,6 +43,7 @@
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/DynLib.hpp>
#include <Nazara/Core/EmptyStream.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/Error.hpp>
@@ -82,6 +83,8 @@
#include <Nazara/Core/SerializationContext.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Core/SparsePtr.hpp>
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/Core/StackVector.hpp>
#include <Nazara/Core/StdLogger.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Core/String.hpp>

View File

@@ -0,0 +1,43 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_BYTEARRAYPOOL_HPP
#define NAZARA_BYTEARRAYPOOL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/String.hpp>
#include <vector>
namespace Nz
{
class AbstractHash;
class NAZARA_CORE_API ByteArrayPool
{
public:
ByteArrayPool() = default;
ByteArrayPool(const ByteArrayPool&) = delete;
ByteArrayPool(ByteArrayPool&&) = default;
~ByteArrayPool() = default;
inline void Clear();
inline ByteArray GetByteArray(std::size_t capacity = 0);
inline void ReturnByteArray(ByteArray byteArray);
ByteArrayPool& operator=(const ByteArrayPool&) = delete;
ByteArrayPool& operator=(ByteArrayPool&&) = default;
private:
std::vector<ByteArray> m_byteArrays;
};
}
#include <Nazara/Core/ByteArrayPool.inl>
#endif // NAZARA_BYTEARRAYPOOL_HPP

View File

@@ -0,0 +1,44 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/ByteArrayPool.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
namespace Detail
{
bool SortByteArrayByCapacity(const ByteArray& byteArray, std::size_t refCapacity)
{
return refCapacity > byteArray.GetCapacity();
}
}
inline void ByteArrayPool::Clear()
{
m_byteArrays.clear();
}
inline ByteArray ByteArrayPool::GetByteArray(std::size_t capacity)
{
ByteArray ret;
auto it = std::lower_bound(m_byteArrays.begin(), m_byteArrays.end(), capacity, Detail::SortByteArrayByCapacity);
if (it != m_byteArrays.end())
{
ret = std::move(*it);
m_byteArrays.erase(it);
}
return ret;
}
inline void ByteArrayPool::ReturnByteArray(ByteArray byteArray)
{
auto it = std::lower_bound(m_byteArrays.begin(), m_byteArrays.end(), byteArray.GetCapacity(), Detail::SortByteArrayByCapacity);
m_byteArrays.emplace(it, std::move(byteArray));
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -27,6 +27,8 @@ namespace Nz
ByteStream(ByteStream&& stream) noexcept = default;
virtual ~ByteStream();
inline void ClearStream();
inline Endianness GetDataEndianness() const;
inline Nz::UInt64 GetSize() const;
inline Stream* GetStream() const;

View File

@@ -30,6 +30,18 @@ namespace Nz
NazaraWarning("Failed to flush bits at serializer destruction");
}
/*!
* \brief Reset stream
*/
inline void ByteStream::ClearStream()
{
// We don't want to lose some bits..
FlushBits();
m_context.stream = nullptr;
m_ownedStream.reset();
}
/*!
* \brief Gets the stream endianness
* \return Type of the endianness
@@ -113,22 +125,15 @@ namespace Nz
}
/*!
* \brief Sets this with a stream
* \brief Changes 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();
ClearStream();
m_context.stream = stream;
m_ownedStream.reset();
}
/*!

View File

@@ -50,7 +50,7 @@
#define NAZARA_CORE_FILE_BUFFERSIZE 4096
// Incorporate the Unicode Character Data table (Necessary to make it work with the flag String::HandleUTF8)
#define NAZARA_CORE_INCLUDE_UNICODEDATA 0
#define NAZARA_CORE_INCLUDE_UNICODEDATA 1
// Use the MemoryManager to manage dynamic allocations (can detect memory leak but allocations/frees are slower)
#define NAZARA_CORE_MANAGE_MEMORY 0

View File

@@ -0,0 +1,46 @@
// Copyright (C) 2019 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_EMPTYSTREAM_HPP
#define NAZARA_EMPTYSTREAM_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Stream.hpp>
namespace Nz
{
class NAZARA_CORE_API EmptyStream : public Stream
{
public:
inline EmptyStream();
EmptyStream(const EmptyStream&) = default;
EmptyStream(EmptyStream&&) noexcept = default;
~EmptyStream() = default;
void Clear();
bool EndOfStream() const override;
UInt64 GetCursorPos() const override;
UInt64 GetSize() const override;
bool SetCursorPos(UInt64 offset) override;
EmptyStream& operator=(const EmptyStream&) = default;
EmptyStream& operator=(EmptyStream&&) noexcept = 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;
UInt64 m_size;
};
}
#include <Nazara/Core/EmptyStream.inl>
#endif // NAZARA_EMPTYSTREAM_HPP

View File

@@ -0,0 +1,22 @@
// Copyright (C) 2019 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/EmptyStream.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::EmptyStream
* \brief Constructs an EmptyStream object by default
*/
inline EmptyStream::EmptyStream() :
m_size(0)
{
m_openMode = Nz::OpenMode_ReadWrite;
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -39,15 +39,20 @@ namespace Nz
static constexpr std::size_t MaxValue = static_cast<std::size_t>(EnumAsFlags<E>::max);
using BitField16 = std::conditional_t<(MaxValue > 8), UInt16, UInt8>;
using BitField32 = std::conditional_t<(MaxValue > 16), UInt32, BitField16>;
using BitField16 = std::conditional_t<(MaxValue >= 8), UInt16, UInt8>;
using BitField32 = std::conditional_t<(MaxValue >= 16), UInt32, BitField16>;
public:
using BitField = std::conditional_t<(MaxValue > 32), UInt64, BitField32>;
using BitField = std::conditional_t<(MaxValue >= 32), UInt64, BitField32>;
constexpr Flags(BitField value = 0);
constexpr Flags(E enumVal);
void Clear();
void Clear(const Flags& flags);
void Set(const Flags& flags);
constexpr bool Test(const Flags& flags) const;
explicit constexpr operator bool() const;

View File

@@ -39,9 +39,49 @@ namespace Nz
{
}
/*!
* \brief Clear all flags
*
* \see Test
*/
template<typename E>
void Flags<E>::Clear()
{
m_value = 0;
}
/*!
* \brief Clear some flags
*
* \param flags Flags to be cleared
*
* \see Test
*/
template<typename E>
void Flags<E>::Clear(const Flags& flags)
{
m_value &= ~flags.m_value;
}
/*!
* \brief Enable some flags
*
* \param flags Flags to be enabled
*
* \see Clear
* \see Test
*/
template<typename E>
void Flags<E>::Set(const Flags& flags)
{
m_value |= flags.m_value;
}
/*!
* \brief Tests if all flags from a Flags object are enabled
* \return True if all tested flags are enabled.
*
* \see Clear
*/
template<typename E>
constexpr bool Flags<E>::Test(const Flags& flags) const

View File

@@ -8,11 +8,22 @@
#define NAZARA_OBJECTHANDLER_HPP
#include <Nazara/Core/Bitset.hpp>
#include <Nazara/Core/Signal.hpp>
#include <memory>
#include <vector>
namespace Nz
{
namespace Detail
{
struct NAZARA_CORE_API HandleData
{
void* object;
static std::shared_ptr<HandleData> GetEmptyObject();
};
}
template<typename T> class ObjectHandle;
template<typename T>
@@ -31,15 +42,16 @@ namespace Nz
HandledObject& operator=(const HandledObject& object);
HandledObject& operator=(HandledObject&& object) noexcept;
NazaraSignal(OnHandledObjectDestruction, HandledObject* /*emitter*/);
protected:
void UnregisterAllHandles() noexcept;
private:
void RegisterHandle(ObjectHandle<T>* handle);
void UnregisterHandle(ObjectHandle<T>* handle) noexcept;
void UpdateHandle(ObjectHandle<T>* oldHandle, ObjectHandle<T>* newHandle) noexcept;
std::shared_ptr<const Detail::HandleData> GetHandleData();
void InitHandleData();
std::vector<ObjectHandle<T>*> m_handles;
std::shared_ptr<Detail::HandleData> m_handleData;
};
}

View File

@@ -2,9 +2,10 @@
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <Nazara/Core/HandledObject.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ObjectHandle.hpp>
#include <algorithm>
#include <cassert>
#include <type_traits>
#include <utility>
@@ -35,10 +36,10 @@ namespace Nz
*/
template<typename T>
HandledObject<T>::HandledObject(HandledObject&& object) noexcept :
m_handles(std::move(object.m_handles))
m_handleData(std::move(object.m_handleData))
{
for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectMoved(static_cast<T*>(this));
if (m_handleData)
m_handleData->object = static_cast<T*>(this);
}
/*!
@@ -74,7 +75,7 @@ namespace Nz
NazaraUnused(object);
// Nothing to do
return *this;
return *this;
}
/*!
@@ -88,73 +89,44 @@ namespace Nz
{
UnregisterAllHandles();
m_handles = std::move(object.m_handles);
for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectMoved(static_cast<T*>(this));
m_handleData = std::move(object.m_handleData);
if (m_handleData)
m_handleData->object = static_cast<T*>(this);
return *this;
}
/*!
* \brief Registers a handle
*
* \param handle Handle to register
*
* \remark One handle can only be registered once, errors can occur if it's more than once
*/
template<typename T>
void HandledObject<T>::RegisterHandle(ObjectHandle<T>* handle)
{
m_handles.push_back(handle);
}
/*!
* \brief Unregisters all handles
*/
template<typename T>
void HandledObject<T>::UnregisterAllHandles() noexcept
{
// Tell every handle we got destroyed, to null them
for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectDestroyed();
if (m_handleData)
{
OnHandledObjectDestruction(this);
m_handles.clear();
m_handleData->object = nullptr;
m_handleData.reset();
}
}
/*!
* \brief Unregisters a handle
*
* \param handle Handle to unregister
*
* \remark One handle can only be unregistered once, crash can occur if it's more than once
* \remark Produces a NazaraAssert if handle not registered
*/
template<typename T>
void HandledObject<T>::UnregisterHandle(ObjectHandle<T>* handle) noexcept
std::shared_ptr<const Detail::HandleData> HandledObject<T>::GetHandleData()
{
auto it = std::find(m_handles.begin(), m_handles.end(), handle);
NazaraAssert(it != m_handles.end(), "Handle not registered");
if (!m_handleData)
InitHandleData();
// Swap and pop idiom, more efficient than vector::erase
std::swap(*it, m_handles.back());
m_handles.pop_back();
return std::shared_ptr<const Detail::HandleData>(m_handleData);
}
/*!
* \brief Updates one handle with another
*
* \param oldHandle Old handle to replace
* \param newHandle New handle to take place
*
* \remark Produces a NazaraAssert if handle not registered
*/
template<typename T>
void HandledObject<T>::UpdateHandle(ObjectHandle<T>* oldHandle, ObjectHandle<T>* newHandle) noexcept
void HandledObject<T>::InitHandleData()
{
auto it = std::find(m_handles.begin(), m_handles.end(), oldHandle);
NazaraAssert(it != m_handles.end(), "Handle not registered");
assert(!m_handleData);
// Simply update the handle
*it = newHandle;
m_handleData = std::make_shared<Detail::HandleData>();
m_handleData->object = static_cast<T*>(this);
}
}

View File

@@ -16,6 +16,7 @@
#define NAZARA_ALLOCA_SUPPORT
#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
#include <alloca.h>
// with Clang/GCC, using alloca with a size of zero does nothing good
@@ -24,16 +25,7 @@
#endif
#ifdef NAZARA_ALLOCA_SUPPORT
#define NazaraStackAllocation(T, size) Nz::StackArray<T>(static_cast<T*>(NAZARA_ALLOCA((size) * sizeof(T))), size)
#define NazaraStackAllocationNoInit(T, size) Nz::StackArray<T>(static_cast<T*>(NAZARA_ALLOCA((size) * sizeof(T))), size, Nz::NoInitTag())
#else
#define NazaraStackAllocation(T, size) Nz::StackArray<T>(static_cast<T*>(Nz::OperatorNew((size) * sizeof(T))), size)
#define NazaraStackAllocationNoInit(T, size) Nz::StackArray<T>(static_cast<T*>(Nz::OperatorNew((size) * sizeof(T))), size, Nz::NoInitTag())
#endif
#include <cstddef>
#include <iterator>
namespace Nz
{
@@ -45,71 +37,6 @@ namespace Nz
template<typename T>
void PlacementDestroy(T* ptr);
struct NoInitTag {};
template<typename T>
class StackArray
{
public:
using value_type = T;
using const_iterator = const value_type*;
using const_pointer = const value_type*;
using const_reference = const value_type&;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using difference_type = std::ptrdiff_t;
using iterator = value_type*;
using pointer = value_type*;
using reference = value_type&;
using reverse_iterator = std::reverse_iterator<iterator>;
using size_type = std::size_t;
StackArray(T* stackMemory, std::size_t size);
StackArray(T* stackMemory, std::size_t size, NoInitTag);
~StackArray();
reference back();
const_reference back() const;
iterator begin() noexcept;
const_iterator begin() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
T* data() noexcept;
const T* data() const noexcept;
bool empty() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
void fill(const T& value);
reference front() noexcept;
const_reference front() const noexcept;
size_type max_size() const noexcept;
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
size_type size() const noexcept;
reference operator[](size_type pos);
const_reference operator[](size_type pos) const;
private:
std::size_t m_size;
T* m_ptr;
};
}
#include <Nazara/Core/MemoryHelper.inl>

View File

@@ -11,10 +11,8 @@
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/Core/MemoryManager.hpp>
#include <algorithm>
#include <cassert>
#include <new>
#include <utility>
#include <Nazara/Core/Debug.hpp>
namespace Nz
@@ -79,187 +77,6 @@ namespace Nz
if (ptr)
ptr->~T();
}
/*!
* \ingroup core
* \class Nz::StackArray
* \brief Core class that represents a stack-allocated (if alloca is present) array
*/
template<typename T>
StackArray<T>::StackArray(T* stackMemory, std::size_t size) :
m_size(size),
m_ptr(stackMemory)
{
for (std::size_t i = 0; i < m_size; ++i)
PlacementNew(&m_ptr[i]);
}
template<typename T>
StackArray<T>::StackArray(T* stackMemory, std::size_t size, NoInitTag) :
m_size(size),
m_ptr(stackMemory)
{
}
template<typename T>
StackArray<T>::~StackArray()
{
for (std::size_t i = 0; i < m_size; ++i)
m_ptr[i].~T();
#ifndef NAZARA_ALLOCA_SUPPORT
OperatorDelete(m_ptr);
#endif
}
template<typename T>
typename StackArray<T>::reference StackArray<T>::back()
{
assert(m_size != 0);
return m_ptr[m_size - 1];
}
template<typename T>
typename StackArray<T>::const_reference StackArray<T>::back() const
{
assert(m_size != 0);
return m_ptr[m_size - 1];
}
template<typename T>
typename StackArray<T>::iterator StackArray<T>::begin() noexcept
{
return iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::const_iterator StackArray<T>::begin() const noexcept
{
return const_iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::const_iterator StackArray<T>::cbegin() const noexcept
{
return const_iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::const_iterator StackArray<T>::cend() const noexcept
{
return const_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::const_reverse_iterator StackArray<T>::crbegin() const noexcept
{
return const_reverse_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::const_reverse_iterator StackArray<T>::crend() const noexcept
{
return const_reverse_iterator(&m_ptr[0]);
}
template<typename T>
T* StackArray<T>::data() noexcept
{
return m_ptr;
}
template<typename T>
const T* StackArray<T>::data() const noexcept
{
return m_ptr;
}
template<typename T>
bool StackArray<T>::empty() const noexcept
{
return m_size == 0;
}
template<typename T>
typename StackArray<T>::iterator StackArray<T>::end() noexcept
{
return iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::const_iterator StackArray<T>::end() const noexcept
{
return const_iterator(&m_ptr[m_size]);
}
template<typename T>
void StackArray<T>::fill(const T& value)
{
std::fill(begin(), end(), value);
}
template<typename T>
typename StackArray<T>::reference StackArray<T>::front() noexcept
{
return m_ptr[0];
}
template<typename T>
typename StackArray<T>::const_reference StackArray<T>::front() const noexcept
{
return m_ptr[0];
}
template<typename T>
typename StackArray<T>::size_type StackArray<T>::max_size() const noexcept
{
return size();
}
template<typename T>
typename StackArray<T>::reverse_iterator StackArray<T>::rbegin() noexcept
{
return reverse_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::const_reverse_iterator StackArray<T>::rbegin() const noexcept
{
return reverse_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::reverse_iterator StackArray<T>::rend() noexcept
{
return reverse_iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::const_reverse_iterator StackArray<T>::rend() const noexcept
{
return reverse_iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::size_type StackArray<T>::size() const noexcept
{
return m_size;
}
template<typename T>
typename StackArray<T>::reference StackArray<T>::operator[](size_type pos)
{
assert(pos < m_size);
return m_ptr[pos];
}
template<typename T>
typename StackArray<T>::const_reference StackArray<T>::operator[](size_type pos) const
{
assert(pos < m_size);
return m_ptr[pos];
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -8,12 +8,12 @@
#define NAZARA_OBJECTHANDLE_HPP
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/HandledObject.hpp>
#include <memory>
#include <ostream>
namespace Nz
{
template<typename T> class HandledObject;
template<typename T>
class ObjectHandle
{
@@ -22,7 +22,7 @@ namespace Nz
public:
ObjectHandle();
explicit ObjectHandle(T* object);
ObjectHandle(const ObjectHandle& handle);
ObjectHandle(const ObjectHandle& handle) = default;
ObjectHandle(ObjectHandle&& handle) noexcept;
~ObjectHandle();
@@ -43,16 +43,13 @@ namespace Nz
T* operator->() const;
ObjectHandle& operator=(T* object);
ObjectHandle& operator=(const ObjectHandle& handle);
ObjectHandle& operator=(const ObjectHandle& handle) = default;
ObjectHandle& operator=(ObjectHandle&& handle) noexcept;
static const ObjectHandle InvalidHandle;
protected:
void OnObjectDestroyed() noexcept;
void OnObjectMoved(T* newObject) noexcept;
T* m_object;
std::shared_ptr<const Detail::HandleData> m_handleData;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const ObjectHandle<T>& handle);

View File

@@ -15,37 +15,15 @@ namespace Nz
* \brief Core class that represents a object handle
*/
/*!
* \brief Constructs a ObjectHandle object by default
*/
template<typename T>
ObjectHandle<T>::ObjectHandle() :
m_object(nullptr)
{
}
/*!
* \brief Constructs a ObjectHandle object with a pointer to an object
*
* \param object Pointer to handle like an object (can be nullptr)
*/
template<typename T>
ObjectHandle<T>::ObjectHandle(T* object) :
ObjectHandle()
ObjectHandle<T>::ObjectHandle() :
m_handleData(Detail::HandleData::GetEmptyObject())
{
Reset(object);
}
/*!
* \brief Constructs a ObjectHandle object by assignation
*
* \param handle ObjectHandle to assign into this
*/
template<typename T>
ObjectHandle<T>::ObjectHandle(const ObjectHandle& handle) :
ObjectHandle()
{
Reset(handle);
}
/*!
@@ -54,12 +32,22 @@ namespace Nz
* \param handle ObjectHandle to move into this
*/
template<typename T>
ObjectHandle<T>::ObjectHandle(ObjectHandle&& handle) noexcept :
ObjectHandle()
ObjectHandle<T>::ObjectHandle(ObjectHandle&& handle) noexcept
{
Reset(std::move(handle));
}
/*!
* \brief Constructs a ObjectHandle object with a pointer to an object
*
* \param object Pointer to handle like an object (can be nullptr)
*/
template<typename T>
ObjectHandle<T>::ObjectHandle(T* object)
{
Reset(object);
}
/*!
* \brief Destructs the object and calls reset with nullptr
*
@@ -78,7 +66,7 @@ namespace Nz
template<typename T>
T* ObjectHandle<T>::GetObject() const
{
return m_object;
return static_cast<T*>(m_handleData->object);
}
/*!
@@ -88,7 +76,7 @@ namespace Nz
template<typename T>
bool ObjectHandle<T>::IsValid() const
{
return m_object != nullptr;
return m_handleData->object != nullptr;
}
/*!
@@ -99,14 +87,10 @@ namespace Nz
template<typename T>
void ObjectHandle<T>::Reset(T* object)
{
// If we already have an entity, we must alert it that we are not pointing to it anymore
if (m_object)
m_object->UnregisterHandle(this);
m_object = object;
if (m_object)
// We alert the new entity that we are pointing to it
m_object->RegisterHandle(this);
if (object)
m_handleData = object->GetHandleData();
else
m_handleData = Detail::HandleData::GetEmptyObject();
}
/*!
@@ -117,7 +101,7 @@ namespace Nz
template<typename T>
void ObjectHandle<T>::Reset(const ObjectHandle& handle)
{
Reset(handle.GetObject());
m_handleData = handle.m_handleData;
}
/*!
@@ -128,18 +112,8 @@ namespace Nz
template<typename T>
void ObjectHandle<T>::Reset(ObjectHandle&& handle) noexcept
{
if (this == &handle)
return;
if (m_object)
m_object->UnregisterHandle(this);
if (T* object = handle.GetObject())
{
m_object = handle.m_object;
handle.m_object = nullptr;
object->UpdateHandle(&handle, this);
}
m_handleData = std::move(handle.m_handleData);
handle.m_handleData = Detail::HandleData::GetEmptyObject();
}
/*!
@@ -151,23 +125,8 @@ namespace Nz
template<typename T>
ObjectHandle<T>& ObjectHandle<T>::Swap(ObjectHandle& handle)
{
// As we swap the two handles, we must alert the entities
// The default version with swap (move) would be working,
// but will register handles one more time (due to temporary copy).
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);
}
// We do the swap
std::swap(m_object, handle.m_object);
std::swap(m_handleData, handle.m_handleData);
return *this;
}
@@ -181,7 +140,7 @@ namespace Nz
Nz::StringStream ss;
ss << "ObjectHandle(";
if (IsValid())
ss << m_object->ToString();
ss << GetObject()->ToString();
else
ss << "Null";
@@ -209,7 +168,7 @@ namespace Nz
template<typename T>
ObjectHandle<T>::operator T*() const
{
return m_object;
return GetObject();
}
/*!
@@ -219,7 +178,7 @@ namespace Nz
template<typename T>
T* ObjectHandle<T>::operator->() const
{
return m_object;
return GetObject();
}
/*!
@@ -229,23 +188,9 @@ namespace Nz
* \param entity Pointer to handle like an object (can be nullptr)
*/
template<typename T>
ObjectHandle<T>& ObjectHandle<T>::operator=(T* entity)
ObjectHandle<T>& ObjectHandle<T>::operator=(T* object)
{
Reset(entity);
return *this;
}
/*!
* \brief Sets the handle of the ObjectHandle with the handle from another
* \return A reference to this
*
* \param handle The other ObjectHandle
*/
template<typename T>
ObjectHandle<T>& ObjectHandle<T>::operator=(const ObjectHandle& handle)
{
Reset(handle);
Reset(object);
return *this;
}
@@ -264,26 +209,6 @@ namespace Nz
return *this;
}
/*!
* \brief Action to do on object destruction
*/
template<typename T>
void ObjectHandle<T>::OnObjectDestroyed() noexcept
{
// Shortcut
m_object = nullptr;
}
/*!
* \brief Action to do on object move
*/
template<typename T>
void ObjectHandle<T>::OnObjectMoved(T* newObject) noexcept
{
// The object has been moved, update our pointer
m_object = newObject;
}
/*!
* \brief Output operator
* \return The stream
@@ -386,7 +311,7 @@ namespace Nz
template<typename T>
bool operator<(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return lhs.m_object < rhs.m_object;
return lhs.GetObject() < rhs.GetObject();
}
/*!
@@ -399,7 +324,7 @@ namespace Nz
template<typename T>
bool operator<(const T& lhs, const ObjectHandle<T>& rhs)
{
return &lhs < rhs.m_object;
return &lhs < rhs.GetObject();
}
/*!
@@ -412,7 +337,7 @@ namespace Nz
template<typename T>
bool operator<(const ObjectHandle<T>& lhs, const T& rhs)
{
return lhs.m_object < &rhs;
return lhs.GetObject() < &rhs;
}
/*!

View File

@@ -23,6 +23,8 @@ namespace Nz
ObjectLibrary() = delete;
~ObjectLibrary() = delete;
static void Clear();
static ObjectRef<Type> Get(const String& name);
static bool Has(const String& name);

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/ObjectLibrary.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Debug.hpp>
@@ -9,10 +10,19 @@ namespace Nz
{
/*!
* \ingroup core
* \class Nz::ObjectRef
* \brief Core class that represents a reference to an object
* \class Nz::ObjectLibrary
* \brief Core class containing a collection of objects
*/
/*!
* \brief Clears the library, freeing every object it contains
*/
template<typename Type>
void ObjectLibrary<Type>::Clear()
{
Type::s_library.clear();
}
/*!
* \brief Gets the ObjectRef object by name
* \return Optional reference

View File

@@ -68,6 +68,10 @@ namespace Nz
template<typename T> bool operator>=(const T& lhs, const ObjectRef<T>& rhs);
template<typename T> bool operator>=(const ObjectRef<T>& lhs, const T& rhs);
template<typename T, typename U> ObjectRef<T> ConstRefCast(const ObjectRef<U>& ref);
template<typename T, typename U> ObjectRef<T> DynamicRefCast(const ObjectRef<U>& ref);
template<typename T, typename U> ObjectRef<T> ReinterpretRefCast(const ObjectRef<U>& ref);
template<typename T, typename U> ObjectRef<T> StaticRefCast(const ObjectRef<U>& ref);
template<typename T> struct PointedType<ObjectRef<T>> { using type = T; };
template<typename T> struct PointedType<ObjectRef<T> const> { using type = T; };

View File

@@ -335,7 +335,7 @@ namespace Nz
template<typename T>
bool operator<(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs)
{
return lhs.m_object < rhs.m_object;
return lhs.Get() < rhs.Get();
}
/*!
@@ -348,7 +348,7 @@ namespace Nz
template<typename T>
bool operator<(const T& lhs, const ObjectRef<T>& rhs)
{
return &lhs < rhs.m_object;
return &lhs < rhs.Get();
}
/*!
@@ -361,7 +361,7 @@ namespace Nz
template<typename T>
bool operator<(const ObjectRef<T>& lhs, const T& rhs)
{
return lhs.m_object < &rhs;
return lhs.Get() < &rhs;
}
/*!
@@ -480,6 +480,60 @@ namespace Nz
{
return !(lhs < rhs);
}
/*!
* \brief Casts an ObjectRef from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*
* \remark It is an undefined behavior to cast between incompatible types
*/
template<typename T, typename U>
ObjectRef<T> ConstRefCast(const ObjectRef<U>& ref)
{
return ObjectRef<T>(const_cast<T*>(ref.Get()));
}
/*!
* \brief Casts an ObjectRef from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*/
template<typename T, typename U>
ObjectRef<T> DynamicRefCast(const ObjectRef<U>& ref)
{
return ObjectRef<T>(dynamic_cast<T*>(ref.Get()));
}
/*!
* \brief Casts an ObjectRef from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*
* \remark It is an undefined behavior to cast between incompatible types
*/
template<typename T, typename U>
ObjectRef<T> ReinterpretRefCast(const ObjectRef<U>& ref)
{
return ObjectRef<T>(static_cast<T*>(ref.Get()));
}
/*!
* \brief Casts an ObjectRef from one type to another using static_cast
* \return Reference to the casted object
*
* \param ref The reference to convert
*
* \remark It is an undefined behavior to cast between incompatible types
*/
template<typename T, typename U>
ObjectRef<T> StaticRefCast(const ObjectRef<U>& ref)
{
return ObjectRef<T>(static_cast<T*>(ref.Get()));
}
}
namespace std
@@ -504,3 +558,4 @@ namespace std
}
#include <Nazara/Core/DebugOff.hpp>
#include "ObjectRef.hpp"

View File

@@ -0,0 +1,46 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_POOLBYTESTREAM_HPP
#define NAZARA_POOLBYTESTREAM_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/ByteStream.hpp>
#include <Nazara/Core/Config.hpp>
namespace Nz
{
class ByteArrayPool;
class NAZARA_CORE_API PoolByteStream : public ByteStream
{
friend class Network;
public:
inline PoolByteStream(ByteArrayPool& pool);
inline PoolByteStream(ByteArrayPool& pool, std::size_t capacity);
PoolByteStream(const PoolByteStream&) = delete;
PoolByteStream(PoolByteStream&& packet) = default;
inline ~PoolByteStream();
void Reset();
void Reset(std::size_t capacity);
PoolByteStream& operator=(const PoolByteStream&) = delete;
PoolByteStream& operator=(PoolByteStream&&) = delete;
private:
void OnEmptyStream() override;
ByteArrayPool& m_pool;
ByteArray m_buffer;
};
}
#include <Nazara/Core/PoolByteStream.inl>
#endif // NAZARA_POOLBYTESTREAM_HPP

View File

@@ -0,0 +1,30 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/PoolByteStream.hpp>
#include <Nazara/Core/Error.hpp>
#include <cstring>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
inline PoolByteStream::PoolByteStream(ByteArrayPool& pool) :
m_pool(pool)
{
}
inline PoolByteStream::PoolByteStream(ByteArrayPool& pool, std::size_t capacity) :
PoolByteStream(pool)
{
Reset(capacity);
}
inline PoolByteStream::~PoolByteStream()
{
FlushBits(); //< Needs to be done here as the stream will be freed before ByteStream calls it
Reset(); //< Returns the byte array (if any) to the pool
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -8,6 +8,8 @@
#define NAZARA_RESOURCELOADER_HPP
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/ObjectRef.hpp>
#include <Nazara/Core/RefCounted.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Core/String.hpp>
@@ -28,19 +30,19 @@ namespace Nz
public:
using ExtensionGetter = bool (*)(const String& extension);
using FileLoader = bool (*)(Type* resource, const String& filePath, const Parameters& parameters);
using MemoryLoader = bool (*)(Type* resource, const void* data, std::size_t size, const Parameters& parameters);
using FileLoader = ObjectRef<Type> (*)(const String& filePath, const Parameters& parameters);
using MemoryLoader = ObjectRef<Type> (*)(const void* data, std::size_t size, const Parameters& parameters);
using StreamChecker = Ternary (*)(Stream& stream, const Parameters& parameters);
using StreamLoader = bool (*)(Type* resource, Stream& stream, const Parameters& parameters);
using StreamLoader = ObjectRef<Type> (*)(Stream& stream, const Parameters& parameters);
ResourceLoader() = delete;
~ResourceLoader() = delete;
static bool IsExtensionSupported(const String& extension);
static bool LoadFromFile(Type* resource, const String& filePath, const Parameters& parameters = Parameters());
static bool LoadFromMemory(Type* resource, const void* data, std::size_t size, const Parameters& parameters = Parameters());
static bool LoadFromStream(Type* resource, Stream& stream, const Parameters& parameters = Parameters());
static ObjectRef<Type> LoadFromFile(const String& filePath, const Parameters& parameters = Parameters());
static ObjectRef<Type> LoadFromMemory(const void* data, std::size_t size, const Parameters& parameters = Parameters());
static ObjectRef<Type> LoadFromStream(Stream& stream, const Parameters& parameters = Parameters());
static void RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr, MemoryLoader memoryLoader = nullptr);
static void UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader = nullptr, MemoryLoader memoryLoader = nullptr);

View File

@@ -53,9 +53,8 @@ namespace Nz
* \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)
ObjectRef<Type> ResourceLoader<Type, Parameters>::LoadFromFile(const String& filePath, const Parameters& parameters)
{
NazaraAssert(resource, "Invalid resource");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
String path = File::NormalizePath(filePath);
@@ -63,7 +62,7 @@ namespace Nz
if (ext.IsEmpty())
{
NazaraError("Failed to get file extension from \"" + filePath + '"');
return false;
return nullptr;
}
File file(path); // Open only if needed
@@ -84,7 +83,7 @@ namespace Nz
if (!file.Open(OpenMode_ReadOnly))
{
NazaraError("Failed to load file: unable to open \"" + filePath + '"');
return false;
return nullptr;
}
}
@@ -107,10 +106,11 @@ namespace Nz
found = true;
}
if (fileLoader(resource, filePath, parameters))
ObjectRef<Type> resource = fileLoader(filePath, parameters);
if (resource)
{
resource->SetFilePath(filePath);
return true;
return resource;
}
}
else
@@ -125,10 +125,11 @@ namespace Nz
file.SetCursorPos(0);
if (streamLoader(resource, file, parameters))
ObjectRef<Type> resource = streamLoader(file, parameters);
if (resource)
{
resource->SetFilePath(filePath);
return true;
return resource;
}
}
@@ -141,7 +142,7 @@ namespace Nz
else
NazaraError("Failed to load file: no loader found for extension \"" + ext + '"');
return false;
return nullptr;
}
/*!
@@ -160,9 +161,8 @@ namespace Nz
* \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, std::size_t size, const Parameters& parameters)
ObjectRef<Type> ResourceLoader<Type, Parameters>::LoadFromMemory(const void* data, std::size_t size, const Parameters& parameters)
{
NazaraAssert(resource, "Invalid resource");
NazaraAssert(data, "Invalid data pointer");
NazaraAssert(size, "No data to load");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
@@ -195,8 +195,9 @@ namespace Nz
found = true;
}
if (memoryLoader(resource, data, size, parameters))
return true;
ObjectRef<Type> resource = memoryLoader(data, size, parameters);
if (resource)
return resource;
}
else
{
@@ -210,8 +211,9 @@ namespace Nz
stream.SetCursorPos(0);
if (streamLoader(resource, stream, parameters))
return true;
ObjectRef<Type> resource = streamLoader(stream, parameters);
if (resource)
return resource;
}
if (recognized == Ternary_True)
@@ -223,7 +225,7 @@ namespace Nz
else
NazaraError("Failed to load file: no loader found");
return false;
return nullptr;
}
/*!
@@ -241,9 +243,8 @@ namespace Nz
* \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)
ObjectRef<Type> ResourceLoader<Type, Parameters>::LoadFromStream(Stream& stream, const Parameters& parameters)
{
NazaraAssert(resource, "Invalid resource");
NazaraAssert(stream.GetCursorPos() < stream.GetSize(), "No data to load");
NazaraAssert(parameters.IsValid(), "Invalid parameters");
@@ -267,8 +268,9 @@ namespace Nz
stream.SetCursorPos(streamPos);
// Load of the resource
if (streamLoader(resource, stream, parameters))
return true;
ObjectRef<Type> resource = streamLoader(stream, parameters);
if (resource)
return resource;
if (recognized == Ternary_True)
NazaraWarning("Loader failed");
@@ -279,7 +281,7 @@ namespace Nz
else
NazaraError("Failed to load file: no loader found");
return false;
return nullptr;
}
/*!

View File

@@ -37,14 +37,8 @@ namespace Nz
auto it = Type::s_managerMap.find(absolutePath);
if (it == Type::s_managerMap.end())
{
ObjectRef<Type> resource = Type::New();
ObjectRef<Type> resource = Type::LoadFromFile(absolutePath, GetDefaultParameters());
if (!resource)
{
NazaraError("Failed to create resource");
return ObjectRef<Type>();
}
if (!resource->LoadFromFile(absolutePath, GetDefaultParameters()))
{
NazaraError("Failed to load resource from file: " + absolutePath);
return ObjectRef<Type>();

View File

@@ -32,7 +32,7 @@ namespace Nz
class ConnectionGuard;
Signal();
Signal(const Signal&) = delete;
Signal(const Signal&);
Signal(Signal&& signal) noexcept;
~Signal() = default;
@@ -47,7 +47,7 @@ namespace Nz
void operator()(Args... args) const;
Signal& operator=(const Signal&) = delete;
Signal& operator=(const Signal&);
Signal& operator=(Signal&& signal) noexcept;
private:

View File

@@ -18,13 +18,23 @@ namespace Nz
/*!
* \brief Constructs a Signal object by default
*/
template<typename... Args>
Signal<Args...>::Signal() :
m_slotIterator(0)
{
}
/*!
* \brief Constructs a Signal object by default
*
* \remark It doesn't make sense to copy a signal, this is only available for convenience to allow compiler-generated copy constructors
*/
template<typename ...Args>
Signal<Args...>::Signal(const Signal&) :
Signal()
{
}
/*!
* \brief Constructs a Signal object by move semantic
*
@@ -174,13 +184,24 @@ namespace Nz
m_slots[m_slotIterator]->callback(args...);
}
/*!
* \brief Doesn't do anything
* \return A reference to this
*
* \remark This is only for convenience to allow compiled-generated assignation operator
*/
template<typename... Args>
Signal<Args...>& Signal<Args...>::operator=(const Signal&)
{
return *this;
}
/*!
* \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) noexcept
{

View File

@@ -0,0 +1,100 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_STACKARRAY_HPP
#define NAZARA_STACKARRAY_HPP
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/Core/MovablePtr.hpp>
#ifdef NAZARA_ALLOCA_SUPPORT
#define NazaraStackArray(T, size) Nz::StackArray<T>(static_cast<T*>(NAZARA_ALLOCA((size) * sizeof(T))), size)
#define NazaraStackArrayNoInit(T, size) Nz::StackArray<T>(static_cast<T*>(NAZARA_ALLOCA((size) * sizeof(T))), size, typename Nz::StackArray<T>::NoInitTag())
#else
#define NazaraStackArray(T, size) Nz::StackArray<T>(static_cast<T*>(Nz::OperatorNew((size) * sizeof(T))), size)
#define NazaraStackArrayNoInit(T, size) Nz::StackArray<T>(static_cast<T*>(Nz::OperatorNew((size) * sizeof(T))), size, typename Nz::StackArray<T>::NoInitTag())
#endif
#include <cstddef>
#include <iterator>
namespace Nz
{
template<typename T>
class StackArray
{
public:
struct NoInitTag {};
using value_type = T;
using const_iterator = const value_type*;
using const_pointer = const value_type*;
using const_reference = const value_type&;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using difference_type = std::ptrdiff_t;
using iterator = value_type*;
using pointer = value_type*;
using reference = value_type&;
using reverse_iterator = std::reverse_iterator<iterator>;
using size_type = std::size_t;
StackArray();
StackArray(T* stackMemory, std::size_t size);
StackArray(T* stackMemory, std::size_t size, NoInitTag);
StackArray(const StackArray&) = delete;
StackArray(StackArray&&) = default;
~StackArray();
reference back();
const_reference back() const;
iterator begin() noexcept;
const_iterator begin() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
T* data() noexcept;
const T* data() const noexcept;
bool empty() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
void fill(const T& value);
reference front() noexcept;
const_reference front() const noexcept;
size_type max_size() const noexcept;
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
size_type size() const noexcept;
reference operator[](size_type pos);
const_reference operator[](size_type pos) const;
StackArray& operator=(const StackArray&) = delete;
StackArray& operator=(StackArray&&) = default;
private:
std::size_t m_size;
MovablePtr<T> m_ptr;
};
}
#include <Nazara/Core/StackArray.inl>
#endif // NAZARA_STACKARRAY_HPP

View File

@@ -0,0 +1,216 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// 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
#define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION
#endif
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/Core/MemoryManager.hpp>
#include <algorithm>
#include <cassert>
#include <new>
#include <utility>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::StackArray
* \brief Core class that represents a stack-allocated (if alloca is present) array
*/
template<typename T>
StackArray<T>::StackArray() :
m_size(0),
m_ptr(nullptr)
{
}
template<typename T>
StackArray<T>::StackArray(T* stackMemory, std::size_t size) :
m_size(size),
m_ptr(stackMemory)
{
for (std::size_t i = 0; i < m_size; ++i)
PlacementNew(&m_ptr[i]);
}
template<typename T>
StackArray<T>::StackArray(T* stackMemory, std::size_t size, NoInitTag) :
m_size(size),
m_ptr(stackMemory)
{
}
template<typename T>
StackArray<T>::~StackArray()
{
for (std::size_t i = 0; i < m_size; ++i)
PlacementDestroy(&m_ptr[i]);
#ifndef NAZARA_ALLOCA_SUPPORT
OperatorDelete(m_ptr);
#endif
}
template<typename T>
typename StackArray<T>::reference StackArray<T>::back()
{
assert(m_size != 0);
return m_ptr[m_size - 1];
}
template<typename T>
typename StackArray<T>::const_reference StackArray<T>::back() const
{
assert(m_size != 0);
return m_ptr[m_size - 1];
}
template<typename T>
typename StackArray<T>::iterator StackArray<T>::begin() noexcept
{
return iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::const_iterator StackArray<T>::begin() const noexcept
{
return const_iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::const_iterator StackArray<T>::cbegin() const noexcept
{
return const_iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::const_iterator StackArray<T>::cend() const noexcept
{
return const_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::const_reverse_iterator StackArray<T>::crbegin() const noexcept
{
return const_reverse_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::const_reverse_iterator StackArray<T>::crend() const noexcept
{
return const_reverse_iterator(&m_ptr[0]);
}
template<typename T>
T* StackArray<T>::data() noexcept
{
return m_ptr;
}
template<typename T>
const T* StackArray<T>::data() const noexcept
{
return m_ptr;
}
template<typename T>
bool StackArray<T>::empty() const noexcept
{
return m_size == 0;
}
template<typename T>
typename StackArray<T>::iterator StackArray<T>::end() noexcept
{
return iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::const_iterator StackArray<T>::end() const noexcept
{
return const_iterator(&m_ptr[m_size]);
}
template<typename T>
void StackArray<T>::fill(const T& value)
{
std::fill(begin(), end(), value);
}
template<typename T>
typename StackArray<T>::reference StackArray<T>::front() noexcept
{
return m_ptr[0];
}
template<typename T>
typename StackArray<T>::const_reference StackArray<T>::front() const noexcept
{
return m_ptr[0];
}
template<typename T>
typename StackArray<T>::size_type StackArray<T>::max_size() const noexcept
{
return size();
}
template<typename T>
typename StackArray<T>::reverse_iterator StackArray<T>::rbegin() noexcept
{
return reverse_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::const_reverse_iterator StackArray<T>::rbegin() const noexcept
{
return reverse_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackArray<T>::reverse_iterator StackArray<T>::rend() noexcept
{
return reverse_iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::const_reverse_iterator StackArray<T>::rend() const noexcept
{
return reverse_iterator(&m_ptr[0]);
}
template<typename T>
typename StackArray<T>::size_type StackArray<T>::size() const noexcept
{
return m_size;
}
template<typename T>
typename StackArray<T>::reference StackArray<T>::operator[](size_type pos)
{
assert(pos < m_size);
return m_ptr[pos];
}
template<typename T>
typename StackArray<T>::const_reference StackArray<T>::operator[](size_type pos) const
{
assert(pos < m_size);
return m_ptr[pos];
}
}
#include <Nazara/Core/DebugOff.hpp>
// 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

@@ -0,0 +1,119 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_STACKVECTOR_HPP
#define NAZARA_STACKVECTOR_HPP
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/Core/MovablePtr.hpp>
#ifdef NAZARA_ALLOCA_SUPPORT
#define NazaraStackVector(T, capacity) Nz::StackVector<T>(static_cast<T*>(NAZARA_ALLOCA((capacity) * sizeof(T))), capacity)
#else
#define NazaraStackVector(T, capacity) Nz::StackVector<T>(static_cast<T*>(Nz::OperatorNew((capacity) * sizeof(T))), capacity)
#endif
#include <cstddef>
#include <iterator>
#include <type_traits>
namespace Nz
{
template<typename T>
class StackVector
{
public:
using value_type = T;
using const_iterator = const value_type*;
using const_pointer = const value_type*;
using const_reference = const value_type&;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using difference_type = std::ptrdiff_t;
using iterator = value_type*;
using pointer = value_type*;
using reference = value_type&;
using reverse_iterator = std::reverse_iterator<iterator>;
using size_type = std::size_t;
StackVector();
StackVector(T* stackMemory, std::size_t capacity);
StackVector(const StackVector&) = delete;
StackVector(StackVector&&) = default;
~StackVector();
reference back();
const_reference back() const;
iterator begin() noexcept;
const_iterator begin() const noexcept;
size_type capacity() const noexcept;
void clear() noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
T* data() noexcept;
const T* data() const noexcept;
template<typename... Args>
iterator emplace(const_iterator pos, Args&&... args);
template<typename... Args>
reference emplace_back(Args&&... args);
bool empty() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
iterator erase(const_iterator pos);
iterator erase(const_iterator first, const_iterator last);
reference front() noexcept;
const_reference front() const noexcept;
iterator insert(const_iterator pos, const T& value);
iterator insert(const_iterator pos, T&& value);
size_type max_size() const noexcept;
reference push_back(const T& value) noexcept(std::is_nothrow_copy_constructible<T>::value);
reference push_back(T&& value) noexcept(std::is_nothrow_move_constructible<T>::value);
void pop_back();
void resize(size_type count);
void resize(size_type count, const value_type& value);
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
size_type size() const noexcept;
reference operator[](size_type pos);
const_reference operator[](size_type pos) const;
StackVector& operator=(const StackVector&) = delete;
StackVector& operator=(StackVector&&) = default;
private:
std::size_t m_capacity;
std::size_t m_size;
MovablePtr<T> m_ptr;
};
}
#include <Nazara/Core/StackVector.inl>
#endif // NAZARA_STACKVECTOR_HPP

View File

@@ -0,0 +1,347 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// 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
#define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION
#endif
#include <Nazara/Core/StackVector.hpp>
#include <Nazara/Core/MemoryManager.hpp>
#include <algorithm>
#include <cassert>
#include <new>
#include <utility>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::StackVector
* \brief Core class that represents a stack-allocated (if alloca is present) vector, that is with a capacity different from its size
*/
template<typename T>
StackVector<T>::StackVector() :
m_capacity(0),
m_size(0),
m_ptr(nullptr)
{
}
template<typename T>
StackVector<T>::StackVector(T* stackMemory, std::size_t capacity) :
m_capacity(capacity),
m_size(0),
m_ptr(stackMemory)
{
}
template<typename T>
StackVector<T>::~StackVector()
{
clear();
#ifndef NAZARA_ALLOCA_SUPPORT
OperatorDelete(m_ptr);
#endif
}
template<typename T>
typename StackVector<T>::reference StackVector<T>::back()
{
assert(m_size != 0);
return m_ptr[m_size - 1];
}
template<typename T>
typename StackVector<T>::const_reference StackVector<T>::back() const
{
assert(m_size != 0);
return m_ptr[m_size - 1];
}
template<typename T>
typename StackVector<T>::iterator StackVector<T>::begin() noexcept
{
return iterator(&m_ptr[0]);
}
template<typename T>
typename StackVector<T>::const_iterator StackVector<T>::begin() const noexcept
{
return const_iterator(&m_ptr[0]);
}
template<typename T>
typename StackVector<T>::size_type StackVector<T>::capacity() const noexcept
{
return m_capacity;
}
template<typename T>
void StackVector<T>::clear() noexcept
{
resize(0);
}
template<typename T>
typename StackVector<T>::const_iterator StackVector<T>::cbegin() const noexcept
{
return const_iterator(&m_ptr[0]);
}
template<typename T>
typename StackVector<T>::const_iterator StackVector<T>::cend() const noexcept
{
return const_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackVector<T>::const_reverse_iterator StackVector<T>::crbegin() const noexcept
{
return const_reverse_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackVector<T>::const_reverse_iterator StackVector<T>::crend() const noexcept
{
return const_reverse_iterator(&m_ptr[0]);
}
template<typename T>
T* StackVector<T>::data() noexcept
{
return m_ptr;
}
template<typename T>
const T* StackVector<T>::data() const noexcept
{
return m_ptr;
}
template<typename T>
template<typename... Args>
typename StackVector<T>::iterator StackVector<T>::emplace(const_iterator pos, Args&& ...args)
{
assert(m_size < m_capacity);
assert(pos >= begin() && pos <= end());
std::size_t index = std::distance(cbegin(), pos);
if (pos < end())
{
iterator lastElement = end() - 1;
PlacementNew(&m_ptr[m_size], std::move(*lastElement));
if (&m_ptr[index] < lastElement)
std::move_backward(&m_ptr[index], &m_ptr[m_size - 1], &m_ptr[m_size]);
PlacementDestroy(&m_ptr[index]);
}
m_size++;
return PlacementNew(&m_ptr[index], std::forward<Args>(args)...);
}
template<typename T>
template<typename... Args>
typename StackVector<T>::reference Nz::StackVector<T>::emplace_back(Args&&... args)
{
assert(m_size < m_capacity);
return *PlacementNew(&m_ptr[m_size++], std::forward<Args>(args)...);
}
template<typename T>
bool StackVector<T>::empty() const noexcept
{
return m_size == 0;
}
template<typename T>
typename StackVector<T>::iterator StackVector<T>::end() noexcept
{
return iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackVector<T>::const_iterator StackVector<T>::end() const noexcept
{
return const_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackVector<T>::iterator StackVector<T>::erase(const_iterator pos)
{
assert(pos < end());
std::size_t index = std::distance(cbegin(), pos);
std::move(begin() + index + 1, end(), begin() + index);
pop_back();
return iterator(&m_ptr[index]);
}
template<typename T>
typename StackVector<T>::iterator StackVector<T>::erase(const_iterator first, const_iterator last)
{
std::size_t index = std::distance(cbegin(), first);
if (first == last)
return begin() + index;
assert(first < last);
assert(first >= begin() && last <= end());
std::size_t count = std::distance(first, last);
std::move(begin() + index + count, end(), begin() + index);
resize(size() - count);
return iterator(&m_ptr[index]);
}
template<typename T>
typename StackVector<T>::reference StackVector<T>::front() noexcept
{
return m_ptr[0];
}
template<typename T>
typename StackVector<T>::const_reference StackVector<T>::front() const noexcept
{
return m_ptr[0];
}
template<typename T>
typename StackVector<T>::iterator StackVector<T>::insert(const_iterator pos, const T& value)
{
return emplace(pos, value);
}
template<typename T>
typename StackVector<T>::iterator StackVector<T>::insert(const_iterator pos, T&& value)
{
return emplace(pos, std::move(value));
}
template<typename T>
typename StackVector<T>::size_type StackVector<T>::max_size() const noexcept
{
return capacity();
}
template<typename T>
typename StackVector<T>::reference StackVector<T>::push_back(const T& value) noexcept(std::is_nothrow_copy_constructible<T>::value)
{
assert(m_size < m_capacity);
return *PlacementNew(&m_ptr[m_size++], value);
}
template<typename T>
typename StackVector<T>::reference StackVector<T>::push_back(T&& value) noexcept(std::is_nothrow_move_constructible<T>::value)
{
assert(m_size < m_capacity);
return *PlacementNew(&m_ptr[m_size++], std::move(value));
}
template<typename T>
void StackVector<T>::pop_back()
{
assert(!empty());
PlacementDestroy(&m_ptr[--m_size]);
}
template<typename T>
void StackVector<T>::resize(size_type count)
{
assert(count <= m_capacity);
if (count > m_size)
{
for (std::size_t i = m_size; i < count; ++i)
PlacementNew(&m_ptr[i]);
m_size = count;
}
else if (count < m_size)
{
for (std::size_t i = count; i < m_size; ++i)
PlacementDestroy(&m_ptr[i]);
m_size = count;
}
}
template<typename T>
void StackVector<T>::resize(size_type count, const value_type& value)
{
assert(count <= m_capacity);
if (count > m_size)
{
for (std::size_t i = m_size; i < count; ++i)
PlacementNew(&m_ptr[i], value);
m_size = count;
}
else if (count < m_size)
{
for (std::size_t i = count; i < m_size; ++i)
PlacementDestroy(&m_ptr[i]);
m_size = count;
}
}
template<typename T>
typename StackVector<T>::reverse_iterator StackVector<T>::rbegin() noexcept
{
return reverse_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackVector<T>::const_reverse_iterator StackVector<T>::rbegin() const noexcept
{
return reverse_iterator(&m_ptr[m_size]);
}
template<typename T>
typename StackVector<T>::reverse_iterator StackVector<T>::rend() noexcept
{
return reverse_iterator(&m_ptr[0]);
}
template<typename T>
typename StackVector<T>::const_reverse_iterator StackVector<T>::rend() const noexcept
{
return reverse_iterator(&m_ptr[0]);
}
template<typename T>
typename StackVector<T>::size_type StackVector<T>::size() const noexcept
{
return m_size;
}
template<typename T>
typename StackVector<T>::reference StackVector<T>::operator[](size_type pos)
{
assert(pos < m_size);
return m_ptr[pos];
}
template<typename T>
typename StackVector<T>::const_reference StackVector<T>::operator[](size_type pos) const
{
assert(pos < m_size);
return m_ptr[pos];
}
}
#include <Nazara/Core/DebugOff.hpp>
// 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

@@ -41,7 +41,7 @@ namespace Nz
inline void String::ReleaseString()
{
m_sharedString = std::move(GetEmptyString());
m_sharedString = GetEmptyString();
}
/*!

View File

@@ -10,7 +10,10 @@
namespace Nz
{
template<typename T>
struct TypeTag {};
struct TypeTag
{
using Type = T;
};
}
#endif // NAZARA_TYPETAG_HPP

View File

@@ -55,7 +55,7 @@ namespace Nz
Category_Other_PrivateUse = Category_Other | 0x0800, // Co
Category_Other_Surrogate = Category_Other | 0x1000, // Cs
// Ponctuations
// Punctuations
Category_Punctuation = 0x10, // P
Category_Punctuation_Close = Category_Punctuation | 0x0100, // Pe
Category_Punctuation_Connector = Category_Punctuation | 0x0200, // Pc
@@ -81,25 +81,29 @@ namespace Nz
enum Direction : UInt8
{
Direction_Arabic_Letter, // AL
Direction_Arabic_Number, // AN
Direction_Boundary_Neutral, // BN
Direction_Common_Separator, // CS
Direction_European_Number, // EN
Direction_European_Separator, // ES
Direction_European_Terminator, // ET
Direction_Left_To_Right, // L
Direction_Left_To_Right_Embedding, // LRE
Direction_Left_To_Right_Override, // LRO
Direction_Nonspacing_Mark, // NSM
Direction_Other_Neutral, // ON
Direction_Paragraph_Separator, // B
Direction_Pop_Directional_Format, // PDF
Direction_Right_To_Left, // R
Direction_Right_To_Left_Embedding, // RLE
Direction_Right_To_Left_Override, // RLO
Direction_Segment_Separator, // S
Direction_White_Space // WS
Direction_Arabic_Letter, // AL
Direction_Arabic_Number, // AN
Direction_Boundary_Neutral, // BN
Direction_Common_Separator, // CS
Direction_European_Number, // EN
Direction_European_Separator, // ES
Direction_European_Terminator, // ET
Direction_First_Strong_Isolate, // FSI
Direction_Left_To_Right, // L
Direction_Left_To_Right_Embedding, // LRE
Direction_Left_To_Right_Isolate, // LRI
Direction_Left_To_Right_Override, // LRO
Direction_Nonspacing_Mark, // NSM
Direction_Other_Neutral, // ON
Direction_Paragraph_Separator, // B
Direction_Pop_Directional_Formatting, // PDF
Direction_Pop_Directional_Isolate, // PDI
Direction_Right_To_Left, // R
Direction_Right_To_Left_Embedding, // RLE
Direction_Right_To_Left_Isolate, // RLI
Direction_Right_To_Left_Override, // RLO
Direction_Segment_Separator, // S
Direction_White_Space // WS
};
static Category GetCategory(char32_t character);

View File

@@ -10,6 +10,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Math/Angle.hpp>
namespace Nz
{
@@ -34,14 +35,14 @@ namespace Nz
std::unique_ptr<InstancedRenderable> Clone() const override;
inline const Color& GetColor() const;
inline float GetRotation() const;
inline const RadianAnglef& GetRotation() const;
inline const Vector2f& GetSize() const;
inline void SetColor(const Color& color);
inline void SetDefaultMaterial();
inline void SetMaterial(MaterialRef material, bool resizeBillboard = true);
inline void SetMaterial(std::size_t skinIndex, MaterialRef material, bool resizeBillboard = true);
inline void SetRotation(float rotation);
inline void SetRotation(const RadianAnglef& rotation);
inline void SetSize(const Vector2f& size);
inline void SetSize(float sizeX, float sizeY);
inline void SetTexture(TextureRef texture, bool resizeBillboard = true);
@@ -58,7 +59,7 @@ namespace Nz
Color m_color;
Vector2f m_sinCos;
Vector2f m_size;
float m_rotation;
RadianAnglef m_rotation;
static BillboardLibrary::LibraryMap s_library;
};

View File

@@ -84,7 +84,7 @@ namespace Nz
* \return Current rotation
*/
inline float Billboard::GetRotation() const
inline const RadianAnglef& Billboard::GetRotation() const
{
return m_rotation;
}
@@ -161,10 +161,12 @@ namespace Nz
* \param rotation Rotation for the billboard
*/
inline void Billboard::SetRotation(float rotation)
inline void Billboard::SetRotation(const RadianAnglef& rotation)
{
m_rotation = rotation;
m_sinCos.Set(std::sin(m_rotation), std::cos(m_rotation));
auto sincos = rotation.GetSinCos();
m_sinCos.Set(sincos.first, sincos.second);
}
/*!

View File

@@ -23,11 +23,13 @@ namespace Nz
{
public:
template<CullTest> class Entry;
class BoxEntry;
class NoTestEntry;
class SphereEntry;
class VolumeEntry;
template<CullTest> friend class Entry;
friend BoxEntry;
friend NoTestEntry;
friend SphereEntry;
friend VolumeEntry;
@@ -41,6 +43,12 @@ namespace Nz
std::size_t Cull(const Frustumf& frustum, bool* forceInvalidation = nullptr);
std::size_t FillWithAllEntries(bool* forceInvalidation = nullptr);
const ResultContainer& GetFullyVisibleResults() const;
const ResultContainer& GetPartiallyVisibleResults() const;
BoxEntry RegisterBoxTest(const T* renderable);
NoTestEntry RegisterNoTest(const T* renderable);
SphereEntry RegisterSphereTest(const T* renderable);
VolumeEntry RegisterVolumeTest(const T* renderable);
@@ -48,37 +56,24 @@ namespace Nz
CullingList& operator=(const CullingList& renderable) = delete;
CullingList& operator=(CullingList&& renderable) = delete;
// STL API
typename ResultContainer::iterator begin();
typename ResultContainer::const_iterator begin() const;
typename ResultContainer::const_iterator cbegin() const;
typename ResultContainer::const_iterator cend() const;
typename ResultContainer::const_reverse_iterator crbegin() const;
typename ResultContainer::const_reverse_iterator crend() const;
bool empty() const;
typename ResultContainer::iterator end();
typename ResultContainer::const_iterator end() const;
typename ResultContainer::reverse_iterator rbegin();
typename ResultContainer::const_reverse_iterator rbegin() const;
typename ResultContainer::reverse_iterator rend();
typename ResultContainer::const_reverse_iterator rend() const;
typename ResultContainer::size_type size() const;
NazaraSignal(OnCullingListRelease, CullingList* /*cullingList*/);
private:
inline void NotifyBoxUpdate(std::size_t index, const Boxf& boundingVolume);
inline void NotifyForceInvalidation(CullTest type, std::size_t index);
inline void NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr);
inline void NotifyRelease(CullTest type, std::size_t index);
inline void NotifySphereUpdate(std::size_t index, const Spheref& sphere);
inline void NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume);
struct BoxVisibilityEntry
{
Boxf box;
BoxEntry* entry;
const T* renderable;
bool forceInvalidation;
};
struct NoTestVisibilityEntry
{
NoTestEntry* entry;
@@ -102,10 +97,12 @@ namespace Nz
bool forceInvalidation;
};
std::vector<BoxVisibilityEntry> m_boxTestList;
std::vector<NoTestVisibilityEntry> m_noTestList;
std::vector<SphereVisibilityEntry> m_sphereTestList;
std::vector<VolumeVisibilityEntry> m_volumeTestList;
ResultContainer m_results;
ResultContainer m_fullyVisibleResults;
ResultContainer m_partiallyVisibleResults;
};
template<typename T>
@@ -133,43 +130,73 @@ namespace Nz
std::size_t m_index;
CullingList* m_parent;
};
template<typename T>
class CullingList<T>::BoxEntry : public CullingList<T>::template Entry<CullTest::Box>
{
friend CullingList;
public:
BoxEntry();
BoxEntry(BoxEntry&&) = default;
~BoxEntry() = default;
void UpdateBox(const Boxf& box);
BoxEntry& operator=(BoxEntry&&) = default;
private:
BoxEntry(CullingList* parent, std::size_t index);
};
template<typename T>
class CullingList<T>::NoTestEntry : public CullingList::template Entry<CullTest::NoTest>
class CullingList<T>::NoTestEntry : public CullingList<T>::template Entry<CullTest::NoTest>
{
friend CullingList;
public:
NoTestEntry();
NoTestEntry(NoTestEntry&&) = default;
~NoTestEntry() = default;
NoTestEntry& operator=(NoTestEntry&&) = default;
private:
NoTestEntry(CullingList* parent, std::size_t index);
};
template<typename T>
class CullingList<T>::SphereEntry : public CullingList::template Entry<CullTest::Sphere>
class CullingList<T>::SphereEntry : public CullingList<T>::template Entry<CullTest::Sphere>
{
friend CullingList;
public:
SphereEntry();
SphereEntry(SphereEntry&&) = default;
~SphereEntry() = default;
void UpdateSphere(const Spheref& sphere);
SphereEntry& operator=(SphereEntry&&) = default;
private:
SphereEntry(CullingList* parent, std::size_t index);
};
template<typename T>
class CullingList<T>::VolumeEntry : public CullingList::template Entry<CullTest::Volume>
class CullingList<T>::VolumeEntry : public CullingList<T>::template Entry<CullTest::Volume>
{
friend CullingList;
public:
VolumeEntry();
VolumeEntry(VolumeEntry&&) = default;
~VolumeEntry() = default;
void UpdateVolume(const BoundingVolumef& sphere);
VolumeEntry& operator=(VolumeEntry&&) = default;
private:
VolumeEntry(CullingList* parent, std::size_t index);
};

View File

@@ -16,16 +16,48 @@ namespace Nz
template<typename T>
std::size_t CullingList<T>::Cull(const Frustumf& frustum, bool* forceInvalidation)
{
m_results.clear();
m_fullyVisibleResults.clear();
m_partiallyVisibleResults.clear();
bool forcedInvalidation = false;
std::size_t visibleHash = 0U;
std::size_t fullyVisibleHash = 5U;
std::size_t partiallyVisibleHash = 5U;
auto CombineHash = [](std::size_t currentHash, std::size_t newHash)
{
return currentHash * 23 + newHash;
};
for (BoxVisibilityEntry& entry : m_boxTestList)
{
switch (frustum.Intersect(entry.box))
{
case IntersectionSide_Inside:
m_fullyVisibleResults.push_back(entry.renderable);
fullyVisibleHash = CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
entry.forceInvalidation = false;
break;
case IntersectionSide_Intersecting:
m_partiallyVisibleResults.push_back(entry.renderable);
partiallyVisibleHash = CombineHash(partiallyVisibleHash, std::hash<const T*>()(entry.renderable));
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
entry.forceInvalidation = false;
break;
case IntersectionSide_Outside:
break;
}
}
for (NoTestVisibilityEntry& entry : m_noTestList)
{
m_results.push_back(entry.renderable);
Nz::HashCombine(visibleHash, entry.renderable);
m_fullyVisibleResults.push_back(entry.renderable);
CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
if (entry.forceInvalidation)
{
@@ -36,34 +68,87 @@ namespace Nz
for (SphereVisibilityEntry& entry : m_sphereTestList)
{
if (frustum.Contains(entry.sphere))
switch (frustum.Intersect(entry.sphere))
{
m_results.push_back(entry.renderable);
Nz::HashCombine(visibleHash, entry.renderable);
case IntersectionSide_Inside:
m_fullyVisibleResults.push_back(entry.renderable);
fullyVisibleHash = CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
if (entry.forceInvalidation)
{
forcedInvalidation = true;
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
entry.forceInvalidation = false;
}
break;
case IntersectionSide_Intersecting:
m_partiallyVisibleResults.push_back(entry.renderable);
partiallyVisibleHash = CombineHash(partiallyVisibleHash, std::hash<const T*>()(entry.renderable));
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
entry.forceInvalidation = false;
break;
case IntersectionSide_Outside:
break;
}
}
for (VolumeVisibilityEntry& entry : m_volumeTestList)
{
if (frustum.Contains(entry.volume))
switch (frustum.Intersect(entry.volume))
{
m_results.push_back(entry.renderable);
Nz::HashCombine(visibleHash, entry.renderable);
case IntersectionSide_Inside:
m_fullyVisibleResults.push_back(entry.renderable);
fullyVisibleHash = CombineHash(fullyVisibleHash, std::hash<const T*>()(entry.renderable));
if (entry.forceInvalidation)
{
forcedInvalidation = true;
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
entry.forceInvalidation = false;
}
break;
case IntersectionSide_Intersecting:
m_partiallyVisibleResults.push_back(entry.renderable);
partiallyVisibleHash = CombineHash(partiallyVisibleHash, std::hash<const T*>()(entry.renderable));
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
entry.forceInvalidation = false;
break;
case IntersectionSide_Outside:
break;
}
}
if (forceInvalidation)
*forceInvalidation = forcedInvalidation;
return 5 + partiallyVisibleHash * 17 + fullyVisibleHash;
}
template<typename T>
std::size_t CullingList<T>::FillWithAllEntries(bool* forceInvalidation)
{
m_fullyVisibleResults.clear();
m_partiallyVisibleResults.clear();
bool forcedInvalidation = false;
std::size_t visibleHash = 5U;
auto FillWithList = [&](auto& testList)
{
for (auto& entry : testList)
{
m_fullyVisibleResults.push_back(entry.renderable);
visibleHash = visibleHash * 23 + std::hash<const T*>()(entry.renderable);
forcedInvalidation = forcedInvalidation | entry.forceInvalidation;
entry.forceInvalidation = false;
}
};
FillWithList(m_boxTestList);
FillWithList(m_noTestList);
FillWithList(m_sphereTestList);
FillWithList(m_volumeTestList);
if (forceInvalidation)
*forceInvalidation = forcedInvalidation;
@@ -71,115 +156,57 @@ namespace Nz
}
template<typename T>
typename CullingList<T>::NoTestEntry CullingList<T>::RegisterNoTest(const T* renderable)
auto CullingList<T>::GetFullyVisibleResults() const -> const ResultContainer&
{
NoTestEntry entry(this, m_noTestList.size());
m_noTestList.emplace_back(NoTestVisibilityEntry{&entry, renderable, false}); //< Address of entry will be updated when moving
return entry;
return m_fullyVisibleResults;
}
template<typename T>
typename CullingList<T>::SphereEntry CullingList<T>::RegisterSphereTest(const T* renderable)
auto CullingList<T>::GetPartiallyVisibleResults() const -> const ResultContainer&
{
SphereEntry entry(this, m_sphereTestList.size());
m_sphereTestList.emplace_back(SphereVisibilityEntry{Nz::Spheref(), &entry, renderable, false}); //< Address of entry will be updated when moving
return entry;
return m_partiallyVisibleResults;
}
template<typename T>
typename CullingList<T>::VolumeEntry CullingList<T>::RegisterVolumeTest(const T* renderable)
auto CullingList<T>::RegisterBoxTest(const T* renderable) -> BoxEntry
{
VolumeEntry entry(this, m_volumeTestList.size());
m_volumeTestList.emplace_back(VolumeVisibilityEntry{Nz::BoundingVolumef(), &entry, renderable, false}); //< Address of entry will be updated when moving
BoxEntry newEntry(this, m_boxTestList.size());
m_boxTestList.emplace_back(BoxVisibilityEntry{ Nz::Boxf(), &newEntry, renderable, false }); //< Address of entry will be updated when moving
return entry;
}
// Interface STD
template<typename T>
typename CullingList<T>::ResultContainer::iterator CullingList<T>::begin()
{
return m_results.begin();
return newEntry;
}
template<typename T>
typename CullingList<T>::ResultContainer::const_iterator CullingList<T>::begin() const
auto CullingList<T>::RegisterNoTest(const T* renderable) -> NoTestEntry
{
return m_results.begin();
NoTestEntry newEntry(this, m_volumeTestList.size());
m_noTestList.emplace_back(NoTestVisibilityEntry{&newEntry, renderable, false}); //< Address of entry will be updated when moving
return newEntry;
}
template<typename T>
typename CullingList<T>::ResultContainer::const_iterator CullingList<T>::cbegin() const
auto CullingList<T>::RegisterSphereTest(const T* renderable) -> SphereEntry
{
return m_results.cbegin();
SphereEntry newEntry(this, m_sphereTestList.size());
m_sphereTestList.emplace_back(SphereVisibilityEntry{Nz::Spheref(), &newEntry, renderable, false}); //< Address of entry will be updated when moving
return newEntry;
}
template<typename T>
typename CullingList<T>::ResultContainer::const_iterator CullingList<T>::cend() const
auto CullingList<T>::RegisterVolumeTest(const T* renderable) -> VolumeEntry
{
return m_results.cend();
VolumeEntry newEntry(this, m_volumeTestList.size());
m_volumeTestList.emplace_back(VolumeVisibilityEntry{Nz::BoundingVolumef(), &newEntry, renderable, false}); //< Address of entry will be updated when moving
return newEntry;
}
template<typename T>
typename CullingList<T>::ResultContainer::const_reverse_iterator CullingList<T>::crbegin() const
inline void CullingList<T>::NotifyBoxUpdate(std::size_t index, const Boxf& box)
{
return m_results.crbegin();
}
template<typename T>
typename CullingList<T>::ResultContainer::const_reverse_iterator CullingList<T>::crend() const
{
return m_results.crend();
}
template<typename T>
bool CullingList<T>::empty() const
{
return m_results.empty();
}
template<typename T>
typename CullingList<T>::ResultContainer::iterator CullingList<T>::end()
{
return m_results.end();
}
template<typename T>
typename CullingList<T>::ResultContainer::const_iterator CullingList<T>::end() const
{
return m_results.end();
}
template<typename T>
typename CullingList<T>::ResultContainer::reverse_iterator CullingList<T>::rbegin()
{
return m_results.rbegin();
}
template<typename T>
typename CullingList<T>::ResultContainer::const_reverse_iterator CullingList<T>::rbegin() const
{
return m_results.rbegin();
}
template<typename T>
typename CullingList<T>::ResultContainer::reverse_iterator CullingList<T>::rend()
{
return m_results.rend();
}
template<typename T>
typename CullingList<T>::ResultContainer::const_reverse_iterator CullingList<T>::rend() const
{
return m_results.rend();
}
template<typename T>
typename CullingList<T>::ResultContainer::size_type CullingList<T>::size() const
{
return m_results.size();
m_boxTestList[index].box = box;
}
template<typename T>
@@ -187,6 +214,12 @@ namespace Nz
{
switch (type)
{
case CullTest::Box:
{
m_boxTestList[index].forceInvalidation = true;
break;
}
case CullTest::NoTest:
{
m_noTestList[index].forceInvalidation = true;
@@ -218,6 +251,15 @@ namespace Nz
switch (type)
{
case CullTest::Box:
{
BoxVisibilityEntry& entry = m_boxTestList[index];
NazaraAssert(entry.entry == oldPtr, "Invalid box entry");
entry.entry = static_cast<BoxEntry*>(newPtr);
break;
}
case CullTest::NoTest:
{
NoTestVisibilityEntry& entry = m_noTestList[index];
@@ -256,6 +298,14 @@ namespace Nz
{
switch (type)
{
case CullTest::Box:
{
m_boxTestList[index] = std::move(m_boxTestList.back());
m_boxTestList[index].entry->UpdateIndex(index);
m_boxTestList.pop_back();
break;
}
case CullTest::NoTest:
{
m_noTestList[index] = std::move(m_noTestList.back());
@@ -358,12 +408,7 @@ namespace Nz
template<typename T>
template<CullTest Type>
#ifdef NAZARA_COMPILER_MSVC
// MSVC bug
typename CullingList<T>::Entry<Type>& CullingList<T>::Entry<Type>::operator=(Entry&& entry)
#else
typename CullingList<T>::template Entry<Type>& CullingList<T>::Entry<Type>::operator=(Entry&& entry)
#endif
{
m_index = entry.m_index;
m_parent = entry.m_parent;
@@ -374,6 +419,26 @@ namespace Nz
return *this;
}
//////////////////////////////////////////////////////////////////////////
template<typename T>
CullingList<T>::BoxEntry::BoxEntry() :
Entry<CullTest::Box>()
{
}
template<typename T>
CullingList<T>::BoxEntry::BoxEntry(CullingList* parent, std::size_t index) :
Entry<CullTest::Box>(parent, index)
{
}
template<typename T>
void CullingList<T>::BoxEntry::UpdateBox(const Boxf& box)
{
this->m_parent->NotifyBoxUpdate(this->m_index, box);
}
//////////////////////////////////////////////////////////////////////////

View File

@@ -51,8 +51,16 @@ namespace Nz
int textureOverlay;
};
struct SpriteBatch
{
std::size_t spriteCount;
const Material* material;
const Texture* overlayTexture;
Recti scissorRect;
};
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
mutable std::vector<std::pair<const VertexStruct_XYZ_Color_UV*, std::size_t>> m_spriteChains;
mutable std::vector<SpriteBatch> m_spriteBatches;
Buffer m_vertexBuffer;
RenderStates m_clearStates;
ShaderRef m_clearShader;

View File

@@ -61,8 +61,16 @@ namespace Nz
int textureOverlay;
};
struct SpriteBatch
{
std::size_t spriteCount;
const Material* material;
const Texture* overlayTexture;
Recti scissorRect;
};
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
mutable std::vector<std::pair<const VertexStruct_XYZ_Color_UV*, std::size_t>> m_spriteChains;
mutable std::vector<SpriteBatch> m_spriteBatches;
Buffer m_vertexBuffer;
RenderStates m_clearStates;
ShaderRef m_clearShader;

View File

@@ -21,6 +21,7 @@ namespace Nz
enum class CullTest
{
Box,
NoTest,
Sphere,
Volume

View File

@@ -83,6 +83,7 @@ namespace Nz
inline void EnableShadowCasting(bool castShadows);
inline void EnableShadowReceive(bool receiveShadows);
inline void EnableStencilTest(bool stencilTest);
inline void EnableVertexColor(bool vertexColor);
inline void EnsurePipelineUpdate() const;
@@ -121,6 +122,7 @@ namespace Nz
inline bool HasHeightMap() const;
inline bool HasNormalMap() const;
inline bool HasSpecularMap() const;
inline bool HasVertexColor() const;
inline bool IsAlphaTestEnabled() const;
inline bool IsBlendingEnabled() const;
@@ -135,10 +137,6 @@ namespace Nz
inline bool IsShadowCastingEnabled() const;
inline bool IsShadowReceiveEnabled() const;
inline bool LoadFromFile(const String& filePath, const MaterialParams& params = MaterialParams());
inline bool LoadFromMemory(const void* data, std::size_t size, const MaterialParams& params = MaterialParams());
inline bool LoadFromStream(Stream& stream, const MaterialParams& params = MaterialParams());
void Reset();
void SaveToParameters(ParameterList* matData);
@@ -178,6 +176,11 @@ namespace Nz
inline static MaterialRef GetDefault();
inline static int GetTextureUnit(TextureMap textureMap);
static inline MaterialRef LoadFromFile(const String& filePath, const MaterialParams& params = MaterialParams());
static inline MaterialRef LoadFromMemory(const void* data, std::size_t size, const MaterialParams& params = MaterialParams());
static inline MaterialRef LoadFromStream(Stream& stream, const MaterialParams& params = MaterialParams());
template<typename... Args> static MaterialRef New(Args&&... args);
// Signals:

View File

@@ -72,7 +72,8 @@ namespace Nz
*/
inline Material::Material(const Material& material) :
RefCounted(),
Resource(material)
Resource(material),
m_reflectionMode(ReflectionMode_Skybox)
{
Copy(material);
}
@@ -118,6 +119,14 @@ namespace Nz
{
m_pipelineInfo = pipelineInfo;
// Temp and dirty fix for pipeline overriding has*Map
m_pipelineInfo.hasAlphaMap = m_alphaMap.IsValid();
m_pipelineInfo.hasDiffuseMap = m_diffuseMap.IsValid();
m_pipelineInfo.hasEmissiveMap = m_emissiveMap.IsValid();
m_pipelineInfo.hasHeightMap = m_heightMap.IsValid();
m_pipelineInfo.hasNormalMap = m_normalMap.IsValid();
m_pipelineInfo.hasSpecularMap = m_specularMap.IsValid();
InvalidatePipeline();
}
@@ -392,6 +401,25 @@ namespace Nz
InvalidatePipeline();
}
/*!
* \brief Enable/Disable vertex coloring on this material
*
* This is a temporary option, until the new material pipeline system is ready, allowing to enable vertex coloring.
* This option only works with meshes using vertex colors.
*
* \param vertexColor Defines if this material will use vertex color or not
*
* \remark Invalidates the pipeline
*
* \see HasVertexColor
*/
inline void Material::EnableVertexColor(bool vertexColor)
{
m_pipelineInfo.hasVertexColor = vertexColor;
InvalidatePipeline();
}
/*!
* \brief Ensures the pipeline gets updated
*
@@ -756,6 +784,15 @@ namespace Nz
return m_specularMap.IsValid();
}
/*!
* \brief Checks whether this material uses vertex coloring
* \return true If it is the case
*/
inline bool Material::HasVertexColor() const
{
return m_pipelineInfo.hasVertexColor;
}
/*!
* \brief Checks whether this material has alpha test enabled
* \return true If it is the case
@@ -866,43 +903,6 @@ namespace Nz
return m_pipelineInfo.shadowReceive;
}
/*!
* \brief Loads the material from file
* \return true if loading is successful
*
* \param filePath Path to the file
* \param params Parameters for the material
*/
inline bool Material::LoadFromFile(const String& filePath, const MaterialParams& params)
{
return MaterialLoader::LoadFromFile(this, filePath, params);
}
/*!
* \brief Loads the material from memory
* \return true if loading is successful
*
* \param data Raw memory
* \param size Size of the memory
* \param params Parameters for the material
*/
inline bool Material::LoadFromMemory(const void* data, std::size_t size, const MaterialParams& params)
{
return MaterialLoader::LoadFromMemory(this, data, size, params);
}
/*!
* \brief Loads the material from stream
* \return true if loading is successful
*
* \param stream Stream to the material
* \param params Parameters for the material
*/
inline bool Material::LoadFromStream(Stream& stream, const MaterialParams& params)
{
return MaterialLoader::LoadFromStream(this, stream, params);
}
/*!
* \brief Sets the alpha map by name
* \return true If successful
@@ -1437,6 +1437,43 @@ namespace Nz
return s_textureUnits[textureMap];
}
/*!
* \brief Loads the material from file
* \return true if loading is successful
*
* \param filePath Path to the file
* \param params Parameters for the material
*/
inline MaterialRef Material::LoadFromFile(const String& filePath, const MaterialParams& params)
{
return MaterialLoader::LoadFromFile(filePath, params);
}
/*!
* \brief Loads the material from memory
* \return true if loading is successful
*
* \param data Raw memory
* \param size Size of the memory
* \param params Parameters for the material
*/
inline MaterialRef Material::LoadFromMemory(const void* data, std::size_t size, const MaterialParams& params)
{
return MaterialLoader::LoadFromMemory(data, size, params);
}
/*!
* \brief Loads the material from stream
* \return true if loading is successful
*
* \param stream Stream to the material
* \param params Parameters for the material
*/
inline MaterialRef Material::LoadFromStream(Stream& stream, const MaterialParams& params)
{
return MaterialLoader::LoadFromStream(stream, params);
}
inline void Material::InvalidatePipeline()
{
m_pipelineUpdated = false;

View File

@@ -26,6 +26,7 @@ namespace Nz
bool hasHeightMap = false;
bool hasNormalMap = false;
bool hasSpecularMap = false;
bool hasVertexColor = false;
bool reflectionMapping = false;
bool shadowReceive = true;

View File

@@ -71,6 +71,7 @@ namespace Nz
NazaraPipelineBoolMember(hasHeightMap);
NazaraPipelineBoolMember(hasNormalMap);
NazaraPipelineBoolMember(hasSpecularMap);
NazaraPipelineBoolMember(hasVertexColor);
NazaraPipelineBoolMember(reflectionMapping);
NazaraPipelineBoolMember(shadowReceive);
@@ -127,6 +128,7 @@ namespace std
NazaraPipelineBoolMember(hasHeightMap);
NazaraPipelineBoolMember(hasNormalMap);
NazaraPipelineBoolMember(hasSpecularMap);
NazaraPipelineBoolMember(hasVertexColor);
NazaraPipelineBoolMember(reflectionMapping);
NazaraPipelineBoolMember(shadowReceive);

View File

@@ -65,10 +65,6 @@ namespace Nz
virtual bool IsAnimated() const;
bool LoadFromFile(const String& filePath, const ModelParameters& params = ModelParameters());
bool LoadFromMemory(const void* data, std::size_t size, const ModelParameters& params = ModelParameters());
bool LoadFromStream(Stream& stream, const ModelParameters& params = ModelParameters());
using InstancedRenderable::SetMaterial;
bool SetMaterial(const String& subMeshName, MaterialRef material);
bool SetMaterial(std::size_t skinIndex, const String& subMeshName, MaterialRef material);
@@ -78,6 +74,10 @@ namespace Nz
Model& operator=(const Model& node) = default;
Model& operator=(Model&& node) = delete;
static ModelRef LoadFromFile(const String& filePath, const ModelParameters& params = ModelParameters());
static ModelRef LoadFromMemory(const void* data, std::size_t size, const ModelParameters& params = ModelParameters());
static ModelRef LoadFromStream(Stream& stream, const ModelParameters& params = ModelParameters());
template<typename... Args> static ModelRef New(Args&&... args);
protected:

View File

@@ -25,6 +25,14 @@ namespace Nz
InstancedRenderable(model)
{
SetMesh(model.m_mesh);
// Since SetMesh does reset materials, we need reapply them
SetSkinCount(model.GetSkinCount());
for (std::size_t skin = 0; skin < model.GetSkinCount(); ++skin)
{
for (std::size_t matIndex = 0; matIndex < model.GetMaterialCount(); ++matIndex)
SetMaterial(skin, matIndex, model.GetMaterial(skin, matIndex));
}
}
/*!
@@ -51,7 +59,6 @@ namespace Nz
*
* \param args Arguments for the model
*/
template<typename... Args>
ModelRef Model::New(Args&&... args)
{

View File

@@ -26,12 +26,10 @@ namespace Nz
class SkeletalModel;
using SkeletalModelLoader = ResourceLoader<SkeletalModel, SkeletalModelParameters>;
using SkeletalModelRef = ObjectRef<SkeletalModel>;
class NAZARA_GRAPHICS_API SkeletalModel : public Model, Updatable
{
friend SkeletalModelLoader;
public:
SkeletalModel();
SkeletalModel(const SkeletalModel& model) = default;
@@ -55,10 +53,6 @@ namespace Nz
bool IsAnimated() const override;
bool IsAnimationEnabled() const;
bool LoadFromFile(const String& filePath, const SkeletalModelParameters& params = SkeletalModelParameters());
bool LoadFromMemory(const void* data, std::size_t size, const SkeletalModelParameters& params = SkeletalModelParameters());
bool LoadFromStream(Stream& stream, const SkeletalModelParameters& params = SkeletalModelParameters());
bool SetAnimation(Animation* animation);
void SetMesh(Mesh* mesh) override;
bool SetSequence(const String& sequenceName);
@@ -67,6 +61,8 @@ namespace Nz
SkeletalModel& operator=(const SkeletalModel& node) = default;
SkeletalModel& operator=(SkeletalModel&& node) = default;
template<typename... Args> static SkeletalModelRef New(Args&&... args);
private:
void MakeBoundingVolume() const override;
/*void Register() override;
@@ -80,9 +76,9 @@ namespace Nz
float m_interpolation;
unsigned int m_currentFrame;
unsigned int m_nextFrame;
static SkeletalModelLoader::LoaderList s_loaders;
};
}
#include <Nazara/Graphics/SkeletalModel.inl>
#endif // NAZARA_SKELETALMODEL_HPP

View File

@@ -0,0 +1,27 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/SkeletalModel.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
/*!
* \brief Creates a new SkeletalModel from the arguments
* \return A reference to the newly created SkeletalModel
*
* \param args Arguments for the skeletal model
*/
template<typename... Args>
SkeletalModelRef SkeletalModel::New(Args&&... args)
{
std::unique_ptr<SkeletalModel> object(new SkeletalModel(std::forward<Args>(args)...));
object->SetPersistent(false);
return object.release();
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@@ -29,7 +29,7 @@ namespace Nz
inline Sprite();
inline Sprite(MaterialRef material);
inline Sprite(Texture* texture);
inline Sprite(const Sprite& sprite);
Sprite(const Sprite&) = default;
Sprite(Sprite&&) = delete;
~Sprite() = default;

View File

@@ -50,21 +50,6 @@ namespace Nz
SetTexture(texture, true);
}
/*!
* \brief Constructs a Sprite object by assignation
*
* \param sprite Sprite to copy into this
*/
inline Sprite::Sprite(const Sprite& sprite) :
InstancedRenderable(sprite),
m_color(sprite.m_color),
m_textureCoords(sprite.m_textureCoords),
m_size(sprite.m_size),
m_origin(sprite.m_origin)
{
}
/*!
* \brief Gets the color of the sprite
*
@@ -295,8 +280,10 @@ namespace Nz
else
{
material->SetDiffuseMap(std::move(texture));
if (resizeSprite && texture && texture->IsValid())
SetSize(Vector2f(Vector2ui(texture->GetSize())));
const TextureRef& newTexture = material->GetDiffuseMap();
if (resizeSprite && newTexture && newTexture->IsValid())
SetSize(Vector2f(Vector2ui(newTexture->GetSize())));
}
}

View File

@@ -59,6 +59,31 @@ namespace Nz
void OnAtlasLayerChange(const AbstractAtlas* atlas, AbstractImage* oldLayer, AbstractImage* newLayer);
void UpdateData(InstanceData* instanceData) const override;
struct RenderKey
{
Texture* texture;
int renderOrder;
bool operator==(const RenderKey& rhs) const
{
return texture == rhs.texture && renderOrder == rhs.renderOrder;
}
bool operator!=(const RenderKey& rhs) const
{
return !operator==(rhs);
}
};
struct HashRenderKey
{
std::size_t operator()(const RenderKey& key) const
{
// Since renderOrder will be very small, this will be enough
return std::hash<Texture*>()(key.texture) + key.renderOrder;
}
};
struct RenderIndices
{
unsigned int first;
@@ -74,10 +99,10 @@ namespace Nz
};
std::unordered_map<const AbstractAtlas*, AtlasSlots> m_atlases;
mutable std::unordered_map<Texture*, RenderIndices> m_renderInfos;
mutable std::unordered_map<RenderKey, RenderIndices, HashRenderKey> m_renderInfos;
mutable std::vector<VertexStruct_XY_Color_UV> m_localVertices;
Color m_color;
Recti m_localBounds;
Rectf m_localBounds;
float m_scale;
static TextSpriteLibrary::LibraryMap s_library;

View File

@@ -14,7 +14,7 @@ namespace Nz
inline TextSprite::TextSprite() :
m_color(Color::White),
m_localBounds(Nz::Recti::Zero()),
m_localBounds(Nz::Rectf::Zero()),
m_scale(1.f)
{
ResetMaterials(1U);

View File

@@ -29,7 +29,7 @@ namespace Nz
struct Tile;
inline TileMap(const Nz::Vector2ui& mapSize, const Nz::Vector2f& tileSize, std::size_t materialCount = 1);
TileMap(const TileMap& TileMap) = default;
TileMap(const TileMap&) = default;
TileMap(TileMap&&) = delete;
~TileMap() = default;

View File

@@ -149,8 +149,8 @@ namespace Nz
m_layers[materialIndex].tiles.insert(tileIndex);
else if (materialIndex != tile.layerIndex)
{
m_layers[materialIndex].tiles.erase(tileIndex);
m_layers[tile.layerIndex].tiles.insert(tileIndex);
m_layers[tile.layerIndex].tiles.erase(tileIndex);
m_layers[materialIndex].tiles.insert(tileIndex);
invalidatedLayers |= 1U << tile.layerIndex;
}
@@ -285,8 +285,8 @@ namespace Nz
m_layers[materialIndex].tiles.insert(tileIndex);
else if (materialIndex != tile.layerIndex)
{
m_layers[materialIndex].tiles.erase(tileIndex);
m_layers[tile.layerIndex].tiles.insert(tileIndex);
m_layers[tile.layerIndex].tiles.erase(tileIndex);
m_layers[materialIndex].tiles.insert(tileIndex);
invalidatedLayers |= 1U << tile.layerIndex;
}

View File

@@ -15,8 +15,7 @@ namespace Nz
{
LuaState::operator=(std::move(instance));
m_ref = instance.m_ref;
instance.m_ref = -1;
std::swap(m_ref, instance.m_ref);
return *this;
}

View File

@@ -157,6 +157,8 @@ namespace Nz
void* PushUserdata(std::size_t size) const;
void PushValue(int index) const;
bool RawEqual(int index1, int index2) const;
void Remove(int index) const;
void Replace(int index) const;

View File

@@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Flags.hpp>
#include <Nazara/Core/MemoryHelper.hpp>
#include <Nazara/Core/StringStream.hpp>
@@ -159,6 +160,35 @@ namespace Nz
return LuaImplQueryArg(instance, index, arg, defValue, TypeTag<T>());
}
template<typename T>
unsigned int LuaImplQueryArg(const LuaState& instance, int index, std::vector<T>* container, TypeTag<std::vector<T>>)
{
instance.CheckType(index, Nz::LuaType_Table);
std::size_t pos = 1;
container->clear();
for (;;)
{
Nz::CallOnExit popStack { [&instance]() { instance.Pop(); } };
instance.PushInteger(pos++);
int tableIndex = (index < 0) ? index - 1 : index;
if (instance.GetTable(tableIndex) == Nz::LuaType_Nil)
break;
T arg;
if (LuaImplQueryArg(instance, -1, &arg, TypeTag<T>()) != 1)
{
instance.Error("Type needs more than one place to be initialized");
return 0;
}
container->push_back(arg);
}
return 1;
}
// Function returns
inline int LuaImplReplyVal(const LuaState& instance, bool val, TypeTag<bool>)
{

View File

@@ -31,6 +31,7 @@
#define NAZARA_GLOBAL_MATH_HPP
#include <Nazara/Math/Algorithm.hpp>
#include <Nazara/Math/Angle.hpp>
#include <Nazara/Math/BoundingVolume.hpp>
#include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Config.hpp>

View File

@@ -35,15 +35,15 @@
namespace Nz
{
template<typename T> /*constexpr*/ 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> /*constexpr*/ std::size_t CountBits(T value);
template<typename T> constexpr std::size_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> /*constexpr*/ T GetNearestPowerOfTwo(T number);
/*constexpr*/ unsigned int GetNumberLength(signed char number);
/*constexpr*/ 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);
/*constexpr*/ unsigned int GetNumberLength(unsigned int number);
unsigned int GetNumberLength(long long number);
@@ -53,12 +53,12 @@ namespace Nz
unsigned int GetNumberLength(long double number, UInt8 precision = NAZARA_CORE_DECIMAL_DIGITS);
template<typename T> /*constexpr*/ unsigned int IntegralLog2(T number);
template<typename T> /*constexpr*/ unsigned int IntegralLog2Pot(T pot);
template<typename T> /*constexpr*/ T IntegralPow(T base, unsigned int exponent);
template<typename T> constexpr T IntegralPow(T 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);
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> constexpr T RadianToDegree(T radians);
long long StringToNumber(String str, UInt8 radix = 10, bool* ok = nullptr);

View File

@@ -98,13 +98,13 @@ namespace Nz
return 0;
}
template<typename T> /*constexpr*/ std::enable_if_t<std::is_floating_point<T>::value, bool> NumberEquals(T a, T b, T maxDifference)
template<typename T> constexpr std::enable_if_t<std::is_floating_point<T>::value, bool> NumberEquals(T a, T b, T maxDifference)
{
T diff = std::abs(a - b);
return diff <= maxDifference;
}
template<typename T> /*constexpr*/ std::enable_if_t<!std::is_signed<T>::value || (!std::is_integral<T>::value && !std::is_floating_point<T>::value), bool> NumberEquals(T a, T b, T maxDifference)
template<typename T> constexpr std::enable_if_t<!std::is_signed<T>::value || (!std::is_integral<T>::value && !std::is_floating_point<T>::value), bool> NumberEquals(T a, T b, T maxDifference)
{
if (b > a)
std::swap(a, b);
@@ -113,7 +113,7 @@ namespace Nz
return diff <= maxDifference;
}
template<typename T> /*constexpr*/ std::enable_if_t<std::is_signed<T>::value && std::is_integral<T>::value, bool> NumberEquals(T a, T b, T maxDifference)
template<typename T> constexpr std::enable_if_t<std::is_signed<T>::value && std::is_integral<T>::value, bool> NumberEquals(T a, T b, T maxDifference)
{
if (b > a)
std::swap(a, b);
@@ -132,10 +132,8 @@ namespace Nz
* \param objective Target value
* \param increment One step value
*/
template<typename T>
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline T Approach(T value, T objective, T increment)
constexpr inline T Approach(T value, T objective, T increment)
{
if (value < objective)
return std::min(value + increment, objective);
@@ -154,7 +152,6 @@ namespace Nz
* \param min Minimum of the interval
* \param max Maximum of the interval
*/
template<typename T>
constexpr T Clamp(T value, T min, T max)
{
@@ -168,10 +165,8 @@ namespace Nz
*
* \param value The value to count bits
*/
template<typename T>
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline std::size_t CountBits(T value)
constexpr inline std::size_t CountBits(T value)
{
// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
std::size_t count = 0;
@@ -191,7 +186,6 @@ namespace Nz
*
* \param degrees Angle in degree (this is expected between 0..360)
*/
template<typename T>
constexpr T DegreeToRadian(T degrees)
{
@@ -205,7 +199,6 @@ namespace Nz
*
* \param degrees Convert degree to NAZARA_MATH_ANGLE_RADIAN unit
*/
template<typename T>
constexpr T FromDegrees(T degrees)
{
@@ -223,7 +216,6 @@ namespace Nz
*
* \param radians Convert radian to NAZARA_MATH_ANGLE_RADIAN unit
*/
template<typename T>
constexpr T FromRadians(T radians)
{
@@ -241,10 +233,8 @@ namespace Nz
*
* \param number Number to get nearest power
*/
template<typename T>
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline T GetNearestPowerOfTwo(T number)
constexpr inline T GetNearestPowerOfTwo(T number)
{
T x = 1;
while (x < number)
@@ -260,9 +250,7 @@ namespace Nz
*
* \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)
constexpr inline unsigned int GetNumberLength(signed char number)
{
// Char is expected to be 1 byte
static_assert(sizeof(number) == 1, "Signed char must be one byte-sized");
@@ -288,9 +276,7 @@ namespace Nz
*
* \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)
constexpr inline unsigned int GetNumberLength(unsigned char number)
{
// Char is expected to be 1 byte
static_assert(sizeof(number) == 1, "Unsigned char must be one byte-sized");
@@ -310,7 +296,6 @@ namespace Nz
*
* \param number Number to get number of digits
*/
inline unsigned int GetNumberLength(int number)
{
if (number == 0)
@@ -326,7 +311,6 @@ namespace Nz
*
* \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)
{
@@ -343,7 +327,6 @@ namespace Nz
*
* \param number Number to get number of digits
*/
inline unsigned int GetNumberLength(long long number)
{
if (number == 0)
@@ -359,7 +342,6 @@ namespace Nz
*
* \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)
{
@@ -377,7 +359,6 @@ namespace Nz
* \param number Number to get number of digits
* \param precision Number of digit after the dot
*/
inline unsigned int GetNumberLength(float number, UInt8 precision)
{
// The imprecision of floats need a cast (log10(9.99999) = 0.99999)
@@ -392,7 +373,6 @@ namespace Nz
* \param number Number to get number of digits
* \param precision Number of digit after the dot
*/
inline unsigned int GetNumberLength(double number, UInt8 precision)
{
// The imprecision of floats need a cast (log10(9.99999) = 0.99999)
@@ -407,7 +387,6 @@ namespace Nz
* \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)
{
// The imprecision of floats need a cast (log10(9.99999) = 0.99999)
@@ -423,7 +402,6 @@ namespace Nz
*
* \remark If number is 0, 0 is returned
*/
template<typename T>
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline unsigned int IntegralLog2(T number)
@@ -442,7 +420,6 @@ namespace Nz
* \remark Only works for power of two
* \remark If number is 0, 0 is returned
*/
template<typename T>
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline unsigned int IntegralLog2Pot(T pot)
@@ -458,10 +435,8 @@ namespace Nz
* \param base Base of the exponentation
* \param exponent Power for the base
*/
//TODO: Mark as constexpr when supported by all major compilers
template<typename T>
/*constexpr*/ T IntegralPow(T base, unsigned int exponent)
constexpr T IntegralPow(T base, unsigned int exponent)
{
T r = 1;
for (unsigned int i = 0; i < exponent; ++i)
@@ -484,7 +459,6 @@ namespace Nz
*
* \see Lerp
*/
template<typename T, typename T2>
constexpr T Lerp(const T& from, const T& to, const T2& interpolation)
{
@@ -540,10 +514,8 @@ namespace Nz
*
* \param angle Angle to normalize
*/
template<typename T>
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline T NormalizeAngle(T angle)
constexpr inline T NormalizeAngle(T angle)
{
#if NAZARA_MATH_ANGLE_RADIAN
const T limit = T(M_PI);
@@ -567,10 +539,8 @@ namespace Nz
* \param a First value
* \param b Second value
*/
template<typename T>
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline bool NumberEquals(T a, T b)
constexpr inline bool NumberEquals(T a, T b)
{
return NumberEquals(a, b, std::numeric_limits<T>::epsilon());
}
@@ -584,10 +554,8 @@ namespace Nz
* \param b Second value
* \param maxDifference Epsilon of comparison (expected to be positive)
*/
template<typename T>
//TODO: Mark as constexpr when supported by all major compilers
/*constexpr*/ inline bool NumberEquals(T a, T b, T maxDifference)
constexpr inline bool NumberEquals(T a, T b, T maxDifference)
{
return Detail::NumberEquals(a, b, maxDifference);
}
@@ -603,7 +571,6 @@ namespace Nz
* \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
@@ -651,7 +618,6 @@ namespace Nz
*
* \param radians Angle in radian (this is expected between 0..2*pi)
*/
template<typename T>
constexpr T RadianToDegree(T radians)
{
@@ -670,7 +636,6 @@ namespace Nz
* \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
@@ -727,7 +692,6 @@ namespace Nz
*
* \param angle Convert degree from NAZARA_MATH_ANGLE_RADIAN unit to degrees
*/
template<typename T>
constexpr T ToDegrees(T angle)
{
@@ -745,7 +709,6 @@ namespace Nz
*
* \param angle Convert degree from NAZARA_MATH_ANGLE_RADIAN unit to radians
*/
template<typename T>
constexpr T ToRadians(T angle)
{

View File

@@ -0,0 +1,106 @@
// Copyright (C) 2017 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
#pragma once
#ifndef NAZARA_ANGLE_HPP
#define NAZARA_ANGLE_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <Nazara/Math/Enums.hpp>
#include <ostream>
#include <type_traits>
#include <utility>
namespace Nz
{
struct SerializationContext;
template<typename T> class EulerAngles;
template<typename T> class Quaternion;
template<AngleUnit Unit, typename T>
class Angle
{
public:
Angle() = default;
Angle(T angle);
template<typename U> explicit Angle(const Angle<Unit, U>& Angle);
Angle(const Angle&) = default;
~Angle() = default;
T GetCos() const;
T GetSin() const;
std::pair<T, T> GetSinCos() const;
T GetTan() const;
Angle& MakeZero();
void Normalize();
Angle& Set(const Angle& ang);
template<typename U> Angle& Set(const Angle<Unit, U>& ang);
T ToDegrees() const;
Angle<AngleUnit::Degree, T> ToDegreeAngle() const;
EulerAngles<T> ToEulerAngles() const;
Quaternion<T> ToQuaternion() const;
T ToRadians() const;
Angle<AngleUnit::Radian, T> ToRadianAngle() const;
String ToString() const;
template<AngleUnit U = Unit, typename = std::enable_if_t<U != AngleUnit::Degree>> operator Angle<AngleUnit::Degree, T>() const { return ToDegreeAngle(); } // GCC < 8 bug
template<AngleUnit U = Unit, typename = std::enable_if_t<U != AngleUnit::Radian>> operator Angle<AngleUnit::Radian, T>() const { return ToRadianAngle(); } // GCC < 8 bug
Angle& operator=(const Angle&) = default;
Angle operator+(const Angle& other) const;
Angle operator-(const Angle& other) const;
Angle operator*(T scalar) const;
Angle operator/(T divider) const;
Angle& operator+=(const Angle& other);
Angle& operator-=(const Angle& other);
Angle& operator*=(T scalar);
Angle& operator/=(T divider);
bool operator==(const Angle& other) const;
bool operator!=(const Angle& other) const;
static Angle FromDegrees(T ang);
static Angle FromRadians(T ang);
static Angle Zero();
T value;
};
template<typename T>
using DegreeAngle = Angle<AngleUnit::Degree, T>;
using DegreeAngled = DegreeAngle<double>;
using DegreeAnglef = DegreeAngle<float>;
template<typename T>
using RadianAngle = Angle<AngleUnit::Radian, T>;
using RadianAngled = RadianAngle<double>;
using RadianAnglef = RadianAngle<float>;
template<AngleUnit Unit, typename T> bool Serialize(SerializationContext& context, const Angle<Unit, T>& angle, TypeTag<Angle<Unit, T>>);
template<AngleUnit Unit, typename T> bool Unserialize(SerializationContext& context, Angle<Unit, T>* angle, TypeTag<Angle<Unit, T>>);
}
template<Nz::AngleUnit Unit, typename T>
Nz::Angle<Unit, T> operator*(T scale, const Nz::Angle<Unit, T>& angle);
template<Nz::AngleUnit Unit, typename T>
Nz::Angle<Unit, T> operator/(T divider, const Nz::Angle<Unit, T>& angle);
template<Nz::AngleUnit Unit, typename T>
std::ostream& operator<<(std::ostream& out, const Nz::Angle<Unit, T>& angle);
#include <Nazara/Math/Angle.inl>
#endif // NAZARA_ANGLE_HPP

View File

@@ -0,0 +1,599 @@
// Copyright (C) 2017 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/Math/Angle.hpp>
#include <algorithm>
#include <cstring>
#ifdef NAZARA_PLATFORM_POSIX
#include <math.h> //< sincos
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
namespace Detail
{
template<AngleUnit Unit> struct AngleUtils;
template<>
struct AngleUtils<AngleUnit::Degree>
{
template<typename T> static constexpr T GetEpsilon()
{
return T(1e-4);
}
template<typename T> static constexpr T GetLimit()
{
return 180;
}
template<typename T> static T FromDegrees(T degrees)
{
return degrees;
}
template<typename T> static T FromRadians(T radians)
{
return RadianToDegree(radians);
}
template<typename T> static T ToDegrees(T degrees)
{
return degrees;
}
template<typename T> static T ToRadians(T degrees)
{
return DegreeToRadian(degrees);
}
template<typename T> static String ToString(T value)
{
return "Angle(" + String::Number(value) + "deg)";
}
template<typename T> static std::ostream& ToString(std::ostream& out, T value)
{
return out << "Angle(" << value << "deg)";
}
};
template<>
struct AngleUtils<AngleUnit::Radian>
{
template<typename T> static constexpr T GetEpsilon()
{
return T(1e-5);
}
template<typename T> static constexpr T GetLimit()
{
return T(M_PI);
}
template<typename T> static T FromDegrees(T degrees)
{
return DegreeToRadian(degrees);
}
template<typename T> static T FromRadians(T radians)
{
return radians;
}
template<typename T> static T ToDegrees(T radians)
{
return RadianToDegree(radians);
}
template<typename T> static T ToRadians(T radians)
{
return radians;
}
template<typename T> static String ToString(T value)
{
return "Angle(" + String::Number(value) + "rad)";
}
template<typename T> static std::ostream& ToString(std::ostream& out, T value)
{
return out << "Angle(" << value << "rad)";
}
};
#ifdef NAZARA_PLATFORM_POSIX
template<typename T>
void SinCos(std::enable_if_t<!std::is_same<T, float>::value && !std::is_same<T, long double>::value, double> x, T* sin, T* cos)
{
double s, c;
::sincos(x, &s, &c);
*sin = static_cast<T>(s);
*cos = static_cast<T>(c);
}
template<typename T>
void SinCos(std::enable_if_t<std::is_same<T, float>::value, float> x, float* s, float* c)
{
::sincosf(x, s, c);
}
template<typename T>
void SinCos(std::enable_if_t<std::is_same<T, long double>::value, long double> x, long double* s, long double* c)
{
::sincosl(x, sin, cos);
}
#else
// Naive implementation, hopefully optimized by the compiler
template<typename T>
void SinCos(T x, T* sin, T* cos)
{
*sin = std::sin(x);
*cos = std::cos(x);
}
#endif
}
/*!
* \ingroup math
* \class Nz::Angle
* \brief Math class that represents an angle
*/
/*!
* \brief Constructs an Angle object with an angle value
*
* \param value value of the angle
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T>::Angle(T angle) :
value(angle)
{
}
/*!
* \brief Computes the cosine of the angle
* \return Cosine of angle
*
* \see GetSinCos
*/
template<AngleUnit Unit, typename T>
T Angle<Unit, T>::GetCos() const
{
return std::cos(ToRadians());
}
/*!
* \brief Computes the sine of the angle
* \return Sine of angle
*
* \see GetSinCos
*/
template<AngleUnit Unit, typename T>
T Angle<Unit, T>::GetSin() const
{
return std::sin(ToRadians());
}
/*!
* \brief Computes both sines and cosines of the angle
* \return Sine and cosine of the angle
*
* \remark This is potentially faster than calling both GetSin and GetCos separately as it can computes both values at the same time.
*
* \see GetCos, GetSin
*/
template<AngleUnit Unit, typename T>
std::pair<T, T> Angle<Unit, T>::GetSinCos() const
{
T sin, cos;
Detail::SinCos<T>(ToRadians(), &sin, &cos);
return std::make_pair(sin, cos);
}
/*!
* \brief Computes the tangent of the angle
* \return Tangent value of the angle
*
* \see GetCos, GetSin
*/
template<AngleUnit Unit, typename T>
T Angle<Unit, T>::GetTan() const
{
return std::tan(ToRadians());
}
/*!
* \brief Changes the angle value to zero
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T>& Angle<Unit, T>::MakeZero()
{
value = T(0);
return *this;
}
/*!
* \brief Normalizes the angle value
*
* If angle exceeds local limits positively or negatively, bring it back between them.
* For degree angles, local limits are [-180, 180]
* For radian angles, local limits are [-M_PI, M_PI]
*/
template<AngleUnit Unit, typename T>
void Angle<Unit, T>::Normalize()
{
constexpr T limit = Detail::AngleUtils<Unit>::template GetLimit<T>();
constexpr T twoLimit = limit * T(2);
value = std::fmod(value, twoLimit);
if (value < T(0))
value += twoLimit;
}
/*!
* \brief Copies the angle value of an angle
*
* \param Angle Angle which will be copied
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T>& Angle<Unit, T>::Set(const Angle& ang)
{
value = ang.value;
return *this;
}
/*!
* \brief Changes the angle value to the same as an Angle of a different type
*
* \param Angle Angle which will be casted
*
* \remark Conversion from U to T occurs using static_cast
*/
template<AngleUnit Unit, typename T>
template<typename U>
Angle<Unit, T>& Angle<Unit, T>::Set(const Angle<Unit, U>& ang)
{
value = static_cast<T>(ang.value);
return *this;
}
/*!
* \brief Returns the degree angle that is equivalent to this one
* \return Equivalent degree angle value
*/
template<AngleUnit Unit, typename T>
T Angle<Unit, T>::ToDegrees() const
{
return Detail::AngleUtils<Unit>::ToDegrees(value);
}
/*!
* \brief Returns the degree angle that is equivalent to this one
* \return Equivalent degree angle
*/
template<AngleUnit Unit, typename T>
Angle<AngleUnit::Degree, T> Angle<Unit, T>::ToDegreeAngle() const
{
return DegreeAngle<T>(ToDegrees());
}
/*!
* \brief Converts the angle to an Euler Angles representation
* \return A 2D rotation expressed in Euler angles
*
* This will assume two-dimensional usage, and will set the angle value (as degrees) as the roll value of the Euler Angles, leaving pitch and yaw to zero
*/
template<AngleUnit Unit, typename T>
EulerAngles<T> Angle<Unit, T>::ToEulerAngles() const
{
return EulerAngles<T>(0, 0, ToDegrees());
}
/*!
* \brief Converts the angle to a Quaternion representation
* \return A 2D rotation expressed with Quaternion
*
* This will assume two-dimensional usage, as if the angle was first converted to Euler Angles and then to a Quaternion
*
* \see ToEulerAngles
*/
template<AngleUnit Unit, typename T>
Quaternion<T> Angle<Unit, T>::ToQuaternion() const
{
auto halfAngle = Angle(*this) / 2.f;
auto sincos = halfAngle.GetSinCos();
return Quaternion<T>(sincos.second, 0, 0, sincos.first);
}
/*!
* \brief Returns the radian angle that is equivalent to this angle
* \return Equivalent radian angle value
*/
template<AngleUnit Unit, typename T>
T Angle<Unit, T>::ToRadians() const
{
return Detail::AngleUtils<Unit>::ToRadians(value);
}
/*!
* \brief Returns the radian angle that is equivalent to this angle
* \return Equivalent radian angle
*/
template<AngleUnit Unit, typename T>
Angle<AngleUnit::Radian, T> Angle<Unit, T>::ToRadianAngle() const
{
return RadianAngle<T>(ToRadians());
}
/*!
* \brief Converts the angle to a string representation
* \return String representation of the angle
*/
template<AngleUnit Unit, typename T>
String Angle<Unit, T>::ToString() const
{
return Detail::AngleUtils<Unit>::ToString(value);
}
/*!
* \brief Returns the degree angle that is equivalent to this one
* \return Equivalent degree angle
*/
/*template<AngleUnit Unit, typename T>
template<AngleUnit U, typename>
Angle<Unit, T>::operator Angle<AngleUnit::Degree, T>() const
{
return ToDegreeAngle();
}*/
/*!
* \brief Converts the angle to a string representation
* \return String representation of the angle
*/
/*template<AngleUnit Unit, typename T>
template<AngleUnit U, typename>
Angle<Unit, T>::operator Angle<AngleUnit::Radian, T>() const
{
return ToRadianAngle();
}*/
/*!
* \brief Addition operator
* \return Adds two angles together
*
* \param other Angle to add
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T> Angle<Unit, T>::operator+(const Angle& other) const
{
return Angle(value + other.value);
}
/*!
* \brief Subtraction operator
* \return Subtracts two angles together
*
* \param other Angle to subtract
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T> Angle<Unit, T>::operator-(const Angle& other) const
{
return Angle(value - other.value);
}
/*!
* \brief Multiplication operator
* \return A copy of the angle, scaled by the multiplier
*
* \param scalar Multiplier
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T> Angle<Unit, T>::operator*(T scalar) const
{
return Angle(value * scalar);
}
/*!
* \brief Divides the angle by a scalar
* \return A copy of the angle, divided by the divider
*
* \param divider Divider
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T> Angle<Unit, T>::operator/(T divider) const
{
return Angle(value / divider);
}
/*!
* \brief Adds an angle by another
* \return A reference to the angle
*
* \param other Angle to add
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T>& Angle<Unit, T>::operator+=(const Angle& other)
{
value += other.value;
return *this;
}
/*!
* \brief Subtract an angle by another
* \return A reference to the angle
*
* \param other Angle to subtract
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T>& Angle<Unit, T>::operator-=(const Angle& other)
{
value -= other.value;
return *this;
}
/*!
* \brief Scales the angle by a scalar
* \return A reference to the angle
*
* \param scalar Multiplier
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T>& Angle<Unit, T>::operator*=(T scalar)
{
value *= scalar;
return *this;
}
/*!
* \brief Divides the angle by a scalar
* \return A reference to the angle
*
* \param divider Divider
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T>& Angle<Unit, T>::operator/=(T divider)
{
value /= divider;
return *this;
}
/*!
* \brief Compares the angle to another for equality
* \return True if both angles are equal
*
* \param other The other angle to compare to
*/
template<AngleUnit Unit, typename T>
bool Angle<Unit, T>::operator==(const Angle& other) const
{
return NumberEquals(value, other.value, Detail::AngleUtils<Unit>::template GetEpsilon<T>());
}
/*!
* \brief Compares the angle to another for inequality
* \return True if both angles are equal
*
* \param other The other angle to compare to
*/
template<AngleUnit Unit, typename T>
bool Angle<Unit, T>::operator!=(const Angle& other) const
{
return !NumberEquals(value, other.value, Detail::AngleUtils<Unit>::template GetEpsilon<T>());
}
/*!
* \brief Builds an Angle instance using a degree angle, converting if needed
* \return An angle describing the degree angle as Unit
*
* \param ang Degree angle
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T> Angle<Unit, T>::FromDegrees(T ang)
{
return Angle(Detail::AngleUtils<Unit>::FromDegrees(ang));
}
/*!
* \brief Builds an Angle instance using a radian angle, converting if needed
* \return An angle describing the radian angle as Unit
*
* \param ang Radian angle
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T> Angle<Unit, T>::FromRadians(T ang)
{
return Angle(Detail::AngleUtils<Unit>::FromRadians(ang));
}
/*!
* \brief Returns an angle with an angle of zero
* \return Zero angle
*/
template<AngleUnit Unit, typename T>
Angle<Unit, T> Angle<Unit, T>::Zero()
{
Angle angle;
angle.MakeZero();
return angle;
}
/*!
* \brief Serializes an Angle
* \return true if successfully serialized
*
* \param context Serialization context
* \param angle Input Angle
*/
template<AngleUnit Unit, typename T>
bool Serialize(SerializationContext& context, const Angle<Unit, T>& angle, TypeTag<Angle<Unit, T>>)
{
if (!Serialize(context, angle.value))
return false;
return true;
}
/*!
* \brief Unserializes an Angle
* \return true if successfully unserialized
*
* \param context Serialization context
* \param angle Output Angle
*/
template<AngleUnit Unit, typename T>
bool Unserialize(SerializationContext& context, Angle<Unit, T>* angle, TypeTag<Angle<Unit, T>>)
{
if (!Unserialize(context, &angle->value))
return false;
return true;
}
}
/*!
* \brief Multiplication operator
* \return An angle corresponding to scale * angle
*
* \param scale Multiplier
* \param angle Angle
*/
template<Nz::AngleUnit Unit, typename T>
Nz::Angle<Unit, T> operator*(T scale, const Nz::Angle<Unit, T>& angle)
{
return Nz::Angle<Unit, T>(scale * angle.value);
}
/*!
* \brief Division operator
* \return An angle corresponding to scale / angle
*
* \param scale Divisor
* \param angle Angle
*/
template<Nz::AngleUnit Unit, typename T>
Nz::Angle<Unit, T> operator/(T scale, const Nz::Angle<Unit, T>& angle)
{
return Nz::Angle<Unit, T>(scale / angle.value);
}
/*!
* \brief Output operator
* \return The stream
*
* \param out The stream
* \param box The box to output
*/
template<Nz::AngleUnit Unit, typename T>
std::ostream& operator<<(std::ostream& out, const Nz::Angle<Unit, T>& angle)
{
return Nz::Detail::AngleUtils<Unit>::ToString(out, angle.value);
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -63,7 +63,6 @@ namespace Nz
Box& Set(T Width, T Height, T Depth);
Box& Set(T X, T Y, T Z, T Width, T Height, T Depth);
Box& Set(const T box[6]);
Box& Set(const Box& box);
Box& Set(const Rect<T>& rect);
Box& Set(const Vector3<T>& lengths);
Box& Set(const Vector3<T>& vec1, const Vector3<T>& vec2);

View File

@@ -585,21 +585,6 @@ 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)
{
std::memcpy(this, &box, sizeof(Box));
return *this;
}
/*!
* \brief Sets the components of the box with components from a Rect
* \return A reference to this box

View File

@@ -9,6 +9,12 @@
namespace Nz
{
enum class AngleUnit
{
Degree,
Radian
};
enum BoxCorner
{
BoxCorner_FarLeftBottom,

View File

@@ -8,6 +8,7 @@
#define NAZARA_EULERANGLES_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Angle.hpp>
#include <Nazara/Math/Quaternion.hpp>
#include <Nazara/Math/Vector3.hpp>
@@ -22,6 +23,7 @@ namespace Nz
EulerAngles() = default;
EulerAngles(T P, T Y, T R);
EulerAngles(const T angles[3]);
template<AngleUnit Unit> EulerAngles(const Angle<Unit, T>& angle);
//EulerAngles(const Matrix3<T>& mat);
EulerAngles(const Quaternion<T>& quat);
template<typename U> explicit EulerAngles(const EulerAngles<U>& angles);
@@ -34,7 +36,7 @@ namespace Nz
EulerAngles& Set(T P, T Y, T R);
EulerAngles& Set(const T angles[3]);
EulerAngles& Set(const EulerAngles<T>& angles);
template<AngleUnit Unit> EulerAngles& Set(const Angle<Unit, T>& angles);
//EulerAngles& Set(const Matrix3<T>& mat);
EulerAngles& Set(const Quaternion<T>& quat);
template<typename U> EulerAngles& Set(const EulerAngles<U>& angles);

View File

@@ -50,12 +50,23 @@ namespace Nz
Set(angles);
}
/*!
* \brief Constructs a EulerAngles object from an angle
*
* \param angle Angle representing a 2D rotation
*/
template<typename T>
template<AngleUnit Unit>
EulerAngles<T>::EulerAngles(const Angle<Unit, T>& angle)
{
Set(angle);
}
/*!
* \brief Constructs a EulerAngles object from a quaternion
*
* \param quat Quaternion representing a rotation of space
*/
template<typename T>
EulerAngles<T>::EulerAngles(const Quaternion<T>& quat)
{
@@ -142,19 +153,20 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the euler angle from another euler angle
* \brief Sets the components of the euler angle from a 2D rotation specified by an Angle
* \return A reference to this euler angle
*
* \param angles The other euler angle
* \param angle 2D angle
*
* \see Angle
*/
template<typename T>
EulerAngles<T>& EulerAngles<T>::Set(const EulerAngles& angles)
template<AngleUnit Unit>
EulerAngles<T>& EulerAngles<T>::Set(const Angle<Unit, T>& angle)
{
std::memcpy(this, &angles, sizeof(EulerAngles));
return *this;
return Set(angle.ToEulerAngles());
}
/*!
@@ -394,3 +406,4 @@ std::ostream& operator<<(std::ostream& out, const Nz::EulerAngles<T>& angles)
#undef F
#include <Nazara/Core/DebugOff.hpp>
#include "EulerAngles.hpp"

View File

@@ -52,7 +52,6 @@ namespace Nz
Frustum& operator=(const Frustum& other) = default;
Frustum& Set(const Frustum& frustum);
template<typename U> Frustum& Set(const Frustum<U>& frustum);
String ToString() const;

View File

@@ -623,21 +623,6 @@ namespace Nz
return (c == 6) ? IntersectionSide_Inside : IntersectionSide_Intersecting;
}
/*!
* \brief Sets the components of the frustum from another frustum
* \return A reference to this frustum
*
* \param frustum The other frustum
*/
template<typename T>
Frustum<T>& Frustum<T>::Set(const Frustum& frustum)
{
std::memcpy(this, &frustum, sizeof(Frustum));
return *this;
}
/*!
* \brief Sets the components of the frustum from another type of Frustum
* \return A reference to this frustum

View File

@@ -44,6 +44,8 @@ namespace Nz
Matrix4& Concatenate(const Matrix4& matrix);
Matrix4& ConcatenateAffine(const Matrix4& matrix);
void Decompose(Vector3<T>& translation, Quaternion<T>& rotation, Vector3<T>& scale);
Vector4<T> GetColumn(unsigned int column) const;
T GetDeterminant() const;
T GetDeterminantAffine() const;
@@ -82,9 +84,7 @@ namespace Nz
T r21, T r22, T r23, T r24,
T r31, T r32, T r33, T r34,
T r41, T r42, T r43, T r44);
Matrix4& Set(const T matrix[16]);
//Matrix4(const Matrix3<T>& matrix);
Matrix4& Set(const Matrix4& matrix);
template<typename U> Matrix4& Set(const Matrix4<U>& matrix);
Matrix4& SetRotation(const Quaternion<T>& rotation);
Matrix4& SetScale(const Vector3<T>& scale);

View File

@@ -55,9 +55,12 @@ namespace Nz
*/
template<typename T>
Matrix4<T>::Matrix4(const T matrix[16])
Matrix4<T>::Matrix4(const T matrix[16]) :
Matrix4(matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3],
matrix[ 4], matrix[ 5], matrix[ 6], matrix[ 7],
matrix[ 8], matrix[ 9], matrix[10], matrix[11],
matrix[12], matrix[13], matrix[14], matrix[15])
{
Set(matrix);
}
/*!
@@ -217,6 +220,25 @@ namespace Nz
F(1.0));
}
template<typename T>
void Matrix4<T>::Decompose(Vector3<T>& translation, Quaternion<T>& rotation, Vector3<T>& scale)
{
Matrix4f localMat(*this);
translation = localMat.GetTranslation();
scale = localMat.GetScale();
Vector3<T> invScale;
invScale.x = T(1) / scale.x;
invScale.y = T(1) / scale.y;
invScale.z = T(1) / scale.z;
localMat.ApplyScale(invScale);
rotation = localMat.GetRotation();
}
/*!
* \brief Gets the ith column of the matrix
* \return Vector4 which is the transformation of this axis
@@ -448,7 +470,7 @@ namespace Nz
for (unsigned int i = 0; i < 16; ++i)
inv[i] *= invDet;
dest->Set(inv);
*dest = inv;
return true;
}
else
@@ -550,7 +572,7 @@ namespace Nz
inv[15] = F(1.0);
dest->Set(inv);
*dest = inv;
return true;
}
else
@@ -1097,37 +1119,6 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the matrix from an array of sixteen elements
* \return A reference to this matrix
*
* \param matrix[16] Matrix components
*/
template<typename T>
Matrix4<T>& Matrix4<T>::Set(const T matrix[16])
{
// Here we are confident of the continuity of memory elements
std::memcpy(&m11, matrix, 16 * sizeof(T));
return *this;
}
/*!
* \brief Sets the components of the matrix from another matrix
* \return A reference to this matrix
*
* \param matrix The other matrix
*/
template<typename T>
Matrix4<T>& Matrix4<T>::Set(const Matrix4& matrix)
{
std::memcpy(this, &matrix, sizeof(Matrix4));
return *this;
}
/*!
* \brief Sets the components of the matrix from another type of Matrix4
* \return A reference to this matrix

View File

@@ -36,7 +36,6 @@ namespace Nz
OrientedBox& Set(T X, T Y, T Z, T Width, T Height, T Depth);
OrientedBox& Set(const Box<T>& box);
OrientedBox& Set(const OrientedBox& orientedBox);
OrientedBox& Set(const Vector3<T>& vec1, const Vector3<T>& vec2);
template<typename U> OrientedBox& Set(const OrientedBox<U>& orientedBox);

View File

@@ -164,21 +164,6 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the oriented box with components from another
* \return A reference to this oriented box
*
* \param orientedBox The other OrientedBox
*/
template<typename T>
OrientedBox<T>& OrientedBox<T>::Set(const OrientedBox& orientedBox)
{
std::memcpy(this, &orientedBox, sizeof(OrientedBox));
return *this;
}
/*!
* \brief Sets a OrientedBox 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

View File

@@ -37,7 +37,6 @@ namespace Nz
Plane& Set(T normalX, T normalY, T normalZ, T Distance);
Plane& Set(const T plane[4]);
Plane& Set(const Plane& plane);
Plane& Set(const Vector3<T>& Normal, T Distance);
Plane& Set(const Vector3<T>& Normal, const Vector3<T>& point);
Plane& Set(const Vector3<T>& point1, const Vector3<T>& point2, const Vector3<T>& point3);

View File

@@ -212,21 +212,6 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the plane from another plane
* \return A reference to this plane
*
* \param plane The other plane
*/
template<typename T>
Plane<T>& Plane<T>::Set(const Plane& plane)
{
std::memcpy(this, &plane, sizeof(Plane));
return *this;
}
/*!
* \brief Sets the components of the plane from a normal and a distance
* \return A reference to this plane

View File

@@ -8,6 +8,7 @@
#define NAZARA_QUATERNION_HPP
#include <Nazara/Core/String.hpp>
#include <Nazara/Math/Angle.hpp>
namespace Nz
{
@@ -21,6 +22,7 @@ namespace Nz
public:
Quaternion() = default;
Quaternion(T W, T X, T Y, T Z);
template<AngleUnit Unit> Quaternion(const Angle<Unit, T>& angle);
Quaternion(const EulerAngles<T>& angles);
Quaternion(T angle, const Vector3<T>& axis);
Quaternion(const T quat[4]);
@@ -49,11 +51,11 @@ namespace Nz
Quaternion& Normalize(T* length = nullptr);
Quaternion& Set(T W, T X, T Y, T Z);
template<AngleUnit Unit> Quaternion& Set(const Angle<Unit, T>& angle);
Quaternion& Set(const EulerAngles<T>& angles);
Quaternion& Set(T angle, const Vector3<T>& normalizedAxis);
Quaternion& Set(const T quat[4]);
//Quaternion& Set(const Matrix3<T>& mat);
Quaternion& Set(const Quaternion& quat);
template<typename U> Quaternion& Set(const Quaternion<U>& quat);
T SquaredMagnitude() const;

View File

@@ -39,6 +39,18 @@ namespace Nz
Set(W, X, Y, Z);
}
/*!
* \brief Constructs a Quaternion object from an angle
*
* \param angle Angle representing a 2D rotation
*/
template<typename T>
template<AngleUnit Unit>
Quaternion<T>::Quaternion(const Angle<Unit, T>& angle)
{
Set(angle);
}
/*!
* \brief Constructs a Quaternion object from a EulerAngles
*
@@ -46,7 +58,6 @@ namespace Nz
*
* \see EulerAngles
*/
template<typename T>
Quaternion<T>::Quaternion(const EulerAngles<T>& angles)
{
@@ -343,6 +354,21 @@ namespace Nz
return *this;
}
/*!
* \brief Sets this quaternion from a 2D rotation specified by an Angle
* \return A reference to this quaternion
*
* \param angle 2D angle
*
* \see Angle
*/
template<typename T>
template<AngleUnit Unit>
Quaternion<T>& Quaternion<T>::Set(const Angle<Unit, T>& angle)
{
return Set(angle.ToQuaternion());
}
/*!
* \brief Sets this quaternion from rotation specified by Euler angle
* \return A reference to this quaternion
@@ -351,7 +377,6 @@ namespace Nz
*
* \see EulerAngles
*/
template<typename T>
Quaternion<T>& Quaternion<T>::Set(const EulerAngles<T>& angles)
{
@@ -405,21 +430,6 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the quaternion from another quaternion
* \return A reference to this quaternion
*
* \param quat The other quaternion
*/
template<typename T>
Quaternion<T>& Quaternion<T>::Set(const Quaternion& quat)
{
std::memcpy(this, &quat, sizeof(Quaternion));
return *this;
}
/*!
* \brief Sets the components of the quaternion from another type of Quaternion
* \return A reference to this quaternion
@@ -886,3 +896,4 @@ std::ostream& operator<<(std::ostream& out, const Nz::Quaternion<T>& quat)
#undef F
#include <Nazara/Core/DebugOff.hpp>
#include "Quaternion.hpp"

View File

@@ -54,7 +54,6 @@ namespace Nz
Ray& Set(const Vector3<T>& origin, const Vector3<T>& direction);
Ray& Set(const T origin[3], const T direction[3]);
Ray& Set(const Plane<T>& planeOne, const Plane<T>& planeTwo);
Ray& Set(const Ray& ray);
template<typename U> Ray& Set(const Ray<U>& ray);
template<typename U> Ray& Set(const Vector3<U>& origin, const Vector3<U>& direction);

View File

@@ -593,21 +593,6 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the ray with components from another
* \return A reference to this ray
*
* \param ray The other ray
*/
template<typename T>
Ray<T>& Ray<T>::Set(const Ray& ray)
{
std::memcpy(this, &ray, sizeof(Ray));
return *this;
}
/*!
* \brief Sets the components of the ray from another type of Ray
* \return A reference to this ray

View File

@@ -55,7 +55,6 @@ namespace Nz
Rect& Set(T Width, T Height);
Rect& Set(T X, T Y, T Width, T Height);
Rect& Set(const T rect[4]);
Rect& Set(const Rect<T>& rect);
Rect& Set(const Vector2<T>& lengths);
Rect& Set(const Vector2<T>& vec1, const Vector2<T>& vec2);
template<typename U> Rect& Set(const Rect<U>& rect);
@@ -92,7 +91,9 @@ namespace Nz
using Recti = Rect<int>;
using Rectui = Rect<unsigned int>;
using Recti32 = Rect<Int32>;
using Recti64 = Rect<Int64>;
using Rectui32 = Rect<UInt32>;
using Rectui64 = Rect<UInt64>;
template<typename T> bool Serialize(SerializationContext& context, const Rect<T>& rect, TypeTag<Rect<T>>);
template<typename T> bool Unserialize(SerializationContext& context, Rect<T>* rect, TypeTag<Rect<T>>);

View File

@@ -475,21 +475,6 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the rectangle with components from another
* \return A reference to this rectangle
*
* \param rect The other Rect
*/
template<typename T>
Rect<T>& Rect<T>::Set(const Rect<T>& rect)
{
std::memcpy(this, &rect, sizeof(Rect));
return *this;
}
/*!
* \brief Sets the components of the rectange from a vector representing width and height
* \return A reference to this rectangle

View File

@@ -53,7 +53,6 @@ namespace Nz
Sphere& Set(T X, T Y, T Z, T Radius);
//Sphere& Set(const Circle<T>& rect);
Sphere& Set(const Sphere& sphere);
Sphere& Set(const Vector3<T>& center, T Radius);
Sphere& Set(const T sphere[4]);
template<typename U> Sphere& Set(const Sphere<U>& sphere);

View File

@@ -397,21 +397,6 @@ namespace Nz
}
*/
/*!
* \brief Sets the components of the sphere with center and radius from another
* \return A reference to this sphere
*
* \param sphere The other sphere
*/
template<typename T>
Sphere<T>& Sphere<T>::Set(const Sphere& sphere)
{
std::memcpy(this, &sphere, sizeof(Sphere));
return *this;
}
/*!
* \brief Sets the components of the sphere from an array of four elements
* \return A reference to this sphere

View File

@@ -33,8 +33,8 @@ namespace Nz
T AbsDotProduct(const Vector2& vec) const;
T AngleBetween(const Vector2& vec) const;
T Distance(const Vector2& vec) const;
float Distancef(const Vector2& vec) const;
template<typename U = T>
U Distance(const Vector2& vec) const;
T DotProduct(const Vector2& vec) const;
T GetLength() const;
@@ -55,7 +55,6 @@ namespace Nz
Vector2& Set(T X, T Y);
Vector2& Set(T scale);
Vector2& Set(const T vec[2]);
Vector2& Set(const Vector2& vec);
Vector2& Set(const Vector3<T>& vec);
Vector2& Set(const Vector4<T>& vec);
template<typename U> Vector2& Set(const Vector2<U>& vec);
@@ -92,6 +91,7 @@ namespace Nz
bool operator>(const Vector2& vec) const;
bool operator>=(const Vector2& vec) const;
template<typename U = T> static U Distance(const Vector2& vec1, const Vector2& vec2);
static T DotProduct(const Vector2& vec1, const Vector2& vec2);
static Vector2 Lerp(const Vector2& from, const Vector2& to, T interpolation);
static Vector2 Normalize(const Vector2& vec);
@@ -108,7 +108,9 @@ namespace Nz
using Vector2i = Vector2<int>;
using Vector2ui = Vector2<unsigned int>;
using Vector2i32 = Vector2<Int32>;
using Vector2i64 = Vector2<Int64>;
using Vector2ui32 = Vector2<UInt32>;
using Vector2ui64 = Vector2<UInt64>;
template<typename T> bool Serialize(SerializationContext& context, const Vector2<T>& vector, TypeTag<Vector2<T>>);
template<typename T> bool Unserialize(SerializationContext& context, Vector2<T>* vector, TypeTag<Vector2<T>>);

View File

@@ -124,22 +124,10 @@ namespace Nz
*/
template<typename T>
T Vector2<T>::Distance(const Vector2& vec) const
template<typename U>
U Vector2<T>::Distance(const Vector2& vec) const
{
return std::sqrt(SquaredDistance(vec));
}
/*!
* \brief Calculates the distance between two vectors
* \return The metric distance in float between two vectors with euclidean norm
*
* \param vec The other vector to measure the distance with
*/
template<typename T>
float Vector2<T>::Distancef(const Vector2& vec) const
{
return std::sqrt(static_cast<float>(SquaredDistance(vec)));
return static_cast<U>(std::sqrt(SquaredDistance(vec)));
}
/*!
@@ -379,22 +367,8 @@ namespace Nz
template<typename T>
Vector2<T>& Vector2<T>::Set(const T vec[2])
{
std::memcpy(&x, vec, 2*sizeof(T));
return *this;
}
/*!
* \brief Sets the components of the vector from another vector
* \return A reference to this vector
*
* \param vec The other vector
*/
template<typename T>
Vector2<T>& Vector2<T>::Set(const Vector2& vec)
{
std::memcpy(this, &vec, sizeof(Vector2));
x = vec[0];
y = vec[1];
return *this;
}
@@ -835,6 +809,24 @@ namespace Nz
return !operator<(vec);
}
/*!
* \brief Measure the distance between two points
* Shorthand for vec1.Distance(vec2)
*
* param vec1 the first point
* param vec2 the second point
*
* \return The distance between the two vectors
*
* \see SquaredDistance
*/
template<typename T>
template<typename U>
U Vector2<T>::Distance(const Vector2& vec1, const Vector2& vec2)
{
return vec1.Distance<U>(vec2);
}
/*!
* \brief Calculates the dot (scalar) product with two vectors
* \return The value of the dot product

View File

@@ -36,8 +36,8 @@ namespace Nz
Vector3 CrossProduct(const Vector3& vec) const;
T Distance(const Vector3& vec) const;
float Distancef(const Vector3& vec) const;
template<typename U = T>
U Distance(const Vector3& vec) const;
T DotProduct(const Vector3& vec) const;
T GetLength() const;
@@ -67,7 +67,6 @@ namespace Nz
Vector3& Set(T scale);
Vector3& Set(const T vec[3]);
Vector3& Set(const Vector2<T>& vec, T Z = 0.0);
Vector3& Set(const Vector3<T>& vec);
template<typename U> Vector3& Set(const Vector3<U>& vec);
Vector3& Set(const Vector4<T>& vec);
@@ -106,8 +105,7 @@ namespace Nz
static Vector3 Backward();
static Vector3 CrossProduct(const Vector3& vec1, const Vector3& vec2);
static T DotProduct(const Vector3& vec1, const Vector3& vec2);
static T Distance(const Vector3& vec1, const Vector3& vec2);
static float Distancef(const Vector3& vec1, const Vector3& vec2);
template<typename U = T> static U Distance(const Vector3& vec1, const Vector3& vec2);
static Vector3 Down();
static Vector3 Forward();
static Vector3 Left();
@@ -130,7 +128,9 @@ namespace Nz
using Vector3i = Vector3<int>;
using Vector3ui = Vector3<unsigned int>;
using Vector3i32 = Vector3<Int32>;
using Vector3i64 = Vector3<Int64>;
using Vector3ui32 = Vector3<UInt32>;
using Vector3ui64 = Vector3<UInt64>;
template<typename T> bool Serialize(SerializationContext& context, const Vector3<T>& vector, TypeTag<Vector3<T>>);
template<typename T> bool Unserialize(SerializationContext& context, Vector3<T>* vector, TypeTag<Vector3<T>>);

View File

@@ -162,21 +162,10 @@ namespace Nz
* \see SquaredDistance
*/
template<typename T>
T Vector3<T>::Distance(const Vector3& vec) const
template<typename U>
U Vector3<T>::Distance(const Vector3& vec) const
{
return std::sqrt(SquaredDistance(vec));
}
/*!
* \brief Calculates the distance between two vectors
* \return The metric distance in float between two vectors with euclidean norm
*
* \param vec The other vector to measure the distance with
*/
template<typename T>
float Vector3<T>::Distancef(const Vector3& vec) const
{
return std::sqrt(static_cast<float>(SquaredDistance(vec)));
return static_cast<U>(std::sqrt(SquaredDistance(vec)));
}
/*!
@@ -534,20 +523,6 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the vector from another vector
* \return A reference to this vector
*
* \param vec The other vector
*/
template<typename T>
Vector3<T>& Vector3<T>::Set(const Vector3& vec)
{
std::memcpy(this, &vec, sizeof(Vector3));
return *this;
}
/*!
* \brief Sets the components of the vector from another type of Vector3
* \return A reference to this vector
@@ -1014,26 +989,10 @@ namespace Nz
* \see SquaredDistance
*/
template<typename T>
T Vector3<T>::Distance(const Vector3& vec1, const Vector3& vec2)
template<typename U>
U Vector3<T>::Distance(const Vector3& vec1, const Vector3& vec2)
{
return vec1.Distance(vec2);
}
/*!
* \brief Measure the distance between two points as a float
* Shorthand for vec1.Distancef(vec2)
*
* param vec1 the first point
* param vec2 the second point
*
* \return The distance between the two vectors as a float
*
* \see SquaredDistancef
*/
template<typename T>
float Vector3<T>::Distancef(const Vector3& vec1, const Vector3& vec2)
{
return vec1.Distancef(vec2);
return vec1.Distance<U>(vec2);
}
/*!

View File

@@ -57,7 +57,6 @@ namespace Nz
Vector4& Set(const T vec[4]);
Vector4& Set(const Vector2<T>& vec, T Z = 0.0, T W = 1.0);
Vector4& Set(const Vector3<T>& vec, T W = 1.0);
Vector4& Set(const Vector4<T>& vec);
template<typename U> Vector4& Set(const Vector4<U>& vec);
String ToString() const;
@@ -106,7 +105,9 @@ namespace Nz
using Vector4i = Vector4<int>;
using Vector4ui = Vector4<unsigned int>;
using Vector4i32 = Vector4<Int32>;
using Vector4i64 = Vector4<Int64>;
using Vector4ui32 = Vector4<UInt32>;
using Vector4ui64 = Vector4<UInt64>;
template<typename T> bool Serialize(SerializationContext& context, const Vector4<T>& vector, TypeTag<Vector4<T>>);
template<typename T> bool Unserialize(SerializationContext& context, Vector4<T>* vector, TypeTag<Vector4<T>>);

View File

@@ -417,7 +417,10 @@ namespace Nz
template<typename T>
Vector4<T>& Vector4<T>::Set(const T vec[4])
{
std::memcpy(&x, vec, 4*sizeof(T));
x = vec[0];
y = vec[1];
z = vec[2];
w = vec[3];
return *this;
}
@@ -459,21 +462,6 @@ namespace Nz
return *this;
}
/*!
* \brief Sets the components of the vector from another vector
* \return A reference to this vector
*
* \param vec The other vector
*/
template<typename T>
Vector4<T>& Vector4<T>::Set(const Vector4& vec)
{
std::memcpy(this, &vec, sizeof(Vector4));
return *this;
}
/*!
* \brief Sets the components of the vector from another type of Vector4
* \return A reference to this vector
@@ -899,6 +887,21 @@ namespace Nz
return !operator<(vec);
}
/*!
* \brief Calculates the dot (scalar) product with two vectors
* \return The value of the dot product
*
* \param vec1 The first vector to calculate the dot product with
* \param vec2 The second vector to calculate the dot product with
*
* \see AbsDotProduct, DotProduct
*/
template<typename T>
T Vector4<T>::DotProduct(const Vector4& vec1, const Vector4& vec2)
{
return vec1.DotProduct(vec2);
}
/*!
* \brief Interpolates the vector to other one with a factor of interpolation
* \return A new vector which is the interpolation of two vectors
@@ -911,7 +914,6 @@ namespace Nz
*
* \see Lerp
*/
template<typename T>
Vector4<T> Vector4<T>::Lerp(const Vector4& from, const Vector4& to, T interpolation)
{

View File

@@ -44,7 +44,7 @@ namespace Nz
AbstractSocket& operator=(AbstractSocket&& abstractSocket);
// Signals:
NazaraSignal(OnStateChange, const AbstractSocket* /*socket*/, SocketState /*newState*/);
NazaraSignal(OnStateChanged, const AbstractSocket* /*socket*/, SocketState /*oldState*/, SocketState /*newState*/);
protected:
AbstractSocket(SocketType type);

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2017 Jérôme Leclercq
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
@@ -66,8 +66,9 @@ namespace Nz
{
if (m_state != newState)
{
OnStateChange(this, newState);
SocketState oldState = m_state;
m_state = newState;
OnStateChanged(this, oldState, newState);
}
}
}

View File

@@ -44,6 +44,8 @@ namespace Nz
ENetHost(ENetHost&&) = default;
inline ~ENetHost();
inline void AllowsIncomingConnections(bool allow = true);
void Broadcast(UInt8 channelId, ENetPacketFlags flags, NetPacket&& packet);
bool CheckEvents(ENetEvent* event);
@@ -56,10 +58,16 @@ namespace Nz
bool Create(const IpAddress& listenAddress, std::size_t peerCount, std::size_t channelCount, UInt32 incomingBandwidth, UInt32 outgoingBandwidth);
inline void Destroy();
inline bool DoesAllowIncomingConnections() const;
void Flush();
inline Nz::IpAddress GetBoundAddress() const;
inline IpAddress GetBoundAddress() const;
inline UInt32 GetServiceTime() const;
inline UInt32 GetTotalReceivedPackets() const;
inline UInt64 GetTotalReceivedData() const;
inline UInt64 GetTotalSentData() const;
inline UInt32 GetTotalSentPackets() const;
int Service(ENetEvent* event, UInt32 timeout);

View File

@@ -2,6 +2,7 @@
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Network/ENetHost.hpp>
#include <utility>
#include <Nazara/Network/Debug.hpp>
@@ -19,6 +20,13 @@ namespace Nz
Destroy();
}
inline void ENetHost::AllowsIncomingConnections(bool allow)
{
NazaraAssert(m_address.IsValid() && !m_address.IsLoopback(), "Only server hosts can allow incoming connections");
m_allowsIncomingConnections = allow;
}
inline bool ENetHost::Create(NetProtocol protocol, UInt16 port, std::size_t peerCount, std::size_t channelCount)
{
NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");
@@ -53,6 +61,11 @@ namespace Nz
m_socket.Close();
}
inline bool ENetHost::DoesAllowIncomingConnections() const
{
return m_allowsIncomingConnections;
}
inline IpAddress ENetHost::GetBoundAddress() const
{
return m_address;
@@ -63,6 +76,26 @@ namespace Nz
return m_serviceTime;
}
inline UInt32 ENetHost::GetTotalReceivedPackets() const
{
return m_totalReceivedPackets;
}
inline UInt64 ENetHost::GetTotalReceivedData() const
{
return m_totalReceivedData;
}
inline UInt64 ENetHost::GetTotalSentData() const
{
return m_totalSentData;
}
inline UInt32 ENetHost::GetTotalSentPackets() const
{
return m_totalSentPackets;
}
inline void ENetHost::SetCompressor(std::unique_ptr<ENetCompressor>&& compressor)
{
m_compressor = std::move(compressor);

View File

@@ -56,6 +56,11 @@ namespace Nz
inline UInt16 GetPeerId() const;
inline UInt32 GetRoundTripTime() const;
inline ENetPeerState GetState() const;
inline UInt64 GetTotalByteReceived() const;
inline UInt64 GetTotalByteSent() const;
inline UInt32 GetTotalPacketReceived() const;
inline UInt32 GetTotalPacketLost() const;
inline UInt32 GetTotalPacketSent() const;
inline bool HasPendingCommands();
@@ -234,9 +239,12 @@ namespace Nz
UInt32 m_timeoutLimit;
UInt32 m_timeoutMaximum;
UInt32 m_timeoutMinimum;
UInt32 m_totalPacketReceived;
UInt32 m_totalPacketLost;
UInt32 m_totalPacketSent;
UInt32 m_windowSize;
UInt64 m_totalPacketLost;
UInt64 m_totalPacketSent;
UInt64 m_totalByteReceived;
UInt64 m_totalByteSent;
bool m_isSimulationEnabled;
};
}

View File

@@ -62,9 +62,34 @@ namespace Nz
return m_state;
}
inline UInt64 ENetPeer::GetTotalByteReceived() const
{
return m_totalByteReceived;
}
inline UInt64 ENetPeer::GetTotalByteSent() const
{
return m_totalByteSent;
}
inline UInt32 ENetPeer::GetTotalPacketReceived() const
{
return m_totalPacketReceived;
}
inline UInt32 ENetPeer::GetTotalPacketLost() const
{
return m_totalPacketLost;
}
inline UInt32 ENetPeer::GetTotalPacketSent() const
{
return m_totalPacketSent;
}
inline bool ENetPeer::HasPendingCommands()
{
return m_outgoingReliableCommands.empty() && m_outgoingUnreliableCommands.empty() && m_sentReliableCommands.empty();
return m_outgoingReliableCommands.empty() && m_outgoingUnreliableCommands.empty() && m_sentReliableCommands.empty() && m_sentUnreliableCommands.empty();
}
inline bool ENetPeer::IsConnected() const
@@ -94,3 +119,4 @@ namespace Nz
}
#include <Nazara/Network/DebugOff.hpp>
#include "ENetPeer.hpp"

View File

@@ -46,10 +46,10 @@ namespace Nz
NetPacket& operator=(const NetPacket&) = delete;
NetPacket& operator=(NetPacket&& packet);
static bool DecodeHeader(const void* data, UInt16* packetSize, UInt16* netCode);
static bool EncodeHeader(void* data, UInt16 packetSize, UInt16 netCode);
static bool DecodeHeader(const void* data, UInt32* packetSize, UInt16* netCode);
static bool EncodeHeader(void* data, UInt32 packetSize, UInt16 netCode);
static constexpr std::size_t HeaderSize = sizeof(UInt16) + sizeof(UInt16); //< PacketSize + NetCode
static constexpr std::size_t HeaderSize = sizeof(UInt32) + sizeof(UInt16); //< PacketSize + NetCode
private:
void OnEmptyStream() override;

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