First commit
This commit is contained in:
29
src/Nazara/Audio/Debug/Leaks.cpp
Normal file
29
src/Nazara/Audio/Debug/Leaks.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Audio/Config.hpp>
|
||||
#if NAZARA_AUDIO_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
|
||||
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
|
||||
#include <new>
|
||||
|
||||
void* operator new(std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, true);
|
||||
}
|
||||
|
||||
void operator delete(void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, true);
|
||||
}
|
||||
#endif
|
||||
187
src/Nazara/Core/ByteArray.cpp
Normal file
187
src/Nazara/Core/ByteArray.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
/*#include <Nazara/Core/ByteArray.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzByteArray::NzByteArray() :
|
||||
m_sharedArray(&emptyArray)
|
||||
{
|
||||
}
|
||||
|
||||
NzByteArray::NzByteArray(const nzUInt8* buffer, unsigned int bufferLength)
|
||||
{
|
||||
if (bufferLength > 0)
|
||||
{
|
||||
m_sharedArray = new SharedArray;
|
||||
m_sharedArray->allocatedSize = bufferLength;
|
||||
m_sharedArray->buffer = new nzUInt8[bufferLength];
|
||||
m_sharedArray->size = bufferLength;
|
||||
std::memcpy(m_sharedArray->buffer, buffer, bufferLength*sizeof(nzUInt8));
|
||||
}
|
||||
else
|
||||
m_sharedArray = &emptyArray;
|
||||
}
|
||||
|
||||
NzByteArray::NzByteArray(const NzByteArray& buffer) :
|
||||
m_sharedArray(buffer.m_sharedArray)
|
||||
{
|
||||
if (m_sharedArray != &emptyArray)
|
||||
{
|
||||
NazaraMutexLock(m_sharedArray->mutex);
|
||||
m_sharedArray->refCount++;
|
||||
NazaraMutexUnlock(m_sharedArray->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
NzByteArray::NzByteArray(NzByteArray&& buffer) :
|
||||
m_sharedArray(buffer.m_sharedArray)
|
||||
{
|
||||
buffer.m_sharedArray = &emptyArray;
|
||||
}
|
||||
|
||||
NzByteArray::NzByteArray(SharedArray* sharedArray) :
|
||||
m_sharedArray(sharedArray)
|
||||
{
|
||||
}
|
||||
|
||||
NzByteArray::~NzByteArray()
|
||||
{
|
||||
ReleaseArray();
|
||||
}
|
||||
|
||||
unsigned int NzByteArray::Capacity() const
|
||||
{
|
||||
return m_sharedArray->allocatedSize;
|
||||
}
|
||||
|
||||
void NzByteArray::Clear()
|
||||
{
|
||||
ReleaseArray();
|
||||
}
|
||||
|
||||
const nzUInt8* NzByteArray::GetBuffer() const
|
||||
{
|
||||
return m_sharedArray->buffer;
|
||||
}
|
||||
|
||||
unsigned int NzByteArray::GetSize() const
|
||||
{
|
||||
return m_sharedArray->size;
|
||||
}
|
||||
|
||||
NzByteArray& NzByteArray::Insert(int pos, const nzUInt8* buffer, unsigned int bufferLength)
|
||||
{
|
||||
if (bufferLength == 0)
|
||||
return *this;
|
||||
|
||||
if (m_sharedArray->size == 0)
|
||||
return operator=(string);
|
||||
|
||||
if (pos < 0)
|
||||
pos = std::max(static_cast<int>(m_sharedArray->size + pos), 0);
|
||||
|
||||
unsigned int start = std::min(static_cast<unsigned int>(pos), m_sharedArray->size);
|
||||
|
||||
// Si le buffer est déjà suffisamment grand
|
||||
if (m_sharedArray->allocatedSize >= m_sharedArray->size + bufferLength)
|
||||
{
|
||||
EnsureOwnership();
|
||||
|
||||
std::memmove(&m_sharedArray->buffer[start+bufferLength], &m_sharedArray->buffer[start], m_sharedArray->size*sizeof(nzUInt8));
|
||||
std::memcpy(&m_sharedArray->buffer[start], buffer, bufferLength*sizeof(nzUInt8));
|
||||
|
||||
m_sharedArray->size += bufferLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int newSize = m_sharedArray->size+bufferLength;
|
||||
nzUInt8* newBuffer = new nzUInt8[newSize+1];
|
||||
|
||||
nzUInt8* ptr = newBuffer;
|
||||
const nzUInt8* s = m_sharedArray->buffer;
|
||||
|
||||
while (ptr != &newBuffer[start])
|
||||
*ptr++ = *s++;
|
||||
|
||||
while (ptr != &newBuffer[start+bufferLength])
|
||||
*ptr++ = *buffer++;
|
||||
|
||||
std::strcpy(ptr, s);
|
||||
|
||||
ReleaseString();
|
||||
m_sharedArray = new SharedString;
|
||||
m_sharedArray->allocatedSize = newSize;
|
||||
m_sharedArray->buffer = newBuffer;
|
||||
m_sharedArray->size = newSize;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzByteArray& NzByteArray::Insert(int pos, const NzByteArray& byteArray);
|
||||
|
||||
bool NzByteArray::IsEmpty() const
|
||||
{
|
||||
return m_sharedArray->size == 0;
|
||||
}
|
||||
|
||||
void NzByteArray::Reserve(unsigned int bufferSize)
|
||||
{
|
||||
if (m_sharedArray->allocatedSize >= bufferSize)
|
||||
return;
|
||||
|
||||
char* ptr = new char[bufferSize+1];
|
||||
if (m_sharedArray->size > 0)
|
||||
std::strcpy(ptr, m_sharedArray->buffer);
|
||||
|
||||
unsigned int size = m_sharedArray->size;
|
||||
|
||||
ReleaseArray();
|
||||
m_sharedArray = new SharedString;
|
||||
m_sharedArray->allocatedSize = bufferSize;
|
||||
m_sharedArray->buffer = ptr;
|
||||
m_sharedArray->size = size;
|
||||
}
|
||||
|
||||
NzByteArray& NzByteArray::Resize(int size, nzUInt8 byte = '\0');
|
||||
NzByteArray NzByteArray::Resized(int size, nzUInt8 byte = '\0') const;
|
||||
|
||||
NzByteArray SubArray(int startPos, int endPos = -1) const;
|
||||
|
||||
void Swap(NzByteArray& byteArray);
|
||||
|
||||
NzByteArray& Trim(nzUInt8 byte = '\0');
|
||||
NzByteArray Trimmed(nzUInt8 byte = '\0') const;
|
||||
|
||||
// Méthodes compatibles STD
|
||||
nzUInt8* begin();
|
||||
const nzUInt8* begin() const;
|
||||
nzUInt8* end();
|
||||
const nzUInt8* end() const;
|
||||
void push_front(nzUInt8 c);
|
||||
void push_back(nzUInt8 c);
|
||||
|
||||
typedef const nzUInt8& const_reference;
|
||||
typedef nzUInt8* iterator;
|
||||
//typedef nzUInt8* reverse_iterator;
|
||||
typedef nzUInt8 value_type;
|
||||
// Méthodes compatibles STD
|
||||
|
||||
nzUInt8& operator[](unsigned int pos);
|
||||
nzUInt8 operator[](unsigned int pos) const;
|
||||
|
||||
NzByteArray& operator=(const NzByteArray& byteArray);
|
||||
NzByteArray& operator=(NzByteArray&& byteArray);
|
||||
|
||||
NzByteArray operator+(const NzByteArray& byteArray) const;
|
||||
NzByteArray& operator+=(const NzByteArray& byteArray);
|
||||
|
||||
static int Compare(const NzByteArray& first, const NzByteArray& second);
|
||||
|
||||
static SharedArray emptyArray;
|
||||
|
||||
private:
|
||||
void EnsureOwnership();
|
||||
bool FillHash(NzHashImpl* hash) const;
|
||||
void ReleaseArray();
|
||||
*/
|
||||
103
src/Nazara/Core/Clock.cpp
Normal file
103
src/Nazara/Core/Clock.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_CLOCK_CPP
|
||||
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/ClockImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/ClockImpl.hpp>
|
||||
#else
|
||||
#error OS not handled
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzClock::NzClock() :
|
||||
m_elapsedTime(0),
|
||||
m_refTime(NzGetMicroseconds()),
|
||||
m_paused(false)
|
||||
{
|
||||
}
|
||||
|
||||
float NzClock::GetSeconds() const
|
||||
{
|
||||
return GetMicroseconds()/1000000.f;
|
||||
}
|
||||
|
||||
nzUInt64 NzClock::GetMicroseconds() const
|
||||
{
|
||||
NazaraMutex(m_mutex);
|
||||
|
||||
return m_elapsedTime + (NzGetMicroseconds()-m_refTime);
|
||||
}
|
||||
|
||||
nzUInt64 NzClock::GetMilliseconds() const
|
||||
{
|
||||
return GetMicroseconds()/1000;
|
||||
}
|
||||
|
||||
bool NzClock::IsPaused() const
|
||||
{
|
||||
NazaraMutex(m_mutex);
|
||||
|
||||
return m_paused;
|
||||
}
|
||||
|
||||
void NzClock::Pause()
|
||||
{
|
||||
NazaraMutex(m_mutex);
|
||||
|
||||
if (!m_paused)
|
||||
{
|
||||
m_elapsedTime += NzGetMicroseconds()-m_refTime;
|
||||
m_paused = true;
|
||||
}
|
||||
else
|
||||
NazaraWarning("Clock is already paused, ignoring...");
|
||||
}
|
||||
|
||||
void NzClock::Restart()
|
||||
{
|
||||
NazaraMutex(m_mutex);
|
||||
|
||||
m_elapsedTime = 0;
|
||||
m_refTime = NzGetMicroseconds();
|
||||
m_paused = false;
|
||||
}
|
||||
|
||||
void NzClock::Unpause()
|
||||
{
|
||||
NazaraMutex(m_mutex);
|
||||
|
||||
if (m_paused)
|
||||
{
|
||||
m_refTime = NzGetMicroseconds();
|
||||
m_paused = false;
|
||||
}
|
||||
else
|
||||
NazaraWarning("Clock is not paused, ignoring...");
|
||||
}
|
||||
|
||||
nzUInt64 NzGetMicrosecondsLowPrecision()
|
||||
{
|
||||
return NzClockImplGetMilliseconds()*1000ULL;
|
||||
}
|
||||
|
||||
nzUInt64 NzGetMicrosecondsFirstRun()
|
||||
{
|
||||
if (NzClockImplInitializeHighPrecision())
|
||||
NzGetMicroseconds = NzClockImplGetMicroseconds;
|
||||
else
|
||||
NzGetMicroseconds = NzGetMicrosecondsLowPrecision;
|
||||
|
||||
return NzGetMicroseconds();
|
||||
}
|
||||
|
||||
NzClockFunction NzGetMicroseconds = NzGetMicrosecondsFirstRun;
|
||||
NzClockFunction NzGetMilliseconds = NzClockImplGetMilliseconds;
|
||||
29
src/Nazara/Core/Debug/Leaks.cpp
Normal file
29
src/Nazara/Core/Debug/Leaks.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#if NAZARA_CORE_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
|
||||
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
|
||||
#include <new>
|
||||
|
||||
void* operator new(std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, true);
|
||||
}
|
||||
|
||||
void operator delete(void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, true);
|
||||
}
|
||||
#endif
|
||||
227
src/Nazara/Core/Debug/MemoryLeakTracker.cpp
Normal file
227
src/Nazara/Core/Debug/MemoryLeakTracker.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Block
|
||||
{
|
||||
std::size_t size;
|
||||
const char* file;
|
||||
Block* prev;
|
||||
Block* next;
|
||||
bool array;
|
||||
unsigned int line;
|
||||
unsigned int magic;
|
||||
};
|
||||
|
||||
bool initialized = false;
|
||||
const unsigned int magic = 0x51429EE;
|
||||
const char* MLTFileName = "NazaraLeaks.log";
|
||||
const char* nextFreeFile = "Internal error";
|
||||
unsigned int nextFreeLine = 0;
|
||||
|
||||
static Block ptrList =
|
||||
{
|
||||
0,
|
||||
nullptr,
|
||||
&ptrList,
|
||||
&ptrList,
|
||||
false,
|
||||
0,
|
||||
magic
|
||||
};
|
||||
}
|
||||
|
||||
NzMemoryManager::NzMemoryManager()
|
||||
{
|
||||
}
|
||||
|
||||
NzMemoryManager::~NzMemoryManager()
|
||||
{
|
||||
Uninitialize();
|
||||
}
|
||||
|
||||
void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line)
|
||||
{
|
||||
EnsureInitialization();
|
||||
|
||||
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
|
||||
ptr->array = multi;
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = size;
|
||||
ptr->magic = magic;
|
||||
|
||||
ptr->prev = ptrList.prev;
|
||||
ptr->next = &ptrList;
|
||||
ptrList.prev->next = ptr;
|
||||
ptrList.prev = ptr;
|
||||
|
||||
return reinterpret_cast<char*>(ptr)+sizeof(Block);
|
||||
}
|
||||
|
||||
void NzMemoryManager::Free(void* pointer, bool multi)
|
||||
{
|
||||
if (!pointer)
|
||||
return;
|
||||
|
||||
Block* ptr = reinterpret_cast<Block*>(reinterpret_cast<char*>(pointer)-sizeof(Block));
|
||||
if (ptr->magic != magic)
|
||||
return;
|
||||
|
||||
if (ptr->array != multi)
|
||||
{
|
||||
char* time = TimeInfo();
|
||||
|
||||
FILE* log = std::fopen(MLTFileName, "a");
|
||||
|
||||
if (nextFreeFile)
|
||||
{
|
||||
if (multi)
|
||||
std::fprintf(log, "%s Warning: delete[] on new at %s:%d\n", time, nextFreeFile, nextFreeLine);
|
||||
else
|
||||
std::fprintf(log, "%s Warning: delete on new[] at %s:%d\n", time, nextFreeFile, nextFreeLine);
|
||||
|
||||
nextFreeFile = nullptr;
|
||||
nextFreeLine = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (multi)
|
||||
std::fprintf(log, "%s Warning: delete[] on new at unknown position\n", time);
|
||||
else
|
||||
std::fprintf(log, "%s Warning: delete on new[] at unknown position\n", time);
|
||||
}
|
||||
|
||||
std::fclose(log);
|
||||
|
||||
std::free(time);
|
||||
}
|
||||
|
||||
ptr->magic = 0;
|
||||
ptr->prev->next = ptr->next;
|
||||
ptr->next->prev = ptr->prev;
|
||||
|
||||
std::free(ptr);
|
||||
}
|
||||
|
||||
void NzMemoryManager::NextFree(const char* file, unsigned int line)
|
||||
{
|
||||
nextFreeFile = file;
|
||||
nextFreeLine = line;
|
||||
}
|
||||
|
||||
void NzMemoryManager::EnsureInitialization()
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
if (std::atexit(Uninitialize) != 0)
|
||||
{
|
||||
static NzMemoryManager manager;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void NzMemoryManager::Initialize()
|
||||
{
|
||||
char* time = TimeInfo();
|
||||
|
||||
FILE* file = std::fopen(MLTFileName, "w");
|
||||
std::fprintf(file, "%s ==============================\n", time);
|
||||
std::fprintf(file, "%s Nazara Memory Leak Tracker \n", time);
|
||||
std::fprintf(file, "%s ==============================\n", time);
|
||||
std::fclose(file);
|
||||
|
||||
std::free(time);
|
||||
}
|
||||
|
||||
char* NzMemoryManager::TimeInfo()
|
||||
{
|
||||
char* buffer = reinterpret_cast<char*>(std::malloc(23*sizeof(char)));
|
||||
|
||||
time_t currentTime = std::time(nullptr);
|
||||
std::strftime(buffer, 23, "%d/%m/%Y - %H:%M:%S:", std::localtime(¤tTime));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void NzMemoryManager::Uninitialize()
|
||||
{
|
||||
FILE* log = std::fopen(MLTFileName, "a");
|
||||
|
||||
char* time = TimeInfo();
|
||||
|
||||
std::fprintf(log, "%s Application finished, checking leaks...\n", time);
|
||||
|
||||
if (ptrList.next == &ptrList)
|
||||
{
|
||||
std::fprintf(log, "%s ==============================\n", time);
|
||||
std::fprintf(log, "%s No leak detected \n", time);
|
||||
std::fprintf(log, "%s ==============================", time);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fprintf(log, "%s ==============================\n", time);
|
||||
std::fprintf(log, "%s Leaks have been detected \n", time);
|
||||
std::fprintf(log, "%s ==============================\n\n", time);
|
||||
std::fputs("Leak list:\n", log);
|
||||
|
||||
Block* ptr = ptrList.next;
|
||||
unsigned int count = 0;
|
||||
unsigned int totalSize = 0;
|
||||
while (ptr != &ptrList)
|
||||
{
|
||||
count++;
|
||||
totalSize += ptr->size;
|
||||
if (ptr->file)
|
||||
std::fprintf(log, "-0x%p -> %d bytes allocated at %s:%d\n", reinterpret_cast<char*>(ptr)+sizeof(Block), ptr->size, ptr->file, ptr->line);
|
||||
else
|
||||
std::fprintf(log, "-0x%p -> %d bytes allocated at unknown position\n", reinterpret_cast<char*>(ptr)+sizeof(Block), ptr->size);
|
||||
|
||||
void* pointer = ptr;
|
||||
ptr = ptr->next;
|
||||
std::free(pointer);
|
||||
}
|
||||
|
||||
std::fprintf(log, "\n%d blocks leaked (%d bytes)", count, totalSize);
|
||||
}
|
||||
|
||||
std::free(time);
|
||||
std::fclose(log);
|
||||
}
|
||||
|
||||
void* operator new(std::size_t size, const char* file, unsigned int line)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, false, file, line);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size, const char* file, unsigned int line)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, true, file, line);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr, const char* file, unsigned int line) throw()
|
||||
{
|
||||
NzMemoryManager::NextFree(file, line);
|
||||
NzMemoryManager::Free(ptr, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* ptr, const char* file, unsigned int line) throw()
|
||||
{
|
||||
NzMemoryManager::NextFree(file, line);
|
||||
NzMemoryManager::Free(ptr, true);
|
||||
}
|
||||
309
src/Nazara/Core/Directory.cpp
Normal file
309
src/Nazara/Core/Directory.cpp
Normal file
@@ -0,0 +1,309 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_DIRECTORY_CPP
|
||||
|
||||
#include <Nazara/Core/Directory.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
//#include <Nazara/ThreadLocalVar.h>
|
||||
|
||||
#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
|
||||
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
NzString currentPath(NzDirectoryImpl::GetCurrent());
|
||||
//static ThreadLocalVar<NzString> currentPath(NzDirectoryImpl::GetCurrent());
|
||||
}
|
||||
|
||||
NzDirectory::NzDirectory() :
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
NzDirectory::NzDirectory(const NzString& dirPath) :
|
||||
m_impl(nullptr)
|
||||
{
|
||||
SetDirectory(dirPath);
|
||||
}
|
||||
|
||||
NzDirectory::~NzDirectory()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void NzDirectory::Close()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
NazaraMutexUnlock(m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
NzString NzDirectory::GetResultName() const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return NzString();
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetResultName();
|
||||
}
|
||||
|
||||
NzString NzDirectory::GetResultPath() const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return NzString();
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_dirPath + NAZARA_DIRECTORY_SEPARATOR + m_impl->GetResultName();
|
||||
}
|
||||
|
||||
nzUInt64 NzDirectory::GetResultSize() const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetResultSize();
|
||||
}
|
||||
|
||||
bool NzDirectory::IsResultDirectory() const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->IsResultDirectory();
|
||||
}
|
||||
|
||||
bool NzDirectory::NextResult(bool skipDots)
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (skipDots)
|
||||
{
|
||||
NzString name;
|
||||
do
|
||||
{
|
||||
if (!m_impl->NextResult())
|
||||
return false;
|
||||
|
||||
name = m_impl->GetResultName();
|
||||
}
|
||||
while (name == '.' || name == "..");
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return m_impl->NextResult();
|
||||
}
|
||||
|
||||
bool NzDirectory::Open()
|
||||
{
|
||||
Close();
|
||||
|
||||
if (!Exists(m_dirPath))
|
||||
return false;
|
||||
|
||||
NazaraMutexLock(m_mutex);
|
||||
|
||||
m_impl = new NzDirectoryImpl(this);
|
||||
if (!m_impl->Open(m_dirPath))
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
NazaraMutexUnlock(m_mutex);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzDirectory::SetDirectory(const NzString& dirPath)
|
||||
{
|
||||
Close();
|
||||
|
||||
m_dirPath = NzFile::AbsolutePath(dirPath);
|
||||
}
|
||||
|
||||
bool NzDirectory::Copy(const NzString& sourcePath, const NzString& destPath)
|
||||
{
|
||||
if (sourcePath.IsEmpty() || destPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
NzString dirPath(sourcePath);
|
||||
NzString dest(NzFile::NormalizePath(destPath));
|
||||
|
||||
if (!Create(destPath, true))
|
||||
{
|
||||
NazaraError("Unable to create \"" + destPath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
NzDirectory 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 (!NzFile::Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName()))
|
||||
{
|
||||
NazaraError("Unable to copy \"" + dir.GetResultPath() + "\" to \"" + dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName() + '"');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dir.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzDirectory::Create(const NzString& dirPath, bool recursive)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
NzString path = NzFile::NormalizePath(dirPath);
|
||||
unsigned int foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR);
|
||||
if (foundPos == NzString::npos)
|
||||
return false;
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
// Contrairement au disque (Ex: "C:"), le chemin réseau n'est pas considéré comme un dossier (Ex: "\\Laptop")
|
||||
if (path.Match("\\\\*"))
|
||||
{
|
||||
foundPos = path.Find('\\', 2);
|
||||
if (foundPos == NzString::npos)
|
||||
return false;
|
||||
|
||||
foundPos = path.Find('\\', foundPos+1);
|
||||
if (foundPos == NzString::npos)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
NzString p = path.Substr(0, foundPos);
|
||||
if (p.EndsWith(NAZARA_DIRECTORY_SEPARATOR))
|
||||
p = p.Substr(0, -2);
|
||||
|
||||
if (!NzDirectoryImpl::Exists(p) && !NzDirectoryImpl::Create(p))
|
||||
return false;
|
||||
|
||||
if (foundPos == NzString::npos)
|
||||
break;
|
||||
|
||||
foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR, foundPos+1);
|
||||
}
|
||||
while (true);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return NzDirectoryImpl::Create(NzFile::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
bool NzDirectory::Exists(const NzString& dirPath)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return NzDirectoryImpl::Exists(NzFile::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
NzString NzDirectory::GetCurrent()
|
||||
{
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
bool NzDirectory::Remove(const NzString& dirPath, bool emptyDirectory)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (emptyDirectory)
|
||||
{
|
||||
NzDirectory dir(dirPath);
|
||||
if (!dir.Open())
|
||||
return NzDirectoryImpl::Remove(dirPath); // Si on n'arrive pas à ouvrir le dossier, on tente de le supprimer
|
||||
|
||||
while (dir.NextResult(true))
|
||||
{
|
||||
if (dir.IsResultDirectory())
|
||||
{
|
||||
if (!Remove(dir.GetResultPath(), true))
|
||||
return false;
|
||||
}
|
||||
else if (!NzFile::Delete(dir.GetResultPath()))
|
||||
{
|
||||
NazaraError(dir.GetResultPath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dir.Close();
|
||||
}
|
||||
|
||||
return NzDirectoryImpl::Remove(NzFile::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
bool NzDirectory::SetCurrent(const NzString& dirPath)
|
||||
{
|
||||
NzString path = NzFile::AbsolutePath(dirPath);
|
||||
if (NzDirectoryImpl::Exists(path))
|
||||
{
|
||||
currentPath = path;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
90
src/Nazara/Core/DynLib.cpp
Normal file
90
src/Nazara/Core/DynLib.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_DYNLIB_CPP
|
||||
|
||||
#include <Nazara/Core/DynLib.hpp>
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/DynLibImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/DynLibImpl.hpp>
|
||||
#else
|
||||
#error No implementation for this platform
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzDynLib::NzDynLib(const NzString& libraryPath) :
|
||||
m_path(libraryPath),
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
NzDynLib::~NzDynLib()
|
||||
{
|
||||
Unload();
|
||||
}
|
||||
|
||||
NzString NzDynLib::GetLastError() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
NzDynLibFunc NzDynLib::GetSymbol(const NzString& symbol) const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Library not opened");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetSymbol(symbol);
|
||||
}
|
||||
|
||||
bool NzDynLib::Load()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
Unload();
|
||||
|
||||
m_impl = new NzDynLibImpl(this);
|
||||
if (!m_impl->Load(m_path))
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzDynLib::Unload()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Unload();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NzDynLib::SetLastError(const NzString& error)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_lastError = error;
|
||||
}
|
||||
67
src/Nazara/Core/Error.cpp
Normal file
67
src/Nazara/Core/Error.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_ERROR_CPP
|
||||
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <windows.h>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
void NzError(nzErrorType type, const NzString& error, unsigned int line, const char* file, const char* function)
|
||||
{
|
||||
NazaraLog->WriteError(type, error, line, file, function);
|
||||
|
||||
#if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE
|
||||
if (type == nzErrorType_AssertFailed)
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int NzGetLastSystemErrorCode()
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
return GetLastError();
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
return errno;
|
||||
#else
|
||||
#error GetLastSystemErrorCode is not implemented on this platform
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
NzString NzGetLastSystemError(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,
|
||||
0,
|
||||
code,
|
||||
0,
|
||||
reinterpret_cast<LPWSTR>(&buffer),
|
||||
0,
|
||||
nullptr);
|
||||
|
||||
NzString error(NzString::Unicode(buffer));
|
||||
LocalFree(buffer);
|
||||
|
||||
error.Trim(); // Pour une raison inconnue, Windows met deux-trois retours à la ligne après le message
|
||||
|
||||
return error;
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
return strerror(code);
|
||||
#else
|
||||
#error GetLastSystemError is not implemented on this platform
|
||||
|
||||
return "GetLastSystemError is not implemented on this platform";
|
||||
#endif
|
||||
}
|
||||
784
src/Nazara/Core/File.cpp
Normal file
784
src/Nazara/Core/File.cpp
Normal file
@@ -0,0 +1,784 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_FILE_CPP
|
||||
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Hash.hpp>
|
||||
#include <Nazara/Core/HashImpl.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/FileImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/FileImpl.hpp>
|
||||
#else
|
||||
#error OS not handled
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzFile::NzFile() :
|
||||
m_endianness(nzEndianness_Unknown),
|
||||
m_impl(nullptr),
|
||||
m_openMode(0)
|
||||
{
|
||||
}
|
||||
|
||||
NzFile::NzFile(const NzString& filePath) :
|
||||
m_endianness(nzEndianness_Unknown),
|
||||
m_impl(nullptr),
|
||||
m_openMode(0)
|
||||
{
|
||||
SetFile(filePath);
|
||||
}
|
||||
|
||||
NzFile::NzFile(const NzString& filePath, unsigned long openMode) :
|
||||
m_endianness(nzEndianness_Unknown),
|
||||
m_impl(nullptr),
|
||||
m_openMode(0)
|
||||
{
|
||||
SetFile(filePath);
|
||||
Open(openMode);
|
||||
}
|
||||
|
||||
NzFile::NzFile(NzFile&& file) :
|
||||
m_endianness(file.m_endianness),
|
||||
m_filePath(std::move(file.m_filePath)),
|
||||
m_impl(file.m_impl),
|
||||
m_openMode(file.m_openMode)
|
||||
{
|
||||
file.m_impl = nullptr;
|
||||
}
|
||||
|
||||
NzFile::~NzFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool NzFile::Copy(const NzString& newFilePath)
|
||||
{
|
||||
return Copy(m_filePath, newFilePath);
|
||||
}
|
||||
|
||||
void NzFile::Close()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzFile::Delete()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
Close();
|
||||
|
||||
return Delete(m_filePath);
|
||||
}
|
||||
|
||||
bool NzFile::EndOfFile() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("File not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->EndOfFile();
|
||||
}
|
||||
|
||||
bool NzFile::Exists() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (IsOpen())
|
||||
return true; // Le fichier est ouvert, donc il existe
|
||||
else
|
||||
return Exists(m_filePath);
|
||||
}
|
||||
|
||||
void NzFile::Flush()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("File not opened");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m_openMode & ReadWrite) == 0 && (m_openMode & WriteOnly) == 0)
|
||||
{
|
||||
NazaraError("Cannot flush file without write access");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->Flush();
|
||||
}
|
||||
|
||||
time_t NzFile::GetCreationTime() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return GetCreationTime(m_filePath);
|
||||
}
|
||||
|
||||
nzUInt64 NzFile::GetCursorPos() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("File not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetCursorPos();
|
||||
}
|
||||
|
||||
NzString NzFile::GetDirectoryPath() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_filePath.SubstrTo(NAZARA_DIRECTORY_SEPARATOR, -1, true);
|
||||
}
|
||||
|
||||
NzString NzFile::GetFilePath() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
NzString NzFile::GetFileName() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_filePath.SubstrFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true);
|
||||
}
|
||||
|
||||
time_t NzFile::GetLastAccessTime() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return GetLastAccessTime(m_filePath);
|
||||
}
|
||||
|
||||
time_t NzFile::GetLastWriteTime() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return GetLastWriteTime(m_filePath);
|
||||
}
|
||||
|
||||
NzString NzFile::GetLine(unsigned int lineSize)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("File not opened");
|
||||
return NzString();
|
||||
}
|
||||
|
||||
if ((m_openMode & ReadOnly) == 0 && (m_openMode & ReadWrite) == 0)
|
||||
{
|
||||
NazaraError("File not opened with read access");
|
||||
return NzString();
|
||||
}
|
||||
#endif
|
||||
|
||||
NzString line;
|
||||
if (lineSize == 0) // Taille maximale indéterminée
|
||||
{
|
||||
while (!m_impl->EndOfFile())
|
||||
{
|
||||
char c;
|
||||
if (m_impl->Read(&c, sizeof(char)) == sizeof(char))
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
if (m_openMode & Text && line.EndsWith('\r'))
|
||||
line.Resize(-1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
line += c;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
line.Reserve(lineSize);
|
||||
for (unsigned int i = 0; i < lineSize; ++i)
|
||||
{
|
||||
char c;
|
||||
if (m_impl->Read(&c, sizeof(char)) == sizeof(char))
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
if (m_openMode & Text && line.EndsWith('\r'))
|
||||
line.Resize(-1);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
line += c;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
nzUInt64 NzFile::GetSize() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return GetSize(m_filePath);
|
||||
}
|
||||
|
||||
bool NzFile::IsOpen() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
std::size_t NzFile::Read(void* buffer, std::size_t typeSize, unsigned int count)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("File not opened");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((m_openMode & ReadOnly) == 0 && (m_openMode & ReadWrite) == 0)
|
||||
{
|
||||
NazaraError("File not opened with read access");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!buffer || count == 0 || typeSize == 0)
|
||||
return 0;
|
||||
|
||||
std::size_t byteRead = m_impl->Read(buffer, typeSize*count);
|
||||
if (byteRead == 0)
|
||||
return 0;
|
||||
|
||||
if (m_endianness != nzEndianness_Unknown && m_endianness != NzGetPlatformEndianness() && typeSize != 1)
|
||||
{
|
||||
unsigned int typeCount = byteRead/typeSize;
|
||||
for (unsigned int i = 0; i < typeCount; ++i)
|
||||
NzByteSwap(static_cast<char*>(buffer) + i*typeSize, typeSize);
|
||||
}
|
||||
|
||||
return byteRead;
|
||||
}
|
||||
|
||||
bool NzFile::Rename(const NzString& newFilePath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
bool opened = IsOpen();
|
||||
Close();
|
||||
|
||||
bool success = Rename(m_filePath, newFilePath);
|
||||
if (success)
|
||||
m_filePath = NormalizePath(newFilePath);
|
||||
|
||||
if (opened)
|
||||
Open();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NzFile::Open(unsigned long openMode)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
Close();
|
||||
|
||||
if (m_filePath.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (openMode != 0)
|
||||
m_openMode = openMode;
|
||||
|
||||
if (m_openMode == 0)
|
||||
return false;
|
||||
|
||||
m_impl = new NzFileImpl(this);
|
||||
if (!m_impl->Open(m_filePath, m_openMode))
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzFile::SetCursorPos(CursorPosition pos, nzInt64 offset)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("File not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SetCursorPos(pos, offset);
|
||||
}
|
||||
|
||||
bool NzFile::SetCursorPos(nzUInt64 offset)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("File not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SetCursorPos(AtBegin, offset);
|
||||
}
|
||||
|
||||
void NzFile::SetEndianness(nzEndianness endianness)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_endianness = endianness;
|
||||
}
|
||||
|
||||
bool NzFile::SetFile(const NzString& filePath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (IsOpen())
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return false;
|
||||
|
||||
NzFileImpl* impl = new NzFileImpl(this);
|
||||
if (!impl->Open(filePath, m_openMode))
|
||||
{
|
||||
delete impl;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
|
||||
m_impl = impl;
|
||||
}
|
||||
|
||||
m_filePath = AbsolutePath(filePath);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzFile::SetOpenMode(unsigned int openMode)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (openMode == 0 || openMode == m_openMode)
|
||||
return true;
|
||||
|
||||
if (IsOpen())
|
||||
{
|
||||
NzFileImpl* impl = new NzFileImpl(this);
|
||||
if (!impl->Open(m_filePath, openMode))
|
||||
{
|
||||
delete impl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
|
||||
m_impl = impl;
|
||||
}
|
||||
|
||||
m_openMode = openMode;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzFile::Write(const NzString& string)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
NzString temp(string);
|
||||
|
||||
if (m_openMode & Text)
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
temp.Replace("\n", "\r\n");
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
// Rien à faire
|
||||
#elif defined(NAZARA_PLATFORM_MACOS)
|
||||
temp.Replace('\n', '\r');
|
||||
#else
|
||||
#error OS not handled
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int size = temp.GetSize();
|
||||
std::size_t bytesWritten = Write(temp.GetBuffer(), sizeof(char), size);
|
||||
|
||||
return bytesWritten == size*sizeof(char);
|
||||
}
|
||||
|
||||
std::size_t NzFile::Write(const void* buffer, std::size_t typeSize, unsigned int count)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!IsOpen())
|
||||
{
|
||||
NazaraError("File not opened");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((m_openMode & ReadWrite) == 0 && (m_openMode & WriteOnly) == 0)
|
||||
{
|
||||
NazaraError("File not opened with write access");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!buffer || count == 0 || typeSize == 0)
|
||||
return 0;
|
||||
|
||||
std::size_t bytesWritten;
|
||||
if (m_endianness != nzEndianness_Unknown && m_endianness != NzGetPlatformEndianness() && typeSize != 1)
|
||||
{
|
||||
char* buf = new char[count*typeSize];
|
||||
std::memcpy(buf, buffer, count*typeSize);
|
||||
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
NzByteSwap(&buf[i*typeSize], typeSize);
|
||||
|
||||
bytesWritten = m_impl->Write(buf, count*typeSize);
|
||||
|
||||
delete[] buf;
|
||||
}
|
||||
else
|
||||
bytesWritten = m_impl->Write(buffer, count*typeSize);
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
NzFile& NzFile::operator=(const NzString& filePath)
|
||||
{
|
||||
SetFile(filePath);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzFile& NzFile::operator=(NzFile&& file)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
std::swap(m_endianness, file.m_endianness);
|
||||
std::swap(m_filePath, file.m_filePath);
|
||||
std::swap(m_impl, file.m_impl);
|
||||
std::swap(m_openMode, file.m_openMode);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzString NzFile::AbsolutePath(const NzString& filePath)
|
||||
{
|
||||
// Je n'utilise pas les fonctions de l'OS car elles ne fonctionnent que pour un chemin existant
|
||||
NzString path = NormalizePath(filePath);
|
||||
if (path.IsEmpty())
|
||||
return NzString();
|
||||
|
||||
NzString base;
|
||||
unsigned int start;
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
if (path.Match("?:*"))
|
||||
start = 1;
|
||||
else if (path.Match("\\\\*"))
|
||||
{
|
||||
base = "\\\\";
|
||||
start = 2;
|
||||
}
|
||||
else if (path.StartsWith('\\')) // Spécial : '\' fait référence au disque racine
|
||||
{
|
||||
NzString drive = NzDirectory::GetCurrent().SubstrTo('\\');
|
||||
NzString end = path.Substr(1, -1);
|
||||
if (end.IsEmpty())
|
||||
path = drive;
|
||||
else
|
||||
path = drive + '\\' + end;
|
||||
|
||||
start = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Path unrecognized");
|
||||
return path;
|
||||
}
|
||||
#elif NAZARA_PLATEFORM_LINUX
|
||||
base = '/';
|
||||
start = 0;
|
||||
#else
|
||||
#error OS case not implemented
|
||||
#endif
|
||||
|
||||
static NzString upDir = NAZARA_DIRECTORY_SEPARATOR + NzString('.');
|
||||
|
||||
if (path.Find(upDir) == NzString::npos)
|
||||
return path;
|
||||
|
||||
std::vector<NzString> sep;
|
||||
if (path.Split(sep, NAZARA_DIRECTORY_SEPARATOR) <= 1)
|
||||
return path;
|
||||
|
||||
// Nous avons un chemin absolu, mais il nous faut un peu le nettoyer
|
||||
unsigned int pathLen = base.GetSize();
|
||||
for (unsigned int i = 0; i < sep.size(); ++i)
|
||||
{
|
||||
if (sep[i] == '.')
|
||||
sep.erase(sep.begin() + i--);
|
||||
else if (sep[i] == "..")
|
||||
{
|
||||
if (i > start) // Si nous ne sommes pas dans la partie protégée
|
||||
sep.erase(sep.begin() + i--);
|
||||
|
||||
sep.erase(sep.begin() + i--);
|
||||
}
|
||||
else
|
||||
pathLen += sep[i].GetSize();
|
||||
}
|
||||
|
||||
pathLen += sep.size()-1;
|
||||
|
||||
///FIXME: Le destructeur de NzStringStream provoque un bug lors de la libération de son vector
|
||||
|
||||
//NzStringStream stream(base);
|
||||
NzString stream;
|
||||
stream.Reserve(pathLen);
|
||||
stream.Append(base);
|
||||
for (unsigned int i = 0; i < sep.size(); ++i)
|
||||
{
|
||||
stream.Append(sep[i]);
|
||||
if (i != sep.size()-1)
|
||||
stream.Append(NAZARA_DIRECTORY_SEPARATOR);
|
||||
/*if (i != sep.size()-1)
|
||||
stream << sep[i] << NAZARA_DIRECTORY_SEPARATOR;
|
||||
else
|
||||
stream << sep[i];*/
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
bool NzFile::Copy(const NzString& sourcePath, const NzString& targetPath)
|
||||
{
|
||||
if (sourcePath.IsEmpty() || targetPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return NzFileImpl::Copy(NormalizePath(sourcePath), NormalizePath(targetPath));
|
||||
}
|
||||
|
||||
bool NzFile::Delete(const NzString& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return NzFileImpl::Delete(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
bool NzFile::Exists(const NzString& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return NzFileImpl::Exists(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
time_t NzFile::GetCreationTime(const NzString& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return 0;
|
||||
|
||||
return NzFileImpl::GetCreationTime(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
time_t NzFile::GetLastAccessTime(const NzString& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return 0;
|
||||
|
||||
return NzFileImpl::GetLastAccessTime(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
time_t NzFile::GetLastWriteTime(const NzString& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return 0;
|
||||
|
||||
return NzFileImpl::GetLastWriteTime(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
NzHashDigest NzFile::GetHash(const NzString& filePath, nzHash hash)
|
||||
{
|
||||
NzFile file(filePath);
|
||||
|
||||
NzHash h(hash);
|
||||
return h.Hash(file);
|
||||
}
|
||||
|
||||
NzHashDigest NzFile::GetHash(const NzString& filePath, NzHashImpl* hash)
|
||||
{
|
||||
NzFile file(filePath);
|
||||
|
||||
NzHash h(hash);
|
||||
return h.Hash(file);
|
||||
}
|
||||
|
||||
nzUInt64 NzFile::GetSize(const NzString& filePath)
|
||||
{
|
||||
if (filePath.IsEmpty())
|
||||
return 0;
|
||||
|
||||
return NzFileImpl::GetSize(NormalizePath(filePath));
|
||||
}
|
||||
|
||||
bool NzFile::IsAbsolute(const NzString& path)
|
||||
{
|
||||
NzString wpath(path);
|
||||
wpath.Trim();
|
||||
|
||||
if (wpath.IsEmpty())
|
||||
return false;
|
||||
|
||||
#if NAZARA_CORE_NORMALIZE_DIRECTORY_SEPARATORS
|
||||
wpath = NormalizeSeparators(wpath);
|
||||
#endif
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
if (path.Match("?:*"))
|
||||
return true;
|
||||
else if (path.Match("\\\\*"))
|
||||
return true;
|
||||
else if (wpath.StartsWith('\\')) // Spécial : '\' fait référence au disque racine
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#elif NAZARA_PLATEFORM_LINUX
|
||||
return wpath.StartsWith('/');
|
||||
#else
|
||||
#error OS case not implemented
|
||||
#endif
|
||||
}
|
||||
|
||||
NzString NzFile::NormalizePath(const NzString& filePath)
|
||||
{
|
||||
NzString path(filePath);
|
||||
path.Trim();
|
||||
|
||||
#if NAZARA_CORE_NORMALIZE_DIRECTORY_SEPARATORS
|
||||
path = NormalizeSeparators(path);
|
||||
#endif
|
||||
|
||||
if (!IsAbsolute(path))
|
||||
path = NzDirectory::GetCurrent() + NAZARA_DIRECTORY_SEPARATOR + path;
|
||||
|
||||
while (path.EndsWith(NAZARA_DIRECTORY_SEPARATOR))
|
||||
path.Resize(-1);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
NzString NzFile::NormalizeSeparators(const NzString& filePath)
|
||||
{
|
||||
NzString path(filePath);
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
path.Replace('/', '\\');
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
path.Replace('\\', '/');
|
||||
#else
|
||||
#error OS not handled
|
||||
#endif
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
bool NzFile::Rename(const NzString& sourcePath, const NzString& targetPath)
|
||||
{
|
||||
if (sourcePath.IsEmpty() || targetPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return NzFileImpl::Rename(NormalizePath(sourcePath), NormalizePath(targetPath));
|
||||
}
|
||||
|
||||
bool NzFile::FillHash(NzHashImpl* hash) const
|
||||
{
|
||||
NzFile file(m_filePath);
|
||||
if (!file.Open(NzFile::ReadOnly))
|
||||
{
|
||||
NazaraError("Unable to open file");
|
||||
return false;
|
||||
}
|
||||
|
||||
nzUInt64 remainingSize = file.GetSize();
|
||||
|
||||
char buffer[NAZARA_CORE_FILE_BUFFERSIZE];
|
||||
unsigned int size;
|
||||
while (remainingSize > 0)
|
||||
{
|
||||
size = (remainingSize >= NAZARA_CORE_FILE_BUFFERSIZE) ? NAZARA_CORE_FILE_BUFFERSIZE : static_cast<unsigned int>(remainingSize);
|
||||
if (file.Read(&buffer[0], sizeof(char), size) != sizeof(char)*size)
|
||||
{
|
||||
NazaraError("Unable to read file");
|
||||
return false;
|
||||
}
|
||||
|
||||
remainingSize -= size;
|
||||
hash->Append(reinterpret_cast<nzUInt8*>(&buffer[0]), size);
|
||||
}
|
||||
|
||||
return true;
|
||||
} // Fermeture auttomatique du fichier
|
||||
57
src/Nazara/Core/Hash.cpp
Normal file
57
src/Nazara/Core/Hash.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_HASH_CPP
|
||||
|
||||
#include <Nazara/Core/Hash.hpp>
|
||||
#include <Nazara/Core/Hash/CRC32.hpp>
|
||||
#include <Nazara/Core/Hash/Fletcher16.hpp>
|
||||
#include <Nazara/Core/Hash/MD5.hpp>
|
||||
#include <Nazara/Core/Hash/Whirlpool.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHash::NzHash(nzHash hash)
|
||||
{
|
||||
switch (hash)
|
||||
{
|
||||
case nzHash_Fletcher16:
|
||||
m_impl = new NzHashFletcher16;
|
||||
break;
|
||||
|
||||
case nzHash_CRC32:
|
||||
m_impl = new NzHashCRC32;
|
||||
break;
|
||||
|
||||
case nzHash_MD5:
|
||||
m_impl = new NzHashMD5;
|
||||
break;
|
||||
|
||||
case nzHash_Whirlpool:
|
||||
m_impl = new NzHashWhirlpool;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NzHash::NzHash(NzHashImpl* hashImpl) :
|
||||
m_impl(hashImpl)
|
||||
{
|
||||
}
|
||||
|
||||
NzHash::~NzHash()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
NzHashDigest NzHash::Hash(const NzHashable& hashable)
|
||||
{
|
||||
m_impl->Begin();
|
||||
if (hashable.FillHash(m_impl))
|
||||
return m_impl->End();
|
||||
else
|
||||
{
|
||||
m_impl->End();
|
||||
|
||||
return NzHashDigest();
|
||||
}
|
||||
}
|
||||
129
src/Nazara/Core/Hash/CRC32.cpp
Normal file
129
src/Nazara/Core/Hash/CRC32.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Hash/CRC32.hpp>
|
||||
#include <Nazara/Core/Endianness.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
struct NzHashCRC32_state
|
||||
{
|
||||
nzUInt32 crc;
|
||||
const nzUInt32* table;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
nzUInt32 crc32_reflect(nzUInt32 ref, unsigned int j)
|
||||
{
|
||||
nzUInt32 value = 0;
|
||||
|
||||
for (unsigned int i = 1; i <= j; ++i)
|
||||
{
|
||||
if (ref & 1)
|
||||
value |= 1 << (j - i);
|
||||
|
||||
ref >>= 1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static const nzUInt32 crc32_table[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
}
|
||||
|
||||
NzHashCRC32::NzHashCRC32(nzUInt32 polynomial)
|
||||
{
|
||||
m_state = new NzHashCRC32_state;
|
||||
|
||||
if (polynomial == 0x04c11db7)
|
||||
m_state->table = crc32_table; // Table précalculée (Bien plus rapide)
|
||||
else
|
||||
{
|
||||
nzUInt32* table = new nzUInt32[256];
|
||||
|
||||
for (unsigned int i = 0; i < 256; ++i)
|
||||
{
|
||||
table[i] = crc32_reflect(i, 8) << 24;
|
||||
for (unsigned int j = 0; j < 8; ++j)
|
||||
table[i] = (table[i] << 1) ^ (table[i] & (1 << 31) ? polynomial : 0);
|
||||
|
||||
table[i] = crc32_reflect(table[i], 32);
|
||||
}
|
||||
|
||||
m_state->table = table;
|
||||
}
|
||||
}
|
||||
|
||||
NzHashCRC32::~NzHashCRC32()
|
||||
{
|
||||
if (m_state->table != crc32_table)
|
||||
delete[] m_state->table;
|
||||
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashCRC32::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
while (len--)
|
||||
m_state->crc = m_state->table[(m_state->crc ^ *data++) & 0xFF] ^ (m_state->crc >> 8);
|
||||
}
|
||||
|
||||
void NzHashCRC32::Begin()
|
||||
{
|
||||
m_state->crc = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
NzHashDigest NzHashCRC32::End()
|
||||
{
|
||||
m_state->crc ^= 0xFFFFFFFF;
|
||||
|
||||
if (NazaraEndianness == nzEndianness_LittleEndian)
|
||||
NzByteSwap(&m_state->crc, sizeof(nzUInt32));
|
||||
|
||||
return NzHashDigest(GetHashName(), reinterpret_cast<nzUInt8*>(&m_state->crc), 4);
|
||||
}
|
||||
|
||||
unsigned int NzHashCRC32::GetDigestLength()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
NzString NzHashCRC32::GetHashName()
|
||||
{
|
||||
static NzString hashName = "CRC32";
|
||||
return hashName;
|
||||
}
|
||||
70
src/Nazara/Core/Hash/Fletcher16.cpp
Normal file
70
src/Nazara/Core/Hash/Fletcher16.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Hash/Fletcher16.hpp>
|
||||
#include <Nazara/Core/Endianness.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
struct NzHashFletcher16_state
|
||||
{
|
||||
nzUInt16 sum1;
|
||||
nzUInt16 sum2;
|
||||
};
|
||||
|
||||
NzHashFletcher16::NzHashFletcher16()
|
||||
{
|
||||
m_state = new NzHashFletcher16_state;
|
||||
}
|
||||
|
||||
NzHashFletcher16::~NzHashFletcher16()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashFletcher16::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
while (len)
|
||||
{
|
||||
unsigned int tlen = std::min(len, 21U);
|
||||
len -= tlen;
|
||||
do
|
||||
{
|
||||
m_state->sum1 += *data++;
|
||||
m_state->sum2 += m_state->sum1;
|
||||
}
|
||||
while (--tlen);
|
||||
|
||||
m_state->sum1 = (m_state->sum1 & 0xff) + (m_state->sum1 >> 8);
|
||||
m_state->sum2 = (m_state->sum2 & 0xff) + (m_state->sum2 >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
void NzHashFletcher16::Begin()
|
||||
{
|
||||
m_state->sum1 = 0xff;
|
||||
m_state->sum2 = 0xff;
|
||||
}
|
||||
|
||||
NzHashDigest NzHashFletcher16::End()
|
||||
{
|
||||
m_state->sum1 = (m_state->sum1 & 0xff) + (m_state->sum1 >> 8);
|
||||
m_state->sum2 = (m_state->sum2 & 0xff) + (m_state->sum2 >> 8);
|
||||
|
||||
nzUInt32 fletcher = (m_state->sum2 << 8) | m_state->sum1;
|
||||
if (NazaraEndianness == nzEndianness_BigEndian)
|
||||
NzByteSwap(&fletcher, sizeof(nzUInt32));
|
||||
|
||||
return NzHashDigest(GetHashName(), reinterpret_cast<nzUInt8*>(&fletcher), 2);
|
||||
}
|
||||
|
||||
unsigned int NzHashFletcher16::GetDigestLength()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
NzString NzHashFletcher16::GetHashName()
|
||||
{
|
||||
static NzString hashName = "Fletcher16";
|
||||
return hashName;
|
||||
}
|
||||
363
src/Nazara/Core/Hash/MD5.cpp
Normal file
363
src/Nazara/Core/Hash/MD5.cpp
Normal file
@@ -0,0 +1,363 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
/*
|
||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
|
||||
#include <Nazara/Core/Hash/MD5.hpp>
|
||||
#include <Nazara/Core/Endianness.hpp>
|
||||
#include <cstring>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
#define T_MASK (static_cast<nzUInt32>(~0))
|
||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||
#define T3 0x242070db
|
||||
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
||||
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
||||
#define T6 0x4787c62a
|
||||
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
||||
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
||||
#define T9 0x698098d8
|
||||
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
||||
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
||||
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
||||
#define T13 0x6b901122
|
||||
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
||||
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
||||
#define T16 0x49b40821
|
||||
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
||||
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
||||
#define T19 0x265e5a51
|
||||
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
||||
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
||||
#define T22 0x02441453
|
||||
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
||||
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
||||
#define T25 0x21e1cde6
|
||||
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
||||
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
||||
#define T28 0x455a14ed
|
||||
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
||||
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
||||
#define T31 0x676f02d9
|
||||
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
||||
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
||||
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
||||
#define T35 0x6d9d6122
|
||||
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
||||
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
||||
#define T38 0x4bdecfa9
|
||||
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
||||
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
||||
#define T41 0x289b7ec6
|
||||
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
||||
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
||||
#define T44 0x04881d05
|
||||
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
||||
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
||||
#define T47 0x1fa27cf8
|
||||
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
||||
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
||||
#define T50 0x432aff97
|
||||
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
||||
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
||||
#define T53 0x655b59c3
|
||||
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
||||
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
||||
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
||||
#define T57 0x6fa87e4f
|
||||
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
||||
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
||||
#define T60 0x4e0811a1
|
||||
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
||||
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
||||
#define T63 0x2ad7d2bb
|
||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||
|
||||
struct NzHashMD5_state
|
||||
{
|
||||
nzUInt32 count[2]; /* message length in bits, lsw first */
|
||||
nzUInt32 abcd[4]; /* digest buffer */
|
||||
nzUInt8 buf[64]; /* accumulate block */
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
void md5_process(NzHashMD5_state* state, const nzUInt8* data)
|
||||
{
|
||||
nzUInt32 a = state->abcd[0];
|
||||
nzUInt32 b = state->abcd[1];
|
||||
nzUInt32 c = state->abcd[2];
|
||||
nzUInt32 d = state->abcd[3];
|
||||
nzUInt32 t;
|
||||
|
||||
#ifdef NAZARA_ENDIANNESS_BIGENDIAN
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
nzUInt32 X[16];
|
||||
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const nzUInt8* xp = data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
nzUInt32 xbuf[16];
|
||||
const nzUInt32* X;
|
||||
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - reinterpret_cast<const nzUInt8*>(0)) & 3))
|
||||
{
|
||||
/* data are properly aligned */
|
||||
X = reinterpret_cast<const nzUInt32*>(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not aligned */
|
||||
std::memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
state->abcd[0] += a;
|
||||
state->abcd[1] += b;
|
||||
state->abcd[2] += c;
|
||||
state->abcd[3] += d;
|
||||
}
|
||||
}
|
||||
|
||||
NzHashMD5::NzHashMD5()
|
||||
{
|
||||
m_state = new NzHashMD5_state;
|
||||
}
|
||||
|
||||
NzHashMD5::~NzHashMD5()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashMD5::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
const nzUInt8 *p = data;
|
||||
int left = len;
|
||||
int offset = (m_state->count[0] >> 3) & 63;
|
||||
nzUInt32 nbits = len << 3;
|
||||
|
||||
if (len <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
m_state->count[1] += len >> 29;
|
||||
m_state->count[0] += nbits;
|
||||
if (m_state->count[0] < nbits)
|
||||
m_state->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset)
|
||||
{
|
||||
int copy = (offset + len > 64 ? 64 - offset : len);
|
||||
|
||||
std::memcpy(m_state->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(m_state, m_state->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
md5_process(m_state, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
std::memcpy(m_state->buf, p, left);
|
||||
}
|
||||
|
||||
void NzHashMD5::Begin()
|
||||
{
|
||||
m_state->count[0] = m_state->count[1] = 0;
|
||||
m_state->abcd[0] = 0x67452301;
|
||||
m_state->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
m_state->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
m_state->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
NzHashDigest NzHashMD5::End()
|
||||
{
|
||||
static const unsigned char pad[64] = {
|
||||
0x80, 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, 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
|
||||
};
|
||||
|
||||
nzUInt8 data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = static_cast<nzUInt8>(m_state->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
Append(pad, ((55 - (m_state->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
Append(data, 8);
|
||||
|
||||
nzUInt8 digest[16];
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = static_cast<nzUInt8>(m_state->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
|
||||
return NzHashDigest(GetHashName(), &digest[0], 16);
|
||||
}
|
||||
|
||||
unsigned int NzHashMD5::GetDigestLength()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
NzString NzHashMD5::GetHashName()
|
||||
{
|
||||
static NzString hashName = "MD5";
|
||||
return hashName;
|
||||
}
|
||||
|
||||
1025
src/Nazara/Core/Hash/Whirlpool.cpp
Normal file
1025
src/Nazara/Core/Hash/Whirlpool.cpp
Normal file
File diff suppressed because it is too large
Load Diff
189
src/Nazara/Core/HashDigest.cpp
Normal file
189
src/Nazara/Core/HashDigest.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_HASHDIGEST_CPP
|
||||
|
||||
#include <Nazara/Core/HashDigest.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHashDigest::NzHashDigest() :
|
||||
m_digest(nullptr),
|
||||
m_digestLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
NzHashDigest::NzHashDigest(NzString hashName, const nzUInt8* digest, unsigned int length) :
|
||||
m_hashName(hashName),
|
||||
m_digestLength(length)
|
||||
{
|
||||
if (m_digestLength > 0)
|
||||
{
|
||||
m_digest = new nzUInt8[length];
|
||||
std::memcpy(m_digest, digest, length);
|
||||
}
|
||||
else
|
||||
m_digest = nullptr;
|
||||
}
|
||||
|
||||
NzHashDigest::NzHashDigest(const NzHashDigest& rhs) :
|
||||
m_hashName(rhs.m_hashName),
|
||||
m_digestLength(rhs.m_digestLength)
|
||||
{
|
||||
if (m_digestLength > 0)
|
||||
{
|
||||
m_digest = new nzUInt8[m_digestLength];
|
||||
std::memcpy(m_digest, rhs.m_digest, m_digestLength);
|
||||
}
|
||||
else
|
||||
m_digest = nullptr;
|
||||
}
|
||||
|
||||
NzHashDigest::NzHashDigest(NzHashDigest&& rhs) :
|
||||
m_hashName(std::move(rhs.m_hashName)),
|
||||
m_digest(rhs.m_digest),
|
||||
m_digestLength(rhs.m_digestLength)
|
||||
{
|
||||
rhs.m_digest = nullptr;
|
||||
rhs.m_digestLength = 0;
|
||||
}
|
||||
|
||||
NzHashDigest::~NzHashDigest()
|
||||
{
|
||||
delete[] m_digest;
|
||||
}
|
||||
|
||||
bool NzHashDigest::IsValid() const
|
||||
{
|
||||
return m_digestLength > 0;
|
||||
}
|
||||
|
||||
const nzUInt8* NzHashDigest::GetDigest() const
|
||||
{
|
||||
return m_digest;
|
||||
}
|
||||
|
||||
unsigned int NzHashDigest::GetDigestLength() const
|
||||
{
|
||||
return m_digestLength;
|
||||
}
|
||||
|
||||
NzString NzHashDigest::GetHashName() const
|
||||
{
|
||||
return m_hashName;
|
||||
}
|
||||
|
||||
NzString NzHashDigest::ToHex() const
|
||||
{
|
||||
if (m_digestLength == 0)
|
||||
return NzString();
|
||||
|
||||
unsigned int length = m_digestLength*2;
|
||||
char* hex_output = new char[length+1];
|
||||
for (unsigned int i = 0; i < m_digestLength; ++i)
|
||||
std::sprintf(hex_output + i*2, "%02x", m_digest[i]);
|
||||
|
||||
return NzString(new NzString::SharedString(length, length, 1, hex_output));
|
||||
}
|
||||
|
||||
nzUInt8 NzHashDigest::operator[](unsigned short pos) const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (pos >= m_digestLength)
|
||||
{
|
||||
NazaraError("Position out of range");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_digest[pos];
|
||||
}
|
||||
|
||||
NzHashDigest& NzHashDigest::operator=(const NzHashDigest& rhs)
|
||||
{
|
||||
m_hashName = rhs.m_hashName;
|
||||
|
||||
m_digestLength = rhs.m_digestLength;
|
||||
if (m_digestLength > 0)
|
||||
{
|
||||
m_digest = new nzUInt8[m_digestLength];
|
||||
std::memcpy(m_digest, rhs.m_digest, m_digestLength);
|
||||
}
|
||||
else
|
||||
m_digest = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzHashDigest& NzHashDigest::operator=(NzHashDigest&& rhs)
|
||||
{
|
||||
std::swap(m_hashName, rhs.m_hashName);
|
||||
std::swap(m_digest, rhs.m_digest);
|
||||
std::swap(m_digestLength, rhs.m_digestLength);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator==(const NzHashDigest& rhs) const
|
||||
{
|
||||
if (m_digest == nullptr || rhs.m_digest == nullptr)
|
||||
return m_digest == rhs.m_digest;
|
||||
|
||||
if (m_digestLength != rhs.m_digestLength)
|
||||
return false;
|
||||
|
||||
return m_hashName == rhs.m_hashName && std::memcmp(m_digest, rhs.m_digest, m_digestLength) == 0;
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator!=(const NzHashDigest& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator<(const NzHashDigest& rhs) const
|
||||
{
|
||||
if (rhs.m_digest == nullptr)
|
||||
return false;
|
||||
|
||||
if (m_digest == nullptr)
|
||||
return true;
|
||||
|
||||
int cmp = NzString::Compare(m_hashName, rhs.m_hashName);
|
||||
if (cmp == 0)
|
||||
{
|
||||
cmp = std::memcmp(m_digest, rhs.m_digest, std::min(m_digestLength, rhs.m_digestLength));
|
||||
|
||||
if (cmp == 0)
|
||||
return m_digestLength < rhs.m_digestLength;
|
||||
else
|
||||
return cmp < 0;
|
||||
}
|
||||
else
|
||||
return cmp < 0;
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator<=(const NzHashDigest& rhs) const
|
||||
{
|
||||
return !rhs.operator<(*this);
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator>(const NzHashDigest& rhs) const
|
||||
{
|
||||
return rhs.operator<(*this);
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator>=(const NzHashDigest& rhs) const
|
||||
{
|
||||
return !operator<(rhs);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const NzHashDigest& hashstring)
|
||||
{
|
||||
out << hashstring.ToHex();
|
||||
return out;
|
||||
}
|
||||
21
src/Nazara/Core/Hashable.cpp
Normal file
21
src/Nazara/Core/Hashable.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_HASHABLE_CPP
|
||||
|
||||
#include <Nazara/Core/Hashable.hpp>
|
||||
#include <Nazara/Core/Hash.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHashDigest NzHashable::GetHash(nzHash hash) const
|
||||
{
|
||||
NzHash h(hash);
|
||||
return h.Hash(*this);
|
||||
}
|
||||
|
||||
NzHashDigest NzHashable::GetHash(NzHashImpl* impl) const
|
||||
{
|
||||
NzHash h(impl);
|
||||
return h.Hash(*this);
|
||||
}
|
||||
20
src/Nazara/Core/Lock.cpp
Normal file
20
src/Nazara/Core/Lock.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_LOCK_CPP
|
||||
|
||||
#include <Nazara/Core/Lock.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzLock::NzLock(NzMutex& mutex) :
|
||||
m_mutex(mutex)
|
||||
{
|
||||
m_mutex.Lock();
|
||||
}
|
||||
|
||||
NzLock::~NzLock()
|
||||
{
|
||||
m_mutex.Unlock();
|
||||
}
|
||||
161
src/Nazara/Core/Log.cpp
Normal file
161
src/Nazara/Core/Log.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_LOG_CPP
|
||||
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <Nazara/Math/Basic.hpp>
|
||||
#include <ctime>
|
||||
|
||||
#if NAZARA_CORE_REDIRECT_TO_CERR_ON_LOG_FAILURE
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/ThreadSafety.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
NzString errorType[] = {
|
||||
"Assert failed: ", // nzErrorType_AssertFailed
|
||||
"Internal error: ", // nzErrorType_Internal
|
||||
"Error: ", // nzErrorType_Normal
|
||||
"Warning: " // nzErrorType_Warning
|
||||
};
|
||||
}
|
||||
|
||||
NzLog::NzLog() :
|
||||
m_filePath("NazaraLog.log"),
|
||||
m_file(nullptr),
|
||||
m_append(false),
|
||||
m_enabled(true),
|
||||
m_writeTime(true)
|
||||
{
|
||||
}
|
||||
|
||||
NzLog::~NzLog()
|
||||
{
|
||||
delete m_file;
|
||||
}
|
||||
|
||||
void NzLog::Enable(bool enable)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_enabled == enable)
|
||||
return;
|
||||
|
||||
m_enabled = enable;
|
||||
if (!m_enabled && m_file)
|
||||
{
|
||||
delete m_file;
|
||||
m_file = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NzLog::EnableAppend(bool enable)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_append = enable;
|
||||
if (!m_append && m_file)
|
||||
{
|
||||
m_file->Delete();
|
||||
m_file = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NzLog::EnableDateTime(bool enable)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_writeTime = enable;
|
||||
}
|
||||
|
||||
NzString NzLog::GetFile() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_file)
|
||||
return m_file->GetFilePath();
|
||||
else
|
||||
return NzString();
|
||||
}
|
||||
|
||||
bool NzLog::IsEnabled() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void NzLog::SetFile(const NzString& filePath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_filePath = filePath;
|
||||
if (m_file)
|
||||
m_file->SetFile(filePath);
|
||||
}
|
||||
|
||||
void NzLog::Write(const NzString& string)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
if (!m_file)
|
||||
m_file = new NzFile(m_filePath, NzFile::Text | NzFile::WriteOnly | ((m_append) ? NzFile::Append : NzFile::Truncate));
|
||||
|
||||
NzString line;
|
||||
|
||||
if (m_writeTime)
|
||||
{
|
||||
line.Reserve(23 + string.GetSize() + 1);
|
||||
line.Resize(23);
|
||||
|
||||
time_t currentTime = std::time(nullptr);
|
||||
std::strftime(&line[0], 24, "%d/%m/%Y - %H:%M:%S: ", std::localtime(¤tTime));
|
||||
}
|
||||
else
|
||||
line.Reserve(string.GetSize() + 1);
|
||||
|
||||
line += string;
|
||||
line += '\n';
|
||||
|
||||
#if NAZARA_CORE_REDIRECT_TO_CERR_ON_LOG_FAILURE
|
||||
if (!m_file->IsOpen() || !m_file->Write(line))
|
||||
std::fputs(line.GetBuffer(), stderr);
|
||||
#else
|
||||
if (m_file->IsOpen())
|
||||
m_file->Write(line);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void NzLog::WriteError(nzErrorType type, const NzString& error, unsigned int line, const NzString& file, const NzString& func)
|
||||
{
|
||||
NzString stream;
|
||||
stream.Reserve(errorType[type].GetSize() + error.GetSize() + 2 + file.GetSize() + 1 + NzGetNumberLength(line) +2 + func.GetSize() + 1);
|
||||
stream += errorType[type];
|
||||
stream += error;
|
||||
stream += " (";
|
||||
stream += file;
|
||||
stream += ':';
|
||||
stream += line;
|
||||
stream += ": ";
|
||||
stream += func;
|
||||
stream += ')';
|
||||
/*NzStringStream stream;
|
||||
stream << errorType[type] << error << " (" << file << ':' << line << ": " << func << ')';*/
|
||||
Write(stream);
|
||||
}
|
||||
|
||||
NzLog* NzLog::Instance()
|
||||
{
|
||||
static NzLog log;
|
||||
return &log;
|
||||
}
|
||||
42
src/Nazara/Core/Mutex.cpp
Normal file
42
src/Nazara/Core/Mutex.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_MUTEX_CPP
|
||||
|
||||
#include <Nazara/Core/Mutex.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>
|
||||
|
||||
NzMutex::NzMutex()
|
||||
{
|
||||
m_impl = new NzMutexImpl;
|
||||
}
|
||||
|
||||
NzMutex::~NzMutex()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
void NzMutex::Lock()
|
||||
{
|
||||
m_impl->Lock();
|
||||
}
|
||||
|
||||
bool NzMutex::TryLock()
|
||||
{
|
||||
return m_impl->TryLock();
|
||||
}
|
||||
|
||||
void NzMutex::Unlock()
|
||||
{
|
||||
m_impl->Unlock();
|
||||
}
|
||||
47
src/Nazara/Core/Semaphore.cpp
Normal file
47
src/Nazara/Core/Semaphore.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_SEMAPHORE_CPP
|
||||
|
||||
#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>
|
||||
|
||||
NzSemaphore::NzSemaphore(unsigned int count)
|
||||
{
|
||||
m_impl = new NzSemaphoreImpl(count);
|
||||
}
|
||||
|
||||
NzSemaphore::~NzSemaphore()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
unsigned int NzSemaphore::GetCount() const
|
||||
{
|
||||
return m_impl->GetCount();
|
||||
}
|
||||
|
||||
void NzSemaphore::Post()
|
||||
{
|
||||
m_impl->Post();
|
||||
}
|
||||
|
||||
void NzSemaphore::Wait()
|
||||
{
|
||||
m_impl->Wait();
|
||||
}
|
||||
|
||||
bool NzSemaphore::Wait(nzUInt32 timeout)
|
||||
{
|
||||
return m_impl->Wait(timeout);
|
||||
}
|
||||
5113
src/Nazara/Core/String.cpp
Normal file
5113
src/Nazara/Core/String.cpp
Normal file
File diff suppressed because it is too large
Load Diff
217
src/Nazara/Core/StringStream.cpp
Normal file
217
src/Nazara/Core/StringStream.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_STRINGSTREAM_CPP
|
||||
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzStringStream::NzStringStream() :
|
||||
m_bufferSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
NzStringStream::NzStringStream(const NzString& str) :
|
||||
m_bufferSize(str.GetSize())
|
||||
{
|
||||
m_strings.push_back(str);
|
||||
}
|
||||
|
||||
NzString NzStringStream::ToString() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
NzString string;
|
||||
string.Reserve(m_bufferSize);
|
||||
|
||||
for (const NzString& str : m_strings)
|
||||
string += str;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(bool boolean)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Boolean(boolean));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(short number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned short number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(int number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned int number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(long number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned long number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(long long number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned long long number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(float number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(double number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(long double number)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(char character)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(character);
|
||||
m_bufferSize++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned char character)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(character);
|
||||
m_bufferSize++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(const char* string)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(string);
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(const std::string& string)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(string);
|
||||
m_bufferSize += string.size();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(const NzString& string)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(string);
|
||||
m_bufferSize += string.GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(const void* ptr)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_strings.push_back(NzString::Pointer(ptr));
|
||||
m_bufferSize += sizeof(void*)*2;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream::operator NzString() const
|
||||
{
|
||||
return ToString();
|
||||
}
|
||||
80
src/Nazara/Core/Thread.cpp
Normal file
80
src/Nazara/Core/Thread.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// Inspiré du code de la SFML par Laurent Gomila
|
||||
|
||||
#define NAZARA_THREAD_CPP
|
||||
|
||||
#include <Nazara/Core/Thread.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
|
||||
#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>
|
||||
|
||||
NzThread::~NzThread()
|
||||
{
|
||||
if (!m_independent)
|
||||
Join();
|
||||
else
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
NzThread::Id NzThread::GetId() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->GetId();
|
||||
else
|
||||
return NzThread::Id();
|
||||
}
|
||||
|
||||
bool NzThread::IsCurrent() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->IsCurrent();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void NzThread::Launch(bool independent)
|
||||
{
|
||||
Join();
|
||||
m_independent = independent;
|
||||
m_impl = new NzThreadImpl(this);
|
||||
}
|
||||
|
||||
void NzThread::Join()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (m_impl->IsCurrent())
|
||||
{
|
||||
NazaraError("A thread cannot join itself");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->Join();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NzThread::Terminate()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Terminate();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
48
src/Nazara/Core/ThreadCondition.cpp
Normal file
48
src/Nazara/Core/ThreadCondition.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_THREADCONDITION_CPP
|
||||
|
||||
#include <Nazara/Core/ThreadCondition.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/ThreadConditionImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/ThreadConditionImpl.hpp>
|
||||
#else
|
||||
#error Thread condition has no implementation
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzThreadCondition::NzThreadCondition()
|
||||
{
|
||||
m_impl = new NzThreadConditionImpl;
|
||||
}
|
||||
|
||||
NzThreadCondition::~NzThreadCondition()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
void NzThreadCondition::Signal()
|
||||
{
|
||||
m_impl->Signal();
|
||||
}
|
||||
|
||||
void NzThreadCondition::SignalAll()
|
||||
{
|
||||
m_impl->SignalAll();
|
||||
}
|
||||
|
||||
void NzThreadCondition::Wait(NzMutex* mutex)
|
||||
{
|
||||
m_impl->Wait(mutex->m_impl);
|
||||
}
|
||||
|
||||
bool NzThreadCondition::Wait(NzMutex* mutex, nzUInt32 timeout)
|
||||
{
|
||||
return m_impl->Wait(mutex->m_impl, timeout);
|
||||
}
|
||||
55
src/Nazara/Core/Unicode.cpp
Normal file
55
src/Nazara/Core/Unicode.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#define NAZARA_UNICODE_CPP
|
||||
|
||||
#include <Nazara/Core/Unicode.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace NzUnicode
|
||||
{
|
||||
#if NAZARA_CORE_INCLUDE_UNICODEDATA
|
||||
struct Character
|
||||
{
|
||||
nzUInt16 category; // Le type du caractère
|
||||
nzUInt8 direction; // Le sens de lecure du caractère
|
||||
nzUInt32 lowerCase; // Le caractère correspondant en minuscule
|
||||
nzUInt32 titleCase; // Le caractère correspondant en titre
|
||||
nzUInt32 upperCase; // Le caractère correspondant en majuscule
|
||||
};
|
||||
|
||||
#include <Nazara/Core/UnicodeData.hpp>
|
||||
|
||||
#else // Implémentation bidon
|
||||
|
||||
Category GetCategory(char32_t character)
|
||||
{
|
||||
NazaraUnused(character);
|
||||
|
||||
return Category_NoCategory;
|
||||
}
|
||||
|
||||
Direction GetDirection(char32_t character)
|
||||
{
|
||||
NazaraUnused(character);
|
||||
|
||||
return Direction_Boundary_Neutral;
|
||||
}
|
||||
|
||||
char32_t GetLowercase(char32_t character)
|
||||
{
|
||||
return character;
|
||||
}
|
||||
|
||||
char32_t GetTitlecase(char32_t character)
|
||||
{
|
||||
return character;
|
||||
}
|
||||
|
||||
char32_t GetUppercase(char32_t character)
|
||||
{
|
||||
return character;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
42
src/Nazara/Core/Win32/ClockImpl.cpp
Normal file
42
src/Nazara/Core/Win32/ClockImpl.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Win32/ClockImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <ctime>
|
||||
#include <windows.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
LARGE_INTEGER frequency; // La fréquence ne varie pas pas au cours de l'exécution
|
||||
}
|
||||
|
||||
bool NzClockImplInitializeHighPrecision()
|
||||
{
|
||||
return QueryPerformanceFrequency(&frequency) != 0;
|
||||
}
|
||||
|
||||
nzUInt64 NzClockImplGetMicroseconds()
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx
|
||||
HANDLE thread = GetCurrentThread();
|
||||
DWORD oldMask = SetThreadAffinityMask(thread, 1);
|
||||
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
|
||||
SetThreadAffinityMask(thread, oldMask);
|
||||
|
||||
return time.QuadPart * 1000000ULL / frequency.QuadPart;
|
||||
}
|
||||
|
||||
nzUInt64 NzClockImplGetMilliseconds()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS_VISTA
|
||||
return GetTickCount64();
|
||||
#else
|
||||
return GetTickCount();
|
||||
#endif
|
||||
}
|
||||
16
src/Nazara/Core/Win32/ClockImpl.hpp
Normal file
16
src/Nazara/Core/Win32/ClockImpl.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_CLOCKIMPL_WINDOWS_HPP
|
||||
#define NAZARA_CLOCKIMPL_WINDOWS_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
|
||||
bool NzClockImplInitializeHighPrecision();
|
||||
nzUInt64 NzClockImplGetMicroseconds();
|
||||
nzUInt64 NzClockImplGetMilliseconds();
|
||||
|
||||
#endif // NAZARA_CLOCKIMPL_WINDOWS_HPP
|
||||
137
src/Nazara/Core/Win32/DirectoryImpl.cpp
Normal file
137
src/Nazara/Core/Win32/DirectoryImpl.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Win32/DirectoryImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzDirectoryImpl::NzDirectoryImpl(const NzDirectory* parent)
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
NzDirectoryImpl::~NzDirectoryImpl()
|
||||
{
|
||||
}
|
||||
|
||||
void NzDirectoryImpl::Close()
|
||||
{
|
||||
FindClose(m_handle);
|
||||
}
|
||||
|
||||
NzString NzDirectoryImpl::GetResultName() const
|
||||
{
|
||||
return NzString::Unicode(m_result.cFileName);
|
||||
}
|
||||
|
||||
nzUInt64 NzDirectoryImpl::GetResultSize() const
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
size.HighPart = m_result.nFileSizeHigh;
|
||||
size.LowPart = m_result.nFileSizeLow;
|
||||
|
||||
return size.QuadPart;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::IsResultDirectory() const
|
||||
{
|
||||
if (m_result.dwFileAttributes != INVALID_FILE_ATTRIBUTES)
|
||||
return (m_result.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::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: " + NzGetLastSystemError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Open(const NzString& dirPath)
|
||||
{
|
||||
NzString searchPath = dirPath + "\\*";
|
||||
wchar_t* path = searchPath.GetWideBuffer();
|
||||
m_handle = FindFirstFileW(path, &m_result);
|
||||
delete[] path;
|
||||
|
||||
if (m_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
NazaraError("Unable to open directory: " + NzGetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_firstCall = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Create(const NzString& dirPath)
|
||||
{
|
||||
wchar_t* path = dirPath.GetWideBuffer();
|
||||
bool success = CreateDirectoryW(path, nullptr) != 0;
|
||||
delete[] path;
|
||||
|
||||
return success || GetLastError() == ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Exists(const NzString& dirPath)
|
||||
{
|
||||
wchar_t* path = dirPath.GetWideBuffer();
|
||||
DWORD attributes = GetFileAttributesW(path);
|
||||
delete[] path;
|
||||
|
||||
if (attributes != INVALID_FILE_ATTRIBUTES)
|
||||
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
NzString NzDirectoryImpl::GetCurrent()
|
||||
{
|
||||
NzString currentPath;
|
||||
wchar_t* path = new wchar_t[MAX_PATH];
|
||||
|
||||
unsigned int size = GetCurrentDirectoryW(MAX_PATH, path);
|
||||
if (size > MAX_PATH) // La taille prends en compte le caractère nul
|
||||
{
|
||||
delete[] path;
|
||||
|
||||
path = new wchar_t[size];
|
||||
if (GetCurrentDirectoryW(size, path) == 0)
|
||||
NazaraError("Unable to get current directory: " + NzGetLastSystemError());
|
||||
else
|
||||
currentPath = NzString::Unicode(path);
|
||||
}
|
||||
else if (size == 0)
|
||||
NazaraError("Unable to get current directory: " + NzGetLastSystemError());
|
||||
else
|
||||
currentPath = NzString::Unicode(path);
|
||||
|
||||
delete[] path;
|
||||
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Remove(const NzString& dirPath)
|
||||
{
|
||||
wchar_t* path = dirPath.GetWideBuffer();
|
||||
bool success = RemoveDirectoryW(path) != 0;
|
||||
delete[] path;
|
||||
|
||||
DWORD error = GetLastError();
|
||||
return success || error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
45
src/Nazara/Core/Win32/DirectoryImpl.hpp
Normal file
45
src/Nazara/Core/Win32/DirectoryImpl.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_DIRECTORYIMPL_HPP
|
||||
#define NAZARA_DIRECTORYIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Utility/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzDirectory;
|
||||
class NzString;
|
||||
|
||||
class NzDirectoryImpl : NzNonCopyable
|
||||
{
|
||||
public:
|
||||
NzDirectoryImpl(const NzDirectory* parent);
|
||||
~NzDirectoryImpl();
|
||||
|
||||
void Close();
|
||||
|
||||
NzString GetResultName() const;
|
||||
nzUInt64 GetResultSize() const;
|
||||
|
||||
bool IsResultDirectory() const;
|
||||
|
||||
bool NextResult();
|
||||
|
||||
bool Open(const NzString& dirPath);
|
||||
|
||||
static bool Create(const NzString& dirPath);
|
||||
static bool Exists(const NzString& dirPath);
|
||||
static NzString GetCurrent();
|
||||
static bool Remove(const NzString& dirPath);
|
||||
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
WIN32_FIND_DATAW m_result;
|
||||
bool m_firstCall;
|
||||
};
|
||||
|
||||
#endif // NAZARA_DIRECTORYIMPL_HPP
|
||||
51
src/Nazara/Core/Win32/DynLibImpl.cpp
Normal file
51
src/Nazara/Core/Win32/DynLibImpl.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Win32/DynLibImpl.hpp>
|
||||
#include <Nazara/Core/DynLib.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzDynLibImpl::NzDynLibImpl(NzDynLib* parent) :
|
||||
m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
NzDynLibImpl::~NzDynLibImpl()
|
||||
{
|
||||
}
|
||||
|
||||
NzDynLibFunc NzDynLibImpl::GetSymbol(const NzString& symbol) const
|
||||
{
|
||||
NzDynLibFunc sym = reinterpret_cast<NzDynLibFunc>(GetProcAddress(m_handle, symbol.GetConstBuffer()));
|
||||
if (!sym)
|
||||
m_parent->SetLastError(NzGetLastSystemError());
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
bool NzDynLibImpl::Load(const NzString& libraryPath)
|
||||
{
|
||||
NzString path = libraryPath;
|
||||
if (!path.EndsWith(".dll"))
|
||||
path += ".dll";
|
||||
|
||||
wchar_t* pathW = path.GetWideBuffer();
|
||||
m_handle = LoadLibraryExW(pathW, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
delete[] pathW;
|
||||
|
||||
if (m_handle)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
m_parent->SetLastError(NzGetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void NzDynLibImpl::Unload()
|
||||
{
|
||||
FreeLibrary(m_handle);
|
||||
}
|
||||
31
src/Nazara/Core/Win32/DynLibImpl.hpp
Normal file
31
src/Nazara/Core/Win32/DynLibImpl.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_DYNLIBIMPL_HPP
|
||||
#define NAZARA_DYNLIBIMPL_HPP
|
||||
|
||||
#include <Nazara/Core/DynLib.hpp>
|
||||
#include <Nazara/Utility/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzString;
|
||||
|
||||
class NzDynLibImpl : NzNonCopyable
|
||||
{
|
||||
public:
|
||||
NzDynLibImpl(NzDynLib* m_parent);
|
||||
~NzDynLibImpl();
|
||||
|
||||
NzDynLibFunc GetSymbol(const NzString& symbol) const;
|
||||
bool Load(const NzString& libraryPath);
|
||||
void Unload();
|
||||
|
||||
private:
|
||||
HMODULE m_handle;
|
||||
NzDynLib* m_parent;
|
||||
};
|
||||
|
||||
#endif // NAZARA_DYNLIBIMPL_HPP
|
||||
309
src/Nazara/Core/Win32/FileImpl.cpp
Normal file
309
src/Nazara/Core/Win32/FileImpl.cpp
Normal file
@@ -0,0 +1,309 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Win32/FileImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Win32/Time.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzFileImpl::NzFileImpl(const NzFile* parent) :
|
||||
m_endOfFile(false)
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
NzFileImpl::~NzFileImpl()
|
||||
{
|
||||
}
|
||||
|
||||
void NzFileImpl::Close()
|
||||
{
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
bool NzFileImpl::EndOfFile() const
|
||||
{
|
||||
return m_endOfFile;
|
||||
}
|
||||
|
||||
void NzFileImpl::Flush()
|
||||
{
|
||||
if (!FlushFileBuffers(m_handle))
|
||||
NazaraError("Unable to flush file: " + NzGetLastSystemError());
|
||||
}
|
||||
|
||||
nzUInt64 NzFileImpl::GetCursorPos() const
|
||||
{
|
||||
LARGE_INTEGER zero;
|
||||
zero.QuadPart = 0;
|
||||
|
||||
LARGE_INTEGER position;
|
||||
SetFilePointerEx(m_handle, zero, &position, FILE_CURRENT);
|
||||
|
||||
return position.QuadPart;
|
||||
}
|
||||
|
||||
bool NzFileImpl::Open(const NzString& filePath, unsigned int mode)
|
||||
{
|
||||
DWORD access;
|
||||
DWORD shareMode = FILE_SHARE_READ;
|
||||
DWORD openMode;
|
||||
if (mode & NzFile::ReadOnly)
|
||||
{
|
||||
access = GENERIC_READ;
|
||||
openMode = OPEN_EXISTING;
|
||||
}
|
||||
else if (mode & NzFile::ReadWrite)
|
||||
{
|
||||
if (mode & NzFile::Append)
|
||||
access = FILE_APPEND_DATA;
|
||||
else
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
|
||||
if (mode & NzFile::Truncate)
|
||||
openMode = CREATE_ALWAYS;
|
||||
else
|
||||
openMode = OPEN_ALWAYS;
|
||||
}
|
||||
else if (mode & NzFile::WriteOnly)
|
||||
{
|
||||
if (mode & NzFile::Append)
|
||||
access = FILE_APPEND_DATA;
|
||||
else
|
||||
access = GENERIC_WRITE;
|
||||
|
||||
if (mode & NzFile::Truncate)
|
||||
openMode = CREATE_ALWAYS;
|
||||
else
|
||||
openMode = OPEN_ALWAYS;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if ((mode & NzFile::Lock) == 0)
|
||||
shareMode |= FILE_SHARE_WRITE;
|
||||
|
||||
wchar_t* path = filePath.GetWideBuffer();
|
||||
m_handle = CreateFileW(path, access, shareMode, nullptr, openMode, 0, nullptr);
|
||||
delete[] path;
|
||||
|
||||
return m_handle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
std::size_t NzFileImpl::Read(void* buffer, std::size_t size)
|
||||
{
|
||||
DWORD read = 0;
|
||||
if (ReadFile(m_handle, buffer, size, &read, nullptr))
|
||||
{
|
||||
m_endOfFile = (size != read);
|
||||
return read;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NzFileImpl::SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset)
|
||||
{
|
||||
DWORD moveMethod;
|
||||
switch (pos)
|
||||
{
|
||||
case NzFile::AtBegin:
|
||||
moveMethod = FILE_BEGIN;
|
||||
break;
|
||||
|
||||
case NzFile::AtCurrent:
|
||||
moveMethod = FILE_CURRENT;
|
||||
break;
|
||||
|
||||
case NzFile::AtEnd:
|
||||
moveMethod = FILE_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraInternalError("Cursor position not handled (0x" + NzString::Number(pos, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
m_endOfFile = false;
|
||||
|
||||
LARGE_INTEGER distance;
|
||||
distance.QuadPart = offset;
|
||||
|
||||
return SetFilePointerEx(m_handle, distance, nullptr, moveMethod) != 0;
|
||||
}
|
||||
|
||||
std::size_t NzFileImpl::Write(const void* buffer, std::size_t size)
|
||||
{
|
||||
DWORD written = 0;
|
||||
|
||||
LARGE_INTEGER cursorPos;
|
||||
cursorPos.QuadPart = GetCursorPos();
|
||||
|
||||
LockFile(m_handle, cursorPos.LowPart, cursorPos.HighPart, size, 0);
|
||||
WriteFile(m_handle, buffer, size, &written, nullptr);
|
||||
UnlockFile(m_handle, cursorPos.LowPart, cursorPos.HighPart, size, 0);
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
bool NzFileImpl::Copy(const NzString& sourcePath, const NzString& targetPath)
|
||||
{
|
||||
wchar_t* path = sourcePath.GetWideBuffer();
|
||||
wchar_t* newPath = targetPath.GetWideBuffer();
|
||||
|
||||
if (CopyFileW(path, newPath, false))
|
||||
{
|
||||
delete[] path;
|
||||
delete[] newPath;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Unable to copy file: " + NzGetLastSystemError());
|
||||
delete[] path;
|
||||
delete[] newPath;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzFileImpl::Delete(const NzString& filePath)
|
||||
{
|
||||
wchar_t* path = filePath.GetWideBuffer();
|
||||
|
||||
if (DeleteFileW(path))
|
||||
{
|
||||
delete[] path;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Unable to delete file (" + filePath + "): " + NzGetLastSystemError());
|
||||
delete[] path;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzFileImpl::Exists(const NzString& filePath)
|
||||
{
|
||||
wchar_t* path = filePath.GetWideBuffer();
|
||||
HANDLE handle = CreateFileW(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
delete[] path;
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
CloseHandle(handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
time_t NzFileImpl::GetCreationTime(const NzString& filePath)
|
||||
{
|
||||
wchar_t* path = filePath.GetWideBuffer();
|
||||
HANDLE handle = CreateFileW(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
delete[] path;
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME creationTime;
|
||||
if (!GetFileTime(handle, &creationTime, nullptr, nullptr))
|
||||
{
|
||||
NazaraError("Unable to get creation time: " + NzGetLastSystemError());
|
||||
|
||||
CloseHandle(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
|
||||
return FileTimeToTime(&creationTime);
|
||||
}
|
||||
|
||||
time_t NzFileImpl::GetLastAccessTime(const NzString& filePath)
|
||||
{
|
||||
wchar_t* path = filePath.GetWideBuffer();
|
||||
HANDLE handle = CreateFileW(path, 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
delete[] path;
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME accessTime;
|
||||
if (!GetFileTime(handle, nullptr, &accessTime, nullptr))
|
||||
{
|
||||
NazaraError("Unable to get last access time: " + NzGetLastSystemError());
|
||||
|
||||
CloseHandle(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
|
||||
return FileTimeToTime(&accessTime);
|
||||
}
|
||||
|
||||
time_t NzFileImpl::GetLastWriteTime(const NzString& filePath)
|
||||
{
|
||||
wchar_t* path = filePath.GetWideBuffer();
|
||||
HANDLE handle = CreateFileW(path, 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
delete[] path;
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME writeTime;
|
||||
if (!GetFileTime(handle, nullptr, nullptr, &writeTime))
|
||||
{
|
||||
NazaraError("Unable to get last write time: " + NzGetLastSystemError());
|
||||
CloseHandle(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
|
||||
return FileTimeToTime(&writeTime);
|
||||
}
|
||||
|
||||
nzUInt64 NzFileImpl::GetSize(const NzString& filePath)
|
||||
{
|
||||
wchar_t* path = filePath.GetWideBuffer();
|
||||
HANDLE handle = CreateFileW(path, 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
delete[] path;
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(handle, &fileSize))
|
||||
fileSize.QuadPart = 0;
|
||||
|
||||
CloseHandle(handle);
|
||||
|
||||
return fileSize.QuadPart;
|
||||
}
|
||||
|
||||
bool NzFileImpl::Rename(const NzString& sourcePath, const NzString& targetPath)
|
||||
{
|
||||
wchar_t* path = sourcePath.GetWideBuffer();
|
||||
wchar_t* newPath = targetPath.GetWideBuffer();
|
||||
|
||||
bool success = MoveFileExW(path, newPath, MOVEFILE_COPY_ALLOWED) != 0;
|
||||
|
||||
delete[] path;
|
||||
delete[] newPath;
|
||||
|
||||
if (success)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Unable to rename file: " + NzGetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
48
src/Nazara/Core/Win32/FileImpl.hpp
Normal file
48
src/Nazara/Core/Win32/FileImpl.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_FILEIMPL_HPP
|
||||
#define NAZARA_FILEIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Utility/NonCopyable.hpp>
|
||||
#include <ctime>
|
||||
#include <windows.h>
|
||||
|
||||
class NzFile;
|
||||
class NzString;
|
||||
|
||||
class NzFileImpl : NzNonCopyable
|
||||
{
|
||||
public:
|
||||
NzFileImpl(const NzFile* parent);
|
||||
~NzFileImpl();
|
||||
|
||||
void Close();
|
||||
bool EndOfFile() const;
|
||||
void Flush();
|
||||
nzUInt64 GetCursorPos() const;
|
||||
bool Open(const NzString& filePath, unsigned int mode);
|
||||
std::size_t Read(void* buffer, std::size_t size);
|
||||
bool SetCursorPos(NzFile::CursorPosition pos, nzInt64 offset);
|
||||
std::size_t Write(const void* buffer, std::size_t size);
|
||||
|
||||
static bool Copy(const NzString& sourcePath, const NzString& targetPath);
|
||||
static bool Delete(const NzString& filePath);
|
||||
static bool Exists(const NzString& filePath);
|
||||
static time_t GetCreationTime(const NzString& filePath);
|
||||
static time_t GetLastAccessTime(const NzString& filePath);
|
||||
static time_t GetLastWriteTime(const NzString& filePath);
|
||||
static nzUInt64 GetSize(const NzString& filePath);
|
||||
static bool Rename(const NzString& sourcePath, const NzString& targetPath);
|
||||
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
bool m_endOfFile;
|
||||
};
|
||||
|
||||
#endif // NAZARA_FILEIMPL_HPP
|
||||
31
src/Nazara/Core/Win32/MutexImpl.cpp
Normal file
31
src/Nazara/Core/Win32/MutexImpl.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Win32/MutexImpl.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzMutexImpl::NzMutexImpl()
|
||||
{
|
||||
InitializeCriticalSection(&m_criticalSection);
|
||||
}
|
||||
|
||||
NzMutexImpl::~NzMutexImpl()
|
||||
{
|
||||
DeleteCriticalSection(&m_criticalSection);
|
||||
}
|
||||
|
||||
void NzMutexImpl::Lock()
|
||||
{
|
||||
EnterCriticalSection(&m_criticalSection);
|
||||
}
|
||||
|
||||
bool NzMutexImpl::TryLock()
|
||||
{
|
||||
return TryEnterCriticalSection(&m_criticalSection) != 0;
|
||||
}
|
||||
|
||||
void NzMutexImpl::Unlock()
|
||||
{
|
||||
LeaveCriticalSection(&m_criticalSection);
|
||||
}
|
||||
30
src/Nazara/Core/Win32/MutexImpl.hpp
Normal file
30
src/Nazara/Core/Win32/MutexImpl.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_MUTEXIMPL_HPP
|
||||
#define NAZARA_MUTEXIMPL_HPP
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
class NzThreadConditionImpl;
|
||||
|
||||
class NzMutexImpl
|
||||
{
|
||||
friend class NzThreadConditionImpl;
|
||||
|
||||
public:
|
||||
NzMutexImpl();
|
||||
~NzMutexImpl();
|
||||
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION m_criticalSection;
|
||||
};
|
||||
|
||||
#endif // NAZARA_MUTEXIMPL_HPP
|
||||
65
src/Nazara/Core/Win32/SemaphoreImpl.cpp
Normal file
65
src/Nazara/Core/Win32/SemaphoreImpl.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Core/Win32/SemaphoreImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <limits>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzSemaphoreImpl::NzSemaphoreImpl(unsigned int count)
|
||||
{
|
||||
m_semaphore = CreateSemaphore(nullptr, count, std::numeric_limits<LONG>::max(), nullptr);
|
||||
#if NAZARA_CORE_SAFE ///FIXME: Ne peut échouer qu'à cause de mauvais paramètres ?
|
||||
if (!m_semaphore)
|
||||
NazaraError("Failed to create semaphore: " + NzGetLastSystemError());
|
||||
#endif
|
||||
}
|
||||
|
||||
NzSemaphoreImpl::~NzSemaphoreImpl()
|
||||
{
|
||||
CloseHandle(m_semaphore);
|
||||
}
|
||||
|
||||
unsigned int NzSemaphoreImpl::GetCount() const
|
||||
{
|
||||
LONG count;
|
||||
ReleaseSemaphore(m_semaphore, 0, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void NzSemaphoreImpl::Post()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!ReleaseSemaphore(m_semaphore, 1, nullptr))
|
||||
NazaraError("Failed to release semaphore: " + NzGetLastSystemError());
|
||||
#else
|
||||
ReleaseSemaphore(m_semaphore, 1, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzSemaphoreImpl::Wait()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (WaitForSingleObject(m_semaphore, INFINITE) == WAIT_FAILED)
|
||||
NazaraError("Failed to wait for semaphore: " + NzGetLastSystemError());
|
||||
#else
|
||||
WaitForSingleObject(m_semaphore, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NzSemaphoreImpl::Wait(nzUInt32 timeout)
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
DWORD result = WaitForSingleObject(m_semaphore, timeout);
|
||||
if (result == WAIT_FAILED)
|
||||
{
|
||||
NazaraError("Failed to wait for semaphore: " + NzGetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return result == WAIT_OBJECT_0;
|
||||
#else
|
||||
return WaitForSingleObject(m_semaphore, timeout) == WAIT_OBJECT_0;
|
||||
#endif
|
||||
}
|
||||
28
src/Nazara/Core/Win32/SemaphoreImpl.hpp
Normal file
28
src/Nazara/Core/Win32/SemaphoreImpl.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SEMAPHOREIMPL_HPP
|
||||
#define NAZARA_SEMAPHOREIMPL_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzSemaphoreImpl
|
||||
{
|
||||
public:
|
||||
NzSemaphoreImpl(unsigned int count);
|
||||
~NzSemaphoreImpl();
|
||||
|
||||
unsigned int GetCount() const;
|
||||
void Post();
|
||||
void Wait();
|
||||
bool Wait(nzUInt32 timeout);
|
||||
|
||||
private:
|
||||
HANDLE m_semaphore;
|
||||
};
|
||||
|
||||
#endif // NAZARA_SEMAPHOREIMPL_HPP
|
||||
98
src/Nazara/Core/Win32/ThreadConditionImpl.cpp
Normal file
98
src/Nazara/Core/Win32/ThreadConditionImpl.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// 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/ThreadConditionImpl.hpp>
|
||||
#include <Nazara/Core/Win32/MutexImpl.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzThreadConditionImpl::NzThreadConditionImpl()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWSVISTA
|
||||
InitializeConditionVariable(&m_cv);
|
||||
#else
|
||||
m_count = 0;
|
||||
InitializeCriticalSection(&m_countLock);
|
||||
m_events[SIGNAL] = CreateEvent(nullptr, false, false, nullptr); // auto-reset event
|
||||
m_events[BROADCAST] = CreateEvent(nullptr, true, false, nullptr); // manual-reset event
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NAZARA_PLATFORM_WINDOWSVISTA
|
||||
NzThreadConditionImpl::~NzThreadConditionImpl()
|
||||
{
|
||||
DeleteCriticalSection(&m_countLock);
|
||||
}
|
||||
#endif
|
||||
|
||||
void NzThreadConditionImpl::Signal()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWSVISTA
|
||||
WakeConditionVariable(&m_cv);
|
||||
#else
|
||||
// Avoid race conditions.
|
||||
EnterCriticalSection(&m_countLock);
|
||||
bool haveWaiters = (m_count > 0);
|
||||
LeaveCriticalSection(&m_countLock);
|
||||
|
||||
if (haveWaiters)
|
||||
SetEvent(m_events[SIGNAL]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzThreadConditionImpl::SignalAll()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWSVISTA
|
||||
WakeAllConditionVariable(&m_cv);
|
||||
#else
|
||||
// Avoid race conditions.
|
||||
EnterCriticalSection(&m_countLock);
|
||||
bool haveWaiters = (m_count > 0);
|
||||
LeaveCriticalSection (&m_countLock);
|
||||
|
||||
if (haveWaiters)
|
||||
SetEvent(m_events[BROADCAST]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzThreadConditionImpl::Wait(NzMutexImpl* mutex)
|
||||
{
|
||||
Wait(mutex, INFINITE);
|
||||
}
|
||||
|
||||
bool NzThreadConditionImpl::Wait(NzMutexImpl* mutex, nzUInt32 timeout)
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWSVISTA
|
||||
return SleepConditionVariableCS(&m_cv, mutex->m_criticalSection, timeout);
|
||||
#else
|
||||
// Avoid race conditions.
|
||||
EnterCriticalSection(&m_countLock);
|
||||
m_count++;
|
||||
LeaveCriticalSection(&m_countLock);
|
||||
|
||||
// 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);
|
||||
|
||||
EnterCriticalSection(&m_countLock);
|
||||
m_count--;
|
||||
bool lastWaiter = (result == WAIT_OBJECT_0 + BROADCAST && m_count == 0);
|
||||
LeaveCriticalSection(&m_countLock);
|
||||
|
||||
// Some thread called SignalAll
|
||||
if (lastWaiter)
|
||||
// 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
|
||||
}
|
||||
51
src/Nazara/Core/Win32/ThreadConditionImpl.hpp
Normal file
51
src/Nazara/Core/Win32/ThreadConditionImpl.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_THREADCONDITIONIMPL_HPP
|
||||
#define NAZARA_THREADCONDITIONIMPL_HPP
|
||||
|
||||
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzMutexImpl;
|
||||
|
||||
class NzThreadConditionImpl
|
||||
{
|
||||
public:
|
||||
NzThreadConditionImpl();
|
||||
#ifdef NAZARA_PLATFORM_WINDOWSVISTA
|
||||
~NzThreadConditionImpl() = default;
|
||||
#else
|
||||
~NzThreadConditionImpl();
|
||||
#endif
|
||||
|
||||
void Signal();
|
||||
void SignalAll();
|
||||
|
||||
void Wait(NzMutexImpl* mutex);
|
||||
bool Wait(NzMutexImpl* mutex, nzUInt32 timeout);
|
||||
|
||||
private:
|
||||
#ifdef NAZARA_PLATFORM_WINDOWSVISTA
|
||||
CONDITION_VARIABLE m_cv;
|
||||
#else
|
||||
enum
|
||||
{
|
||||
SIGNAL = 0,
|
||||
BROADCAST = 1,
|
||||
MAX_EVENTS = 2
|
||||
};
|
||||
|
||||
CRITICAL_SECTION m_countLock;
|
||||
HANDLE m_events[MAX_EVENTS];
|
||||
unsigned int m_count;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // NAZARA_THREADCONDITIONIMPL_HPP
|
||||
94
src/Nazara/Core/Win32/ThreadImpl.cpp
Normal file
94
src/Nazara/Core/Win32/ThreadImpl.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// Inspiré du code de la SFML par Laurent Gomila
|
||||
|
||||
#include <Nazara/Core/Win32/ThreadImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Utility/Functor.hpp>
|
||||
#include <process.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzThread::Id::Id(const NzThreadImpl* thread)
|
||||
{
|
||||
if (thread->m_thread)
|
||||
m_handle = reinterpret_cast<void*>(thread->m_threadId); // Un entier transformé en pointeur : Hacky
|
||||
else
|
||||
m_handle = nullptr;
|
||||
}
|
||||
|
||||
NzThread::Id::~Id()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzThread::Id::operator==(const Id& rhs) const
|
||||
{
|
||||
return m_handle == rhs.m_handle;
|
||||
}
|
||||
|
||||
bool NzThread::Id::operator!=(const Id& rhs) const
|
||||
{
|
||||
return m_handle != rhs.m_handle;
|
||||
}
|
||||
|
||||
NzThreadImpl::NzThreadImpl(NzThread* thread)
|
||||
{
|
||||
m_thread = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, &NzThreadImpl::ThreadProc, thread, 0, &m_threadId));
|
||||
if (!m_thread)
|
||||
NazaraError("Failed to create thread: " + NzGetLastSystemError());
|
||||
}
|
||||
|
||||
NzThreadImpl::~NzThreadImpl()
|
||||
{
|
||||
}
|
||||
|
||||
NzThread::Id NzThreadImpl::GetId() const
|
||||
{
|
||||
return NzThread::Id(reinterpret_cast<void*>(m_threadId)); // Hacky
|
||||
}
|
||||
|
||||
bool NzThreadImpl::IsCurrent() const
|
||||
{
|
||||
return m_threadId == GetCurrentThreadId();
|
||||
}
|
||||
|
||||
void NzThreadImpl::Join()
|
||||
{
|
||||
if (m_thread)
|
||||
WaitForSingleObject(m_thread, INFINITE);
|
||||
}
|
||||
|
||||
void NzThreadImpl::Terminate()
|
||||
{
|
||||
if (m_thread)
|
||||
TerminateThread(m_thread, 0);
|
||||
}
|
||||
|
||||
unsigned int _stdcall NzThreadImpl::ThreadProc(void* userdata)
|
||||
{
|
||||
NzThread* owner = static_cast<NzThread*>(userdata);
|
||||
NzFunctor* func = owner->m_func;
|
||||
HANDLE myHandle = owner->m_impl->m_thread;
|
||||
func->Run();
|
||||
delete func;
|
||||
|
||||
// http://stackoverflow.com/questions/418742/is-it-reasonable-to-call-closehandle-on-a-thread-before-it-terminates
|
||||
CloseHandle(myHandle);
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
NzThread::Id NzThread::GetCurrentId()
|
||||
{
|
||||
return NzThread::Id(reinterpret_cast<void*>(GetCurrentThreadId())); // Hacky
|
||||
}
|
||||
|
||||
void NzThread::Sleep(nzUInt32 time)
|
||||
{
|
||||
::Sleep(time);
|
||||
}
|
||||
38
src/Nazara/Core/Win32/ThreadImpl.hpp
Normal file
38
src/Nazara/Core/Win32/ThreadImpl.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// 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/Prerequesites.hpp>
|
||||
#include <Nazara/Core/Thread.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzThread;
|
||||
|
||||
class NzThreadImpl
|
||||
{
|
||||
friend class NzThread::Id;
|
||||
|
||||
public:
|
||||
NzThreadImpl(NzThread* threadFunc);
|
||||
~NzThreadImpl();
|
||||
|
||||
NzThread::Id GetId() const;
|
||||
bool IsCurrent() const;
|
||||
void Join();
|
||||
void Terminate();
|
||||
|
||||
private:
|
||||
static unsigned int _stdcall ThreadProc(void* userdata);
|
||||
|
||||
HANDLE m_thread;
|
||||
unsigned int m_threadId;
|
||||
};
|
||||
|
||||
#endif // NAZARA_THREADIMPL_HPP
|
||||
32
src/Nazara/Core/Win32/Time.hpp
Normal file
32
src/Nazara/Core/Win32/Time.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_WINDOWS_TIME_HPP
|
||||
#define NAZARA_WINDOWS_TIME_HPP
|
||||
|
||||
#include <ctime>
|
||||
#include <windows.h>
|
||||
|
||||
time_t FileTimeToTime(FILETIME* time)
|
||||
{
|
||||
SYSTEMTIME stUTC, stLocal;
|
||||
|
||||
FileTimeToSystemTime(time, &stUTC);
|
||||
SystemTimeToTzSpecificLocalTime(nullptr, &stUTC, &stLocal);
|
||||
|
||||
std::tm timeinfo;
|
||||
timeinfo.tm_sec = stLocal.wSecond;
|
||||
timeinfo.tm_min = stLocal.wMinute;
|
||||
timeinfo.tm_hour = stLocal.wHour;
|
||||
timeinfo.tm_mday = stLocal.wDay;
|
||||
timeinfo.tm_mon = stLocal.wMonth-1;
|
||||
timeinfo.tm_year = stLocal.wYear-1900;
|
||||
timeinfo.tm_isdst = -1;
|
||||
|
||||
return std::mktime(&timeinfo);
|
||||
}
|
||||
|
||||
#endif // NAZARA_WINDOWS_TIME_HPP
|
||||
29
src/Nazara/Network/Debug/Leaks.cpp
Normal file
29
src/Nazara/Network/Debug/Leaks.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Network/Config.hpp>
|
||||
#if NAZARA_NETWORK_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
|
||||
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
|
||||
#include <new>
|
||||
|
||||
void* operator new(std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, true);
|
||||
}
|
||||
|
||||
void operator delete(void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, true);
|
||||
}
|
||||
#endif
|
||||
196
src/Nazara/Renderer/Buffer.cpp
Normal file
196
src/Nazara/Renderer/Buffer.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Buffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/HardwareBuffer.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/SoftwareBuffer.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzBuffer::NzBuffer(nzBufferType type) :
|
||||
m_type(type),
|
||||
m_typeSize(0),
|
||||
m_impl(nullptr),
|
||||
m_length(0)
|
||||
{
|
||||
}
|
||||
|
||||
NzBuffer::NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) :
|
||||
m_type(type),
|
||||
m_impl(nullptr)
|
||||
{
|
||||
Create(length, typeSize, usage);
|
||||
|
||||
#if NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Failed to create buffer");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NzBuffer::~NzBuffer()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool NzBuffer::CopyContent(NzBuffer& buffer)
|
||||
{
|
||||
void* ptr = buffer.Lock(nzBufferLock_ReadOnly);
|
||||
if (!ptr)
|
||||
{
|
||||
NazaraError("Unable to lock buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool r = Fill(ptr, 0, m_length);
|
||||
|
||||
if (!buffer.Unlock())
|
||||
NazaraWarning("Unable to unlock buffer");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
// On tente d'abord de faire un buffer hardware, si supporté
|
||||
if (NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer))
|
||||
{
|
||||
m_impl = new NzHardwareBuffer(this, m_type);
|
||||
if (!m_impl->Create(length, typeSize, usage))
|
||||
{
|
||||
NazaraWarning("Failed to create hardware buffer, trying to create software buffer...");
|
||||
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_impl)
|
||||
{
|
||||
m_impl = new NzSoftwareBuffer(this, m_type);
|
||||
if (!m_impl->Create(length, typeSize, usage))
|
||||
{
|
||||
NazaraError("Failed to create software buffer");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_length = length;
|
||||
m_typeSize = typeSize;
|
||||
m_usage = usage;
|
||||
|
||||
// Si on arrive ici c'est que tout s'est bien passé.
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzBuffer::Destroy()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Buffer not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offset+length > m_length)
|
||||
{
|
||||
NazaraError("Exceeding buffer size");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->Fill(data, offset, length);
|
||||
}
|
||||
|
||||
unsigned int NzBuffer::GetLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
unsigned int NzBuffer::GetSize() const
|
||||
{
|
||||
return m_length*m_typeSize;
|
||||
}
|
||||
|
||||
nzBufferStorage NzBuffer::GetStorage() const
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
nzBufferType NzBuffer::GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
nzUInt8 NzBuffer::GetTypeSize() const
|
||||
{
|
||||
return m_typeSize;
|
||||
}
|
||||
|
||||
nzBufferUsage NzBuffer::GetUsage() const
|
||||
{
|
||||
return m_usage;
|
||||
}
|
||||
|
||||
bool NzBuffer::IsHardware() const
|
||||
{
|
||||
return m_storage == nzBufferStorage_Hardware;
|
||||
}
|
||||
|
||||
void* NzBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Buffer not created");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (offset+length > m_length)
|
||||
{
|
||||
NazaraError("Exceeding buffer size");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->Lock(lock, offset, length);
|
||||
}
|
||||
|
||||
bool NzBuffer::Unlock()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Buffer not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->Unlock();
|
||||
}
|
||||
|
||||
bool NzBuffer::IsHardwareSupported()
|
||||
{
|
||||
return NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer);
|
||||
}
|
||||
7
src/Nazara/Renderer/BufferImpl.cpp
Normal file
7
src/Nazara/Renderer/BufferImpl.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/BufferImpl.hpp>
|
||||
|
||||
NzBufferImpl::~NzBufferImpl() = default;
|
||||
31
src/Nazara/Renderer/BufferImpl.hpp
Normal file
31
src/Nazara/Renderer/BufferImpl.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_BUFFERIMPL_HPP
|
||||
#define NAZARA_BUFFERIMPL_HPP
|
||||
|
||||
#include <Nazara/Renderer/Buffer.hpp>
|
||||
|
||||
class NzBufferImpl
|
||||
{
|
||||
public:
|
||||
NzBufferImpl() = default;
|
||||
virtual ~NzBufferImpl();
|
||||
|
||||
virtual void Bind() = 0;
|
||||
|
||||
virtual bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static) = 0;
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
virtual bool Fill(const void* data, unsigned int offset, unsigned int length) = 0;
|
||||
|
||||
virtual bool IsHardware() const = 0;
|
||||
|
||||
virtual void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0) = 0;
|
||||
virtual bool Unlock() = 0;
|
||||
};
|
||||
|
||||
#endif // NAZARA_BUFFERIMPL_INCLUDED
|
||||
167
src/Nazara/Renderer/Context.cpp
Normal file
167
src/Nazara/Renderer/Context.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
#include <Nazara/Renderer/Linux/ContextImpl.hpp>
|
||||
#else
|
||||
#error Lack of implementation: Context
|
||||
#endif
|
||||
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NzContext::NzContext() :
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
NzContext::~NzContext()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
if (m_impl->IsActive())
|
||||
NzContextImpl::Desactivate();
|
||||
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzContext::Create(const NzContextParameters& parameters)
|
||||
{
|
||||
m_parameters = parameters;
|
||||
if (m_parameters.shared && !m_parameters.shareContext)
|
||||
m_parameters.shareContext = s_reference;
|
||||
|
||||
m_impl = new NzContextImpl;
|
||||
if (!m_impl->Create(m_parameters))
|
||||
{
|
||||
NazaraError("Failed to create context implementation");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_impl->Activate())
|
||||
{
|
||||
NazaraError("Failed to activate context");
|
||||
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_parameters.antialiasingLevel > 0)
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const NzContextParameters& NzContext::GetParameters() const
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
NazaraError("No context has been created");
|
||||
#endif
|
||||
|
||||
return m_parameters;
|
||||
}
|
||||
|
||||
bool NzContext::IsActive() const
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->IsActive();
|
||||
}
|
||||
|
||||
bool NzContext::SetActive(bool active)
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (active)
|
||||
{
|
||||
if (!m_impl->IsActive())
|
||||
return m_impl->Activate();
|
||||
}
|
||||
else if (m_impl->IsActive())
|
||||
return NzContextImpl::Desactivate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzContext::SwapBuffers()
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_parameters.doubleBuffered)
|
||||
{
|
||||
NazaraError("Context is not double buffered");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->SwapBuffers();
|
||||
}
|
||||
|
||||
const NzContext* NzContext::GetReference()
|
||||
{
|
||||
return s_reference;
|
||||
}
|
||||
|
||||
bool NzContext::InitializeReference()
|
||||
{
|
||||
NzContextParameters parameters;
|
||||
// parameters.compatibilityProfile = true;
|
||||
parameters.shared = false; // Difficile de partager le contexte de référence avec lui-même
|
||||
|
||||
s_reference = new NzContext;
|
||||
if (!s_reference->Create(parameters))
|
||||
{
|
||||
delete s_reference;
|
||||
s_reference = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzContext::UninitializeReference()
|
||||
{
|
||||
delete s_reference;
|
||||
s_reference = nullptr;
|
||||
}
|
||||
|
||||
NzContext* NzContext::s_reference = nullptr;
|
||||
14
src/Nazara/Renderer/ContextParameters.cpp
Normal file
14
src/Nazara/Renderer/ContextParameters.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/ContextParameters.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
nzUInt8 NzContextParameters::defaultMajorVersion; // Initialisé par NzOpenGL
|
||||
nzUInt8 NzContextParameters::defaultMinorVersion; // Initialisé par NzOpenGL
|
||||
const NzContext* NzContextParameters::defaultShareContext = nullptr;
|
||||
NzWindowHandle NzContextParameters::defaultWindow = 0;
|
||||
bool NzContextParameters::defaultCompatibilityProfile = false;
|
||||
bool NzContextParameters::defaultDoubleBuffered = false;
|
||||
bool NzContextParameters::defaultShared = true;
|
||||
29
src/Nazara/Renderer/Debug/Leaks.cpp
Normal file
29
src/Nazara/Renderer/Debug/Leaks.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#if NAZARA_RENDERER_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
|
||||
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
|
||||
#include <new>
|
||||
|
||||
void* operator new(std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, true);
|
||||
}
|
||||
|
||||
void operator delete(void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, true);
|
||||
}
|
||||
#endif
|
||||
254
src/Nazara/Renderer/GLSLShader.cpp
Normal file
254
src/Nazara/Renderer/GLSLShader.cpp
Normal file
@@ -0,0 +1,254 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/GLSLShader.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
GLenum shaderType[nzShaderType_Count] = {
|
||||
GL_FRAGMENT_SHADER, // nzShaderType_Fragment
|
||||
GL_GEOMETRY_SHADER, // nzShaderType_Geometry
|
||||
GL_VERTEX_SHADER // nzShaderType_Vertex
|
||||
};
|
||||
}
|
||||
|
||||
NzGLSLShader::NzGLSLShader(NzShader* parent) :
|
||||
m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
NzGLSLShader::~NzGLSLShader()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzGLSLShader::Bind()
|
||||
{
|
||||
glUseProgram(m_program);
|
||||
|
||||
return true; ///FIXME: Comment détecter une erreur d'OpenGL sans ralentir le programme ?
|
||||
}
|
||||
|
||||
bool NzGLSLShader::Compile()
|
||||
{
|
||||
m_idCache.clear();
|
||||
|
||||
glLinkProgram(m_program);
|
||||
|
||||
GLint success;
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &success);
|
||||
|
||||
if (success == GL_TRUE)
|
||||
{
|
||||
static NzString success("Linkage successful");
|
||||
m_log = success;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// On remplit le log avec l'erreur de compilation
|
||||
GLint length = 0;
|
||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &length);
|
||||
if (length > 1)
|
||||
{
|
||||
m_log.Reserve(length+19-1); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
m_log.Prepend("Linkage error: ");
|
||||
m_log.Resize(length+19-1); // Extension du buffer d'écriture pour ajouter le log
|
||||
|
||||
glGetProgramInfoLog(m_program, length-1, nullptr, &m_log[19]);
|
||||
}
|
||||
else
|
||||
m_log = "Linkage failed but no info log found";
|
||||
|
||||
NazaraError(m_log);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzGLSLShader::Create()
|
||||
{
|
||||
m_program = glCreateProgram();
|
||||
if (!m_program)
|
||||
{
|
||||
NazaraError("Failed to create program");
|
||||
return false;
|
||||
}
|
||||
|
||||
glBindAttribLocation(m_program, 0, "Position");
|
||||
glBindAttribLocation(m_program, 1, "Normal");
|
||||
//glBindAttribLocation(m_program, 2, "Diffuse");
|
||||
glBindAttribLocation(m_program, 3, "Tangent");
|
||||
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
{
|
||||
NzString uniformName = "TexCoord" + NzString::Number(i);
|
||||
glBindAttribLocation(m_program, 4+i, uniformName.GetConstBuffer());
|
||||
}
|
||||
|
||||
for (int i = 0; i < nzShaderType_Count; ++i)
|
||||
m_shaders[i] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzGLSLShader::Destroy()
|
||||
{
|
||||
for (GLuint shader : m_shaders)
|
||||
if (shader)
|
||||
glDeleteShader(shader);
|
||||
|
||||
if (m_program)
|
||||
glDeleteProgram(m_program);
|
||||
}
|
||||
|
||||
NzString NzGLSLShader::GetLog() const
|
||||
{
|
||||
return m_log;
|
||||
}
|
||||
|
||||
nzShaderLanguage NzGLSLShader::GetLanguage() const
|
||||
{
|
||||
return nzShaderLanguage_GLSL;
|
||||
}
|
||||
|
||||
NzString NzGLSLShader::GetSourceCode(nzShaderType type) const
|
||||
{
|
||||
NzString source;
|
||||
|
||||
GLint length;
|
||||
glGetShaderiv(m_shaders[type], GL_SHADER_SOURCE_LENGTH, &length);
|
||||
if (length > 1)
|
||||
{
|
||||
source.Resize(length-1); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
glGetShaderSource(m_shaders[type], length, nullptr, &source[0]);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
GLint NzGLSLShader::GetUniformLocation(const NzString& name) const
|
||||
{
|
||||
std::map<NzString, GLint>::const_iterator it = m_idCache.find(name);
|
||||
GLint id;
|
||||
if (it == m_idCache.end())
|
||||
{
|
||||
id = glGetUniformLocation(m_program, name.GetConstBuffer());
|
||||
m_idCache[name] = id;
|
||||
}
|
||||
else
|
||||
id = it->second;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::IsLoaded(nzShaderType type) const
|
||||
{
|
||||
return m_shaders[type] != 0;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::Load(nzShaderType type, const NzString& source)
|
||||
{
|
||||
GLuint shader = glCreateShader(shaderType[type]);
|
||||
if (!shader)
|
||||
{
|
||||
m_log = "Failed to create shader object";
|
||||
NazaraError(m_log);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* tmp = source.GetConstBuffer();
|
||||
GLint length = source.GetSize();
|
||||
glShaderSource(shader, 1, &tmp, &length);
|
||||
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
|
||||
if (success == GL_TRUE)
|
||||
{
|
||||
glAttachShader(m_program, shader);
|
||||
m_shaders[type] = shader;
|
||||
|
||||
static NzString success("Compilation successful");
|
||||
m_log = success;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// On remplit le log avec l'erreur de compilation
|
||||
length = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
|
||||
if (length > 1)
|
||||
{
|
||||
m_log.Reserve(length+19-1); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
m_log.Prepend("Compilation error: ");
|
||||
m_log.Resize(length+19-1); // Extension du buffer d'écriture pour ajouter le log
|
||||
|
||||
glGetShaderInfoLog(shader, length-1, nullptr, &m_log[19]);
|
||||
}
|
||||
else
|
||||
m_log = "Compilation failed but no info log found";
|
||||
|
||||
NazaraError(m_log);
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendBoolean(const NzString& name, bool value)
|
||||
{
|
||||
glUniform1i(GetUniformLocation(name), value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendDouble(const NzString& name, double value)
|
||||
{
|
||||
glUniform1d(GetUniformLocation(name), value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendFloat(const NzString& name, float value)
|
||||
{
|
||||
glUniform1f(GetUniformLocation(name), value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendInteger(const NzString& name, int value)
|
||||
{
|
||||
glUniform1i(GetUniformLocation(name), value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendMatrix(const NzString& name, const NzMatrix4d& matrix)
|
||||
{
|
||||
glUniformMatrix4dv(GetUniformLocation(name), 1, GL_FALSE, matrix);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendMatrix(const NzString& name, const NzMatrix4f& matrix)
|
||||
{
|
||||
glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, matrix);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzGLSLShader::Unbind()
|
||||
{
|
||||
glUseProgram(0);
|
||||
}
|
||||
55
src/Nazara/Renderer/GLSLShader.hpp
Normal file
55
src/Nazara/Renderer/GLSLShader.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_GLSLSHADER_HPP
|
||||
#define NAZARA_GLSLSHADER_HPP
|
||||
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||
#include <map>
|
||||
|
||||
class NzGLSLShader : public NzShaderImpl
|
||||
{
|
||||
public:
|
||||
NzGLSLShader(NzShader* parent);
|
||||
~NzGLSLShader();
|
||||
|
||||
bool Bind();
|
||||
|
||||
bool Compile();
|
||||
bool Create();
|
||||
|
||||
void Destroy();
|
||||
|
||||
NzString GetLog() const;
|
||||
nzShaderLanguage GetLanguage() const;
|
||||
NzString GetSourceCode(nzShaderType type) const;
|
||||
GLint GetUniformLocation(const NzString& name) const;
|
||||
|
||||
bool IsLoaded(nzShaderType type) const;
|
||||
|
||||
bool Load(nzShaderType type, const NzString& source);
|
||||
|
||||
bool SendBoolean(const NzString& name, bool value);
|
||||
bool SendDouble(const NzString& name, double value);
|
||||
bool SendFloat(const NzString& name, float value);
|
||||
bool SendInteger(const NzString& name, int value);
|
||||
bool SendMatrix(const NzString& name, const NzMatrix4d& matrix);
|
||||
bool SendMatrix(const NzString& name, const NzMatrix4f& matrix);
|
||||
|
||||
void Unbind();
|
||||
|
||||
private:
|
||||
mutable std::map<NzString, GLint> m_idCache;
|
||||
GLuint m_program;
|
||||
GLuint m_shaders[nzShaderType_Count];
|
||||
NzShader* m_parent;
|
||||
NzString m_log;
|
||||
};
|
||||
|
||||
#endif // NAZARA_GLSLSHADER_HPPs
|
||||
231
src/Nazara/Renderer/HardwareBuffer.cpp
Normal file
231
src/Nazara/Renderer/HardwareBuffer.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/HardwareBuffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
GLenum bufferLock[] = {
|
||||
GL_WRITE_ONLY, // nzBufferLock_DiscardAndWrite
|
||||
GL_READ_ONLY, // nzBufferLock_ReadOnly
|
||||
GL_READ_WRITE, // nzBufferLock_ReadWrite
|
||||
GL_WRITE_ONLY // nzBufferLock_WriteOnly
|
||||
};
|
||||
|
||||
GLenum bufferLockRange[] = {
|
||||
GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_WRITE_BIT, // nzBufferLock_DiscardAndWrite
|
||||
GL_MAP_READ_BIT, // nzBufferLock_ReadOnly
|
||||
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, // nzBufferLock_ReadWrite
|
||||
GL_MAP_WRITE_BIT // nzBufferLock_WriteOnly
|
||||
};
|
||||
|
||||
GLenum bufferTarget[] = {
|
||||
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index,
|
||||
GL_ARRAY_BUFFER, // nzBufferType_Vertex
|
||||
};
|
||||
|
||||
GLenum bufferTargetBinding[] = {
|
||||
GL_ELEMENT_ARRAY_BUFFER_BINDING, // BufferType_Index,
|
||||
GL_ARRAY_BUFFER_BINDING, // BufferType_Vertex
|
||||
};
|
||||
|
||||
GLenum bufferUsage[] = {
|
||||
// J'ai choisi DYNAMIC_DRAW à la place de STREAM_DRAW car DYNAMIC semble plus adapté au profil "une mise à jour pour quelques rendus"
|
||||
// Ce qui est je pense le scénario qui arrivera le plus souvent (Prévoir une option pour permettre d'utiliser le STREAM_DRAW ?)
|
||||
// Source: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=160839
|
||||
GL_DYNAMIC_DRAW, // nzBufferUsage_Dynamic
|
||||
GL_STATIC_DRAW // nzBufferUsage_Static
|
||||
};
|
||||
|
||||
typedef nzUInt8* (*LockRoutine)(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length);
|
||||
|
||||
nzUInt8* LockBuffer(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
NazaraUnused(length);
|
||||
|
||||
if (lock == nzBufferLock_DiscardAndWrite)
|
||||
{
|
||||
GLint size;
|
||||
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &size);
|
||||
|
||||
GLint usage;
|
||||
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &usage);
|
||||
|
||||
// On discard le buffer
|
||||
glBufferData(bufferTargetBinding[type], size, nullptr, usage);
|
||||
}
|
||||
|
||||
void* ptr = glMapBuffer(bufferTarget[type], bufferLock[lock]);
|
||||
if (ptr)
|
||||
return reinterpret_cast<nzUInt8*>(ptr) + offset;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nzUInt8* LockBufferRange(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
return reinterpret_cast<nzUInt8*>(glMapBufferRange(bufferTarget[type], offset, length, bufferLockRange[lock]));
|
||||
}
|
||||
|
||||
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
if (glMapBufferRange)
|
||||
lockBuffer = LockBufferRange;
|
||||
else
|
||||
lockBuffer = LockBuffer;
|
||||
|
||||
return lockBuffer(type, lock, offset, length);
|
||||
}
|
||||
|
||||
LockRoutine lockBuffer = LockBufferFirstRun;
|
||||
}
|
||||
|
||||
NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) :
|
||||
m_type(type),
|
||||
m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
NzHardwareBuffer::~NzHardwareBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void NzHardwareBuffer::Bind()
|
||||
{
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage)
|
||||
{
|
||||
m_buffer = 0;
|
||||
glGenBuffers(1, &m_buffer);
|
||||
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Failed to create buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], &previous);
|
||||
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
glBufferData(bufferTarget[m_type], length*typeSize, nullptr, bufferUsage[usage]);
|
||||
|
||||
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
|
||||
if (previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzHardwareBuffer::Destroy()
|
||||
{
|
||||
glDeleteBuffers(1, &m_buffer);
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
GLuint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
|
||||
if (previous != m_buffer)
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
|
||||
// Il semblerait que glBufferSubData soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil
|
||||
if (length < 32*1024)
|
||||
{
|
||||
if (length == m_parent->GetLength())
|
||||
glBufferData(bufferTarget[m_type], m_parent->GetSize(), data, bufferUsage[m_parent->GetStorage()]);
|
||||
else
|
||||
{
|
||||
nzUInt8 typeSize = m_parent->GetTypeSize();
|
||||
glBufferSubData(bufferTarget[m_type], offset*typeSize, length*typeSize, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nzUInt8* ptr = lockBuffer(m_type, (length == m_parent->GetLength()) ? nzBufferLock_DiscardAndWrite : nzBufferLock_WriteOnly, offset, length);
|
||||
if (ptr)
|
||||
{
|
||||
NazaraError("Failed to lock buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memcpy(ptr, data, length*m_parent->GetTypeSize());
|
||||
|
||||
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
|
||||
{
|
||||
// Une erreur rare est survenue, nous devons réinitialiser le buffer
|
||||
NazaraError("Failed to unlock buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
|
||||
|
||||
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::IsHardware() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void* NzHardwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
|
||||
GLuint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
|
||||
if (previous != m_buffer)
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
|
||||
void* ptr = lockBuffer(m_type, lock, offset, length);
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::Unlock()
|
||||
{
|
||||
GLuint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
|
||||
if (previous != m_buffer)
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
|
||||
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
|
||||
{
|
||||
// Une erreur rare est survenue, nous devons réinitialiser le buffer
|
||||
NazaraError("Failed to unlock buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
|
||||
|
||||
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]);
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return true;
|
||||
}
|
||||
38
src/Nazara/Renderer/HardwareBuffer.hpp
Normal file
38
src/Nazara/Renderer/HardwareBuffer.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_HARDWAREBUFFER_HPP
|
||||
#define NAZARA_HARDWAREBUFFER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Renderer/BufferImpl.hpp>
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
|
||||
class NzHardwareBuffer : public NzBufferImpl
|
||||
{
|
||||
public:
|
||||
NzHardwareBuffer(NzBuffer* parent, nzBufferType type);
|
||||
~NzHardwareBuffer();
|
||||
|
||||
void Bind();
|
||||
|
||||
bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static);
|
||||
void Destroy();
|
||||
|
||||
bool Fill(const void* data, unsigned int offset, unsigned int length);
|
||||
|
||||
bool IsHardware() const;
|
||||
|
||||
void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0);
|
||||
bool Unlock();
|
||||
|
||||
private:
|
||||
GLuint m_buffer;
|
||||
nzBufferType m_type;
|
||||
NzBuffer* m_parent;
|
||||
};
|
||||
|
||||
#endif // NAZARA_HARDWAREBUFFER_HPP
|
||||
154
src/Nazara/Renderer/IndexBuffer.cpp
Normal file
154
src/Nazara/Renderer/IndexBuffer.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/IndexBuffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzIndexBuffer::NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount) :
|
||||
m_buffer(buffer),
|
||||
m_ownsBuffer(false),
|
||||
m_indexCount(indexCount),
|
||||
m_startIndex(startIndex)
|
||||
{
|
||||
if (m_buffer)
|
||||
m_buffer->AddResourceReference();
|
||||
}
|
||||
|
||||
NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferUsage usage) :
|
||||
m_ownsBuffer(true),
|
||||
m_indexCount(length),
|
||||
m_startIndex(0)
|
||||
{
|
||||
m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, usage);
|
||||
m_buffer->AddResourceReference();
|
||||
m_buffer->SetPersistent(false);
|
||||
}
|
||||
|
||||
NzIndexBuffer::NzIndexBuffer(const NzIndexBuffer& indexBuffer) :
|
||||
m_buffer(indexBuffer.m_buffer),
|
||||
m_indexCount(indexBuffer.m_indexCount),
|
||||
m_startIndex(indexBuffer.m_startIndex)
|
||||
{
|
||||
if (m_buffer)
|
||||
{
|
||||
if (m_ownsBuffer)
|
||||
{
|
||||
m_buffer = new NzBuffer(nzBufferType_Index, indexBuffer.m_buffer->GetLength(), indexBuffer.m_buffer->GetSize(), indexBuffer.m_buffer->GetUsage());
|
||||
m_buffer->AddResourceReference();
|
||||
m_buffer->SetPersistent(false);
|
||||
m_buffer->CopyContent(*indexBuffer.m_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer = indexBuffer.m_buffer;
|
||||
m_buffer->AddResourceReference();
|
||||
}
|
||||
}
|
||||
else
|
||||
m_buffer = nullptr;
|
||||
}
|
||||
|
||||
NzIndexBuffer::~NzIndexBuffer()
|
||||
{
|
||||
if (m_buffer)
|
||||
m_buffer->RemoveResourceReference();
|
||||
}
|
||||
|
||||
bool NzIndexBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Impossible to fill sequential buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offset+length > m_indexCount)
|
||||
{
|
||||
NazaraError("Exceeding virtual buffer size");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Fill(data, m_startIndex+offset, length);
|
||||
}
|
||||
|
||||
NzBuffer* NzIndexBuffer::GetBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
nzUInt8 NzIndexBuffer::GetIndexSize() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Sequential index buffer: Buffer has no index size");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->GetTypeSize();
|
||||
}
|
||||
|
||||
unsigned int NzIndexBuffer::GetIndexCount() const
|
||||
{
|
||||
return m_indexCount;
|
||||
}
|
||||
|
||||
unsigned int NzIndexBuffer::GetStartIndex() const
|
||||
{
|
||||
return m_startIndex;
|
||||
}
|
||||
|
||||
bool NzIndexBuffer::IsHardware() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Sequential index buffer is neither hardware or software");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->IsHardware();
|
||||
}
|
||||
|
||||
bool NzIndexBuffer::IsSequential() const
|
||||
{
|
||||
return m_buffer == nullptr;
|
||||
}
|
||||
|
||||
void* NzIndexBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Impossible to lock sequential index buffer");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (offset+length > m_indexCount)
|
||||
{
|
||||
NazaraError("Exceeding virtual buffer size");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Lock(lock, m_startIndex+offset, (length) ? length : m_indexCount-offset);
|
||||
}
|
||||
|
||||
bool NzIndexBuffer::Unlock()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Impossible to unlock sequential index buffer");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Unlock();
|
||||
}
|
||||
563
src/Nazara/Renderer/OpenGL.cpp
Normal file
563
src/Nazara/Renderer/OpenGL.cpp
Normal file
@@ -0,0 +1,563 @@
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
HMODULE openGLlibrary;
|
||||
#endif
|
||||
|
||||
NzOpenGLFunc LoadEntry(const char* name, bool launchException = true)
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
NzOpenGLFunc entry = reinterpret_cast<NzOpenGLFunc>(wglGetProcAddress(name));
|
||||
if (!entry) // wglGetProcAddress ne fonctionne pas sur les fonctions OpenGL <= 1.1
|
||||
entry = reinterpret_cast<NzOpenGLFunc>(GetProcAddress(openGLlibrary, name));
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
NzOpenGLFunc entry = reinterpret_cast<NzOpenGLFunc>(glXGetProcAddress(name));
|
||||
#else
|
||||
#error OS not handled
|
||||
#endif
|
||||
|
||||
if (!entry && launchException)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "failed to load \"" << name << '"';
|
||||
|
||||
throw std::runtime_error(oss.str());
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
bool LoadLibrary()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
openGLlibrary = ::LoadLibraryA("opengl32.dll");
|
||||
|
||||
return openGLlibrary != nullptr;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void UnloadLibrary()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
FreeLibrary(openGLlibrary);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::set<NzString> openGLextensionSet;
|
||||
bool openGLextensions[NzOpenGL::Count] = {false};
|
||||
unsigned int openGLversion = 0;
|
||||
|
||||
bool LoadExtensionsString(const NzString& extensionString)
|
||||
{
|
||||
if (extensionString.IsEmpty())
|
||||
{
|
||||
NazaraError("Unable to get extension string");
|
||||
return false;
|
||||
}
|
||||
|
||||
// On peut sûrement faire plus rapide mais comme ça ne se fait qu'une fois et que NzString implémente le COW...
|
||||
std::vector<NzString> ext;
|
||||
extensionString.Split(ext);
|
||||
|
||||
for (std::vector<NzString>::iterator it = ext.begin(); it != ext.end(); ++it)
|
||||
openGLextensionSet.insert(*it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadExtensions3()
|
||||
{
|
||||
GLint extensionCount = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
|
||||
|
||||
if (extensionCount <= 0)
|
||||
{
|
||||
NazaraError("Unable to get extension count");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < extensionCount; ++i)
|
||||
{
|
||||
NzString extension(reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)));
|
||||
if (extension.IsEmpty())
|
||||
{
|
||||
NazaraWarning("Unable to get extension #" + NzString::Number(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
openGLextensionSet.insert(extension);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int NzOpenGL::GetVersion()
|
||||
{
|
||||
return openGLversion;
|
||||
}
|
||||
|
||||
bool NzOpenGL::Initialize()
|
||||
{
|
||||
if (!LoadLibrary())
|
||||
{
|
||||
NazaraError("Failed to load OpenGL library");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Le chargement des fonctions OpenGL nécessite un contexte OpenGL
|
||||
// Le contexte de chargement ne peut pas être partagé car le contexte de référence n'existe pas encore
|
||||
NzContextParameters parameters;
|
||||
parameters.majorVersion = 2;
|
||||
parameters.minorVersion = 0;
|
||||
parameters.shared = false;
|
||||
|
||||
NzContext loadContext;
|
||||
if (!loadContext.Create(parameters))
|
||||
{
|
||||
NazaraError("Failed to create load context");
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************Noyau****************************************/
|
||||
|
||||
try
|
||||
{
|
||||
glActiveTexture = reinterpret_cast<PFNGLACTIVETEXTUREPROC>(LoadEntry("glActiveTexture"));
|
||||
glAttachShader = reinterpret_cast<PFNGLATTACHSHADERPROC>(LoadEntry("glAttachShader"));
|
||||
glBindAttribLocation = reinterpret_cast<PFNGLBINDATTRIBLOCATIONPROC>(LoadEntry("glBindAttribLocation"));
|
||||
glBindBuffer = reinterpret_cast<PFNGLBINDBUFFERPROC>(LoadEntry("glBindBuffer"));
|
||||
glBindTexture = reinterpret_cast<PFNGLBINDTEXTUREPROC>(LoadEntry("glBindTexture"));
|
||||
glBlendFunc = reinterpret_cast<PFNGLBLENDFUNCPROC>(LoadEntry("glBlendFunc"));
|
||||
glBufferData = reinterpret_cast<PFNGLBUFFERDATAPROC>(LoadEntry("glBufferData"));
|
||||
glBufferSubData = reinterpret_cast<PFNGLBUFFERSUBDATAPROC>(LoadEntry("glBufferSubData"));
|
||||
glClear = reinterpret_cast<PFNGLCLEARPROC>(LoadEntry("glClear"));
|
||||
glClearColor = reinterpret_cast<PFNGLCLEARCOLORPROC>(LoadEntry("glClearColor"));
|
||||
glClearDepth = reinterpret_cast<PFNGLCLEARDEPTHPROC>(LoadEntry("glClearDepth"));
|
||||
glClearStencil = reinterpret_cast<PFNGLCLEARSTENCILPROC>(LoadEntry("glClearStencil"));
|
||||
glCreateProgram = reinterpret_cast<PFNGLCREATEPROGRAMPROC>(LoadEntry("glCreateProgram"));
|
||||
glCreateShader = reinterpret_cast<PFNGLCREATESHADERPROC>(LoadEntry("glCreateShader"));
|
||||
glColorMask = reinterpret_cast<PFNGLCOLORMASKPROC>(LoadEntry("glColorMask"));
|
||||
glCullFace = reinterpret_cast<PFNGLCULLFACEPROC>(LoadEntry("glCullFace"));
|
||||
glCompileShader = reinterpret_cast<PFNGLCOMPILESHADERPROC>(LoadEntry("glCompileShader"));
|
||||
glDeleteBuffers = reinterpret_cast<PFNGLDELETEBUFFERSPROC>(LoadEntry("glDeleteBuffers"));
|
||||
glDeleteProgram = reinterpret_cast<PFNGLDELETEPROGRAMPROC>(LoadEntry("glDeleteProgram"));
|
||||
glDeleteShader = reinterpret_cast<PFNGLDELETESHADERPROC>(LoadEntry("glDeleteShader"));
|
||||
glDeleteTextures = reinterpret_cast<PFNGLDELETETEXTURESPROC>(LoadEntry("glDeleteTextures"));
|
||||
glDepthFunc = reinterpret_cast<PFNGLDEPTHFUNCPROC>(LoadEntry("glDepthFunc"));
|
||||
glDepthMask = reinterpret_cast<PFNGLDEPTHMASKPROC>(LoadEntry("glDepthMask"));
|
||||
glDisable = reinterpret_cast<PFNGLDISABLEPROC>(LoadEntry("glDisable"));
|
||||
glDisableVertexAttribArray = reinterpret_cast<PFNGLDISABLEVERTEXATTRIBARRAYPROC>(LoadEntry("glDisableVertexAttribArray"));
|
||||
glDrawArrays = reinterpret_cast<PFNGLDRAWARRAYSPROC>(LoadEntry("glDrawArrays"));
|
||||
glDrawBuffer = reinterpret_cast<PFNGLDRAWBUFFERPROC>(LoadEntry("glDrawBuffer"));
|
||||
glDrawBuffers = reinterpret_cast<PFNGLDRAWBUFFERSPROC>(LoadEntry("glDrawBuffers"));
|
||||
glDrawElements = reinterpret_cast<PFNGLDRAWELEMENTSPROC>(LoadEntry("glDrawElements"));
|
||||
glFlush = reinterpret_cast<PFNGLFLUSHPROC>(LoadEntry("glFlush"));
|
||||
glEnable = reinterpret_cast<PFNGLENABLEPROC>(LoadEntry("glEnable"));
|
||||
glEnableVertexAttribArray = reinterpret_cast<PFNGLENABLEVERTEXATTRIBARRAYPROC>(LoadEntry("glEnableVertexAttribArray"));
|
||||
glGenBuffers = reinterpret_cast<PFNGLGENBUFFERSPROC>(LoadEntry("glGenBuffers"));
|
||||
glGenTextures = reinterpret_cast<PFNGLGENTEXTURESPROC>(LoadEntry("glGenTextures"));
|
||||
glGetBufferParameteriv = reinterpret_cast<PFNGLGETBUFFERPARAMETERIVPROC>(LoadEntry("glGetBufferParameteriv"));
|
||||
glGetError = reinterpret_cast<PFNGLGETERRORPROC>(LoadEntry("glGetError"));
|
||||
glGetIntegerv = reinterpret_cast<PFNGLGETINTEGERVPROC>(LoadEntry("glGetIntegerv"));
|
||||
glGetProgramiv = reinterpret_cast<PFNGLGETPROGRAMIVPROC>(LoadEntry("glGetProgramiv"));
|
||||
glGetProgramInfoLog = reinterpret_cast<PFNGLGETPROGRAMINFOLOGPROC>(LoadEntry("glGetProgramInfoLog"));
|
||||
glGetShaderInfoLog = reinterpret_cast<PFNGLGETSHADERINFOLOGPROC>(LoadEntry("glGetShaderInfoLog"));
|
||||
glGetShaderiv = reinterpret_cast<PFNGLGETSHADERIVPROC>(LoadEntry("glGetShaderiv"));
|
||||
glGetShaderSource = reinterpret_cast<PFNGLGETSHADERSOURCEPROC>(LoadEntry("glGetShaderSource"));
|
||||
glGetString = reinterpret_cast<PFNGLGETSTRINGPROC>(LoadEntry("glGetString"));
|
||||
glGetTexImage = reinterpret_cast<PFNGLGETTEXIMAGEPROC>(LoadEntry("glGetTexImage"));
|
||||
glGetTexParameterfv = reinterpret_cast<PFNGLGETTEXPARAMETERFVPROC>(LoadEntry("glGetTexParameterfv"));
|
||||
glGetTexParameteriv = reinterpret_cast<PFNGLGETTEXPARAMETERIVPROC>(LoadEntry("glGetTexParameteriv"));
|
||||
glGetUniformLocation = reinterpret_cast<PFNGLGETUNIFORMLOCATIONPROC>(LoadEntry("glGetUniformLocation"));
|
||||
glLinkProgram = reinterpret_cast<PFNGLLINKPROGRAMPROC>(LoadEntry("glLinkProgram"));
|
||||
glMapBuffer = reinterpret_cast<PFNGLMAPBUFFERPROC>(LoadEntry("glMapBuffer"));
|
||||
glPolygonMode = reinterpret_cast<PFNGLPOLYGONMODEPROC>(LoadEntry("glPolygonMode"));
|
||||
glScissor = reinterpret_cast<PFNGLSCISSORPROC>(LoadEntry("glScissor"));
|
||||
glShaderSource = reinterpret_cast<PFNGLSHADERSOURCEPROC>(LoadEntry("glShaderSource"));
|
||||
glStencilFunc = reinterpret_cast<PFNGLSTENCILFUNCPROC>(LoadEntry("glStencilFunc"));
|
||||
glStencilOp = reinterpret_cast<PFNGLSTENCILOPPROC>(LoadEntry("glStencilOp"));
|
||||
glTexImage2D = reinterpret_cast<PFNGLTEXIMAGE2DPROC>(LoadEntry("glTexImage2D"));
|
||||
glTexParameterf = reinterpret_cast<PFNGLTEXPARAMETERFPROC>(LoadEntry("glTexParameterf"));
|
||||
glTexParameteri = reinterpret_cast<PFNGLTEXPARAMETERIPROC>(LoadEntry("glTexParameteri"));
|
||||
glTexSubImage2D = reinterpret_cast<PFNGLTEXSUBIMAGE2DPROC>(LoadEntry("glTexSubImage2D"));
|
||||
glUniform1f = reinterpret_cast<PFNGLUNIFORM1FPROC>(LoadEntry("glUniform1f"));
|
||||
glUniform1i = reinterpret_cast<PFNGLUNIFORM1IPROC>(LoadEntry("glUniform1i"));
|
||||
glUniform2fv = reinterpret_cast<PFNGLUNIFORM2FVPROC>(LoadEntry("glUniform2fv"));
|
||||
glUniform3fv = reinterpret_cast<PFNGLUNIFORM3FVPROC>(LoadEntry("glUniform3fv"));
|
||||
glUniform4fv = reinterpret_cast<PFNGLUNIFORM4FVPROC>(LoadEntry("glUniform4fv"));
|
||||
glUniformMatrix4fv = reinterpret_cast<PFNGLUNIFORMMATRIX4FVPROC>(LoadEntry("glUniformMatrix4fv"));
|
||||
glUnmapBuffer = reinterpret_cast<PFNGLUNMAPBUFFERPROC>(LoadEntry("glUnmapBuffer"));
|
||||
glUseProgram = reinterpret_cast<PFNGLUSEPROGRAMPROC>(LoadEntry("glUseProgram"));
|
||||
glVertexAttrib4f = reinterpret_cast<PFNGLVERTEXATTRIB4FPROC>(LoadEntry("glVertexAttrib4f"));
|
||||
glVertexAttribPointer = reinterpret_cast<PFNGLVERTEXATTRIBPOINTERPROC>(LoadEntry("glVertexAttribPointer"));
|
||||
glViewport = reinterpret_cast<PFNGLVIEWPORTPROC>(LoadEntry("glViewport"));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Unable to load OpenGL: " + NzString(e.what()));
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fonctions optionnelles
|
||||
glGetStringi = reinterpret_cast<PFNGLGETSTRINGIPROC>(LoadEntry("glGetStringi", false));
|
||||
glMapBufferRange = reinterpret_cast<PFNGLMAPBUFFERRANGEPROC>(LoadEntry("glMapBufferRange", false));
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
wglCreateContextAttribs = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(LoadEntry("wglCreateContextAttribsARB", false));
|
||||
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(LoadEntry("wglChoosePixelFormatARB", false));
|
||||
if (!wglChoosePixelFormat)
|
||||
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATEXTPROC>(LoadEntry("wglChoosePixelFormatEXT", false));
|
||||
|
||||
wglGetExtensionsStringARB = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGARBPROC>(LoadEntry("wglGetExtensionsStringARB", false));
|
||||
wglGetExtensionsStringEXT = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGEXTPROC>(LoadEntry("wglGetExtensionsStringEXT", false));
|
||||
wglSwapInterval = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(LoadEntry("wglSwapIntervalEXT", false));
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
glXCreateContextAttribs = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(LoadEntry("glXCreateContextAttribsARB", false));
|
||||
glXSwapInterval = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(LoadEntry("glXSwapIntervalSGI", false));
|
||||
#endif
|
||||
|
||||
// Récupération de la version d'OpenGL
|
||||
// Ce code se base sur le fait que la carte graphique renverra un contexte de compatibilité avec la plus haute version supportée
|
||||
// Ce qui semble vrai au moins chez ATI/AMD et NVidia, mais si quelqu'un à une meilleure idée ...
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
if (!version)
|
||||
{
|
||||
NazaraError("Unable to retrieve OpenGL version");
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int major = version[0] - '0';
|
||||
unsigned int minor = version[2] - '0';
|
||||
|
||||
if (major == 0 || major > 9)
|
||||
{
|
||||
NazaraError("Unable to retrieve OpenGL major version");
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (minor > 9)
|
||||
{
|
||||
NazaraWarning("Unable to retrieve OpenGL minor version (using 0)");
|
||||
minor = 0;
|
||||
}
|
||||
|
||||
openGLversion = major*100 + minor*10;
|
||||
|
||||
/****************************************Extensions****************************************/
|
||||
|
||||
if (!glGetStringi || !LoadExtensions3())
|
||||
{
|
||||
if (openGLversion >= 300) // Dans le cas contraire c'est normal
|
||||
NazaraWarning("Failed to load OpenGL 3 extension system, switching to OpenGL 2 extension system...");
|
||||
|
||||
if (!LoadExtensionsString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))))
|
||||
NazaraWarning("Failed to load extension system");
|
||||
}
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
{
|
||||
bool loaded;
|
||||
if (wglGetExtensionsStringARB)
|
||||
loaded = LoadExtensionsString(reinterpret_cast<const char*>(wglGetExtensionsStringARB(wglGetCurrentDC())));
|
||||
else if (wglGetExtensionsStringEXT)
|
||||
loaded = LoadExtensionsString(reinterpret_cast<const char*>(wglGetExtensionsStringEXT()));
|
||||
else
|
||||
loaded = false;
|
||||
|
||||
if (!loaded)
|
||||
NazaraWarning("Failed to load windows' extension string");
|
||||
}
|
||||
#endif
|
||||
|
||||
// AnisotropicFilter
|
||||
openGLextensions[NzOpenGL::AnisotropicFilter] = IsSupported("GL_EXT_texture_filter_anisotropic");
|
||||
|
||||
// FP64
|
||||
if (openGLversion >= 400 || IsSupported("GL_ARB_gpu_shader_fp64"))
|
||||
{
|
||||
try
|
||||
{
|
||||
glUniform1d = reinterpret_cast<PFNGLUNIFORM1DPROC>(LoadEntry("glUniform1d"));
|
||||
glUniform2dv = reinterpret_cast<PFNGLUNIFORM2DVPROC>(LoadEntry("glUniform2dv"));
|
||||
glUniform3dv = reinterpret_cast<PFNGLUNIFORM3DVPROC>(LoadEntry("glUniform3dv"));
|
||||
glUniform4dv = reinterpret_cast<PFNGLUNIFORM4DVPROC>(LoadEntry("glUniform4dv"));
|
||||
|
||||
openGLextensions[NzOpenGL::FP64] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to load ARB_gpu_shader_fp64: " + NzString(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
// Framebuffer_Object
|
||||
try
|
||||
{
|
||||
glBindFramebuffer = reinterpret_cast<PFNGLBINDFRAMEBUFFERPROC>(LoadEntry("glBindFramebuffer"));
|
||||
glBindRenderbuffer = reinterpret_cast<PFNGLBINDRENDERBUFFERPROC>(LoadEntry("glBindRenderbuffer"));
|
||||
glCheckFramebufferStatus = reinterpret_cast<PFNGLCHECKFRAMEBUFFERSTATUSPROC>(LoadEntry("glCheckFramebufferStatus"));
|
||||
glDeleteFramebuffers = reinterpret_cast<PFNGLDELETEFRAMEBUFFERSPROC>(LoadEntry("glDeleteFramebuffers"));
|
||||
glDeleteRenderbuffers = reinterpret_cast<PFNGLDELETERENDERBUFFERSPROC>(LoadEntry("glDeleteRenderbuffers"));
|
||||
glFramebufferRenderbuffer = reinterpret_cast<PFNGLFRAMEBUFFERRENDERBUFFERPROC>(LoadEntry("glFramebufferRenderbuffer"));
|
||||
glFramebufferTexture2D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DPROC>(LoadEntry("glFramebufferTexture2D"));
|
||||
glGenerateMipmap = reinterpret_cast<PFNGLGENERATEMIPMAPPROC>(LoadEntry("glGenerateMipmap"));
|
||||
glGenFramebuffers = reinterpret_cast<PFNGLGENFRAMEBUFFERSPROC>(LoadEntry("glGenFramebuffers"));
|
||||
glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSPROC>(LoadEntry("glGenRenderbuffers"));
|
||||
glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEPROC>(LoadEntry("glRenderbufferStorage"));
|
||||
|
||||
openGLextensions[NzOpenGL::Framebuffer_Object] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
if (openGLversion >= 300)
|
||||
NazaraWarning("Failed to load core FBOs (" + NzString(e.what()) + ")");
|
||||
|
||||
if (IsSupported("GL_EXT_framebuffer_object"))
|
||||
{
|
||||
try
|
||||
{
|
||||
glBindFramebuffer = reinterpret_cast<PFNGLBINDFRAMEBUFFEREXTPROC>(LoadEntry("glBindFramebufferEXT"));
|
||||
glBindRenderbuffer = reinterpret_cast<PFNGLBINDRENDERBUFFEREXTPROC>(LoadEntry("glBindRenderbufferEXT"));
|
||||
glCheckFramebufferStatus = reinterpret_cast<PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC>(LoadEntry("glCheckFramebufferStatusEXT"));
|
||||
glDeleteFramebuffers = reinterpret_cast<PFNGLDELETEFRAMEBUFFERSEXTPROC>(LoadEntry("glDeleteFramebuffersEXT"));
|
||||
glDeleteRenderbuffers = reinterpret_cast<PFNGLDELETERENDERBUFFERSEXTPROC>(LoadEntry("glDeleteRenderbuffersEXT"));
|
||||
glFramebufferRenderbuffer = reinterpret_cast<PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC>(LoadEntry("glFramebufferRenderbufferEXT"));
|
||||
glFramebufferTexture2D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DEXTPROC>(LoadEntry("glFramebufferTexture2DEXT"));
|
||||
glGenerateMipmap = reinterpret_cast<PFNGLGENERATEMIPMAPEXTPROC>(LoadEntry("glGenerateMipmapEXT"));
|
||||
glGenFramebuffers = reinterpret_cast<PFNGLGENFRAMEBUFFERSEXTPROC>(LoadEntry("glGenFramebuffersEXT"));
|
||||
glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSEXTPROC>(LoadEntry("glGenRenderbuffersEXT"));
|
||||
glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEEXTPROC>(LoadEntry("glRenderbufferStorageEXT"));
|
||||
|
||||
openGLextensions[NzOpenGL::Framebuffer_Object] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to load EXT_framebuffer_object: " + NzString(e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Occlusion_Query
|
||||
try
|
||||
{
|
||||
glBeginQuery = reinterpret_cast<PFNGLBEGINQUERYPROC>(LoadEntry("glBeginQuery"));
|
||||
glDeleteQueries = reinterpret_cast<PFNGLDELETEQUERIESPROC>(LoadEntry("glDeleteQueries"));
|
||||
glEndQuery = reinterpret_cast<PFNGLENDQUERYPROC>(LoadEntry("glEndQuery"));
|
||||
glGenQueries = reinterpret_cast<PFNGLGENQUERIESPROC>(LoadEntry("glGenQueries"));
|
||||
glGetQueryiv = reinterpret_cast<PFNGLGETQUERYIVPROC>(LoadEntry("glGetQueryiv"));
|
||||
glGetQueryObjectiv = reinterpret_cast<PFNGLGETQUERYOBJECTIVPROC>(LoadEntry("glGetQueryObjectiv"));
|
||||
glGetQueryObjectuiv = reinterpret_cast<PFNGLGETQUERYOBJECTUIVPROC>(LoadEntry("glGetQueryObjectuiv"));
|
||||
|
||||
openGLextensions[NzOpenGL::Occlusion_Query] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
if (openGLversion >= 150)
|
||||
NazaraWarning("Failed to load core Occlusion Queries (" + NzString(e.what()) + "), loading ARB_occlusion_query...");
|
||||
|
||||
if (IsSupported("GL_ARB_occlusion_query"))
|
||||
{
|
||||
try
|
||||
{
|
||||
glBeginQuery = reinterpret_cast<PFNGLBEGINQUERYARBPROC>(LoadEntry("glBeginQueryARB"));
|
||||
glDeleteQueries = reinterpret_cast<PFNGLDELETEQUERIESARBPROC>(LoadEntry("glDeleteQueriesARB"));
|
||||
glEndQuery = reinterpret_cast<PFNGLENDQUERYARBPROC>(LoadEntry("glEndQueryARB"));
|
||||
glGenQueries = reinterpret_cast<PFNGLGENQUERIESARBPROC>(LoadEntry("glGenQueriesARB"));
|
||||
glGetQueryiv = reinterpret_cast<PFNGLGETQUERYIVARBPROC>(LoadEntry("glGetQueryivARB"));
|
||||
glGetQueryObjectiv = reinterpret_cast<PFNGLGETQUERYOBJECTIVARBPROC>(LoadEntry("glGetQueryObjectivARB"));
|
||||
glGetQueryObjectuiv = reinterpret_cast<PFNGLGETQUERYOBJECTUIVARBPROC>(LoadEntry("glGetQueryObjectuivARB"));
|
||||
|
||||
openGLextensions[NzOpenGL::Occlusion_Query] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to load ARB_occlusion_query: " + NzString(e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Texture3D
|
||||
if (IsSupported("GL_EXT_texture3D"))
|
||||
{
|
||||
try
|
||||
{
|
||||
glTexImage3D = reinterpret_cast<PFNGLTEXIMAGE3DEXTPROC>(LoadEntry("glTexImage3DEXT"));
|
||||
glTexSubImage3D = reinterpret_cast<PFNGLTEXSUBIMAGE3DEXTPROC>(LoadEntry("glTexSubImage3DEXT"));
|
||||
|
||||
openGLextensions[NzOpenGL::Texture3D] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to load EXT_texture3D: " + NzString(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************Contextes****************************************/
|
||||
|
||||
/*
|
||||
NzContextParameters::defaultMajorVersion = openGLversion/100;
|
||||
NzContextParameters::defaultMinorVersion = (openGLversion%100)/10;
|
||||
*/
|
||||
|
||||
NzContextParameters::defaultMajorVersion = std::min(openGLversion/100, 2U);
|
||||
NzContextParameters::defaultMinorVersion = std::min((openGLversion%100)/10, 1U);
|
||||
|
||||
if (!NzContext::InitializeReference())
|
||||
{
|
||||
NazaraError("Failed to initialize reference context");
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NzContextParameters::defaultShareContext = NzContext::GetReference();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzOpenGL::IsSupported(Extension extension)
|
||||
{
|
||||
return openGLextensions[extension];
|
||||
}
|
||||
|
||||
bool NzOpenGL::IsSupported(const NzString& string)
|
||||
{
|
||||
return openGLextensionSet.find(string) != openGLextensionSet.end();
|
||||
}
|
||||
|
||||
void NzOpenGL::Uninitialize()
|
||||
{
|
||||
NzContext::UninitializeReference();
|
||||
|
||||
for (bool& ext : openGLextensions)
|
||||
ext = false;
|
||||
|
||||
openGLextensionSet.clear();
|
||||
openGLversion = 0;
|
||||
|
||||
UnloadLibrary();
|
||||
}
|
||||
|
||||
PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
|
||||
PFNGLATTACHSHADERPROC glAttachShader = nullptr;
|
||||
PFNGLBEGINQUERYPROC glBeginQuery = nullptr;
|
||||
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation = nullptr;
|
||||
PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
|
||||
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr;
|
||||
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr;
|
||||
PFNGLBINDTEXTUREPROC glBindTexture = nullptr;
|
||||
PFNGLBLENDFUNCPROC glBlendFunc = nullptr;
|
||||
PFNGLBUFFERDATAPROC glBufferData = nullptr;
|
||||
PFNGLBUFFERSUBDATAPROC glBufferSubData = nullptr;
|
||||
PFNGLCLEARPROC glClear = nullptr;
|
||||
PFNGLCLEARCOLORPROC glClearColor = nullptr;
|
||||
PFNGLCLEARDEPTHPROC glClearDepth = nullptr;
|
||||
PFNGLCLEARSTENCILPROC glClearStencil = nullptr;
|
||||
PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr;
|
||||
PFNGLCREATESHADERPROC glCreateShader = nullptr;
|
||||
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = nullptr;
|
||||
PFNGLCOLORMASKPROC glColorMask = nullptr;
|
||||
PFNGLCULLFACEPROC glCullFace = nullptr;
|
||||
PFNGLCOMPILESHADERPROC glCompileShader = nullptr;
|
||||
PFNGLDELETEBUFFERSPROC glDeleteBuffers = nullptr;
|
||||
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = nullptr;
|
||||
PFNGLDELETEPROGRAMPROC glDeleteProgram = nullptr;
|
||||
PFNGLDELETEQUERIESPROC glDeleteQueries = nullptr;
|
||||
PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = nullptr;
|
||||
PFNGLDELETESHADERPROC glDeleteShader = nullptr;
|
||||
PFNGLDELETETEXTURESPROC glDeleteTextures = nullptr;
|
||||
PFNGLDEPTHFUNCPROC glDepthFunc = nullptr;
|
||||
PFNGLDEPTHMASKPROC glDepthMask = nullptr;
|
||||
PFNGLDISABLEPROC glDisable = nullptr;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = nullptr;
|
||||
PFNGLDRAWARRAYSPROC glDrawArrays = nullptr;
|
||||
PFNGLDRAWBUFFERPROC glDrawBuffer = nullptr;
|
||||
PFNGLDRAWBUFFERSPROC glDrawBuffers = nullptr;
|
||||
PFNGLDRAWELEMENTSPROC glDrawElements = nullptr;
|
||||
PFNGLENDQUERYPROC glEndQuery = nullptr;
|
||||
PFNGLFLUSHPROC glFlush = nullptr;
|
||||
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = nullptr;
|
||||
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = nullptr;
|
||||
PFNGLENABLEPROC glEnable = nullptr;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
|
||||
PFNGLGENERATEMIPMAPPROC glGenerateMipmap = nullptr;
|
||||
PFNGLGENBUFFERSPROC glGenBuffers = nullptr;
|
||||
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = nullptr;
|
||||
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = nullptr;
|
||||
PFNGLGENQUERIESPROC glGenQueries = nullptr;
|
||||
PFNGLGENTEXTURESPROC glGenTextures = nullptr;
|
||||
PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv = nullptr;
|
||||
PFNGLGETERRORPROC glGetError = nullptr;
|
||||
PFNGLGETINTEGERVPROC glGetIntegerv = nullptr;
|
||||
PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr;
|
||||
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr;
|
||||
PFNGLGETQUERYIVPROC glGetQueryiv = nullptr;
|
||||
PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv = nullptr;
|
||||
PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv = nullptr;
|
||||
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr;
|
||||
PFNGLGETSHADERIVPROC glGetShaderiv = nullptr;
|
||||
PFNGLGETSHADERSOURCEPROC glGetShaderSource = nullptr;
|
||||
PFNGLGETSTRINGPROC glGetString = nullptr;
|
||||
PFNGLGETSTRINGIPROC glGetStringi = nullptr;
|
||||
PFNGLGETTEXIMAGEPROC glGetTexImage = nullptr;
|
||||
PFNGLGETTEXPARAMETERFVPROC glGetTexParameterfv = nullptr;
|
||||
PFNGLGETTEXPARAMETERIVPROC glGetTexParameteriv = nullptr;
|
||||
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr;
|
||||
PFNGLLINKPROGRAMPROC glLinkProgram = nullptr;
|
||||
PFNGLMAPBUFFERPROC glMapBuffer = nullptr;
|
||||
PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr;
|
||||
PFNGLPOLYGONMODEPROC glPolygonMode = nullptr;
|
||||
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = nullptr;
|
||||
PFNGLSCISSORPROC glScissor = nullptr;
|
||||
PFNGLSHADERSOURCEPROC glShaderSource = nullptr;
|
||||
PFNGLSTENCILFUNCPROC glStencilFunc = nullptr;
|
||||
PFNGLSTENCILOPPROC glStencilOp = nullptr;
|
||||
PFNGLTEXIMAGE2DPROC glTexImage2D = nullptr;
|
||||
PFNGLTEXIMAGE3DEXTPROC glTexImage3D = nullptr;
|
||||
PFNGLTEXPARAMETERFPROC glTexParameterf = nullptr;
|
||||
PFNGLTEXPARAMETERIPROC glTexParameteri = nullptr;
|
||||
PFNGLTEXSUBIMAGE2DPROC glTexSubImage2D = nullptr;
|
||||
PFNGLTEXSUBIMAGE3DEXTPROC glTexSubImage3D = nullptr;
|
||||
PFNGLUNIFORM1DPROC glUniform1d = nullptr;
|
||||
PFNGLUNIFORM1FPROC glUniform1f = nullptr;
|
||||
PFNGLUNIFORM1IPROC glUniform1i = nullptr;
|
||||
PFNGLUNIFORM2DVPROC glUniform2dv = nullptr;
|
||||
PFNGLUNIFORM2FVPROC glUniform2fv = nullptr;
|
||||
PFNGLUNIFORM3DVPROC glUniform3dv = nullptr;
|
||||
PFNGLUNIFORM3FVPROC glUniform3fv = nullptr;
|
||||
PFNGLUNIFORM4DVPROC glUniform4dv = nullptr;
|
||||
PFNGLUNIFORM4FVPROC glUniform4fv = nullptr;
|
||||
PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv = nullptr;
|
||||
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = nullptr;
|
||||
PFNGLUNMAPBUFFERPROC glUnmapBuffer = nullptr;
|
||||
PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
|
||||
PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f = nullptr;
|
||||
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
|
||||
PFNGLVIEWPORTPROC glViewport = nullptr;
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat = nullptr;
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr;
|
||||
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = nullptr;
|
||||
PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT = nullptr;
|
||||
PFNWGLSWAPINTERVALEXTPROC wglSwapInterval = nullptr;
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = nullptr;
|
||||
PFNGLXSWAPINTERVALSGIPROC glXSwapInterval = nullptr;
|
||||
#endif
|
||||
29
src/Nazara/Renderer/RenderTarget.cpp
Normal file
29
src/Nazara/Renderer/RenderTarget.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzRenderTarget::~NzRenderTarget() = default;
|
||||
|
||||
bool NzRenderTarget::IsActive() const
|
||||
{
|
||||
return NazaraRenderer->GetTarget() == this;
|
||||
}
|
||||
|
||||
bool NzRenderTarget::SetActive(bool active)
|
||||
{
|
||||
if (active)
|
||||
return NazaraRenderer->SetTarget(this);
|
||||
else if (NazaraRenderer->GetTarget() == this)
|
||||
return NazaraRenderer->SetTarget(nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzRenderTarget::Desactivate()
|
||||
{
|
||||
// Seuls les target sans contextes (ex: RenderTexture) nécessitent une désactivation
|
||||
}
|
||||
156
src/Nazara/Renderer/RenderWindow.cpp
Normal file
156
src/Nazara/Renderer/RenderWindow.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/RenderWindow.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <Nazara/Renderer/ContextParameters.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
NzContextParameters invalidContextParameters;
|
||||
NzRenderTargetParameters invalidRTParameters;
|
||||
}
|
||||
|
||||
NzRenderWindow::NzRenderWindow() :
|
||||
m_context(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) :
|
||||
m_context(nullptr)
|
||||
{
|
||||
Create(mode, title, style, parameters);
|
||||
}
|
||||
|
||||
NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters) :
|
||||
m_context(nullptr)
|
||||
{
|
||||
Create(handle, parameters);
|
||||
}
|
||||
|
||||
NzRenderWindow::~NzRenderWindow()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzRenderWindow::CanActivate() const
|
||||
{
|
||||
return m_impl != nullptr && m_context != nullptr;
|
||||
}
|
||||
|
||||
bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
|
||||
{
|
||||
m_parameters = parameters;
|
||||
return NzWindow::Create(mode, title, style);
|
||||
}
|
||||
|
||||
bool NzRenderWindow::Create(NzWindowHandle handle, const NzContextParameters& parameters)
|
||||
{
|
||||
m_parameters = parameters;
|
||||
return NzWindow::Create(handle);
|
||||
}
|
||||
|
||||
void NzRenderWindow::Display()
|
||||
{
|
||||
if (m_context)
|
||||
m_context->SwapBuffers();
|
||||
}
|
||||
|
||||
void NzRenderWindow::EnableVerticalSync(bool enabled)
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
if (!m_context->SetActive(true))
|
||||
{
|
||||
NazaraError("Unable to activate context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wglSwapInterval)
|
||||
wglSwapInterval(enabled ? 1 : 0);
|
||||
else
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
if (!m_context->SetActive(true))
|
||||
{
|
||||
NazaraError("Unable to activate context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (glXSwapInterval)
|
||||
glXSwapInterval(enabled ? 1 : 0);
|
||||
else
|
||||
#else
|
||||
#error Vertical Sync is not supported on this platform
|
||||
#endif
|
||||
NazaraError("Vertical Sync is not supported on this platform");
|
||||
}
|
||||
else
|
||||
NazaraError("No context");
|
||||
}
|
||||
|
||||
NzRenderTargetParameters NzRenderWindow::GetRenderTargetParameters() const
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
const NzContextParameters& parameters = m_context->GetParameters();
|
||||
return NzRenderTargetParameters(parameters.antialiasingLevel, parameters.depthBits, parameters.stencilBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Window not created/context not initialized");
|
||||
return NzRenderTargetParameters();
|
||||
}
|
||||
}
|
||||
|
||||
NzContextParameters NzRenderWindow::GetContextParameters() const
|
||||
{
|
||||
if (m_context)
|
||||
return m_context->GetParameters();
|
||||
else
|
||||
{
|
||||
NazaraError("Window not created/context not initialized");
|
||||
return NzContextParameters();
|
||||
}
|
||||
}
|
||||
|
||||
bool NzRenderWindow::HasContext() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderWindow::Activate()
|
||||
{
|
||||
return m_context->SetActive(true);
|
||||
}
|
||||
|
||||
void NzRenderWindow::OnClose()
|
||||
{
|
||||
delete m_context;
|
||||
}
|
||||
|
||||
bool NzRenderWindow::OnCreate()
|
||||
{
|
||||
m_parameters.doubleBuffered = true;
|
||||
m_parameters.window = GetHandle();
|
||||
m_context = new NzContext;
|
||||
if (!m_context->Create(m_parameters))
|
||||
{
|
||||
NazaraError("Failed not create context");
|
||||
delete m_context;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EnableVerticalSync(false);
|
||||
|
||||
#if NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION
|
||||
if (!SetActive(true)) // Les fenêtres s'activent à la création
|
||||
NazaraWarning("Failed to activate window");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
248
src/Nazara/Renderer/Renderer.cpp
Normal file
248
src/Nazara/Renderer/Renderer.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp> // Pour éviter une redéfinition de WIN32_LEAN_AND_MEAN
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/BufferImpl.hpp>
|
||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzRenderer::NzRenderer() :
|
||||
m_indexBuffer(nullptr),
|
||||
m_target(nullptr),
|
||||
m_shader(nullptr)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (s_instance)
|
||||
throw std::runtime_error("Renderer already instanced");
|
||||
#endif
|
||||
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
NzRenderer::~NzRenderer()
|
||||
{
|
||||
Uninitialize();
|
||||
|
||||
s_instance = nullptr;
|
||||
}
|
||||
|
||||
void NzRenderer::Clear(nzRendererClear flags)
|
||||
{
|
||||
#if NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags)
|
||||
{
|
||||
GLenum mask = 0;
|
||||
|
||||
if (flags & nzRendererClear_Color)
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
|
||||
if (flags & nzRendererClear_Depth)
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
if (flags & nzRendererClear_Stencil)
|
||||
mask |= GL_STENCIL_BUFFER_BIT;
|
||||
|
||||
glClear(mask);
|
||||
}
|
||||
}
|
||||
|
||||
NzShader* NzRenderer::GetShader() const
|
||||
{
|
||||
return m_shader;
|
||||
}
|
||||
|
||||
NzRenderTarget* NzRenderer::GetTarget() const
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
bool NzRenderer::HasCapability(nzRendererCap capability) const
|
||||
{
|
||||
return m_capabilities[capability];
|
||||
}
|
||||
|
||||
bool NzRenderer::Initialize()
|
||||
{
|
||||
if (NzOpenGL::Initialize())
|
||||
{
|
||||
m_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter);
|
||||
m_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64);
|
||||
m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 2.0
|
||||
m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0
|
||||
m_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D);
|
||||
m_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3
|
||||
m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
|
||||
m_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void NzRenderer::SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a)
|
||||
{
|
||||
#if NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glClearColor(r/255.f, g/255.f, b/255.f, a/255.f);
|
||||
}
|
||||
|
||||
void NzRenderer::SetClearDepth(double depth)
|
||||
{
|
||||
#if NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glClearDepth(depth);
|
||||
}
|
||||
|
||||
void NzRenderer::SetClearStencil(unsigned int value)
|
||||
{
|
||||
#if NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glClearStencil(value);
|
||||
}
|
||||
|
||||
bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
|
||||
{
|
||||
if (indexBuffer == m_indexBuffer)
|
||||
return true;
|
||||
|
||||
// OpenGL ne nécessite pas de débinder un index buffer pour ne pas l'utiliser
|
||||
if (indexBuffer)
|
||||
indexBuffer->GetBuffer()->m_impl->Bind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderer::SetShader(NzShader* shader)
|
||||
{
|
||||
if (shader == m_shader)
|
||||
return true;
|
||||
|
||||
if (shader)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!shader->IsCompiled())
|
||||
{
|
||||
NazaraError("Shader is not compiled");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!shader->m_impl->Bind())
|
||||
{
|
||||
NazaraError("Failed to bind shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_shader = shader;
|
||||
}
|
||||
else if (m_shader)
|
||||
{
|
||||
m_shader->m_impl->Unbind();
|
||||
m_shader = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderer::SetTarget(NzRenderTarget* target)
|
||||
{
|
||||
if (target == m_target)
|
||||
return true;
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (target && !target->CanActivate())
|
||||
{
|
||||
NazaraError("Target cannot be activated");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_target && !m_target->HasContext())
|
||||
m_target->Desactivate();
|
||||
|
||||
if (target)
|
||||
{
|
||||
if (target->Activate())
|
||||
m_target = target;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to activate target");
|
||||
m_target = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_target = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer)
|
||||
{
|
||||
if (m_vertexBuffer == vertexBuffer)
|
||||
return true;
|
||||
|
||||
m_vertexBuffer = vertexBuffer;
|
||||
m_vertexBufferUpdated = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzRenderer::Uninitialize()
|
||||
{
|
||||
NzOpenGL::Uninitialize();
|
||||
}
|
||||
|
||||
#if NAZARA_RENDERER_SINGLETON
|
||||
void NzRenderer::Destroy()
|
||||
{
|
||||
delete s_instance;
|
||||
s_instance = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
NzRenderer* NzRenderer::Instance()
|
||||
{
|
||||
#if NAZARA_RENDERER_SINGLETON
|
||||
if (!s_instance)
|
||||
s_instance = new NzRenderer;
|
||||
#elif defined(NAZARA_DEBUG)
|
||||
if (!s_instance)
|
||||
NazaraError("Renderer not instanced");
|
||||
#endif
|
||||
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
NzRenderer* NzRenderer::s_instance = nullptr;
|
||||
391
src/Nazara/Renderer/Shader.cpp
Normal file
391
src/Nazara/Renderer/Shader.cpp
Normal file
@@ -0,0 +1,391 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Renderer/GLSLShader.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzShader::NzShader() :
|
||||
m_impl(nullptr),
|
||||
m_compiled(false)
|
||||
{
|
||||
}
|
||||
|
||||
NzShader::NzShader(nzShaderLanguage language) :
|
||||
m_impl(nullptr),
|
||||
m_compiled(false)
|
||||
{
|
||||
Create(language);
|
||||
|
||||
#if NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Failed to create shader");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NzShader::~NzShader()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool NzShader::Create(nzShaderLanguage language)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
switch (language)
|
||||
{
|
||||
case nzShaderLanguage_Cg:
|
||||
NazaraError("Cg support is not implemented yet");
|
||||
return false;
|
||||
|
||||
case nzShaderLanguage_GLSL:
|
||||
m_impl = new NzGLSLShader(this);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Shader language not handled (0x" + NzString::Number(language, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_impl->Create())
|
||||
{
|
||||
NazaraError("Failed to create shader");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzShader::Compile()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_impl->Compile())
|
||||
{
|
||||
m_compiled = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void NzShader::Destroy()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NzString NzShader::GetLog() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NzString error = "Shader not created";
|
||||
NazaraError(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetLog();
|
||||
}
|
||||
|
||||
nzShaderLanguage NzShader::GetLanguage() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NzString error = "Shader not created";
|
||||
NazaraError(error);
|
||||
|
||||
return nzShaderLanguage_Unknown;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetLanguage();
|
||||
}
|
||||
|
||||
NzString NzShader::GetSourceCode(nzShaderType type) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NzString error = "Shader not created";
|
||||
NazaraError(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
NzString error = "Shader type not supported";
|
||||
NazaraError(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!m_impl->IsLoaded(type))
|
||||
{
|
||||
NzString error = "Shader not loaded";
|
||||
NazaraError(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetSourceCode(type);
|
||||
}
|
||||
|
||||
bool NzShader::IsCompiled() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_compiled;
|
||||
}
|
||||
|
||||
bool NzShader::IsLoaded(nzShaderType type) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
NazaraError("Shader type not supported");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->IsLoaded(type);
|
||||
}
|
||||
|
||||
bool NzShader::Load(nzShaderType type, const NzString& source)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
NazaraError("Shader type not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source.IsEmpty())
|
||||
{
|
||||
NazaraError("Empty source code");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_impl->IsLoaded(type))
|
||||
{
|
||||
NazaraError("Shader already loaded");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->Load(type, source);
|
||||
}
|
||||
|
||||
bool NzShader::LoadFromFile(nzShaderType type, const NzString& filePath)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
NazaraError("Shader type not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_impl->IsLoaded(type))
|
||||
{
|
||||
NazaraError("Shader already loaded");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
NzFile file(filePath);
|
||||
if (!file.Open(NzFile::ReadOnly | NzFile::Text))
|
||||
{
|
||||
NazaraError("Failed to open \"" + filePath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
NzString source;
|
||||
unsigned int length = file.GetSize();
|
||||
source.Resize(length);
|
||||
|
||||
if (file.Read(&source[0], sizeof(char), length) != length*sizeof(char))
|
||||
{
|
||||
NazaraError("Failed to read shader file");
|
||||
return false;
|
||||
}
|
||||
|
||||
file.Close();
|
||||
|
||||
return m_impl->Load(type, source);
|
||||
}
|
||||
|
||||
bool NzShader::SendBoolean(const NzString& name, bool value)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendBoolean(name, value);
|
||||
}
|
||||
|
||||
bool NzShader::SendDouble(const NzString& name, double value)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NazaraRenderer->HasCapability(nzRendererCap_FP64))
|
||||
{
|
||||
NazaraError("FP64 is not supported");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendDouble(name, value);
|
||||
}
|
||||
|
||||
bool NzShader::SendFloat(const NzString& name, float value)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendFloat(name, value);
|
||||
}
|
||||
|
||||
bool NzShader::SendInteger(const NzString& name, int value)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendInteger(name, value);
|
||||
}
|
||||
|
||||
bool NzShader::SendMatrix(const NzString& name, const NzMatrix4d& matrix)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NazaraRenderer->HasCapability(nzRendererCap_FP64))
|
||||
{
|
||||
NazaraError("FP64 is not supported");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendMatrix(name, matrix);
|
||||
}
|
||||
|
||||
bool NzShader::SendMatrix(const NzString& name, const NzMatrix4f& matrix)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendMatrix(name, matrix);
|
||||
}
|
||||
|
||||
bool NzShader::IsLanguageSupported(nzShaderLanguage language)
|
||||
{
|
||||
switch (language)
|
||||
{
|
||||
case nzShaderLanguage_Cg:
|
||||
return false; // ??
|
||||
|
||||
case nzShaderLanguage_GLSL:
|
||||
return true;
|
||||
|
||||
default:
|
||||
NazaraError("Shader language not handled (0x" + NzString::Number(language, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzShader::IsTypeSupported(nzShaderType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case nzShaderType_Fragment:
|
||||
case nzShaderType_Vertex:
|
||||
return true;
|
||||
|
||||
case nzShaderType_Geometry:
|
||||
return false; // ??
|
||||
|
||||
default:
|
||||
NazaraError("Shader type not handled (0x" + NzString::Number(type, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
7
src/Nazara/Renderer/ShaderImpl.cpp
Normal file
7
src/Nazara/Renderer/ShaderImpl.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||
|
||||
NzShaderImpl::~NzShaderImpl() = default;
|
||||
43
src/Nazara/Renderer/ShaderImpl.hpp
Normal file
43
src/Nazara/Renderer/ShaderImpl.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERIMPL_HPP
|
||||
#define NAZARA_SHADERIMPL_HPP
|
||||
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
|
||||
class NzShaderImpl
|
||||
{
|
||||
public:
|
||||
NzShaderImpl() = default;
|
||||
virtual ~NzShaderImpl();
|
||||
|
||||
virtual bool Bind() = 0;
|
||||
|
||||
virtual bool Compile() = 0;
|
||||
virtual bool Create() = 0;
|
||||
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
virtual NzString GetLog() const = 0;
|
||||
virtual nzShaderLanguage GetLanguage() const = 0;
|
||||
virtual NzString GetSourceCode(nzShaderType type) const = 0;
|
||||
|
||||
virtual bool IsLoaded(nzShaderType type) const = 0;
|
||||
|
||||
virtual bool Load(nzShaderType type, const NzString& source) = 0;
|
||||
|
||||
virtual bool SendBoolean(const NzString& name, bool value) = 0;
|
||||
virtual bool SendDouble(const NzString& name, double value) = 0;
|
||||
virtual bool SendFloat(const NzString& name, float value) = 0;
|
||||
virtual bool SendInteger(const NzString& name, int value) = 0;
|
||||
virtual bool SendMatrix(const NzString& name, const NzMatrix4d& matrix) = 0;
|
||||
virtual bool SendMatrix(const NzString& name, const NzMatrix4f& matrix) = 0;
|
||||
|
||||
virtual void Unbind() = 0;
|
||||
};
|
||||
|
||||
#endif // NAZARA_SHADERIMPL_HPP
|
||||
113
src/Nazara/Renderer/SoftwareBuffer.cpp
Normal file
113
src/Nazara/Renderer/SoftwareBuffer.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/SoftwareBuffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
GLenum bufferTarget[] = {
|
||||
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index,
|
||||
GL_ARRAY_BUFFER, // nzBufferType_Vertex
|
||||
};
|
||||
}
|
||||
|
||||
NzSoftwareBuffer::NzSoftwareBuffer(NzBuffer* parent, nzBufferType type) :
|
||||
m_type(type)
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
NzSoftwareBuffer::~NzSoftwareBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void NzSoftwareBuffer::Bind()
|
||||
{
|
||||
glBindBuffer(bufferTarget[m_type], 0);
|
||||
}
|
||||
|
||||
bool NzSoftwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage)
|
||||
{
|
||||
NazaraUnused(usage);
|
||||
|
||||
// Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs
|
||||
try
|
||||
{
|
||||
m_buffer = new nzUInt8[length*typeSize];
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to allocate software buffer (" + NzString(e.what()) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
m_length = length;
|
||||
m_locked = false;
|
||||
m_typeSize = typeSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzSoftwareBuffer::Destroy()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (m_locked)
|
||||
{
|
||||
NazaraError("Buffer already locked");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::memcpy(&m_buffer[offset*m_typeSize], data, length*m_typeSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzSoftwareBuffer::IsHardware() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void* NzSoftwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
NazaraUnused(length);
|
||||
NazaraUnused(lock);
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (m_locked)
|
||||
{
|
||||
NazaraError("Buffer already locked");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_locked = true;
|
||||
|
||||
return &m_buffer[offset*m_typeSize];
|
||||
}
|
||||
|
||||
bool NzSoftwareBuffer::Unlock()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_locked)
|
||||
{
|
||||
NazaraError("Buffer not locked");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_locked = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
39
src/Nazara/Renderer/SoftwareBuffer.hpp
Normal file
39
src/Nazara/Renderer/SoftwareBuffer.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SOFTWAREBUFFER_HPP
|
||||
#define NAZARA_SOFTWAREBUFFER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Renderer/BufferImpl.hpp>
|
||||
|
||||
class NzSoftwareBuffer : public NzBufferImpl
|
||||
{
|
||||
public:
|
||||
NzSoftwareBuffer(NzBuffer* parent, nzBufferType type);
|
||||
~NzSoftwareBuffer();
|
||||
|
||||
void Bind();
|
||||
|
||||
bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static);
|
||||
void Destroy();
|
||||
|
||||
bool Fill(const void* data, unsigned int offset, unsigned int length);
|
||||
|
||||
bool IsHardware() const;
|
||||
|
||||
void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0);
|
||||
bool Unlock();
|
||||
|
||||
private:
|
||||
nzBufferType m_type;
|
||||
nzUInt8 m_typeSize;
|
||||
nzUInt8* m_buffer;
|
||||
bool m_locked;
|
||||
unsigned int m_length;
|
||||
};
|
||||
|
||||
#endif // NAZARA_SOFTWAREBUFFER_HPP
|
||||
106
src/Nazara/Renderer/VertexBuffer.cpp
Normal file
106
src/Nazara/Renderer/VertexBuffer.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/VertexBuffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzVertexBuffer::NzVertexBuffer(NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount) :
|
||||
m_buffer(buffer),
|
||||
m_ownsBuffer(false),
|
||||
m_startVertex(startVertex),
|
||||
m_vertexCount(vertexCount)
|
||||
{
|
||||
m_buffer->AddResourceReference();
|
||||
}
|
||||
|
||||
NzVertexBuffer::NzVertexBuffer(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) :
|
||||
m_ownsBuffer(true),
|
||||
m_startVertex(0),
|
||||
m_vertexCount(length)
|
||||
{
|
||||
m_buffer = new NzBuffer(nzBufferType_Vertex, length, typeSize, usage);
|
||||
m_buffer->AddResourceReference();
|
||||
m_buffer->SetPersistent(false);
|
||||
}
|
||||
|
||||
NzVertexBuffer::NzVertexBuffer(const NzVertexBuffer& vertexBuffer) :
|
||||
m_ownsBuffer(vertexBuffer.m_ownsBuffer),
|
||||
m_startVertex(vertexBuffer.m_startVertex),
|
||||
m_vertexCount(vertexBuffer.m_vertexCount)
|
||||
{
|
||||
if (m_ownsBuffer)
|
||||
{
|
||||
m_buffer = new NzBuffer(nzBufferType_Vertex, vertexBuffer.m_buffer->GetLength(), vertexBuffer.m_buffer->GetSize(), vertexBuffer.m_buffer->GetUsage());
|
||||
m_buffer->AddResourceReference();
|
||||
m_buffer->SetPersistent(false);
|
||||
m_buffer->CopyContent(*vertexBuffer.m_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer = vertexBuffer.m_buffer;
|
||||
m_buffer->AddResourceReference();
|
||||
}
|
||||
}
|
||||
|
||||
NzVertexBuffer::~NzVertexBuffer()
|
||||
{
|
||||
m_buffer->RemoveResourceReference();
|
||||
}
|
||||
|
||||
bool NzVertexBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (offset+length > m_vertexCount)
|
||||
{
|
||||
NazaraError("Exceeding virtual buffer size");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Fill(data, m_startVertex+offset, length);
|
||||
}
|
||||
|
||||
NzBuffer* NzVertexBuffer::GetBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
unsigned int NzVertexBuffer::GetStartVertex() const
|
||||
{
|
||||
return m_startVertex;
|
||||
}
|
||||
|
||||
nzUInt8 NzVertexBuffer::GetTypeSize() const
|
||||
{
|
||||
return m_buffer->GetTypeSize();
|
||||
}
|
||||
|
||||
unsigned int NzVertexBuffer::GetVertexCount() const
|
||||
{
|
||||
return m_vertexCount;
|
||||
}
|
||||
|
||||
bool NzVertexBuffer::IsHardware() const
|
||||
{
|
||||
return m_buffer->IsHardware();
|
||||
}
|
||||
|
||||
void* NzVertexBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (offset+length > m_vertexCount)
|
||||
{
|
||||
NazaraError("Exceeding virtual buffer size");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Lock(lock, m_startVertex+offset, (length) ? length : m_vertexCount-offset);
|
||||
}
|
||||
|
||||
bool NzVertexBuffer::Unlock()
|
||||
{
|
||||
return m_buffer->Unlock();
|
||||
}
|
||||
126
src/Nazara/Renderer/VertexDeclaration.cpp
Normal file
126
src/Nazara/Renderer/VertexDeclaration.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/VertexDeclaration.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned int size[] =
|
||||
{
|
||||
4, // nzElementType_Color
|
||||
8, // nzElementType_Double1
|
||||
16, // nzElementType_Double2
|
||||
24, // nzElementType_Double3
|
||||
32, // nzElementType_Double4
|
||||
4, // nzElementType_Float1
|
||||
8, // nzElementType_Float2
|
||||
12, // nzElementType_Float3
|
||||
16 // nzElementType_Float4
|
||||
};
|
||||
}
|
||||
|
||||
bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount)
|
||||
{
|
||||
for (unsigned int i = 0; i < elementCount; ++i)
|
||||
{
|
||||
unsigned int stream = elements[i].stream;
|
||||
|
||||
if (stream >= m_streams.size())
|
||||
m_streams.resize(stream+1);
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
else // Seulement si le stream ne vient pas d'être créé (Autrement c'est inutile)
|
||||
{
|
||||
bool fp64 = NazaraRenderer->HasCapability(nzRendererCap_FP64);
|
||||
|
||||
for (unsigned int j = 0; j < i; ++j)
|
||||
{
|
||||
if (elements[j].stream == stream && elements[j].usage == elements[i].usage && elements[j].usageIndex == elements[i].usageIndex)
|
||||
{
|
||||
NazaraError("Element usage (" + NzString::Number(elements[j].usage, 16) + ") collision on stream " + NzString::Number(stream) + " with usage index " + NzString::Number(elements[j].usageIndex));
|
||||
return false;
|
||||
}
|
||||
else if (!fp64 && elements[j].type >= nzElementType_Double1 && elements[j].type <= nzElementType_Double4)
|
||||
{
|
||||
NazaraError("FP64 not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Element element;
|
||||
element.offset = elements[i].offset;
|
||||
element.type = elements[i].type;
|
||||
element.usage = elements[i].usage;
|
||||
element.usageIndex = elements[i].usageIndex;
|
||||
|
||||
m_streams[stream].elements.push_back(element);
|
||||
}
|
||||
|
||||
for (Stream& stream : m_streams)
|
||||
{
|
||||
stream.stride = 0;
|
||||
for (const Element& element : stream.elements)
|
||||
stream.stride += size[element.type];
|
||||
|
||||
#if NAZARA_RENDERER_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32
|
||||
stream.stride = ((static_cast<int>(stream.stride)-1)/32+1)*32;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const NzVertexDeclaration::Element* NzVertexDeclaration::GetElement(unsigned int i, unsigned int stream) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (stream >= m_streams.size())
|
||||
{
|
||||
NazaraError("Stream out of range");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (i >= m_streams[stream].elements.size())
|
||||
{
|
||||
NazaraError("Index out of range");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return &m_streams[stream].elements[i];
|
||||
}
|
||||
|
||||
unsigned int NzVertexDeclaration::GetElementCount(unsigned int stream) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (stream >= m_streams.size())
|
||||
{
|
||||
NazaraError("Stream out of range");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_streams[stream].elements.size();
|
||||
}
|
||||
|
||||
unsigned int NzVertexDeclaration::GetStreamCount() const
|
||||
{
|
||||
return m_streams.size();
|
||||
}
|
||||
|
||||
unsigned int NzVertexDeclaration::GetStride(unsigned int stream) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (stream >= m_streams.size())
|
||||
{
|
||||
NazaraError("Stream out of range");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_streams[stream].stride;
|
||||
}
|
||||
257
src/Nazara/Renderer/Win32/ContextImpl.cpp
Normal file
257
src/Nazara/Renderer/Win32/ContextImpl.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Lock.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
NzContextImpl::NzContextImpl()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzContextImpl::Activate()
|
||||
{
|
||||
return wglMakeCurrent(m_deviceContext, m_context);
|
||||
}
|
||||
|
||||
bool NzContextImpl::Create(NzContextParameters& parameters)
|
||||
{
|
||||
if (parameters.window)
|
||||
{
|
||||
m_window = static_cast<HWND>(parameters.window);
|
||||
m_ownsWindow = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
ShowWindow(m_window, SW_HIDE);
|
||||
m_ownsWindow = true;
|
||||
|
||||
if (!m_window)
|
||||
{
|
||||
NazaraError("Failed to create window");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_deviceContext = GetDC(m_window);
|
||||
if (!m_deviceContext)
|
||||
{
|
||||
NazaraError("Failed to get device context");
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
int pixelFormat = 0;
|
||||
if (parameters.antialiasingLevel > 0)
|
||||
{
|
||||
if (wglChoosePixelFormat)
|
||||
{
|
||||
bool valid;
|
||||
UINT numFormats;
|
||||
|
||||
int attributes[] = {
|
||||
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
||||
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
|
||||
WGL_COLOR_BITS_ARB, (parameters.bitsPerPixel == 32) ? 24 : parameters.bitsPerPixel,
|
||||
WGL_ALPHA_BITS_ARB, (parameters.bitsPerPixel == 32) ? 8 : 0,
|
||||
WGL_DEPTH_BITS_ARB, parameters.depthBits,
|
||||
WGL_STENCIL_BITS_ARB, parameters.stencilBits,
|
||||
WGL_DOUBLE_BUFFER_ARB, (parameters.doubleBuffered) ? GL_TRUE : GL_FALSE,
|
||||
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
|
||||
WGL_SAMPLES_ARB, parameters.antialiasingLevel,
|
||||
0, 0
|
||||
};
|
||||
|
||||
do
|
||||
{
|
||||
valid = wglChoosePixelFormat(m_deviceContext, attributes, nullptr, 1, &pixelFormat, &numFormats);
|
||||
}
|
||||
while ((!valid || numFormats == 0) && --attributes[19] > 0);
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
NazaraWarning("Could not find a format matching requirements, disabling antialiasing...");
|
||||
pixelFormat = 0;
|
||||
}
|
||||
|
||||
parameters.antialiasingLevel = attributes[19];
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraWarning("Antialiasing is not supported");
|
||||
parameters.antialiasingLevel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PIXELFORMATDESCRIPTOR descriptor;
|
||||
ZeroMemory(&descriptor, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
descriptor.nVersion = 1;
|
||||
|
||||
if (pixelFormat == 0)
|
||||
{
|
||||
descriptor.cColorBits = parameters.bitsPerPixel;
|
||||
descriptor.cDepthBits = parameters.depthBits;
|
||||
descriptor.cStencilBits = parameters.stencilBits;
|
||||
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
descriptor.iPixelType = PFD_TYPE_RGBA;
|
||||
|
||||
if (parameters.bitsPerPixel == 32)
|
||||
descriptor.cAlphaBits = 8;
|
||||
|
||||
if (parameters.doubleBuffered)
|
||||
descriptor.dwFlags |= PFD_DOUBLEBUFFER;
|
||||
|
||||
pixelFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
|
||||
if (pixelFormat == 0)
|
||||
{
|
||||
NazaraError("Failed to choose pixel format");
|
||||
Destroy();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor))
|
||||
{
|
||||
NazaraError("Failed to set pixel format");
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Arrivé ici, tout est créé, nous récupérons donc les paramètres actuels du contexte
|
||||
if (DescribePixelFormat(m_deviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &descriptor) != 0)
|
||||
{
|
||||
parameters.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits;
|
||||
parameters.depthBits = descriptor.cDepthBits;
|
||||
parameters.stencilBits = descriptor.cDepthBits;
|
||||
}
|
||||
else
|
||||
NazaraWarning("Failed to get context's parameters");
|
||||
|
||||
HGLRC shareContext = (parameters.shared) ? static_cast<NzContextImpl*>(parameters.shareContext->m_impl)->m_context : nullptr;
|
||||
|
||||
std::cout << "Context version: " << (int) parameters.majorVersion << '.' << (int) parameters.minorVersion << std::endl;
|
||||
std::cout << "Active context: " << wglGetCurrentContext() << std::endl;
|
||||
|
||||
m_context = nullptr;
|
||||
if (wglCreateContextAttribs)
|
||||
{
|
||||
std::cout << "wglCreateContextAttribs" << std::endl;
|
||||
|
||||
/*int attributes[] = {
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, parameters.majorVersion,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, parameters.minorVersion,
|
||||
WGL_CONTEXT_FLAGS_ARB, (parameters.compatibilityProfile) ? 0 : WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
0
|
||||
};*/
|
||||
int attributes[4*2+1];
|
||||
int* attrib = attributes;
|
||||
|
||||
*attrib++ = WGL_CONTEXT_MAJOR_VERSION_ARB;
|
||||
*attrib++ = parameters.majorVersion;
|
||||
|
||||
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
|
||||
*attrib++ = parameters.minorVersion;
|
||||
|
||||
if (parameters.majorVersion >= 3)
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
|
||||
if (parameters.compatibilityProfile)
|
||||
*attrib++ = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||
else
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||
|
||||
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
|
||||
*attrib++ = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||
}
|
||||
}
|
||||
|
||||
*attrib++ = 0;
|
||||
|
||||
m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes);
|
||||
|
||||
if (m_context)
|
||||
std::cout << "Context created with success ! Pointer: " << m_context << std::endl;
|
||||
else
|
||||
std::cout << "wglCreateContextAttribs failed ! (glGetError(): " << glGetError() << ") " << std::endl;
|
||||
}
|
||||
|
||||
if (!m_context)
|
||||
{
|
||||
std::cout << "wglCreateContext" << std::endl;
|
||||
|
||||
m_context = wglCreateContext(m_deviceContext);
|
||||
if (m_context)
|
||||
std::cout << "Context created with success ! Pointer: " << m_context << std::endl;
|
||||
else
|
||||
std::cout << "wglCreateContext failed ! (glGetError(): " << glGetError() << ") " << std::endl;
|
||||
|
||||
if (shareContext)
|
||||
{
|
||||
std::cout << "Sharing context with context " << shareContext << std::endl;
|
||||
// wglShareLists n'est pas thread-safe (source: SFML)
|
||||
static NzMutex mutex;
|
||||
NzLock lock(mutex);
|
||||
|
||||
if (wglShareLists(shareContext, m_context))
|
||||
std::cout << "Success !" << std::endl;
|
||||
else
|
||||
{
|
||||
std::cout << "Failed !" << std::endl;
|
||||
NazaraWarning("Failed to share the context: " + NzGetLastSystemError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_context)
|
||||
{
|
||||
NazaraError("Failed to create context");
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzContextImpl::Destroy()
|
||||
{
|
||||
if (m_context)
|
||||
wglDeleteContext(m_context);
|
||||
|
||||
if (m_deviceContext)
|
||||
ReleaseDC(m_window, m_deviceContext);
|
||||
|
||||
if (m_ownsWindow)
|
||||
DestroyWindow(m_window);
|
||||
}
|
||||
|
||||
bool NzContextImpl::IsActive() const
|
||||
{
|
||||
return wglGetCurrentContext() == m_context;
|
||||
}
|
||||
|
||||
void NzContextImpl::SwapBuffers()
|
||||
{
|
||||
::SwapBuffers(m_deviceContext);
|
||||
}
|
||||
|
||||
bool NzContextImpl::Desactivate()
|
||||
{
|
||||
return wglMakeCurrent(nullptr, nullptr);
|
||||
}
|
||||
|
||||
33
src/Nazara/Renderer/Win32/ContextImpl.hpp
Normal file
33
src/Nazara/Renderer/Win32/ContextImpl.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_CONTEXTIMPL_HPP
|
||||
#define NAZARA_CONTEXTIMPL_HPP
|
||||
|
||||
#include <Nazara/Renderer/ContextParameters.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzContextImpl
|
||||
{
|
||||
public:
|
||||
NzContextImpl();
|
||||
|
||||
bool Activate();
|
||||
bool Create(NzContextParameters& parameters);
|
||||
void Destroy();
|
||||
bool IsActive() const;
|
||||
void SwapBuffers();
|
||||
|
||||
static bool Desactivate();
|
||||
|
||||
private:
|
||||
HDC m_deviceContext;
|
||||
HGLRC m_context;
|
||||
HWND m_window;
|
||||
bool m_ownsWindow;
|
||||
};
|
||||
|
||||
#endif // NAZARA_CONTEXTIMPL_HPP
|
||||
29
src/Nazara/Utility/Debug/Leaks.cpp
Normal file
29
src/Nazara/Utility/Debug/Leaks.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Config.hpp>
|
||||
#if NAZARA_UTILITY_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
|
||||
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
|
||||
#include <new>
|
||||
|
||||
void* operator new(std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, true);
|
||||
}
|
||||
|
||||
void operator delete(void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, true);
|
||||
}
|
||||
#endif
|
||||
20
src/Nazara/Utility/Keyboard.cpp
Normal file
20
src/Nazara/Utility/Keyboard.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Keyboard.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Utility/Win32/InputImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
#include <Nazara/Utility/Linux/InputImpl.hpp>
|
||||
#else
|
||||
#error Lack of implementation: Keyboard
|
||||
#endif
|
||||
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
bool NzKeyboard::IsKeyPressed(Key key)
|
||||
{
|
||||
return NzEventImpl::IsKeyPressed(key);
|
||||
}
|
||||
50
src/Nazara/Utility/Mouse.cpp
Normal file
50
src/Nazara/Utility/Mouse.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Mouse.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Utility/Win32/InputImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
#include <Nazara/Utility/Linux/InputImpl.hpp>
|
||||
#else
|
||||
#error Lack of implementation: Mouse
|
||||
#endif
|
||||
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
NzVector2i NzMouse::GetPosition()
|
||||
{
|
||||
return NzEventImpl::GetMousePosition();
|
||||
}
|
||||
|
||||
NzVector2i NzMouse::GetPosition(const NzWindow& relativeTo)
|
||||
{
|
||||
return NzEventImpl::GetMousePosition(relativeTo);
|
||||
}
|
||||
|
||||
bool NzMouse::IsButtonPressed(Button button)
|
||||
{
|
||||
return NzEventImpl::IsMouseButtonPressed(button);
|
||||
}
|
||||
|
||||
void NzMouse::SetPosition(const NzVector2i& position)
|
||||
{
|
||||
NzEventImpl::SetMousePosition(position.x, position.y);
|
||||
}
|
||||
|
||||
void NzMouse::SetPosition(const NzVector2i& position, const NzWindow& relativeTo)
|
||||
{
|
||||
NzEventImpl::SetMousePosition(position.x, position.y, relativeTo);
|
||||
}
|
||||
|
||||
void NzMouse::SetPosition(int x, int y)
|
||||
{
|
||||
NzEventImpl::SetMousePosition(x, y);
|
||||
}
|
||||
|
||||
void NzMouse::SetPosition(int x, int y, const NzWindow& relativeTo)
|
||||
{
|
||||
NzEventImpl::SetMousePosition(x, y, relativeTo);
|
||||
}
|
||||
47
src/Nazara/Utility/Resource.cpp
Normal file
47
src/Nazara/Utility/Resource.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Resource.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Utility/Config.hpp>
|
||||
|
||||
NzResource::NzResource(bool persistent) :
|
||||
m_resourcePersistent(persistent),
|
||||
m_resourceReferenceCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
NzResource::~NzResource() = default;
|
||||
|
||||
void NzResource::AddResourceReference() const
|
||||
{
|
||||
m_resourceReferenceCount++;
|
||||
}
|
||||
|
||||
bool NzResource::IsPersistent() const
|
||||
{
|
||||
return m_resourcePersistent;
|
||||
}
|
||||
|
||||
void NzResource::RemoveResourceReference() const
|
||||
{
|
||||
#if NAZARA_UTILITY_SAFE
|
||||
if (m_resourceReferenceCount == 0)
|
||||
{
|
||||
NazaraError("Impossible to remove reference (Ref. counter is already 0)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (--m_resourceReferenceCount == 0 && !m_resourcePersistent)
|
||||
delete this;
|
||||
}
|
||||
|
||||
void NzResource::SetPersistent(bool persistent)
|
||||
{
|
||||
m_resourcePersistent = persistent;
|
||||
|
||||
if (!persistent && m_resourceReferenceCount == 0)
|
||||
delete this;
|
||||
}
|
||||
92
src/Nazara/Utility/VideoMode.cpp
Normal file
92
src/Nazara/Utility/VideoMode.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/VideoMode.hpp>
|
||||
#include <Nazara/Utility/VideoModeImpl.hpp>
|
||||
#include <algorithm>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
NzVideoMode::NzVideoMode() :
|
||||
bitsPerPixel(0),
|
||||
height(0),
|
||||
width(0)
|
||||
{
|
||||
}
|
||||
|
||||
NzVideoMode::NzVideoMode(unsigned int w, unsigned int h, nzUInt8 bpp) :
|
||||
bitsPerPixel(bpp),
|
||||
height(h),
|
||||
width(w)
|
||||
{
|
||||
}
|
||||
|
||||
bool NzVideoMode::IsFullscreenValid() const
|
||||
{
|
||||
const std::vector<NzVideoMode>& modes = GetFullscreenModes();
|
||||
|
||||
return std::binary_search(modes.begin(), modes.end(), *this, std::greater<NzVideoMode>());
|
||||
}
|
||||
|
||||
NzVideoMode NzVideoMode::GetDesktopMode()
|
||||
{
|
||||
return NzVideoModeImpl::GetDesktopMode();
|
||||
}
|
||||
|
||||
const std::vector<NzVideoMode>& NzVideoMode::GetFullscreenModes()
|
||||
{
|
||||
static std::vector<NzVideoMode> modes;
|
||||
if (modes.empty())
|
||||
{
|
||||
NzVideoModeImpl::GetFullscreenModes(modes);
|
||||
std::sort(modes.begin(), modes.end(), std::greater<NzVideoMode>());
|
||||
}
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
bool operator==(const NzVideoMode& left, const NzVideoMode& right)
|
||||
{
|
||||
return left.width == right.width && left.height == right.height && left.bitsPerPixel == right.bitsPerPixel;
|
||||
}
|
||||
|
||||
bool operator!=(const NzVideoMode& left, const NzVideoMode& right)
|
||||
{
|
||||
return left.width != right.width || left.height != right.height || left.bitsPerPixel != right.bitsPerPixel;
|
||||
}
|
||||
|
||||
bool operator<(const NzVideoMode& left, const NzVideoMode& right)
|
||||
{
|
||||
if (left.bitsPerPixel == right.bitsPerPixel)
|
||||
{
|
||||
if (left.width == right.width)
|
||||
return left.height < right.height;
|
||||
else
|
||||
return left.width < right.width;
|
||||
}
|
||||
else
|
||||
return left.bitsPerPixel < right.bitsPerPixel;
|
||||
}
|
||||
|
||||
bool operator<=(const NzVideoMode& left, const NzVideoMode& right)
|
||||
{
|
||||
if (left.bitsPerPixel == right.bitsPerPixel)
|
||||
{
|
||||
if (left.width == right.width)
|
||||
return left.height <= right.height;
|
||||
else
|
||||
return left.width < right.width;
|
||||
}
|
||||
else
|
||||
return left.bitsPerPixel < right.bitsPerPixel;
|
||||
}
|
||||
|
||||
bool operator>(const NzVideoMode& left, const NzVideoMode& right)
|
||||
{
|
||||
return right < left;
|
||||
}
|
||||
|
||||
bool operator>=(const NzVideoMode& left, const NzVideoMode& right)
|
||||
{
|
||||
return right <= left;
|
||||
}
|
||||
21
src/Nazara/Utility/VideoModeImpl.hpp
Normal file
21
src/Nazara/Utility/VideoModeImpl.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_VIDEOMODEIMPL_HPP
|
||||
#define NAZARA_VIDEOMODEIMPL_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
class NzVideoMode;
|
||||
|
||||
class NzVideoModeImpl
|
||||
{
|
||||
public:
|
||||
static NzVideoMode GetDesktopMode();
|
||||
static void GetFullscreenModes(std::vector<NzVideoMode>& modes);
|
||||
};
|
||||
|
||||
#endif // NAZARA_VIDEOMODEIMPL_HPP
|
||||
241
src/Nazara/Utility/Win32/InputImpl.cpp
Normal file
241
src/Nazara/Utility/Win32/InputImpl.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Win32/InputImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Utility/Window.hpp>
|
||||
#include <windows.h>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
NzVector2i NzEventImpl::GetMousePosition()
|
||||
{
|
||||
POINT pos;
|
||||
GetCursorPos(&pos);
|
||||
|
||||
return NzVector2i(pos.x, pos.y);
|
||||
}
|
||||
|
||||
NzVector2i NzEventImpl::GetMousePosition(const NzWindow& relativeTo)
|
||||
{
|
||||
HWND handle = static_cast<HWND>(relativeTo.GetHandle());
|
||||
if (handle)
|
||||
{
|
||||
POINT pos;
|
||||
GetCursorPos(&pos);
|
||||
ScreenToClient(handle, &pos);
|
||||
|
||||
return NzVector2i(pos.x, pos.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Window's handle is invalid");
|
||||
|
||||
// Attention que (-1, -1) est une position tout à fait valide et ne doit pas être utilisée pour tester l'erreur
|
||||
return NzVector2i(-1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
bool NzEventImpl::IsKeyPressed(NzKeyboard::Key key)
|
||||
{
|
||||
static int vKeys[NzKeyboard::Count] = {
|
||||
// Lettres
|
||||
0x41, // Key::A
|
||||
0x42, // Key::B
|
||||
0x43, // Key::C
|
||||
0x44, // Key::D
|
||||
0x45, // Key::E
|
||||
0x46, // Key::F
|
||||
0x47, // Key::G
|
||||
0x48, // Key::H
|
||||
0x49, // Key::I
|
||||
0x4A, // Key::J
|
||||
0x4B, // Key::K
|
||||
0x4C, // Key::L
|
||||
0x4D, // Key::M
|
||||
0x4E, // Key::N
|
||||
0x4F, // Key::O
|
||||
0x50, // Key::P
|
||||
0x51, // Key::Q
|
||||
0x52, // Key::R
|
||||
0x53, // Key::S
|
||||
0x54, // Key::T
|
||||
0x55, // Key::U
|
||||
0x56, // Key::V
|
||||
0x57, // Key::W
|
||||
0x58, // Key::X
|
||||
0x59, // Key::Y
|
||||
0x5A, // Key::Z
|
||||
|
||||
// Touches de fonction
|
||||
VK_F1, // Key::F1
|
||||
VK_F2, // Key::F2
|
||||
VK_F3, // Key::F3
|
||||
VK_F4, // Key::F4
|
||||
VK_F5, // Key::F5
|
||||
VK_F6, // Key::F6
|
||||
VK_F7, // Key::F7
|
||||
VK_F8, // Key::F8
|
||||
VK_F9, // Key::F9
|
||||
VK_F10, // Key::F10
|
||||
VK_F11, // Key::F11
|
||||
VK_F12, // Key::F12
|
||||
VK_F13, // Key::F13
|
||||
VK_F14, // Key::F14
|
||||
VK_F15, // Key::F15
|
||||
|
||||
// Flèches directionnelles
|
||||
VK_DOWN, // Key::Down
|
||||
VK_LEFT, // Key::Left
|
||||
VK_RIGHT, // Key::Right
|
||||
VK_UP, // Key::Up
|
||||
|
||||
// Pavé numérique
|
||||
VK_ADD, // Key::Add
|
||||
VK_DIVIDE, // Key::Divide
|
||||
VK_MULTIPLY, // Key::Multiply
|
||||
VK_NUMPAD0, // Key::Numpad0
|
||||
VK_NUMPAD1, // Key::Numpad1
|
||||
VK_NUMPAD2, // Key::Numpad2
|
||||
VK_NUMPAD3, // Key::Numpad3
|
||||
VK_NUMPAD4, // Key::Numpad4
|
||||
VK_NUMPAD5, // Key::Numpad5
|
||||
VK_NUMPAD6, // Key::Numpad6
|
||||
VK_NUMPAD7, // Key::Numpad7
|
||||
VK_NUMPAD8, // Key::Numpad8
|
||||
VK_NUMPAD9, // Key::Numpad9
|
||||
VK_SUBTRACT, // Key::Subtract
|
||||
|
||||
// Diverss
|
||||
VK_OEM_5, // Key::Backslash
|
||||
VK_BACK, // Key::Backspace
|
||||
VK_CLEAR, // Key::Clear
|
||||
VK_OEM_COMMA, // Key::Comma,
|
||||
VK_OEM_MINUS, // Key::Dash
|
||||
VK_DELETE, // Key::Delete
|
||||
VK_END, // Key::End
|
||||
VK_OEM_PLUS, // Key::Equal
|
||||
VK_ESCAPE, // Key::Escape
|
||||
VK_HOME, // Key::Home
|
||||
VK_INSERT, // Key::Insert
|
||||
VK_LMENU, // Key::LAlt
|
||||
VK_OEM_4, // Key::LBracket
|
||||
VK_LCONTROL, // Key::LControl
|
||||
VK_LSHIFT, // Key::LShift
|
||||
VK_LWIN, // Key::LSystem
|
||||
0x30, // Key::Num0
|
||||
0x31, // Key::Num1
|
||||
0x32, // Key::Num2
|
||||
0x33, // Key::Num3
|
||||
0x34, // Key::Num4
|
||||
0x35, // Key::Num5
|
||||
0x36, // Key::Num6
|
||||
0x37, // Key::Num7
|
||||
0x38, // Key::Num8
|
||||
0x39, // Key::Num9
|
||||
VK_NEXT, // Key::PageDown
|
||||
VK_PRIOR, // Key::PageUp
|
||||
VK_PAUSE, // Key::Pause
|
||||
VK_OEM_PERIOD, // Key::Period,
|
||||
VK_PRINT, // Key::Print
|
||||
VK_SNAPSHOT, // Key::PrintScreen
|
||||
VK_OEM_7, // Key::Quote
|
||||
VK_RMENU, // Key::RAlt
|
||||
VK_OEM_6, // Key::RBracket
|
||||
VK_RCONTROL, // Key::RControl
|
||||
VK_RETURN, // Key::Return
|
||||
VK_RSHIFT, // Key::RShift
|
||||
VK_RWIN, // Key::RSystem
|
||||
VK_OEM_1, // Key::Semicolon
|
||||
VK_OEM_2, // Key::Slash
|
||||
VK_SPACE, // Key::Space
|
||||
VK_TAB, // Key::Tab
|
||||
VK_OEM_3, // Key::Tilde
|
||||
|
||||
// Touches navigateur
|
||||
VK_BROWSER_BACK, // Key::Browser_Back
|
||||
VK_BROWSER_FAVORITES, // Key::Browser_Favorites
|
||||
VK_BROWSER_FORWARD, // Key::Browser_Forward
|
||||
VK_BROWSER_HOME, // Key::Browser_Home
|
||||
VK_BROWSER_REFRESH, // Key::Browser_Refresh
|
||||
VK_BROWSER_SEARCH, // Key::Browser_Search
|
||||
VK_BROWSER_STOP, // Key::Browser_Stop
|
||||
|
||||
// Touches de contr
|
||||
VK_MEDIA_NEXT_TRACK, // Key::Media_Next,
|
||||
VK_MEDIA_PLAY_PAUSE, // Key::Media_PlayPause,
|
||||
VK_MEDIA_PREV_TRACK, // Key::Media_Previous,
|
||||
VK_MEDIA_STOP, // Key::Media_Stop,
|
||||
|
||||
// Touches de contrôle du volume
|
||||
VK_VOLUME_DOWN, // Key::Volume_Down
|
||||
VK_VOLUME_MUTE, // Key::Volume_Mute
|
||||
VK_VOLUME_UP, // Key::Volume_Up
|
||||
|
||||
// Touches à verrouillage
|
||||
VK_CAPITAL, // Key::CapsLock
|
||||
VK_NUMLOCK, // Key::NumLock
|
||||
VK_SCROLL // Key::ScrollLock
|
||||
};
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case NzKeyboard::CapsLock:
|
||||
case NzKeyboard::NumLock:
|
||||
case NzKeyboard::ScrollLock:
|
||||
return GetKeyState(vKeys[key]) != 0;
|
||||
|
||||
default:
|
||||
return (GetAsyncKeyState(vKeys[key]) & 0x8000) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzEventImpl::IsMouseButtonPressed(NzMouse::Button button)
|
||||
{
|
||||
static int vButtons[NzMouse::Count] = {
|
||||
VK_LBUTTON, // Button::Left
|
||||
VK_MBUTTON, // Button::Middle
|
||||
VK_RBUTTON, // Button::Right
|
||||
VK_XBUTTON1, // Button::XButton1
|
||||
VK_XBUTTON2 // Button::XButton2
|
||||
};
|
||||
|
||||
// Gestion de l'inversement des boutons de la souris
|
||||
switch (button)
|
||||
{
|
||||
case NzMouse::Left:
|
||||
if (GetSystemMetrics(SM_SWAPBUTTON))
|
||||
return (GetAsyncKeyState(VK_RBUTTON) & 0x8000) != 0;
|
||||
|
||||
break;
|
||||
|
||||
case NzMouse::Right:
|
||||
if (GetSystemMetrics(SM_SWAPBUTTON))
|
||||
return (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (GetAsyncKeyState(vButtons[button]) & 0x8000) != 0;
|
||||
}
|
||||
|
||||
void NzEventImpl::SetMousePosition(int x, int y)
|
||||
{
|
||||
SetCursorPos(x, y);
|
||||
}
|
||||
|
||||
void NzEventImpl::SetMousePosition(int x, int y, const NzWindow& relativeTo)
|
||||
{
|
||||
HWND handle = static_cast<HWND>(relativeTo.GetHandle());
|
||||
if (handle)
|
||||
{
|
||||
POINT pos = {x, y};
|
||||
ClientToScreen(handle, &pos);
|
||||
SetCursorPos(pos.x, pos.y);
|
||||
}
|
||||
else
|
||||
NazaraError("Window's handle is invalid");
|
||||
}
|
||||
25
src/Nazara/Utility/Win32/InputImpl.hpp
Normal file
25
src/Nazara/Utility/Win32/InputImpl.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_INPUTIMPL_HPP
|
||||
#define NAZARA_INPUTIMPL_HPP
|
||||
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Utility/Keyboard.hpp>
|
||||
#include <Nazara/Utility/Mouse.hpp>
|
||||
|
||||
class NzEventImpl
|
||||
{
|
||||
public:
|
||||
static NzVector2i GetMousePosition();
|
||||
static NzVector2i GetMousePosition(const NzWindow& relativeTo);
|
||||
static bool IsKeyPressed(NzKeyboard::Key key);
|
||||
static bool IsMouseButtonPressed(NzMouse::Button button);
|
||||
static void SetMousePosition(int x, int y);
|
||||
static void SetMousePosition(int x, int y, const NzWindow& relativeTo);
|
||||
};
|
||||
|
||||
#endif // NAZARA_INPUTIMPL_HPP
|
||||
32
src/Nazara/Utility/Win32/VideoModeImpl.cpp
Normal file
32
src/Nazara/Utility/Win32/VideoModeImpl.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/VideoModeImpl.hpp>
|
||||
#include <Nazara/Utility/VideoMode.hpp>
|
||||
#include <algorithm>
|
||||
#include <windows.h>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
NzVideoMode NzVideoModeImpl::GetDesktopMode()
|
||||
{
|
||||
DEVMODE mode;
|
||||
mode.dmSize = sizeof(DEVMODE);
|
||||
EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &mode);
|
||||
|
||||
return NzVideoMode(mode.dmPelsWidth, mode.dmPelsHeight, mode.dmBitsPerPel);
|
||||
}
|
||||
|
||||
void NzVideoModeImpl::GetFullscreenModes(std::vector<NzVideoMode>& modes)
|
||||
{
|
||||
DEVMODE win32Mode;
|
||||
win32Mode.dmSize = sizeof(DEVMODE);
|
||||
for (unsigned int i = 0; EnumDisplaySettings(nullptr, i, &win32Mode); ++i)
|
||||
{
|
||||
NzVideoMode mode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel);
|
||||
|
||||
// Il existe plusieurs modes avec ces trois caractéristques identiques
|
||||
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
|
||||
modes.push_back(mode);
|
||||
}
|
||||
}
|
||||
971
src/Nazara/Utility/Win32/WindowImpl.cpp
Normal file
971
src/Nazara/Utility/Win32/WindowImpl.cpp
Normal file
@@ -0,0 +1,971 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// Un grand merci à Laurent Gomila pour la SFML qui m'aura bien aidé à réaliser cette implémentation
|
||||
|
||||
#include <Nazara/Utility/Win32/WindowImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Core/Thread.hpp>
|
||||
#include <Nazara/Core/ThreadCondition.hpp>
|
||||
#include <cstdio>
|
||||
#include <windowsx.h>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
// N'est pas définit avec MinGW apparemment
|
||||
#ifndef MAPVK_VK_TO_VSC
|
||||
#define MAPVK_VK_TO_VSC 0
|
||||
#endif
|
||||
|
||||
#undef IsMinimized // Conflit avec la méthode du même nom
|
||||
|
||||
namespace
|
||||
{
|
||||
const wchar_t* className = L"Nazara Window";
|
||||
NzWindowImpl* fullscreenWindow = nullptr;
|
||||
unsigned int windowCount = 0;
|
||||
}
|
||||
|
||||
NzWindowImpl::NzWindowImpl(NzWindow* parent) :
|
||||
m_cursor(nullptr),
|
||||
m_handle(nullptr),
|
||||
m_callback(0),
|
||||
m_maxSize(-1),
|
||||
m_minSize(-1),
|
||||
m_parent(parent),
|
||||
m_keyRepeat(true),
|
||||
m_mouseInside(false),
|
||||
m_smoothScrolling(false),
|
||||
m_scrolling(0)
|
||||
{
|
||||
}
|
||||
|
||||
void NzWindowImpl::Close()
|
||||
{
|
||||
if (m_ownsWindow)
|
||||
{
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
if (m_thread)
|
||||
{
|
||||
m_threadActive = false;
|
||||
PostMessageW(m_handle, WM_NULL, 0, 0); // Pour réveiller le thread
|
||||
|
||||
m_thread->Join();
|
||||
delete m_thread;
|
||||
}
|
||||
#else
|
||||
if (m_handle)
|
||||
DestroyWindow(m_handle);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
SetEventListener(false);
|
||||
|
||||
if (--windowCount == 0)
|
||||
Uninitialize();
|
||||
}
|
||||
|
||||
bool NzWindowImpl::Create(NzVideoMode mode, const NzString& title, nzUInt32 style)
|
||||
{
|
||||
if (windowCount++ == 0 && !Initialize())
|
||||
{
|
||||
NazaraError("Unable to initialize window implementation");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fullscreen = (style & NzWindow::Fullscreen) != 0;
|
||||
DWORD win32Style, win32StyleEx;
|
||||
unsigned int x, y;
|
||||
unsigned int width = mode.width;
|
||||
unsigned int height = mode.height;
|
||||
if (fullscreen)
|
||||
{
|
||||
DEVMODE win32Mode;
|
||||
win32Mode.dmBitsPerPel = mode.bitsPerPixel;
|
||||
win32Mode.dmPelsHeight = mode.height;
|
||||
win32Mode.dmPelsWidth = mode.width;
|
||||
win32Mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
||||
win32Mode.dmSize = sizeof(DEVMODE);
|
||||
|
||||
if (ChangeDisplaySettings(&win32Mode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
|
||||
{
|
||||
// Situation extrêmement rare grâce à NzVideoMode::IsValid appelé par NzWindow
|
||||
NazaraError("Failed to change display settings for fullscreen, this video mode is not supported by your computer");
|
||||
fullscreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
win32Style = WS_CLIPCHILDREN | WS_POPUP;
|
||||
|
||||
// Pour cacher la barre des tâches
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ff700543(v=vs.85).aspx
|
||||
win32StyleEx = WS_EX_APPWINDOW;
|
||||
|
||||
fullscreenWindow = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
win32Style = WS_VISIBLE;
|
||||
if (style & NzWindow::Titlebar)
|
||||
{
|
||||
win32Style |= WS_CAPTION | WS_MINIMIZEBOX;
|
||||
if (style & NzWindow::Closable)
|
||||
win32Style |= WS_SYSMENU;
|
||||
|
||||
if (style & NzWindow::Resizable)
|
||||
win32Style |= WS_MAXIMIZEBOX | WS_SIZEBOX;
|
||||
}
|
||||
else
|
||||
win32Style |= WS_POPUP;
|
||||
|
||||
win32StyleEx = 0;
|
||||
|
||||
RECT rect = {0, 0, width, height};
|
||||
AdjustWindowRect(&rect, win32Style, false);
|
||||
width = rect.right-rect.left;
|
||||
height = rect.bottom-rect.top;
|
||||
|
||||
x = (GetSystemMetrics(SM_CXSCREEN) - width)/2;
|
||||
y = (GetSystemMetrics(SM_CYSCREEN) - height)/2;
|
||||
}
|
||||
|
||||
m_callback = 0;
|
||||
|
||||
wchar_t* wtitle = title.GetWideBuffer();
|
||||
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
NzMutex mutex;
|
||||
NzThreadCondition condition;
|
||||
m_thread = new NzThread(WindowThread, &m_handle, win32StyleEx, wtitle, win32Style, x, y, width, height, this, &mutex, &condition);
|
||||
m_threadActive = true;
|
||||
|
||||
// On attend que la fenêtre soit créée
|
||||
mutex.Lock();
|
||||
m_thread->Launch();
|
||||
condition.Wait(&mutex);
|
||||
mutex.Unlock();
|
||||
#else
|
||||
m_handle = CreateWindowExW(win32StyleEx, className, wtitle, win32Style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), this);
|
||||
#endif
|
||||
|
||||
delete[] wtitle;
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
SetForegroundWindow(m_handle);
|
||||
ShowWindow(m_handle, SW_SHOW);
|
||||
}
|
||||
|
||||
m_eventListener = true;
|
||||
m_ownsWindow = true;
|
||||
|
||||
if (m_handle != nullptr)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
if (--windowCount == 0)
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzWindowImpl::Create(NzWindowHandle handle)
|
||||
{
|
||||
if (!handle)
|
||||
{
|
||||
NazaraError("Invalid handle");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_handle = static_cast<HWND>(handle);
|
||||
m_eventListener = false;
|
||||
m_ownsWindow = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzWindowImpl::EnableKeyRepeat(bool enable)
|
||||
{
|
||||
m_keyRepeat = enable;
|
||||
}
|
||||
|
||||
void NzWindowImpl::EnableSmoothScrolling(bool enable)
|
||||
{
|
||||
m_smoothScrolling = enable;
|
||||
}
|
||||
|
||||
NzWindowHandle NzWindowImpl::GetHandle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
unsigned int NzWindowImpl::GetHeight() const
|
||||
{
|
||||
RECT rect;
|
||||
GetClientRect(m_handle, &rect);
|
||||
return rect.bottom-rect.top;
|
||||
}
|
||||
|
||||
NzVector2i NzWindowImpl::GetPosition() const
|
||||
{
|
||||
RECT rect;
|
||||
GetWindowRect(m_handle, &rect);
|
||||
return NzVector2i(rect.left, rect.top);
|
||||
}
|
||||
|
||||
NzVector2i NzWindowImpl::GetSize() const
|
||||
{
|
||||
RECT rect;
|
||||
GetClientRect(m_handle, &rect);
|
||||
return NzVector2i(rect.right-rect.left, rect.bottom-rect.top);
|
||||
}
|
||||
|
||||
NzString NzWindowImpl::GetTitle() const
|
||||
{
|
||||
unsigned int titleSize = GetWindowTextLengthW(m_handle);
|
||||
if (titleSize == 0)
|
||||
return NzString();
|
||||
|
||||
titleSize++; // Caractère nul
|
||||
|
||||
wchar_t* wTitle = new wchar_t[titleSize];
|
||||
GetWindowTextW(m_handle, wTitle, titleSize);
|
||||
|
||||
NzString title = NzString::Unicode(wTitle);
|
||||
|
||||
delete[] wTitle;
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
unsigned int NzWindowImpl::GetWidth() const
|
||||
{
|
||||
RECT rect;
|
||||
GetClientRect(m_handle, &rect);
|
||||
return rect.right-rect.left;
|
||||
}
|
||||
|
||||
bool NzWindowImpl::HasFocus() const
|
||||
{
|
||||
return GetForegroundWindow() == m_handle;
|
||||
}
|
||||
|
||||
void NzWindowImpl::ProcessEvents(bool block)
|
||||
{
|
||||
if (m_ownsWindow)
|
||||
{
|
||||
if (block)
|
||||
WaitMessage();
|
||||
|
||||
MSG message;
|
||||
while (PeekMessageW(&message, nullptr, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&message);
|
||||
DispatchMessageW(&message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NzWindowImpl::IsMinimized() const
|
||||
{
|
||||
return IsIconic(m_handle);
|
||||
}
|
||||
|
||||
bool NzWindowImpl::IsVisible() const
|
||||
{
|
||||
return IsWindowVisible(m_handle);
|
||||
}
|
||||
|
||||
void NzWindowImpl::SetEventListener(bool listener)
|
||||
{
|
||||
if (m_ownsWindow)
|
||||
m_eventListener = listener;
|
||||
else if (listener != m_eventListener)
|
||||
{
|
||||
if (listener)
|
||||
{
|
||||
SetWindowLongPtr(m_handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
|
||||
m_callback = SetWindowLongPtr(m_handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(MessageHandler));
|
||||
m_eventListener = true;
|
||||
}
|
||||
else if (m_eventListener)
|
||||
{
|
||||
SetWindowLongPtr(m_handle, GWLP_WNDPROC, m_callback);
|
||||
m_eventListener = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NzWindowImpl::SetFocus()
|
||||
{
|
||||
SetForegroundWindow(m_handle);
|
||||
}
|
||||
|
||||
void NzWindowImpl::SetMaximumSize(int width, int height)
|
||||
{
|
||||
RECT rect = {0, 0, width, height};
|
||||
AdjustWindowRect(&rect, GetWindowLongPtr(m_handle, GWL_STYLE), false);
|
||||
|
||||
if (width != -1)
|
||||
m_maxSize.x = rect.right-rect.left;
|
||||
else
|
||||
m_maxSize.x = -1;
|
||||
|
||||
if (height != -1)
|
||||
m_maxSize.y = rect.bottom-rect.top;
|
||||
else
|
||||
m_maxSize.y = -1;
|
||||
}
|
||||
|
||||
void NzWindowImpl::SetMinimumSize(int width, int height)
|
||||
{
|
||||
RECT rect = {0, 0, width, height};
|
||||
AdjustWindowRect(&rect, GetWindowLongPtr(m_handle, GWL_STYLE), false);
|
||||
|
||||
if (width != -1)
|
||||
m_minSize.x = rect.right-rect.left;
|
||||
else
|
||||
m_minSize.x = -1;
|
||||
|
||||
if (height != -1)
|
||||
m_minSize.y = rect.bottom-rect.top;
|
||||
else
|
||||
m_minSize.y = -1;
|
||||
}
|
||||
|
||||
void NzWindowImpl::SetPosition(int x, int y)
|
||||
{
|
||||
SetWindowPos(m_handle, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
void NzWindowImpl::SetSize(unsigned int width, unsigned int height)
|
||||
{
|
||||
// SetWindowPos demande la taille totale de la fenêtre
|
||||
RECT rect = {0, 0, width, height};
|
||||
AdjustWindowRect(&rect, GetWindowLongPtr(m_handle, GWL_STYLE), false);
|
||||
|
||||
SetWindowPos(m_handle, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
void NzWindowImpl::SetTitle(const NzString& title)
|
||||
{
|
||||
wchar_t* wtitle = title.GetWideBuffer();
|
||||
SetWindowTextW(m_handle, wtitle);
|
||||
delete[] wtitle;
|
||||
}
|
||||
|
||||
void NzWindowImpl::SetVisible(bool visible)
|
||||
{
|
||||
ShowWindow(m_handle, (visible) ? SW_SHOW : SW_HIDE);
|
||||
}
|
||||
|
||||
void NzWindowImpl::ShowMouseCursor(bool show)
|
||||
{
|
||||
// Pas besoin de libérer le curseur par la suite s'il est partagé
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx
|
||||
|
||||
if (show)
|
||||
m_cursor = static_cast<HCURSOR>(LoadImage(nullptr, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_SHARED));
|
||||
else
|
||||
m_cursor = nullptr;
|
||||
|
||||
SetCursor(m_cursor);
|
||||
}
|
||||
|
||||
void NzWindowImpl::StayOnTop(bool stayOnTop)
|
||||
{
|
||||
SetWindowPos(m_handle, (stayOnTop) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
|
||||
}
|
||||
|
||||
bool NzWindowImpl::HandleMessage(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// Inutile de récupérer des évènements ne venant pas de notre fenêtre
|
||||
if (m_handle != window)
|
||||
return false;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
if (fullscreenWindow == this)
|
||||
ChangeDisplaySettings(nullptr, 0);
|
||||
|
||||
break;
|
||||
|
||||
case WM_SETCURSOR:
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648382(v=vs.85).aspx
|
||||
if (LOWORD(lParam) == HTCLIENT)
|
||||
SetCursor(m_cursor);
|
||||
|
||||
break;
|
||||
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
{
|
||||
WINDOWPOS* pos = reinterpret_cast<WINDOWPOS*>(lParam);
|
||||
|
||||
pos->cx = std::max(pos->cx, m_minSize.x);
|
||||
pos->cy = std::max(pos->cy, m_minSize.y);
|
||||
|
||||
if (m_maxSize.x >= 0)
|
||||
pos->cx = std::min(pos->cx, m_maxSize.x);
|
||||
|
||||
if (m_maxSize.y >= 0)
|
||||
pos->cy = std::min(pos->cy, m_maxSize.y);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_eventListener)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_CHAR:
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/ms646267(VS.85).aspx
|
||||
if (m_keyRepeat || (HIWORD(lParam) & KF_REPEAT) == 0)
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::TextEntered;
|
||||
event.text.character = static_cast<nzUInt32>(wParam);
|
||||
m_parent->PushEvent(event);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CLOSE:
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::Quit;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
return true; // Afin que Windows ne ferme pas la fenêtre automatiquement
|
||||
}
|
||||
|
||||
case WM_LBUTTONDBLCLK:
|
||||
{
|
||||
// Cet évènement est généré à la place d'un WM_LBUTTONDOWN lors d'un double-clic.
|
||||
// Comme nous désirons quand même notifier chaque clic, nous envoyons les deux évènements.
|
||||
NzEvent event;
|
||||
event.mouseButton.button = NzMouse::Left;
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
|
||||
event.type = NzEvent::MouseButtonDoubleClicked;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
event.type = NzEvent::MouseButtonPressed;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseButtonPressed;
|
||||
event.mouseButton.button = NzMouse::Left;
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseButtonReleased;
|
||||
event.mouseButton.button = NzMouse::Left;
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/ms646267(VS.85).aspx
|
||||
if (m_keyRepeat || (HIWORD(lParam) & KF_REPEAT) == 0)
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::KeyPressed;
|
||||
event.key.code = ConvertVirtualKey(wParam, lParam);
|
||||
event.key.alt = ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0);
|
||||
event.key.control = ((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0);
|
||||
event.key.shift = ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0);
|
||||
event.key.system = (((GetAsyncKeyState(VK_LWIN) & 0x8000) != 0) || ((GetAsyncKeyState(VK_RWIN) & 0x8000) != 0));
|
||||
m_parent->PushEvent(event);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/ms646267(VS.85).aspx
|
||||
NzEvent event;
|
||||
event.type = NzEvent::KeyReleased;
|
||||
event.key.code = ConvertVirtualKey(wParam, lParam);
|
||||
event.key.alt = ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0);
|
||||
event.key.control = ((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0);
|
||||
event.key.shift = ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0);
|
||||
event.key.system = ((GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000));
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_KILLFOCUS:
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::LostFocus;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MBUTTONDBLCLK:
|
||||
{
|
||||
NzEvent event;
|
||||
event.mouseButton.button = NzMouse::Middle;
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
|
||||
event.type = NzEvent::MouseButtonDoubleClicked;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
event.type = NzEvent::MouseButtonPressed;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MBUTTONDOWN:
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseButtonPressed;
|
||||
event.mouseButton.button = NzMouse::Middle;
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MBUTTONUP:
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseButtonReleased;
|
||||
event.mouseButton.button = NzMouse::Middle;
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Nécessite un appel précédent à TrackMouseEvent (Fait dans WM_MOUSEMOVE)
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms645615(v=vs.85).aspx
|
||||
case WM_MOUSELEAVE:
|
||||
{
|
||||
m_mouseInside = false;
|
||||
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseLeft;
|
||||
m_parent->PushEvent(event);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
if (!m_mouseInside)
|
||||
{
|
||||
m_mouseInside = true;
|
||||
|
||||
TRACKMOUSEEVENT mouseEvent;
|
||||
mouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
mouseEvent.dwFlags = TME_LEAVE;
|
||||
mouseEvent.hwndTrack = m_handle;
|
||||
|
||||
TrackMouseEvent(&mouseEvent);
|
||||
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseEntered;
|
||||
m_parent->PushEvent(event);
|
||||
}
|
||||
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseMoved;
|
||||
event.mouseMove.x = GET_X_LPARAM(lParam);
|
||||
event.mouseMove.y = GET_Y_LPARAM(lParam);
|
||||
m_parent->PushEvent(event);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
if (m_smoothScrolling)
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseWheelMoved;
|
||||
event.mouseWheel.delta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wParam))/WHEEL_DELTA;
|
||||
m_parent->PushEvent(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scrolling += GET_WHEEL_DELTA_WPARAM(wParam);
|
||||
if (std::abs(m_scrolling) >= WHEEL_DELTA)
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseWheelMoved;
|
||||
event.mouseWheel.delta = m_scrolling/WHEEL_DELTA;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
m_scrolling %= WHEEL_DELTA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MOVE:
|
||||
{
|
||||
NzVector2i position = GetPosition();
|
||||
|
||||
NzEvent event;
|
||||
event.type = NzEvent::Moved;
|
||||
event.position.x = position.x;
|
||||
event.position.y = position.y;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RBUTTONDBLCLK:
|
||||
{
|
||||
NzEvent event;
|
||||
event.mouseButton.button = NzMouse::Right;
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
|
||||
event.type = NzEvent::MouseButtonDoubleClicked;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
event.type = NzEvent::MouseButtonPressed;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseButtonPressed;
|
||||
event.mouseButton.button = NzMouse::Right;
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RBUTTONUP:
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::MouseButtonReleased;
|
||||
event.mouseButton.button = NzMouse::Right;
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SETFOCUS:
|
||||
{
|
||||
NzEvent event;
|
||||
event.type = NzEvent::GainedFocus;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SIZE:
|
||||
{
|
||||
if (wParam != SIZE_MINIMIZED)
|
||||
{
|
||||
NzVector2i size = GetSize(); // On récupère uniquement la taille de la zone client
|
||||
|
||||
NzEvent event;
|
||||
event.type = NzEvent::Resized;
|
||||
event.size.width = size.x;
|
||||
event.size.height = size.y;
|
||||
m_parent->PushEvent(event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_XBUTTONDBLCLK:
|
||||
{
|
||||
NzEvent event;
|
||||
if (HIWORD(wParam) == XBUTTON1)
|
||||
event.mouseButton.button = NzMouse::XButton1;
|
||||
else
|
||||
event.mouseButton.button = NzMouse::XButton2;
|
||||
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
|
||||
event.type = NzEvent::MouseButtonDoubleClicked;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
event.type = NzEvent::MouseButtonPressed;
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_XBUTTONDOWN:
|
||||
{
|
||||
NzEvent event;
|
||||
if (HIWORD(wParam) == XBUTTON1)
|
||||
event.mouseButton.button = NzMouse::XButton1;
|
||||
else
|
||||
event.mouseButton.button = NzMouse::XButton2;
|
||||
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_XBUTTONUP:
|
||||
{
|
||||
NzEvent event;
|
||||
if (HIWORD(wParam) == XBUTTON1)
|
||||
event.mouseButton.button = NzMouse::XButton1;
|
||||
else
|
||||
event.mouseButton.button = NzMouse::XButton2;
|
||||
|
||||
event.mouseButton.x = GET_X_LPARAM(lParam);
|
||||
event.mouseButton.y = GET_Y_LPARAM(lParam);
|
||||
m_parent->PushEvent(event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK NzWindowImpl::MessageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
NzWindowImpl* me;
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
me = reinterpret_cast<NzWindowImpl*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams);
|
||||
SetWindowLongPtr(window, GWL_USERDATA, reinterpret_cast<LONG_PTR>(me));
|
||||
}
|
||||
else
|
||||
me = reinterpret_cast<NzWindowImpl*>(GetWindowLongPtr(window, GWL_USERDATA));
|
||||
|
||||
if (me)
|
||||
{
|
||||
if (me->HandleMessage(window, message, wParam, lParam))
|
||||
return 0;
|
||||
else if (me->m_callback)
|
||||
return CallWindowProcW(reinterpret_cast<WNDPROC>(me->m_callback), window, message, wParam, lParam);
|
||||
}
|
||||
|
||||
return DefWindowProcW(window, message, wParam, lParam);
|
||||
}
|
||||
|
||||
bool NzWindowImpl::Initialize()
|
||||
{
|
||||
// Nous devons faire un type Unicode pour que la fenêtre le soit également
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms633574(v=vs.85).aspx
|
||||
WNDCLASSW windowClass;
|
||||
windowClass.cbClsExtra = 0;
|
||||
windowClass.cbWndExtra = 0;
|
||||
windowClass.hbrBackground = nullptr;
|
||||
windowClass.hCursor = nullptr; // Le curseur est définit dynamiquement
|
||||
windowClass.hIcon = nullptr; // L'icône est définie dynamiquement
|
||||
windowClass.hInstance = GetModuleHandle(nullptr);
|
||||
windowClass.lpfnWndProc = MessageHandler;
|
||||
windowClass.lpszClassName = className;
|
||||
windowClass.lpszMenuName = nullptr;
|
||||
windowClass.style = CS_DBLCLKS; // Gestion du double-clic
|
||||
|
||||
return RegisterClassW(&windowClass);
|
||||
}
|
||||
|
||||
NzKeyboard::Key NzWindowImpl::ConvertVirtualKey(WPARAM key, LPARAM flags)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case VK_CONTROL: return (HIWORD(flags) & KF_EXTENDED) ? NzKeyboard::RControl : NzKeyboard::LControl;
|
||||
case VK_MENU: return (HIWORD(flags) & KF_EXTENDED) ? NzKeyboard::RAlt : NzKeyboard::LAlt;
|
||||
case VK_SHIFT:
|
||||
{
|
||||
static UINT scancode = MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC);
|
||||
return (((flags >> 16) & 0xFF) == scancode) ? NzKeyboard::LShift : NzKeyboard::RShift;
|
||||
}
|
||||
|
||||
case 0x30: return NzKeyboard::Num0;
|
||||
case 0x31: return NzKeyboard::Num1;
|
||||
case 0x32: return NzKeyboard::Num2;
|
||||
case 0x33: return NzKeyboard::Num3;
|
||||
case 0x34: return NzKeyboard::Num4;
|
||||
case 0x35: return NzKeyboard::Num5;
|
||||
case 0x36: return NzKeyboard::Num6;
|
||||
case 0x37: return NzKeyboard::Num7;
|
||||
case 0x38: return NzKeyboard::Num8;
|
||||
case 0x39: return NzKeyboard::Num9;
|
||||
case 0x41: return NzKeyboard::A;
|
||||
case 0x42: return NzKeyboard::B;
|
||||
case 0x43: return NzKeyboard::C;
|
||||
case 0x44: return NzKeyboard::D;
|
||||
case 0x45: return NzKeyboard::E;
|
||||
case 0x46: return NzKeyboard::F;
|
||||
case 0x47: return NzKeyboard::G;
|
||||
case 0x48: return NzKeyboard::H;
|
||||
case 0x49: return NzKeyboard::I;
|
||||
case 0x4A: return NzKeyboard::J;
|
||||
case 0x4B: return NzKeyboard::K;
|
||||
case 0x4C: return NzKeyboard::L;
|
||||
case 0x4D: return NzKeyboard::M;
|
||||
case 0x4E: return NzKeyboard::N;
|
||||
case 0x4F: return NzKeyboard::O;
|
||||
case 0x50: return NzKeyboard::P;
|
||||
case 0x51: return NzKeyboard::Q;
|
||||
case 0x52: return NzKeyboard::R;
|
||||
case 0x53: return NzKeyboard::S;
|
||||
case 0x54: return NzKeyboard::T;
|
||||
case 0x55: return NzKeyboard::U;
|
||||
case 0x56: return NzKeyboard::V;
|
||||
case 0x57: return NzKeyboard::W;
|
||||
case 0x58: return NzKeyboard::X;
|
||||
case 0x59: return NzKeyboard::Y;
|
||||
case 0x5A: return NzKeyboard::Z;
|
||||
case VK_ADD: return NzKeyboard::Add;
|
||||
case VK_BACK: return NzKeyboard::Backspace;
|
||||
case VK_BROWSER_BACK: return NzKeyboard::Browser_Back;
|
||||
case VK_BROWSER_FAVORITES: return NzKeyboard::Browser_Favorites;
|
||||
case VK_BROWSER_FORWARD: return NzKeyboard::Browser_Forward;
|
||||
case VK_BROWSER_HOME: return NzKeyboard::Browser_Home;
|
||||
case VK_BROWSER_REFRESH: return NzKeyboard::Browser_Refresh;
|
||||
case VK_BROWSER_SEARCH: return NzKeyboard::Browser_Search;
|
||||
case VK_BROWSER_STOP: return NzKeyboard::Browser_Stop;
|
||||
case VK_CAPITAL: return NzKeyboard::CapsLock;
|
||||
case VK_CLEAR: return NzKeyboard::Clear;
|
||||
case VK_DELETE: return NzKeyboard::Delete;
|
||||
case VK_DIVIDE: return NzKeyboard::Divide;
|
||||
case VK_DOWN: return NzKeyboard::Down;
|
||||
case VK_END: return NzKeyboard::End;
|
||||
case VK_ESCAPE: return NzKeyboard::Escape;
|
||||
case VK_F1: return NzKeyboard::F1;
|
||||
case VK_F2: return NzKeyboard::F2;
|
||||
case VK_F3: return NzKeyboard::F3;
|
||||
case VK_F4: return NzKeyboard::F4;
|
||||
case VK_F5: return NzKeyboard::F5;
|
||||
case VK_F6: return NzKeyboard::F6;
|
||||
case VK_F7: return NzKeyboard::F7;
|
||||
case VK_F8: return NzKeyboard::F8;
|
||||
case VK_F9: return NzKeyboard::F9;
|
||||
case VK_F10: return NzKeyboard::F10;
|
||||
case VK_F11: return NzKeyboard::F11;
|
||||
case VK_F12: return NzKeyboard::F12;
|
||||
case VK_F13: return NzKeyboard::F13;
|
||||
case VK_F14: return NzKeyboard::F14;
|
||||
case VK_F15: return NzKeyboard::F15;
|
||||
case VK_HOME: return NzKeyboard::Home;
|
||||
case VK_INSERT: return NzKeyboard::Insert;
|
||||
case VK_LEFT: return NzKeyboard::Left;
|
||||
case VK_LWIN: return NzKeyboard::LSystem;
|
||||
case VK_MEDIA_NEXT_TRACK: return NzKeyboard::Media_Next;
|
||||
case VK_MEDIA_PLAY_PAUSE: return NzKeyboard::Media_Play;
|
||||
case VK_MEDIA_PREV_TRACK: return NzKeyboard::Media_Previous;
|
||||
case VK_MEDIA_STOP: return NzKeyboard::Media_Stop;
|
||||
case VK_MULTIPLY: return NzKeyboard::Multiply;
|
||||
case VK_NEXT: return NzKeyboard::PageDown;
|
||||
case VK_NUMPAD0: return NzKeyboard::Numpad0;
|
||||
case VK_NUMPAD1: return NzKeyboard::Numpad1;
|
||||
case VK_NUMPAD2: return NzKeyboard::Numpad2;
|
||||
case VK_NUMPAD3: return NzKeyboard::Numpad3;
|
||||
case VK_NUMPAD4: return NzKeyboard::Numpad4;
|
||||
case VK_NUMPAD5: return NzKeyboard::Numpad5;
|
||||
case VK_NUMPAD6: return NzKeyboard::Numpad6;
|
||||
case VK_NUMPAD7: return NzKeyboard::Numpad7;
|
||||
case VK_NUMPAD8: return NzKeyboard::Numpad8;
|
||||
case VK_NUMPAD9: return NzKeyboard::Numpad9;
|
||||
case VK_NUMLOCK: return NzKeyboard::NumLock;
|
||||
case VK_OEM_1: return NzKeyboard::Semicolon;
|
||||
case VK_OEM_2: return NzKeyboard::Slash;
|
||||
case VK_OEM_3: return NzKeyboard::Tilde;
|
||||
case VK_OEM_4: return NzKeyboard::LBracket;
|
||||
case VK_OEM_5: return NzKeyboard::Backslash;
|
||||
case VK_OEM_6: return NzKeyboard::RBracket;
|
||||
case VK_OEM_7: return NzKeyboard::Quote;
|
||||
case VK_OEM_COMMA: return NzKeyboard::Comma;
|
||||
case VK_OEM_MINUS: return NzKeyboard::Dash;
|
||||
case VK_OEM_PERIOD: return NzKeyboard::Period;
|
||||
case VK_OEM_PLUS: return NzKeyboard::Equal;
|
||||
case VK_RIGHT: return NzKeyboard::Right;
|
||||
case VK_PRIOR: return NzKeyboard::PageUp;
|
||||
case VK_PAUSE: return NzKeyboard::Pause;
|
||||
case VK_PRINT: return NzKeyboard::Print;
|
||||
case VK_SCROLL: return NzKeyboard::ScrollLock;
|
||||
case VK_SNAPSHOT: return NzKeyboard::PrintScreen;
|
||||
case VK_SUBTRACT: return NzKeyboard::Subtract;
|
||||
case VK_RETURN: return NzKeyboard::Return;
|
||||
case VK_RWIN: return NzKeyboard::RSystem;
|
||||
case VK_SPACE: return NzKeyboard::Space;
|
||||
case VK_TAB: return NzKeyboard::Tab;
|
||||
case VK_UP: return NzKeyboard::Up;
|
||||
case VK_VOLUME_DOWN: return NzKeyboard::Volume_Down;
|
||||
case VK_VOLUME_MUTE: return NzKeyboard::Volume_Mute;
|
||||
case VK_VOLUME_UP: return NzKeyboard::Volume_Up;
|
||||
|
||||
default:
|
||||
return NzKeyboard::Key(NzKeyboard::Undefined);
|
||||
}
|
||||
}
|
||||
|
||||
void NzWindowImpl::Uninitialize()
|
||||
{
|
||||
UnregisterClassW(className, GetModuleHandle(nullptr));
|
||||
}
|
||||
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
void NzWindowImpl::WindowThread(HWND* handle, DWORD styleEx, const wchar_t* title, DWORD style, unsigned int x, unsigned int y, unsigned int width, unsigned int height, NzWindowImpl* window, NzMutex* mutex, NzThreadCondition* condition)
|
||||
{
|
||||
*handle = CreateWindowExW(styleEx, className, title, style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), window);
|
||||
|
||||
mutex->Lock();
|
||||
condition->Signal();
|
||||
mutex->Unlock();
|
||||
// mutex et condition sont considérés invalides à partir d'ici
|
||||
|
||||
while (window->m_threadActive)
|
||||
window->ProcessEvents(true);
|
||||
|
||||
DestroyWindow(*handle);
|
||||
}
|
||||
#endif
|
||||
100
src/Nazara/Utility/Win32/WindowImpl.hpp
Normal file
100
src/Nazara/Utility/Win32/WindowImpl.hpp
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// Interface inspirée de la SFML par Laurent Gomila
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_WINDOWIMPL_HPP
|
||||
#define NAZARA_WINDOWIMPL_HPP
|
||||
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Math/Vector2.hpp>
|
||||
#include <Nazara/Utility/Config.hpp>
|
||||
#include <Nazara/Utility/Keyboard.hpp>
|
||||
#include <Nazara/Utility/Mouse.hpp>
|
||||
#include <Nazara/Utility/NonCopyable.hpp>
|
||||
#include <Nazara/Utility/VideoMode.hpp>
|
||||
#include <Nazara/Utility/Window.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
class NzMutex;
|
||||
class NzThread;
|
||||
class NzThreadCondition;
|
||||
#endif
|
||||
|
||||
#undef IsMinimized // Conflit avec la méthode du même nom
|
||||
|
||||
class NzWindowImpl : NzNonCopyable
|
||||
{
|
||||
public:
|
||||
NzWindowImpl(NzWindow* parent);
|
||||
~NzWindowImpl() = default;
|
||||
|
||||
void Close();
|
||||
|
||||
bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style);
|
||||
bool Create(NzWindowHandle handle);
|
||||
|
||||
void EnableKeyRepeat(bool enable);
|
||||
void EnableSmoothScrolling(bool enable);
|
||||
|
||||
NzWindowHandle GetHandle() const;
|
||||
unsigned int GetHeight() const;
|
||||
NzVector2i GetPosition() const;
|
||||
NzVector2i GetSize() const;
|
||||
NzString GetTitle() const;
|
||||
unsigned int GetWidth() const;
|
||||
|
||||
bool HasFocus() const;
|
||||
|
||||
void ProcessEvents(bool block);
|
||||
|
||||
bool IsMinimized() const;
|
||||
bool IsVisible() const;
|
||||
|
||||
void SetEventListener(bool listener);
|
||||
void SetFocus();
|
||||
void SetMaximumSize(int width, int height);
|
||||
void SetMinimumSize(int width, int height);
|
||||
void SetPosition(int x, int y);
|
||||
void SetSize(unsigned int width, unsigned int height);
|
||||
void SetTitle(const NzString& title);
|
||||
void SetVisible(bool visible);
|
||||
|
||||
void ShowMouseCursor(bool show);
|
||||
void StayOnTop(bool stayOnTop);
|
||||
|
||||
private:
|
||||
bool HandleMessage(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static bool Initialize();
|
||||
static LRESULT CALLBACK MessageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
static NzKeyboard::Key ConvertVirtualKey(WPARAM key, LPARAM flags);
|
||||
static void Uninitialize();
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
static void WindowThread(HWND* handle, DWORD styleEx, const wchar_t* title, DWORD style, unsigned int x, unsigned int y, unsigned int width, unsigned int height, NzWindowImpl* window, NzMutex* mutex, NzThreadCondition* condition);
|
||||
#endif
|
||||
|
||||
HCURSOR m_cursor;
|
||||
HWND m_handle;
|
||||
LONG_PTR m_callback;
|
||||
NzVector2i m_maxSize;
|
||||
NzVector2i m_minSize;
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
NzThread* m_thread;
|
||||
#endif
|
||||
NzWindow* m_parent;
|
||||
bool m_eventListener;
|
||||
bool m_keyRepeat;
|
||||
bool m_mouseInside;
|
||||
bool m_ownsWindow;
|
||||
bool m_smoothScrolling;
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
bool m_threadActive;
|
||||
#endif
|
||||
short m_scrolling;
|
||||
};
|
||||
#endif // NAZARA_WINDOWIMPL_HPP
|
||||
475
src/Nazara/Utility/Window.cpp
Normal file
475
src/Nazara/Utility/Window.cpp
Normal file
@@ -0,0 +1,475 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Window.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Lock.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Utility/Win32/WindowImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
#include <Nazara/Utility/Linux/WindowImpl.hpp>
|
||||
#else
|
||||
#error Lack of implementation: Window
|
||||
#endif
|
||||
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
NzWindow* fullscreenWindow = nullptr;
|
||||
}
|
||||
|
||||
NzWindow::NzWindow() :
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
m_impl(nullptr),
|
||||
m_eventListener(true),
|
||||
m_waitForEvent(false)
|
||||
#else
|
||||
m_impl(nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
NzWindow::NzWindow(NzVideoMode mode, const NzString& title, nzUInt32 style) :
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
m_impl(nullptr),
|
||||
m_eventListener(true),
|
||||
m_waitForEvent(false)
|
||||
#else
|
||||
m_impl(nullptr)
|
||||
#endif
|
||||
{
|
||||
Create(mode, title, style);
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Failed to create window");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NzWindow::NzWindow(NzWindowHandle handle) :
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
m_impl(nullptr),
|
||||
m_eventListener(true),
|
||||
m_waitForEvent(false)
|
||||
#else
|
||||
m_impl(nullptr)
|
||||
#endif
|
||||
{
|
||||
Create(handle);
|
||||
|
||||
#if NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Failed to create window");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NzWindow::~NzWindow()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void NzWindow::Close()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
OnClose();
|
||||
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
if (fullscreenWindow == this)
|
||||
fullscreenWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style)
|
||||
{
|
||||
bool opened = IsOpen();
|
||||
NzVector2i position;
|
||||
if (opened)
|
||||
position = m_impl->GetPosition();
|
||||
|
||||
Close();
|
||||
|
||||
// Inspiré du code de la SFML par Laurent Gomila
|
||||
if (style & Fullscreen)
|
||||
{
|
||||
if (fullscreenWindow)
|
||||
{
|
||||
NazaraError("Window (" + NzString::Pointer(fullscreenWindow) + ") already in fullscreen mode");
|
||||
style &= ~Fullscreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mode.IsFullscreenValid())
|
||||
{
|
||||
NazaraWarning("Mode is not fullscreen valid");
|
||||
mode = NzVideoMode::GetFullscreenModes()[0];
|
||||
}
|
||||
|
||||
fullscreenWindow = this;
|
||||
}
|
||||
}
|
||||
else if (style & Closable || style & Resizable)
|
||||
style |= Titlebar;
|
||||
|
||||
m_impl = new NzWindowImpl(this);
|
||||
if (!m_impl->Create(mode, title, style))
|
||||
{
|
||||
NazaraError("Failed to create window implementation");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ownsWindow = true;
|
||||
|
||||
if (!OnCreate())
|
||||
{
|
||||
NazaraError("Failed to initialize window extension");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl->EnableKeyRepeat(true);
|
||||
m_impl->EnableSmoothScrolling(false);
|
||||
m_impl->SetMaximumSize(-1, -1);
|
||||
m_impl->SetMinimumSize(-1, -1);
|
||||
m_impl->SetVisible(true);
|
||||
m_impl->ShowMouseCursor(true);
|
||||
|
||||
if (opened)
|
||||
m_impl->SetPosition(position.x, position.y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzWindow::Create(NzWindowHandle handle)
|
||||
{
|
||||
Close();
|
||||
|
||||
m_impl = new NzWindowImpl(this);
|
||||
if (!m_impl->Create(handle))
|
||||
{
|
||||
NazaraError("Unable to create window implementation");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ownsWindow = false;
|
||||
|
||||
if (!OnCreate())
|
||||
{
|
||||
NazaraError("Failed to initialize window's derivate");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzWindow::EnableKeyRepeat(bool enable)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->EnableKeyRepeat(enable);
|
||||
}
|
||||
|
||||
void NzWindow::EnableSmoothScrolling(bool enable)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->EnableSmoothScrolling(enable);
|
||||
}
|
||||
|
||||
NzWindowHandle NzWindow::GetHandle() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->GetHandle();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int NzWindow::GetHeight() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->GetHeight();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
NzVector2i NzWindow::GetPosition() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->GetPosition();
|
||||
else
|
||||
return NzVector2i(0);
|
||||
}
|
||||
|
||||
NzVector2i NzWindow::GetSize() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->GetSize();
|
||||
else
|
||||
return NzVector2i(0);
|
||||
}
|
||||
|
||||
NzString NzWindow::GetTitle() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->GetTitle();
|
||||
else
|
||||
return NzString();
|
||||
}
|
||||
|
||||
unsigned int NzWindow::GetWidth() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->GetWidth();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NzWindow::HasFocus() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->HasFocus();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzWindow::IsOpen() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
bool NzWindow::IsMinimized() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->IsMinimized();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzWindow::IsVisible() const
|
||||
{
|
||||
if (m_impl)
|
||||
return m_impl->IsVisible();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzWindow::PollEvent(NzEvent* event)
|
||||
{
|
||||
if (!m_impl)
|
||||
return false;
|
||||
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
NzLock lock(m_eventMutex);
|
||||
#else
|
||||
m_impl->ProcessEvents(false);
|
||||
#endif
|
||||
|
||||
if (!m_events.empty())
|
||||
{
|
||||
if (event)
|
||||
*event = m_events.front();
|
||||
|
||||
m_events.pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void NzWindow::SetEventListener(bool listener)
|
||||
{
|
||||
if (!m_impl)
|
||||
return;
|
||||
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
m_impl->SetEventListener(listener);
|
||||
if (!listener)
|
||||
{
|
||||
NzLock lock(m_eventMutex);
|
||||
while (!m_events.empty())
|
||||
m_events.pop();
|
||||
}
|
||||
#else
|
||||
if (m_ownsWindow)
|
||||
{
|
||||
// Inutile de transmettre l'ordre dans ce cas-là
|
||||
if (!listener)
|
||||
NazaraError("A non-threaded window needs to listen to events");
|
||||
}
|
||||
else
|
||||
m_impl->SetEventListener(listener);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzWindow::SetFocus()
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetFocus();
|
||||
}
|
||||
|
||||
void NzWindow::SetMaximumSize(const NzVector2i& maxSize)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetMaximumSize(maxSize.x, maxSize.y);
|
||||
}
|
||||
|
||||
void NzWindow::SetMaximumSize(int width, int height)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetMaximumSize(width, height);
|
||||
}
|
||||
|
||||
void NzWindow::SetMinimumSize(const NzVector2i& minSize)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetMinimumSize(minSize.x, minSize.y);
|
||||
}
|
||||
|
||||
void NzWindow::SetMinimumSize(int width, int height)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetMinimumSize(width, height);
|
||||
}
|
||||
|
||||
void NzWindow::SetPosition(const NzVector2i& position)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetPosition(position.x, position.y);
|
||||
}
|
||||
|
||||
void NzWindow::SetPosition(int x, int y)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetPosition(x, y);
|
||||
}
|
||||
|
||||
void NzWindow::SetSize(const NzVector2i& size)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetSize(size.x, size.y);
|
||||
}
|
||||
|
||||
void NzWindow::SetSize(unsigned int width, unsigned int height)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetSize(width, height);
|
||||
}
|
||||
|
||||
void NzWindow::SetTitle(const NzString& title)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetTitle(title);
|
||||
}
|
||||
|
||||
void NzWindow::SetVisible(bool visible)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->SetVisible(visible);
|
||||
}
|
||||
|
||||
void NzWindow::ShowMouseCursor(bool show)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->ShowMouseCursor(show);
|
||||
}
|
||||
|
||||
void NzWindow::StayOnTop(bool stayOnTop)
|
||||
{
|
||||
if (m_impl)
|
||||
m_impl->StayOnTop(stayOnTop);
|
||||
}
|
||||
|
||||
bool NzWindow::WaitEvent(NzEvent* event)
|
||||
{
|
||||
if (!m_impl)
|
||||
return false;
|
||||
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
NzLock 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_waitForEvent = false;
|
||||
}
|
||||
|
||||
if (!m_events.empty())
|
||||
{
|
||||
if (event)
|
||||
*event = m_events.front();
|
||||
|
||||
m_events.pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
#else
|
||||
while (m_events.empty())
|
||||
m_impl->ProcessEvents(true);
|
||||
|
||||
if (event)
|
||||
*event = m_events.front();
|
||||
|
||||
m_events.pop();
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzWindow::OnClose()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzWindow::OnCreate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzWindow::PushEvent(const NzEvent& event)
|
||||
{
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
m_eventMutex.Lock();
|
||||
#endif
|
||||
|
||||
m_events.push(event);
|
||||
|
||||
#if NAZARA_UTILITY_THREADED_WINDOW
|
||||
m_eventMutex.Unlock();
|
||||
|
||||
if (m_waitForEvent)
|
||||
{
|
||||
m_eventConditionMutex.Lock();
|
||||
m_eventCondition.Signal();
|
||||
m_eventConditionMutex.Unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user