Merge branch 'nazara-next' into vulkan
This commit is contained in:
@@ -14,9 +14,7 @@
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/MemoryView.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Core/Stream.hpp>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@@ -99,7 +97,7 @@ namespace Nz
|
||||
return m_format;
|
||||
}
|
||||
|
||||
Mutex& GetMutex() override
|
||||
std::mutex& GetMutex() override
|
||||
{
|
||||
return m_mutex;
|
||||
}
|
||||
@@ -114,11 +112,11 @@ namespace Nz
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
bool Open(const String& filePath, bool forceMono)
|
||||
bool Open(const std::filesystem::path& filePath, bool forceMono)
|
||||
{
|
||||
// Nous devons gérer nous-même le flux car il doit rester ouvert après le passage du loader
|
||||
// (les flux automatiquement ouverts par le ResourceLoader étant fermés après celui-ci)
|
||||
std::unique_ptr<File> file(new File);
|
||||
std::unique_ptr<File> file = std::make_unique<File>();
|
||||
if (!file->Open(filePath, OpenMode_ReadOnly))
|
||||
{
|
||||
NazaraError("Failed to open stream from file: " + Error::GetLastError());
|
||||
@@ -219,15 +217,15 @@ namespace Nz
|
||||
AudioFormat m_format;
|
||||
SNDFILE* m_handle;
|
||||
bool m_mixToMono;
|
||||
Mutex m_mutex;
|
||||
std::mutex m_mutex;
|
||||
UInt32 m_duration;
|
||||
UInt32 m_sampleRate;
|
||||
UInt64 m_sampleCount;
|
||||
};
|
||||
|
||||
bool IsSupported(const String& extension)
|
||||
bool IsSupported(const std::string& extension)
|
||||
{
|
||||
static std::set<String> supportedExtensions = {
|
||||
static std::set<std::string> supportedExtensions = {
|
||||
"aiff", "au", "avr", "caf", "flac", "htk", "ircam", "mat4", "mat5", "mpc2k",
|
||||
"nist","ogg", "pvf", "raw", "rf64", "sd2", "sds", "svx", "voc", "w64", "wav", "wve"
|
||||
};
|
||||
@@ -253,9 +251,9 @@ namespace Nz
|
||||
return Ternary_False;
|
||||
}
|
||||
|
||||
SoundStreamRef LoadSoundStreamFile(const String& filePath, const SoundStreamParams& parameters)
|
||||
SoundStreamRef LoadSoundStreamFile(const std::filesystem::path& filePath, const SoundStreamParams& parameters)
|
||||
{
|
||||
std::unique_ptr<sndfileStream> soundStream(new sndfileStream);
|
||||
std::unique_ptr<sndfileStream> soundStream = std::make_unique<sndfileStream>();
|
||||
if (!soundStream->Open(filePath, parameters.forceMono))
|
||||
{
|
||||
NazaraError("Failed to open sound stream");
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
#include <Nazara/Audio/Music.hpp>
|
||||
#include <Nazara/Audio/OpenAL.hpp>
|
||||
#include <Nazara/Audio/SoundStream.hpp>
|
||||
#include <Nazara/Core/LockGuard.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Core/Thread.hpp>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <Nazara/Audio/Debug.hpp>
|
||||
|
||||
@@ -29,9 +28,9 @@ namespace Nz
|
||||
ALenum audioFormat;
|
||||
std::atomic<UInt64> processedSamples;
|
||||
std::vector<Int16> chunkSamples;
|
||||
Mutex bufferLock;
|
||||
std::mutex bufferLock;
|
||||
SoundStreamRef stream;
|
||||
Thread thread;
|
||||
std::thread thread;
|
||||
UInt64 playingOffset;
|
||||
bool loop = false;
|
||||
bool streaming = false;
|
||||
@@ -142,7 +141,7 @@ namespace Nz
|
||||
NazaraAssert(m_impl, "Music not created");
|
||||
|
||||
// Prevent music thread from enqueing new buffers while we're getting the count
|
||||
Nz::LockGuard lock(m_impl->bufferLock);
|
||||
std::lock_guard<std::mutex> lock(m_impl->bufferLock);
|
||||
|
||||
ALint samples = 0;
|
||||
alGetSourcei(m_source, AL_SAMPLE_OFFSET, &samples);
|
||||
@@ -215,7 +214,7 @@ namespace Nz
|
||||
* \param filePath Path to the file
|
||||
* \param params Parameters for the music
|
||||
*/
|
||||
bool Music::OpenFromFile(const String& filePath, const SoundStreamParams& params)
|
||||
bool Music::OpenFromFile(const std::filesystem::path& filePath, const SoundStreamParams& params)
|
||||
{
|
||||
if (SoundStreamRef soundStream = SoundStream::OpenFromFile(filePath, params))
|
||||
return Create(soundStream);
|
||||
@@ -305,7 +304,7 @@ namespace Nz
|
||||
{
|
||||
// Starting streaming's thread
|
||||
m_impl->streaming = true;
|
||||
m_impl->thread = Thread(&Music::MusicThread, this);
|
||||
m_impl->thread = std::thread(&Music::MusicThread, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,30 +350,29 @@ namespace Nz
|
||||
{
|
||||
std::size_t sampleCount = m_impl->chunkSamples.size();
|
||||
std::size_t sampleRead = 0;
|
||||
|
||||
Nz::LockGuard lock(m_impl->stream->GetMutex());
|
||||
|
||||
m_impl->stream->Seek(m_impl->playingOffset);
|
||||
|
||||
// Fill the buffer by reading from the stream
|
||||
for (;;)
|
||||
{
|
||||
sampleRead += m_impl->stream->Read(&m_impl->chunkSamples[sampleRead], sampleCount - sampleRead);
|
||||
if (sampleRead < sampleCount && m_impl->loop)
|
||||
std::lock_guard<std::mutex> lock(m_impl->stream->GetMutex());
|
||||
|
||||
m_impl->stream->Seek(m_impl->playingOffset);
|
||||
|
||||
// Fill the buffer by reading from the stream
|
||||
for (;;)
|
||||
{
|
||||
// In case we read less than expected, assume we reached the end of the stream and seek back to the beginning
|
||||
m_impl->stream->Seek(0);
|
||||
continue;
|
||||
sampleRead += m_impl->stream->Read(&m_impl->chunkSamples[sampleRead], sampleCount - sampleRead);
|
||||
if (sampleRead < sampleCount && m_impl->loop)
|
||||
{
|
||||
// In case we read less than expected, assume we reached the end of the stream and seek back to the beginning
|
||||
m_impl->stream->Seek(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Either we read the size we wanted, either we're not looping
|
||||
break;
|
||||
}
|
||||
|
||||
// Either we read the size we wanted, either we're not looping
|
||||
break;
|
||||
m_impl->playingOffset = m_impl->stream->Tell();
|
||||
}
|
||||
|
||||
m_impl->playingOffset = m_impl->stream->Tell();
|
||||
|
||||
lock.Unlock();
|
||||
|
||||
// Update the buffer (send it to OpenAL) and queue it if we got any data
|
||||
if (sampleRead > 0)
|
||||
{
|
||||
@@ -410,31 +408,31 @@ namespace Nz
|
||||
break;
|
||||
}
|
||||
|
||||
Nz::LockGuard lock(m_impl->bufferLock);
|
||||
|
||||
// We treat read buffers
|
||||
ALint processedCount = 0;
|
||||
alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &processedCount);
|
||||
while (processedCount--)
|
||||
{
|
||||
ALuint buffer;
|
||||
alSourceUnqueueBuffers(m_source, 1, &buffer);
|
||||
std::lock_guard<std::mutex> lock(m_impl->bufferLock);
|
||||
|
||||
ALint bits, size;
|
||||
alGetBufferi(buffer, AL_BITS, &bits);
|
||||
alGetBufferi(buffer, AL_SIZE, &size);
|
||||
// We treat read buffers
|
||||
ALint processedCount = 0;
|
||||
alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &processedCount);
|
||||
while (processedCount--)
|
||||
{
|
||||
ALuint buffer;
|
||||
alSourceUnqueueBuffers(m_source, 1, &buffer);
|
||||
|
||||
if (bits != 0)
|
||||
m_impl->processedSamples += (8 * size) / bits;
|
||||
ALint bits, size;
|
||||
alGetBufferi(buffer, AL_BITS, &bits);
|
||||
alGetBufferi(buffer, AL_SIZE, &size);
|
||||
|
||||
if (FillAndQueueBuffer(buffer))
|
||||
break;
|
||||
if (bits != 0)
|
||||
m_impl->processedSamples += (8 * size) / bits;
|
||||
|
||||
if (FillAndQueueBuffer(buffer))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lock.Unlock();
|
||||
|
||||
// We go back to sleep
|
||||
Thread::Sleep(50);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
|
||||
// Stop playing of the sound (in the case where it has not been already done)
|
||||
@@ -456,7 +454,7 @@ namespace Nz
|
||||
if (m_impl->streaming)
|
||||
{
|
||||
m_impl->streaming = false;
|
||||
m_impl->thread.Join();
|
||||
m_impl->thread.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Nz
|
||||
std::size_t length;
|
||||
while ((length = std::strlen(deviceString)) > 0)
|
||||
{
|
||||
devices.push_back(String(deviceString, length));
|
||||
devices.emplace_back(deviceString, length);
|
||||
deviceString += length + 1;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace Nz
|
||||
bool succeeded = false;
|
||||
for (const char* path : libs)
|
||||
{
|
||||
String libPath(path);
|
||||
std::filesystem::path libPath(path);
|
||||
if (!s_library.Load(libPath))
|
||||
continue;
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace Nz
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraWarning(libPath + " loading failed: " + String(e.what()));
|
||||
NazaraWarning(libPath.generic_u8string() + " loading failed: " + std::string(e.what()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,12 +149,12 @@ namespace Nz
|
||||
*
|
||||
* \remark Produces a NazaraError if loading failed
|
||||
*/
|
||||
bool Sound::LoadFromFile(const String& filePath, const SoundBufferParams& params)
|
||||
bool Sound::LoadFromFile(const std::filesystem::path& filePath, const SoundBufferParams& params)
|
||||
{
|
||||
SoundBufferRef buffer = SoundBuffer::LoadFromFile(filePath, params);
|
||||
if (!buffer)
|
||||
{
|
||||
NazaraError("Failed to load buffer from file (" + filePath + ')');
|
||||
NazaraError("Failed to load buffer from file (" + filePath.generic_u8string() + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ namespace Nz
|
||||
* \param filePath Path to the file
|
||||
* \param params Parameters for the sound buffer
|
||||
*/
|
||||
SoundBufferRef SoundBuffer::LoadFromFile(const String& filePath, const SoundBufferParams& params)
|
||||
SoundBufferRef SoundBuffer::LoadFromFile(const std::filesystem::path& filePath, const SoundBufferParams& params)
|
||||
{
|
||||
return SoundBufferLoader::LoadFromFile(filePath, params);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Nz
|
||||
|
||||
SoundStream::~SoundStream() = default;
|
||||
|
||||
SoundStreamRef SoundStream::OpenFromFile(const String& filePath, const SoundStreamParams& params)
|
||||
SoundStreamRef SoundStream::OpenFromFile(const std::filesystem::path& filePath, const SoundStreamParams& params)
|
||||
{
|
||||
return SoundStreamLoader::LoadFromFile(filePath, params);
|
||||
}
|
||||
|
||||
@@ -12,12 +12,6 @@
|
||||
#error OS not handled
|
||||
#endif
|
||||
|
||||
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_CLOCK
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#else
|
||||
#include <Nazara/Core/ThreadSafetyOff.hpp>
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
@@ -78,8 +72,6 @@ namespace Nz
|
||||
*/
|
||||
UInt64 Clock::GetMicroseconds() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
UInt64 elapsedMicroseconds = m_elapsedTime;
|
||||
if (!m_paused)
|
||||
elapsedMicroseconds += (GetElapsedMicroseconds() - m_refTime);
|
||||
@@ -106,8 +98,6 @@ namespace Nz
|
||||
*/
|
||||
bool Clock::IsPaused() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_paused;
|
||||
}
|
||||
|
||||
@@ -121,8 +111,6 @@ namespace Nz
|
||||
*/
|
||||
void Clock::Pause()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (!m_paused)
|
||||
{
|
||||
m_elapsedTime += GetElapsedMicroseconds() - m_refTime;
|
||||
@@ -139,8 +127,6 @@ namespace Nz
|
||||
*/
|
||||
UInt64 Clock::Restart()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
Nz::UInt64 now = GetElapsedMicroseconds();
|
||||
|
||||
Nz::UInt64 elapsedTime = m_elapsedTime;
|
||||
@@ -164,8 +150,6 @@ namespace Nz
|
||||
*/
|
||||
void Clock::Unpause()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (m_paused)
|
||||
{
|
||||
m_refTime = GetElapsedMicroseconds();
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
// 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/ConditionVariable.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/ConditionVariableImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/ConditionVariableImpl.hpp>
|
||||
#else
|
||||
#error Condition variable has no implementation
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup core
|
||||
* \class Nz::ConditionVariable
|
||||
* \brief Core class that represents a condition variable
|
||||
*
|
||||
* The ConditionVariable class is a synchronization primitive that can be used to block a thread, or multiple threads at the same time, until another thread both modifies a shared variable (the condition), and notifies the ConditionVariable
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a ConditionVariable object by default
|
||||
*/
|
||||
|
||||
ConditionVariable::ConditionVariable()
|
||||
{
|
||||
m_impl = new ConditionVariableImpl;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object
|
||||
*/
|
||||
|
||||
ConditionVariable::~ConditionVariable()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sends a signal to one thread waiting on the condition
|
||||
*
|
||||
* If any threads are waiting on *this, calling Signal unblocks one of the waiting threads
|
||||
*
|
||||
* \see SignalAll
|
||||
*/
|
||||
|
||||
void ConditionVariable::Signal()
|
||||
{
|
||||
m_impl->Signal();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sends a signal to every threads waiting on the condition
|
||||
*
|
||||
* Unblocks all threads currently waiting for *this
|
||||
*
|
||||
* \see Signal
|
||||
*/
|
||||
|
||||
void ConditionVariable::SignalAll()
|
||||
{
|
||||
m_impl->SignalAll();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Makes the thread wait on the condition
|
||||
*
|
||||
* Wait causes the current thread to block until the condition variable is notified or a spurious wakeup occurs
|
||||
*
|
||||
* \param mutex Mutex for the condition
|
||||
*
|
||||
* \remark Produces a NazaraAssert if mutex is invalid
|
||||
*/
|
||||
|
||||
void ConditionVariable::Wait(Mutex* mutex)
|
||||
{
|
||||
NazaraAssert(mutex != nullptr, "Mutex must be valid");
|
||||
m_impl->Wait(mutex->m_impl);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Makes the thread wait on the condition for a certain amount of time
|
||||
*
|
||||
* Wait causes the current thread to block until the condition variable is notified, a specific time is reached, or a spurious wakeup occurs
|
||||
*
|
||||
* \param mutex Mutex for the condition
|
||||
* \param timeout Time before expiration of the waiting
|
||||
*
|
||||
* \remark Produces a NazaraAssert if mutex is invalid
|
||||
*/
|
||||
|
||||
bool ConditionVariable::Wait(Mutex* mutex, UInt32 timeout)
|
||||
{
|
||||
NazaraAssert(mutex != nullptr, "Mutex must be valid");
|
||||
return m_impl->Wait(mutex->m_impl, timeout);
|
||||
}
|
||||
}
|
||||
@@ -1,535 +0,0 @@
|
||||
// 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/Directory.hpp>
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/DirectoryImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/DirectoryImpl.hpp>
|
||||
#else
|
||||
#error OS not handled
|
||||
#endif
|
||||
|
||||
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_DIRECTORY
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#else
|
||||
#include <Nazara/Core/ThreadSafetyOff.hpp>
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
//FIXME: MinGW seems to dislike thread_local shared_ptr.. (using a std::string is a working hackfix)
|
||||
thread_local std::string currentPath(DirectoryImpl::GetCurrent().ToStdString());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup core
|
||||
* \class Nz::Directory
|
||||
* \brief Core class that represents a directory
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Directory object by default
|
||||
*/
|
||||
|
||||
Directory::Directory() :
|
||||
m_pattern('*'),
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Directory object with a path
|
||||
*
|
||||
* \param dirPath Path to the directory
|
||||
*/
|
||||
|
||||
Directory::Directory(const String& dirPath) :
|
||||
m_dirPath(dirPath),
|
||||
m_pattern('*'),
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls Close
|
||||
*
|
||||
* \see Close
|
||||
*/
|
||||
|
||||
Directory::~Directory()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Closes the directory
|
||||
*/
|
||||
|
||||
void Directory::Close()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the directory exists
|
||||
* \return true if directory exists
|
||||
*/
|
||||
|
||||
bool Directory::Exists() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (IsOpen())
|
||||
return true; // If directory is open, then it exists
|
||||
else
|
||||
return Exists(m_dirPath);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the path of the directory
|
||||
* \return Path of the directory
|
||||
*/
|
||||
|
||||
String Directory::GetPath() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_dirPath;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the pattern for the path of the directory
|
||||
* \return Pattern for the path of the directory
|
||||
*/
|
||||
|
||||
String Directory::GetPattern() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_pattern;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the result name of the directory
|
||||
* \return Resulting name
|
||||
*
|
||||
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
|
||||
*/
|
||||
|
||||
String Directory::GetResultName() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetResultName();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the result path of the directory
|
||||
* \return Resulting path
|
||||
*
|
||||
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
|
||||
*/
|
||||
|
||||
String Directory::GetResultPath() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_dirPath + NAZARA_DIRECTORY_SEPARATOR + m_impl->GetResultName();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the resulting size of the directory
|
||||
* \return Size of the directory
|
||||
*
|
||||
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
|
||||
*/
|
||||
|
||||
UInt64 Directory::GetResultSize() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetResultSize();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the directory is open
|
||||
* \return true if open
|
||||
*/
|
||||
|
||||
bool Directory::IsOpen() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the directory is result
|
||||
* \return true if result
|
||||
*
|
||||
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
|
||||
*/
|
||||
|
||||
bool Directory::IsResultDirectory() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->IsResultDirectory();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the next result in the directory
|
||||
* \return true if directory has a next result
|
||||
*
|
||||
* \param skipDots Skips the dots in the path
|
||||
*
|
||||
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
|
||||
*/
|
||||
|
||||
bool Directory::NextResult(bool skipDots)
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
String name;
|
||||
for (;;)
|
||||
{
|
||||
if (!m_impl->NextResult())
|
||||
return false;
|
||||
|
||||
name = m_impl->GetResultName();
|
||||
|
||||
if (skipDots && (name == '.' || name == ".."))
|
||||
continue;
|
||||
|
||||
if (name.Match(m_pattern))
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Opens the directory
|
||||
* \return true if opening is successful
|
||||
*/
|
||||
|
||||
bool Directory::Open()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
Close();
|
||||
|
||||
if (!Exists(m_dirPath))
|
||||
return false;
|
||||
|
||||
m_impl = new DirectoryImpl(this);
|
||||
if (!m_impl->Open(m_dirPath))
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the path of the directory
|
||||
*
|
||||
* \param dirPath Path of the directory
|
||||
*/
|
||||
|
||||
void Directory::SetPath(const String& dirPath)
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
Close();
|
||||
|
||||
m_dirPath = File::AbsolutePath(dirPath);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the pattern of the directory
|
||||
*
|
||||
* \param pattern Pattern of the directory
|
||||
*/
|
||||
|
||||
void Directory::SetPattern(const String& pattern)
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
m_pattern = pattern;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Copies the first directory to a new directory path
|
||||
* \return true if copy is successful
|
||||
*
|
||||
* \param sourcePath Path of the original directory
|
||||
* \param destPath Path of the copied directory
|
||||
*
|
||||
* \remark Produces a NazaraError if could not create destination directory
|
||||
* \remark Produces a NazaraError if could not open origin directory
|
||||
* \remark Produces a NazaraError if could not copy a file
|
||||
*/
|
||||
|
||||
bool Directory::Copy(const String& sourcePath, const String& destPath)
|
||||
{
|
||||
if (sourcePath.IsEmpty() || destPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
String dirPath(sourcePath);
|
||||
String dest(File::NormalizePath(destPath));
|
||||
|
||||
if (!Create(destPath, true))
|
||||
{
|
||||
NazaraError("Unable to create \"" + destPath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
Directory dir(dirPath);
|
||||
if (!dir.Open())
|
||||
{
|
||||
NazaraError("Unable to open \"" + destPath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
while (dir.NextResult(true))
|
||||
{
|
||||
if (dir.IsResultDirectory())
|
||||
{
|
||||
if (!Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName()))
|
||||
return false;
|
||||
}
|
||||
else if (!File::Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName()))
|
||||
{
|
||||
NazaraError("Failed to copy \"" + dir.GetResultPath() + "\" to \"" + dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName() + '"');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dir.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a directory from a path
|
||||
* \return true if creation is successful
|
||||
*
|
||||
* \param dirPath Path of the directory
|
||||
* \param recursive Creates subdirectories
|
||||
*/
|
||||
|
||||
bool Directory::Create(const String& dirPath, bool recursive)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
String path = File::NormalizePath(dirPath);
|
||||
std::size_t foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR);
|
||||
if (foundPos == String::npos)
|
||||
return false;
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
// Unlike to disk (Ex: "C:"), the network path is not considered as a directory (Ex: "\\Laptop")
|
||||
if (path.Match("\\\\*"))
|
||||
{
|
||||
foundPos = path.Find('\\', 2);
|
||||
if (foundPos == String::npos)
|
||||
return false;
|
||||
|
||||
foundPos = path.Find('\\', foundPos + 1);
|
||||
if (foundPos == String::npos)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (;;)
|
||||
{
|
||||
String p = path.SubString(0, foundPos);
|
||||
if (p.EndsWith(NAZARA_DIRECTORY_SEPARATOR))
|
||||
p = p.SubString(0, -2);
|
||||
|
||||
if (!p.IsEmpty())
|
||||
{
|
||||
if (!DirectoryImpl::Exists(p) && !DirectoryImpl::Create(p))
|
||||
return false;
|
||||
|
||||
if (foundPos == String::npos)
|
||||
break;
|
||||
}
|
||||
|
||||
foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR, foundPos + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return DirectoryImpl::Create(File::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the directory exists
|
||||
* \return true if directory exists
|
||||
*
|
||||
* \param dirPath Path of the directory
|
||||
*/
|
||||
|
||||
bool Directory::Exists(const String& dirPath)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return DirectoryImpl::Exists(File::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the current path of this directory
|
||||
* \return Current path
|
||||
*/
|
||||
|
||||
String Directory::GetCurrent()
|
||||
{
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets this current file relative to the engine
|
||||
* \return Path to this file
|
||||
*/
|
||||
|
||||
const char* Directory::GetCurrentFileRelativeToEngine(const char* currentFile)
|
||||
{
|
||||
///FIXME: Is this method in the right place ?
|
||||
const char* ptr = std::strstr(currentFile, "NazaraEngine/");
|
||||
if (!ptr)
|
||||
ptr = std::strstr(currentFile, "NazaraEngine\\");
|
||||
|
||||
if (!ptr)
|
||||
ptr = currentFile;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Removes the directory
|
||||
* \return true if remove is successful
|
||||
*
|
||||
* \param dirPath Path of the directory
|
||||
* \param emptyDirectory Remove recursively
|
||||
*/
|
||||
|
||||
bool Directory::Remove(const String& dirPath, bool emptyDirectory)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (emptyDirectory)
|
||||
{
|
||||
Directory dir(dirPath);
|
||||
if (!dir.Open())
|
||||
return DirectoryImpl::Remove(dirPath); // If we can't open the directory, we try to delete it
|
||||
|
||||
while (dir.NextResult(true))
|
||||
{
|
||||
if (dir.IsResultDirectory())
|
||||
{
|
||||
if (!Remove(dir.GetResultPath(), true))
|
||||
return false;
|
||||
}
|
||||
else if (!File::Delete(dir.GetResultPath()))
|
||||
{
|
||||
NazaraError(dir.GetResultPath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dir.Close();
|
||||
}
|
||||
|
||||
return DirectoryImpl::Remove(File::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the current directory
|
||||
* \return true if directory path exists
|
||||
*
|
||||
* \param dirPath Path of the directory
|
||||
*/
|
||||
|
||||
bool Directory::SetCurrent(const String& dirPath)
|
||||
{
|
||||
String path = File::AbsolutePath(dirPath);
|
||||
if (DirectoryImpl::Exists(path))
|
||||
{
|
||||
currentPath = path.ToStdString();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -15,12 +15,6 @@
|
||||
#error No implementation for this platform
|
||||
#endif
|
||||
|
||||
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_DYNLIB
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#else
|
||||
#include <Nazara/Core/ThreadSafetyOff.hpp>
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
@@ -31,35 +25,16 @@ namespace Nz
|
||||
* \brief Core class that represents a dynamic library loader
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a DynLib object by default
|
||||
*/
|
||||
|
||||
DynLib::DynLib() :
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object and calls Unload
|
||||
*
|
||||
* \see Unload
|
||||
*/
|
||||
|
||||
DynLib::~DynLib()
|
||||
{
|
||||
Unload();
|
||||
}
|
||||
DynLib::DynLib() = default;
|
||||
DynLib::DynLib(DynLib&&) noexcept = default;
|
||||
DynLib::~DynLib() = default;
|
||||
|
||||
/*!
|
||||
* \brief Gets the last error
|
||||
* \return Last error
|
||||
*/
|
||||
|
||||
String DynLib::GetLastError() const
|
||||
std::string DynLib::GetLastError() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
@@ -69,11 +44,8 @@ namespace Nz
|
||||
*
|
||||
* \remark Produces a NazaraError if library is not loaded with NAZARA_CORE_SAFE defined
|
||||
*/
|
||||
|
||||
DynLibFunc DynLib::GetSymbol(const String& symbol) const
|
||||
DynLibFunc DynLib::GetSymbol(const char* symbol) const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsLoaded())
|
||||
{
|
||||
@@ -89,7 +61,6 @@ namespace Nz
|
||||
* \brief Checks whether the library is loaded
|
||||
* \return true if loaded
|
||||
*/
|
||||
|
||||
bool DynLib::IsLoaded() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
@@ -103,38 +74,28 @@ namespace Nz
|
||||
*
|
||||
* \remark Produces a NazaraError if library is could not be loaded
|
||||
*/
|
||||
|
||||
bool DynLib::Load(const String& libraryPath)
|
||||
bool DynLib::Load(const std::filesystem::path& libraryPath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
Unload();
|
||||
|
||||
std::unique_ptr<DynLibImpl> impl(new DynLibImpl(this));
|
||||
auto impl = std::make_unique<DynLibImpl>(this);
|
||||
if (!impl->Load(libraryPath, &m_lastError))
|
||||
{
|
||||
NazaraError("Failed to load library: " + m_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl = impl.release();
|
||||
|
||||
m_impl = std::move(impl);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Unloads the library
|
||||
*/
|
||||
|
||||
void DynLib::Unload()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (IsLoaded())
|
||||
{
|
||||
m_impl->Unload();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
m_impl.reset();
|
||||
}
|
||||
|
||||
DynLib& DynLib::operator=(DynLib&&) noexcept = default;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Directory.hpp>
|
||||
#include <Nazara/Core/CallOnExit.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Nazara/Core/StringExt.hpp>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -82,25 +83,21 @@ namespace Nz
|
||||
* \param code Code of the error
|
||||
*/
|
||||
|
||||
String Error::GetLastSystemError(unsigned int code)
|
||||
std::string Error::GetLastSystemError(unsigned int code)
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
wchar_t* buffer = nullptr;
|
||||
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
code,
|
||||
0,
|
||||
reinterpret_cast<LPWSTR>(&buffer),
|
||||
0,
|
||||
nullptr);
|
||||
nullptr,
|
||||
code,
|
||||
0,
|
||||
reinterpret_cast<LPWSTR>(&buffer),
|
||||
0,
|
||||
nullptr);
|
||||
|
||||
String error(String::Unicode(buffer));
|
||||
LocalFree(buffer);
|
||||
|
||||
error.Trim(); // For an unknown reason, Windows put two-three line return after the message
|
||||
|
||||
return error;
|
||||
CallOnExit freeOnExit([buffer] { LocalFree(buffer); });
|
||||
return FromWideString(buffer);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
return std::strerror(code);
|
||||
#else
|
||||
@@ -166,7 +163,7 @@ namespace Nz
|
||||
|
||||
void Error::Trigger(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
|
||||
{
|
||||
file = Nz::Directory::GetCurrentFileRelativeToEngine(file);
|
||||
file = GetCurrentFileRelativeToEngine(file);
|
||||
|
||||
if (type == ErrorType_AssertFailed || (s_flags & ErrorFlag_Silent) == 0 || (s_flags & ErrorFlag_SilentDisabled) != 0)
|
||||
Log::WriteError(type, error, line, file, function);
|
||||
@@ -186,6 +183,17 @@ namespace Nz
|
||||
throw std::runtime_error(error.ToStdString());
|
||||
}
|
||||
|
||||
const char* Error::GetCurrentFileRelativeToEngine(const char* file)
|
||||
{
|
||||
if (const char* ptr = std::strstr(file, "NazaraEngine/"))
|
||||
return ptr;
|
||||
|
||||
if (const char* ptr = std::strstr(file, "NazaraEngine\\"))
|
||||
return ptr;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
UInt32 Error::s_flags = ErrorFlag_None;
|
||||
String Error::s_lastError;
|
||||
const char* Error::s_lastErrorFunction = "";
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/AbstractHash.hpp>
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#include <Nazara/Core/Directory.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
@@ -19,12 +18,6 @@
|
||||
#error OS not handled
|
||||
#endif
|
||||
|
||||
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_FILE
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#else
|
||||
#include <Nazara/Core/ThreadSafetyOff.hpp>
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
@@ -39,10 +32,7 @@ namespace Nz
|
||||
* \brief Constructs a File object by default
|
||||
*/
|
||||
|
||||
File::File() :
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
File::File() = default;
|
||||
|
||||
/*!
|
||||
* \brief Constructs a File object with a file path
|
||||
@@ -50,7 +40,7 @@ namespace Nz
|
||||
* \param filePath Path to the file
|
||||
*/
|
||||
|
||||
File::File(const String& filePath) :
|
||||
File::File(const std::filesystem::path& filePath) :
|
||||
File()
|
||||
{
|
||||
SetFile(filePath);
|
||||
@@ -63,7 +53,7 @@ namespace Nz
|
||||
* \param openMode Flag of the file
|
||||
*/
|
||||
|
||||
File::File(const String& filePath, OpenModeFlags openMode) :
|
||||
File::File(const std::filesystem::path& filePath, OpenModeFlags openMode) :
|
||||
File()
|
||||
{
|
||||
Open(filePath, openMode);
|
||||
@@ -75,6 +65,8 @@ namespace Nz
|
||||
* \see Close
|
||||
*/
|
||||
|
||||
File::File(File&& file) noexcept = default;
|
||||
|
||||
File::~File()
|
||||
{
|
||||
Close();
|
||||
@@ -82,14 +74,12 @@ namespace Nz
|
||||
|
||||
/*!
|
||||
* \brief Copies this file to a new file path
|
||||
* \return true if copy is successful
|
||||
*
|
||||
* \param newFilePath Path of the new file
|
||||
*/
|
||||
|
||||
bool File::Copy(const String& newFilePath)
|
||||
void File::Copy(const std::filesystem::path& newFilePath)
|
||||
{
|
||||
return Copy(m_filePath, newFilePath);
|
||||
std::filesystem::copy(m_filePath, newFilePath);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -98,13 +88,9 @@ namespace Nz
|
||||
|
||||
void File::Close()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
m_impl.reset();
|
||||
|
||||
m_openMode = OpenMode_NotOpen;
|
||||
}
|
||||
@@ -117,11 +103,9 @@ namespace Nz
|
||||
|
||||
bool File::Delete()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
Close();
|
||||
|
||||
return Delete(m_filePath);
|
||||
return std::filesystem::remove(m_filePath);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -133,8 +117,6 @@ namespace Nz
|
||||
|
||||
bool File::EndOfFile() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
@@ -167,24 +149,10 @@ namespace Nz
|
||||
|
||||
bool File::Exists() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (IsOpen())
|
||||
return true; // Le fichier est ouvert, donc il existe
|
||||
else
|
||||
return Exists(m_filePath);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the creation time of the file
|
||||
* \return Information about the creation time
|
||||
*/
|
||||
|
||||
time_t File::GetCreationTime() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return GetCreationTime(m_filePath);
|
||||
return std::filesystem::exists(m_filePath);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -196,8 +164,6 @@ namespace Nz
|
||||
|
||||
UInt64 File::GetCursorPos() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
NazaraAssert(IsOpen(), "File is not open");
|
||||
|
||||
return m_impl->GetCursorPos();
|
||||
@@ -207,72 +173,32 @@ namespace Nz
|
||||
* \brief Gets the directory of the file
|
||||
* \return Directory of the file
|
||||
*/
|
||||
|
||||
String File::GetDirectory() const
|
||||
std::filesystem::path File::GetDirectory() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_filePath.SubStringTo(NAZARA_DIRECTORY_SEPARATOR, -1, true, true);
|
||||
return m_filePath.parent_path();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the name of the file
|
||||
* \return Name of the file
|
||||
*/
|
||||
|
||||
String File::GetFileName() const
|
||||
std::filesystem::path File::GetFileName() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_filePath.SubStringFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the last time the file was accessed
|
||||
* \return Information about the last access time
|
||||
*/
|
||||
|
||||
time_t File::GetLastAccessTime() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return GetLastAccessTime(m_filePath);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the last time the file was written
|
||||
* \return Information about the last writing time
|
||||
*/
|
||||
|
||||
time_t File::GetLastWriteTime() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return GetLastWriteTime(m_filePath);
|
||||
return m_filePath.filename();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the path of the file
|
||||
* \return Path of the file
|
||||
*/
|
||||
|
||||
String File::GetPath() const
|
||||
std::filesystem::path File::GetPath() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the size of the file
|
||||
* \return Size of the file
|
||||
*/
|
||||
|
||||
UInt64 File::GetSize() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return GetSize(m_filePath);
|
||||
return std::filesystem::file_size(m_filePath);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -282,8 +208,6 @@ namespace Nz
|
||||
|
||||
bool File::IsOpen() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
@@ -298,26 +222,24 @@ namespace Nz
|
||||
|
||||
bool File::Open(OpenModeFlags openMode)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
Close();
|
||||
|
||||
if (m_filePath.IsEmpty())
|
||||
if (m_filePath.empty())
|
||||
return false;
|
||||
|
||||
if (openMode == OpenMode_NotOpen)
|
||||
return false;
|
||||
|
||||
std::unique_ptr<FileImpl> impl(new FileImpl(this));
|
||||
std::unique_ptr<FileImpl> impl = std::make_unique<FileImpl>(this);
|
||||
if (!impl->Open(m_filePath, openMode))
|
||||
{
|
||||
ErrorFlags flags(ErrorFlag_Silent); // Silent by default
|
||||
NazaraError("Failed to open \"" + m_filePath + "\": " + Error::GetLastSystemError());
|
||||
NazaraError("Failed to open \"" + m_filePath.generic_u8string() + "\": " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_openMode = openMode;
|
||||
m_impl = impl.release();
|
||||
m_impl = std::move(impl);
|
||||
|
||||
if (m_openMode & OpenMode_Text)
|
||||
m_streamOptions |= StreamOption_Text;
|
||||
@@ -337,38 +259,14 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if OS error to open a file
|
||||
*/
|
||||
|
||||
bool File::Open(const String& filePath, OpenModeFlags openMode)
|
||||
bool File::Open(const std::filesystem::path& filePath, OpenModeFlags openMode)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
Close();
|
||||
|
||||
SetFile(filePath);
|
||||
return Open(openMode);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Renames the file with a new name
|
||||
* \return true if rename is successful
|
||||
*/
|
||||
|
||||
bool File::Rename(const String& newFilePath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
bool open = IsOpen();
|
||||
Close();
|
||||
|
||||
bool success = Rename(m_filePath, newFilePath);
|
||||
if (success)
|
||||
m_filePath = NormalizePath(newFilePath);
|
||||
|
||||
if (open)
|
||||
Open();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the position of the cursor
|
||||
* \return true if cursor is successfully positioned
|
||||
@@ -381,8 +279,6 @@ namespace Nz
|
||||
|
||||
bool File::SetCursorPos(CursorPosition pos, Int64 offset)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
NazaraAssert(IsOpen(), "File is not open");
|
||||
|
||||
return m_impl->SetCursorPos(pos, offset);
|
||||
@@ -399,8 +295,6 @@ namespace Nz
|
||||
|
||||
bool File::SetCursorPos(UInt64 offset)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
NazaraAssert(IsOpen(), "File is not open");
|
||||
|
||||
return m_impl->SetCursorPos(CursorPosition_AtBegin, offset);
|
||||
@@ -413,29 +307,24 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if file path can not be open
|
||||
*/
|
||||
|
||||
bool File::SetFile(const String& filePath)
|
||||
bool File::SetFile(const std::filesystem::path& filePath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (IsOpen())
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
if (filePath.empty())
|
||||
return false;
|
||||
|
||||
std::unique_ptr<FileImpl> impl(new FileImpl(this));
|
||||
std::unique_ptr<FileImpl> impl = std::make_unique<FileImpl>(this);
|
||||
if (!impl->Open(filePath, m_openMode))
|
||||
{
|
||||
NazaraError("Failed to open new file; " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
|
||||
m_impl = impl.release();
|
||||
m_impl = std::move(impl);
|
||||
}
|
||||
|
||||
m_filePath = AbsolutePath(filePath);
|
||||
m_filePath = std::filesystem::absolute(filePath);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -450,317 +339,13 @@ namespace Nz
|
||||
*/
|
||||
bool File::SetSize(UInt64 size)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
NazaraAssert(IsOpen(), "File is not open");
|
||||
NazaraAssert(IsWritable(), "File is not writable");
|
||||
|
||||
return m_impl->SetSize(size);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the file path
|
||||
* \return A reference to this
|
||||
*
|
||||
* \remark Produces a NazaraError if file path can not be open
|
||||
*/
|
||||
|
||||
File& File::operator=(const String& filePath)
|
||||
{
|
||||
SetFile(filePath);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the absolute path of the file
|
||||
* \return Absolute path of the file
|
||||
*
|
||||
* \param filePath Path of the file
|
||||
*
|
||||
* \remark Produces a NazaraError if filePath is weird with NAZARA_PLATFORM_WINDOWS defined
|
||||
*/
|
||||
|
||||
String File::AbsolutePath(const String& filePath)
|
||||
{
|
||||
// We don't use OS functions because they only work for existing path
|
||||
String path = NormalizePath(filePath);
|
||||
if (path.IsEmpty())
|
||||
return String();
|
||||
|
||||
String base;
|
||||
unsigned int start;
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
if (path.Match("?:*"))
|
||||
start = 1;
|
||||
else if (path.Match("\\\\*"))
|
||||
{
|
||||
base = "\\\\";
|
||||
start = 2;
|
||||
}
|
||||
else if (path.StartsWith('\\')) // Special : '\' refering to root
|
||||
{
|
||||
String drive = Directory::GetCurrent().SubStringTo('\\');
|
||||
String end = path.SubString(1, -1);
|
||||
if (end.IsEmpty())
|
||||
path = drive;
|
||||
else
|
||||
path = drive + '\\' + end;
|
||||
|
||||
start = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Path unrecognized");
|
||||
return path;
|
||||
}
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
base = '/';
|
||||
start = 0;
|
||||
#else
|
||||
#error OS case not implemented
|
||||
#endif
|
||||
|
||||
static String upDir = NAZARA_DIRECTORY_SEPARATOR + String('.');
|
||||
|
||||
if (path.Find(upDir) == String::npos)
|
||||
return path;
|
||||
|
||||
std::vector<String> sep;
|
||||
if (path.Split(sep, NAZARA_DIRECTORY_SEPARATOR) <= 1)
|
||||
return path;
|
||||
|
||||
// We have the absolute path, but we need to clean it up
|
||||
for (unsigned int i = 0; i < sep.size(); ++i)
|
||||
{
|
||||
if (sep[i] == '.')
|
||||
sep.erase(sep.begin() + i--);
|
||||
else if (sep[i] == "..")
|
||||
{
|
||||
if (i > start) // If we are not in the protected area
|
||||
sep.erase(sep.begin() + i--);
|
||||
|
||||
sep.erase(sep.begin() + i--);
|
||||
}
|
||||
}
|
||||
|
||||
StringStream stream(base);
|
||||
for (unsigned int i = 0; i < sep.size(); ++i)
|
||||
{
|
||||
if (i != sep.size()-1)
|
||||
stream << sep[i] << NAZARA_DIRECTORY_SEPARATOR;
|
||||
else
|
||||
stream << sep[i];
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Copies the first file to a new file path
|
||||
* \return true if copy is successful
|
||||
*
|
||||
* \param sourcePath Path of the original file
|
||||
* \param targetPath Path of the copied file
|
||||
*/
|
||||
|
||||
bool File::Copy(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
if (sourcePath.IsEmpty() || targetPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return FileImpl::Copy(NormalizePath(sourcePath), NormalizePath(targetPath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Deletes the file
|
||||
* \return true if delete is successful
|
||||
*
|
||||
* \param filePath Path of the file
|
||||
*/
|
||||
|
||||
bool File::Delete(const String& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return FileImpl::Delete(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the file exists
|
||||
* \return true if file exists
|
||||
*
|
||||
* \param filePath Path of the file
|
||||
*/
|
||||
|
||||
bool File::Exists(const String& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return FileImpl::Exists(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the creation time of the file
|
||||
* \return Information about the creation time
|
||||
*
|
||||
* \param filePath Path of the file
|
||||
*/
|
||||
|
||||
time_t File::GetCreationTime(const String& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return 0;
|
||||
|
||||
return FileImpl::GetCreationTime(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the directory of the file
|
||||
* \return Directory of the file
|
||||
*
|
||||
* \param filePath Path of the file
|
||||
*/
|
||||
|
||||
String File::GetDirectory(const String& filePath)
|
||||
{
|
||||
return filePath.SubStringTo(NAZARA_DIRECTORY_SEPARATOR, -1, true, true);
|
||||
}
|
||||
/*!
|
||||
* \brief Gets the last time the file was accessed
|
||||
* \return Information about the last access time
|
||||
*
|
||||
* \param filePath Path of the file
|
||||
*/
|
||||
|
||||
time_t File::GetLastAccessTime(const String& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return 0;
|
||||
|
||||
return FileImpl::GetLastAccessTime(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the last time the file was written
|
||||
* \return Information about the last writing time
|
||||
*
|
||||
* \param filePath Path of the file
|
||||
*/
|
||||
|
||||
time_t File::GetLastWriteTime(const String& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return 0;
|
||||
|
||||
return FileImpl::GetLastWriteTime(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the size of the file
|
||||
* \return Size of the file
|
||||
*
|
||||
* \param filePath Path of the file
|
||||
*/
|
||||
|
||||
UInt64 File::GetSize(const String& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return 0;
|
||||
|
||||
return FileImpl::GetSize(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the file path is absolute
|
||||
* \return true if path is absolute
|
||||
*
|
||||
* \param filePath Path to test
|
||||
*/
|
||||
|
||||
bool File::IsAbsolute(const String& filePath)
|
||||
{
|
||||
String path(filePath.Trimmed());
|
||||
if (path.IsEmpty())
|
||||
return false;
|
||||
|
||||
path = NormalizeSeparators(path);
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
if (path.Match("?:*")) // Ex: C:\Hello
|
||||
return true;
|
||||
else if (path.Match("\\\\*")) // Ex: \\Laptop
|
||||
return true;
|
||||
else if (path.StartsWith('\\')) // Special : '\' referring to the root
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
return path.StartsWith('/');
|
||||
#else
|
||||
#error OS case not implemented
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Normalizes the file path
|
||||
* \return Path normalized (replacing '/' with '\\' on Windows, ...)
|
||||
*
|
||||
* \param filePath Path to normalize
|
||||
*/
|
||||
|
||||
String File::NormalizePath(const String& filePath)
|
||||
{
|
||||
String path = NormalizeSeparators(filePath.Trimmed());
|
||||
|
||||
if (!IsAbsolute(path))
|
||||
path = Directory::GetCurrent() + NAZARA_DIRECTORY_SEPARATOR + path;
|
||||
|
||||
while (path.EndsWith(NAZARA_DIRECTORY_SEPARATOR))
|
||||
path.Resize(-1);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Normalizes the path separator
|
||||
* \return Path normalized (replacing '/' with '\\' on Windows, ...)
|
||||
*
|
||||
* \param filePath Path to normalize
|
||||
*/
|
||||
|
||||
String File::NormalizeSeparators(const String& filePath)
|
||||
{
|
||||
String path(filePath);
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
path.Replace('/', '\\');
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
path.Replace('\\', '/');
|
||||
#else
|
||||
#error OS case not implemented
|
||||
#endif
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Renames the file with a new name
|
||||
* \return true if rename is successful
|
||||
*
|
||||
* \param sourcePath Path of the original file
|
||||
* \param targetPath Path of the renamed file
|
||||
*/
|
||||
|
||||
bool File::Rename(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
if (sourcePath.IsEmpty() || targetPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return FileImpl::Rename(NormalizePath(sourcePath), NormalizePath(targetPath));
|
||||
}
|
||||
File& File::operator=(File&& file) noexcept = default;
|
||||
|
||||
/*!
|
||||
* \brief Flushes the stream
|
||||
@@ -770,8 +355,6 @@ namespace Nz
|
||||
|
||||
void File::FlushStream()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
NazaraAssert(IsOpen(), "File is not open");
|
||||
|
||||
m_impl->Flush();
|
||||
@@ -789,8 +372,6 @@ namespace Nz
|
||||
|
||||
std::size_t File::ReadBlock(void* buffer, std::size_t size)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
NazaraAssert(IsOpen(), "File is not open");
|
||||
|
||||
if (size == 0)
|
||||
@@ -822,8 +403,6 @@ namespace Nz
|
||||
|
||||
std::size_t File::WriteBlock(const void* buffer, std::size_t size)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
NazaraAssert(IsOpen(), "File is not open");
|
||||
|
||||
if (size == 0)
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <array>
|
||||
#include <ctime>
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
@@ -25,7 +27,7 @@ namespace Nz
|
||||
*/
|
||||
|
||||
FileLogger::FileLogger(const String& logPath) :
|
||||
m_outputFile(logPath),
|
||||
m_outputPath(logPath.ToStdString()),
|
||||
m_forceStdOutput(false),
|
||||
m_stdReplicationEnabled(true),
|
||||
m_timeLoggingEnabled(true)
|
||||
@@ -107,9 +109,10 @@ namespace Nz
|
||||
m_forceStdOutput = false;
|
||||
});
|
||||
|
||||
if (!m_outputFile.IsOpen())
|
||||
if (!m_outputFile.is_open())
|
||||
{
|
||||
if (!m_outputFile.Open(OpenMode_Text | OpenMode_Truncate | OpenMode_WriteOnly))
|
||||
m_outputFile.open(m_outputPath, std::ios_base::trunc | std::ios_base::out);
|
||||
if (!m_outputFile.is_open())
|
||||
{
|
||||
NazaraError("Failed to open output file");
|
||||
return;
|
||||
@@ -117,7 +120,7 @@ namespace Nz
|
||||
}
|
||||
|
||||
// Apply some processing before writing
|
||||
StringStream stream;
|
||||
std::ostringstream stream;
|
||||
if (m_timeLoggingEnabled)
|
||||
{
|
||||
std::array<char, 24> buffer;
|
||||
@@ -130,7 +133,7 @@ namespace Nz
|
||||
|
||||
stream << string << '\n';
|
||||
|
||||
m_outputFile.Write(stream);
|
||||
m_outputFile << stream.str();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -148,6 +151,6 @@ namespace Nz
|
||||
void FileLogger::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
|
||||
{
|
||||
AbstractLogger::WriteError(type, error, line, file, function);
|
||||
m_outputFile.Flush();
|
||||
m_outputFile.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
// 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/Mutex.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/MutexImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/MutexImpl.hpp>
|
||||
#else
|
||||
#error Lack of implementation: Mutex
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup core
|
||||
* \class Nz::Mutex
|
||||
* \brief Core class that represents a binary semaphore, a mutex
|
||||
*
|
||||
* \remark The mutex is recursive, it means that a thread who owns the mutex can call the same function which needs the same mutex
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Mutex object by default
|
||||
*/
|
||||
|
||||
Mutex::Mutex()
|
||||
{
|
||||
m_impl = new MutexImpl;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object
|
||||
*/
|
||||
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Locks the mutex
|
||||
*
|
||||
* If another thread has already locked the mutex, a call to lock will block execution until the lock is acquired. A thread may call lock on a recursive mutex repeatedly. Ownership will only be released after the thread makes a matching number of calls to unlock
|
||||
*/
|
||||
|
||||
void Mutex::Lock()
|
||||
{
|
||||
NazaraAssert(m_impl, "Cannot lock a moved mutex");
|
||||
m_impl->Lock();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Tries to lock the mutex
|
||||
* \return true if the lock was acquired successfully
|
||||
*/
|
||||
|
||||
bool Mutex::TryLock()
|
||||
{
|
||||
NazaraAssert(m_impl, "Cannot lock a moved mutex");
|
||||
return m_impl->TryLock();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Unlocks the mutex
|
||||
*
|
||||
* Unlocks the mutex if its level of ownership is 1 (there was exactly one more call to Lock() than there were calls to Unlock() made by this thread), reduces the level of ownership by 1 otherwise
|
||||
*/
|
||||
|
||||
void Mutex::Unlock()
|
||||
{
|
||||
NazaraAssert(m_impl, "Cannot unlock a moved mutex");
|
||||
m_impl->Unlock();
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,8 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/PluginManager.hpp>
|
||||
#include <Nazara/Core/Directory.hpp>
|
||||
#include <Nazara/Core/DynLib.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <memory>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
@@ -17,7 +15,7 @@ namespace Nz
|
||||
using PluginLoad = int (*)();
|
||||
using PluginUnload = void (*)();
|
||||
|
||||
String s_pluginFiles[] =
|
||||
std::filesystem::path s_pluginFiles[] =
|
||||
{
|
||||
"PluginAssimp", // Plugin_Assimp
|
||||
};
|
||||
@@ -37,7 +35,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if not initialized
|
||||
*/
|
||||
|
||||
void PluginManager::AddDirectory(const String& directoryPath)
|
||||
void PluginManager::AddDirectory(const std::filesystem::path& directoryPath)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
@@ -45,7 +43,7 @@ namespace Nz
|
||||
return;
|
||||
}
|
||||
|
||||
s_directories.insert(File::AbsolutePath(directoryPath));
|
||||
s_directories.insert(std::filesystem::absolute(directoryPath));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -79,9 +77,13 @@ namespace Nz
|
||||
|
||||
bool PluginManager::Mount(Plugin plugin)
|
||||
{
|
||||
Nz::String pluginName = s_pluginFiles[plugin];
|
||||
std::filesystem::path pluginName = s_pluginFiles[plugin];
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (Mount(pluginName + "-d", true))
|
||||
std::filesystem::path debugPath = pluginName;
|
||||
debugPath += "-d";
|
||||
|
||||
if (Mount(debugPath, true))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
@@ -102,7 +104,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if fail to initialize the plugin with PluginLoad
|
||||
*/
|
||||
|
||||
bool PluginManager::Mount(const String& pluginPath, bool appendExtension)
|
||||
bool PluginManager::Mount(const std::filesystem::path& pluginPath, bool appendExtension)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
@@ -110,23 +112,17 @@ namespace Nz
|
||||
return false;
|
||||
}
|
||||
|
||||
String path = pluginPath;
|
||||
if (appendExtension && !path.EndsWith(NAZARA_DYNLIB_EXTENSION))
|
||||
std::filesystem::path path = pluginPath;
|
||||
if (appendExtension && path.extension() == NAZARA_DYNLIB_EXTENSION)
|
||||
path += NAZARA_DYNLIB_EXTENSION;
|
||||
|
||||
bool exists = false;
|
||||
if (!File::IsAbsolute(path))
|
||||
if (!path.is_absolute())
|
||||
{
|
||||
for (const String& dir : s_directories)
|
||||
for (const std::filesystem::path& dir : s_directories)
|
||||
{
|
||||
String testPath;
|
||||
testPath.Reserve(dir.GetSize() + path.GetSize() + 10);
|
||||
|
||||
testPath = dir;
|
||||
testPath += NAZARA_DIRECTORY_SEPARATOR;
|
||||
testPath += path;
|
||||
|
||||
if (File::Exists(testPath))
|
||||
std::filesystem::path testPath = dir / path;
|
||||
if (std::filesystem::exists(testPath))
|
||||
{
|
||||
path = testPath;
|
||||
exists = true;
|
||||
@@ -134,7 +130,7 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (File::Exists(path))
|
||||
else if (std::filesystem::exists(path))
|
||||
exists = true;
|
||||
|
||||
if (!exists)
|
||||
@@ -143,7 +139,7 @@ namespace Nz
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<DynLib> library(new DynLib);
|
||||
std::unique_ptr<DynLib> library = std::make_unique<DynLib>();
|
||||
if (!library->Load(path))
|
||||
{
|
||||
NazaraError("Failed to load plugin");
|
||||
@@ -163,7 +159,8 @@ namespace Nz
|
||||
return false;
|
||||
}
|
||||
|
||||
s_plugins[pluginPath] = library.release();
|
||||
std::filesystem::path canonicalPath = std::filesystem::canonical(pluginPath);
|
||||
s_plugins[canonicalPath] = std::move(library);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -176,7 +173,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if not initialized
|
||||
*/
|
||||
|
||||
void PluginManager::RemoveDirectory(const String& directoryPath)
|
||||
void PluginManager::RemoveDirectory(const std::filesystem::path& directoryPath)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
@@ -184,7 +181,7 @@ namespace Nz
|
||||
return;
|
||||
}
|
||||
|
||||
s_directories.erase(File::AbsolutePath(directoryPath));
|
||||
s_directories.erase(std::filesystem::canonical(directoryPath));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -210,7 +207,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if plugin is not loaded
|
||||
*/
|
||||
|
||||
void PluginManager::Unmount(const String& pluginPath)
|
||||
void PluginManager::Unmount(const std::filesystem::path& pluginPath)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
@@ -218,7 +215,8 @@ namespace Nz
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = s_plugins.find(pluginPath);
|
||||
std::filesystem::path canonicalPath = std::filesystem::canonical(pluginPath);
|
||||
auto it = s_plugins.find(canonicalPath);
|
||||
if (it == s_plugins.end())
|
||||
{
|
||||
NazaraError("Plugin not loaded");
|
||||
@@ -229,9 +227,6 @@ namespace Nz
|
||||
if (func)
|
||||
func();
|
||||
|
||||
it->second->Unload();
|
||||
delete it->second;
|
||||
|
||||
s_plugins.erase(it);
|
||||
}
|
||||
|
||||
@@ -253,15 +248,12 @@ namespace Nz
|
||||
PluginUnload func = reinterpret_cast<PluginUnload>(pair.second->GetSymbol("PluginUnload"));
|
||||
if (func)
|
||||
func();
|
||||
|
||||
pair.second->Unload();
|
||||
delete pair.second;
|
||||
}
|
||||
|
||||
s_plugins.clear();
|
||||
}
|
||||
|
||||
std::set<String> PluginManager::s_directories;
|
||||
std::unordered_map<String, DynLib*> PluginManager::s_plugins;
|
||||
std::set<std::filesystem::path> PluginManager::s_directories;
|
||||
std::unordered_map<std::filesystem::path, std::unique_ptr<DynLib>, PluginManager::PathHash> PluginManager::s_plugins;
|
||||
bool PluginManager::s_initialized = false;
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// 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/Posix/ConditionVariableImpl.hpp>
|
||||
#include <Nazara/Core/Posix/MutexImpl.hpp>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
ConditionVariableImpl::ConditionVariableImpl()
|
||||
{
|
||||
pthread_cond_init(&m_cv, nullptr);
|
||||
}
|
||||
|
||||
ConditionVariableImpl::~ConditionVariableImpl()
|
||||
{
|
||||
pthread_cond_destroy(&m_cv);
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::Signal()
|
||||
{
|
||||
pthread_cond_signal(&m_cv);
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::SignalAll()
|
||||
{
|
||||
pthread_cond_broadcast(&m_cv);
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::Wait(MutexImpl* mutex)
|
||||
{
|
||||
pthread_cond_wait(&m_cv, &mutex->m_handle);
|
||||
}
|
||||
|
||||
bool ConditionVariableImpl::Wait(MutexImpl* mutex, UInt32 timeout)
|
||||
{
|
||||
// get the current time
|
||||
timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
|
||||
// construct the time limit (current time + time to wait)
|
||||
timespec ti;
|
||||
ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000;
|
||||
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
||||
ti.tv_nsec %= 1000000000;
|
||||
|
||||
return pthread_cond_timedwait(&m_cv,&mutex->m_handle, &ti) != 0;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// This file is part of the "Nazara Engine - Core module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_CONDITIONVARIABLEIMPL_HPP
|
||||
#define NAZARA_CONDITIONVARIABLEIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class MutexImpl;
|
||||
|
||||
class ConditionVariableImpl
|
||||
{
|
||||
public:
|
||||
ConditionVariableImpl();
|
||||
~ConditionVariableImpl();
|
||||
|
||||
void Signal();
|
||||
void SignalAll();
|
||||
|
||||
void Wait(MutexImpl* mutex);
|
||||
bool Wait(MutexImpl* mutex, UInt32 timeout);
|
||||
|
||||
private:
|
||||
pthread_cond_t m_cv;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_CONDITIONVARIABLEIMPL_HPP
|
||||
@@ -1,120 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// 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/Posix/DirectoryImpl.hpp>
|
||||
#include <Nazara/Core/Directory.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/StackArray.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
DirectoryImpl::DirectoryImpl(const Directory* parent) :
|
||||
m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void DirectoryImpl::Close()
|
||||
{
|
||||
closedir(m_handle);
|
||||
}
|
||||
|
||||
String DirectoryImpl::GetResultName() const
|
||||
{
|
||||
return m_result->d_name;
|
||||
}
|
||||
|
||||
UInt64 DirectoryImpl::GetResultSize() const
|
||||
{
|
||||
String path = m_parent->GetPath();
|
||||
std::size_t pathSize = path.GetSize();
|
||||
|
||||
std::size_t resultNameSize = std::strlen(m_result->d_name);
|
||||
|
||||
std::size_t fullNameSize = pathSize + 1 + resultNameSize;
|
||||
StackArray<char> fullName = NazaraStackArrayNoInit(char, fullNameSize + 1);
|
||||
std::memcpy(&fullName[0], path.GetConstBuffer(), pathSize * sizeof(char));
|
||||
fullName[pathSize] = '/';
|
||||
std::memcpy(&fullName[pathSize + 1], m_result->d_name, resultNameSize * sizeof(char));
|
||||
fullName[fullNameSize] = '\0';
|
||||
|
||||
struct stat64 results;
|
||||
stat64(fullName.data(), &results);
|
||||
|
||||
return results.st_size;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::IsResultDirectory() const
|
||||
{
|
||||
//TODO: Fix d_type handling (field can be missing or be a symbolic link, both cases which must be handled by calling stat)
|
||||
|
||||
return m_result->d_type == DT_DIR;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::NextResult()
|
||||
{
|
||||
if ((m_result = readdir64(m_handle)))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
if (errno == EBADF || errno == EOVERFLOW)
|
||||
NazaraError("Unable to get next result: " + Error::GetLastSystemError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Open(const String& dirPath)
|
||||
{
|
||||
m_handle = opendir(dirPath.GetConstBuffer());
|
||||
if (!m_handle)
|
||||
{
|
||||
NazaraError("Unable to open directory: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Create(const String& dirPath)
|
||||
{
|
||||
mode_t permissions = S_IRWXU | S_IRWXG | S_IRWXO; // 777
|
||||
return mkdir(dirPath.GetConstBuffer(), permissions) != -1;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Exists(const String& dirPath)
|
||||
{
|
||||
struct stat64 filestats;
|
||||
if (stat64(dirPath.GetConstBuffer(), &filestats) == -1) // error
|
||||
return false;
|
||||
|
||||
return S_ISDIR(filestats.st_mode) || S_ISREG(filestats.st_mode);
|
||||
}
|
||||
|
||||
String DirectoryImpl::GetCurrent()
|
||||
{
|
||||
String currentPath;
|
||||
|
||||
char path[MAXPATHLEN];
|
||||
if (getcwd(path, MAXPATHLEN))
|
||||
currentPath = path;
|
||||
else
|
||||
NazaraError("Unable to get current directory: " + Error::GetLastSystemError()); // Bug: initialisation -> if no path for log !
|
||||
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Remove(const String& dirPath)
|
||||
{
|
||||
bool success = rmdir(dirPath.GetConstBuffer()) != -1;
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// 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_DIRECTORYIMPL_HPP
|
||||
#define NAZARA_DIRECTORYIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <dirent.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class Directory;
|
||||
class String;
|
||||
|
||||
class DirectoryImpl
|
||||
{
|
||||
public:
|
||||
DirectoryImpl(const Directory* parent);
|
||||
DirectoryImpl(const DirectoryImpl&) = delete;
|
||||
DirectoryImpl(DirectoryImpl&&) = delete; ///TODO
|
||||
~DirectoryImpl() = default;
|
||||
|
||||
void Close();
|
||||
|
||||
String GetResultName() const;
|
||||
UInt64 GetResultSize() const;
|
||||
|
||||
bool IsResultDirectory() const;
|
||||
|
||||
bool NextResult();
|
||||
|
||||
bool Open(const String& dirPath);
|
||||
|
||||
DirectoryImpl& operator=(const DirectoryImpl&) = delete;
|
||||
DirectoryImpl& operator=(DirectoryImpl&&) = delete; ///TODO
|
||||
|
||||
static bool Create(const String& dirPath);
|
||||
static bool Exists(const String& dirPath);
|
||||
static String GetCurrent();
|
||||
static bool Remove(const String& dirPath);
|
||||
|
||||
private:
|
||||
const Directory* m_parent;
|
||||
DIR* m_handle;
|
||||
dirent64* m_result;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_DIRECTORYIMPL_HPP
|
||||
@@ -10,12 +10,18 @@
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
DynLibImpl::DynLibImpl(DynLib* parent)
|
||||
DynLibImpl::DynLibImpl(DynLib*) :
|
||||
m_handle(nullptr)
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
DynLibFunc DynLibImpl::GetSymbol(const String& symbol, String* errorMessage) const
|
||||
DynLibImpl::~DynLibImpl()
|
||||
{
|
||||
if (m_handle)
|
||||
dlclose(m_handle);
|
||||
}
|
||||
|
||||
DynLibFunc DynLibImpl::GetSymbol(const char* symbol, std::string* errorMessage) const
|
||||
{
|
||||
/*
|
||||
Il n'est pas standard de cast un pointeur d'objet vers un pointeur de fonction.
|
||||
@@ -31,23 +37,21 @@ namespace Nz
|
||||
|
||||
dlerror(); // Clear error flag
|
||||
|
||||
converter.pointer = dlsym(m_handle, symbol.GetConstBuffer());
|
||||
converter.pointer = dlsym(m_handle, symbol);
|
||||
if (!converter.pointer)
|
||||
*errorMessage = dlerror();
|
||||
|
||||
return converter.func;
|
||||
}
|
||||
|
||||
bool DynLibImpl::Load(const String& libraryPath, String* errorMessage)
|
||||
bool DynLibImpl::Load(const std::filesystem::path& libraryPath, std::string* errorMessage)
|
||||
{
|
||||
String path = libraryPath;
|
||||
|
||||
size_t pos = path.FindLast(".so");
|
||||
if (pos == String::npos || (path.GetLength() > pos+3 && path[pos+3] != '.'))
|
||||
std::filesystem::path path = libraryPath;
|
||||
if (path.extension() != ".so")
|
||||
path += ".so";
|
||||
|
||||
dlerror(); // Clear error flag
|
||||
m_handle = dlopen(path.GetConstBuffer(), RTLD_LAZY | RTLD_GLOBAL);
|
||||
m_handle = dlopen(path.generic_u8string().data(), RTLD_LAZY | RTLD_GLOBAL);
|
||||
|
||||
if (m_handle)
|
||||
return true;
|
||||
@@ -57,9 +61,4 @@ namespace Nz
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DynLibImpl::Unload()
|
||||
{
|
||||
dlclose(m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#define NAZARA_DYNLIBIMPL_HPP
|
||||
|
||||
#include <Nazara/Core/DynLib.hpp>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
@@ -17,11 +19,10 @@ namespace Nz
|
||||
{
|
||||
public:
|
||||
DynLibImpl(DynLib* m_parent);
|
||||
~DynLibImpl() = default;
|
||||
~DynLibImpl();
|
||||
|
||||
DynLibFunc GetSymbol(const String& symbol, String* errorMessage) const;
|
||||
bool Load(const String& libraryPath, String* errorMessage);
|
||||
void Unload();
|
||||
DynLibFunc GetSymbol(const char* symbol, std::string* errorMessage) const;
|
||||
bool Load(const std::filesystem::path& libraryPath, std::string* errorMessage);
|
||||
|
||||
private:
|
||||
void* m_handle;
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
namespace Nz
|
||||
{
|
||||
FileImpl::FileImpl(const File* parent) :
|
||||
m_fileDescriptor(-1),
|
||||
m_endOfFile(false),
|
||||
m_endOfFileUpdated(true)
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
void FileImpl::Close()
|
||||
FileImpl::~FileImpl()
|
||||
{
|
||||
if (m_fileDescriptor != -1)
|
||||
close(m_fileDescriptor);
|
||||
@@ -52,7 +53,7 @@ namespace Nz
|
||||
return static_cast<UInt64>(position);
|
||||
}
|
||||
|
||||
bool FileImpl::Open(const String& filePath, OpenModeFlags mode)
|
||||
bool FileImpl::Open(const std::filesystem::path& filePath, OpenModeFlags mode)
|
||||
{
|
||||
int flags;
|
||||
mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
@@ -75,10 +76,10 @@ namespace Nz
|
||||
if (mode & OpenMode_Truncate)
|
||||
flags |= O_TRUNC;
|
||||
|
||||
m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
|
||||
if (m_fileDescriptor == -1)
|
||||
int fileDescriptor = open64(filePath.generic_u8string().data(), flags, permissions);
|
||||
if (fileDescriptor == -1)
|
||||
{
|
||||
NazaraError("Failed to open \"" + filePath + "\" : " + Error::GetLastSystemError());
|
||||
NazaraError("Failed to open \"" + filePath.generic_u8string() + "\" : " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -95,16 +96,16 @@ namespace Nz
|
||||
|
||||
initialize_flock(lock);
|
||||
|
||||
if (fcntl(m_fileDescriptor, F_GETLK, &lock) == -1)
|
||||
if (fcntl(fileDescriptor, F_GETLK, &lock) == -1)
|
||||
{
|
||||
Close();
|
||||
close(fileDescriptor);
|
||||
NazaraError("Unable to detect presence of lock on the file");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lock.l_type != F_UNLCK)
|
||||
{
|
||||
Close();
|
||||
close(fileDescriptor);
|
||||
NazaraError("A lock is present on the file");
|
||||
return false;
|
||||
}
|
||||
@@ -113,14 +114,16 @@ namespace Nz
|
||||
{
|
||||
initialize_flock(lock);
|
||||
|
||||
if (fcntl(m_fileDescriptor, F_SETLK, &lock) == -1)
|
||||
if (fcntl(fileDescriptor, F_SETLK, &lock) == -1)
|
||||
{
|
||||
Close();
|
||||
close(fileDescriptor);
|
||||
NazaraError("Unable to place a lock on the file");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_fileDescriptor = fileDescriptor;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -177,121 +180,4 @@ namespace Nz
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
bool FileImpl::Copy(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY);
|
||||
if (fd1 == -1)
|
||||
{
|
||||
NazaraError("Fail to open input file (" + sourcePath + "): " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
mode_t permissions;
|
||||
struct stat sb;
|
||||
if (fstat(fd1, &sb) == -1) // get permission from first file
|
||||
{
|
||||
NazaraWarning("Could not get permissions of source file");
|
||||
permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
permissions = sb.st_mode & ~S_IFMT; // S_IFMT: bit mask for the file type bit field -> ~S_IFMT: general permissions
|
||||
}
|
||||
|
||||
int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions);
|
||||
if (fd2 == -1)
|
||||
{
|
||||
NazaraError("Fail to open output file (" + targetPath + "): " + Error::GetLastSystemError()); // TODO: more info ?
|
||||
close(fd1);
|
||||
return false;
|
||||
}
|
||||
|
||||
char buffer[512];
|
||||
ssize_t bytes;
|
||||
do
|
||||
{
|
||||
bytes = read(fd1,buffer,512);
|
||||
if (bytes == -1)
|
||||
{
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
NazaraError("An error occured from copy : " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
write(fd2,buffer,bytes);
|
||||
}
|
||||
while (bytes == 512);
|
||||
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileImpl::Delete(const String& filePath)
|
||||
{
|
||||
bool success = unlink(filePath.GetConstBuffer()) != -1;
|
||||
|
||||
if (success)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileImpl::Exists(const String& filePath)
|
||||
{
|
||||
const char* path = filePath.GetConstBuffer();
|
||||
if (access(path, F_OK) != -1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
time_t FileImpl::GetCreationTime(const String& filePath)
|
||||
{
|
||||
NazaraUnused(filePath);
|
||||
|
||||
NazaraWarning("Posix has no creation time information");
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t FileImpl::GetLastAccessTime(const String& filePath)
|
||||
{
|
||||
struct stat64 stats;
|
||||
stat64(filePath.GetConstBuffer(), &stats);
|
||||
|
||||
return stats.st_atime;
|
||||
}
|
||||
|
||||
time_t FileImpl::GetLastWriteTime(const String& filePath)
|
||||
{
|
||||
struct stat64 stats;
|
||||
stat64(filePath.GetConstBuffer(), &stats);
|
||||
|
||||
return stats.st_mtime;
|
||||
}
|
||||
|
||||
UInt64 FileImpl::GetSize(const String& filePath)
|
||||
{
|
||||
struct stat64 stats;
|
||||
stat64(filePath.GetConstBuffer(), &stats);
|
||||
|
||||
return static_cast<UInt64>(stats.st_size);
|
||||
}
|
||||
|
||||
bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1;
|
||||
|
||||
if (success)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Unable to rename file: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Enums.hpp>
|
||||
#include <ctime>
|
||||
#include <filesystem>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
@@ -26,13 +27,12 @@ namespace Nz
|
||||
FileImpl(const File* parent);
|
||||
FileImpl(const FileImpl&) = delete;
|
||||
FileImpl(FileImpl&&) = delete; ///TODO
|
||||
~FileImpl() = default;
|
||||
~FileImpl();
|
||||
|
||||
void Close();
|
||||
bool EndOfFile() const;
|
||||
void Flush();
|
||||
UInt64 GetCursorPos() const;
|
||||
bool Open(const String& filePath, OpenModeFlags mode);
|
||||
bool Open(const std::filesystem::path& filePath, OpenModeFlags mode);
|
||||
std::size_t Read(void* buffer, std::size_t size);
|
||||
bool SetCursorPos(CursorPosition pos, Int64 offset);
|
||||
bool SetSize(UInt64 size);
|
||||
@@ -41,15 +41,6 @@ namespace Nz
|
||||
FileImpl& operator=(const FileImpl&) = delete;
|
||||
FileImpl& operator=(FileImpl&&) = delete; ///TODO
|
||||
|
||||
static bool Copy(const String& sourcePath, const String& targetPath);
|
||||
static bool Delete(const String& filePath);
|
||||
static bool Exists(const String& filePath);
|
||||
static time_t GetCreationTime(const String& filePath);
|
||||
static time_t GetLastAccessTime(const String& filePath);
|
||||
static time_t GetLastWriteTime(const String& filePath);
|
||||
static UInt64 GetSize(const String& filePath);
|
||||
static bool Rename(const String& sourcePath, const String& targetPath);
|
||||
|
||||
private:
|
||||
int m_fileDescriptor;
|
||||
mutable bool m_endOfFile;
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// 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/Posix/MutexImpl.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
pthread_mutex_init(&m_handle, &attr);
|
||||
}
|
||||
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
pthread_mutex_destroy(&m_handle);
|
||||
}
|
||||
|
||||
void MutexImpl::Lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_handle);
|
||||
}
|
||||
|
||||
bool MutexImpl::TryLock()
|
||||
{
|
||||
return pthread_mutex_trylock(&m_handle) == 0;
|
||||
}
|
||||
|
||||
void MutexImpl::Unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_handle);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// 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_MUTEXIMPL_HPP
|
||||
#define NAZARA_MUTEXIMPL_HPP
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class MutexImpl
|
||||
{
|
||||
friend class ConditionVariableImpl;
|
||||
|
||||
public:
|
||||
MutexImpl();
|
||||
~MutexImpl();
|
||||
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_handle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_MUTEXIMPL_HPP
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// 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/Posix/SemaphoreImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
SemaphoreImpl::SemaphoreImpl(unsigned int count)
|
||||
{
|
||||
if (sem_init(&m_semaphore, 0, count) != 0)
|
||||
NazaraError("Failed to create semaphore: " + Error::GetLastSystemError());
|
||||
}
|
||||
|
||||
SemaphoreImpl::~SemaphoreImpl()
|
||||
{
|
||||
sem_destroy(&m_semaphore);
|
||||
}
|
||||
|
||||
unsigned int SemaphoreImpl::GetCount() const
|
||||
{
|
||||
int count=0;
|
||||
sem_getvalue(const_cast<sem_t*>(&m_semaphore), &count);
|
||||
return static_cast<unsigned int>(count);
|
||||
}
|
||||
|
||||
void SemaphoreImpl::Post()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (sem_post(&m_semaphore)==-1)
|
||||
NazaraError("Failed to release semaphore: " + Error::GetLastSystemError());
|
||||
#else
|
||||
sem_post(&m_semaphore);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SemaphoreImpl::Wait()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (sem_wait(&m_semaphore) == -1 )
|
||||
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||
#else
|
||||
sem_wait(&m_semaphore);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SemaphoreImpl::Wait(UInt32 timeout)
|
||||
{
|
||||
timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
|
||||
timespec ti;
|
||||
ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000;
|
||||
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
|
||||
ti.tv_nsec %= 1000000000;
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (sem_timedwait(&m_semaphore, &ti) != 0)
|
||||
{
|
||||
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return sem_timedwait(&m_semaphore, &ti) != 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// 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_SEMAPHOREIMPL_HPP
|
||||
#define NAZARA_SEMAPHOREIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <semaphore.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class SemaphoreImpl
|
||||
{
|
||||
public:
|
||||
SemaphoreImpl(unsigned int count);
|
||||
~SemaphoreImpl();
|
||||
|
||||
unsigned int GetCount() const;
|
||||
void Post();
|
||||
void Wait();
|
||||
bool Wait(UInt32 timeout);
|
||||
|
||||
private:
|
||||
sem_t m_semaphore;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_SEMAPHOREIMPL_HPP
|
||||
@@ -1,78 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// 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/Posix/ThreadImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Functor.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <time.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
ThreadImpl::ThreadImpl(Functor* functor)
|
||||
{
|
||||
int error = pthread_create(&m_handle, nullptr, &ThreadImpl::ThreadProc, functor);
|
||||
if (error != 0)
|
||||
NazaraInternalError("Failed to create thread: " + Error::GetLastSystemError());
|
||||
}
|
||||
|
||||
void ThreadImpl::Detach()
|
||||
{
|
||||
pthread_detach(m_handle);
|
||||
}
|
||||
|
||||
void ThreadImpl::Join()
|
||||
{
|
||||
pthread_join(m_handle, nullptr);
|
||||
}
|
||||
|
||||
void ThreadImpl::SetName(const Nz::String& name)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
pthread_setname_np(m_handle, name.GetConstBuffer());
|
||||
#else
|
||||
NazaraWarning("Setting thread name is not supported on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThreadImpl::SetCurrentName(const Nz::String& name)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
pthread_setname_np(pthread_self(), name.GetConstBuffer());
|
||||
#else
|
||||
NazaraWarning("Setting current thread name is not supported on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThreadImpl::Sleep(UInt32 time)
|
||||
{
|
||||
if (time == 0)
|
||||
sched_yield();
|
||||
else
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = time / 1000;
|
||||
ts.tv_nsec = (time - ts.tv_sec * 1000) * 1'000'000;
|
||||
|
||||
int r;
|
||||
do
|
||||
{
|
||||
r = nanosleep(&ts, &ts);
|
||||
}
|
||||
while (r == -1 && errno == EINTR);
|
||||
}
|
||||
}
|
||||
|
||||
void* ThreadImpl::ThreadProc(void* userdata)
|
||||
{
|
||||
Functor* func = static_cast<Functor*>(userdata);
|
||||
func->Run();
|
||||
delete func;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright (C) 2015 Alexandre Janniaux
|
||||
// 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_THREADIMPL_HPP
|
||||
#define NAZARA_THREADIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
|
||||
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct Functor;
|
||||
class String;
|
||||
|
||||
class ThreadImpl
|
||||
{
|
||||
public:
|
||||
ThreadImpl(Functor* threadFunc);
|
||||
|
||||
void Detach();
|
||||
void Join();
|
||||
void SetName(const Nz::String& name);
|
||||
|
||||
static void SetCurrentName(const Nz::String& name);
|
||||
static void Sleep(UInt32 time);
|
||||
|
||||
private:
|
||||
static void* ThreadProc(void* userdata);
|
||||
|
||||
pthread_t m_handle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_THREADIMPL_HPP
|
||||
@@ -20,7 +20,7 @@ namespace Nz
|
||||
* \return A reference to the path
|
||||
*/
|
||||
|
||||
const String& Resource::GetFilePath() const
|
||||
const std::filesystem::path& Resource::GetFilePath() const
|
||||
{
|
||||
return m_filePath;
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace Nz
|
||||
* \param filePath Path to the resource
|
||||
*/
|
||||
|
||||
void Resource::SetFilePath(const String& filePath)
|
||||
void Resource::SetFilePath(const std::filesystem::path& filePath)
|
||||
{
|
||||
m_filePath = filePath;
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
// 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/Semaphore.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/SemaphoreImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/SemaphoreImpl.hpp>
|
||||
#else
|
||||
#error Lack of implementation: Semaphore
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup core
|
||||
* \class Nz::Semaphore
|
||||
* \brief Core class that represents a counting semaphore
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a semaphore object with a count
|
||||
*/
|
||||
|
||||
Semaphore::Semaphore(unsigned int count)
|
||||
{
|
||||
m_impl = new SemaphoreImpl(count);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destructs the object
|
||||
*/
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the number of count that can handle the semaphore
|
||||
* \return Number of count associated with the semaphore
|
||||
*/
|
||||
|
||||
unsigned int Semaphore::GetCount() const
|
||||
{
|
||||
return m_impl->GetCount();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Increments the count of the semaphore and wait if count equals zero
|
||||
*
|
||||
* Increments the value of semaphore variable by 1. After the increment, if the pre-increment value was negative (meaning there are processes waiting for a resource), it transfers a blocked process from the semaphore's waiting queue to the ready queue
|
||||
*/
|
||||
|
||||
void Semaphore::Post()
|
||||
{
|
||||
m_impl->Post();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Decrements the count of the semaphore and wait if count equals zero
|
||||
*
|
||||
* If the value of semaphore variable is not negative, decrements it by 1. If the semaphore variable is now negative, the process executing Wait is blocked (i.e., added to the semaphore's queue) until the value is greater or equal to 1. Otherwise, the process continues execution, having used a unit of the resource
|
||||
*/
|
||||
|
||||
void Semaphore::Wait()
|
||||
{
|
||||
m_impl->Wait();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Decrements the count of the semaphore and wait if count equals zero
|
||||
* \return true if the semaphore successfully decrements before timeout
|
||||
*
|
||||
* If the value of semaphore variable is not negative, decrements it by 1. If the semaphore variable is now negative, the process executing Wait is blocked (i.e., added to the semaphore's queue) until the value is greater or equal to 1. Otherwise, the process continues execution, having used a unit of the resource
|
||||
*/
|
||||
|
||||
bool Semaphore::Wait(UInt32 timeout)
|
||||
{
|
||||
return m_impl->Wait(timeout);
|
||||
}
|
||||
}
|
||||
@@ -28,9 +28,9 @@ namespace Nz
|
||||
* \return Empty string (meant to be virtual)
|
||||
*/
|
||||
|
||||
String Stream::GetDirectory() const
|
||||
std::filesystem::path Stream::GetDirectory() const
|
||||
{
|
||||
return String();
|
||||
return std::filesystem::path();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -38,9 +38,9 @@ namespace Nz
|
||||
* \return Empty string (meant to be virtual)
|
||||
*/
|
||||
|
||||
String Stream::GetPath() const
|
||||
std::filesystem::path Stream::GetPath() const
|
||||
{
|
||||
return String();
|
||||
return std::filesystem::path();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -57,9 +57,9 @@ namespace Nz
|
||||
* \remark With the text stream option, "\r\n" is treated as "\n"
|
||||
* \remark The line separator character is not returned as part of the string
|
||||
*/
|
||||
String Stream::ReadLine(unsigned int lineSize)
|
||||
std::string Stream::ReadLine(unsigned int lineSize)
|
||||
{
|
||||
String line;
|
||||
std::string line;
|
||||
if (lineSize == 0) // Maximal size undefined
|
||||
{
|
||||
const unsigned int bufferSize = 64;
|
||||
@@ -79,9 +79,9 @@ namespace Nz
|
||||
if (ptr != buffer)
|
||||
{
|
||||
if (m_streamOptions & StreamOption_Text && buffer[pos - 1] == '\r')
|
||||
line.Append(buffer, pos - 1);
|
||||
line.append(buffer, pos - 1);
|
||||
else
|
||||
line.Append(buffer, pos);
|
||||
line.append(buffer, pos);
|
||||
}
|
||||
|
||||
if (!SetCursorPos(GetCursorPos() - readSize + pos + 1))
|
||||
@@ -100,28 +100,28 @@ namespace Nz
|
||||
length--;
|
||||
}
|
||||
|
||||
line.Append(buffer, length);
|
||||
line.append(buffer, length);
|
||||
}
|
||||
}
|
||||
while (readSize == bufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
line.Set(lineSize, '\0');
|
||||
line.resize(lineSize, '\0');
|
||||
std::size_t readSize = Read(&line[0], lineSize);
|
||||
std::size_t pos = line.Find('\n');
|
||||
std::size_t pos = line.find('\n');
|
||||
if (pos <= readSize) // False only if the character is not available (npos being the biggest integer)
|
||||
{
|
||||
if (m_streamOptions & StreamOption_Text && pos > 0 && line[pos - 1] == '\r')
|
||||
line.Resize(pos);
|
||||
line.resize(pos);
|
||||
else
|
||||
line.Resize(pos + 1);
|
||||
line.resize(pos + 1);
|
||||
|
||||
if (!SetCursorPos(GetCursorPos() - readSize + pos + 1))
|
||||
NazaraWarning("Failed to reset cursos pos");
|
||||
}
|
||||
else
|
||||
line.Resize(readSize);
|
||||
line.resize(readSize);
|
||||
}
|
||||
|
||||
return line;
|
||||
|
||||
226
src/Nazara/Core/StringExt.cpp
Normal file
226
src/Nazara/Core/StringExt.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
// 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/StringExt.hpp>
|
||||
#include <Nazara/Core/Algorithm.hpp>
|
||||
#include <Utfcpp/utf8.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool IsSpace(char32_t character)
|
||||
{
|
||||
return character == '\t' || Unicode::GetCategory(character) & Unicode::Category_Separator;
|
||||
}
|
||||
|
||||
char ToLower(char character)
|
||||
{
|
||||
if (character >= 'A' && character <= 'Z')
|
||||
return character + ('a' - 'A');
|
||||
else
|
||||
return character;
|
||||
}
|
||||
|
||||
char ToUpper(char character)
|
||||
{
|
||||
if (character >= 'a' && character <= 'z')
|
||||
return character + ('A' - 'a');
|
||||
else
|
||||
return character;
|
||||
}
|
||||
|
||||
template<std::size_t S>
|
||||
struct WideConverter
|
||||
{
|
||||
static std::string From(const wchar_t* wstr, std::size_t size)
|
||||
{
|
||||
if constexpr (S == 2)
|
||||
{
|
||||
// UTF-16 (Windows)
|
||||
return FromUtf16String(std::u16string_view(reinterpret_cast<const char16_t*>(wstr), size));
|
||||
}
|
||||
else if constexpr (S == 4)
|
||||
{
|
||||
// UTF-32 (Linux)
|
||||
return FromUtf32String(std::u32string_view(reinterpret_cast<const char32_t*>(wstr), size));
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(AlwaysFalse<std::integral_constant<std::size_t, S>>::value, "Unsupported platform");
|
||||
return std::string("<platform error>");
|
||||
}
|
||||
}
|
||||
|
||||
static std::wstring To(const std::string_view& str)
|
||||
{
|
||||
if constexpr (S == 2)
|
||||
{
|
||||
std::wstring result;
|
||||
utf8::utf8to16(str.begin(), str.end(), std::back_inserter(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
else if constexpr (S == 4)
|
||||
{
|
||||
std::wstring result;
|
||||
utf8::utf8to32(str.begin(), str.end(), std::back_inserter(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(AlwaysFalse<std::integral_constant<std::size_t, S>>::value, "Unsupported platform");
|
||||
return std::wstring(L"<platform error>");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::string FromUtf16String(const char16_t* u16str)
|
||||
{
|
||||
std::size_t size = std::char_traits<char16_t>::length(u16str);
|
||||
return FromUtf16String(std::u16string_view(u16str, size));
|
||||
}
|
||||
|
||||
std::string FromUtf16String(const std::u16string_view& u16str)
|
||||
{
|
||||
std::string result;
|
||||
utf8::utf16to8(u16str.begin(), u16str.end(), std::back_inserter(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string FromUtf32String(const char32_t* u32str)
|
||||
{
|
||||
std::size_t size = std::char_traits<char32_t>::length(u32str);
|
||||
return FromUtf32String(std::u32string_view(u32str, size));
|
||||
}
|
||||
|
||||
std::string FromUtf32String(const std::u32string_view& u32str)
|
||||
{
|
||||
std::string result;
|
||||
utf8::utf32to8(u32str.begin(), u32str.end(), std::back_inserter(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string FromWideString(const wchar_t* wstr)
|
||||
{
|
||||
std::size_t size = std::char_traits<wchar_t>::length(wstr);
|
||||
return WideConverter<sizeof(wchar_t)>::From(wstr, size);
|
||||
}
|
||||
|
||||
std::string FromWideString(const std::wstring_view& wstr)
|
||||
{
|
||||
return WideConverter<sizeof(wchar_t)>::From(wstr.data(), wstr.size());
|
||||
}
|
||||
|
||||
bool StartsWith(const std::string_view& str, const std::string_view& s, CaseIndependent)
|
||||
{
|
||||
if (s.size() > str.size())
|
||||
return false;
|
||||
|
||||
return std::equal(str.begin(), str.begin() + s.size(), s.begin(), s.end(), [](char c1, char c2)
|
||||
{
|
||||
return ToLower(c1) == ToLower(c2);
|
||||
});
|
||||
}
|
||||
|
||||
bool StartsWith(const std::string_view& str, const std::string_view& s, CaseIndependent, UnicodeAware)
|
||||
{
|
||||
if (str.empty() || s.empty())
|
||||
return str == s;
|
||||
|
||||
utf8::iterator<const char*> it(str.data(), str.data(), str.data() + str.size());
|
||||
utf8::iterator<const char*> it2(s.data(), s.data(), s.data() + s.size());
|
||||
do
|
||||
{
|
||||
if (it2.base() >= s.data() + s.size())
|
||||
return true;
|
||||
|
||||
if (Unicode::GetLowercase(*it) != Unicode::GetLowercase(*it2))
|
||||
return false;
|
||||
|
||||
++it2;
|
||||
}
|
||||
while (*it++);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ToLower(const std::string_view& str)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(str.size());
|
||||
std::transform(str.begin(), str.end(), std::back_inserter(result), Overload<char>(ToLower));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ToLower(const std::string_view& str, UnicodeAware)
|
||||
{
|
||||
if (str.empty())
|
||||
return std::string();
|
||||
|
||||
std::string result;
|
||||
result.reserve(str.size());
|
||||
|
||||
utf8::unchecked::iterator<const char*> it(str.data());
|
||||
do
|
||||
utf8::append(Unicode::GetLowercase(*it), std::back_inserter(result));
|
||||
while (*++it);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ToUpper(const std::string_view& str)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(str.size());
|
||||
std::transform(str.begin(), str.end(), std::back_inserter(result), Overload<char>(ToUpper));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ToUpper(const std::string_view& str, UnicodeAware)
|
||||
{
|
||||
if (str.empty())
|
||||
return std::string();
|
||||
|
||||
std::string result;
|
||||
result.reserve(str.size());
|
||||
|
||||
utf8::iterator<const char*> it(str.data(), str.data(), str.data() + str.size());
|
||||
do
|
||||
utf8::append(Unicode::GetUppercase(*it), std::back_inserter(result));
|
||||
while (*++it);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::u16string ToUtf16String(const std::string_view& str)
|
||||
{
|
||||
std::u16string result;
|
||||
utf8::utf8to16(str.begin(), str.end(), std::back_inserter(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::u32string ToUtf32String(const std::string_view& str)
|
||||
{
|
||||
std::u32string result;
|
||||
utf8::utf8to32(str.begin(), str.end(), std::back_inserter(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring ToWideString(const std::string_view& str)
|
||||
{
|
||||
return WideConverter<sizeof(wchar_t)>::To(str);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Core/DebugOff.hpp>
|
||||
@@ -1,280 +0,0 @@
|
||||
// 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/Thread.hpp>
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/HardwareInfo.hpp>
|
||||
#include <Nazara/Core/MovablePtr.hpp>
|
||||
#include <ostream>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/ThreadImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/ThreadImpl.hpp>
|
||||
#else
|
||||
#error Thread has no implementation
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
/*!
|
||||
* \ingroup core
|
||||
* \class Nz::Thread
|
||||
* \brief Core class that represents a thread
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Thread<T> object by default
|
||||
*/
|
||||
|
||||
Thread::Thread() :
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Waits that the thread ends and then destroys this
|
||||
*/
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Join();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Detaches the thread
|
||||
*/
|
||||
|
||||
void Thread::Detach()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Detach();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the id of the thread
|
||||
* \return The identifiant of the thread (PID)
|
||||
*/
|
||||
|
||||
Thread::Id Thread::GetId() const
|
||||
{
|
||||
return Thread::Id(m_impl);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the thread can be joined
|
||||
* \return true if well formed and not detached
|
||||
*/
|
||||
|
||||
bool Thread::IsJoinable() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Waits that the thread ends
|
||||
*
|
||||
* \remark Produce a NazaraError if no functor was assigned and NAZARA_CORE_SAFE is defined
|
||||
*/
|
||||
|
||||
void Thread::Join()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("This thread is not joinable");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->Join();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Changes the debugging name associated to a thread
|
||||
*
|
||||
* Changes the debugging name associated with a particular thread, and may helps with debugging tools.
|
||||
*
|
||||
* \param name The new name of the thread
|
||||
*
|
||||
* \remark Due to system limitations, thread name cannot exceed 15 characters (excluding null-terminator)
|
||||
*
|
||||
* \see SetCurrentThreadName
|
||||
*/
|
||||
void Thread::SetName(const String& name)
|
||||
{
|
||||
NazaraAssert(m_impl, "Invalid thread");
|
||||
NazaraAssert(name.GetSize() < 16, "Thread name is too long");
|
||||
|
||||
m_impl->SetName(name);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the number of simulatenous threads that can run on the same cpu
|
||||
* \return The number of simulatenous threads
|
||||
*/
|
||||
unsigned int Thread::HardwareConcurrency()
|
||||
{
|
||||
return HardwareInfo::GetProcessorCount();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Changes the debugging name associated to the calling thread
|
||||
*
|
||||
* Changes the debugging name associated with the calling thread, and may helps with debugging tools.
|
||||
*
|
||||
* \param name The new name associated with this thread
|
||||
*
|
||||
* \remark Due to system limitations, thread name cannot exceed 15 characters (excluding null-terminator)
|
||||
*
|
||||
* \see SetName
|
||||
*/
|
||||
void Thread::SetCurrentThreadName(const String& name)
|
||||
{
|
||||
NazaraAssert(name.GetSize() < 16, "Thread name is too long");
|
||||
|
||||
ThreadImpl::SetCurrentName(name);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Makes sleep this thread
|
||||
*
|
||||
* \param milliseconds The number of milliseconds to sleep
|
||||
*/
|
||||
void Thread::Sleep(UInt32 milliseconds)
|
||||
{
|
||||
ThreadImpl::Sleep(milliseconds);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates the implementation of this thread
|
||||
*
|
||||
* \param functor The task the thread will represent
|
||||
*/
|
||||
|
||||
void Thread::CreateImpl(Functor* functor)
|
||||
{
|
||||
m_impl = new ThreadImpl(functor);
|
||||
}
|
||||
|
||||
/*********************************Thread::Id********************************/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a Thread<T> object with a thread implementation
|
||||
*
|
||||
* \param thread Thread implementation assigned to the thread
|
||||
*/
|
||||
|
||||
Thread::Id::Id(ThreadImpl* thread) :
|
||||
m_id(thread)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compares two Thread::Id
|
||||
* \return true if the two thread ids are the same
|
||||
*
|
||||
* \param lhs First id
|
||||
* \param rhs Second id
|
||||
*/
|
||||
|
||||
bool operator==(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id == rhs.m_id;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compares two Thread::Id
|
||||
* \return false if the two thread ids are the same
|
||||
*
|
||||
* \param lhs First id
|
||||
* \param rhs Second id
|
||||
*/
|
||||
|
||||
bool operator!=(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id != rhs.m_id;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compares two Thread::Id
|
||||
* \return true if the first thread id is inferior to the second one
|
||||
*
|
||||
* \param lhs First id
|
||||
* \param rhs Second id
|
||||
*/
|
||||
|
||||
bool operator<(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id < rhs.m_id;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compares two Thread::Id
|
||||
* \return true if the first thread id is inferior or equal to the second one
|
||||
*
|
||||
* \param lhs First id
|
||||
* \param rhs Second id
|
||||
*/
|
||||
|
||||
bool operator<=(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id <= rhs.m_id;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compares two Thread::Id
|
||||
* \return true if the first thread id is superior to the second one
|
||||
*
|
||||
* \param lhs First id
|
||||
* \param rhs Second id
|
||||
*/
|
||||
|
||||
bool operator>(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id > rhs.m_id;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compares two Thread::Id
|
||||
* \return true if the first thread id is superior or equal to the second one
|
||||
*
|
||||
* \param lhs First id
|
||||
* \param rhs Second id
|
||||
*/
|
||||
|
||||
bool operator>=(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id >= rhs.m_id;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Output operator
|
||||
* \return The stream
|
||||
*
|
||||
* \param out The stream
|
||||
* \param id The thread id to output
|
||||
*/
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const Nz::Thread::Id& id)
|
||||
{
|
||||
o << id.m_id;
|
||||
return o;
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
// 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
|
||||
|
||||
// Source: http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
|
||||
|
||||
#include <Nazara/Core/Win32/ConditionVariableImpl.hpp>
|
||||
#include <Nazara/Core/Win32/MutexImpl.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
ConditionVariableImpl::ConditionVariableImpl()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_NT6
|
||||
InitializeConditionVariable(&m_cv);
|
||||
#else
|
||||
m_count = 0;
|
||||
m_events[BROADCAST] = CreateEvent(nullptr, true, false, nullptr); // manual-reset event
|
||||
m_events[SIGNAL] = CreateEvent(nullptr, false, false, nullptr); // auto-reset event
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !NAZARA_CORE_WINDOWS_NT6
|
||||
ConditionVariableImpl::~ConditionVariableImpl()
|
||||
{
|
||||
CloseHandle(m_events[BROADCAST]);
|
||||
CloseHandle(m_events[SIGNAL]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ConditionVariableImpl::Signal()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_NT6
|
||||
WakeConditionVariable(&m_cv);
|
||||
#else
|
||||
if (m_count > 0)
|
||||
SetEvent(m_events[SIGNAL]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::SignalAll()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_NT6
|
||||
WakeAllConditionVariable(&m_cv);
|
||||
#else
|
||||
if (m_count > 0)
|
||||
SetEvent(m_events[BROADCAST]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::Wait(MutexImpl* mutex)
|
||||
{
|
||||
Wait(mutex, INFINITE);
|
||||
}
|
||||
|
||||
bool ConditionVariableImpl::Wait(MutexImpl* mutex, UInt32 timeout)
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_NT6
|
||||
return SleepConditionVariableCS(&m_cv, &mutex->m_criticalSection, timeout) == TRUE;
|
||||
#else
|
||||
m_count++;
|
||||
|
||||
// It's ok to release the mutex here since Win32
|
||||
// manual-reset events maintain state when used with SetEvent.
|
||||
// This avoids the "lost wakeup" bug...
|
||||
LeaveCriticalSection(&mutex->m_criticalSection);
|
||||
|
||||
// Wait for either event to become signaled due to Signal being called or SignalAll being called.
|
||||
int result = WaitForMultipleObjects(2, m_events, false, timeout);
|
||||
|
||||
// Some thread called SignalAll
|
||||
if (--m_count == 0 && result == WAIT_OBJECT_0 + BROADCAST)
|
||||
// We're the last waiter to be notified or to stop waiting, so reset the manual event.
|
||||
ResetEvent(m_events[BROADCAST]);
|
||||
|
||||
// Reacquire the mutex.
|
||||
EnterCriticalSection(&mutex->m_criticalSection);
|
||||
|
||||
return result != WAIT_TIMEOUT;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// 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
|
||||
|
||||
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_CONDITIONVARIABLEIMPL_HPP
|
||||
#define NAZARA_CONDITIONVARIABLEIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <atomic>
|
||||
#include <windows.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class MutexImpl;
|
||||
|
||||
class ConditionVariableImpl
|
||||
{
|
||||
public:
|
||||
ConditionVariableImpl();
|
||||
#if NAZARA_CORE_WINDOWS_NT6
|
||||
~ConditionVariableImpl() = default;
|
||||
#else
|
||||
~ConditionVariableImpl();
|
||||
#endif
|
||||
|
||||
void Signal();
|
||||
void SignalAll();
|
||||
|
||||
void Wait(MutexImpl* mutex);
|
||||
bool Wait(MutexImpl* mutex, UInt32 timeout);
|
||||
|
||||
private:
|
||||
#if NAZARA_CORE_WINDOWS_NT6
|
||||
CONDITION_VARIABLE m_cv;
|
||||
#else
|
||||
enum
|
||||
{
|
||||
SIGNAL,
|
||||
BROADCAST,
|
||||
MAX_EVENTS
|
||||
};
|
||||
|
||||
std::atomic_uint m_count;
|
||||
HANDLE m_events[MAX_EVENTS];
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_CONDITIONVARIABLEIMPL_HPP
|
||||
@@ -1,122 +0,0 @@
|
||||
// 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/Win32/DirectoryImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <memory>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
DirectoryImpl::DirectoryImpl(const Directory* parent)
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
void DirectoryImpl::Close()
|
||||
{
|
||||
FindClose(m_handle);
|
||||
}
|
||||
|
||||
String DirectoryImpl::GetResultName() const
|
||||
{
|
||||
return String::Unicode(m_result.cFileName);
|
||||
}
|
||||
|
||||
UInt64 DirectoryImpl::GetResultSize() const
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
size.HighPart = m_result.nFileSizeHigh;
|
||||
size.LowPart = m_result.nFileSizeLow;
|
||||
|
||||
return size.QuadPart;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::IsResultDirectory() const
|
||||
{
|
||||
if (m_result.dwFileAttributes != INVALID_FILE_ATTRIBUTES)
|
||||
return (m_result.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::NextResult()
|
||||
{
|
||||
if (m_firstCall) // Nous devons ignorer le premier appel car FindFirstFile nous a déjà renvoyé des résultats
|
||||
{
|
||||
m_firstCall = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (FindNextFileW(m_handle, &m_result))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
if (GetLastError() != ERROR_NO_MORE_FILES)
|
||||
NazaraError("Unable to get next result: " + Error::GetLastSystemError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Open(const String& dirPath)
|
||||
{
|
||||
String searchPath = dirPath + "\\*";
|
||||
|
||||
m_handle = FindFirstFileW(searchPath.GetWideString().data(), &m_result);
|
||||
if (m_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
NazaraError("Unable to open directory: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_firstCall = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Create(const String& dirPath)
|
||||
{
|
||||
return (CreateDirectoryW(dirPath.GetWideString().data(), nullptr) != 0) || GetLastError() == ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Exists(const String& dirPath)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesW(dirPath.GetWideString().data());
|
||||
if (attributes != INVALID_FILE_ATTRIBUTES)
|
||||
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
String DirectoryImpl::GetCurrent()
|
||||
{
|
||||
String currentPath;
|
||||
std::unique_ptr<wchar_t[]> path(new wchar_t[MAX_PATH]);
|
||||
|
||||
unsigned int size = GetCurrentDirectoryW(MAX_PATH, path.get());
|
||||
if (size > MAX_PATH) // La taille prends en compte le caractère nul
|
||||
{
|
||||
path.reset(new wchar_t[size]);
|
||||
if (GetCurrentDirectoryW(size, path.get()) != 0)
|
||||
currentPath = String::Unicode(path.get());
|
||||
else
|
||||
NazaraError("Unable to get current directory: " + Error::GetLastSystemError());
|
||||
}
|
||||
else if (size == 0)
|
||||
NazaraError("Unable to get current directory: " + Error::GetLastSystemError());
|
||||
else
|
||||
currentPath = String::Unicode(path.get());
|
||||
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Remove(const String& dirPath)
|
||||
{
|
||||
bool success = RemoveDirectoryW(dirPath.GetWideString().data()) != 0;
|
||||
|
||||
DWORD error = GetLastError();
|
||||
return success || error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// 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_DIRECTORYIMPL_HPP
|
||||
#define NAZARA_DIRECTORYIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class Directory;
|
||||
class String;
|
||||
|
||||
class DirectoryImpl
|
||||
{
|
||||
public:
|
||||
DirectoryImpl(const Directory* parent);
|
||||
DirectoryImpl(const DirectoryImpl&) = delete;
|
||||
DirectoryImpl(DirectoryImpl&&) = delete; ///TODO
|
||||
~DirectoryImpl() = default;
|
||||
|
||||
void Close();
|
||||
|
||||
String GetResultName() const;
|
||||
UInt64 GetResultSize() const;
|
||||
|
||||
bool IsResultDirectory() const;
|
||||
|
||||
bool NextResult();
|
||||
|
||||
bool Open(const String& dirPath);
|
||||
|
||||
DirectoryImpl& operator=(const DirectoryImpl&) = delete;
|
||||
DirectoryImpl& operator=(DirectoryImpl&&) = delete; ///TODO
|
||||
|
||||
static bool Create(const String& dirPath);
|
||||
static bool Exists(const String& dirPath);
|
||||
static String GetCurrent();
|
||||
static bool Remove(const String& dirPath);
|
||||
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
WIN32_FIND_DATAW m_result;
|
||||
bool m_firstCall;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_DIRECTORYIMPL_HPP
|
||||
@@ -5,34 +5,39 @@
|
||||
#include <Nazara/Core/Win32/DynLibImpl.hpp>
|
||||
#include <Nazara/Core/DynLib.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Core/StringExt.hpp>
|
||||
#include <memory>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
DynLibImpl::DynLibImpl(DynLib* parent)
|
||||
DynLibImpl::DynLibImpl(DynLib*) :
|
||||
m_handle(nullptr)
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
DynLibFunc DynLibImpl::GetSymbol(const String& symbol, String* errorMessage) const
|
||||
DynLibImpl::~DynLibImpl()
|
||||
{
|
||||
DynLibFunc sym = reinterpret_cast<DynLibFunc>(GetProcAddress(m_handle, symbol.GetConstBuffer()));
|
||||
if (m_handle)
|
||||
FreeLibrary(m_handle);
|
||||
}
|
||||
|
||||
DynLibFunc DynLibImpl::GetSymbol(const char* symbol, std::string* errorMessage) const
|
||||
{
|
||||
DynLibFunc sym = reinterpret_cast<DynLibFunc>(GetProcAddress(m_handle, symbol));
|
||||
if (!sym)
|
||||
*errorMessage = Error::GetLastSystemError();
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
bool DynLibImpl::Load(const String& libraryPath, String* errorMessage)
|
||||
bool DynLibImpl::Load(const std::filesystem::path& libraryPath, std::string* errorMessage)
|
||||
{
|
||||
String path = libraryPath;
|
||||
if (!path.EndsWith(".dll"))
|
||||
std::filesystem::path path = libraryPath;
|
||||
if (path.extension() != ".dll")
|
||||
path += ".dll";
|
||||
|
||||
m_handle = LoadLibraryExW(path.GetWideString().data(), nullptr, (File::IsAbsolute(path)) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0);
|
||||
m_handle = LoadLibraryExW(ToWideString(path.generic_u8string()).data(), nullptr, (path.is_absolute()) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0);
|
||||
if (m_handle)
|
||||
return true;
|
||||
else
|
||||
@@ -41,10 +46,4 @@ namespace Nz
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DynLibImpl::Unload()
|
||||
{
|
||||
FreeLibrary(m_handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,23 +9,21 @@
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/DynLib.hpp>
|
||||
#include <filesystem>
|
||||
#include <windows.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class String;
|
||||
|
||||
class DynLibImpl
|
||||
{
|
||||
public:
|
||||
DynLibImpl(DynLib* m_parent);
|
||||
DynLibImpl(const DynLibImpl&) = delete;
|
||||
DynLibImpl(DynLibImpl&&) = delete; ///TODO?
|
||||
~DynLibImpl() = default;
|
||||
~DynLibImpl();
|
||||
|
||||
DynLibFunc GetSymbol(const String& symbol, String* errorMessage) const;
|
||||
bool Load(const String& libraryPath, String* errorMessage);
|
||||
void Unload();
|
||||
DynLibFunc GetSymbol(const char* symbol, std::string* errorMessage) const;
|
||||
bool Load(const std::filesystem::path& libraryPath, std::string* errorMessage);
|
||||
|
||||
DynLibImpl& operator=(const DynLibImpl&) = delete;
|
||||
DynLibImpl& operator=(DynLibImpl&&) = delete; ///TODO?
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <Nazara/Core/Win32/FileImpl.hpp>
|
||||
#include <Nazara/Core/CallOnExit.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/StringExt.hpp>
|
||||
#include <Nazara/Core/Win32/Time.hpp>
|
||||
#include <memory>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
@@ -18,9 +19,10 @@ namespace Nz
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
void FileImpl::Close()
|
||||
FileImpl::~FileImpl()
|
||||
{
|
||||
CloseHandle(m_handle);
|
||||
if (m_handle)
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
bool FileImpl::EndOfFile() const
|
||||
@@ -55,7 +57,7 @@ namespace Nz
|
||||
return position.QuadPart;
|
||||
}
|
||||
|
||||
bool FileImpl::Open(const String& filePath, OpenModeFlags mode)
|
||||
bool FileImpl::Open(const std::filesystem::path& filePath, OpenModeFlags mode)
|
||||
{
|
||||
DWORD access = 0;
|
||||
DWORD shareMode = FILE_SHARE_READ;
|
||||
@@ -87,7 +89,7 @@ namespace Nz
|
||||
if ((mode & OpenMode_Lock) == 0)
|
||||
shareMode |= FILE_SHARE_WRITE;
|
||||
|
||||
m_handle = CreateFileW(filePath.GetWideString().data(), access, shareMode, nullptr, openMode, 0, nullptr);
|
||||
m_handle = CreateFileW(ToWideString(filePath.generic_u8string()).data(), access, shareMode, nullptr, openMode, 0, nullptr);
|
||||
return m_handle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
@@ -197,118 +199,4 @@ namespace Nz
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
bool FileImpl::Copy(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
if (CopyFileW(sourcePath.GetWideString().data(), targetPath.GetWideString().data(), false))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to copy file: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileImpl::Delete(const String& filePath)
|
||||
{
|
||||
if (DeleteFileW(filePath.GetWideString().data()))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileImpl::Exists(const String& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
CloseHandle(handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
time_t FileImpl::GetCreationTime(const String& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME creationTime;
|
||||
if (!GetFileTime(handle, &creationTime, nullptr, nullptr))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
|
||||
NazaraError("Unable to get creation time: " + Error::GetLastSystemError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return FileTimeToTime(&creationTime);
|
||||
}
|
||||
|
||||
time_t FileImpl::GetLastAccessTime(const String& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME accessTime;
|
||||
if (!GetFileTime(handle, nullptr, &accessTime, nullptr))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
|
||||
NazaraError("Unable to get last access time: " + Error::GetLastSystemError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return FileTimeToTime(&accessTime);
|
||||
}
|
||||
|
||||
time_t FileImpl::GetLastWriteTime(const String& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME writeTime;
|
||||
if (!GetFileTime(handle, nullptr, nullptr, &writeTime))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
|
||||
NazaraError("Unable to get last write time: " + Error::GetLastSystemError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return FileTimeToTime(&writeTime);
|
||||
}
|
||||
|
||||
UInt64 FileImpl::GetSize(const String& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(handle, &fileSize))
|
||||
fileSize.QuadPart = 0;
|
||||
|
||||
CloseHandle(handle);
|
||||
return fileSize.QuadPart;
|
||||
}
|
||||
|
||||
bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
if (MoveFileExW(sourcePath.GetWideString().data(), targetPath.GetWideString().data(), MOVEFILE_COPY_ALLOWED))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Unable to rename file: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,12 @@ namespace Nz
|
||||
FileImpl(const File* parent);
|
||||
FileImpl(const FileImpl&) = delete;
|
||||
FileImpl(FileImpl&&) = delete; ///TODO
|
||||
~FileImpl() = default;
|
||||
~FileImpl();
|
||||
|
||||
void Close();
|
||||
bool EndOfFile() const;
|
||||
void Flush();
|
||||
UInt64 GetCursorPos() const;
|
||||
bool Open(const String& filePath, OpenModeFlags mode);
|
||||
bool Open(const std::filesystem::path& filePath, OpenModeFlags mode);
|
||||
std::size_t Read(void* buffer, std::size_t size);
|
||||
bool SetCursorPos(CursorPosition pos, Int64 offset);
|
||||
bool SetSize(UInt64 size);
|
||||
@@ -38,15 +37,6 @@ namespace Nz
|
||||
FileImpl& operator=(const FileImpl&) = delete;
|
||||
FileImpl& operator=(FileImpl&&) = delete; ///TODO
|
||||
|
||||
static bool Copy(const String& sourcePath, const String& targetPath);
|
||||
static bool Delete(const String& filePath);
|
||||
static bool Exists(const String& filePath);
|
||||
static time_t GetCreationTime(const String& filePath);
|
||||
static time_t GetLastAccessTime(const String& filePath);
|
||||
static time_t GetLastWriteTime(const String& filePath);
|
||||
static UInt64 GetSize(const String& filePath);
|
||||
static bool Rename(const String& sourcePath, const String& targetPath);
|
||||
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
mutable bool m_endOfFile;
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// 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/Win32/MutexImpl.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_CS_SPINLOCKS > 0
|
||||
InitializeCriticalSectionAndSpinCount(&m_criticalSection, NAZARA_CORE_WINDOWS_CS_SPINLOCKS);
|
||||
#else
|
||||
InitializeCriticalSection(&m_criticalSection);
|
||||
#endif
|
||||
}
|
||||
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
DeleteCriticalSection(&m_criticalSection);
|
||||
}
|
||||
|
||||
void MutexImpl::Lock()
|
||||
{
|
||||
EnterCriticalSection(&m_criticalSection);
|
||||
}
|
||||
|
||||
bool MutexImpl::TryLock()
|
||||
{
|
||||
return TryEnterCriticalSection(&m_criticalSection) != 0;
|
||||
}
|
||||
|
||||
void MutexImpl::Unlock()
|
||||
{
|
||||
LeaveCriticalSection(&m_criticalSection);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// 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_MUTEXIMPL_HPP
|
||||
#define NAZARA_MUTEXIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class MutexImpl
|
||||
{
|
||||
friend class ConditionVariableImpl;
|
||||
|
||||
public:
|
||||
MutexImpl();
|
||||
~MutexImpl();
|
||||
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION m_criticalSection;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_MUTEXIMPL_HPP
|
||||
@@ -1,67 +0,0 @@
|
||||
// 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/Win32/SemaphoreImpl.hpp>
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <limits>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
SemaphoreImpl::SemaphoreImpl(unsigned int count)
|
||||
{
|
||||
m_semaphore = CreateSemaphoreW(nullptr, count, std::numeric_limits<LONG>::max(), nullptr);
|
||||
if (!m_semaphore)
|
||||
NazaraError("Failed to create semaphore: " + Error::GetLastSystemError());
|
||||
}
|
||||
|
||||
SemaphoreImpl::~SemaphoreImpl()
|
||||
{
|
||||
CloseHandle(m_semaphore);
|
||||
}
|
||||
|
||||
unsigned int SemaphoreImpl::GetCount() const
|
||||
{
|
||||
LONG count;
|
||||
ReleaseSemaphore(m_semaphore, 0, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void SemaphoreImpl::Post()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!ReleaseSemaphore(m_semaphore, 1, nullptr))
|
||||
NazaraError("Failed to release semaphore: " + Error::GetLastSystemError());
|
||||
#else
|
||||
ReleaseSemaphore(m_semaphore, 1, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SemaphoreImpl::Wait()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (WaitForSingleObject(m_semaphore, INFINITE) == WAIT_FAILED)
|
||||
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||
#else
|
||||
WaitForSingleObject(m_semaphore, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SemaphoreImpl::Wait(UInt32 timeout)
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
DWORD result = WaitForSingleObject(m_semaphore, timeout);
|
||||
if (result == WAIT_FAILED)
|
||||
{
|
||||
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return result == WAIT_OBJECT_0;
|
||||
#else
|
||||
return WaitForSingleObject(m_semaphore, timeout) == WAIT_OBJECT_0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// 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_SEMAPHOREIMPL_HPP
|
||||
#define NAZARA_SEMAPHOREIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class SemaphoreImpl
|
||||
{
|
||||
public:
|
||||
SemaphoreImpl(unsigned int count);
|
||||
~SemaphoreImpl();
|
||||
|
||||
unsigned int GetCount() const;
|
||||
void Post();
|
||||
void Wait();
|
||||
bool Wait(UInt32 timeout);
|
||||
|
||||
private:
|
||||
HANDLE m_semaphore;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_SEMAPHOREIMPL_HPP
|
||||
@@ -1,122 +0,0 @@
|
||||
// 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/Win32/ThreadImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Functor.hpp>
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
// Windows 10, version 1607 brought SetThreadDescription in order to name a thread
|
||||
using SetThreadDescriptionFunc = HRESULT(WINAPI*)(HANDLE hThread, PCWSTR lpThreadDescription);
|
||||
|
||||
#ifdef NAZARA_COMPILER_MSVC
|
||||
namespace
|
||||
{
|
||||
#pragma pack(push,8)
|
||||
struct THREADNAME_INFO
|
||||
{
|
||||
DWORD dwType;
|
||||
LPCSTR szName;
|
||||
DWORD dwThreadID;
|
||||
DWORD dwFlags;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
||||
#endif
|
||||
|
||||
ThreadImpl::ThreadImpl(Functor* functor)
|
||||
{
|
||||
unsigned int threadId;
|
||||
m_handle = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, &ThreadImpl::ThreadProc, functor, 0, &threadId));
|
||||
if (!m_handle)
|
||||
NazaraInternalError("Failed to create thread: " + Error::GetLastSystemError());
|
||||
|
||||
m_threadId = threadId;
|
||||
}
|
||||
|
||||
void ThreadImpl::Detach()
|
||||
{
|
||||
// http://stackoverflow.com/questions/418742/is-it-reasonable-to-call-closehandle-on-a-thread-before-it-terminates
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
void ThreadImpl::Join()
|
||||
{
|
||||
WaitForSingleObject(m_handle, INFINITE);
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
void ThreadImpl::SetName(const Nz::String& name)
|
||||
{
|
||||
SetThreadName(m_handle, name);
|
||||
}
|
||||
|
||||
void ThreadImpl::SetCurrentName(const Nz::String& name)
|
||||
{
|
||||
SetThreadName(::GetCurrentThread(), name);
|
||||
}
|
||||
|
||||
void ThreadImpl::Sleep(UInt32 time)
|
||||
{
|
||||
::Sleep(time);
|
||||
}
|
||||
|
||||
void ThreadImpl::RaiseThreadNameException(DWORD threadId, const char* threadName)
|
||||
{
|
||||
#ifdef NAZARA_COMPILER_MSVC
|
||||
if (!::IsDebuggerPresent())
|
||||
return;
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||
constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
|
||||
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
info.dwThreadID = threadId;
|
||||
info.dwFlags = 0;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 6320 6322)
|
||||
__try
|
||||
{
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
NazaraWarning("SetThreadDescription is not supported and threadname exception is only supported with MSVC");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThreadImpl::SetThreadName(HANDLE threadHandle, const Nz::String& name)
|
||||
{
|
||||
// Try to use SetThreadDescription if available
|
||||
static SetThreadDescriptionFunc SetThreadDescription = reinterpret_cast<SetThreadDescriptionFunc>(::GetProcAddress(::GetModuleHandleW(L"Kernel32.dll"), "SetThreadDescription"));
|
||||
if (SetThreadDescription)
|
||||
SetThreadDescription(threadHandle, name.GetWideString().data());
|
||||
else
|
||||
RaiseThreadNameException(::GetThreadId(threadHandle), name.GetConstBuffer());
|
||||
}
|
||||
|
||||
unsigned int __stdcall ThreadImpl::ThreadProc(void* userdata)
|
||||
{
|
||||
Functor* func = static_cast<Functor*>(userdata);
|
||||
func->Run();
|
||||
delete func;
|
||||
|
||||
/*
|
||||
En C++, il vaut mieux retourner depuis la fonction que de quitter le thread explicitement
|
||||
Source : http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659(v=vs.85).aspx
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
// 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
|
||||
|
||||
// Inspiré du code de la SFML par Laurent Gomila
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_THREADIMPL_HPP
|
||||
#define NAZARA_THREADIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct Functor;
|
||||
|
||||
class ThreadImpl
|
||||
{
|
||||
public:
|
||||
ThreadImpl(Functor* threadFunc);
|
||||
|
||||
void Detach();
|
||||
void Join();
|
||||
void SetName(const Nz::String& name);
|
||||
|
||||
static void SetCurrentName(const Nz::String& name);
|
||||
static void Sleep(UInt32 time);
|
||||
|
||||
private:
|
||||
static void RaiseThreadNameException(DWORD threadId, const char* threadName);
|
||||
static void SetThreadName(HANDLE threadHandle, const Nz::String& name);
|
||||
static unsigned int __stdcall ThreadProc(void* userdata);
|
||||
|
||||
DWORD m_threadId;
|
||||
HANDLE m_handle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_THREADIMPL_HPP
|
||||
@@ -22,13 +22,14 @@ namespace Nz
|
||||
{
|
||||
const ParameterList& matData = model->GetMesh()->GetMaterialData(i);
|
||||
|
||||
String filePath;
|
||||
if (matData.GetStringParameter(MaterialData::FilePath, &filePath))
|
||||
String path;
|
||||
if (matData.GetStringParameter(MaterialData::FilePath, &path))
|
||||
{
|
||||
if (!File::Exists(filePath))
|
||||
std::filesystem::path filePath = path.ToStdString();
|
||||
if (!std::filesystem::exists(filePath))
|
||||
{
|
||||
NazaraWarning("Shader name does not refer to an existing file, \".tga\" is used by default");
|
||||
filePath += ".tga";
|
||||
filePath.replace_extension(".tga");
|
||||
}
|
||||
|
||||
if (MaterialRef material = Material::LoadFromFile(filePath, parameters.material))
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Nz
|
||||
bool isEnabled;
|
||||
double dValue;
|
||||
long long iValue;
|
||||
String path;
|
||||
Nz::String path;
|
||||
|
||||
ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled, true);
|
||||
|
||||
@@ -247,22 +247,22 @@ namespace Nz
|
||||
|
||||
// Textures
|
||||
if (matParams.loadAlphaMap && matData.GetStringParameter(MaterialData::AlphaTexturePath, &path))
|
||||
SetAlphaMap(path);
|
||||
SetAlphaMap(path.ToStdString());
|
||||
|
||||
if (matParams.loadDiffuseMap && matData.GetStringParameter(MaterialData::DiffuseTexturePath, &path))
|
||||
SetDiffuseMap(path);
|
||||
SetDiffuseMap(path.ToStdString());
|
||||
|
||||
if (matParams.loadEmissiveMap && matData.GetStringParameter(MaterialData::EmissiveTexturePath, &path))
|
||||
SetEmissiveMap(path);
|
||||
SetEmissiveMap(path.ToStdString());
|
||||
|
||||
if (matParams.loadHeightMap && matData.GetStringParameter(MaterialData::HeightTexturePath, &path))
|
||||
SetHeightMap(path);
|
||||
SetHeightMap(path.ToStdString());
|
||||
|
||||
if (matParams.loadNormalMap && matData.GetStringParameter(MaterialData::NormalTexturePath, &path))
|
||||
SetNormalMap(path);
|
||||
SetNormalMap(path.ToStdString());
|
||||
|
||||
if (matParams.loadSpecularMap && matData.GetStringParameter(MaterialData::SpecularTexturePath, &path))
|
||||
SetSpecularMap(path);
|
||||
SetSpecularMap(path.ToStdString());
|
||||
|
||||
SetShader(matParams.shaderName);
|
||||
}
|
||||
@@ -329,44 +329,44 @@ namespace Nz
|
||||
// Textures
|
||||
if (HasAlphaMap())
|
||||
{
|
||||
const String& path = GetAlphaMap()->GetFilePath();
|
||||
if (!path.IsEmpty())
|
||||
matData->SetParameter(MaterialData::AlphaTexturePath, path);
|
||||
const std::filesystem::path& path = GetAlphaMap()->GetFilePath();
|
||||
if (!path.empty())
|
||||
matData->SetParameter(MaterialData::AlphaTexturePath, path.generic_u8string());
|
||||
}
|
||||
|
||||
if (HasDiffuseMap())
|
||||
{
|
||||
const String& path = GetDiffuseMap()->GetFilePath();
|
||||
if (!path.IsEmpty())
|
||||
matData->SetParameter(MaterialData::DiffuseTexturePath, path);
|
||||
const std::filesystem::path& path = GetDiffuseMap()->GetFilePath();
|
||||
if (!path.empty())
|
||||
matData->SetParameter(MaterialData::DiffuseTexturePath, path.generic_u8string());
|
||||
}
|
||||
|
||||
if (HasEmissiveMap())
|
||||
{
|
||||
const String& path = GetEmissiveMap()->GetFilePath();
|
||||
if (!path.IsEmpty())
|
||||
matData->SetParameter(MaterialData::EmissiveTexturePath, path);
|
||||
const std::filesystem::path& path = GetEmissiveMap()->GetFilePath();
|
||||
if (!path.empty())
|
||||
matData->SetParameter(MaterialData::EmissiveTexturePath, path.generic_u8string());
|
||||
}
|
||||
|
||||
if (HasHeightMap())
|
||||
{
|
||||
const String& path = GetHeightMap()->GetFilePath();
|
||||
if (!path.IsEmpty())
|
||||
matData->SetParameter(MaterialData::HeightTexturePath, path);
|
||||
const std::filesystem::path& path = GetHeightMap()->GetFilePath();
|
||||
if (!path.empty())
|
||||
matData->SetParameter(MaterialData::HeightTexturePath, path.generic_u8string());
|
||||
}
|
||||
|
||||
if (HasNormalMap())
|
||||
{
|
||||
const String& path = GetNormalMap()->GetFilePath();
|
||||
if (!path.IsEmpty())
|
||||
matData->SetParameter(MaterialData::NormalTexturePath, path);
|
||||
const std::filesystem::path& path = GetNormalMap()->GetFilePath();
|
||||
if (!path.empty())
|
||||
matData->SetParameter(MaterialData::NormalTexturePath, path.generic_u8string());
|
||||
}
|
||||
|
||||
if (HasSpecularMap())
|
||||
{
|
||||
const String& path = GetSpecularMap()->GetFilePath();
|
||||
if (!path.IsEmpty())
|
||||
matData->SetParameter(MaterialData::SpecularTexturePath, path);
|
||||
const std::filesystem::path& path = GetSpecularMap()->GetFilePath();
|
||||
if (!path.empty())
|
||||
matData->SetParameter(MaterialData::SpecularTexturePath, path.generic_u8string());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
#include <Nazara/Renderer/UberShaderPreprocessor.hpp>
|
||||
#include <filesystem>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
@@ -29,7 +30,7 @@ namespace Nz
|
||||
#include <Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert.h>
|
||||
};
|
||||
|
||||
void OverrideShader(const String& path, String* source)
|
||||
void OverrideShader(const std::filesystem::path& path, String* source)
|
||||
{
|
||||
ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled);
|
||||
|
||||
@@ -46,7 +47,7 @@ namespace Nz
|
||||
|
||||
*source = shaderSource;
|
||||
|
||||
NazaraNotice(path + " will be used to override built-in shader");
|
||||
NazaraNotice(path.generic_u8string() + " will be used to override built-in shader");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if there is no subMesh with that name
|
||||
* \remark Produces a NazaraError if material is invalid
|
||||
*/
|
||||
const MaterialRef& Model::GetMaterial(const String& subMeshName) const
|
||||
const MaterialRef& Model::GetMaterial(const std::string& subMeshName) const
|
||||
{
|
||||
NazaraAssert(m_mesh, "Model has no mesh");
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if there is no subMesh with that name
|
||||
* \remark Produces a NazaraError if material index is invalid
|
||||
*/
|
||||
const MaterialRef& Model::GetMaterial(std::size_t skinIndex, const String& subMeshName) const
|
||||
const MaterialRef& Model::GetMaterial(std::size_t skinIndex, const std::string& subMeshName) const
|
||||
{
|
||||
NazaraAssert(m_mesh, "Model has no mesh");
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if material index is invalid
|
||||
*/
|
||||
|
||||
bool Model::SetMaterial(const String& subMeshName, MaterialRef material)
|
||||
bool Model::SetMaterial(const std::string& subMeshName, MaterialRef material)
|
||||
{
|
||||
SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName);
|
||||
if (!subMesh)
|
||||
@@ -185,7 +185,7 @@ namespace Nz
|
||||
* \remark Produces a NazaraError if there is no subMesh with that name
|
||||
* \remark Produces a NazaraError if material index is invalid
|
||||
*/
|
||||
bool Model::SetMaterial(std::size_t skinIndex, const String& subMeshName, MaterialRef material)
|
||||
bool Model::SetMaterial(std::size_t skinIndex, const std::string& subMeshName, MaterialRef material)
|
||||
{
|
||||
SubMesh* subMesh = m_mesh->GetSubMesh(subMeshName);
|
||||
if (!subMesh)
|
||||
@@ -239,7 +239,7 @@ namespace Nz
|
||||
* \param filePath Path to the file
|
||||
* \param params Parameters for the model
|
||||
*/
|
||||
ModelRef Model::LoadFromFile(const String& filePath, const ModelParameters& params)
|
||||
ModelRef Model::LoadFromFile(const std::filesystem::path& filePath, const ModelParameters& params)
|
||||
{
|
||||
return ModelLoader::LoadFromFile(filePath, params);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Nz
|
||||
*
|
||||
* \return True if the material was found or loaded from its name/path, false if it couldn't
|
||||
*/
|
||||
bool Sprite::SetMaterial(String materialName, bool resizeSprite)
|
||||
bool Sprite::SetMaterial(std::string materialName, bool resizeSprite)
|
||||
{
|
||||
MaterialRef material = MaterialLibrary::Query(materialName);
|
||||
if (!material)
|
||||
@@ -85,7 +85,7 @@ namespace Nz
|
||||
*
|
||||
* \return True if the material was found or loaded from its name/path, false if it couldn't
|
||||
*/
|
||||
bool Sprite::SetMaterial(std::size_t skinIndex, String materialName, bool resizeSprite)
|
||||
bool Sprite::SetMaterial(std::size_t skinIndex, std::string materialName, bool resizeSprite)
|
||||
{
|
||||
MaterialRef material = MaterialLibrary::Query(materialName);
|
||||
if (!material)
|
||||
@@ -114,7 +114,7 @@ namespace Nz
|
||||
*
|
||||
* \remark The sprite material gets copied to prevent accidentally changing other drawable materials
|
||||
*/
|
||||
bool Sprite::SetTexture(String textureName, bool resizeSprite)
|
||||
bool Sprite::SetTexture(std::string textureName, bool resizeSprite)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
if (!texture)
|
||||
@@ -144,7 +144,7 @@ namespace Nz
|
||||
*
|
||||
* \remark The sprite material gets copied to prevent accidentally changing other drawable materials
|
||||
*/
|
||||
bool Sprite::SetTexture(std::size_t skinIndex, String textureName, bool resizeSprite)
|
||||
bool Sprite::SetTexture(std::size_t skinIndex, std::string textureName, bool resizeSprite)
|
||||
{
|
||||
TextureRef texture = TextureLibrary::Query(textureName);
|
||||
if (!texture)
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Lua module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Lua/Config.hpp>
|
||||
#if NAZARA_LUA_MANAGE_MEMORY
|
||||
|
||||
#include <Nazara/Core/MemoryManager.hpp>
|
||||
#include <new> // Nécessaire ?
|
||||
|
||||
void* operator new(std::size_t size)
|
||||
{
|
||||
return Nz::MemoryManager::Allocate(size, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size)
|
||||
{
|
||||
return Nz::MemoryManager::Allocate(size, true);
|
||||
}
|
||||
|
||||
void operator delete(void* pointer) noexcept
|
||||
{
|
||||
Nz::MemoryManager::Free(pointer, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* pointer) noexcept
|
||||
{
|
||||
Nz::MemoryManager::Free(pointer, true);
|
||||
}
|
||||
|
||||
#endif // NAZARA_LUA_MANAGE_MEMORY
|
||||
@@ -1,63 +0,0 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Lua scripting module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Lua/Lua.hpp>
|
||||
#include <Nazara/Core/Core.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Nazara/Lua/Config.hpp>
|
||||
#include <Nazara/Lua/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
bool Lua::Initialize()
|
||||
{
|
||||
if (s_moduleReferenceCounter > 0)
|
||||
{
|
||||
s_moduleReferenceCounter++;
|
||||
return true; // Déjà initialisé
|
||||
}
|
||||
|
||||
// Initialisation des dépendances
|
||||
if (!Core::Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize core module");
|
||||
return false;
|
||||
}
|
||||
|
||||
s_moduleReferenceCounter++;
|
||||
|
||||
// Initialisation du module
|
||||
|
||||
NazaraNotice("Initialized: Lua module");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Lua::IsInitialized()
|
||||
{
|
||||
return s_moduleReferenceCounter != 0;
|
||||
}
|
||||
|
||||
void Lua::Uninitialize()
|
||||
{
|
||||
if (s_moduleReferenceCounter != 1)
|
||||
{
|
||||
// Le module est soit encore utilisé, soit pas initialisé
|
||||
if (s_moduleReferenceCounter > 1)
|
||||
s_moduleReferenceCounter--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Libération du module
|
||||
s_moduleReferenceCounter = 0;
|
||||
|
||||
NazaraNotice("Uninitialized: Lua module");
|
||||
|
||||
// Libération des dépendances
|
||||
Core::Uninitialize();
|
||||
}
|
||||
|
||||
unsigned int Lua::s_moduleReferenceCounter = 0;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Lua scripting module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Lua/LuaCoroutine.hpp>
|
||||
#include <Lua/lua.h>
|
||||
#include <Nazara/Lua/LuaInstance.hpp>
|
||||
#include <Nazara/Lua/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
LuaCoroutine::LuaCoroutine(lua_State* internalState, int refIndex) :
|
||||
LuaState(internalState),
|
||||
m_ref(refIndex)
|
||||
{
|
||||
}
|
||||
|
||||
LuaCoroutine::~LuaCoroutine()
|
||||
{
|
||||
if (m_ref >= 0)
|
||||
DestroyReference(m_ref);
|
||||
}
|
||||
|
||||
bool LuaCoroutine::CanResume() const
|
||||
{
|
||||
return lua_status(m_state) == LUA_YIELD;
|
||||
}
|
||||
|
||||
Ternary LuaCoroutine::Resume(unsigned int argCount)
|
||||
{
|
||||
LuaInstance& instance = GetInstance(m_state);
|
||||
if (instance.m_level++ == 0)
|
||||
instance.m_clock.Restart();
|
||||
|
||||
int status = lua_resume(m_state, nullptr, argCount);
|
||||
instance.m_level--;
|
||||
|
||||
if (status == LUA_OK)
|
||||
return Ternary_True;
|
||||
else if (status == LUA_YIELD)
|
||||
return Ternary_Unknown;
|
||||
else
|
||||
{
|
||||
m_lastError = ToString(-1);
|
||||
Pop();
|
||||
return Ternary_False;
|
||||
}
|
||||
}
|
||||
|
||||
bool LuaCoroutine::Run(int argCount, int /*resultCount*/, int /*errHandler*/)
|
||||
{
|
||||
return Resume(argCount) != Ternary_False;
|
||||
}
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Lua scripting module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Lua/LuaInstance.hpp>
|
||||
#include <Lua/lauxlib.h>
|
||||
#include <Lua/lua.h>
|
||||
#include <Lua/lualib.h>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Lua/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
int AtPanic(lua_State* internalState)
|
||||
{
|
||||
String lastError(lua_tostring(internalState, -1));
|
||||
|
||||
throw std::runtime_error("Lua panic: " + lastError.ToStdString());
|
||||
}
|
||||
}
|
||||
|
||||
LuaInstance::LuaInstance() :
|
||||
LuaState(nullptr),
|
||||
m_memoryLimit(0),
|
||||
m_memoryUsage(0),
|
||||
m_timeLimit(1000),
|
||||
m_level(0)
|
||||
{
|
||||
m_state = lua_newstate(MemoryAllocator, this);
|
||||
lua_atpanic(m_state, AtPanic);
|
||||
lua_sethook(m_state, TimeLimiter, LUA_MASKCOUNT, 1000);
|
||||
}
|
||||
|
||||
LuaInstance::LuaInstance(LuaInstance&& instance) :
|
||||
LuaState(std::move(instance))
|
||||
{
|
||||
std::swap(m_memoryLimit, instance.m_memoryLimit);
|
||||
std::swap(m_memoryUsage, instance.m_memoryUsage);
|
||||
std::swap(m_timeLimit, instance.m_timeLimit);
|
||||
std::swap(m_clock, instance.m_clock);
|
||||
std::swap(m_level, instance.m_level);
|
||||
|
||||
if (m_state)
|
||||
lua_setallocf(m_state, MemoryAllocator, this);
|
||||
|
||||
if (instance.m_state)
|
||||
lua_setallocf(instance.m_state, MemoryAllocator, &instance);
|
||||
}
|
||||
|
||||
LuaInstance::~LuaInstance()
|
||||
{
|
||||
if (m_state)
|
||||
lua_close(m_state);
|
||||
}
|
||||
|
||||
void LuaInstance::LoadLibraries(LuaLibFlags libFlags)
|
||||
{
|
||||
// From luaL_openlibs
|
||||
std::array<luaL_Reg, LuaLib_Max + 1 + 1> libs;
|
||||
std::size_t libCount = 0;
|
||||
|
||||
libs[libCount++] = { "_G", luaopen_base };
|
||||
|
||||
if (libFlags & LuaLib_Coroutine)
|
||||
libs[libCount++] = { LUA_COLIBNAME, luaopen_coroutine };
|
||||
|
||||
if (libFlags & LuaLib_Debug)
|
||||
libs[libCount++] = { LUA_DBLIBNAME, luaopen_debug };
|
||||
|
||||
if (libFlags & LuaLib_Io)
|
||||
libs[libCount++] = { LUA_IOLIBNAME, luaopen_io };
|
||||
|
||||
if (libFlags & LuaLib_Math)
|
||||
libs[libCount++] = { LUA_MATHLIBNAME, luaopen_math };
|
||||
|
||||
if (libFlags & LuaLib_Os)
|
||||
libs[libCount++] = { LUA_OSLIBNAME, luaopen_os };
|
||||
|
||||
if (libFlags & LuaLib_Package)
|
||||
libs[libCount++] = { LUA_LOADLIBNAME, luaopen_package };
|
||||
|
||||
if (libFlags & LuaLib_String)
|
||||
libs[libCount++] = { LUA_STRLIBNAME, luaopen_string };
|
||||
|
||||
if (libFlags & LuaLib_Table)
|
||||
libs[libCount++] = { LUA_TABLIBNAME, luaopen_table };
|
||||
|
||||
if (libFlags & LuaLib_Utf8)
|
||||
libs[libCount++] = { LUA_UTF8LIBNAME, luaopen_utf8 };
|
||||
|
||||
for (std::size_t i = 0; i < libCount; ++i)
|
||||
{
|
||||
luaL_requiref(m_state, libs[i].name, libs[i].func, 1);
|
||||
lua_pop(m_state, 1); /* remove lib */
|
||||
}
|
||||
}
|
||||
|
||||
LuaInstance& LuaInstance::operator=(LuaInstance&& instance)
|
||||
{
|
||||
LuaState::operator=(std::move(instance));
|
||||
|
||||
std::swap(m_memoryLimit, instance.m_memoryLimit);
|
||||
std::swap(m_memoryUsage, instance.m_memoryUsage);
|
||||
std::swap(m_timeLimit, instance.m_timeLimit);
|
||||
std::swap(m_clock, instance.m_clock);
|
||||
std::swap(m_level, instance.m_level);
|
||||
|
||||
if (m_state)
|
||||
lua_setallocf(m_state, MemoryAllocator, this);
|
||||
|
||||
if (instance.m_state)
|
||||
lua_setallocf(instance.m_state, MemoryAllocator, &instance);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void* LuaInstance::MemoryAllocator(void* ud, void* ptr, std::size_t osize, std::size_t nsize)
|
||||
{
|
||||
LuaInstance* instance = static_cast<LuaInstance*>(ud);
|
||||
std::size_t memoryLimit = instance->GetMemoryLimit();
|
||||
std::size_t memoryUsage = instance->GetMemoryUsage();
|
||||
|
||||
if (nsize == 0)
|
||||
{
|
||||
assert(memoryUsage >= osize);
|
||||
|
||||
instance->SetMemoryUsage(memoryUsage - osize);
|
||||
std::free(ptr);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t usage = memoryUsage + nsize;
|
||||
if (ptr)
|
||||
usage -= osize;
|
||||
|
||||
if (memoryLimit != 0 && usage > memoryLimit)
|
||||
{
|
||||
NazaraError("Lua memory usage is over memory limit (" + String::Number(usage) + " > " + String::Number(memoryLimit) + ')');
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
instance->SetMemoryUsage(usage);
|
||||
|
||||
return std::realloc(ptr, nsize);
|
||||
}
|
||||
}
|
||||
|
||||
void LuaInstance::TimeLimiter(lua_State* internalState, lua_Debug* debug)
|
||||
{
|
||||
NazaraUnused(debug);
|
||||
|
||||
LuaInstance* instance;
|
||||
lua_getallocf(internalState, reinterpret_cast<void**>(&instance));
|
||||
|
||||
if (instance->m_clock.GetMilliseconds() > instance->GetTimeLimit())
|
||||
luaL_error(internalState, "maximum execution time exceeded");
|
||||
}
|
||||
}
|
||||
@@ -1,875 +0,0 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Lua scripting module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Lua/LuaState.hpp>
|
||||
#include <Lua/lauxlib.h>
|
||||
#include <Lua/lua.h>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/MemoryHelper.hpp>
|
||||
#include <Nazara/Core/MemoryView.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <Nazara/Lua/LuaCoroutine.hpp>
|
||||
#include <Nazara/Lua/LuaInstance.hpp>
|
||||
#include <Nazara/Lua/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
LuaType FromLuaType(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LUA_TBOOLEAN:
|
||||
return LuaType_Boolean;
|
||||
|
||||
case LUA_TFUNCTION:
|
||||
return LuaType_Function;
|
||||
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
return LuaType_LightUserdata;
|
||||
|
||||
case LUA_TNIL:
|
||||
return LuaType_Nil;
|
||||
|
||||
case LUA_TNONE:
|
||||
return LuaType_None;
|
||||
|
||||
case LUA_TNUMBER:
|
||||
return LuaType_Number;
|
||||
|
||||
case LUA_TSTRING:
|
||||
return LuaType_String;
|
||||
|
||||
case LUA_TTABLE:
|
||||
return LuaType_Table;
|
||||
|
||||
case LUA_TTHREAD:
|
||||
return LuaType_Thread;
|
||||
|
||||
case LUA_TUSERDATA:
|
||||
return LuaType_Userdata;
|
||||
|
||||
default:
|
||||
return LuaType_None;
|
||||
}
|
||||
}
|
||||
|
||||
struct StreamData
|
||||
{
|
||||
Stream* stream;
|
||||
char buffer[NAZARA_CORE_FILE_BUFFERSIZE];
|
||||
};
|
||||
|
||||
const char* StreamReader(lua_State* internalState, void* data, std::size_t* size)
|
||||
{
|
||||
NazaraUnused(internalState);
|
||||
|
||||
StreamData* streamData = static_cast<StreamData*>(data);
|
||||
|
||||
if (streamData->stream->EndOfStream())
|
||||
return nullptr;
|
||||
else
|
||||
{
|
||||
*size = streamData->stream->Read(streamData->buffer, NAZARA_CORE_FILE_BUFFERSIZE);
|
||||
return streamData->buffer;
|
||||
}
|
||||
}
|
||||
|
||||
int s_comparisons[] = {
|
||||
LUA_OPEQ, // LuaComparison_Equality
|
||||
LUA_OPLT, // LuaComparison_Less
|
||||
LUA_OPLE // LuaComparison_LessOrEqual
|
||||
};
|
||||
|
||||
static_assert(sizeof(s_comparisons)/sizeof(int) == LuaComparison_Max+1, "Lua comparison array is incomplete");
|
||||
|
||||
int s_operations[] = {
|
||||
LUA_OPADD, // LuaOperation_Addition
|
||||
LUA_OPBAND, // LuaOperation_BitwiseAnd
|
||||
LUA_OPSHL, // LuaOperation_BitwiseLeftShift
|
||||
LUA_OPBNOT, // LuaOperation_BitwiseNot
|
||||
LUA_OPBOR, // LuaOperation_BitwiseOr
|
||||
LUA_OPSHR, // LuaOperation_BitwiseRightShift
|
||||
LUA_OPBXOR, // LuaOperation_BitwiseXOr
|
||||
LUA_OPDIV, // LuaOperation_Division
|
||||
LUA_OPPOW, // LuaOperation_Exponentiation
|
||||
LUA_OPIDIV, // LuaOperation_FloorDivision
|
||||
LUA_OPMUL, // LuaOperation_Multiplication
|
||||
LUA_OPMOD, // LuaOperation_Modulo
|
||||
LUA_OPUNM, // LuaOperation_Negation
|
||||
LUA_OPSUB // LuaOperation_Substraction
|
||||
};
|
||||
|
||||
static_assert(sizeof(s_operations)/sizeof(int) == LuaOperation_Max+1, "Lua operation array is incomplete");
|
||||
|
||||
int s_types[] = {
|
||||
LUA_TBOOLEAN, // LuaType_Boolean
|
||||
LUA_TFUNCTION, // LuaType_Function
|
||||
LUA_TLIGHTUSERDATA, // LuaType_LightUserdata
|
||||
LUA_TNIL, // LuaType_Nil
|
||||
LUA_TNUMBER, // LuaType_Number
|
||||
LUA_TNONE, // LuaType_None
|
||||
LUA_TSTRING, // LuaType_String
|
||||
LUA_TTABLE, // LuaType_Table
|
||||
LUA_TTHREAD, // LuaType_Thread
|
||||
LUA_TUSERDATA // LuaType_Userdata
|
||||
};
|
||||
|
||||
static_assert(sizeof(s_types)/sizeof(int) == LuaType_Max+1, "Lua type array is incomplete");
|
||||
}
|
||||
|
||||
void LuaState::ArgCheck(bool condition, unsigned int argNum, const char* error) const
|
||||
{
|
||||
luaL_argcheck(m_state, condition, argNum, error);
|
||||
}
|
||||
|
||||
void LuaState::ArgCheck(bool condition, unsigned int argNum, const String& error) const
|
||||
{
|
||||
luaL_argcheck(m_state, condition, argNum, error.GetConstBuffer());
|
||||
}
|
||||
|
||||
int LuaState::ArgError(unsigned int argNum, const char* error) const
|
||||
{
|
||||
return luaL_argerror(m_state, argNum, error);
|
||||
}
|
||||
|
||||
int LuaState::ArgError(unsigned int argNum, const String& error) const
|
||||
{
|
||||
return luaL_argerror(m_state, argNum, error.GetConstBuffer());
|
||||
}
|
||||
|
||||
bool LuaState::Call(unsigned int argCount)
|
||||
{
|
||||
return Run(argCount, LUA_MULTRET, 0);
|
||||
}
|
||||
|
||||
bool LuaState::Call(unsigned int argCount, unsigned int resultCount)
|
||||
{
|
||||
return Run(argCount, resultCount, 0);
|
||||
}
|
||||
|
||||
bool LuaState::CallWithHandler(unsigned int argCount, int errorHandler)
|
||||
{
|
||||
return Run(argCount, LUA_MULTRET, errorHandler);
|
||||
}
|
||||
|
||||
bool LuaState::CallWithHandler(unsigned int argCount, unsigned int resultCount, int errorHandler)
|
||||
{
|
||||
return Run(argCount, resultCount, errorHandler);
|
||||
}
|
||||
|
||||
void LuaState::CheckAny(int index) const
|
||||
{
|
||||
luaL_checkany(m_state, index);
|
||||
}
|
||||
|
||||
bool LuaState::CheckBoolean(int index) const
|
||||
{
|
||||
if (lua_isnoneornil(m_state, index))
|
||||
{
|
||||
const char* msg = lua_pushfstring(m_state, "%s expected, got %s", lua_typename(m_state, LUA_TBOOLEAN), luaL_typename(m_state, index));
|
||||
luaL_argerror(m_state, index, msg); // Lance une exception
|
||||
return false;
|
||||
}
|
||||
|
||||
return lua_toboolean(m_state, index) != 0;
|
||||
}
|
||||
|
||||
bool LuaState::CheckBoolean(int index, bool defValue) const
|
||||
{
|
||||
if (lua_isnoneornil(m_state, index))
|
||||
return defValue;
|
||||
|
||||
return lua_toboolean(m_state, index) != 0;
|
||||
}
|
||||
|
||||
long long LuaState::CheckInteger(int index) const
|
||||
{
|
||||
return luaL_checkinteger(m_state, index);
|
||||
}
|
||||
|
||||
long long LuaState::CheckInteger(int index, long long defValue) const
|
||||
{
|
||||
return luaL_optinteger(m_state, index, defValue);
|
||||
}
|
||||
|
||||
double LuaState::CheckNumber(int index) const
|
||||
{
|
||||
return luaL_checknumber(m_state, index);
|
||||
}
|
||||
|
||||
double LuaState::CheckNumber(int index, double defValue) const
|
||||
{
|
||||
return luaL_optnumber(m_state, index, defValue);
|
||||
}
|
||||
|
||||
void LuaState::CheckStack(int space, const char* error) const
|
||||
{
|
||||
luaL_checkstack(m_state, space, error);
|
||||
}
|
||||
|
||||
void LuaState::CheckStack(int space, const String& error) const
|
||||
{
|
||||
CheckStack(space, error.GetConstBuffer());
|
||||
}
|
||||
|
||||
const char* LuaState::CheckString(int index, std::size_t* length) const
|
||||
{
|
||||
return luaL_checklstring(m_state, index, length);
|
||||
}
|
||||
|
||||
const char* LuaState::CheckString(int index, const char* defValue, std::size_t* length) const
|
||||
{
|
||||
return luaL_optlstring(m_state, index, defValue, length);
|
||||
}
|
||||
|
||||
void LuaState::CheckType(int index, LuaType type) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (type > LuaType_Max)
|
||||
{
|
||||
NazaraError("Lua type out of enum");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
luaL_checktype(m_state, index, s_types[type]);
|
||||
}
|
||||
|
||||
void* LuaState::CheckUserdata(int index, const char* tname) const
|
||||
{
|
||||
return luaL_checkudata(m_state, index, tname);
|
||||
}
|
||||
|
||||
void* LuaState::CheckUserdata(int index, const String& tname) const
|
||||
{
|
||||
return luaL_checkudata(m_state, index, tname.GetConstBuffer());
|
||||
}
|
||||
|
||||
bool LuaState::Compare(int index1, int index2, LuaComparison comparison) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (comparison > LuaComparison_Max)
|
||||
{
|
||||
NazaraError("Lua comparison out of enum");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (lua_compare(m_state, index1, index2, s_comparisons[comparison]) != 0);
|
||||
}
|
||||
|
||||
void LuaState::Compute(LuaOperation operation) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (operation > LuaOperation_Max)
|
||||
{
|
||||
NazaraError("Lua operation out of enum");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
lua_arith(m_state, s_operations[operation]);
|
||||
}
|
||||
|
||||
void LuaState::Concatenate(int count) const
|
||||
{
|
||||
lua_concat(m_state, count);
|
||||
}
|
||||
|
||||
int LuaState::CreateReference()
|
||||
{
|
||||
return luaL_ref(m_state, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
void LuaState::DestroyReference(int ref)
|
||||
{
|
||||
luaL_unref(m_state, LUA_REGISTRYINDEX, ref);
|
||||
}
|
||||
|
||||
String LuaState::DumpStack() const
|
||||
{
|
||||
StringStream stream;
|
||||
unsigned int stackTop = GetStackTop();
|
||||
stream << stackTop << " entries\n";
|
||||
|
||||
for (unsigned int i = 1; i <= stackTop; ++i)
|
||||
{
|
||||
stream << i << ": ";
|
||||
switch (GetType(i))
|
||||
{
|
||||
case LuaType_Boolean:
|
||||
stream << "Boolean(" << ToBoolean(i) << ')';
|
||||
break;
|
||||
|
||||
case LuaType_Function:
|
||||
stream << "Function(" << ToPointer(i) << ')';
|
||||
break;
|
||||
|
||||
case LuaType_LightUserdata:
|
||||
case LuaType_Userdata:
|
||||
stream << "Userdata(" << ToUserdata(i) << ')';
|
||||
break;
|
||||
|
||||
case LuaType_Nil:
|
||||
stream << "Nil";
|
||||
break;
|
||||
|
||||
case LuaType_None:
|
||||
stream << "None";
|
||||
break;
|
||||
|
||||
case LuaType_Number:
|
||||
stream << "Number(" << ToNumber(i) << ')';
|
||||
break;
|
||||
|
||||
case LuaType_String:
|
||||
stream << "String(" << ToString(i) << ')';
|
||||
break;
|
||||
|
||||
case LuaType_Table:
|
||||
stream << "Table(" << ToPointer(i) << ')';
|
||||
break;
|
||||
|
||||
case LuaType_Thread:
|
||||
stream << "Thread(" << ToPointer(i) << ')';
|
||||
break;
|
||||
|
||||
default:
|
||||
stream << "Unknown(" << ToPointer(i) << ')';
|
||||
break;
|
||||
}
|
||||
|
||||
stream << '\n';
|
||||
}
|
||||
|
||||
return stream.ToString();
|
||||
}
|
||||
|
||||
void LuaState::Error(const char* message) const
|
||||
{
|
||||
luaL_error(m_state, message);
|
||||
}
|
||||
|
||||
void LuaState::Error(const String& message) const
|
||||
{
|
||||
luaL_error(m_state, message.GetConstBuffer());
|
||||
}
|
||||
|
||||
bool LuaState::Execute(const String& code, int errorHandler)
|
||||
{
|
||||
if (code.IsEmpty())
|
||||
return true;
|
||||
|
||||
if (!Load(code))
|
||||
return false;
|
||||
|
||||
return CallWithHandler(errorHandler, 0);
|
||||
}
|
||||
|
||||
bool LuaState::ExecuteFromFile(const String& filePath, int errorHandler)
|
||||
{
|
||||
if (!LoadFromFile(filePath))
|
||||
return false;
|
||||
|
||||
return CallWithHandler(errorHandler, 0);
|
||||
}
|
||||
|
||||
bool LuaState::ExecuteFromMemory(const void* data, std::size_t size, int errorHandler)
|
||||
{
|
||||
MemoryView stream(data, size);
|
||||
return ExecuteFromStream(stream, errorHandler);
|
||||
}
|
||||
|
||||
bool LuaState::ExecuteFromStream(Stream& stream, int errorHandler)
|
||||
{
|
||||
if (!LoadFromStream(stream))
|
||||
return false;
|
||||
|
||||
return CallWithHandler(errorHandler, 0);
|
||||
}
|
||||
|
||||
int LuaState::GetAbsIndex(int index) const
|
||||
{
|
||||
return lua_absindex(m_state, index);
|
||||
}
|
||||
|
||||
LuaType LuaState::GetField(const char* fieldName, int tableIndex) const
|
||||
{
|
||||
return FromLuaType(lua_getfield(m_state, tableIndex, fieldName));
|
||||
}
|
||||
|
||||
LuaType LuaState::GetField(const String& fieldName, int tableIndex) const
|
||||
{
|
||||
return FromLuaType(lua_getfield(m_state, tableIndex, fieldName.GetConstBuffer()));
|
||||
}
|
||||
|
||||
LuaType LuaState::GetGlobal(const char* name) const
|
||||
{
|
||||
return FromLuaType(lua_getglobal(m_state, name));
|
||||
}
|
||||
|
||||
LuaType LuaState::GetGlobal(const String& name) const
|
||||
{
|
||||
return FromLuaType(lua_getglobal(m_state, name.GetConstBuffer()));
|
||||
}
|
||||
|
||||
LuaType LuaState::GetMetatable(const char* tname) const
|
||||
{
|
||||
return FromLuaType(luaL_getmetatable(m_state, tname));
|
||||
}
|
||||
|
||||
LuaType LuaState::GetMetatable(const String& tname) const
|
||||
{
|
||||
return FromLuaType(luaL_getmetatable(m_state, tname.GetConstBuffer()));
|
||||
}
|
||||
|
||||
bool LuaState::GetMetatable(int index) const
|
||||
{
|
||||
return lua_getmetatable(m_state, index) != 0;
|
||||
}
|
||||
|
||||
unsigned int LuaState::GetStackTop() const
|
||||
{
|
||||
return static_cast<int>(lua_gettop(m_state));
|
||||
}
|
||||
|
||||
LuaType LuaState::GetTable(int index) const
|
||||
{
|
||||
return FromLuaType(lua_gettable(m_state, index));
|
||||
}
|
||||
|
||||
LuaType LuaState::GetTableRaw(int index) const
|
||||
{
|
||||
return FromLuaType(lua_rawget(m_state, index));
|
||||
}
|
||||
|
||||
LuaType LuaState::GetType(int index) const
|
||||
{
|
||||
return FromLuaType(lua_type(m_state, index));
|
||||
}
|
||||
|
||||
const char* LuaState::GetTypeName(LuaType type) const
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (type > LuaType_Max)
|
||||
{
|
||||
NazaraError("Lua type out of enum");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return lua_typename(m_state, s_types[type]);
|
||||
}
|
||||
|
||||
void LuaState::Insert(int index) const
|
||||
{
|
||||
lua_insert(m_state, index);
|
||||
}
|
||||
|
||||
bool LuaState::IsOfType(int index, LuaType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LuaType_Boolean:
|
||||
return lua_isboolean(m_state, index) != 0;
|
||||
|
||||
case LuaType_Function:
|
||||
return lua_isfunction(m_state, index) != 0;
|
||||
|
||||
case LuaType_LightUserdata:
|
||||
return lua_islightuserdata(m_state, index) != 0;
|
||||
|
||||
case LuaType_Nil:
|
||||
return lua_isnil(m_state, index) != 0;
|
||||
|
||||
case LuaType_None:
|
||||
return lua_isnone(m_state, index) != 0;
|
||||
|
||||
case LuaType_Number:
|
||||
return lua_isnumber(m_state, index) != 0;
|
||||
|
||||
case LuaType_String:
|
||||
return lua_isstring(m_state, index) != 0;
|
||||
|
||||
case LuaType_Table:
|
||||
return lua_istable(m_state, index) != 0;
|
||||
|
||||
case LuaType_Thread:
|
||||
return lua_isthread(m_state, index) != 0;
|
||||
|
||||
case LuaType_Userdata:
|
||||
return lua_isuserdata(m_state, index) != 0;
|
||||
}
|
||||
|
||||
NazaraError("Lua type not handled (0x" + String::Number(type, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LuaState::IsOfType(int index, const char* tname) const
|
||||
{
|
||||
void* ud = luaL_testudata(m_state, index, tname);
|
||||
return ud != nullptr;
|
||||
}
|
||||
|
||||
bool LuaState::IsOfType(int index, const String& tname) const
|
||||
{
|
||||
return IsOfType(index, tname.GetConstBuffer());
|
||||
}
|
||||
|
||||
bool LuaState::IsValid(int index) const
|
||||
{
|
||||
return lua_isnoneornil(m_state, index) == 0;
|
||||
}
|
||||
|
||||
bool LuaState::Load(const String& code)
|
||||
{
|
||||
if (luaL_loadstring(m_state, code.GetConstBuffer()) != 0)
|
||||
{
|
||||
m_lastError = lua_tostring(m_state, -1);
|
||||
lua_pop(m_state, 1);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaState::LoadFromFile(const String& filePath)
|
||||
{
|
||||
File file(filePath);
|
||||
if (!file.Open(OpenMode_ReadOnly | OpenMode_Text))
|
||||
{
|
||||
NazaraError("Failed to open file");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t length = static_cast<std::size_t>(file.GetSize());
|
||||
|
||||
String source(length, '\0');
|
||||
|
||||
if (file.Read(&source[0], length) != length)
|
||||
{
|
||||
NazaraError("Failed to read file");
|
||||
return false;
|
||||
}
|
||||
|
||||
file.Close();
|
||||
|
||||
return Load(source);
|
||||
}
|
||||
|
||||
bool LuaState::LoadFromMemory(const void* data, std::size_t size)
|
||||
{
|
||||
MemoryView stream(data, size);
|
||||
return LoadFromStream(stream);
|
||||
}
|
||||
|
||||
bool LuaState::LoadFromStream(Stream& stream)
|
||||
{
|
||||
StreamData data;
|
||||
data.stream = &stream;
|
||||
|
||||
if (lua_load(m_state, StreamReader, &data, "C++", nullptr) != 0)
|
||||
{
|
||||
m_lastError = lua_tostring(m_state, -1);
|
||||
lua_pop(m_state, 1);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
long long LuaState::Length(int index) const
|
||||
{
|
||||
return luaL_len(m_state, index);
|
||||
}
|
||||
|
||||
std::size_t LuaState::LengthRaw(int index) const
|
||||
{
|
||||
return lua_rawlen(m_state, index);
|
||||
}
|
||||
|
||||
void LuaState::MoveTo(LuaState* instance, int n) const
|
||||
{
|
||||
lua_xmove(m_state, instance->m_state, n);
|
||||
}
|
||||
|
||||
LuaCoroutine LuaState::NewCoroutine()
|
||||
{
|
||||
lua_State* thread = lua_newthread(m_state);
|
||||
int ref = luaL_ref(m_state, LUA_REGISTRYINDEX);
|
||||
|
||||
return LuaCoroutine(thread, ref);
|
||||
}
|
||||
|
||||
bool LuaState::NewMetatable(const char* str)
|
||||
{
|
||||
return luaL_newmetatable(m_state, str) != 0;
|
||||
}
|
||||
|
||||
bool LuaState::NewMetatable(const String& str)
|
||||
{
|
||||
return luaL_newmetatable(m_state, str.GetConstBuffer()) != 0;
|
||||
}
|
||||
|
||||
bool LuaState::Next(int index) const
|
||||
{
|
||||
return lua_next(m_state, index) != 0;
|
||||
}
|
||||
|
||||
void LuaState::Pop(unsigned int n) const
|
||||
{
|
||||
lua_pop(m_state, static_cast<int>(n));
|
||||
}
|
||||
|
||||
void LuaState::PushBoolean(bool value) const
|
||||
{
|
||||
lua_pushboolean(m_state, (value) ? 1 : 0);
|
||||
}
|
||||
|
||||
void LuaState::PushCFunction(LuaCFunction func, unsigned int upvalueCount) const
|
||||
{
|
||||
lua_pushcclosure(m_state, func, upvalueCount);
|
||||
}
|
||||
|
||||
void LuaState::PushFunction(LuaFunction func) const
|
||||
{
|
||||
LuaFunction* luaFunc = static_cast<LuaFunction*>(lua_newuserdata(m_state, sizeof(LuaFunction)));
|
||||
PlacementNew(luaFunc, std::move(func));
|
||||
|
||||
lua_pushcclosure(m_state, ProxyFunc, 1);
|
||||
}
|
||||
|
||||
void LuaState::PushInteger(long long value) const
|
||||
{
|
||||
lua_pushinteger(m_state, value);
|
||||
}
|
||||
|
||||
void LuaState::PushLightUserdata(void* value) const
|
||||
{
|
||||
lua_pushlightuserdata(m_state, value);
|
||||
}
|
||||
|
||||
void LuaState::PushMetatable(const char* str) const
|
||||
{
|
||||
luaL_getmetatable(m_state, str);
|
||||
}
|
||||
|
||||
void LuaState::PushMetatable(const String& str) const
|
||||
{
|
||||
luaL_getmetatable(m_state, str.GetConstBuffer());
|
||||
}
|
||||
|
||||
void LuaState::PushNil() const
|
||||
{
|
||||
lua_pushnil(m_state);
|
||||
}
|
||||
|
||||
void LuaState::PushNumber(double value) const
|
||||
{
|
||||
lua_pushnumber(m_state, value);
|
||||
}
|
||||
|
||||
void LuaState::PushReference(int ref) const
|
||||
{
|
||||
lua_rawgeti(m_state, LUA_REGISTRYINDEX, ref);
|
||||
}
|
||||
|
||||
void LuaState::PushString(const char* str) const
|
||||
{
|
||||
lua_pushstring(m_state, str);
|
||||
}
|
||||
|
||||
void LuaState::PushString(const char* str, std::size_t size) const
|
||||
{
|
||||
lua_pushlstring(m_state, str, size);
|
||||
}
|
||||
|
||||
void LuaState::PushString(const String& str) const
|
||||
{
|
||||
lua_pushlstring(m_state, str.GetConstBuffer(), str.GetSize());
|
||||
}
|
||||
|
||||
void LuaState::PushTable(std::size_t sequenceElementCount, std::size_t arrayElementCount) const
|
||||
{
|
||||
constexpr std::size_t maxInt = std::numeric_limits<int>::max();
|
||||
lua_createtable(m_state, static_cast<int>(std::min(sequenceElementCount, maxInt)), static_cast<int>(std::min(arrayElementCount, maxInt)));
|
||||
}
|
||||
|
||||
void* LuaState::PushUserdata(std::size_t size) const
|
||||
{
|
||||
return lua_newuserdata(m_state, size);
|
||||
}
|
||||
|
||||
void LuaState::PushValue(int index) const
|
||||
{
|
||||
lua_pushvalue(m_state, index);
|
||||
}
|
||||
|
||||
bool LuaState::RawEqual(int index1, int index2) const
|
||||
{
|
||||
return lua_rawequal(m_state, index1, index2);
|
||||
}
|
||||
|
||||
void LuaState::Remove(int index) const
|
||||
{
|
||||
lua_remove(m_state, index);
|
||||
}
|
||||
|
||||
void LuaState::Replace(int index) const
|
||||
{
|
||||
lua_replace(m_state, index);
|
||||
}
|
||||
|
||||
void LuaState::SetField(const char* name, int tableIndex) const
|
||||
{
|
||||
lua_setfield(m_state, tableIndex, name);
|
||||
}
|
||||
|
||||
void LuaState::SetField(const String& name, int tableIndex) const
|
||||
{
|
||||
lua_setfield(m_state, tableIndex, name.GetConstBuffer());
|
||||
}
|
||||
|
||||
void LuaState::SetGlobal(const char* name)
|
||||
{
|
||||
lua_setglobal(m_state, name);
|
||||
}
|
||||
|
||||
void LuaState::SetGlobal(const String& name)
|
||||
{
|
||||
lua_setglobal(m_state, name.GetConstBuffer());
|
||||
}
|
||||
|
||||
void LuaState::SetMetatable(const char* tname) const
|
||||
{
|
||||
luaL_setmetatable(m_state, tname);
|
||||
}
|
||||
|
||||
void LuaState::SetMetatable(const String& tname) const
|
||||
{
|
||||
luaL_setmetatable(m_state, tname.GetConstBuffer());
|
||||
}
|
||||
|
||||
void LuaState::SetMetatable(int index) const
|
||||
{
|
||||
lua_setmetatable(m_state, index);
|
||||
}
|
||||
|
||||
void LuaState::SetTable(int index) const
|
||||
{
|
||||
lua_settable(m_state, index);
|
||||
}
|
||||
|
||||
void LuaState::SetTableRaw(int index) const
|
||||
{
|
||||
lua_rawset(m_state, index);
|
||||
}
|
||||
|
||||
bool LuaState::ToBoolean(int index) const
|
||||
{
|
||||
return lua_toboolean(m_state, index) != 0;
|
||||
}
|
||||
|
||||
long long LuaState::ToInteger(int index, bool* succeeded) const
|
||||
{
|
||||
int success;
|
||||
long long result = lua_tointegerx(m_state, index, &success);
|
||||
|
||||
if (succeeded)
|
||||
*succeeded = (success != 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
double LuaState::ToNumber(int index, bool* succeeded) const
|
||||
{
|
||||
int success;
|
||||
double result = lua_tonumberx(m_state, index, &success);
|
||||
|
||||
if (succeeded)
|
||||
*succeeded = (success != 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const void* LuaState::ToPointer(int index) const
|
||||
{
|
||||
return lua_topointer(m_state, index);
|
||||
}
|
||||
|
||||
const char* LuaState::ToString(int index, std::size_t* length) const
|
||||
{
|
||||
return lua_tolstring(m_state, index, length);
|
||||
}
|
||||
|
||||
void* LuaState::ToUserdata(int index) const
|
||||
{
|
||||
return lua_touserdata(m_state, index);
|
||||
}
|
||||
|
||||
void* LuaState::ToUserdata(int index, const char* tname) const
|
||||
{
|
||||
return luaL_testudata(m_state, index, tname);
|
||||
}
|
||||
|
||||
void* LuaState::ToUserdata(int index, const String& tname) const
|
||||
{
|
||||
return luaL_testudata(m_state, index, tname.GetConstBuffer());
|
||||
}
|
||||
|
||||
void LuaState::Traceback(const char* message, int level)
|
||||
{
|
||||
luaL_traceback(m_state, m_state, message, level);
|
||||
}
|
||||
|
||||
bool LuaState::Run(int argCount, int resultCount, int errHandler)
|
||||
{
|
||||
LuaInstance& instance = GetInstance(m_state);
|
||||
|
||||
if (instance.m_level++ == 0)
|
||||
instance.m_clock.Restart();
|
||||
|
||||
int status = lua_pcall(m_state, argCount, resultCount, errHandler);
|
||||
|
||||
instance.m_level--;
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
m_lastError = lua_tostring(m_state, -1);
|
||||
lua_pop(m_state, 1);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int LuaState::GetIndexOfUpValue(int upValue)
|
||||
{
|
||||
return lua_upvalueindex(upValue);
|
||||
}
|
||||
|
||||
LuaInstance& LuaState::GetInstance(lua_State* internalState)
|
||||
{
|
||||
LuaInstance* instance;
|
||||
lua_getallocf(internalState, reinterpret_cast<void**>(&instance));
|
||||
|
||||
return *instance;
|
||||
}
|
||||
|
||||
int LuaState::ProxyFunc(lua_State* internalState)
|
||||
{
|
||||
LuaFunction& func = *static_cast<LuaFunction*>(lua_touserdata(internalState, lua_upvalueindex(1)));
|
||||
LuaState state = GetState(internalState);
|
||||
|
||||
return func(state);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Network/NetPacket.hpp>
|
||||
#include <Nazara/Core/LockGuard.hpp>
|
||||
#include <Nazara/Core/MemoryView.hpp>
|
||||
#include <Nazara/Network/Debug.hpp>
|
||||
|
||||
@@ -113,7 +112,7 @@ namespace Nz
|
||||
|
||||
std::size_t size = m_buffer->GetSize();
|
||||
|
||||
Nz::LockGuard lock(*s_availableBuffersMutex);
|
||||
std::lock_guard<std::mutex> lock(s_availableBuffersMutex);
|
||||
s_availableBuffers.emplace_back(std::make_pair(size, std::move(m_buffer)));
|
||||
}
|
||||
|
||||
@@ -132,7 +131,7 @@ namespace Nz
|
||||
NazaraAssert(minCapacity >= cursorPos, "Cannot init stream with a smaller capacity than wanted cursor pos");
|
||||
|
||||
{
|
||||
Nz::LockGuard lock(*s_availableBuffersMutex);
|
||||
std::lock_guard<std::mutex> lock(s_availableBuffersMutex);
|
||||
|
||||
FreeStream(); //< In case it wasn't released yet
|
||||
|
||||
@@ -160,7 +159,6 @@ namespace Nz
|
||||
|
||||
bool NetPacket::Initialize()
|
||||
{
|
||||
s_availableBuffersMutex = std::make_unique<Mutex>();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -171,9 +169,8 @@ namespace Nz
|
||||
void NetPacket::Uninitialize()
|
||||
{
|
||||
s_availableBuffers.clear();
|
||||
s_availableBuffersMutex.reset();
|
||||
}
|
||||
|
||||
std::unique_ptr<Mutex> NetPacket::s_availableBuffersMutex;
|
||||
std::mutex NetPacket::s_availableBuffersMutex;
|
||||
std::vector<std::pair<std::size_t, std::unique_ptr<ByteArray>>> NetPacket::s_availableBuffers;
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/Config.hpp>
|
||||
#if NAZARA_NOISE_MANAGE_MEMORY
|
||||
|
||||
#include <Nazara/Core/MemoryManager.hpp>
|
||||
#include <new> // Nécessaire ?
|
||||
|
||||
void* operator new(std::size_t size)
|
||||
{
|
||||
return Nz::MemoryManager::Allocate(size, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size)
|
||||
{
|
||||
return Nz::MemoryManager::Allocate(size, true);
|
||||
}
|
||||
|
||||
void operator delete(void* pointer) noexcept
|
||||
{
|
||||
Nz::MemoryManager::Free(pointer, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* pointer) noexcept
|
||||
{
|
||||
Nz::MemoryManager::Free(pointer, true);
|
||||
}
|
||||
|
||||
#endif // NAZARA_NOISE_MANAGE_MEMORY
|
||||
@@ -1,62 +0,0 @@
|
||||
// Copyright (C) 2017 Rémi Bèges
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/FBM.hpp>
|
||||
#include <Nazara/Noise/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
FBM::FBM(const NoiseBase & source): m_source(source)
|
||||
{
|
||||
}
|
||||
|
||||
///TODO: Handle with variadic templates
|
||||
float FBM::Get(float x, float y, float scale) const
|
||||
{
|
||||
float value = 0.f;
|
||||
for(int i = 0; i < m_octaves; ++i)
|
||||
{
|
||||
value += m_source.Get(x, y, scale) * m_exponent_array.at(i);
|
||||
scale *= m_lacunarity;
|
||||
}
|
||||
|
||||
float remainder = m_octaves - static_cast<int>(m_octaves);
|
||||
if(std::fabs(remainder) > 0.01f)
|
||||
value += remainder * m_source.Get(x, y, scale) * m_exponent_array.at(static_cast<int>(m_octaves-1));
|
||||
|
||||
return value / m_sum;
|
||||
}
|
||||
|
||||
float FBM::Get(float x, float y, float z, float scale) const
|
||||
{
|
||||
float value = 0.f;
|
||||
for(int i = 0; i < m_octaves; ++i)
|
||||
{
|
||||
value += m_source.Get(x, y, z, scale) * m_exponent_array.at(i);
|
||||
scale *= m_lacunarity;
|
||||
}
|
||||
|
||||
float remainder = m_octaves - static_cast<int>(m_octaves);
|
||||
if(std::fabs(remainder) > 0.01f)
|
||||
value += remainder * m_source.Get(x, y, z, scale) * m_exponent_array.at(static_cast<int>(m_octaves-1));
|
||||
|
||||
return value / m_sum;
|
||||
}
|
||||
|
||||
float FBM::Get(float x, float y, float z, float w, float scale) const
|
||||
{
|
||||
float value = 0.f;
|
||||
for(int i = 0; i < m_octaves; ++i)
|
||||
{
|
||||
value += m_source.Get(x, y, z, w, scale) * m_exponent_array.at(i);
|
||||
scale *= m_lacunarity;
|
||||
}
|
||||
|
||||
float remainder = m_octaves - static_cast<int>(m_octaves);
|
||||
if(std::fabs(remainder) > 0.01f)
|
||||
value += remainder * m_source.Get(x, y, z, w, scale) * m_exponent_array.at(static_cast<int>(m_octaves-1));
|
||||
|
||||
return value / m_sum;
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
// Copyright (C) 2017 Rémi Bèges
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/HybridMultiFractal.hpp>
|
||||
#include <Nazara/Noise/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
HybridMultiFractal::HybridMultiFractal(const NoiseBase & source) :
|
||||
m_source(source)
|
||||
{
|
||||
}
|
||||
|
||||
float HybridMultiFractal::Get(float x, float y, float scale) const
|
||||
{
|
||||
float offset = 1.0f;
|
||||
float value = (m_source.Get(x, y, scale) + offset) * m_exponent_array.at(0);
|
||||
float weight = value;
|
||||
float signal = 0.f;
|
||||
|
||||
scale *= m_lacunarity;
|
||||
|
||||
for(int i(1) ; i < m_octaves; ++i)
|
||||
{
|
||||
if (weight > 1.f)
|
||||
weight = 1.f;
|
||||
|
||||
signal = (m_source.Get(x, y, scale) + offset) * m_exponent_array.at(i);
|
||||
value += weight * signal;
|
||||
weight *= signal;
|
||||
scale *= m_lacunarity;
|
||||
}
|
||||
|
||||
float remainder = m_octaves - static_cast<int>(m_octaves);
|
||||
|
||||
if (remainder > 0.f)
|
||||
value += remainder * m_source.Get(x, y, scale) * m_exponent_array.at(static_cast<int>(m_octaves-1));
|
||||
|
||||
return value / m_sum - offset;
|
||||
}
|
||||
|
||||
float HybridMultiFractal::Get(float x, float y, float z, float scale) const
|
||||
{
|
||||
float offset = 1.0f;
|
||||
float value = (m_source.Get(x, y, z, scale) + offset) * m_exponent_array.at(0);
|
||||
float weight = value;
|
||||
float signal = 0.f;
|
||||
|
||||
scale *= m_lacunarity;
|
||||
|
||||
for(int i(1) ; i < m_octaves; ++i)
|
||||
{
|
||||
if (weight > 1.f)
|
||||
weight = 1.f;
|
||||
|
||||
signal = (m_source.Get(x, y, z, scale) + offset) * m_exponent_array.at(i);
|
||||
value += weight * signal;
|
||||
weight *= signal;
|
||||
scale *= m_lacunarity;
|
||||
}
|
||||
|
||||
float remainder = m_octaves - static_cast<int>(m_octaves);
|
||||
|
||||
if (remainder > 0.f)
|
||||
value += remainder * m_source.Get(x, y, z, scale) * m_exponent_array.at(static_cast<int>(m_octaves-1));
|
||||
|
||||
return value / m_sum - offset;
|
||||
}
|
||||
|
||||
float HybridMultiFractal::Get(float x, float y, float z, float w, float scale) const
|
||||
{
|
||||
float offset = 1.0f;
|
||||
float value = (m_source.Get(x, y, z, w, scale) + offset) * m_exponent_array.at(0);
|
||||
float weight = value;
|
||||
float signal = 0.f;
|
||||
|
||||
scale *= m_lacunarity;
|
||||
|
||||
for(int i(1) ; i < m_octaves; ++i)
|
||||
{
|
||||
if (weight > 1.f)
|
||||
weight = 1.f;
|
||||
|
||||
signal = (m_source.Get(x, y, z, w, scale) + offset) * m_exponent_array.at(i);
|
||||
value += weight * signal;
|
||||
weight *= signal;
|
||||
scale *= m_lacunarity;
|
||||
}
|
||||
|
||||
float remainder = m_octaves - static_cast<int>(m_octaves);
|
||||
|
||||
if (remainder > 0.f)
|
||||
value += remainder * m_source.Get(x, y, z, w, scale) * m_exponent_array.at(static_cast<int>(m_octaves-1));
|
||||
|
||||
return value / m_sum - offset;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright (C) 2017 Rémi Bèges
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/MixerBase.hpp>
|
||||
#include <cmath>
|
||||
#include <Nazara/Noise/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
MixerBase::MixerBase() :
|
||||
m_hurst(1.2f),
|
||||
m_lacunarity(5.f),
|
||||
m_octaves(3.f)
|
||||
{
|
||||
Recompute();
|
||||
}
|
||||
|
||||
float MixerBase::GetHurstParameter() const
|
||||
{
|
||||
return m_hurst;
|
||||
}
|
||||
|
||||
float MixerBase::GetLacunarity() const
|
||||
{
|
||||
return m_lacunarity;
|
||||
}
|
||||
|
||||
float MixerBase::GetOctaveNumber() const
|
||||
{
|
||||
return m_octaves;
|
||||
}
|
||||
|
||||
void MixerBase::SetParameters(float hurst, float lacunarity, float octaves)
|
||||
{
|
||||
m_hurst = hurst;
|
||||
m_lacunarity = lacunarity;
|
||||
m_octaves = octaves;
|
||||
|
||||
Recompute();
|
||||
}
|
||||
|
||||
void MixerBase::Recompute()
|
||||
{
|
||||
float frequency = 1.0;
|
||||
m_sum = 0.f;
|
||||
m_exponent_array.clear();
|
||||
|
||||
for (int i(0) ; i < static_cast<int>(m_octaves) ; ++i)
|
||||
{
|
||||
m_exponent_array.push_back(std::pow( frequency, -m_hurst ));
|
||||
frequency *= m_lacunarity;
|
||||
m_sum += m_exponent_array.at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright (C) 2017 Rémi Bèges
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/Noise.hpp>
|
||||
#include <Nazara/Core/Core.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Nazara/Noise/Config.hpp>
|
||||
#include <Nazara/Noise/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
bool Noise::Initialize()
|
||||
{
|
||||
if (s_moduleReferenceCounter > 0)
|
||||
{
|
||||
s_moduleReferenceCounter++;
|
||||
return true; // Déjà initialisé
|
||||
}
|
||||
|
||||
// Initialisation des dépendances
|
||||
if (!Core::Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize core module");
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
s_moduleReferenceCounter++;
|
||||
|
||||
// Initialisation du module
|
||||
|
||||
NazaraNotice("Initialized: Noise module");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Noise::IsInitialized()
|
||||
{
|
||||
return s_moduleReferenceCounter != 0;
|
||||
}
|
||||
|
||||
void Noise::Uninitialize()
|
||||
{
|
||||
if (s_moduleReferenceCounter != 1)
|
||||
{
|
||||
// Le module est soit encore utilisé, soit pas initialisé
|
||||
if (s_moduleReferenceCounter > 1)
|
||||
s_moduleReferenceCounter--;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Libération du module
|
||||
s_moduleReferenceCounter = 0;
|
||||
|
||||
NazaraNotice("Uninitialized: Noise module");
|
||||
|
||||
// Libération des dépendances
|
||||
Core::Uninitialize();
|
||||
}
|
||||
|
||||
unsigned int Noise::s_moduleReferenceCounter = 0;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
// Copyright (C) 2017 Rémi Bèges
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/NoiseBase.hpp>
|
||||
#include <numeric>
|
||||
#include <Nazara/Noise/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
NoiseBase::NoiseBase(unsigned int seed) :
|
||||
m_scale(0.05f)
|
||||
{
|
||||
SetSeed(seed);
|
||||
|
||||
// Fill permutations with initial values
|
||||
std::iota(m_permutations.begin(), m_permutations.begin() + 256, 0);
|
||||
}
|
||||
|
||||
float NoiseBase::GetScale()
|
||||
{
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
void NoiseBase::SetScale(float scale)
|
||||
{
|
||||
m_scale = scale;
|
||||
}
|
||||
|
||||
void NoiseBase::SetSeed(unsigned int seed)
|
||||
{
|
||||
m_randomEngine.seed(seed);
|
||||
}
|
||||
|
||||
void NoiseBase::Shuffle()
|
||||
{
|
||||
std::shuffle(m_permutations.begin(), m_permutations.begin() + 256, m_randomEngine);
|
||||
|
||||
for(std::size_t i = 1; i < (m_permutations.size() / 256); ++i)
|
||||
std::copy(m_permutations.begin(), m_permutations.begin() + 256, m_permutations.begin() + 256 * i);
|
||||
}
|
||||
|
||||
std::array<Vector2f, 2 * 2 * 2> NoiseBase::s_gradients2 =
|
||||
{
|
||||
{
|
||||
{1.f, 1.f}, {-1.f, 1.f}, {1.f, -1.f}, {-1.f, -1.f},
|
||||
{1.f, 0.f}, {-1.f, 0.f}, {0.f, 1.f}, { 0.f, -1.f}
|
||||
}
|
||||
};
|
||||
|
||||
std::array<Vector3f, 2 * 2 * 2 * 2> NoiseBase::s_gradients3 =
|
||||
{
|
||||
{
|
||||
{1.f,1.f,0.f}, {-1.f, 1.f, 0.f}, {1.f, -1.f, 0.f}, {-1.f, -1.f, 0.f},
|
||||
{1.f,0.f,1.f}, {-1.f, 0.f, 1.f}, {1.f, 0.f, -1.f}, {-1.f, 0.f, -1.f},
|
||||
{0.f,1.f,1.f}, { 0.f, -1.f, 1.f}, {0.f, 1.f, -1.f}, {0.f, -1.f, -1.f},
|
||||
{1.f,1.f,0.f}, {-1.f, 1.f, 0.f}, {0.f, -1.f, 1.f}, {0.f, -1.f, -1.f}
|
||||
}
|
||||
};
|
||||
|
||||
std::array<Vector4f, 2 * 2 * 2 * 2 * 2> NoiseBase::s_gradients4 =
|
||||
{
|
||||
{
|
||||
{0,1,1,1}, {0,1,1,-1}, {0,1,-1,1}, {0,1,-1,-1},
|
||||
{0,-1,1,1},{0,-1,1,-1},{0,-1,-1,1},{0,-1,-1,-1},
|
||||
{1,0,1,1}, {1,0,1,-1}, {1,0,-1,1}, {1,0,-1,-1},
|
||||
{-1,0,1,1},{-1,0,1,-1},{-1,0,-1,1},{-1,0,-1,-1},
|
||||
{1,1,0,1}, {1,1,0,-1}, {1,-1,0,1}, {1,-1,0,-1},
|
||||
{-1,1,0,1},{-1,1,0,-1},{-1,-1,0,1},{-1,-1,0,-1},
|
||||
{1,1,1,0}, {1,1,-1,0}, {1,-1,1,0}, {1,-1,-1,0},
|
||||
{-1,1,1,0},{-1,1,-1,0},{-1,-1,1,0},{-1,-1,-1,0}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright (C) 2017 Rémi Bèges
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/NoiseTools.hpp>
|
||||
#include <Nazara/Noise/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
int fastfloor(float n)
|
||||
{
|
||||
return (n >= 0) ? static_cast<int>(n) : static_cast<int>(n-1);
|
||||
}
|
||||
|
||||
int JenkinsHash(int a, int b, int c)
|
||||
{
|
||||
a = a-b; a = a - c; a = a^(static_cast<unsigned int>(c) >> 13);
|
||||
b = b-c; b = b - a; b = b^(a << 8);
|
||||
c = c-a; c = c - b; c = c^(static_cast<unsigned int>(b) >> 13);
|
||||
a = a-b; a = a - c; a = a^(static_cast<unsigned int>(c) >> 12);
|
||||
b = b-c; b = b - a; b = b^(a << 16);
|
||||
c = c-a; c = c - b; c = c^(static_cast<unsigned int>(b) >> 5);
|
||||
a = a-b; a = a - c; a = a^(static_cast<unsigned int>(c) >> 3);
|
||||
b = b-c; b = b - a; b = b^(a << 10);
|
||||
c = c-a; c = c - b; c = c^(static_cast<unsigned int>(b) >> 15);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
// Copyright (C) 2017 Rémi Bèges
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/Perlin.hpp>
|
||||
#include <Nazara/Noise/NoiseTools.hpp>
|
||||
#include <Nazara/Noise/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
Perlin::Perlin(unsigned int seed) :
|
||||
Perlin()
|
||||
{
|
||||
SetSeed(seed);
|
||||
Shuffle();
|
||||
}
|
||||
|
||||
float Perlin::Get(float x, float y, float scale) const
|
||||
{
|
||||
float xc, yc;
|
||||
int x0, y0;
|
||||
int gi0,gi1,gi2,gi3;
|
||||
int ii, jj;
|
||||
|
||||
float s,t,u,v;
|
||||
float Cx,Cy;
|
||||
float Li1, Li2;
|
||||
float tempx,tempy;
|
||||
|
||||
xc = x * scale;
|
||||
yc = y * scale;
|
||||
|
||||
x0 = fastfloor(xc);
|
||||
y0 = fastfloor(yc);
|
||||
|
||||
ii = x0 & 255;
|
||||
jj = y0 & 255;
|
||||
|
||||
gi0 = m_permutations[ii + m_permutations[jj]] & 7;
|
||||
gi1 = m_permutations[ii + 1 + m_permutations[jj]] & 7;
|
||||
gi2 = m_permutations[ii + m_permutations[jj + 1]] & 7;
|
||||
gi3 = m_permutations[ii + 1 + m_permutations[jj + 1]] & 7;
|
||||
|
||||
tempx = xc - x0;
|
||||
tempy = yc - y0;
|
||||
|
||||
Cx = tempx * tempx * tempx * (tempx * (tempx * 6 - 15) + 10);
|
||||
Cy = tempy * tempy * tempy * (tempy * (tempy * 6 - 15) + 10);
|
||||
|
||||
s = s_gradients2[gi0][0]*tempx + s_gradients2[gi0][1]*tempy;
|
||||
|
||||
tempx = xc - (x0 + 1);
|
||||
t = s_gradients2[gi1][0]*tempx + s_gradients2[gi1][1]*tempy;
|
||||
|
||||
tempy = yc - (y0 + 1);
|
||||
v = s_gradients2[gi3][0]*tempx + s_gradients2[gi3][1]*tempy;
|
||||
|
||||
tempx = xc - x0;
|
||||
u = s_gradients2[gi2][0]*tempx + s_gradients2[gi2][1]*tempy;
|
||||
|
||||
Li1 = s + Cx*(t-s);
|
||||
Li2 = u + Cx*(v-u);
|
||||
|
||||
return Li1 + Cy*(Li2-Li1);
|
||||
}
|
||||
|
||||
float Perlin::Get(float x, float y, float z, float scale) const
|
||||
{
|
||||
float xc, yc, zc;
|
||||
int x0, y0, z0;
|
||||
int gi0,gi1,gi2,gi3,gi4,gi5,gi6,gi7;
|
||||
int ii, jj, kk;
|
||||
|
||||
float Li1,Li2,Li3,Li4,Li5,Li6;
|
||||
float s[2],t[2],u[2],v[2];
|
||||
float Cx,Cy,Cz;
|
||||
float tempx,tempy,tempz;
|
||||
|
||||
xc = x * scale;
|
||||
yc = y * scale;
|
||||
zc = z * scale;
|
||||
|
||||
x0 = fastfloor(xc);
|
||||
y0 = fastfloor(yc);
|
||||
z0 = fastfloor(zc);
|
||||
|
||||
ii = x0 & 255;
|
||||
jj = y0 & 255;
|
||||
kk = z0 & 255;
|
||||
|
||||
gi0 = m_permutations[ii + m_permutations[jj + m_permutations[kk]]] & 15;
|
||||
gi1 = m_permutations[ii + 1 + m_permutations[jj + m_permutations[kk]]] & 15;
|
||||
gi2 = m_permutations[ii + m_permutations[jj + 1 + m_permutations[kk]]] & 15;
|
||||
gi3 = m_permutations[ii + 1 + m_permutations[jj + 1 + m_permutations[kk]]] & 15;
|
||||
|
||||
gi4 = m_permutations[ii + m_permutations[jj + m_permutations[kk + 1]]] & 15;
|
||||
gi5 = m_permutations[ii + 1 + m_permutations[jj + m_permutations[kk + 1]]] & 15;
|
||||
gi6 = m_permutations[ii + m_permutations[jj + 1 + m_permutations[kk + 1]]] & 15;
|
||||
gi7 = m_permutations[ii + 1 + m_permutations[jj + 1 + m_permutations[kk + 1]]] & 15;
|
||||
|
||||
tempx = xc - x0;
|
||||
tempy = yc - y0;
|
||||
tempz = zc - z0;
|
||||
|
||||
Cx = tempx * tempx * tempx * (tempx * (tempx * 6 - 15) + 10);
|
||||
Cy = tempy * tempy * tempy * (tempy * (tempy * 6 - 15) + 10);
|
||||
Cz = tempz * tempz * tempz * (tempz * (tempz * 6 - 15) + 10);
|
||||
|
||||
s[0] = s_gradients3[gi0][0]*tempx + s_gradients3[gi0][1]*tempy + s_gradients3[gi0][2]*tempz;
|
||||
|
||||
tempx = xc - (x0 + 1);
|
||||
t[0] = s_gradients3[gi1][0]*tempx + s_gradients3[gi1][1]*tempy + s_gradients3[gi1][2]*tempz;
|
||||
|
||||
tempy = yc - (y0 + 1);
|
||||
v[0] = s_gradients3[gi3][0]*tempx + s_gradients3[gi3][1]*tempy + s_gradients3[gi3][2]*tempz;
|
||||
|
||||
tempx = xc - x0;
|
||||
u[0] = s_gradients3[gi2][0]*tempx + s_gradients3[gi2][1]*tempy + s_gradients3[gi2][2]*tempz;
|
||||
|
||||
tempy = yc - y0;
|
||||
tempz = zc - (z0 + 1);
|
||||
s[1] = s_gradients3[gi4][0]*tempx + s_gradients3[gi4][1]*tempy + s_gradients3[gi4][2]*tempz;
|
||||
|
||||
tempx = xc - (x0 + 1);
|
||||
t[1] = s_gradients3[gi5][0]*tempx + s_gradients3[gi5][1]*tempy + s_gradients3[gi5][2]*tempz;
|
||||
|
||||
tempy = yc - (y0 + 1);
|
||||
v[1] = s_gradients3[gi7][0]*tempx + s_gradients3[gi7][1]*tempy + s_gradients3[gi7][2]*tempz;
|
||||
|
||||
tempx = xc - x0;
|
||||
u[1] = s_gradients3[gi6][0]*tempx + s_gradients3[gi6][1]*tempy + s_gradients3[gi6][2]*tempz;
|
||||
|
||||
Li1 = s[0] + Cx*(t[0]-s[0]);
|
||||
Li2 = u[0] + Cx*(v[0]-u[0]);
|
||||
Li3 = s[1] + Cx*(t[1]-s[1]);
|
||||
Li4 = u[1] + Cx*(v[1]-u[1]);
|
||||
|
||||
Li5 = Li1 + Cy * (Li2-Li1);
|
||||
Li6 = Li3 + Cy * (Li4-Li3);
|
||||
|
||||
return Li5 + Cz * (Li6-Li5);
|
||||
}
|
||||
|
||||
float Perlin::Get(float x, float y, float z, float w, float scale) const
|
||||
{
|
||||
float xc,yc,zc,wc;
|
||||
int x0,y0,z0,w0;
|
||||
int gi0,gi1,gi2,gi3,gi4,gi5,gi6,gi7,gi8,gi9,gi10,gi11,gi12,gi13,gi14,gi15;
|
||||
int ii,jj,kk,ll;
|
||||
|
||||
float Li1,Li2,Li3,Li4,Li5,Li6,Li7,Li8,Li9,Li10,Li11,Li12,Li13,Li14;
|
||||
float s[4],t[4],u[4],v[4];
|
||||
float Cx,Cy,Cz,Cw;
|
||||
|
||||
float tempx,tempy,tempz,tempw;
|
||||
|
||||
xc = x * scale;
|
||||
yc = y * scale;
|
||||
zc = z * scale;
|
||||
wc = w * scale;
|
||||
|
||||
x0 = fastfloor(xc);
|
||||
y0 = fastfloor(yc);
|
||||
z0 = fastfloor(zc);
|
||||
w0 = fastfloor(wc);
|
||||
|
||||
ii = x0 & 255;
|
||||
jj = y0 & 255;
|
||||
kk = z0 & 255;
|
||||
ll = w0 & 255;
|
||||
|
||||
gi0 = m_permutations[ii + m_permutations[jj + m_permutations[kk + m_permutations[ll]]]] & 31;
|
||||
gi1 = m_permutations[ii + 1 + m_permutations[jj + m_permutations[kk + m_permutations[ll]]]] & 31;
|
||||
gi2 = m_permutations[ii + m_permutations[jj + 1 + m_permutations[kk + m_permutations[ll]]]] & 31;
|
||||
gi3 = m_permutations[ii + 1 + m_permutations[jj + 1 + m_permutations[kk + m_permutations[ll]]]] & 31;
|
||||
|
||||
gi4 = m_permutations[ii + m_permutations[jj + + m_permutations[kk + 1 + m_permutations[ll]]]] & 31;
|
||||
gi5 = m_permutations[ii + 1 + m_permutations[jj + + m_permutations[kk + 1 + m_permutations[ll]]]] & 31;
|
||||
gi6 = m_permutations[ii + m_permutations[jj + 1 + m_permutations[kk + 1 + m_permutations[ll]]]] & 31;
|
||||
gi7 = m_permutations[ii + 1 + m_permutations[jj + 1 + m_permutations[kk + 1 + m_permutations[ll]]]] & 31;
|
||||
|
||||
gi8 = m_permutations[ii + m_permutations[jj + m_permutations[kk + m_permutations[ll + 1]]]] & 31;
|
||||
gi9 = m_permutations[ii + 1 + m_permutations[jj + m_permutations[kk + m_permutations[ll + 1]]]] & 31;
|
||||
gi10 = m_permutations[ii + m_permutations[jj + 1 + m_permutations[kk + m_permutations[ll + 1]]]] & 31;
|
||||
gi11 = m_permutations[ii + 1 + m_permutations[jj + 1 + m_permutations[kk + m_permutations[ll + 1]]]] & 31;
|
||||
|
||||
gi12 = m_permutations[ii + m_permutations[jj + m_permutations[kk + 1 + m_permutations[ll + 1]]]] & 31;
|
||||
gi13 = m_permutations[ii + 1 + m_permutations[jj + m_permutations[kk + 1 + m_permutations[ll + 1]]]] & 31;
|
||||
gi14 = m_permutations[ii + m_permutations[jj + 1 + m_permutations[kk + 1 + m_permutations[ll + 1]]]] & 31;
|
||||
gi15 = m_permutations[ii + 1 + m_permutations[jj + 1 + m_permutations[kk + 1 + m_permutations[ll + 1]]]] & 31;
|
||||
|
||||
tempx = xc - x0;
|
||||
tempy = yc - y0;
|
||||
tempz = zc - z0;
|
||||
tempw = wc - w0;
|
||||
|
||||
Cx = tempx * tempx * tempx * (tempx * (tempx * 6 - 15) + 10);
|
||||
Cy = tempy * tempy * tempy * (tempy * (tempy * 6 - 15) + 10);
|
||||
Cz = tempz * tempz * tempz * (tempz * (tempz * 6 - 15) + 10);
|
||||
Cw = tempw * tempw * tempw * (tempw * (tempw * 6 - 15) + 10);
|
||||
|
||||
s[0] = s_gradients4[gi0][0]*tempx + s_gradients4[gi0][1]*tempy + s_gradients4[gi0][2]*tempz + s_gradients4[gi0][3]*tempw;
|
||||
|
||||
tempx = xc - (x0+1);
|
||||
t[0] = s_gradients4[gi1][0]*tempx + s_gradients4[gi1][1]*tempy + s_gradients4[gi1][2]*tempz + s_gradients4[gi1][3]*tempw;
|
||||
|
||||
tempy = yc - (y0+1);
|
||||
v[0] = s_gradients4[gi3][0]*tempx + s_gradients4[gi3][1]*tempy + s_gradients4[gi3][2]*tempz + s_gradients4[gi3][3]*tempw;
|
||||
|
||||
tempx = xc - x0;
|
||||
u[0] = s_gradients4[gi2][0]*tempx + s_gradients4[gi2][1]*tempy + s_gradients4[gi2][2]*tempz + s_gradients4[gi2][3]*tempw;
|
||||
|
||||
tempy = yc - y0;
|
||||
tempz = zc - (z0+1);
|
||||
s[1] = s_gradients4[gi4][0]*tempx + s_gradients4[gi4][1]*tempy + s_gradients4[gi4][2]*tempz + s_gradients4[gi4][3]*tempw;
|
||||
|
||||
tempx = xc - (x0+1);
|
||||
t[1] = s_gradients4[gi5][0]*tempx + s_gradients4[gi5][1]*tempy + s_gradients4[gi5][2]*tempz + s_gradients4[gi5][3]*tempw;
|
||||
|
||||
tempy = yc - (y0+1);
|
||||
v[1] = s_gradients4[gi7][0]*tempx + s_gradients4[gi7][1]*tempy + s_gradients4[gi7][2]*tempz + s_gradients4[gi7][3]*tempw;
|
||||
|
||||
tempx = xc - x0;
|
||||
u[1] = s_gradients4[gi6][0]*tempx + s_gradients4[gi6][1]*tempy + s_gradients4[gi6][2]*tempz + s_gradients4[gi6][3]*tempw;
|
||||
|
||||
|
||||
tempy = yc - y0;
|
||||
tempz = zc - z0;
|
||||
tempw = wc - (w0+1);
|
||||
s[2] = s_gradients4[gi8][0]*tempx + s_gradients4[gi8][1]*tempy + s_gradients4[gi8][2]*tempz + s_gradients4[gi8][3]*tempw;
|
||||
|
||||
tempx = xc - (x0+1);
|
||||
t[2] = s_gradients4[gi9][0]*tempx + s_gradients4[gi9][1]*tempy + s_gradients4[gi9][2]*tempz + s_gradients4[gi9][3]*tempw;
|
||||
|
||||
tempy = yc - (y0+1);
|
||||
v[2] = s_gradients4[gi11][0]*tempx + s_gradients4[gi11][1]*tempy + s_gradients4[gi11][2]*tempz + s_gradients4[gi11][3]*tempw;
|
||||
|
||||
tempx = xc - x0;
|
||||
u[2] = s_gradients4[gi10][0]*tempx + s_gradients4[gi10][1]*tempy + s_gradients4[gi10][2]*tempz + s_gradients4[gi10][3]*tempw;
|
||||
|
||||
|
||||
tempy = yc - y0;
|
||||
tempz = zc - (z0+1);
|
||||
s[3] = s_gradients4[gi12][0]*tempx + s_gradients4[gi12][1]*tempy + s_gradients4[gi12][2]*tempz + s_gradients4[gi12][3]*tempw;
|
||||
|
||||
tempx = xc - (x0+1);
|
||||
t[3] = s_gradients4[gi13][0]*tempx + s_gradients4[gi13][1]*tempy + s_gradients4[gi13][2]*tempz + s_gradients4[gi13][3]*tempw;
|
||||
|
||||
tempy = yc - (y0+1);
|
||||
v[3] = s_gradients4[gi15][0]*tempx + s_gradients4[gi15][1]*tempy + s_gradients4[gi15][2]*tempz + s_gradients4[gi15][3]*tempw;
|
||||
|
||||
tempx = xc - x0;
|
||||
u[3] = s_gradients4[gi14][0]*tempx + s_gradients4[gi14][1]*tempy + s_gradients4[gi14][2]*tempz + s_gradients4[gi14][3]*tempw;
|
||||
|
||||
Li1 = s[0] + Cx*(t[0]-s[0]);
|
||||
Li2 = u[0] + Cx*(v[0]-u[0]);
|
||||
Li3 = s[1] + Cx*(t[1]-s[1]);
|
||||
Li4 = u[1] + Cx*(v[1]-u[1]);
|
||||
Li5 = s[2] + Cx*(t[2]-s[2]);
|
||||
Li6 = u[2] + Cx*(v[2]-u[2]);
|
||||
Li7 = s[3] + Cx*(t[3]-s[3]);
|
||||
Li8 = u[3] + Cx*(v[3]-u[3]);
|
||||
|
||||
Li9 = Li1 + Cy*(Li2-Li1);
|
||||
Li10 = Li3 + Cy*(Li4-Li3);
|
||||
Li11 = Li5 + Cy*(Li6-Li5);
|
||||
Li12 = Li7 + Cy*(Li8-Li7);
|
||||
|
||||
Li13 = Li9 + Cz*(Li10-Li9);
|
||||
Li14 = Li11 + Cz*(Li12-Li11);
|
||||
|
||||
return Li13 + Cw*(Li14-Li13);
|
||||
}
|
||||
}
|
||||
@@ -1,374 +0,0 @@
|
||||
// Copyright (C) 2017 Rémi Bèges
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/Simplex.hpp>
|
||||
#include <Nazara/Noise/NoiseTools.hpp>
|
||||
#include <Nazara/Noise/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr float s_SkewCoeff2D = 0.5f * (float(M_SQRT3) - 1.f);
|
||||
constexpr float s_UnskewCoeff2D = (3.f - float(M_SQRT3))/6.f;
|
||||
constexpr float s_SkewCoeff3D = 1.f / 3.f;
|
||||
constexpr float s_UnskewCoeff3D = 1.f / 6.f;
|
||||
constexpr float s_SkewCoeff4D = (float(M_SQRT5) - 1.f)/4.f;
|
||||
constexpr float s_UnskewCoeff4D = (5.f - float(M_SQRT5))/20.f;
|
||||
}
|
||||
|
||||
Simplex::Simplex(unsigned int seed)
|
||||
{
|
||||
SetSeed(seed);
|
||||
Shuffle();
|
||||
}
|
||||
|
||||
float Simplex::Get(float x, float y, float scale) const
|
||||
{
|
||||
float xc = x * scale;
|
||||
float yc = y * scale;
|
||||
|
||||
float sum = (xc + yc) * s_SkewCoeff2D;
|
||||
Vector2i skewedCubeOrigin(fastfloor(xc + sum), fastfloor(yc + sum));
|
||||
|
||||
sum = (skewedCubeOrigin.x + skewedCubeOrigin.y) * s_UnskewCoeff2D;
|
||||
Vector2f unskewedCubeOrigin(skewedCubeOrigin.x - sum, skewedCubeOrigin.y - sum);
|
||||
|
||||
Vector2f unskewedDistToOrigin(xc - unskewedCubeOrigin.x, yc - unskewedCubeOrigin.y);
|
||||
|
||||
Vector2ui off1;
|
||||
if(unskewedDistToOrigin.x > unskewedDistToOrigin.y)
|
||||
off1.Set(1, 0);
|
||||
else
|
||||
off1.Set(0, 1);
|
||||
|
||||
std::array<Vector2f, 3> d;
|
||||
d[0] = -unskewedDistToOrigin;
|
||||
d[1] = d[0] + Vector2f(off1) - Vector2f(s_UnskewCoeff2D);
|
||||
d[2] = d[0] + Vector2f(1.f - 2.f * s_UnskewCoeff2D);
|
||||
|
||||
Vector2i offset(skewedCubeOrigin.x & 255, skewedCubeOrigin.y & 255);
|
||||
std::array<std::size_t, 3> gi = {
|
||||
{
|
||||
m_permutations[offset.x + m_permutations[offset.y]] & 7,
|
||||
m_permutations[offset.x + off1.x + m_permutations[offset.y + off1.y]] & 7,
|
||||
m_permutations[offset.x + 1 + m_permutations[offset.y + 1]] & 7
|
||||
}
|
||||
};
|
||||
|
||||
float n = 0.f;
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
{
|
||||
float c = 0.5f - d[i].x * d[i].x - d[i].y *d[i].y;
|
||||
if (c > 0.f)
|
||||
n += c * c * c * c * (s_gradients2[gi[i]].x * d[i].x + s_gradients2[gi[i]].y * d[i].y);
|
||||
}
|
||||
|
||||
return n*70.f;
|
||||
}
|
||||
|
||||
float Simplex::Get(float x, float y, float z, float scale) const
|
||||
{
|
||||
float xc, yc, zc;
|
||||
int ii,jj,kk;
|
||||
int gi0,gi1,gi2,gi3;
|
||||
int skewedCubeOriginx,skewedCubeOriginy,skewedCubeOriginz;
|
||||
|
||||
int off1x,off1y,off1z;
|
||||
int off2x,off2y,off2z;
|
||||
float n1,n2,n3,n4;
|
||||
float c1,c2,c3,c4;
|
||||
|
||||
float sum;
|
||||
float unskewedCubeOriginx,unskewedCubeOriginy,unskewedCubeOriginz;
|
||||
float unskewedDistToOriginx,unskewedDistToOriginy,unskewedDistToOriginz;
|
||||
float d1x,d1y,d1z;
|
||||
float d2x,d2y,d2z;
|
||||
float d3x,d3y,d3z;
|
||||
float d4x,d4y,d4z;
|
||||
|
||||
xc = x * scale;
|
||||
yc = y * scale;
|
||||
zc = z * scale;
|
||||
|
||||
sum = (xc + yc + zc) * s_SkewCoeff3D;
|
||||
skewedCubeOriginx = fastfloor(xc + sum);
|
||||
skewedCubeOriginy = fastfloor(yc + sum);
|
||||
skewedCubeOriginz = fastfloor(zc + sum);
|
||||
|
||||
sum = (skewedCubeOriginx + skewedCubeOriginy + skewedCubeOriginz) * s_UnskewCoeff3D;
|
||||
unskewedCubeOriginx = skewedCubeOriginx - sum;
|
||||
unskewedCubeOriginy = skewedCubeOriginy - sum;
|
||||
unskewedCubeOriginz = skewedCubeOriginz - sum;
|
||||
|
||||
unskewedDistToOriginx = xc - unskewedCubeOriginx;
|
||||
unskewedDistToOriginy = yc - unskewedCubeOriginy;
|
||||
unskewedDistToOriginz = zc - unskewedCubeOriginz;
|
||||
|
||||
if(unskewedDistToOriginx >= unskewedDistToOriginy)
|
||||
{
|
||||
if(unskewedDistToOriginy >= unskewedDistToOriginz)
|
||||
{
|
||||
off1x = 1;
|
||||
off1y = 0;
|
||||
off1z = 0;
|
||||
off2x = 1;
|
||||
off2y = 1;
|
||||
off2z = 0;
|
||||
}
|
||||
else if(unskewedDistToOriginx >= unskewedDistToOriginz)
|
||||
{
|
||||
off1x = 1;
|
||||
off1y = 0;
|
||||
off1z = 0;
|
||||
off2x = 1;
|
||||
off2y = 0;
|
||||
off2z = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
off1x = 0;
|
||||
off1y = 0;
|
||||
off1z = 1;
|
||||
off2x = 1;
|
||||
off2y = 0;
|
||||
off2z = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(unskewedDistToOriginy < unskewedDistToOriginz)
|
||||
{
|
||||
off1x = 0;
|
||||
off1y = 0;
|
||||
off1z = 1;
|
||||
off2x = 0;
|
||||
off2y = 1;
|
||||
off2z = 1;
|
||||
}
|
||||
else if(unskewedDistToOriginx < unskewedDistToOriginz)
|
||||
{
|
||||
off1x = 0;
|
||||
off1y = 1;
|
||||
off1z = 0;
|
||||
off2x = 0;
|
||||
off2y = 1;
|
||||
off2z = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
off1x = 0;
|
||||
off1y = 1;
|
||||
off1z = 0;
|
||||
off2x = 1;
|
||||
off2y = 1;
|
||||
off2z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
d1x = unskewedDistToOriginx;
|
||||
d1y = unskewedDistToOriginy;
|
||||
d1z = unskewedDistToOriginz;
|
||||
|
||||
d2x = d1x - off1x + s_UnskewCoeff3D;
|
||||
d2y = d1y - off1y + s_UnskewCoeff3D;
|
||||
d2z = d1z - off1z + s_UnskewCoeff3D;
|
||||
|
||||
d3x = d1x - off2x + 2.f*s_UnskewCoeff3D;
|
||||
d3y = d1y - off2y + 2.f*s_UnskewCoeff3D;
|
||||
d3z = d1z - off2z + 2.f*s_UnskewCoeff3D;
|
||||
|
||||
d4x = d1x - 1.f + 3.f*s_UnskewCoeff3D;
|
||||
d4y = d1y - 1.f + 3.f*s_UnskewCoeff3D;
|
||||
d4z = d1z - 1.f + 3.f*s_UnskewCoeff3D;
|
||||
|
||||
ii = skewedCubeOriginx & 255;
|
||||
jj = skewedCubeOriginy & 255;
|
||||
kk = skewedCubeOriginz & 255;
|
||||
|
||||
gi0 = m_permutations[ii + m_permutations[jj + m_permutations[kk ]]] % 12;
|
||||
gi1 = m_permutations[ii + off1x + m_permutations[jj + off1y + m_permutations[kk + off1z ]]] % 12;
|
||||
gi2 = m_permutations[ii + off2x + m_permutations[jj + off2y + m_permutations[kk + off2z ]]] % 12;
|
||||
gi3 = m_permutations[ii + 1 + m_permutations[jj + 1 + m_permutations[kk + 1 ]]] % 12;
|
||||
|
||||
c1 = 0.6f - d1x * d1x - d1y * d1y - d1z * d1z;
|
||||
c2 = 0.6f - d2x * d2x - d2y * d2y - d2z * d2z;
|
||||
c3 = 0.6f - d3x * d3x - d3y * d3y - d3z * d3z;
|
||||
c4 = 0.6f - d4x * d4x - d4y * d4y - d4z * d4z;
|
||||
|
||||
if(c1 < 0)
|
||||
n1 = 0;
|
||||
else
|
||||
n1 = c1*c1*c1*c1*(s_gradients3[gi0][0] * d1x + s_gradients3[gi0][1] * d1y + s_gradients3[gi0][2] * d1z);
|
||||
|
||||
if(c2 < 0)
|
||||
n2 = 0;
|
||||
else
|
||||
n2 = c2*c2*c2*c2*(s_gradients3[gi1][0] * d2x + s_gradients3[gi1][1] * d2y + s_gradients3[gi1][2] * d2z);
|
||||
|
||||
if(c3 < 0)
|
||||
n3 = 0;
|
||||
else
|
||||
n3 = c3*c3*c3*c3*(s_gradients3[gi2][0] * d3x + s_gradients3[gi2][1] * d3y + s_gradients3[gi2][2] * d3z);
|
||||
|
||||
if(c4 < 0)
|
||||
n4 = 0;
|
||||
else
|
||||
n4 = c4*c4*c4*c4*(s_gradients3[gi3][0] * d4x + s_gradients3[gi3][1] * d4y + s_gradients3[gi3][2] * d4z);
|
||||
|
||||
return (n1+n2+n3+n4)*32;
|
||||
}
|
||||
|
||||
float Simplex::Get(float x, float y, float z, float w, float scale) const
|
||||
{
|
||||
static std::array<Vector4ui, 64> lookupTable =
|
||||
{
|
||||
{
|
||||
{0,1,2,3}, {0,1,3,2}, {0,0,0,0}, {0,2,3,1}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {1,2,3,0},
|
||||
{0,2,1,3}, {0,0,0,0}, {0,3,1,2}, {0,3,2,1}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {1,3,2,0},
|
||||
{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0},
|
||||
{1,2,0,3}, {0,0,0,0}, {1,3,0,2}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {2,3,0,1}, {2,3,1,0},
|
||||
{1,0,2,3}, {1,0,3,2}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {2,0,3,1}, {0,0,0,0}, {2,1,3,0},
|
||||
{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0},
|
||||
{2,0,1,3}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {3,0,1,2}, {3,0,2,1}, {0,0,0,0}, {3,1,2,0},
|
||||
{2,1,0,3}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {3,1,0,2}, {0,0,0,0}, {3,2,0,1}, {3,2,1,0}
|
||||
}
|
||||
};
|
||||
|
||||
float xc,yc,zc,wc;
|
||||
int ii,jj,kk,ll;
|
||||
int gi0,gi1,gi2,gi3,gi4;
|
||||
int skewedCubeOriginx,skewedCubeOriginy,skewedCubeOriginz,skewedCubeOriginw;
|
||||
|
||||
int off1x,off1y,off1z,off1w;
|
||||
int off2x,off2y,off2z,off2w;
|
||||
int off3x,off3y,off3z,off3w;
|
||||
|
||||
int c;
|
||||
float n1,n2,n3,n4,n5;
|
||||
float c1,c2,c3,c4,c5;
|
||||
|
||||
float sum;
|
||||
float unskewedCubeOriginx,unskewedCubeOriginy,unskewedCubeOriginz,unskewedCubeOriginw;
|
||||
float unskewedDistToOriginx,unskewedDistToOriginy,unskewedDistToOriginz,unskewedDistToOriginw;
|
||||
float d1x,d2x,d3x,d4x,d5x;
|
||||
float d1y,d2y,d3y,d4y,d5y;
|
||||
float d1z,d2z,d3z,d4z,d5z;
|
||||
float d1w,d2w,d3w,d4w,d5w;
|
||||
|
||||
xc = x * scale;
|
||||
yc = y * scale;
|
||||
zc = z * scale;
|
||||
wc = w * scale;
|
||||
|
||||
sum = (xc + yc + zc + wc) * s_SkewCoeff4D;
|
||||
skewedCubeOriginx = fastfloor(xc + sum);
|
||||
skewedCubeOriginy = fastfloor(yc + sum);
|
||||
skewedCubeOriginz = fastfloor(zc + sum);
|
||||
skewedCubeOriginw = fastfloor(wc + sum);
|
||||
|
||||
sum = (skewedCubeOriginx + skewedCubeOriginy + skewedCubeOriginz + skewedCubeOriginw) * s_UnskewCoeff4D;
|
||||
unskewedCubeOriginx = skewedCubeOriginx - sum;
|
||||
unskewedCubeOriginy = skewedCubeOriginy - sum;
|
||||
unskewedCubeOriginz = skewedCubeOriginz - sum;
|
||||
unskewedCubeOriginw = skewedCubeOriginw - sum;
|
||||
|
||||
unskewedDistToOriginx = xc - unskewedCubeOriginx;
|
||||
unskewedDistToOriginy = yc - unskewedCubeOriginy;
|
||||
unskewedDistToOriginz = zc - unskewedCubeOriginz;
|
||||
unskewedDistToOriginw = wc - unskewedCubeOriginw;
|
||||
|
||||
c = 0;
|
||||
c += (unskewedDistToOriginx > unskewedDistToOriginy) ? 32 : 0;
|
||||
c += (unskewedDistToOriginx > unskewedDistToOriginz) ? 16 : 0;
|
||||
c += (unskewedDistToOriginy > unskewedDistToOriginz) ? 8 : 0;
|
||||
c += (unskewedDistToOriginx > unskewedDistToOriginw) ? 4 : 0;
|
||||
c += (unskewedDistToOriginy > unskewedDistToOriginw) ? 2 : 0;
|
||||
c += (unskewedDistToOriginz > unskewedDistToOriginw) ? 1 : 0;
|
||||
|
||||
off1x = lookupTable[c][0] >= 3 ? 1 : 0;
|
||||
off1y = lookupTable[c][1] >= 3 ? 1 : 0;
|
||||
off1z = lookupTable[c][2] >= 3 ? 1 : 0;
|
||||
off1w = lookupTable[c][3] >= 3 ? 1 : 0;
|
||||
|
||||
off2x = lookupTable[c][0] >= 2 ? 1 : 0;
|
||||
off2y = lookupTable[c][1] >= 2 ? 1 : 0;
|
||||
off2z = lookupTable[c][2] >= 2 ? 1 : 0;
|
||||
off2w = lookupTable[c][3] >= 2 ? 1 : 0;
|
||||
|
||||
off3x = lookupTable[c][0] >= 1 ? 1 : 0;
|
||||
off3y = lookupTable[c][1] >= 1 ? 1 : 0;
|
||||
off3z = lookupTable[c][2] >= 1 ? 1 : 0;
|
||||
off3w = lookupTable[c][3] >= 1 ? 1 : 0;
|
||||
|
||||
d1x = unskewedDistToOriginx;
|
||||
d1y = unskewedDistToOriginy;
|
||||
d1z = unskewedDistToOriginz;
|
||||
d1w = unskewedDistToOriginw;
|
||||
|
||||
d2x = d1x - off1x + s_UnskewCoeff4D;
|
||||
d2y = d1y - off1y + s_UnskewCoeff4D;
|
||||
d2z = d1z - off1z + s_UnskewCoeff4D;
|
||||
d2w = d1w - off1w + s_UnskewCoeff4D;
|
||||
|
||||
d3x = d1x - off2x + 2.f*s_UnskewCoeff4D;
|
||||
d3y = d1y - off2y + 2.f*s_UnskewCoeff4D;
|
||||
d3z = d1z - off2z + 2.f*s_UnskewCoeff4D;
|
||||
d3w = d1w - off2w + 2.f*s_UnskewCoeff4D;
|
||||
|
||||
d4x = d1x - off3x + 3.f*s_UnskewCoeff4D;
|
||||
d4y = d1y - off3y + 3.f*s_UnskewCoeff4D;
|
||||
d4z = d1z - off3z + 3.f*s_UnskewCoeff4D;
|
||||
d4w = d1w - off3w + 3.f*s_UnskewCoeff4D;
|
||||
|
||||
d5x = d1x - 1.f + 4*s_UnskewCoeff4D;
|
||||
d5y = d1y - 1.f + 4*s_UnskewCoeff4D;
|
||||
d5z = d1z - 1.f + 4*s_UnskewCoeff4D;
|
||||
d5w = d1w - 1.f + 4*s_UnskewCoeff4D;
|
||||
|
||||
ii = skewedCubeOriginx & 255;
|
||||
jj = skewedCubeOriginy & 255;
|
||||
kk = skewedCubeOriginz & 255;
|
||||
ll = skewedCubeOriginw & 255;
|
||||
|
||||
gi0 = m_permutations[ii + m_permutations[jj + m_permutations[kk + m_permutations[ll ]]]] & 31;
|
||||
gi1 = m_permutations[ii + off1x + m_permutations[jj + off1y + m_permutations[kk + off1z + m_permutations[ll + off1w]]]] & 31;
|
||||
gi2 = m_permutations[ii + off2x + m_permutations[jj + off2y + m_permutations[kk + off2z + m_permutations[ll + off2w]]]] & 31;
|
||||
gi3 = m_permutations[ii + off3x + m_permutations[jj + off3y + m_permutations[kk + off3z + m_permutations[ll + off3w]]]] & 31;
|
||||
gi4 = m_permutations[ii + 1 + m_permutations[jj + 1 + m_permutations[kk + 1 + m_permutations[ll + 1 ]]]] % 32;
|
||||
|
||||
c1 = 0.6f - d1x*d1x - d1y*d1y - d1z*d1z - d1w*d1w;
|
||||
c2 = 0.6f - d2x*d2x - d2y*d2y - d2z*d2z - d2w*d2w;
|
||||
c3 = 0.6f - d3x*d3x - d3y*d3y - d3z*d3z - d3w*d3w;
|
||||
c4 = 0.6f - d4x*d4x - d4y*d4y - d4z*d4z - d4w*d4w;
|
||||
c5 = 0.6f - d5x*d5x - d5y*d5y - d5z*d5z - d5w*d5w;
|
||||
|
||||
if(c1 < 0)
|
||||
n1 = 0;
|
||||
else
|
||||
n1 = c1*c1*c1*c1*(s_gradients4[gi0][0]*d1x + s_gradients4[gi0][1]*d1y + s_gradients4[gi0][2]*d1z + s_gradients4[gi0][3]*d1w);
|
||||
|
||||
if(c2 < 0)
|
||||
n2 = 0;
|
||||
else
|
||||
n2 = c2*c2*c2*c2*(s_gradients4[gi1][0]*d2x + s_gradients4[gi1][1]*d2y + s_gradients4[gi1][2]*d2z + s_gradients4[gi1][3]*d2w);
|
||||
|
||||
if(c3 < 0)
|
||||
n3 = 0;
|
||||
else
|
||||
n3 = c3*c3*c3*c3*(s_gradients4[gi2][0]*d3x + s_gradients4[gi2][1]*d3y + s_gradients4[gi2][2]*d3z + s_gradients4[gi2][3]*d3w);
|
||||
|
||||
if(c4 < 0)
|
||||
n4 = 0;
|
||||
else
|
||||
n4 = c4*c4*c4*c4*(s_gradients4[gi3][0]*d4x + s_gradients4[gi3][1]*d4y + s_gradients4[gi3][2]*d4z + s_gradients4[gi3][3]*d4w);
|
||||
|
||||
if(c5 < 0)
|
||||
n5 = 0;
|
||||
else
|
||||
n5 = c5*c5*c5*c5*(s_gradients4[gi4][0]*d5x + s_gradients4[gi4][1]*d5y + s_gradients4[gi4][2]*d5z + s_gradients4[gi4][3]*d5w);
|
||||
|
||||
return (n1+n2+n3+n4+n5)*27.f;
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
// Copyright (C) 2017 Rémi Bèges
|
||||
// This file is part of the "Nazara Engine - Noise module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Noise/Worley.hpp>
|
||||
#include <Nazara/Noise/NoiseTools.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Noise/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
static constexpr std::array<float, 4> m_functionScales = {
|
||||
{
|
||||
1.f / float(M_SQRT2),
|
||||
0.5f / float(M_SQRT2),
|
||||
0.5f / float(M_SQRT2),
|
||||
0.5f / float(M_SQRT2)
|
||||
}
|
||||
};
|
||||
}
|
||||
Worley::Worley() :
|
||||
m_function(WorleyFunction_F1)
|
||||
{
|
||||
}
|
||||
|
||||
Worley::Worley(unsigned int seed) :
|
||||
Worley()
|
||||
{
|
||||
SetSeed(seed);
|
||||
Shuffle();
|
||||
}
|
||||
|
||||
float Worley::Get(float x, float y, float scale) const
|
||||
{
|
||||
std::map<float, Vector2f> featurePoints;
|
||||
|
||||
float xc, yc;
|
||||
int x0, y0;
|
||||
float fractx, fracty;
|
||||
|
||||
xc = x * scale;
|
||||
yc = y * scale;
|
||||
|
||||
x0 = fastfloor(xc);
|
||||
y0 = fastfloor(yc);
|
||||
|
||||
fractx = xc - static_cast<float>(x0);
|
||||
fracty = yc - static_cast<float>(y0);
|
||||
|
||||
featurePoints.clear();
|
||||
|
||||
SquareTest(x0,y0,xc,yc,featurePoints);
|
||||
|
||||
std::size_t functionIndex = static_cast<std::size_t>(m_function);
|
||||
|
||||
auto it = featurePoints.begin();
|
||||
std::advance(it, functionIndex);
|
||||
|
||||
if(fractx < it->first)
|
||||
SquareTest(x0 - 1,y0,xc,yc,featurePoints);
|
||||
|
||||
it = featurePoints.begin();
|
||||
std::advance(it, functionIndex);
|
||||
|
||||
if(1.f - fractx < it->first)
|
||||
SquareTest(x0 + 1,y0,xc,yc,featurePoints);
|
||||
|
||||
it = featurePoints.begin();
|
||||
std::advance(it, functionIndex);
|
||||
|
||||
if(fracty < it->first)
|
||||
SquareTest(x0,y0 - 1,xc,yc,featurePoints);
|
||||
|
||||
it = featurePoints.begin();
|
||||
std::advance(it, functionIndex);
|
||||
|
||||
if (1.f - fracty < it->first)
|
||||
SquareTest(x0,y0 + 1,xc,yc,featurePoints);
|
||||
|
||||
it = featurePoints.begin();
|
||||
std::advance(it, functionIndex);
|
||||
|
||||
if (fractx < it->first && fracty < it->first)
|
||||
SquareTest(x0 - 1, y0 - 1,xc,yc,featurePoints);
|
||||
|
||||
it = featurePoints.begin();
|
||||
std::advance(it, functionIndex);
|
||||
|
||||
if (1.f - fractx < it->first && fracty < it->first)
|
||||
SquareTest(x0 + 1, y0 - 1,xc,yc,featurePoints);
|
||||
|
||||
it = featurePoints.begin();
|
||||
std::advance(it, functionIndex);
|
||||
|
||||
if (fractx < it->first && 1.f - fracty < it->first)
|
||||
SquareTest(x0 - 1, y0 + 1,xc,yc,featurePoints);
|
||||
|
||||
it = featurePoints.begin();
|
||||
std::advance(it, functionIndex);
|
||||
|
||||
if(1.f - fractx < it->first && 1.f - fracty < it->first)
|
||||
SquareTest(x0 + 1, y0 + 1,xc,yc,featurePoints);
|
||||
|
||||
it = featurePoints.begin();
|
||||
std::advance(it, functionIndex);
|
||||
|
||||
return it->first * m_functionScales[functionIndex];
|
||||
}
|
||||
|
||||
float Worley::Get(float /*x*/, float /*y*/, float /*z*/, float /*scale*/) const
|
||||
{
|
||||
throw std::runtime_error("Worley 3D not available yet.");
|
||||
}
|
||||
|
||||
float Worley::Get(float /*x*/, float /*y*/, float /*z*/, float /*w*/, float /*scale*/) const
|
||||
{
|
||||
throw std::runtime_error("Worley 4D not available yet.");
|
||||
}
|
||||
|
||||
void Worley::Set(WorleyFunction func)
|
||||
{
|
||||
m_function = func;
|
||||
}
|
||||
|
||||
void Worley::SquareTest(int xi, int yi, float x, float y, std::map<float, Vector2f>& featurePoints) const
|
||||
{
|
||||
int ii = xi & 255;
|
||||
int jj = yi & 255;
|
||||
|
||||
std::size_t seed = m_permutations[ii + m_permutations[jj]];
|
||||
|
||||
//On initialise notre rng avec seed
|
||||
std::minstd_rand0 randomNumberGenerator(static_cast<unsigned int>(seed));
|
||||
|
||||
//On prend un nombre de points à déterminer dans le cube, compris entre 1 et 8
|
||||
std::size_t m = (seed & 7) + 1;
|
||||
|
||||
//On calcule les emplacements des différents points
|
||||
for(std::size_t i(0) ; i < m; ++i)
|
||||
{
|
||||
Nz::Vector2f featurePoint;
|
||||
featurePoint.x = (randomNumberGenerator() & 1023) / 1023.f + static_cast<float>(xi);
|
||||
featurePoint.y = (randomNumberGenerator() & 1023) / 1023.f + static_cast<float>(yi);
|
||||
|
||||
// TODO : Check order is correct
|
||||
float distance = std::sqrt((featurePoint.x - x) * (featurePoint.x - x) +
|
||||
(featurePoint.y - y) * (featurePoint.y - y));
|
||||
|
||||
//Insertion dans la liste triée
|
||||
featurePoints[distance] = featurePoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,7 +347,7 @@ namespace Nz
|
||||
m_vertices[i] = *vertices++;
|
||||
}
|
||||
else // Fast path
|
||||
std::memcpy(m_vertices.data(), vertices, vertexCount*sizeof(Vector3f));
|
||||
std::memcpy(m_vertices.data(), vertices.GetPtr(), vertexCount*sizeof(Vector3f));
|
||||
}
|
||||
|
||||
ConvexCollider3D::ConvexCollider3D(SparsePtr<const Vector3f> vertices, unsigned int vertexCount, float tolerance, const Vector3f& translation, const Quaternionf& rotation) :
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
// Un grand merci à Laurent Gomila pour la SFML qui m'aura bien aidé à réaliser cette implémentation
|
||||
|
||||
#include <Nazara/Platform/Win32/WindowImpl.hpp>
|
||||
#include <Nazara/Core/ConditionVariable.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Core/Thread.hpp>
|
||||
#include <Nazara/Platform/Config.hpp>
|
||||
#include <Nazara/Platform/Cursor.hpp>
|
||||
#include <Nazara/Platform/Icon.hpp>
|
||||
@@ -130,15 +127,15 @@ namespace Nz
|
||||
|
||||
if (async)
|
||||
{
|
||||
Mutex mutex;
|
||||
ConditionVariable condition;
|
||||
std::mutex mutex;
|
||||
std::condition_variable condition;
|
||||
m_threadActive = true;
|
||||
|
||||
// On attend que la fenêtre soit créée
|
||||
mutex.Lock();
|
||||
m_thread = Thread(WindowThread, &m_handle, win32StyleEx, title, win32Style, fullscreen, Rectui(x, y, width, height), this, &mutex, &condition);
|
||||
condition.Wait(&mutex);
|
||||
mutex.Unlock();
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
m_thread = std::thread(WindowThread, std::ref(m_handle), win32StyleEx, title, win32Style, fullscreen, Rectui(x, y, width, height), this, std::ref(mutex), std::ref(condition));
|
||||
|
||||
condition.wait(lock);
|
||||
}
|
||||
else
|
||||
m_handle = CreateWindowExW(win32StyleEx, className, title.GetWideString().data(), win32Style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), this);
|
||||
@@ -186,12 +183,12 @@ namespace Nz
|
||||
{
|
||||
if (m_style & WindowStyle_Threaded)
|
||||
{
|
||||
if (m_thread.IsJoinable())
|
||||
if (m_thread.joinable())
|
||||
{
|
||||
m_threadActive = false;
|
||||
PostMessageW(m_handle, WM_NULL, 0, 0); // Wake up our thread
|
||||
|
||||
m_thread.Join();
|
||||
m_thread.join();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1151,24 +1148,24 @@ namespace Nz
|
||||
return style;
|
||||
}
|
||||
|
||||
void WindowImpl::WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition)
|
||||
void WindowImpl::WindowThread(HWND& handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, std::mutex& mutex, std::condition_variable& condition)
|
||||
{
|
||||
HWND& winHandle = *handle;
|
||||
winHandle = CreateWindowExW(styleEx, className, title.GetWideString().data(), style, dimensions.x, dimensions.y, dimensions.width, dimensions.height, nullptr, nullptr, GetModuleHandle(nullptr), window);
|
||||
handle = CreateWindowExW(styleEx, className, title.GetWideString().data(), style, dimensions.x, dimensions.y, dimensions.width, dimensions.height, nullptr, nullptr, GetModuleHandle(nullptr), window);
|
||||
|
||||
if (winHandle)
|
||||
if (handle)
|
||||
window->PrepareWindow(fullscreen);
|
||||
|
||||
mutex->Lock();
|
||||
condition->Signal();
|
||||
mutex->Unlock(); // mutex and condition may be destroyed after this line
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
condition.notify_all();
|
||||
}
|
||||
|
||||
if (!winHandle)
|
||||
if (!handle)
|
||||
return;
|
||||
|
||||
while (window->m_threadActive)
|
||||
window->ProcessEvents(true);
|
||||
|
||||
DestroyWindow(winHandle);
|
||||
DestroyWindow(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Core/Thread.hpp>
|
||||
#include <Nazara/Math/Rect.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Platform/Config.hpp>
|
||||
@@ -19,12 +18,13 @@
|
||||
#include <Nazara/Platform/Mouse.hpp>
|
||||
#include <Nazara/Platform/VideoMode.hpp>
|
||||
#include <Nazara/Platform/Window.hpp>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <windows.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class ConditionVariable;
|
||||
class Mutex;
|
||||
class Window;
|
||||
|
||||
#undef IsMinimized // Conflits with windows.h redefinition
|
||||
@@ -87,7 +87,7 @@ namespace Nz
|
||||
static Keyboard::Key ConvertVirtualKey(WPARAM key, LPARAM flags);
|
||||
static LRESULT CALLBACK MessageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
static UInt32 RetrieveStyle(HWND window);
|
||||
static void WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition);
|
||||
static void WindowThread(HWND& handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, std::mutex& mutex, std::condition_variable& condition);
|
||||
|
||||
HCURSOR m_cursor;
|
||||
HWND m_handle;
|
||||
@@ -98,7 +98,7 @@ namespace Nz
|
||||
Vector2i m_mousePos;
|
||||
Vector2i m_position;
|
||||
Vector2ui m_size;
|
||||
Thread m_thread;
|
||||
std::thread m_thread;
|
||||
Window* m_parent;
|
||||
bool m_eventListener;
|
||||
bool m_keyRepeat;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <Nazara/Platform/Window.hpp>
|
||||
#include <Nazara/Core/CallOnExit.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/LockGuard.hpp>
|
||||
#include <Nazara/Platform/Cursor.hpp>
|
||||
#include <Nazara/Platform/Icon.hpp>
|
||||
|
||||
@@ -39,13 +38,10 @@ namespace Nz
|
||||
Window::Window(Window&& window) :
|
||||
m_events(std::move(window.m_events)),
|
||||
m_pendingEvents(std::move(window.m_pendingEvents)),
|
||||
m_eventCondition(std::move(window.m_eventCondition)),
|
||||
m_cursorController(std::move(window.m_cursorController)),
|
||||
m_cursor(std::move(window.m_cursor)),
|
||||
m_eventHandler(std::move(window.m_eventHandler)),
|
||||
m_icon(std::move(window.m_icon)),
|
||||
m_eventMutex(std::move(window.m_eventMutex)),
|
||||
m_eventConditionMutex(std::move(window.m_eventConditionMutex)),
|
||||
m_asyncWindow(window.m_asyncWindow),
|
||||
m_closed(window.m_asyncWindow),
|
||||
m_closeOnQuit(window.m_closeOnQuit),
|
||||
@@ -344,7 +340,7 @@ namespace Nz
|
||||
m_impl->ProcessEvents(block);
|
||||
else
|
||||
{
|
||||
LockGuard eventLock(m_eventMutex);
|
||||
std::lock_guard<std::mutex> eventLock(m_eventMutex);
|
||||
|
||||
for (const WindowEvent& event : m_pendingEvents)
|
||||
HandleEvent(event);
|
||||
@@ -570,16 +566,19 @@ namespace Nz
|
||||
}
|
||||
else
|
||||
{
|
||||
LockGuard lock(m_eventMutex);
|
||||
std::lock_guard<std::mutex> lock(m_eventMutex);
|
||||
|
||||
if (m_events.empty())
|
||||
{
|
||||
m_waitForEvent = true;
|
||||
m_eventConditionMutex.Lock();
|
||||
m_eventMutex.Unlock();
|
||||
m_eventCondition.Wait(&m_eventConditionMutex);
|
||||
m_eventMutex.Lock();
|
||||
m_eventConditionMutex.Unlock();
|
||||
{
|
||||
m_eventMutex.unlock();
|
||||
|
||||
std::unique_lock<std::mutex> eventConditionLock(m_eventConditionMutex);
|
||||
m_eventCondition.wait(eventConditionLock);
|
||||
|
||||
m_eventMutex.lock();
|
||||
}
|
||||
m_waitForEvent = false;
|
||||
}
|
||||
|
||||
@@ -601,13 +600,10 @@ namespace Nz
|
||||
{
|
||||
m_events = std::move(window.m_events);
|
||||
m_pendingEvents = std::move(window.m_pendingEvents);
|
||||
m_eventCondition = std::move(window.m_eventCondition);
|
||||
m_cursorController = std::move(window.m_cursorController);
|
||||
m_cursor = std::move(window.m_cursor);
|
||||
m_eventHandler = std::move(window.m_eventHandler);
|
||||
m_icon = std::move(window.m_icon);
|
||||
m_eventMutex = std::move(window.m_eventMutex);
|
||||
m_eventConditionMutex = std::move(window.m_eventConditionMutex);
|
||||
m_asyncWindow = window.m_asyncWindow;
|
||||
m_closed = window.m_asyncWindow;
|
||||
m_closeOnQuit = window.m_closeOnQuit;
|
||||
|
||||
@@ -165,15 +165,14 @@ namespace Nz
|
||||
|
||||
if (m_style & WindowStyle_Threaded)
|
||||
{
|
||||
Mutex mutex;
|
||||
ConditionVariable condition;
|
||||
std::mutex mutex;
|
||||
std::condition_variable condition;
|
||||
m_threadActive = true;
|
||||
|
||||
// Wait until the thread is ready
|
||||
mutex.Lock();
|
||||
m_thread = Thread(WindowThread, this, &mutex, &condition);
|
||||
condition.Wait(&mutex);
|
||||
mutex.Unlock();
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
m_thread = std::thread(WindowThread, this, std::ref(mutex), std::ref(condition));
|
||||
condition.wait(lock);
|
||||
}
|
||||
|
||||
// Set fullscreen video mode and switch to fullscreen if necessary
|
||||
@@ -238,10 +237,10 @@ namespace Nz
|
||||
{
|
||||
if (m_style & WindowStyle_Threaded)
|
||||
{
|
||||
if (m_thread.IsJoinable())
|
||||
if (m_thread.joinable())
|
||||
{
|
||||
m_threadActive = false;
|
||||
m_thread.Join();
|
||||
m_thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1577,11 +1576,12 @@ namespace Nz
|
||||
));
|
||||
}
|
||||
|
||||
void WindowImpl::WindowThread(WindowImpl* window, Mutex* mutex, ConditionVariable* condition)
|
||||
void WindowImpl::WindowThread(WindowImpl* window, std::mutex& mutex, std::condition_variable& condition)
|
||||
{
|
||||
mutex->Lock();
|
||||
condition->Signal();
|
||||
mutex->Unlock(); // mutex and condition may be destroyed after this line
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
condition.notify_all();
|
||||
}
|
||||
|
||||
if (!window->m_window)
|
||||
return;
|
||||
|
||||
@@ -10,18 +10,18 @@
|
||||
#define NAZARA_WINDOWIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Thread.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Platform/Enums.hpp>
|
||||
#include <Nazara/Platform/Keyboard.hpp>
|
||||
#include <Nazara/Platform/WindowHandle.hpp>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <xcb/randr.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class ConditionVariable;
|
||||
class Mutex;
|
||||
class Cursor;
|
||||
class Icon;
|
||||
class VideoMode;
|
||||
@@ -100,13 +100,13 @@ namespace Nz
|
||||
bool UpdateNormalHints();
|
||||
void UpdateEventQueue(xcb_generic_event_t* event);
|
||||
|
||||
static void WindowThread(WindowImpl* window, Mutex* mutex, ConditionVariable* condition);
|
||||
static void WindowThread(WindowImpl* window, std::mutex& mutex, std::condition_variable& condition);
|
||||
|
||||
xcb_window_t m_window;
|
||||
xcb_screen_t* m_screen;
|
||||
xcb_randr_get_screen_info_reply_t m_oldVideoMode;
|
||||
xcb_size_hints_t m_size_hints;
|
||||
Thread m_thread;
|
||||
std::thread m_thread;
|
||||
WindowStyleFlags m_style;
|
||||
Window* m_parent;
|
||||
bool m_eventListener;
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
#include <Nazara/Renderer/RenderWindow.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Thread.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
@@ -16,7 +17,7 @@ namespace Nz
|
||||
{
|
||||
int remainingTime = 1000/static_cast<int>(m_framerateLimit) - static_cast<int>(m_clock.GetMilliseconds());
|
||||
if (remainingTime > 0)
|
||||
Thread::Sleep(remainingTime);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(remainingTime));
|
||||
|
||||
m_clock.Restart();
|
||||
}
|
||||
|
||||
@@ -16,13 +16,13 @@ namespace Nz
|
||||
{
|
||||
struct AnimationImpl
|
||||
{
|
||||
std::unordered_map<String, UInt32> sequenceMap;
|
||||
std::unordered_map<String, std::size_t> sequenceMap;
|
||||
std::vector<Sequence> sequences;
|
||||
std::vector<SequenceJoint> sequenceJoints; // Uniquement pour les animations squelettiques
|
||||
AnimationType type;
|
||||
bool loopPointInterpolation = false;
|
||||
UInt32 frameCount;
|
||||
UInt32 jointCount; // Uniquement pour les animations squelettiques
|
||||
std::size_t frameCount;
|
||||
std::size_t jointCount; // Uniquement pour les animations squelettiques
|
||||
};
|
||||
|
||||
bool AnimationParams::IsValid() const
|
||||
@@ -50,7 +50,7 @@ namespace Nz
|
||||
|
||||
if (m_impl->type == AnimationType_Skeletal)
|
||||
{
|
||||
UInt32 endFrame = sequence.firstFrame + sequence.frameCount - 1;
|
||||
std::size_t endFrame = sequence.firstFrame + sequence.frameCount - 1;
|
||||
if (endFrame >= m_impl->frameCount)
|
||||
{
|
||||
m_impl->frameCount = endFrame+1;
|
||||
@@ -69,7 +69,7 @@ namespace Nz
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->sequenceMap[sequence.name] = static_cast<UInt32>(m_impl->sequences.size());
|
||||
m_impl->sequenceMap[sequence.name] = static_cast<std::size_t>(m_impl->sequences.size());
|
||||
}
|
||||
|
||||
m_impl->sequences.push_back(sequence);
|
||||
@@ -77,7 +77,7 @@ namespace Nz
|
||||
return true;
|
||||
}
|
||||
|
||||
void Animation::AnimateSkeleton(Skeleton* targetSkeleton, UInt32 frameA, UInt32 frameB, float interpolation) const
|
||||
void Animation::AnimateSkeleton(Skeleton* targetSkeleton, std::size_t frameA, std::size_t frameB, float interpolation) const
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
NazaraAssert(m_impl->type == AnimationType_Skeletal, "Animation is not skeletal");
|
||||
@@ -86,7 +86,7 @@ namespace Nz
|
||||
NazaraAssert(frameA < m_impl->frameCount, "FrameA is out of range");
|
||||
NazaraAssert(frameB < m_impl->frameCount, "FrameB is out of range");
|
||||
|
||||
for (UInt32 i = 0; i < m_impl->jointCount; ++i)
|
||||
for (std::size_t i = 0; i < m_impl->jointCount; ++i)
|
||||
{
|
||||
Joint* joint = targetSkeleton->GetJoint(i);
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
bool Animation::CreateSkeletal(UInt32 frameCount, UInt32 jointCount)
|
||||
bool Animation::CreateSkeletal(std::size_t frameCount, std::size_t jointCount)
|
||||
{
|
||||
NazaraAssert(frameCount > 0, "Frame count must be over zero");
|
||||
NazaraAssert(jointCount > 0, "Frame count must be over zero");
|
||||
@@ -133,14 +133,14 @@ namespace Nz
|
||||
m_impl->loopPointInterpolation = loopPointInterpolation;
|
||||
}
|
||||
|
||||
UInt32 Animation::GetFrameCount() const
|
||||
std::size_t Animation::GetFrameCount() const
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
|
||||
return m_impl->frameCount;
|
||||
}
|
||||
|
||||
UInt32 Animation::GetJointCount() const
|
||||
std::size_t Animation::GetJointCount() const
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace Nz
|
||||
return &m_impl->sequences[it->second];
|
||||
}
|
||||
|
||||
Sequence* Animation::GetSequence(UInt32 index)
|
||||
Sequence* Animation::GetSequence(std::size_t index)
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
NazaraAssert(index < m_impl->sequences.size(), "Sequence index out of range");
|
||||
@@ -183,7 +183,7 @@ namespace Nz
|
||||
return &m_impl->sequences[it->second];
|
||||
}
|
||||
|
||||
const Sequence* Animation::GetSequence(UInt32 index) const
|
||||
const Sequence* Animation::GetSequence(std::size_t index) const
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
NazaraAssert(index < m_impl->sequences.size(), "Sequence index out of range");
|
||||
@@ -191,14 +191,14 @@ namespace Nz
|
||||
return &m_impl->sequences[index];
|
||||
}
|
||||
|
||||
UInt32 Animation::GetSequenceCount() const
|
||||
std::size_t Animation::GetSequenceCount() const
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
|
||||
return static_cast<UInt32>(m_impl->sequences.size());
|
||||
return static_cast<std::size_t>(m_impl->sequences.size());
|
||||
}
|
||||
|
||||
UInt32 Animation::GetSequenceIndex(const String& sequenceName) const
|
||||
std::size_t Animation::GetSequenceIndex(const String& sequenceName) const
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace Nz
|
||||
return it->second;
|
||||
}
|
||||
|
||||
SequenceJoint* Animation::GetSequenceJoints(UInt32 frameIndex)
|
||||
SequenceJoint* Animation::GetSequenceJoints(std::size_t frameIndex)
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
NazaraAssert(m_impl->type == AnimationType_Skeletal, "Animation is not skeletal");
|
||||
@@ -220,7 +220,7 @@ namespace Nz
|
||||
return &m_impl->sequenceJoints[frameIndex*m_impl->jointCount];
|
||||
}
|
||||
|
||||
const SequenceJoint* Animation::GetSequenceJoints(UInt32 frameIndex) const
|
||||
const SequenceJoint* Animation::GetSequenceJoints(std::size_t frameIndex) const
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
NazaraAssert(m_impl->type == AnimationType_Skeletal, "Animation is not skeletal");
|
||||
@@ -242,7 +242,7 @@ namespace Nz
|
||||
return m_impl->sequenceMap.find(sequenceName) != m_impl->sequenceMap.end();
|
||||
}
|
||||
|
||||
bool Animation::HasSequence(UInt32 index) const
|
||||
bool Animation::HasSequence(std::size_t index) const
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace Nz
|
||||
m_impl->sequences.erase(sequenceIt);
|
||||
}
|
||||
|
||||
void Animation::RemoveSequence(UInt32 index)
|
||||
void Animation::RemoveSequence(std::size_t index)
|
||||
{
|
||||
NazaraAssert(m_impl, "Animation not created");
|
||||
NazaraAssert(index < m_impl->sequences.size(), "Sequence index out of range");
|
||||
@@ -289,7 +289,7 @@ namespace Nz
|
||||
m_impl->sequences.erase(it);
|
||||
}
|
||||
|
||||
AnimationRef Animation::LoadFromFile(const String& filePath, const AnimationParams& params)
|
||||
AnimationRef Animation::LoadFromFile(const std::filesystem::path& filePath, const AnimationParams& params)
|
||||
{
|
||||
return AnimationLoader::LoadFromFile(filePath, params);
|
||||
}
|
||||
|
||||
@@ -354,7 +354,7 @@ namespace Nz
|
||||
return s_defaultMinimumStepSize;
|
||||
}
|
||||
|
||||
FontRef Font::OpenFromFile(const String& filePath, const FontParams& params)
|
||||
FontRef Font::OpenFromFile(const std::filesystem::path& filePath, const FontParams& params)
|
||||
{
|
||||
return FontLoader::LoadFromFile(filePath, params);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Nz
|
||||
DDSLoader() = delete;
|
||||
~DDSLoader() = delete;
|
||||
|
||||
static bool IsSupported(const String& extension)
|
||||
static bool IsSupported(const std::string& extension)
|
||||
{
|
||||
return (extension == "dds");
|
||||
}
|
||||
|
||||
@@ -320,9 +320,9 @@ namespace Nz
|
||||
return characterSize/15.f; // Joker ?
|
||||
}
|
||||
|
||||
bool SetFile(const String& filePath)
|
||||
bool SetFile(const std::filesystem::path& filePath)
|
||||
{
|
||||
std::unique_ptr<File> file(new File);
|
||||
std::unique_ptr<File> file = std::make_unique<File>();
|
||||
if (!file->Open(filePath, OpenMode_ReadOnly))
|
||||
{
|
||||
NazaraError("Failed to open stream from file: " + Error::GetLastError());
|
||||
@@ -336,7 +336,7 @@ namespace Nz
|
||||
|
||||
void SetMemory(const void* data, std::size_t size)
|
||||
{
|
||||
m_ownedStream.reset(new MemoryView(data, size));
|
||||
m_ownedStream = std::make_unique<MemoryView>(data, size);
|
||||
SetStream(*m_ownedStream);
|
||||
}
|
||||
|
||||
@@ -349,14 +349,14 @@ namespace Nz
|
||||
m_stream.pos = 0;
|
||||
m_stream.size = static_cast<unsigned long>(stream.GetSize());
|
||||
|
||||
m_args.driver = 0;
|
||||
m_args.driver = nullptr;
|
||||
m_args.flags = FT_OPEN_STREAM;
|
||||
m_args.stream = &m_stream;
|
||||
}
|
||||
|
||||
bool SupportsOutline(float /*outlineThickness*/) const override
|
||||
{
|
||||
return s_stroker != 0;
|
||||
return s_stroker != nullptr;
|
||||
}
|
||||
|
||||
bool SupportsStyle(TextStyleFlags style) const override
|
||||
@@ -383,10 +383,10 @@ namespace Nz
|
||||
mutable unsigned int m_characterSize;
|
||||
};
|
||||
|
||||
bool IsSupported(const String& extension)
|
||||
bool IsSupported(const std::string& extension)
|
||||
{
|
||||
///FIXME: Je suppose qu'il en manque quelques unes..
|
||||
static std::set<String> supportedExtensions = {
|
||||
static std::set<std::string> supportedExtensions = {
|
||||
"afm", "bdf", "cff", "cid", "dfont", "fnt", "fon", "otf", "pfa", "pfb", "pfm", "pfr", "sfnt", "ttc", "tte", "ttf"
|
||||
};
|
||||
|
||||
@@ -408,12 +408,11 @@ namespace Nz
|
||||
return Ternary_False;
|
||||
}
|
||||
|
||||
FontRef LoadFile(const String& filePath, const FontParams& parameters)
|
||||
FontRef LoadFile(const std::filesystem::path& filePath, const FontParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
std::unique_ptr<FreeTypeStream> face(new FreeTypeStream);
|
||||
|
||||
std::unique_ptr<FreeTypeStream> face = std::make_unique<FreeTypeStream>();
|
||||
if (!face->SetFile(filePath))
|
||||
{
|
||||
NazaraError("Failed to open file");
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool IsSupported(const String& extension)
|
||||
bool IsSupported(const std::string& extension)
|
||||
{
|
||||
return (extension == "md2");
|
||||
}
|
||||
@@ -93,14 +93,14 @@ namespace Nz
|
||||
mesh->SetMaterialCount(header.num_skins);
|
||||
stream.SetCursorPos(header.offset_skins);
|
||||
{
|
||||
String baseDir = stream.GetDirectory();
|
||||
std::filesystem::path baseDir = stream.GetDirectory();
|
||||
char skin[68];
|
||||
for (unsigned int i = 0; i < header.num_skins; ++i)
|
||||
{
|
||||
stream.Read(skin, 68*sizeof(char));
|
||||
|
||||
ParameterList matData;
|
||||
matData.SetParameter(MaterialData::DiffuseTexturePath, baseDir + skin);
|
||||
matData.SetParameter(MaterialData::DiffuseTexturePath, (baseDir / skin).generic_u8string());
|
||||
|
||||
mesh->SetMaterialData(i, std::move(matData));
|
||||
}
|
||||
@@ -196,10 +196,8 @@ namespace Nz
|
||||
Vector2f invSkinSize(1.f / header.skinwidth, 1.f / header.skinheight);
|
||||
for (unsigned int i = 0; i < header.num_tris; ++i)
|
||||
{
|
||||
for (unsigned int j = 0; j < 3; ++j)
|
||||
for (unsigned int fixedIndex : indexFix) //< Reverse winding order
|
||||
{
|
||||
const unsigned int fixedIndex = indexFix[j]; //< Reverse winding order
|
||||
|
||||
const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]];
|
||||
Vector2f uv(texC.u, texC.v);
|
||||
uv *= invSkinSize;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Formats/MD5AnimLoader.hpp>
|
||||
#include <Nazara/Core/Directory.hpp>
|
||||
#include <Nazara/Utility/Formats/MD5AnimParser.hpp>
|
||||
#include <Nazara/Utility/Animation.hpp>
|
||||
#include <Nazara/Utility/Sequence.hpp>
|
||||
@@ -13,7 +12,7 @@ namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool IsSupported(const String& extension)
|
||||
bool IsSupported(const std::string& extension)
|
||||
{
|
||||
return (extension == "md5anim");
|
||||
}
|
||||
@@ -40,10 +39,10 @@ namespace Nz
|
||||
}
|
||||
|
||||
const MD5AnimParser::Frame* frames = parser.GetFrames();
|
||||
UInt32 frameCount = parser.GetFrameCount();
|
||||
UInt32 frameRate = parser.GetFrameRate();
|
||||
std::size_t frameCount = parser.GetFrameCount();
|
||||
std::size_t frameRate = parser.GetFrameRate();
|
||||
const MD5AnimParser::Joint* joints = parser.GetJoints();
|
||||
UInt32 jointCount = parser.GetJointCount();
|
||||
std::size_t jointCount = parser.GetJointCount();
|
||||
|
||||
// À ce stade, nous sommes censés avoir assez d'informations pour créer l'animation
|
||||
AnimationRef animation = Animation::New();
|
||||
@@ -53,7 +52,7 @@ namespace Nz
|
||||
sequence.firstFrame = 0;
|
||||
sequence.frameCount = frameCount;
|
||||
sequence.frameRate = frameRate;
|
||||
sequence.name = stream.GetPath().SubStringFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true);
|
||||
sequence.name = stream.GetPath().filename().generic_u8string();
|
||||
|
||||
animation->AddSequence(sequence);
|
||||
|
||||
@@ -63,10 +62,10 @@ namespace Nz
|
||||
Quaternionf rotationQuat = Quaternionf::RotationBetween(Vector3f::UnitX(), Vector3f::Forward()) *
|
||||
Quaternionf::RotationBetween(Vector3f::UnitZ(), Vector3f::Up());
|
||||
|
||||
for (UInt32 i = 0; i < jointCount; ++i)
|
||||
for (std::size_t i = 0; i < jointCount; ++i)
|
||||
{
|
||||
int parent = joints[i].parent;
|
||||
for (UInt32 j = 0; j < frameCount; ++j)
|
||||
for (std::size_t j = 0; j < frameCount; ++j)
|
||||
{
|
||||
SequenceJoint& sequenceJoint = sequenceJoints[j*jointCount + i];
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool IsSupported(const String& extension)
|
||||
bool IsSupported(const std::string& extension)
|
||||
{
|
||||
return (extension == "md5mesh");
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace Nz
|
||||
Quaternionf rotationQuat = Quaternionf::RotationBetween(Vector3f::UnitX(), Vector3f::Forward()) *
|
||||
Quaternionf::RotationBetween(Vector3f::UnitZ(), Vector3f::Up());
|
||||
|
||||
String baseDir = stream.GetDirectory();
|
||||
std::filesystem::path baseDir = stream.GetDirectory();
|
||||
|
||||
// Le hellknight de Doom 3 fait ~120 unités, et il est dit qu'il fait trois mètres
|
||||
// Nous réduisons donc la taille générale des fichiers MD5 de 1/40
|
||||
@@ -198,7 +198,7 @@ namespace Nz
|
||||
|
||||
// Material
|
||||
ParameterList matData;
|
||||
matData.SetParameter(MaterialData::FilePath, baseDir + md5Mesh.shader);
|
||||
matData.SetParameter(MaterialData::FilePath, (baseDir / md5Mesh.shader).generic_u8string());
|
||||
|
||||
mesh->SetMaterialData(i, std::move(matData));
|
||||
|
||||
@@ -211,11 +211,11 @@ namespace Nz
|
||||
|
||||
// Animation
|
||||
// Il est peut-être éventuellement possible que la probabilité que l'animation ait le même nom soit non-nulle.
|
||||
String path = stream.GetPath();
|
||||
if (!path.IsEmpty())
|
||||
std::filesystem::path path = stream.GetPath();
|
||||
if (!path.empty())
|
||||
{
|
||||
path.Replace(".md5mesh", ".md5anim", -8, String::CaseInsensitive);
|
||||
if (File::Exists(path))
|
||||
path.replace_extension(".md5anim");
|
||||
if (std::filesystem::exists(path))
|
||||
mesh->SetAnimation(path);
|
||||
}
|
||||
}
|
||||
@@ -306,7 +306,7 @@ namespace Nz
|
||||
|
||||
// Material
|
||||
ParameterList matData;
|
||||
matData.SetParameter(MaterialData::FilePath, baseDir + md5Mesh.shader);
|
||||
matData.SetParameter(MaterialData::FilePath, (baseDir / md5Mesh.shader).generic_u8string());
|
||||
|
||||
mesh->SetMaterialData(i, std::move(matData));
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <Nazara/Utility/Formats/MD5MeshParser.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/StringExt.hpp>
|
||||
#include <Nazara/Utility/Config.hpp>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
@@ -71,19 +72,19 @@ namespace Nz
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
case 'M': // MD5Version
|
||||
if (m_currentLine.GetWord(0) != "MD5Version")
|
||||
if (!StartsWith(m_currentLine, "MD5Version "))
|
||||
UnrecognizedLine();
|
||||
break;
|
||||
|
||||
case 'c': // commandline
|
||||
if (m_currentLine.GetWord(0) != "commandline")
|
||||
if (!StartsWith(m_currentLine, "commandline "))
|
||||
UnrecognizedLine();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'j': // joints
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (!m_currentLine.StartsWith("joints {"))
|
||||
if (!StartsWith(m_currentLine, "joints {"))
|
||||
{
|
||||
UnrecognizedLine();
|
||||
break;
|
||||
@@ -100,7 +101,7 @@ namespace Nz
|
||||
case 'm': // mesh
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (m_currentLine != "mesh {")
|
||||
if (!StartsWith(m_currentLine, "mesh {"))
|
||||
{
|
||||
UnrecognizedLine();
|
||||
break;
|
||||
@@ -113,7 +114,7 @@ namespace Nz
|
||||
Warning("More meshes than registred");
|
||||
#endif
|
||||
|
||||
m_meshes.push_back(Mesh());
|
||||
m_meshes.emplace_back();
|
||||
}
|
||||
|
||||
if (!ParseMesh())
|
||||
@@ -182,14 +183,25 @@ namespace Nz
|
||||
m_lineCount++;
|
||||
|
||||
m_currentLine = m_stream.ReadLine();
|
||||
if (m_currentLine.IsEmpty())
|
||||
continue;
|
||||
|
||||
m_currentLine = m_currentLine.SubStringTo("//"); // On ignore les commentaires
|
||||
m_currentLine.Simplify(); // Pour un traitement plus simple
|
||||
m_currentLine.Trim();
|
||||
if (std::size_t p = m_currentLine.find("//"); p != m_currentLine.npos)
|
||||
{
|
||||
if (p > 0)
|
||||
m_currentLine = m_currentLine.substr(0, p - 1);
|
||||
else
|
||||
m_currentLine.clear();
|
||||
}
|
||||
|
||||
// Trim left
|
||||
m_currentLine.erase(m_currentLine.begin(), std::find_if(m_currentLine.begin(), m_currentLine.end(), [](char c)
|
||||
{
|
||||
return !std::isspace(c);
|
||||
}));
|
||||
|
||||
if (m_currentLine.empty())
|
||||
continue;
|
||||
}
|
||||
while (m_currentLine.IsEmpty());
|
||||
while (m_currentLine.empty());
|
||||
}
|
||||
else
|
||||
m_keepLastLine = false;
|
||||
@@ -197,9 +209,9 @@ namespace Nz
|
||||
return true;
|
||||
}
|
||||
|
||||
void MD5MeshParser::Error(const String& message)
|
||||
void MD5MeshParser::Error(const std::string& message)
|
||||
{
|
||||
NazaraError(message + " at line #" + String::Number(m_lineCount));
|
||||
NazaraError(message + " at line #" + std::to_string(m_lineCount));
|
||||
}
|
||||
|
||||
bool MD5MeshParser::ParseJoints()
|
||||
@@ -216,7 +228,7 @@ namespace Nz
|
||||
if (!Advance())
|
||||
return false;
|
||||
|
||||
std::size_t pos = m_currentLine.Find(' ');
|
||||
std::size_t pos = m_currentLine.find(' ');
|
||||
if (pos == String::npos)
|
||||
{
|
||||
UnrecognizedLine(true);
|
||||
@@ -231,8 +243,8 @@ namespace Nz
|
||||
|
||||
char name[64];
|
||||
if (std::sscanf(&m_currentLine[0], "%63s %d ( %f %f %f ) ( %f %f %f )", &name[0], &m_joints[i].parent,
|
||||
&m_joints[i].bindPos.x, &m_joints[i].bindPos.y, &m_joints[i].bindPos.z,
|
||||
&m_joints[i].bindOrient.x, &m_joints[i].bindOrient.y, &m_joints[i].bindOrient.z) != 8)
|
||||
&m_joints[i].bindPos.x, &m_joints[i].bindPos.y, &m_joints[i].bindPos.z,
|
||||
&m_joints[i].bindOrient.x, &m_joints[i].bindOrient.y, &m_joints[i].bindOrient.z) != 8)
|
||||
{
|
||||
UnrecognizedLine(true);
|
||||
return false;
|
||||
@@ -246,7 +258,7 @@ namespace Nz
|
||||
{
|
||||
if (static_cast<std::size_t>(parent) >= jointCount)
|
||||
{
|
||||
Error("Joint's parent is out of bounds (" + String::Number(parent) + " >= " + String::Number(jointCount) + ')');
|
||||
Error("Joint's parent is out of bounds (" + std::to_string(parent) + " >= " + std::to_string(jointCount) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -257,7 +269,7 @@ namespace Nz
|
||||
if (!Advance())
|
||||
return false;
|
||||
|
||||
if (m_currentLine != '}')
|
||||
if (m_currentLine != "}")
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
Warning("Hierarchy braces closing not found");
|
||||
@@ -282,17 +294,42 @@ namespace Nz
|
||||
break;
|
||||
|
||||
case 's': // shader
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (!m_currentLine.StartsWith("shader "))
|
||||
if (!StartsWith(m_currentLine, "shader "))
|
||||
{
|
||||
UnrecognizedLine();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_meshes[m_meshIndex].shader = m_currentLine.SubString(7);
|
||||
m_meshes[m_meshIndex].shader.Trim('"');
|
||||
std::string_view shader = m_currentLine;
|
||||
shader = shader.substr(7);
|
||||
if (shader.empty())
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if (shader.front() == '"')
|
||||
shader.remove_prefix(1);
|
||||
|
||||
if (shader.empty())
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if (shader.back() == '"')
|
||||
shader.remove_prefix(1);
|
||||
|
||||
m_meshes[m_meshIndex].shader = shader;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n': // num[tris/verts]
|
||||
{
|
||||
@@ -315,7 +352,7 @@ namespace Nz
|
||||
|
||||
if (index != i)
|
||||
{
|
||||
Error("Unexpected triangle index (expected " + String::Number(i) + ", got " + String::Number(index) + ')');
|
||||
Error("Unexpected triangle index (expected " + std::to_string(i) + ", got " + std::to_string(index) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -338,7 +375,7 @@ namespace Nz
|
||||
|
||||
if (index != i)
|
||||
{
|
||||
Error("Unexpected vertex index (expected " + String::Number(i) + ", got " + String::Number(index) + ')');
|
||||
Error("Unexpected vertex index (expected " + std::to_string(i) + ", got " + std::to_string(index) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -354,7 +391,7 @@ namespace Nz
|
||||
Weight& weight = m_meshes[m_meshIndex].weights[i];
|
||||
unsigned int index;
|
||||
if (std::sscanf(&m_currentLine[0], "weight %u %u %f ( %f %f %f )", &index, &weight.joint, &weight.bias,
|
||||
&weight.pos.x, &weight.pos.y, &weight.pos.z) != 6)
|
||||
&weight.pos.x, &weight.pos.y, &weight.pos.z) != 6)
|
||||
{
|
||||
UnrecognizedLine(true);
|
||||
return false;
|
||||
@@ -362,7 +399,7 @@ namespace Nz
|
||||
|
||||
if (index != i)
|
||||
{
|
||||
Error("Unexpected weight index (expected " + String::Number(i) + ", got " + String::Number(index) + ')');
|
||||
Error("Unexpected weight index (expected " + std::to_string(i) + ", got " + std::to_string(index) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -408,14 +445,14 @@ namespace Nz
|
||||
return true;
|
||||
}
|
||||
|
||||
void MD5MeshParser::Warning(const String& message)
|
||||
void MD5MeshParser::Warning(const std::string& message)
|
||||
{
|
||||
NazaraWarning(message + " at line #" + String::Number(m_lineCount));
|
||||
NazaraWarning(message + " at line #" + std::to_string(m_lineCount));
|
||||
}
|
||||
|
||||
void MD5MeshParser::UnrecognizedLine(bool error)
|
||||
{
|
||||
String message = "Unrecognized \"" + m_currentLine + '"';
|
||||
std::string message = "Unrecognized \"" + m_currentLine + '"';
|
||||
|
||||
if (error)
|
||||
Error(message);
|
||||
|
||||
@@ -4,12 +4,31 @@
|
||||
|
||||
#include <Nazara/Utility/Formats/MTLParser.hpp>
|
||||
#include <Nazara/Core/CallOnExit.hpp>
|
||||
#include <Nazara/Core/StringExt.hpp>
|
||||
#include <Nazara/Utility/Config.hpp>
|
||||
#include <cstdio>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template<std::size_t N>
|
||||
bool TestKeyword(const std::string& currentLine, const char(&keyword)[N], std::size_t& offset)
|
||||
{
|
||||
if (currentLine.size() > N && StartsWith(currentLine, keyword, CaseIndependent{}) && std::isspace(currentLine[N - 1]))
|
||||
{
|
||||
offset = N;
|
||||
while (offset < currentLine.size() && std::isspace(currentLine[offset]))
|
||||
offset++;
|
||||
|
||||
return offset < currentLine.size();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MTLParser::Parse(Stream& stream)
|
||||
{
|
||||
m_currentStream = &stream;
|
||||
@@ -31,266 +50,434 @@ namespace Nz
|
||||
m_materials.clear();
|
||||
|
||||
Material* currentMaterial = nullptr;
|
||||
std::size_t offset;
|
||||
|
||||
while (Advance(false))
|
||||
{
|
||||
String keyword = m_currentLine.GetWord(0).ToLower();
|
||||
if (keyword == "ka")
|
||||
switch (std::tolower(m_currentLine[0]))
|
||||
{
|
||||
float r, g, b;
|
||||
if (std::sscanf(&m_currentLine[3], "%f %f %f", &r, &g, &b) == 3)
|
||||
case 'b':
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
if (TestKeyword(m_currentLine, "bump", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->ambient = Color(static_cast<UInt8>(r*255.f), static_cast<UInt8>(g*255.f), static_cast<UInt8>(b*255.f));
|
||||
currentMaterial->bumpMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (keyword == "kd")
|
||||
{
|
||||
float r, g, b;
|
||||
if (std::sscanf(&m_currentLine[3], "%f %f %f", &r, &g, &b) == 3)
|
||||
|
||||
case 'd':
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
if (TestKeyword(m_currentLine, "d", offset))
|
||||
{
|
||||
float alpha;
|
||||
if (std::sscanf(&m_currentLine[2], "%f", &alpha) == 1)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->diffuse = Color(static_cast<UInt8>(r*255.f), static_cast<UInt8>(g*255.f), static_cast<UInt8>(b*255.f));
|
||||
currentMaterial->alpha = alpha;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "decal", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->decalMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "disp", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->displacementMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (keyword == "ks")
|
||||
{
|
||||
float r, g, b;
|
||||
if (std::sscanf(&m_currentLine[3], "%f %f %f", &r, &g, &b) == 3)
|
||||
|
||||
case 'e':
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
if (TestKeyword(m_currentLine, "emissive", offset))
|
||||
{
|
||||
// <!> This is a custom keyword
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->specular = Color(static_cast<UInt8>(r*255.f), static_cast<UInt8>(g*255.f), static_cast<UInt8>(b*255.f));
|
||||
currentMaterial->emissiveMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (keyword == "ni")
|
||||
{
|
||||
float density;
|
||||
if (std::sscanf(&m_currentLine[3], "%f", &density) == 1)
|
||||
|
||||
case 'k':
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
if (TestKeyword(m_currentLine, "ka", offset))
|
||||
{
|
||||
float r, g, b;
|
||||
if (std::sscanf(&m_currentLine[offset], "%f %f %f", &r, &g, &b) == 3)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->refractionIndex = density;
|
||||
currentMaterial->ambient = Color(static_cast<UInt8>(r * 255.f), static_cast<UInt8>(g * 255.f), static_cast<UInt8>(b * 255.f));
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "kd", offset))
|
||||
{
|
||||
float r, g, b;
|
||||
if (std::sscanf(&m_currentLine[offset], "%f %f %f", &r, &g, &b) == 3)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->diffuse = Color(static_cast<UInt8>(r * 255.f), static_cast<UInt8>(g * 255.f), static_cast<UInt8>(b * 255.f));
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "ks", offset))
|
||||
{
|
||||
float r, g, b;
|
||||
if (std::sscanf(&m_currentLine[offset], "%f %f %f", &r, &g, &b) == 3)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->specular = Color(static_cast<UInt8>(r * 255.f), static_cast<UInt8>(g * 255.f), static_cast<UInt8>(b * 255.f));
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (keyword == "ns")
|
||||
{
|
||||
float coef;
|
||||
if (std::sscanf(&m_currentLine[3], "%f", &coef) == 1)
|
||||
|
||||
case 'i':
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
if (TestKeyword(m_currentLine, "illum", offset))
|
||||
{
|
||||
unsigned int model;
|
||||
if (std::sscanf(&m_currentLine[offset], "%u", &model) == 1)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->shininess = coef;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (keyword == 'd')
|
||||
{
|
||||
float alpha;
|
||||
if (std::sscanf(&m_currentLine[(keyword[0] == 'd') ? 2 : 3], "%f", &alpha) == 1)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->alpha = alpha;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (keyword == "tr")
|
||||
{
|
||||
float alpha;
|
||||
if (std::sscanf(&m_currentLine[(keyword[0] == 'd') ? 2 : 3], "%f", &alpha) == 1)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->alpha = 1.f - alpha; // tr vaut pour la "valeur de transparence", 0 = opaque
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (keyword == "illum")
|
||||
{
|
||||
unsigned int model;
|
||||
if (std::sscanf(&m_currentLine[6], "%u", &model) == 1)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->illumModel = model;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (keyword == "map_ka")
|
||||
{
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->ambientMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "map_kd")
|
||||
{
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->diffuseMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "map_ks")
|
||||
{
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->specularMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "map_bump" || keyword == "bump")
|
||||
{
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->bumpMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "map_d")
|
||||
{
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->alphaMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "map_decal" || keyword == "decal")
|
||||
{
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->decalMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "map_disp" || keyword == "disp")
|
||||
{
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->displacementMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "map_refl" || keyword == "refl")
|
||||
{
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->reflectionMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "map_normal" || keyword == "normal")
|
||||
{
|
||||
// <!> This is a custom keyword
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->normalMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "map_emissive" || keyword == "emissive")
|
||||
{
|
||||
// <!> This is a custom keyword
|
||||
std::size_t mapPos = m_currentLine.GetWordPosition(1);
|
||||
if (mapPos != String::npos)
|
||||
{
|
||||
String map = m_currentLine.SubString(mapPos);
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->emissiveMap = map;
|
||||
}
|
||||
}
|
||||
else if (keyword == "newmtl")
|
||||
{
|
||||
String materialName = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
|
||||
if (!materialName.IsEmpty())
|
||||
currentMaterial = AddMaterial(materialName);
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
currentMaterial->illumModel = model;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'm':
|
||||
{
|
||||
if (TestKeyword(m_currentLine, "map_ka", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->ambientMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "map_kd", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->diffuseMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "map_ks", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->specularMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "map_bump", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->bumpMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "map_d", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->alphaMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "map_decal", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->decalMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "map_disp", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->displacementMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "map_refl", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->reflectionMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "map_normal", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->normalMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "map_emissive", offset))
|
||||
{
|
||||
// <!> This is a custom keyword
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->emissiveMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n':
|
||||
{
|
||||
if (TestKeyword(m_currentLine, "ni", offset))
|
||||
{
|
||||
float density;
|
||||
if (std::sscanf(&m_currentLine[offset], "%f", &density) == 1)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->refractionIndex = density;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "ns", offset))
|
||||
{
|
||||
float coef;
|
||||
if (std::sscanf(&m_currentLine[offset], "%f", &coef) == 1)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->shininess = coef;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "normal", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->normalMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
else if (TestKeyword(m_currentLine, "newmtl", offset))
|
||||
{
|
||||
std::string materialName = m_currentLine.substr(offset);
|
||||
if (!materialName.empty())
|
||||
currentMaterial = AddMaterial(materialName);
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'r':
|
||||
{
|
||||
if (TestKeyword(m_currentLine, "refl", offset))
|
||||
{
|
||||
std::string map = m_currentLine.substr(offset);
|
||||
if (!map.empty())
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->reflectionMap = map;
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 't':
|
||||
{
|
||||
if (TestKeyword(m_currentLine, "tr", offset))
|
||||
{
|
||||
float alpha;
|
||||
if (std::sscanf(&m_currentLine[offset], "%f", &alpha) == 1)
|
||||
{
|
||||
if (!currentMaterial)
|
||||
currentMaterial = AddMaterial("default");
|
||||
|
||||
currentMaterial->alpha = 1.f - alpha; // tr vaut pour la "valeur de transparence", 0 = opaque
|
||||
}
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
else
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
UnrecognizedLine();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -378,49 +565,49 @@ namespace Nz
|
||||
EmitLine(mat.illumModel);
|
||||
}
|
||||
|
||||
if (!mat.ambientMap.IsEmpty())
|
||||
if (!mat.ambientMap.empty())
|
||||
{
|
||||
Emit("map_Ka ");
|
||||
EmitLine(mat.ambientMap);
|
||||
}
|
||||
|
||||
if (!mat.diffuseMap.IsEmpty())
|
||||
if (!mat.diffuseMap.empty())
|
||||
{
|
||||
Emit("map_Kd ");
|
||||
EmitLine(mat.diffuseMap);
|
||||
}
|
||||
|
||||
if (!mat.specularMap.IsEmpty())
|
||||
if (!mat.specularMap.empty())
|
||||
{
|
||||
Emit("map_Ks ");
|
||||
EmitLine(mat.specularMap);
|
||||
}
|
||||
|
||||
if (!mat.bumpMap.IsEmpty())
|
||||
if (!mat.bumpMap.empty())
|
||||
{
|
||||
Emit("map_bump ");
|
||||
EmitLine(mat.bumpMap);
|
||||
}
|
||||
|
||||
if (!mat.alphaMap.IsEmpty())
|
||||
if (!mat.alphaMap.empty())
|
||||
{
|
||||
Emit("map_d ");
|
||||
EmitLine(mat.alphaMap);
|
||||
}
|
||||
|
||||
if (!mat.decalMap.IsEmpty())
|
||||
if (!mat.decalMap.empty())
|
||||
{
|
||||
Emit("map_decal ");
|
||||
EmitLine(mat.decalMap);
|
||||
}
|
||||
|
||||
if (!mat.displacementMap.IsEmpty())
|
||||
if (!mat.displacementMap.empty())
|
||||
{
|
||||
Emit("map_disp ");
|
||||
EmitLine(mat.displacementMap);
|
||||
}
|
||||
|
||||
if (!mat.reflectionMap.IsEmpty())
|
||||
if (!mat.reflectionMap.empty())
|
||||
{
|
||||
Emit("map_refl ");
|
||||
EmitLine(mat.reflectionMap);
|
||||
@@ -450,13 +637,18 @@ namespace Nz
|
||||
m_lineCount++;
|
||||
|
||||
m_currentLine = m_currentStream->ReadLine();
|
||||
if (m_currentLine.IsEmpty())
|
||||
continue;
|
||||
if (std::size_t p = m_currentLine.find('#'); p != m_currentLine.npos)
|
||||
{
|
||||
if (p > 0)
|
||||
m_currentLine = m_currentLine.substr(0, p - 1);
|
||||
else
|
||||
m_currentLine.clear();
|
||||
}
|
||||
|
||||
m_currentLine = m_currentLine.SubStringTo("#"); // On ignore les commentaires
|
||||
m_currentLine.Simplify(); // Pour un traitement plus simple
|
||||
if (m_currentLine.empty())
|
||||
continue;
|
||||
}
|
||||
while (m_currentLine.IsEmpty());
|
||||
while (m_currentLine.empty());
|
||||
}
|
||||
else
|
||||
m_keepLastLine = false;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool IsSupported(const String& extension)
|
||||
bool IsSupported(const std::string& extension)
|
||||
{
|
||||
return (extension == "obj");
|
||||
}
|
||||
@@ -42,12 +42,12 @@ namespace Nz
|
||||
return Ternary_Unknown;
|
||||
}
|
||||
|
||||
bool ParseMTL(Mesh* mesh, const String& filePath, const String* materials, const OBJParser::Mesh* meshes, UInt32 meshCount)
|
||||
bool ParseMTL(Mesh* mesh, const std::filesystem::path& filePath, const std::string* materials, const OBJParser::Mesh* meshes, std::size_t meshCount)
|
||||
{
|
||||
File file(filePath);
|
||||
if (!file.Open(OpenMode_ReadOnly | OpenMode_Text))
|
||||
{
|
||||
NazaraError("Failed to open MTL file (" + file.GetPath() + ')');
|
||||
NazaraError("Failed to open MTL file (" + file.GetPath().generic_u8string() + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -59,10 +59,10 @@ namespace Nz
|
||||
}
|
||||
|
||||
std::unordered_map<String, ParameterList> materialCache;
|
||||
String baseDir = file.GetDirectory();
|
||||
for (UInt32 i = 0; i < meshCount; ++i)
|
||||
std::filesystem::path baseDir = file.GetDirectory();
|
||||
for (std::size_t i = 0; i < meshCount; ++i)
|
||||
{
|
||||
const String& matName = materials[meshes[i].material];
|
||||
const std::string& matName = materials[meshes[i].material];
|
||||
const MTLParser::Material* mtlMat = materialParser.GetMaterial(matName);
|
||||
if (!mtlMat)
|
||||
{
|
||||
@@ -89,53 +89,53 @@ namespace Nz
|
||||
data.SetParameter(MaterialData::Shininess, mtlMat->shininess);
|
||||
data.SetParameter(MaterialData::SpecularColor, specularColor);
|
||||
|
||||
if (!mtlMat->alphaMap.IsEmpty())
|
||||
if (!mtlMat->alphaMap.empty())
|
||||
{
|
||||
String fullPath = mtlMat->alphaMap;
|
||||
if (!Nz::File::IsAbsolute(fullPath))
|
||||
fullPath.Prepend(baseDir);
|
||||
std::filesystem::path fullPath = mtlMat->alphaMap;
|
||||
if (!fullPath.is_absolute())
|
||||
fullPath = baseDir / fullPath;
|
||||
|
||||
data.SetParameter(MaterialData::AlphaTexturePath, fullPath);
|
||||
data.SetParameter(MaterialData::AlphaTexturePath, fullPath.generic_u8string());
|
||||
}
|
||||
|
||||
if (!mtlMat->diffuseMap.IsEmpty())
|
||||
if (!mtlMat->diffuseMap.empty())
|
||||
{
|
||||
String fullPath = mtlMat->diffuseMap;
|
||||
if (!Nz::File::IsAbsolute(fullPath))
|
||||
fullPath.Prepend(baseDir);
|
||||
std::filesystem::path fullPath = mtlMat->diffuseMap;
|
||||
if (!fullPath.is_absolute())
|
||||
fullPath = baseDir / fullPath;
|
||||
|
||||
data.SetParameter(MaterialData::DiffuseTexturePath, fullPath);
|
||||
data.SetParameter(MaterialData::DiffuseTexturePath, fullPath.generic_u8string());
|
||||
}
|
||||
|
||||
if (!mtlMat->emissiveMap.IsEmpty())
|
||||
if (!mtlMat->emissiveMap.empty())
|
||||
{
|
||||
String fullPath = mtlMat->emissiveMap;
|
||||
if (!Nz::File::IsAbsolute(fullPath))
|
||||
fullPath.Prepend(baseDir);
|
||||
std::filesystem::path fullPath = mtlMat->emissiveMap;
|
||||
if (!fullPath.is_absolute())
|
||||
fullPath = baseDir / fullPath;
|
||||
|
||||
data.SetParameter(MaterialData::EmissiveTexturePath, fullPath);
|
||||
data.SetParameter(MaterialData::EmissiveTexturePath, fullPath.generic_u8string());
|
||||
}
|
||||
|
||||
if (!mtlMat->normalMap.IsEmpty())
|
||||
if (!mtlMat->normalMap.empty())
|
||||
{
|
||||
String fullPath = mtlMat->normalMap;
|
||||
if (!Nz::File::IsAbsolute(fullPath))
|
||||
fullPath.Prepend(baseDir);
|
||||
std::filesystem::path fullPath = mtlMat->normalMap;
|
||||
if (!fullPath.is_absolute())
|
||||
fullPath = baseDir / fullPath;
|
||||
|
||||
data.SetParameter(MaterialData::NormalTexturePath, fullPath);
|
||||
data.SetParameter(MaterialData::NormalTexturePath, fullPath.generic_u8string());
|
||||
}
|
||||
|
||||
if (!mtlMat->specularMap.IsEmpty())
|
||||
if (!mtlMat->specularMap.empty())
|
||||
{
|
||||
String fullPath = mtlMat->specularMap;
|
||||
if (!Nz::File::IsAbsolute(fullPath))
|
||||
fullPath.Prepend(baseDir);
|
||||
std::filesystem::path fullPath = mtlMat->specularMap;
|
||||
if (!fullPath.is_absolute())
|
||||
fullPath = baseDir / fullPath;
|
||||
|
||||
data.SetParameter(MaterialData::SpecularTexturePath, fullPath);
|
||||
data.SetParameter(MaterialData::SpecularTexturePath, fullPath.generic_u8string());
|
||||
}
|
||||
|
||||
// If we either have an alpha value or an alpha map, let's configure the material for transparency
|
||||
if (alphaValue != 255 || !mtlMat->alphaMap.IsEmpty())
|
||||
if (alphaValue != 255 || !mtlMat->alphaMap.empty())
|
||||
{
|
||||
// Some default settings
|
||||
data.SetParameter(MaterialData::Blending, true);
|
||||
@@ -169,27 +169,27 @@ namespace Nz
|
||||
MeshRef mesh = Mesh::New();
|
||||
mesh->CreateStatic();
|
||||
|
||||
const String* materials = parser.GetMaterials();
|
||||
const std::string* materials = parser.GetMaterials();
|
||||
const Vector4f* positions = parser.GetPositions();
|
||||
const Vector3f* normals = parser.GetNormals();
|
||||
const Vector3f* texCoords = parser.GetTexCoords();
|
||||
|
||||
const OBJParser::Mesh* meshes = parser.GetMeshes();
|
||||
UInt32 meshCount = parser.GetMeshCount();
|
||||
std::size_t meshCount = parser.GetMeshCount();
|
||||
|
||||
NazaraAssert(materials != nullptr && positions != nullptr && normals != nullptr &&
|
||||
texCoords != nullptr && meshes != nullptr && meshCount > 0,
|
||||
"Invalid OBJParser output");
|
||||
|
||||
// Un conteneur temporaire pour contenir les indices de face avant triangulation
|
||||
std::vector<UInt32> faceIndices(3); // Comme il y aura au moins trois sommets
|
||||
for (UInt32 i = 0; i < meshCount; ++i)
|
||||
std::vector<std::size_t> faceIndices(3); // Comme il y aura au moins trois sommets
|
||||
for (std::size_t i = 0; i < meshCount; ++i)
|
||||
{
|
||||
std::size_t faceCount = meshes[i].faces.size();
|
||||
if (faceCount == 0)
|
||||
continue;
|
||||
|
||||
std::vector<UInt32> indices;
|
||||
std::vector<std::size_t> indices;
|
||||
indices.reserve(faceCount*3); // Pire cas si les faces sont des triangles
|
||||
|
||||
// Afin d'utiliser OBJParser::FaceVertex comme clé dans un unordered_map,
|
||||
@@ -226,10 +226,10 @@ namespace Nz
|
||||
unsigned int vertexCount = 0;
|
||||
for (unsigned int j = 0; j < faceCount; ++j)
|
||||
{
|
||||
UInt32 faceVertexCount = meshes[i].faces[j].vertexCount;
|
||||
std::size_t faceVertexCount = meshes[i].faces[j].vertexCount;
|
||||
faceIndices.resize(faceVertexCount);
|
||||
|
||||
for (UInt32 k = 0; k < faceVertexCount; ++k)
|
||||
for (std::size_t k = 0; k < faceVertexCount; ++k)
|
||||
{
|
||||
const OBJParser::FaceVertex& vertex = meshes[i].vertices[meshes[i].faces[j].firstVertex + k];
|
||||
|
||||
@@ -241,7 +241,7 @@ namespace Nz
|
||||
}
|
||||
|
||||
// Triangulation
|
||||
for (UInt32 k = 1; k < faceVertexCount-1; ++k)
|
||||
for (std::size_t k = 1; k < faceVertexCount-1; ++k)
|
||||
{
|
||||
indices.push_back(faceIndices[0]);
|
||||
indices.push_back(faceIndices[k]);
|
||||
@@ -250,13 +250,13 @@ namespace Nz
|
||||
}
|
||||
|
||||
// Création des buffers
|
||||
IndexBufferRef indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), UInt32(indices.size()), parameters.storage, parameters.indexBufferFlags);
|
||||
VertexBufferRef vertexBuffer = VertexBuffer::New(parameters.vertexDeclaration, UInt32(vertexCount), parameters.storage, parameters.vertexBufferFlags);
|
||||
IndexBufferRef indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits<UInt16>::max(), std::size_t(indices.size()), parameters.storage, parameters.indexBufferFlags);
|
||||
VertexBufferRef vertexBuffer = VertexBuffer::New(parameters.vertexDeclaration, std::size_t(vertexCount), parameters.storage, parameters.vertexBufferFlags);
|
||||
|
||||
// Remplissage des indices
|
||||
IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly);
|
||||
for (std::size_t j = 0; j < indices.size(); ++j)
|
||||
indexMapper.Set(j, indices[j]);
|
||||
indexMapper.Set(j, UInt32(indices[j]));
|
||||
|
||||
indexMapper.Unmap(); // Pour laisser les autres tâches affecter l'index buffer
|
||||
|
||||
@@ -337,11 +337,11 @@ namespace Nz
|
||||
mesh->Recenter();
|
||||
|
||||
// On charge les matériaux si demandé
|
||||
String mtlLib = parser.GetMtlLib();
|
||||
if (!mtlLib.IsEmpty())
|
||||
std::filesystem::path mtlLib = parser.GetMtlLib();
|
||||
if (!mtlLib.empty())
|
||||
{
|
||||
ErrorFlags flags(ErrorFlag_ThrowExceptionDisabled);
|
||||
ParseMTL(mesh, stream.GetDirectory() + mtlLib, materials, meshes, meshCount);
|
||||
ParseMTL(mesh, stream.GetDirectory() / mtlLib, materials, meshes, meshCount);
|
||||
}
|
||||
|
||||
return mesh;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <Nazara/Utility/Formats/OBJParser.hpp>
|
||||
#include <Nazara/Core/CallOnExit.hpp>
|
||||
#include <Nazara/Core/StringExt.hpp>
|
||||
#include <Nazara/Utility/Config.hpp>
|
||||
#include <cctype>
|
||||
#include <memory>
|
||||
@@ -45,32 +46,29 @@ namespace Nz
|
||||
case 'o': //< Object (defines a mesh)
|
||||
case 's': //< Smooth
|
||||
{
|
||||
if (m_currentLine.GetSize() > 1 && m_currentLine[1] == ' ')
|
||||
if (m_currentLine.size() > 1 && m_currentLine[1] == ' ')
|
||||
return true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'm': //< MTLLib
|
||||
if (m_currentLine.GetWord(0).ToLower() == "mtllib")
|
||||
if (StartsWith(m_currentLine, "mtllib "))
|
||||
return true;
|
||||
|
||||
break;
|
||||
|
||||
case 'u': //< Usemtl
|
||||
if (m_currentLine.GetWord(0).ToLower() == "usemtl")
|
||||
if (StartsWith(m_currentLine, "usemtl "))
|
||||
return true;
|
||||
|
||||
break;
|
||||
|
||||
case 'v': //< Position/Normal/Texcoords
|
||||
{
|
||||
String word = m_currentLine.GetWord(0).ToLower();
|
||||
if (word == 'v')
|
||||
return true;
|
||||
else if (word == "vn")
|
||||
return true;
|
||||
else if (word == "vt")
|
||||
if (StartsWith(m_currentLine, "v ") ||
|
||||
StartsWith(m_currentLine, "vn ") ||
|
||||
StartsWith(m_currentLine, "vt "))
|
||||
return true;
|
||||
|
||||
break;
|
||||
@@ -87,7 +85,7 @@ namespace Nz
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OBJParser::Parse(Nz::Stream& stream, UInt32 reservedVertexCount)
|
||||
bool OBJParser::Parse(Nz::Stream& stream, std::size_t reservedVertexCount)
|
||||
{
|
||||
m_currentStream = &stream;
|
||||
m_errorCount = 0;
|
||||
@@ -106,10 +104,10 @@ namespace Nz
|
||||
});
|
||||
}
|
||||
|
||||
String matName, meshName;
|
||||
std::string matName, meshName;
|
||||
matName = meshName = "default";
|
||||
m_meshes.clear();
|
||||
m_mtlLib.Clear();
|
||||
m_mtlLib.clear();
|
||||
|
||||
m_normals.clear();
|
||||
m_positions.clear();
|
||||
@@ -122,12 +120,12 @@ namespace Nz
|
||||
|
||||
// Sort meshes by material and group
|
||||
using MatPair = std::pair<Mesh, unsigned int>;
|
||||
std::unordered_map<String, std::unordered_map<String, MatPair>> meshesByName;
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, MatPair>> meshesByName;
|
||||
|
||||
UInt32 faceReserve = 0;
|
||||
UInt32 vertexReserve = 0;
|
||||
unsigned int matCount = 0;
|
||||
auto GetMaterial = [&] (const String& mesh, const String& mat) -> Mesh*
|
||||
auto GetMaterial = [&] (const std::string& mesh, const std::string& mat) -> Mesh*
|
||||
{
|
||||
auto& map = meshesByName[mesh];
|
||||
auto it = map.find(mat);
|
||||
@@ -154,22 +152,22 @@ namespace Nz
|
||||
case '#': //< Comment
|
||||
// Some softwares write comments to gives the number of vertex/faces an importer can expect
|
||||
unsigned int data;
|
||||
if (std::sscanf(m_currentLine.GetConstBuffer(), "# position count: %u", &data) == 1)
|
||||
if (std::sscanf(m_currentLine.data(), "# position count: %u", &data) == 1)
|
||||
m_positions.reserve(data);
|
||||
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# normal count: %u", &data) == 1)
|
||||
else if (std::sscanf(m_currentLine.data(), "# normal count: %u", &data) == 1)
|
||||
m_normals.reserve(data);
|
||||
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# texcoords count: %u", &data) == 1)
|
||||
else if (std::sscanf(m_currentLine.data(), "# texcoords count: %u", &data) == 1)
|
||||
m_texCoords.reserve(data);
|
||||
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# face count: %u", &data) == 1)
|
||||
else if (std::sscanf(m_currentLine.data(), "# face count: %u", &data) == 1)
|
||||
faceReserve = data;
|
||||
else if (std::sscanf(m_currentLine.GetConstBuffer(), "# vertex count: %u", &data) == 1)
|
||||
else if (std::sscanf(m_currentLine.data(), "# vertex count: %u", &data) == 1)
|
||||
vertexReserve = data;
|
||||
|
||||
break;
|
||||
|
||||
case 'f': //< Face
|
||||
{
|
||||
if (m_currentLine.GetSize() < 7) // Since we only treat triangles, this is the minimum length of a face line (f 1 2 3)
|
||||
if (m_currentLine.size() < 7) // Since we only treat triangles, this is the minimum length of a face line (f 1 2 3)
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (!UnrecognizedLine())
|
||||
@@ -178,7 +176,7 @@ namespace Nz
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int vertexCount = m_currentLine.Count(' ');
|
||||
std::size_t vertexCount = std::count(m_currentLine.begin(), m_currentLine.end(), ' ');
|
||||
if (vertexCount < 3)
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
@@ -192,8 +190,8 @@ namespace Nz
|
||||
currentMesh = GetMaterial(meshName, matName);
|
||||
|
||||
Face face;
|
||||
face.firstVertex = static_cast<UInt32>(currentMesh->vertices.size());
|
||||
face.vertexCount = static_cast<UInt32>(vertexCount);
|
||||
face.firstVertex = currentMesh->vertices.size();
|
||||
face.vertexCount = vertexCount;
|
||||
|
||||
currentMesh->vertices.resize(face.firstVertex + vertexCount, FaceVertex{0, 0, 0});
|
||||
|
||||
@@ -230,7 +228,7 @@ namespace Nz
|
||||
p += static_cast<int>(m_positions.size());
|
||||
if (p < 0)
|
||||
{
|
||||
Error("Vertex index out of range (" + String::Number(p) + " < 0");
|
||||
Error("Vertex index out of range (" + std::to_string(p) + " < 0");
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
@@ -243,7 +241,7 @@ namespace Nz
|
||||
n += static_cast<int>(m_normals.size());
|
||||
if (n < 0)
|
||||
{
|
||||
Error("Normal index out of range (" + String::Number(n) + " < 0");
|
||||
Error("Normal index out of range (" + std::to_string(n) + " < 0");
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
@@ -256,7 +254,7 @@ namespace Nz
|
||||
t += static_cast<int>(m_texCoords.size());
|
||||
if (t < 0)
|
||||
{
|
||||
Error("Texture coordinates index out of range (" + String::Number(t) + " < 0");
|
||||
Error("Texture coordinates index out of range (" + std::to_string(t) + " < 0");
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
@@ -266,19 +264,19 @@ namespace Nz
|
||||
|
||||
if (static_cast<std::size_t>(p) > m_positions.size())
|
||||
{
|
||||
Error("Vertex index out of range (" + String::Number(p) + " >= " + String::Number(m_positions.size()) + ')');
|
||||
Error("Vertex index out of range (" + std::to_string(p) + " >= " + std::to_string(m_positions.size()) + ')');
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
else if (n != 0 && static_cast<std::size_t>(n) > m_normals.size())
|
||||
{
|
||||
Error("Normal index out of range (" + String::Number(n) + " >= " + String::Number(m_normals.size()) + ')');
|
||||
Error("Normal index out of range (" + std::to_string(n) + " >= " + std::to_string(m_normals.size()) + ')');
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
else if (t != 0 && static_cast<std::size_t>(t) > m_texCoords.size())
|
||||
{
|
||||
Error("TexCoord index out of range (" + String::Number(t) + " >= " + String::Number(m_texCoords.size()) + ')');
|
||||
Error("TexCoord index out of range (" + std::to_string(t) + " >= " + std::to_string(m_texCoords.size()) + ')');
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
@@ -299,29 +297,36 @@ namespace Nz
|
||||
}
|
||||
|
||||
case 'm': //< MTLLib
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (m_currentLine.GetWord(0).ToLower() != "mtllib")
|
||||
{
|
||||
const char prefix[] = "mtllib ";
|
||||
if (!StartsWith(m_currentLine, prefix))
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (!UnrecognizedLine())
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_mtlLib = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
|
||||
break;
|
||||
}
|
||||
|
||||
m_mtlLib = m_currentLine.substr(sizeof(prefix) - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'g': //< Group (inside a mesh)
|
||||
case 'o': //< Object (defines a mesh)
|
||||
{
|
||||
if (m_currentLine.GetSize() <= 2 || m_currentLine[1] != ' ')
|
||||
if (m_currentLine.size() <= 2 || m_currentLine[1] != ' ')
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (!UnrecognizedLine())
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
String objectName = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
|
||||
if (objectName.IsEmpty())
|
||||
std::string objectName = m_currentLine.substr(2);
|
||||
if (objectName.empty())
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (!UnrecognizedLine())
|
||||
@@ -335,12 +340,12 @@ namespace Nz
|
||||
break;
|
||||
}
|
||||
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
case 's': //< Smooth
|
||||
if (m_currentLine.GetSize() <= 2 || m_currentLine[1] == ' ')
|
||||
if (m_currentLine.size() <= 2 || m_currentLine[1] == ' ')
|
||||
{
|
||||
String param = m_currentLine.SubString(2);
|
||||
if (param != "all" && param != "on" && param != "off" && !param.IsNumber())
|
||||
std::string param = m_currentLine.substr(2);
|
||||
if (param != "all" && param != "on" && param != "off" && !IsNumber(param))
|
||||
{
|
||||
if (!UnrecognizedLine())
|
||||
return false;
|
||||
@@ -349,33 +354,51 @@ namespace Nz
|
||||
else if (!UnrecognizedLine())
|
||||
return false;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
case 'u': //< Usemtl
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (m_currentLine.GetWord(0) != "usemtl" && !UnrecognizedLine())
|
||||
return false;
|
||||
#endif
|
||||
|
||||
matName = m_currentLine.SubString(m_currentLine.GetWordPosition(1));
|
||||
currentMesh = nullptr;
|
||||
if (matName.IsEmpty())
|
||||
{
|
||||
const char prefix[] = "usemtl ";
|
||||
if (!StartsWith(m_currentLine, prefix))
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (!UnrecognizedLine())
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
std::string newMatName = m_currentLine.substr(sizeof(prefix) - 1);
|
||||
if (newMatName.empty())
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (!UnrecognizedLine())
|
||||
return false;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
matName = std::move(newMatName);
|
||||
currentMesh = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'v': //< Position/Normal/Texcoords
|
||||
{
|
||||
String word = m_currentLine.GetWord(0).ToLower();
|
||||
if (word == 'v')
|
||||
if (m_currentLine.size() < 7)
|
||||
{
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
if (!UnrecognizedLine())
|
||||
return false;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if (std::isspace(m_currentLine[1]))
|
||||
{
|
||||
Vector4f vertex(Vector3f::Zero(), 1.f);
|
||||
unsigned int paramCount = std::sscanf(&m_currentLine[2], "%f %f %f %f", &vertex.x, &vertex.y, &vertex.z, &vertex.w);
|
||||
unsigned int paramCount = std::sscanf(&m_currentLine[2], " %f %f %f %f", &vertex.x, &vertex.y, &vertex.z, &vertex.w);
|
||||
if (paramCount >= 1)
|
||||
m_positions.push_back(vertex);
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
@@ -383,10 +406,10 @@ namespace Nz
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else if (word == "vn")
|
||||
else if (m_currentLine[1] == 'n' && std::isspace(m_currentLine[2]))
|
||||
{
|
||||
Vector3f normal(Vector3f::Zero());
|
||||
unsigned int paramCount = std::sscanf(&m_currentLine[3], "%f %f %f", &normal.x, &normal.y, &normal.z);
|
||||
unsigned int paramCount = std::sscanf(&m_currentLine[3], " %f %f %f", &normal.x, &normal.y, &normal.z);
|
||||
if (paramCount == 3)
|
||||
m_normals.push_back(normal);
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
@@ -394,10 +417,10 @@ namespace Nz
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else if (word == "vt")
|
||||
else if (m_currentLine[1] == 't' && std::isspace(m_currentLine[2]))
|
||||
{
|
||||
Vector3f uvw(Vector3f::Zero());
|
||||
unsigned int paramCount = std::sscanf(&m_currentLine[3], "%f %f %f", &uvw.x, &uvw.y, &uvw.z);
|
||||
unsigned int paramCount = std::sscanf(&m_currentLine[3], " %f %f %f", &uvw.x, &uvw.y, &uvw.z);
|
||||
if (paramCount >= 2)
|
||||
m_texCoords.push_back(uvw);
|
||||
#if NAZARA_UTILITY_STRICT_RESOURCE_PARSING
|
||||
@@ -422,7 +445,7 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<String, unsigned int> materials;
|
||||
std::unordered_map<std::string, unsigned int> materials;
|
||||
m_materials.resize(matCount);
|
||||
|
||||
for (auto& meshPair : meshesByName)
|
||||
@@ -480,10 +503,10 @@ namespace Nz
|
||||
EmitLine("# Exported by Nazara Engine");
|
||||
EmitLine();
|
||||
|
||||
if (!m_mtlLib.IsEmpty())
|
||||
if (!m_mtlLib.empty())
|
||||
{
|
||||
Emit("mtllib ");
|
||||
EmitLine(m_mtlLib);
|
||||
EmitLine(m_mtlLib.generic_u8string());
|
||||
EmitLine();
|
||||
}
|
||||
|
||||
@@ -617,12 +640,18 @@ namespace Nz
|
||||
m_lineCount++;
|
||||
|
||||
m_currentLine = m_currentStream->ReadLine();
|
||||
if (m_currentLine.IsEmpty())
|
||||
continue;
|
||||
if (std::size_t p = m_currentLine.find('#'); p != m_currentLine.npos)
|
||||
{
|
||||
if (p > 0)
|
||||
m_currentLine = m_currentLine.substr(0, p - 1);
|
||||
else
|
||||
m_currentLine.clear();
|
||||
}
|
||||
|
||||
m_currentLine.Simplify(); // Simplify lines (convert multiple blanks into a single space and trims)
|
||||
if (m_currentLine.empty())
|
||||
continue;
|
||||
}
|
||||
while (m_currentLine.IsEmpty());
|
||||
while (m_currentLine.empty());
|
||||
}
|
||||
else
|
||||
m_keepLastLine = false;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// This file is part of the "Nazara Engine - Utility module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Directory.hpp>
|
||||
#include <Nazara/Utility/MaterialData.hpp>
|
||||
#include <Nazara/Utility/Mesh.hpp>
|
||||
#include <Nazara/Utility/StaticMesh.hpp>
|
||||
@@ -28,12 +27,12 @@ namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
UInt32 GetCount() const
|
||||
std::size_t GetCount() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
UInt32 Insert(const T& data)
|
||||
std::size_t Insert(const T& data)
|
||||
{
|
||||
auto it = m_cache.find(data);
|
||||
if (it == m_cache.end())
|
||||
@@ -47,17 +46,17 @@ namespace Nz
|
||||
}
|
||||
|
||||
private:
|
||||
UInt32 m_count;
|
||||
std::map<T, UInt32> m_cache;
|
||||
std::size_t m_count;
|
||||
std::map<T, std::size_t> m_cache;
|
||||
T* m_buffer;
|
||||
};
|
||||
|
||||
bool IsSupported(const String& extension)
|
||||
bool IsSupported(const std::string& extension)
|
||||
{
|
||||
return (extension == "obj");
|
||||
}
|
||||
|
||||
bool SaveToStream(const Mesh& mesh, const String& format, Stream& stream, const MeshParams& parameters)
|
||||
bool SaveToStream(const Mesh& mesh, const std::string& format, Stream& stream, const MeshParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
@@ -73,18 +72,18 @@ namespace Nz
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt32 worstCacheVertexCount = mesh.GetVertexCount();
|
||||
std::size_t worstCacheVertexCount = mesh.GetVertexCount();
|
||||
OBJParser objFormat;
|
||||
objFormat.SetNormalCount(worstCacheVertexCount);
|
||||
objFormat.SetPositionCount(worstCacheVertexCount);
|
||||
objFormat.SetTexCoordCount(worstCacheVertexCount);
|
||||
|
||||
String mtlPath = stream.GetPath();
|
||||
if (!mtlPath.IsEmpty())
|
||||
std::filesystem::path mtlPath = stream.GetPath();
|
||||
if (!mtlPath.empty())
|
||||
{
|
||||
mtlPath.Replace(".obj", ".mtl");
|
||||
String fileName = mtlPath.SubStringFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true);
|
||||
if (!fileName.IsEmpty())
|
||||
mtlPath.replace_extension(".mtl");
|
||||
std::filesystem::path fileName = mtlPath.filename();
|
||||
if (!fileName.empty())
|
||||
objFormat.SetMtlLib(fileName);
|
||||
}
|
||||
|
||||
@@ -94,17 +93,20 @@ namespace Nz
|
||||
|
||||
// Materials
|
||||
MTLParser mtlFormat;
|
||||
std::unordered_set<String> registredMaterials;
|
||||
std::unordered_set<std::string> registredMaterials;
|
||||
|
||||
UInt32 matCount = mesh.GetMaterialCount();
|
||||
String* materialNames = objFormat.SetMaterialCount(matCount);
|
||||
for (UInt32 i = 0; i < matCount; ++i)
|
||||
std::size_t matCount = mesh.GetMaterialCount();
|
||||
std::string* materialNames = objFormat.SetMaterialCount(matCount);
|
||||
for (std::size_t i = 0; i < matCount; ++i)
|
||||
{
|
||||
const ParameterList& matData = mesh.GetMaterialData(i);
|
||||
|
||||
String name;
|
||||
if (!matData.GetStringParameter(MaterialData::Name, &name))
|
||||
name = "material_" + String::Number(i);
|
||||
String nzname;
|
||||
std::string name;
|
||||
if (matData.GetStringParameter(MaterialData::Name, &nzname))
|
||||
name = nzname.ToStdString();
|
||||
else
|
||||
name = "material_" + std::to_string(i);
|
||||
|
||||
// Makes sure we only have one material of that name
|
||||
while (registredMaterials.find(name) != registredMaterials.end())
|
||||
@@ -117,7 +119,7 @@ namespace Nz
|
||||
|
||||
String strVal;
|
||||
if (matData.GetStringParameter(MaterialData::FilePath, &strVal))
|
||||
material->diffuseMap = strVal;
|
||||
material->diffuseMap = strVal.ToStdString();
|
||||
else
|
||||
{
|
||||
Color colorVal;
|
||||
@@ -136,28 +138,28 @@ namespace Nz
|
||||
material->shininess = float(dValue);
|
||||
|
||||
if (matData.GetStringParameter(MaterialData::AlphaTexturePath, &strVal))
|
||||
material->alphaMap = strVal;
|
||||
material->alphaMap = strVal.ToStdString();
|
||||
|
||||
if (matData.GetStringParameter(MaterialData::DiffuseTexturePath, &strVal))
|
||||
material->diffuseMap = strVal;
|
||||
material->diffuseMap = strVal.ToStdString();
|
||||
|
||||
if (matData.GetStringParameter(MaterialData::SpecularTexturePath, &strVal))
|
||||
material->specularMap = strVal;
|
||||
material->specularMap = strVal.ToStdString();
|
||||
}
|
||||
}
|
||||
|
||||
// Meshes
|
||||
UInt32 meshCount = mesh.GetSubMeshCount();
|
||||
std::size_t meshCount = mesh.GetSubMeshCount();
|
||||
OBJParser::Mesh* meshes = objFormat.SetMeshCount(meshCount);
|
||||
for (UInt32 i = 0; i < meshCount; ++i)
|
||||
for (std::size_t i = 0; i < meshCount; ++i)
|
||||
{
|
||||
const StaticMesh* staticMesh = static_cast<const StaticMesh*>(mesh.GetSubMesh(i));
|
||||
|
||||
UInt32 triangleCount = staticMesh->GetTriangleCount();
|
||||
std::size_t triangleCount = staticMesh->GetTriangleCount();
|
||||
|
||||
meshes[i].faces.resize(triangleCount);
|
||||
meshes[i].material = staticMesh->GetMaterialIndex();
|
||||
meshes[i].name = "mesh_" + String::Number(i);
|
||||
meshes[i].name = "mesh_" + std::to_string(i);
|
||||
meshes[i].vertices.resize(triangleCount * 3);
|
||||
|
||||
{
|
||||
@@ -167,7 +169,7 @@ namespace Nz
|
||||
SparsePtr<Vector3f> positionPtr = vertexMapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
|
||||
SparsePtr<Vector2f> texCoordsPtr = vertexMapper.GetComponentPtr<Vector2f>(VertexComponent_TexCoord);
|
||||
|
||||
UInt32 faceIndex = 0;
|
||||
std::size_t faceIndex = 0;
|
||||
TriangleIterator triangle(staticMesh);
|
||||
do
|
||||
{
|
||||
@@ -179,7 +181,7 @@ namespace Nz
|
||||
{
|
||||
OBJParser::FaceVertex& vertexIndices = meshes[i].vertices[face.firstVertex + j];
|
||||
|
||||
UInt32 index = triangle[j];
|
||||
std::size_t index = triangle[j];
|
||||
vertexIndices.normal = normalCache.Insert(normalPtr[index]);
|
||||
vertexIndices.position = positionCache.Insert(positionPtr[index]);
|
||||
vertexIndices.texCoord = texCoordsCache.Insert(texCoordsPtr[index]);
|
||||
@@ -197,7 +199,7 @@ namespace Nz
|
||||
|
||||
objFormat.Save(stream);
|
||||
|
||||
if (!mtlPath.IsEmpty())
|
||||
if (!mtlPath.empty())
|
||||
{
|
||||
File mtlFile(mtlPath, OpenMode_WriteOnly | OpenMode_Truncate);
|
||||
if (mtlFile.IsOpen())
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Nz
|
||||
|
||||
static_assert(sizeof(pcx_header) == (6+48+54)*sizeof(UInt8) + 10*sizeof(UInt16), "pcx_header struct must be packed");
|
||||
|
||||
bool IsSupported(const String& extension)
|
||||
bool IsSupported(const std::string& extension)
|
||||
{
|
||||
return (extension == "pcx");
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Nz
|
||||
|
||||
static stbi_io_callbacks callbacks = {Read, Skip, Eof};
|
||||
|
||||
bool IsSupported(const String& extension)
|
||||
bool IsSupported(const std::string& extension)
|
||||
{
|
||||
static std::set<String> supportedExtensions = {"bmp", "gif", "hdr", "jpg", "jpeg", "pic", "png", "ppm", "pgm", "psd", "tga"};
|
||||
return supportedExtensions.find(extension) != supportedExtensions.end();
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Nz
|
||||
{
|
||||
using FormatHandler = bool(*)(const Image& image, const ImageParams& parameters, Stream& stream);
|
||||
|
||||
std::map<String, FormatHandler> s_formatHandlers;
|
||||
std::map<std::string, FormatHandler> s_formatHandlers;
|
||||
|
||||
int ConvertToFloatFormat(Image& image)
|
||||
{
|
||||
@@ -102,12 +102,12 @@ namespace Nz
|
||||
throw std::runtime_error("Failed to write to stream");
|
||||
}
|
||||
|
||||
bool FormatQuerier(const String& extension)
|
||||
bool FormatQuerier(const std::string& extension)
|
||||
{
|
||||
return s_formatHandlers.find(extension) != s_formatHandlers.end();
|
||||
}
|
||||
|
||||
bool SaveToStream(const Image& image, const String& format, Stream& stream, const ImageParams& parameters)
|
||||
bool SaveToStream(const Image& image, const std::string& format, Stream& stream, const ImageParams& parameters)
|
||||
{
|
||||
NazaraUnused(parameters);
|
||||
|
||||
|
||||
@@ -850,7 +850,7 @@ namespace Nz
|
||||
}
|
||||
|
||||
// LoadArray
|
||||
ImageRef Image::LoadArrayFromFile(const String& filePath, const ImageParams& imageParams, const Vector2ui& atlasSize)
|
||||
ImageRef Image::LoadArrayFromFile(const std::filesystem::path& filePath, const ImageParams& imageParams, const Vector2ui& atlasSize)
|
||||
{
|
||||
ImageRef image = Image::LoadFromFile(filePath, imageParams);
|
||||
if (!image)
|
||||
@@ -951,7 +951,7 @@ namespace Nz
|
||||
return LoadArrayFromImage(image, atlasSize);
|
||||
}
|
||||
|
||||
ImageRef Image::LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams, const CubemapParams& cubemapParams)
|
||||
ImageRef Image::LoadCubemapFromFile(const std::filesystem::path& filePath, const ImageParams& imageParams, const CubemapParams& cubemapParams)
|
||||
{
|
||||
ImageRef image = Image::LoadFromFile(filePath, imageParams);
|
||||
if (!image)
|
||||
@@ -1074,7 +1074,7 @@ namespace Nz
|
||||
return LoadCubemapFromImage(image, cubemapParams);
|
||||
}
|
||||
|
||||
bool Image::LoadFaceFromFile(CubemapFace face, const String& filePath, const ImageParams& params)
|
||||
bool Image::LoadFaceFromFile(CubemapFace face, const std::filesystem::path& filePath, const ImageParams& params)
|
||||
{
|
||||
NazaraAssert(IsValid() && IsCubemap(), "Texture must be a valid cubemap");
|
||||
|
||||
@@ -1158,12 +1158,12 @@ namespace Nz
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::SaveToFile(const String& filePath, const ImageParams& params)
|
||||
bool Image::SaveToFile(const std::filesystem::path& filePath, const ImageParams& params)
|
||||
{
|
||||
return ImageSaver::SaveToFile(*this, filePath, params);
|
||||
}
|
||||
|
||||
bool Image::SaveToStream(Stream& stream, const String& format, const ImageParams& params)
|
||||
bool Image::SaveToStream(Stream& stream, const std::string& format, const ImageParams& params)
|
||||
{
|
||||
return ImageSaver::SaveToStream(*this, stream, format, params);
|
||||
}
|
||||
@@ -1429,7 +1429,7 @@ namespace Nz
|
||||
return 0;
|
||||
}
|
||||
|
||||
ImageRef Image::LoadFromFile(const String& filePath, const ImageParams& params)
|
||||
ImageRef Image::LoadFromFile(const std::filesystem::path& filePath, const ImageParams& params)
|
||||
{
|
||||
return ImageLoader::LoadFromFile(filePath, params);
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ namespace Nz
|
||||
Reset(largeIndices, std::move(buffer));
|
||||
}
|
||||
|
||||
IndexBuffer::IndexBuffer(bool largeIndices, BufferRef buffer, UInt32 offset, UInt32 size)
|
||||
IndexBuffer::IndexBuffer(bool largeIndices, BufferRef buffer, std::size_t offset, std::size_t size)
|
||||
{
|
||||
ErrorFlags(ErrorFlag_ThrowException, true);
|
||||
Reset(largeIndices, std::move(buffer), offset, size);
|
||||
}
|
||||
|
||||
IndexBuffer::IndexBuffer(bool largeIndices, UInt32 length, DataStorage storage, BufferUsageFlags usage)
|
||||
IndexBuffer::IndexBuffer(bool largeIndices, std::size_t length, DataStorage storage, BufferUsageFlags usage)
|
||||
{
|
||||
ErrorFlags(ErrorFlag_ThrowException, true);
|
||||
Reset(largeIndices, length, storage, usage);
|
||||
@@ -53,14 +53,14 @@ namespace Nz
|
||||
return Nz::ComputeCacheMissCount(mapper.begin(), m_indexCount);
|
||||
}
|
||||
|
||||
bool IndexBuffer::Fill(const void* data, UInt32 startIndex, UInt32 length)
|
||||
bool IndexBuffer::Fill(const void* data, std::size_t startIndex, std::size_t length)
|
||||
{
|
||||
UInt32 stride = GetStride();
|
||||
std::size_t stride = GetStride();
|
||||
|
||||
return FillRaw(data, startIndex*stride, length*stride);
|
||||
}
|
||||
|
||||
bool IndexBuffer::FillRaw(const void* data, UInt32 offset, UInt32 size)
|
||||
bool IndexBuffer::FillRaw(const void* data, std::size_t offset, std::size_t size)
|
||||
{
|
||||
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size");
|
||||
@@ -68,7 +68,7 @@ namespace Nz
|
||||
return m_buffer->Fill(data, m_startOffset+offset, size);
|
||||
}
|
||||
|
||||
void* IndexBuffer::MapRaw(BufferAccess access, UInt32 offset, UInt32 size)
|
||||
void* IndexBuffer::MapRaw(BufferAccess access, std::size_t offset, std::size_t size)
|
||||
{
|
||||
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size");
|
||||
@@ -76,7 +76,7 @@ namespace Nz
|
||||
return m_buffer->Map(access, offset, size);
|
||||
}
|
||||
|
||||
void* IndexBuffer::MapRaw(BufferAccess access, UInt32 offset, UInt32 size) const
|
||||
void* IndexBuffer::MapRaw(BufferAccess access, std::size_t offset, std::size_t size) const
|
||||
{
|
||||
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size");
|
||||
@@ -103,14 +103,14 @@ namespace Nz
|
||||
Reset(largeIndices, buffer, 0, buffer->GetSize());
|
||||
}
|
||||
|
||||
void IndexBuffer::Reset(bool largeIndices, BufferRef buffer, UInt32 offset, UInt32 size)
|
||||
void IndexBuffer::Reset(bool largeIndices, BufferRef buffer, std::size_t offset, std::size_t size)
|
||||
{
|
||||
NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(buffer->GetType() == BufferType_Index, "Buffer must be an index buffer");
|
||||
NazaraAssert(size > 0, "Invalid size");
|
||||
NazaraAssert(offset + size > buffer->GetSize(), "Virtual buffer exceed buffer bounds");
|
||||
|
||||
UInt32 stride = static_cast<UInt32>((largeIndices) ? sizeof(UInt32) : sizeof(UInt16));
|
||||
std::size_t stride = static_cast<std::size_t>((largeIndices) ? sizeof(std::size_t) : sizeof(UInt16));
|
||||
|
||||
m_buffer = buffer;
|
||||
m_endOffset = offset + size;
|
||||
@@ -119,9 +119,9 @@ namespace Nz
|
||||
m_startOffset = offset;
|
||||
}
|
||||
|
||||
void IndexBuffer::Reset(bool largeIndices, UInt32 length, DataStorage storage, BufferUsageFlags usage)
|
||||
void IndexBuffer::Reset(bool largeIndices, std::size_t length, DataStorage storage, BufferUsageFlags usage)
|
||||
{
|
||||
UInt32 stride = static_cast<UInt32>((largeIndices) ? sizeof(UInt32) : sizeof(UInt16));
|
||||
std::size_t stride = static_cast<std::size_t>((largeIndices) ? sizeof(std::size_t) : sizeof(UInt16));
|
||||
|
||||
m_endOffset = length * stride;
|
||||
m_indexCount = length;
|
||||
|
||||
@@ -71,10 +71,10 @@ namespace Nz
|
||||
InvalidateAABB();
|
||||
}
|
||||
|
||||
void Mesh::AddSubMesh(const String& identifier, SubMesh* subMesh)
|
||||
void Mesh::AddSubMesh(const std::string& identifier, SubMesh* subMesh)
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
NazaraAssert(!identifier.IsEmpty(), "Identifier is empty");
|
||||
NazaraAssert(!identifier.empty(), "Identifier is empty");
|
||||
NazaraAssert(m_subMeshMap.find(identifier) == m_subMeshMap.end(), "SubMesh identifier \"" + identifier + "\" is already in use");
|
||||
NazaraAssert(subMesh, "Invalid submesh");
|
||||
NazaraAssert(subMesh->GetAnimationType() == m_animationType, "Submesh animation type doesn't match mesh animation type");
|
||||
@@ -83,7 +83,7 @@ namespace Nz
|
||||
|
||||
AddSubMesh(subMesh);
|
||||
|
||||
m_subMeshMap[identifier] = static_cast<UInt32>(index);
|
||||
m_subMeshMap[identifier] = static_cast<std::size_t>(index);
|
||||
}
|
||||
|
||||
SubMesh* Mesh::BuildSubMesh(const Primitive& primitive, const MeshParams& params)
|
||||
@@ -256,11 +256,11 @@ namespace Nz
|
||||
|
||||
void Mesh::BuildSubMeshes(const PrimitiveList& list, const MeshParams& params)
|
||||
{
|
||||
for (UInt32 i = 0; i < list.GetSize(); ++i)
|
||||
for (std::size_t i = 0; i < list.GetSize(); ++i)
|
||||
BuildSubMesh(list.GetPrimitive(i), params);
|
||||
}
|
||||
|
||||
bool Mesh::CreateSkeletal(UInt32 jointCount)
|
||||
bool Mesh::CreateSkeletal(std::size_t jointCount)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
@@ -293,7 +293,7 @@ namespace Nz
|
||||
{
|
||||
OnMeshDestroy(this);
|
||||
|
||||
m_animationPath.Clear();
|
||||
m_animationPath.clear();
|
||||
m_materialData.clear();
|
||||
m_materialData.resize(1);
|
||||
m_skeleton.Destroy();
|
||||
@@ -350,7 +350,7 @@ namespace Nz
|
||||
return m_aabb;
|
||||
}
|
||||
|
||||
String Mesh::GetAnimation() const
|
||||
std::filesystem::path Mesh::GetAnimation() const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
@@ -364,7 +364,7 @@ namespace Nz
|
||||
return m_animationType;
|
||||
}
|
||||
|
||||
UInt32 Mesh::GetJointCount() const
|
||||
std::size_t Mesh::GetJointCount() const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
NazaraAssert(m_animationType == AnimationType_Skeletal, "Mesh is not skeletal");
|
||||
@@ -372,7 +372,7 @@ namespace Nz
|
||||
return m_jointCount;
|
||||
}
|
||||
|
||||
ParameterList& Mesh::GetMaterialData(UInt32 index)
|
||||
ParameterList& Mesh::GetMaterialData(std::size_t index)
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
NazaraAssert(index < m_materialData.size(), "Material index out of range");
|
||||
@@ -380,7 +380,7 @@ namespace Nz
|
||||
return m_materialData[index];
|
||||
}
|
||||
|
||||
const ParameterList& Mesh::GetMaterialData(UInt32 index) const
|
||||
const ParameterList& Mesh::GetMaterialData(std::size_t index) const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
NazaraAssert(index < m_materialData.size(), "Material index out of range");
|
||||
@@ -388,11 +388,11 @@ namespace Nz
|
||||
return m_materialData[index];
|
||||
}
|
||||
|
||||
UInt32 Mesh::GetMaterialCount() const
|
||||
std::size_t Mesh::GetMaterialCount() const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
return static_cast<UInt32>(m_materialData.size());
|
||||
return static_cast<std::size_t>(m_materialData.size());
|
||||
}
|
||||
|
||||
Skeleton* Mesh::GetSkeleton()
|
||||
@@ -411,7 +411,7 @@ namespace Nz
|
||||
return &m_skeleton;
|
||||
}
|
||||
|
||||
SubMesh* Mesh::GetSubMesh(const String& identifier)
|
||||
SubMesh* Mesh::GetSubMesh(const std::string& identifier)
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
@@ -421,7 +421,7 @@ namespace Nz
|
||||
return m_subMeshes[it->second].subMesh;
|
||||
}
|
||||
|
||||
SubMesh* Mesh::GetSubMesh(UInt32 index)
|
||||
SubMesh* Mesh::GetSubMesh(std::size_t index)
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
NazaraAssert(index < m_subMeshes.size(), "Submesh index out of range");
|
||||
@@ -429,7 +429,7 @@ namespace Nz
|
||||
return m_subMeshes[index].subMesh;
|
||||
}
|
||||
|
||||
const SubMesh* Mesh::GetSubMesh(const String& identifier) const
|
||||
const SubMesh* Mesh::GetSubMesh(const std::string& identifier) const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
@@ -439,7 +439,7 @@ namespace Nz
|
||||
return m_subMeshes[it->second].subMesh;
|
||||
}
|
||||
|
||||
const SubMesh* Mesh::GetSubMesh(UInt32 index) const
|
||||
const SubMesh* Mesh::GetSubMesh(std::size_t index) const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
NazaraAssert(index < m_subMeshes.size(), "Submesh index out of range");
|
||||
@@ -447,14 +447,14 @@ namespace Nz
|
||||
return m_subMeshes[index].subMesh;
|
||||
}
|
||||
|
||||
UInt32 Mesh::GetSubMeshCount() const
|
||||
std::size_t Mesh::GetSubMeshCount() const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
return static_cast<UInt32>(m_subMeshes.size());
|
||||
return static_cast<std::size_t>(m_subMeshes.size());
|
||||
}
|
||||
|
||||
UInt32 Mesh::GetSubMeshIndex(const String& identifier) const
|
||||
std::size_t Mesh::GetSubMeshIndex(const std::string& identifier) const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
@@ -464,22 +464,22 @@ namespace Nz
|
||||
return it->second;
|
||||
}
|
||||
|
||||
UInt32 Mesh::GetTriangleCount() const
|
||||
std::size_t Mesh::GetTriangleCount() const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
UInt32 triangleCount = 0;
|
||||
std::size_t triangleCount = 0;
|
||||
for (const SubMeshData& data : m_subMeshes)
|
||||
triangleCount += data.subMesh->GetTriangleCount();
|
||||
|
||||
return triangleCount;
|
||||
}
|
||||
|
||||
UInt32 Mesh::GetVertexCount() const
|
||||
std::size_t Mesh::GetVertexCount() const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
UInt32 vertexCount = 0;
|
||||
std::size_t vertexCount = 0;
|
||||
for (const SubMeshData& data : m_subMeshes)
|
||||
vertexCount += data.subMesh->GetVertexCount();
|
||||
|
||||
@@ -495,14 +495,14 @@ namespace Nz
|
||||
OnMeshInvalidateAABB(this);
|
||||
}
|
||||
|
||||
bool Mesh::HasSubMesh(const String& identifier) const
|
||||
bool Mesh::HasSubMesh(const std::string& identifier) const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
return m_subMeshMap.find(identifier) != m_subMeshMap.end();
|
||||
}
|
||||
|
||||
bool Mesh::HasSubMesh(UInt32 index) const
|
||||
bool Mesh::HasSubMesh(std::size_t index) const
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
@@ -536,8 +536,8 @@ namespace Nz
|
||||
BufferMapper<VertexBuffer> mapper(staticMesh.GetVertexBuffer(), BufferAccess_ReadWrite);
|
||||
MeshVertex* vertices = static_cast<MeshVertex*>(mapper.GetPointer());
|
||||
|
||||
UInt32 vertexCount = staticMesh.GetVertexCount();
|
||||
for (UInt32 i = 0; i < vertexCount; ++i)
|
||||
std::size_t vertexCount = staticMesh.GetVertexCount();
|
||||
for (std::size_t i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
vertices->position -= center;
|
||||
vertices++;
|
||||
@@ -551,49 +551,47 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::RemoveSubMesh(const String& identifier)
|
||||
void Mesh::RemoveSubMesh(const std::string& identifier)
|
||||
{
|
||||
UInt32 index = GetSubMeshIndex(identifier);
|
||||
|
||||
// On déplace l'itérateur du début d'une distance de x
|
||||
auto it2 = m_subMeshes.begin();
|
||||
std::advance(it2, index);
|
||||
m_subMeshes.erase(it2);
|
||||
|
||||
InvalidateAABB();
|
||||
std::size_t index = GetSubMeshIndex(identifier);
|
||||
RemoveSubMesh(index);
|
||||
}
|
||||
|
||||
void Mesh::RemoveSubMesh(UInt32 index)
|
||||
void Mesh::RemoveSubMesh(std::size_t index)
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
NazaraAssert(index < m_subMeshes.size(), "Submesh index out of range");
|
||||
|
||||
// On déplace l'itérateur du début de x
|
||||
auto it = m_subMeshes.begin();
|
||||
std::advance(it, index);
|
||||
m_subMeshes.erase(it);
|
||||
m_subMeshes.erase(m_subMeshes.begin() + index);
|
||||
|
||||
// Shift indices
|
||||
for (auto& it : m_subMeshMap)
|
||||
{
|
||||
if (it.second > index)
|
||||
it.second--;
|
||||
}
|
||||
|
||||
InvalidateAABB();
|
||||
}
|
||||
|
||||
bool Mesh::SaveToFile(const String& filePath, const MeshParams& params)
|
||||
bool Mesh::SaveToFile(const std::filesystem::path& filePath, const MeshParams& params)
|
||||
{
|
||||
return MeshSaver::SaveToFile(*this, filePath, params);
|
||||
}
|
||||
|
||||
bool Mesh::SaveToStream(Stream& stream, const String& format, const MeshParams& params)
|
||||
bool Mesh::SaveToStream(Stream& stream, const std::string& format, const MeshParams& params)
|
||||
{
|
||||
return MeshSaver::SaveToStream(*this, stream, format, params);
|
||||
}
|
||||
|
||||
void Mesh::SetAnimation(const String& animationPath)
|
||||
void Mesh::SetAnimation(const std::filesystem::path& animationPath)
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
|
||||
m_animationPath = animationPath;
|
||||
}
|
||||
|
||||
void Mesh::SetMaterialData(UInt32 matIndex, ParameterList data)
|
||||
void Mesh::SetMaterialData(std::size_t matIndex, ParameterList data)
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
NazaraAssert(matIndex < m_materialData.size(), "Material index out of range");
|
||||
@@ -601,7 +599,7 @@ namespace Nz
|
||||
m_materialData[matIndex] = std::move(data);
|
||||
}
|
||||
|
||||
void Mesh::SetMaterialCount(UInt32 matCount)
|
||||
void Mesh::SetMaterialCount(std::size_t matCount)
|
||||
{
|
||||
NazaraAssert(m_isValid, "Mesh should be created first");
|
||||
NazaraAssert(matCount > 0, "A mesh should have at least a material");
|
||||
@@ -611,7 +609,7 @@ namespace Nz
|
||||
#ifdef NAZARA_DEBUG
|
||||
for (SubMeshData& data : m_subMeshes)
|
||||
{
|
||||
UInt32 matIndex = data.subMesh->GetMaterialIndex();
|
||||
std::size_t matIndex = data.subMesh->GetMaterialIndex();
|
||||
if (matIndex >= matCount)
|
||||
{
|
||||
data.subMesh->SetMaterialIndex(0); // To prevent a crash
|
||||
@@ -635,8 +633,8 @@ namespace Nz
|
||||
|
||||
Boxf aabb(vertices->position.x, vertices->position.y, vertices->position.z, 0.f, 0.f, 0.f);
|
||||
|
||||
UInt32 vertexCount = staticMesh.GetVertexCount();
|
||||
for (UInt32 i = 0; i < vertexCount; ++i)
|
||||
std::size_t vertexCount = staticMesh.GetVertexCount();
|
||||
for (std::size_t i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
vertices->position = matrix.Transform(vertices->position);
|
||||
aabb.ExtendTo(vertices->position);
|
||||
@@ -648,7 +646,7 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
MeshRef Mesh::LoadFromFile(const String& filePath, const MeshParams& params)
|
||||
MeshRef Mesh::LoadFromFile(const std::filesystem::path& filePath, const MeshParams& params)
|
||||
{
|
||||
return MeshLoader::LoadFromFile(filePath, params);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace Nz
|
||||
return m_vertexBuffer;
|
||||
}
|
||||
|
||||
unsigned int SkeletalMesh::GetVertexCount() const
|
||||
std::size_t SkeletalMesh::GetVertexCount() const
|
||||
{
|
||||
return m_vertexBuffer->GetVertexCount();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Nz
|
||||
{
|
||||
struct SkeletonImpl
|
||||
{
|
||||
std::unordered_map<String, UInt32> jointMap;
|
||||
std::unordered_map<String, std::size_t> jointMap;
|
||||
std::vector<Joint> joints;
|
||||
Boxf aabb;
|
||||
bool aabbUpdated = false;
|
||||
@@ -32,7 +32,7 @@ namespace Nz
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool Skeleton::Create(UInt32 jointCount)
|
||||
bool Skeleton::Create(std::size_t jointCount)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (jointCount == 0)
|
||||
@@ -118,7 +118,7 @@ namespace Nz
|
||||
return &m_impl->joints[it->second];
|
||||
}
|
||||
|
||||
Joint* Skeleton::GetJoint(UInt32 index)
|
||||
Joint* Skeleton::GetJoint(std::size_t index)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
@@ -165,7 +165,7 @@ namespace Nz
|
||||
return &m_impl->joints[it->second];
|
||||
}
|
||||
|
||||
const Joint* Skeleton::GetJoint(UInt32 index) const
|
||||
const Joint* Skeleton::GetJoint(std::size_t index) const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
@@ -210,7 +210,7 @@ namespace Nz
|
||||
return &m_impl->joints[0];
|
||||
}
|
||||
|
||||
UInt32 Skeleton::GetJointCount() const
|
||||
std::size_t Skeleton::GetJointCount() const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
@@ -220,7 +220,7 @@ namespace Nz
|
||||
}
|
||||
#endif
|
||||
|
||||
return static_cast<UInt32>(m_impl->joints.size());
|
||||
return static_cast<std::size_t>(m_impl->joints.size());
|
||||
}
|
||||
|
||||
int Skeleton::GetJointIndex(const String& jointName) const
|
||||
@@ -285,7 +285,7 @@ namespace Nz
|
||||
InvalidateJoints();
|
||||
}
|
||||
|
||||
void Skeleton::Interpolate(const Skeleton& skeletonA, const Skeleton& skeletonB, float interpolation, UInt32* indices, UInt32 indiceCount)
|
||||
void Skeleton::Interpolate(const Skeleton& skeletonA, const Skeleton& skeletonB, float interpolation, std::size_t* indices, std::size_t indiceCount)
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (!m_impl)
|
||||
@@ -315,9 +315,9 @@ namespace Nz
|
||||
|
||||
const Joint* jointsA = &skeletonA.m_impl->joints[0];
|
||||
const Joint* jointsB = &skeletonB.m_impl->joints[0];
|
||||
for (UInt32 i = 0; i < indiceCount; ++i)
|
||||
for (std::size_t i = 0; i < indiceCount; ++i)
|
||||
{
|
||||
UInt32 index = indices[i];
|
||||
std::size_t index = indices[i];
|
||||
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (index >= m_impl->joints.size())
|
||||
@@ -352,7 +352,7 @@ namespace Nz
|
||||
m_impl->jointMapUpdated = skeleton.m_impl->jointMapUpdated;
|
||||
m_impl->joints = skeleton.m_impl->joints;
|
||||
|
||||
// Code crade mais son optimisation demanderait de stocker jointCount*sizeof(UInt32) en plus
|
||||
// Code crade mais son optimisation demanderait de stocker jointCount*sizeof(std::size_t) en plus
|
||||
// Ce qui, pour juste une copie qui ne se fera que rarement, ne vaut pas le coup
|
||||
// L'éternel trade-off mémoire/calculs ..
|
||||
std::size_t jointCount = skeleton.m_impl->joints.size();
|
||||
@@ -414,7 +414,7 @@ namespace Nz
|
||||
{
|
||||
NazaraAssert(m_impl->jointMap.find(name) == m_impl->jointMap.end(), "Joint name \"" + name + "\" is already present in joint map");
|
||||
|
||||
m_impl->jointMap[name] = static_cast<UInt32>(i);
|
||||
m_impl->jointMap[name] = static_cast<std::size_t>(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Nz
|
||||
return m_vertexBuffer;
|
||||
}
|
||||
|
||||
unsigned int StaticMesh::GetVertexCount() const
|
||||
std::size_t StaticMesh::GetVertexCount() const
|
||||
{
|
||||
return m_vertexBuffer->GetVertexCount();
|
||||
}
|
||||
|
||||
@@ -32,14 +32,14 @@ namespace Nz
|
||||
void SubMesh::GenerateNormals()
|
||||
{
|
||||
VertexMapper mapper(this);
|
||||
UInt32 vertexCount = mapper.GetVertexCount();
|
||||
std::size_t vertexCount = mapper.GetVertexCount();
|
||||
|
||||
SparsePtr<Vector3f> normals = mapper.GetComponentPtr<Vector3f>(VertexComponent_Normal);
|
||||
SparsePtr<Vector3f> positions = mapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
|
||||
if (!normals || !positions)
|
||||
return;
|
||||
|
||||
for (UInt32 i = 0; i < vertexCount; ++i)
|
||||
for (std::size_t i = 0; i < vertexCount; ++i)
|
||||
normals[i].MakeZero();
|
||||
|
||||
TriangleIterator iterator(this);
|
||||
@@ -58,14 +58,14 @@ namespace Nz
|
||||
}
|
||||
while (iterator.Advance());
|
||||
|
||||
for (UInt32 i = 0; i < vertexCount; ++i)
|
||||
for (std::size_t i = 0; i < vertexCount; ++i)
|
||||
normals[i].Normalize();
|
||||
}
|
||||
|
||||
void SubMesh::GenerateNormalsAndTangents()
|
||||
{
|
||||
VertexMapper mapper(this);
|
||||
UInt32 vertexCount = mapper.GetVertexCount();
|
||||
std::size_t vertexCount = mapper.GetVertexCount();
|
||||
|
||||
SparsePtr<Vector3f> normals = mapper.GetComponentPtr<Vector3f>(VertexComponent_Normal);
|
||||
SparsePtr<Vector3f> positions = mapper.GetComponentPtr<Vector3f>(VertexComponent_Position);
|
||||
@@ -74,7 +74,7 @@ namespace Nz
|
||||
if (!normals || !positions || !tangents || !texCoords)
|
||||
return;
|
||||
|
||||
for (UInt32 i = 0; i < vertexCount; ++i)
|
||||
for (std::size_t i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
normals[i].MakeZero();
|
||||
tangents[i].MakeZero();
|
||||
@@ -169,10 +169,10 @@ namespace Nz
|
||||
return m_primitiveMode;
|
||||
}
|
||||
|
||||
unsigned int SubMesh::GetTriangleCount() const
|
||||
std::size_t SubMesh::GetTriangleCount() const
|
||||
{
|
||||
const IndexBuffer* indexBuffer = GetIndexBuffer();
|
||||
unsigned int indexCount;
|
||||
std::size_t indexCount;
|
||||
if (indexBuffer)
|
||||
indexCount = indexBuffer->GetIndexCount();
|
||||
else
|
||||
@@ -199,7 +199,7 @@ namespace Nz
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt32 SubMesh::GetMaterialIndex() const
|
||||
std::size_t SubMesh::GetMaterialIndex() const
|
||||
{
|
||||
return m_matIndex;
|
||||
}
|
||||
@@ -209,7 +209,7 @@ namespace Nz
|
||||
m_primitiveMode = mode;
|
||||
}
|
||||
|
||||
void SubMesh::SetMaterialIndex(UInt32 matIndex)
|
||||
void SubMesh::SetMaterialIndex(std::size_t matIndex)
|
||||
{
|
||||
m_matIndex = matIndex;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@ namespace Nz
|
||||
Reset(std::move(vertexDeclaration), std::move(buffer));
|
||||
}
|
||||
|
||||
VertexBuffer::VertexBuffer(VertexDeclarationConstRef vertexDeclaration, BufferRef buffer, UInt32 offset, UInt32 size)
|
||||
VertexBuffer::VertexBuffer(VertexDeclarationConstRef vertexDeclaration, BufferRef buffer, std::size_t offset, std::size_t size)
|
||||
{
|
||||
ErrorFlags(ErrorFlag_ThrowException, true);
|
||||
Reset(std::move(vertexDeclaration), std::move(buffer), offset, size);
|
||||
}
|
||||
|
||||
VertexBuffer::VertexBuffer(VertexDeclarationConstRef vertexDeclaration, UInt32 length, DataStorage storage, BufferUsageFlags usage)
|
||||
VertexBuffer::VertexBuffer(VertexDeclarationConstRef vertexDeclaration, std::size_t length, DataStorage storage, BufferUsageFlags usage)
|
||||
{
|
||||
ErrorFlags(ErrorFlag_ThrowException, true);
|
||||
Reset(std::move(vertexDeclaration), length, storage, usage);
|
||||
@@ -42,13 +42,13 @@ namespace Nz
|
||||
OnVertexBufferRelease(this);
|
||||
}
|
||||
|
||||
bool VertexBuffer::Fill(const void* data, UInt32 startVertex, UInt32 length)
|
||||
bool VertexBuffer::Fill(const void* data, std::size_t startVertex, std::size_t length)
|
||||
{
|
||||
UInt32 stride = static_cast<UInt32>(m_vertexDeclaration->GetStride());
|
||||
std::size_t stride = static_cast<std::size_t>(m_vertexDeclaration->GetStride());
|
||||
return FillRaw(data, startVertex*stride, length*stride);
|
||||
}
|
||||
|
||||
bool VertexBuffer::FillRaw(const void* data, UInt32 offset, UInt32 size)
|
||||
bool VertexBuffer::FillRaw(const void* data, std::size_t offset, std::size_t size)
|
||||
{
|
||||
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size");
|
||||
@@ -56,24 +56,24 @@ namespace Nz
|
||||
return m_buffer->Fill(data, m_startOffset + offset, size);
|
||||
}
|
||||
|
||||
void* VertexBuffer::Map(BufferAccess access, UInt32 startVertex, UInt32 length)
|
||||
void* VertexBuffer::Map(BufferAccess access, std::size_t startVertex, std::size_t length)
|
||||
{
|
||||
UInt32 stride = static_cast<UInt32>(m_vertexDeclaration->GetStride());
|
||||
std::size_t stride = static_cast<std::size_t>(m_vertexDeclaration->GetStride());
|
||||
|
||||
return MapRaw(access, startVertex*stride, length*stride);
|
||||
}
|
||||
|
||||
void* VertexBuffer::Map(BufferAccess access, UInt32 startVertex, UInt32 length) const
|
||||
void* VertexBuffer::Map(BufferAccess access, std::size_t startVertex, std::size_t length) const
|
||||
{
|
||||
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(m_vertexDeclaration, "Invalid vertex declaration");
|
||||
|
||||
UInt32 stride = static_cast<UInt32>(m_vertexDeclaration->GetStride());
|
||||
std::size_t stride = static_cast<std::size_t>(m_vertexDeclaration->GetStride());
|
||||
|
||||
return MapRaw(access, startVertex*stride, length*stride);
|
||||
}
|
||||
|
||||
void* VertexBuffer::MapRaw(BufferAccess access, UInt32 offset, UInt32 size)
|
||||
void* VertexBuffer::MapRaw(BufferAccess access, std::size_t offset, std::size_t size)
|
||||
{
|
||||
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size");
|
||||
@@ -81,7 +81,7 @@ namespace Nz
|
||||
return m_buffer->Map(access, offset, size);
|
||||
}
|
||||
|
||||
void* VertexBuffer::MapRaw(BufferAccess access, UInt32 offset, UInt32 size) const
|
||||
void* VertexBuffer::MapRaw(BufferAccess access, std::size_t offset, std::size_t size) const
|
||||
{
|
||||
NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size");
|
||||
@@ -100,11 +100,11 @@ namespace Nz
|
||||
NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(buffer->GetType() == BufferType_Vertex, "Buffer must be a vertex buffer");
|
||||
|
||||
UInt32 size = buffer->GetSize();
|
||||
std::size_t size = buffer->GetSize();
|
||||
Reset(std::move(vertexDeclaration), std::move(buffer), 0, size);
|
||||
}
|
||||
|
||||
void VertexBuffer::Reset(VertexDeclarationConstRef vertexDeclaration, BufferRef buffer, UInt32 offset, UInt32 size)
|
||||
void VertexBuffer::Reset(VertexDeclarationConstRef vertexDeclaration, BufferRef buffer, std::size_t offset, std::size_t size)
|
||||
{
|
||||
NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer");
|
||||
NazaraAssert(size > 0, "Invalid size");
|
||||
@@ -113,13 +113,13 @@ namespace Nz
|
||||
m_buffer = buffer;
|
||||
m_endOffset = offset + size;
|
||||
m_startOffset = offset;
|
||||
m_vertexCount = (vertexDeclaration) ? (size / static_cast<UInt32>(vertexDeclaration->GetStride())) : 0;
|
||||
m_vertexCount = (vertexDeclaration) ? (size / static_cast<std::size_t>(vertexDeclaration->GetStride())) : 0;
|
||||
m_vertexDeclaration = vertexDeclaration;
|
||||
}
|
||||
|
||||
void VertexBuffer::Reset(VertexDeclarationConstRef vertexDeclaration, UInt32 length, DataStorage storage, BufferUsageFlags usage)
|
||||
void VertexBuffer::Reset(VertexDeclarationConstRef vertexDeclaration, std::size_t length, DataStorage storage, BufferUsageFlags usage)
|
||||
{
|
||||
m_endOffset = length * ((vertexDeclaration) ? static_cast<UInt32>(vertexDeclaration->GetStride()) : 1);
|
||||
m_endOffset = length * ((vertexDeclaration) ? static_cast<std::size_t>(vertexDeclaration->GetStride()) : 1);
|
||||
m_startOffset = 0;
|
||||
m_vertexCount = length;
|
||||
m_vertexDeclaration = std::move(vertexDeclaration);
|
||||
@@ -140,7 +140,7 @@ namespace Nz
|
||||
{
|
||||
NazaraAssert(vertexDeclaration, "Invalid vertex declaration");
|
||||
|
||||
m_vertexCount = (m_endOffset - m_startOffset) / static_cast<UInt32>(vertexDeclaration->GetStride());
|
||||
m_vertexCount = (m_endOffset - m_startOffset) / static_cast<std::size_t>(vertexDeclaration->GetStride());
|
||||
m_vertexDeclaration = std::move(vertexDeclaration);
|
||||
}
|
||||
|
||||
|
||||
229
src/NazaraSDK/Application.cpp
Normal file
229
src/NazaraSDK/Application.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NazaraSDK/Application.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <regex>
|
||||
|
||||
#ifndef NDK_SERVER
|
||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||
#include <Nazara/Utility/SimpleTextDrawer.hpp>
|
||||
#include <NazaraSDK/Components/CameraComponent.hpp>
|
||||
#include <NazaraSDK/Components/GraphicsComponent.hpp>
|
||||
#include <NazaraSDK/Components/NodeComponent.hpp>
|
||||
#include <NazaraSDK/Systems/RenderSystem.hpp>
|
||||
#endif
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
/*!
|
||||
* \ingroup NDK
|
||||
* \class Ndk::Application
|
||||
* \brief NDK class that represents the application, it offers a set of tools to ease the development
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs an Application object with command-line arguments
|
||||
*
|
||||
* Pass the argc and argv arguments from the main function.
|
||||
*
|
||||
* Command-line arguments can be retrieved by application methods
|
||||
*
|
||||
* This calls Sdk::Initialize()
|
||||
*
|
||||
* \remark Only one Application instance can exist at a time
|
||||
*/
|
||||
Application::Application(int argc, char* argv[]) :
|
||||
Application()
|
||||
{
|
||||
std::regex optionRegex(R"(-(\w+))");
|
||||
std::regex valueRegex(R"(-(\w+)\s*=\s*(.+))");
|
||||
|
||||
std::smatch results;
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string argument(argv[i]);
|
||||
if (std::regex_match(argument, results, valueRegex))
|
||||
{
|
||||
Nz::String key(results[1].str());
|
||||
Nz::String value(results[2].str());
|
||||
|
||||
m_parameters[key.ToLower()] = value;
|
||||
NazaraDebug("Registred parameter from command-line: " + key.ToLower() + "=" + value);
|
||||
}
|
||||
else if (std::regex_match(argument, results, optionRegex))
|
||||
{
|
||||
Nz::String option(results[1].str());
|
||||
|
||||
m_options.insert(option);
|
||||
NazaraDebug("Registred option from command-line: " + option);
|
||||
}
|
||||
else
|
||||
NazaraWarning("Ignored command-line argument #" + Nz::String::Number(i) + " \"" + argument + '"');
|
||||
}
|
||||
|
||||
#ifndef NDK_SERVER
|
||||
if (HasOption("console"))
|
||||
EnableConsole(true);
|
||||
|
||||
if (HasOption("fpscounter"))
|
||||
EnableFPSCounter(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Runs the application by updating worlds, taking care about windows, ...
|
||||
*/
|
||||
bool Application::Run()
|
||||
{
|
||||
#ifndef NDK_SERVER
|
||||
bool hasAtLeastOneActiveWindow = false;
|
||||
|
||||
auto it = m_windows.begin();
|
||||
while (it != m_windows.end())
|
||||
{
|
||||
Nz::Window& window = *it->window;
|
||||
|
||||
window.ProcessEvents();
|
||||
|
||||
if (!window.IsOpen(true))
|
||||
{
|
||||
it = m_windows.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
hasAtLeastOneActiveWindow = true;
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
if (m_exitOnClosedWindows && !hasAtLeastOneActiveWindow)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (m_shouldQuit)
|
||||
return false;
|
||||
|
||||
m_updateTime = m_updateClock.Restart() / 1'000'000.f;
|
||||
|
||||
for (World& world : m_worlds)
|
||||
world.Update(m_updateTime);
|
||||
|
||||
#ifndef NDK_SERVER
|
||||
for (WindowInfo& info : m_windows)
|
||||
{
|
||||
if (!info.overlayWorld)
|
||||
continue;
|
||||
|
||||
if (info.fpsCounter)
|
||||
{
|
||||
FPSCounterOverlay& fpsCounter = *info.fpsCounter;
|
||||
|
||||
fpsCounter.frameCount++;
|
||||
|
||||
fpsCounter.elapsedTime += m_updateTime;
|
||||
if (fpsCounter.elapsedTime >= 1.f)
|
||||
{
|
||||
fpsCounter.sprite->Update(Nz::SimpleTextDrawer::Draw("FPS: " + Nz::String::Number(fpsCounter.frameCount), 36));
|
||||
fpsCounter.frameCount = 0;
|
||||
fpsCounter.elapsedTime = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
info.overlayWorld->Update(m_updateTime);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef NDK_SERVER
|
||||
void Application::SetupConsole(WindowInfo& info)
|
||||
{
|
||||
std::unique_ptr<ConsoleOverlay> overlay = std::make_unique<ConsoleOverlay>();
|
||||
|
||||
Nz::Vector2ui windowDimensions;
|
||||
if (info.window->IsValid())
|
||||
windowDimensions = info.window->GetSize();
|
||||
else
|
||||
windowDimensions.MakeZero();
|
||||
|
||||
overlay->console = info.canvas->Add<Console>();
|
||||
|
||||
Console& consoleRef = *overlay->console;
|
||||
consoleRef.Resize({float(windowDimensions.x), windowDimensions.y / 4.f});
|
||||
consoleRef.Show(false);
|
||||
|
||||
// Redirect logs toward the console
|
||||
overlay->logSlot.Connect(Nz::Log::OnLogWrite, [&consoleRef] (const Nz::String& str)
|
||||
{
|
||||
consoleRef.AddLine(str);
|
||||
});
|
||||
|
||||
// Setup a few event callback to handle the console
|
||||
Nz::EventHandler& eventHandler = info.window->GetEventHandler();
|
||||
|
||||
overlay->keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& event)
|
||||
{
|
||||
if (event.code == Nz::Keyboard::F9)
|
||||
{
|
||||
// Toggle console visibility and focus
|
||||
if (consoleRef.IsVisible())
|
||||
{
|
||||
consoleRef.ClearFocus();
|
||||
consoleRef.Show(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
consoleRef.Show(true);
|
||||
consoleRef.SetFocus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
overlay->resizedSlot.Connect(info.renderTarget->OnRenderTargetSizeChange, [&consoleRef] (const Nz::RenderTarget* renderTarget)
|
||||
{
|
||||
Nz::Vector2ui size = renderTarget->GetSize();
|
||||
consoleRef.Resize({float(size.x), size.y / 4.f});
|
||||
});
|
||||
|
||||
info.console = std::move(overlay);
|
||||
}
|
||||
|
||||
void Application::SetupFPSCounter(WindowInfo& info)
|
||||
{
|
||||
std::unique_ptr<FPSCounterOverlay> fpsCounter = std::make_unique<FPSCounterOverlay>();
|
||||
fpsCounter->sprite = Nz::TextSprite::New();
|
||||
|
||||
fpsCounter->entity = info.overlayWorld->CreateEntity();
|
||||
fpsCounter->entity->AddComponent<NodeComponent>();
|
||||
fpsCounter->entity->AddComponent<GraphicsComponent>().Attach(fpsCounter->sprite);
|
||||
|
||||
info.fpsCounter = std::move(fpsCounter);
|
||||
}
|
||||
|
||||
void Application::SetupOverlay(WindowInfo& info)
|
||||
{
|
||||
info.overlayWorld = std::make_unique<World>(false); //< No default system
|
||||
|
||||
if (info.window->IsValid())
|
||||
info.canvas = std::make_unique<Canvas>(info.overlayWorld->CreateHandle(), info.window->GetEventHandler(), info.window->GetCursorController().CreateHandle());
|
||||
|
||||
RenderSystem& renderSystem = info.overlayWorld->AddSystem<RenderSystem>();
|
||||
renderSystem.ChangeRenderTechnique<Nz::ForwardRenderTechnique>();
|
||||
renderSystem.SetDefaultBackground(nullptr);
|
||||
renderSystem.SetGlobalUp(Nz::Vector3f::Down());
|
||||
|
||||
EntityHandle viewer = info.overlayWorld->CreateEntity();
|
||||
CameraComponent& camComponent = viewer->AddComponent<CameraComponent>();
|
||||
viewer->AddComponent<NodeComponent>();
|
||||
|
||||
camComponent.SetProjectionType(Nz::ProjectionType_Orthogonal);
|
||||
camComponent.SetTarget(info.renderTarget);
|
||||
}
|
||||
#endif
|
||||
|
||||
Application* Application::s_application = nullptr;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user