Merge remote-tracking branch 'refs/remotes/origin/master' into gui

This commit is contained in:
Lynix
2016-11-30 13:08:08 +01:00
227 changed files with 9347 additions and 4815 deletions

View File

@@ -61,8 +61,6 @@ namespace Nz
* \return true if creation was succesful
*
* \param soundStream Sound stream which is the source for the music
*
* \remark Produces a NazaraError if soundStream is invalid with NAZARA_AUDIO_SAFE defined
*/
bool Music::Create(SoundStream* soundStream)
@@ -86,13 +84,14 @@ namespace Nz
/*!
* \brief Destroys the current music and frees resources
*
* \remark If the Music is playing, it is stopped first.
*/
void Music::Destroy()
{
if (m_impl)
{
Stop();
StopThread();
delete m_impl;
m_impl = nullptr;
@@ -104,18 +103,11 @@ namespace Nz
*
* \param loop Should music loop
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \remark Music must be valid when calling this function
*/
void Music::EnableLooping(bool loop)
{
#if NAZARA_AUDIO_SAFE
if (!m_impl)
{
NazaraError("Music not created");
return;
}
#endif
NazaraAssert(m_impl, "Music not created");
m_impl->loop = loop;
}
@@ -124,18 +116,11 @@ namespace Nz
* \brief Gets the duration of the music
* \return Duration of the music in milliseconds
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \remark Music must be valid when calling this function
*/
UInt32 Music::GetDuration() const
{
#if NAZARA_AUDIO_SAFE
if (!m_impl)
{
NazaraError("Music not created");
return 0;
}
#endif
NazaraAssert(m_impl, "Music not created");
return m_impl->stream->GetDuration();
}
@@ -144,18 +129,11 @@ namespace Nz
* \brief Gets the format of the music
* \return Enumeration of type AudioFormat (mono, stereo, ...)
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \remark Music must be valid when calling this function
*/
AudioFormat Music::GetFormat() const
{
#if NAZARA_AUDIO_SAFE
if (!m_impl)
{
NazaraError("Music not created");
return AudioFormat_Unknown;
}
#endif
NazaraAssert(m_impl, "Music not created");
return m_impl->stream->GetFormat();
}
@@ -164,7 +142,7 @@ namespace Nz
* \brief Gets the current offset in the music
* \return Offset in milliseconds (works with entire seconds)
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \remark Music must be valid when calling this function
*/
UInt32 Music::GetPlayingOffset() const
{
@@ -183,7 +161,7 @@ namespace Nz
* \brief Gets the number of samples in the music
* \return Count of samples (number of seconds * sample rate * channel count)
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \remark Music must be valid when calling this function
*/
UInt64 Music::GetSampleCount() const
{
@@ -196,7 +174,7 @@ namespace Nz
* \brief Gets the rates of sample in the music
* \return Rate of sample in Hertz (Hz)
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \remark Music must be valid when calling this function
*/
UInt32 Music::GetSampleRate() const
{
@@ -209,8 +187,7 @@ namespace Nz
* \brief Gets the status of the music
* \return Enumeration of type SoundStatus (Playing, Stopped, ...)
*
* \remark If the music is not playing, Stopped is returned
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \remark Music must be valid when calling this function
*/
SoundStatus Music::GetStatus() const
{
@@ -229,44 +206,37 @@ namespace Nz
* \brief Checks whether the music is looping
* \return true if it is the case
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \remark Music must be valid when calling this function
*/
bool Music::IsLooping() const
{
#if NAZARA_AUDIO_SAFE
if (!m_impl)
{
NazaraError("Music not created");
return false;
}
#endif
NazaraAssert(m_impl, "Music not created");
return m_impl->loop;
}
/*!
* \brief Loads the music from file
* \return true if loading is successful
* \brief Opens the music from a file
* \return true if the file was successfully opened
*
* \param filePath Path to the file
* \param params Parameters for the music
*/
bool Music::OpenFromFile(const String& filePath, const MusicParams& params)
{
return MusicLoader::LoadFromFile(this, filePath, params);
}
/*!
* \brief Loads the music from memory
* \brief Opens the music from memory
* \return true if loading is successful
*
* \param data Raw memory
* \param size Size of the memory
* \param params Parameters for the music
*
* \remark The memory pointer must stay valid (accessible) as long as the music is playing
*/
bool Music::OpenFromMemory(const void* data, std::size_t size, const MusicParams& params)
{
return MusicLoader::LoadFromMemory(this, data, size, params);
@@ -278,8 +248,9 @@ namespace Nz
*
* \param stream Stream to the music
* \param params Parameters for the music
*
* \remark The stream must stay valid as long as the music is playing
*/
bool Music::OpenFromStream(Stream& stream, const MusicParams& params)
{
return MusicLoader::LoadFromStream(this, stream, params);
@@ -287,8 +258,9 @@ namespace Nz
/*!
* \brief Pauses the music
*
* \remark Music must be valid when calling this function
*/
void Music::Pause()
{
alSourcePause(m_source);
@@ -297,18 +269,16 @@ namespace Nz
/*!
* \brief Plays the music
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* Plays/Resume the music.
* If the music is currently playing, resets the playing offset to the beginning offset.
* If the music is currently paused, resumes the playing.
* If the music is currently stopped, starts the playing at the previously set playing offset.
*
* \remark Music must be valid when calling this function
*/
void Music::Play()
{
#if NAZARA_AUDIO_SAFE
if (!m_impl)
{
NazaraError("Music not created");
return;
}
#endif
NazaraAssert(m_impl, "Music not created");
// Maybe we are already playing
if (m_impl->streaming)
@@ -336,25 +306,20 @@ namespace Nz
}
/*!
* \brief Sets the playing offset for the music
* \brief Changes the playing offset of the music
*
* \param offset Offset in the music in milliseconds
* If the music is not playing, this sets the playing offset for the next Play call
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \param offset The offset in milliseconds
*
* \remark Music must be valid when calling this function
*/
void Music::SetPlayingOffset(UInt32 offset)
{
#if NAZARA_AUDIO_SAFE
if (!m_impl)
{
NazaraError("Music not created");
return;
}
#endif
NazaraAssert(m_impl, "Music not created");
bool isPlaying = m_impl->streaming;
if (isPlaying)
Stop();
@@ -368,33 +333,16 @@ namespace Nz
/*!
* \brief Stops the music
*
* \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined
* \remark Music must be valid when calling this function
*/
void Music::Stop()
{
#if NAZARA_AUDIO_SAFE
if (!m_impl)
{
NazaraError("Music not created");
return;
}
#endif
NazaraAssert(m_impl, "Music not created");
if (m_impl->streaming)
{
m_impl->streaming = false;
m_impl->thread.Join();
}
StopThread();
SetPlayingOffset(0);
}
/*!
* \brief Fills the buffer and queues it up
* \return true if operation was successful
*
* \param buffer Index of the buffer
*/
bool Music::FillAndQueueBuffer(unsigned int buffer)
{
std::size_t sampleCount = m_impl->chunkSamples.size();
@@ -425,10 +373,6 @@ namespace Nz
return sampleRead != sampleCount; // End of stream (Does not happen when looping)
}
/*!
* \brief Thread function for the music
*/
void Music::MusicThread()
{
// Allocation of streaming buffers
@@ -463,11 +407,11 @@ namespace Nz
{
ALuint buffer;
alSourceUnqueueBuffers(m_source, 1, &buffer);
ALint bits, size;
alGetBufferi(buffer, AL_BITS, &bits);
alGetBufferi(buffer, AL_SIZE, &size);
if (bits != 0)
m_impl->processedSamples += (8 * size) / bits;
@@ -495,5 +439,14 @@ namespace Nz
alDeleteBuffers(NAZARA_AUDIO_STREAMED_BUFFER_COUNT, buffers);
}
void Music::StopThread()
{
if (m_impl->streaming)
{
m_impl->streaming = false;
m_impl->thread.Join();
}
}
MusicLoader::LoaderList Music::s_loaders;
}

View File

@@ -15,6 +15,22 @@ namespace Nz
* \brief Core class that represents an array of bytes
*/
/*!
* \brief Gives a string representation in base 16
* \return String in base 16
*/
String ByteArray::ToHex() const
{
std::size_t length = m_array.size() * 2;
String hexOutput(length, '\0');
for (std::size_t i = 0; i < m_array.size(); ++i)
std::sprintf(&hexOutput[i * 2], "%02x", m_array[i]);
return hexOutput;
}
/*!
* \brief Output operator
* \return The stream

View File

@@ -24,7 +24,7 @@ namespace Nz
* \param openMode Reading/writing mode for the stream
*/
ByteStream::ByteStream(ByteArray* byteArray, UInt32 openMode) :
ByteStream::ByteStream(ByteArray* byteArray, OpenModeFlags openMode) :
ByteStream()
{
SetStream(byteArray, openMode);
@@ -67,7 +67,7 @@ namespace Nz
* \param openMode Reading/writing mode for the stream
*/
void ByteStream::SetStream(ByteArray* byteArray, UInt32 openMode)
void ByteStream::SetStream(ByteArray* byteArray, OpenModeFlags openMode)
{
std::unique_ptr<Stream> stream(new MemoryStream(byteArray, openMode));

View File

@@ -64,7 +64,7 @@ namespace Nz
* \param openMode Flag of the file
*/
File::File(const String& filePath, UInt32 openMode) :
File::File(const String& filePath, OpenModeFlags openMode) :
File()
{
Open(filePath, openMode);
@@ -311,7 +311,7 @@ namespace Nz
* \remark Produces a NazaraError if OS error to open a file
*/
bool File::Open(unsigned int openMode)
bool File::Open(OpenModeFlags openMode)
{
NazaraLock(m_mutex)
@@ -352,7 +352,7 @@ namespace Nz
* \remark Produces a NazaraError if OS error to open a file
*/
bool File::Open(const String& filePath, unsigned int openMode)
bool File::Open(const String& filePath, OpenModeFlags openMode)
{
NazaraLock(m_mutex)
@@ -906,5 +906,5 @@ namespace Nz
}
return true;
};
}
}

View File

@@ -65,7 +65,7 @@ namespace Nz
* \remark Produces a NazaraAssert if byteArray is nullptr
*/
void MemoryStream::SetBuffer(ByteArray* byteArray, UInt32 openMode)
void MemoryStream::SetBuffer(ByteArray* byteArray, OpenModeFlags openMode)
{
NazaraAssert(byteArray, "Invalid ByteArray");

View File

@@ -49,7 +49,7 @@ namespace Nz
return static_cast<UInt64>(position);
}
bool FileImpl::Open(const String& filePath, UInt32 mode)
bool FileImpl::Open(const String& filePath, OpenModeFlags mode)
{
int flags;
mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
@@ -66,6 +66,9 @@ namespace Nz
if (mode & OpenMode_Append)
flags |= O_APPEND;
if (mode & OpenMode_MustExist)
flags &= ~O_CREAT;
if (mode & OpenMode_Truncate)
flags |= O_TRUNC;

View File

@@ -36,7 +36,7 @@ namespace Nz
bool EndOfFile() const;
void Flush();
UInt64 GetCursorPos() const;
bool Open(const String& filePath, UInt32 mode);
bool Open(const String& filePath, OpenModeFlags mode);
std::size_t Read(void* buffer, std::size_t size);
bool SetCursorPos(CursorPosition pos, Int64 offset);
bool SetSize(UInt64 size);

View File

@@ -55,20 +55,20 @@ namespace Nz
return position.QuadPart;
}
bool FileImpl::Open(const String& filePath, UInt32 mode)
bool FileImpl::Open(const String& filePath, OpenModeFlags mode)
{
DWORD access = 0;
DWORD shareMode = FILE_SHARE_READ;
DWORD openMode = 0;
if (mode & OpenMode_ReadOnly)
{
access |= GENERIC_READ;
if (mode & OpenMode_MustExit || (mode & OpenMode_WriteOnly) == 0)
if (mode & OpenMode_MustExist || (mode & OpenMode_WriteOnly) == 0)
openMode |= OPEN_EXISTING;
}
if (mode & OpenMode_WriteOnly)
{
if (mode & OpenMode_Append)
@@ -78,7 +78,7 @@ namespace Nz
if (mode & OpenMode_Truncate)
openMode |= CREATE_ALWAYS;
else if (mode & OpenMode_MustExit)
else if (mode & OpenMode_MustExist)
openMode |= OPEN_EXISTING;
else
openMode |= OPEN_ALWAYS;

View File

@@ -29,7 +29,7 @@ namespace Nz
bool EndOfFile() const;
void Flush();
UInt64 GetCursorPos() const;
bool Open(const String& filePath, UInt32 mode);
bool Open(const String& filePath, OpenModeFlags mode);
std::size_t Read(void* buffer, std::size_t size);
bool SetCursorPos(CursorPosition pos, Int64 offset);
bool SetSize(UInt64 size);

View File

@@ -159,13 +159,13 @@ namespace Nz
instanceBuffer->SetVertexDeclaration(VertexDeclaration::Get(VertexLayout_Matrix4));
const Matrix4f* instanceMatrices = &instances[0];
unsigned int instanceCount = instances.size();
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // The number of matrices that can be hold in the buffer
std::size_t instanceCount = instances.size();
std::size_t maxInstanceCount = instanceBuffer->GetVertexCount(); // The number of matrices that can be hold in the buffer
while (instanceCount > 0)
{
// We compute the number of instances that we will be able to show this time (Depending on the instance buffer size)
unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
std::size_t renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
instanceCount -= renderedInstanceCount;
// We fill the instancing buffer with our world matrices

View File

@@ -267,13 +267,13 @@ namespace Nz
const Texture* overlay = overlayIt.first;
auto& spriteChainVector = overlayIt.second.spriteChains;
unsigned int spriteChainCount = spriteChainVector.size();
std::size_t spriteChainCount = spriteChainVector.size();
if (spriteChainCount > 0)
{
Renderer::SetTexture(overlayUnit, (overlay) ? overlay : &m_whiteTexture);
unsigned int spriteChain = 0; // Which chain of sprites are we treating
unsigned int spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
std::size_t spriteChain = 0; // Which chain of sprites are we treating
std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
do
{
@@ -281,13 +281,13 @@ namespace Nz
BufferMapper<VertexBuffer> vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite);
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
unsigned int spriteCount = 0;
unsigned int maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
std::size_t spriteCount = 0;
std::size_t maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
do
{
ForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain];
unsigned int count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset);
std::size_t count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset);
std::memcpy(vertices, currentChain.vertices + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV));
vertices += count * 4;
@@ -373,17 +373,17 @@ namespace Nz
auto& entry = matIt.second;
auto& billboardVector = entry.billboards;
unsigned int billboardCount = billboardVector.size();
std::size_t billboardCount = billboardVector.size();
if (billboardCount > 0)
{
// We begin to apply the material (and get the shader activated doing so)
material->Apply(pipelineInstance);
const ForwardRenderQueue::BillboardData* data = &billboardVector[0];
unsigned int maxBillboardPerDraw = instanceBuffer->GetVertexCount();
std::size_t maxBillboardPerDraw = instanceBuffer->GetVertexCount();
do
{
unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
billboardCount -= renderedBillboardCount;
instanceBuffer->Fill(data, 0, renderedBillboardCount, true);
@@ -435,12 +435,12 @@ namespace Nz
auto& billboardVector = entry.billboards;
const ForwardRenderQueue::BillboardData* data = &billboardVector[0];
unsigned int maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4);
std::size_t maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4);
unsigned int billboardCount = billboardVector.size();
std::size_t billboardCount = billboardVector.size();
do
{
unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
billboardCount -= renderedBillboardCount;
BufferMapper<VertexBuffer> vertexMapper(m_billboardPointBuffer, BufferAccess_DiscardAndWrite, 0, renderedBillboardCount * 4);
@@ -584,13 +584,13 @@ namespace Nz
instanceBuffer->SetVertexDeclaration(VertexDeclaration::Get(VertexLayout_Matrix4));
const Matrix4f* instanceMatrices = &instances[0];
unsigned int instanceCount = instances.size();
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch
std::size_t instanceCount = instances.size();
std::size_t maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch
while (instanceCount > 0)
{
// We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size)
unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
std::size_t renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
instanceCount -= renderedInstanceCount;
// We fill the instancing buffer with our world matrices

View File

@@ -383,7 +383,7 @@ namespace Nz
auto& transparentModelData = currentLayer.transparentModelData;
// The material is transparent, we must draw this mesh using another way (after the rendering of opages objects while sorting them)
unsigned int index = transparentModelData.size();
std::size_t index = transparentModelData.size();
transparentModelData.resize(index+1);
TransparentModelData& data = transparentModelData.back();
@@ -527,6 +527,24 @@ namespace Nz
layers.erase(it++);
else
{
for (auto& pipelinePair : layer.billboards)
{
auto& pipelineEntry = pipelinePair.second;
if (pipelineEntry.enabled)
{
for (auto& matIt : pipelinePair.second.materialMap)
{
auto& entry = matIt.second;
auto& billboardVector = entry.billboards;
billboardVector.clear();
}
}
pipelineEntry.enabled = false;
}
for (auto& pipelinePair : layer.basicSprites)
{
auto& pipelineEntry = pipelinePair.second;
@@ -603,7 +621,7 @@ namespace Nz
{
Layer& layer = pair.second;
std::sort(layer.transparentModels.begin(), layer.transparentModels.end(), [&layer, &nearPlane, &viewerNormal] (unsigned int index1, unsigned int index2)
std::sort(layer.transparentModels.begin(), layer.transparentModels.end(), [&layer, &nearPlane, &viewerNormal] (std::size_t index1, std::size_t index2)
{
const Spheref& sphere1 = layer.transparentModelData[index1].squaredBoundingSphere;
const Spheref& sphere2 = layer.transparentModelData[index2].squaredBoundingSphere;
@@ -672,7 +690,7 @@ namespace Nz
BatchedBillboardEntry& entry = it->second;
auto& billboardVector = entry.billboards;
unsigned int prevSize = billboardVector.size();
std::size_t prevSize = billboardVector.size();
billboardVector.resize(prevSize + count);
return &billboardVector[prevSize];

View File

@@ -33,8 +33,8 @@ namespace Nz
Vector2f uv;
};
unsigned int s_maxQuads = std::numeric_limits<UInt16>::max() / 6;
unsigned int s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB
std::size_t s_maxQuads = std::numeric_limits<UInt16>::max() / 6;
std::size_t s_vertexBufferSize = 4 * 1024 * 1024; // 4 MiB
}
/*!
@@ -347,13 +347,13 @@ namespace Nz
const Texture* overlay = overlayIt.first;
auto& spriteChainVector = overlayIt.second.spriteChains;
unsigned int spriteChainCount = spriteChainVector.size();
std::size_t spriteChainCount = spriteChainVector.size();
if (spriteChainCount > 0)
{
Renderer::SetTexture(overlayUnit, (overlay) ? overlay : &m_whiteTexture);
unsigned int spriteChain = 0; // Which chain of sprites are we treating
unsigned int spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
std::size_t spriteChain = 0; // Which chain of sprites are we treating
std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
do
{
@@ -361,13 +361,13 @@ namespace Nz
BufferMapper<VertexBuffer> vertexMapper(m_spriteBuffer, BufferAccess_DiscardAndWrite);
VertexStruct_XYZ_Color_UV* vertices = static_cast<VertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
unsigned int spriteCount = 0;
unsigned int maxSpriteCount = std::min(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
std::size_t spriteCount = 0;
std::size_t maxSpriteCount = std::min<std::size_t>(s_maxQuads, m_spriteBuffer.GetVertexCount() / 4);
do
{
ForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain];
unsigned int count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset);
std::size_t count = std::min(maxSpriteCount - spriteCount, currentChain.spriteCount - spriteChainOffset);
std::memcpy(vertices, currentChain.vertices + spriteChainOffset * 4, 4 * count * sizeof(VertexStruct_XYZ_Color_UV));
vertices += count * 4;
@@ -450,17 +450,17 @@ namespace Nz
auto& entry = matIt.second;
auto& billboardVector = entry.billboards;
unsigned int billboardCount = billboardVector.size();
std::size_t billboardCount = billboardVector.size();
if (billboardCount > 0)
{
// We begin to apply the material (and get the shader activated doing so)
material->Apply(pipelineInstance);
const ForwardRenderQueue::BillboardData* data = &billboardVector[0];
unsigned int maxBillboardPerDraw = instanceBuffer->GetVertexCount();
std::size_t maxBillboardPerDraw = instanceBuffer->GetVertexCount();
do
{
unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
billboardCount -= renderedBillboardCount;
instanceBuffer->Fill(data, 0, renderedBillboardCount, true);
@@ -512,12 +512,12 @@ namespace Nz
auto& billboardVector = entry.billboards;
const ForwardRenderQueue::BillboardData* data = &billboardVector[0];
unsigned int maxBillboardPerDraw = std::min(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4);
std::size_t maxBillboardPerDraw = std::min<std::size_t>(s_maxQuads, m_billboardPointBuffer.GetVertexCount() / 4);
unsigned int billboardCount = billboardVector.size();
std::size_t billboardCount = billboardVector.size();
do
{
unsigned int renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
std::size_t renderedBillboardCount = std::min(billboardCount, maxBillboardPerDraw);
billboardCount -= renderedBillboardCount;
BufferMapper<VertexBuffer> vertexMapper(m_billboardPointBuffer, BufferAccess_DiscardAndWrite, 0, renderedBillboardCount * 4);
@@ -561,8 +561,6 @@ namespace Nz
Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, renderedBillboardCount * 6);
}
while (billboardCount > 0);
billboardVector.clear();
}
}
}
@@ -666,16 +664,16 @@ namespace Nz
// With instancing, impossible to select the lights for each object
// So, it's only activated for directional lights
unsigned int lightCount = m_renderQueue.directionalLights.size();
unsigned int lightIndex = 0;
std::size_t lightCount = m_renderQueue.directionalLights.size();
std::size_t lightIndex = 0;
RendererComparison oldDepthFunc = Renderer::GetDepthFunc();
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
for (unsigned int pass = 0; pass < passCount; ++pass)
std::size_t passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
for (std::size_t pass = 0; pass < passCount; ++pass)
{
if (shaderUniforms->hasLightUniforms)
{
unsigned int renderedLightCount = std::min(lightCount, NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
std::size_t renderedLightCount = std::min<std::size_t>(lightCount, NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS);
lightCount -= renderedLightCount;
if (pass == 1)
@@ -690,18 +688,18 @@ namespace Nz
}
// Sends the uniforms
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
for (std::size_t i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset * i, freeTextureUnit + i);
}
const Matrix4f* instanceMatrices = &instances[0];
unsigned int instanceCount = instances.size();
unsigned int maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch
std::size_t instanceCount = instances.size();
std::size_t maxInstanceCount = instanceBuffer->GetVertexCount(); // Maximum number of instance in one batch
while (instanceCount > 0)
{
// We compute the number of instances that we will be able to draw this time (depending on the instancing buffer size)
unsigned int renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
std::size_t renderedInstanceCount = std::min(instanceCount, maxInstanceCount);
instanceCount -= renderedInstanceCount;
// We fill the instancing buffer with our world matrices
@@ -726,16 +724,16 @@ namespace Nz
// Choose the lights depending on an object position and apparent radius
ChooseLights(Spheref(matrix.GetTranslation() + squaredBoundingSphere.GetPosition(), squaredBoundingSphere.radius));
unsigned int lightCount = m_lights.size();
std::size_t lightCount = m_lights.size();
Renderer::SetMatrix(MatrixType_World, matrix);
unsigned int lightIndex = 0;
std::size_t lightIndex = 0;
RendererComparison oldDepthFunc = Renderer::GetDepthFunc(); // In the case where we have to change it
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
for (unsigned int pass = 0; pass < passCount; ++pass)
std::size_t passCount = (lightCount == 0) ? 1 : (lightCount - 1) / NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
for (std::size_t pass = 0; pass < passCount; ++pass)
{
lightCount -= std::min(lightCount, NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
lightCount -= std::min<std::size_t>(lightCount, NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS);
if (pass == 1)
{
@@ -749,7 +747,7 @@ namespace Nz
}
// Sends the light uniforms to the shader
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
for (std::size_t i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset*i, freeTextureUnit + i);
// And we draw
@@ -772,7 +770,6 @@ namespace Nz
}
}
}
instances.clear();
}
}
}
@@ -835,7 +832,7 @@ namespace Nz
{
lightCount = std::min(m_renderQueue.directionalLights.size(), static_cast<decltype(m_renderQueue.directionalLights.size())>(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS));
for (unsigned int i = 0; i < lightCount; ++i)
for (std::size_t i = 0; i < lightCount; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset * i, freeTextureUnit++);
}
@@ -874,7 +871,7 @@ namespace Nz
float radius = modelData.squaredBoundingSphere.radius;
ChooseLights(Spheref(position, radius), false);
for (unsigned int i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
for (std::size_t i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset*i, freeTextureUnit++);
}

View File

@@ -94,6 +94,7 @@ namespace Nz
void InstancedRenderable::UpdateData(InstanceData* instanceData) const
{
NazaraAssert(instanceData, "Invalid instance data");
NazaraUnused(instanceData);
}
InstancedRenderableLibrary::LibraryMap InstancedRenderable::s_library;

View File

@@ -100,7 +100,7 @@ namespace Nz
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if type is not supported
*/
void ParticleDeclaration::EnableComponent(ParticleComponent component, ComponentType type, unsigned int offset)
void ParticleDeclaration::EnableComponent(ParticleComponent component, ComponentType type, std::size_t offset)
{
#ifdef NAZARA_DEBUG
if (component > ParticleComponent_Max)
@@ -145,7 +145,7 @@ namespace Nz
* \remark Produces a NazaraError with NAZARA_GRAPHICS_SAFE defined if enumeration is equal to ParticleComponent_Unused
*/
void ParticleDeclaration::GetComponent(ParticleComponent component, bool* enabled, ComponentType* type, unsigned int* offset) const
void ParticleDeclaration::GetComponent(ParticleComponent component, bool* enabled, ComponentType* type, std::size_t* offset) const
{
#ifdef NAZARA_DEBUG
if (component > ParticleComponent_Max)
@@ -180,7 +180,7 @@ namespace Nz
* \return Stride of the declaration
*/
unsigned int ParticleDeclaration::GetStride() const
std::size_t ParticleDeclaration::GetStride() const
{
return m_stride;
}

View File

@@ -74,11 +74,11 @@ namespace Nz
if (emissionCount >= 1.f)
{
// We compute the maximum number of particles which can be emitted
unsigned int emissionCountInt = static_cast<unsigned int>(emissionCount);
unsigned int maxParticleCount = emissionCountInt * m_emissionCount;
std::size_t emissionCountInt = static_cast<std::size_t>(emissionCount);
std::size_t maxParticleCount = emissionCountInt * m_emissionCount;
// We get the number of particles that we are able to create (depending on the free space)
unsigned int particleCount = std::min(maxParticleCount, system.GetMaxParticleCount() - system.GetParticleCount());
std::size_t particleCount = std::min(maxParticleCount, system.GetMaxParticleCount() - system.GetParticleCount());
if (particleCount == 0)
return;
@@ -115,7 +115,7 @@ namespace Nz
* \return Current emission count
*/
unsigned int ParticleEmitter::GetEmissionCount() const
std::size_t ParticleEmitter::GetEmissionCount() const
{
return m_emissionCount;
}
@@ -146,7 +146,7 @@ namespace Nz
* \param count Emission count
*/
void ParticleEmitter::SetEmissionCount(unsigned int count)
void ParticleEmitter::SetEmissionCount(std::size_t count)
{
m_emissionCount = count;
}

View File

@@ -142,11 +142,10 @@ namespace Nz
* \remark Produces a NazaraAssert if renderQueue is invalid
*/
void ParticleGroup::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix) const
void ParticleGroup::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& /*transformMatrix*/) const
{
NazaraAssert(m_renderer, "Invalid particle renderer");
NazaraAssert(renderQueue, "Invalid renderqueue");
NazaraUnused(transformMatrix);
if (m_particleCount > 0)
{
@@ -215,7 +214,7 @@ namespace Nz
if (m_particleCount + count > m_maxParticleCount)
return nullptr;
unsigned int particlesIndex = m_particleCount;
std::size_t particlesIndex = m_particleCount;
m_particleCount += count;
return &m_buffer[particlesIndex * m_particleSize];
@@ -264,7 +263,7 @@ namespace Nz
* \return Current maximum number
*/
unsigned int ParticleGroup::GetMaxParticleCount() const
std::size_t ParticleGroup::GetMaxParticleCount() const
{
return m_maxParticleCount;
}
@@ -274,7 +273,7 @@ namespace Nz
* \return Current number
*/
unsigned int ParticleGroup::GetParticleCount() const
std::size_t ParticleGroup::GetParticleCount() const
{
return m_particleCount;
}
@@ -284,7 +283,7 @@ namespace Nz
* \return Current size
*/
unsigned int ParticleGroup::GetParticleSize() const
std::size_t ParticleGroup::GetParticleSize() const
{
return m_particleSize;
}
@@ -295,7 +294,7 @@ namespace Nz
* \param index Index of the particle
*/
void ParticleGroup::KillParticle(unsigned int index)
void ParticleGroup::KillParticle(std::size_t index)
{
///FIXME: Verify the index
@@ -402,10 +401,8 @@ namespace Nz
* \param transformMatrix Matrix transformation for our bounding volume
*/
void ParticleGroup::UpdateBoundingVolume(const Matrix4f& transformMatrix)
void ParticleGroup::UpdateBoundingVolume(const Matrix4f& /*transformMatrix*/)
{
NazaraUnused(transformMatrix);
// Nothing to do here (our bounding volume is global)
}

View File

@@ -170,7 +170,7 @@ namespace Nz
* \return Number of techniques
*/
unsigned int RenderTechniques::GetCount()
std::size_t RenderTechniques::GetCount()
{
return s_renderTechniques.size();
}

View File

@@ -44,6 +44,64 @@ namespace Nz
m_boundingVolume.Set(-origin, m_size.x*Vector3f::Right() + m_size.y*Vector3f::Down() - origin);
}
/*!
* \brief Sets the material of the sprite from a name
*
* Tries to get a material from the MaterialLibrary and then the MaterialManager (which will treat the name as a path)
* Fails if the texture name is not a part of the MaterialLibrary nor the MaterialManager (which fails if it couldn't load the texture from its filepath)
*
* \param materialName Named texture for the material
* \param resizeSprite Should the sprite be resized to the material diffuse map size?
*
* \return True if the material was found or loaded from its name/path, false if it couldn't
*/
bool Sprite::SetMaterial(String materialName, bool resizeSprite)
{
MaterialRef material = MaterialLibrary::Query(materialName);
if (!material)
{
material = MaterialManager::Get(materialName);
if (!material)
{
NazaraError("Failed to get material \"" + materialName + "\"");
return false;
}
}
SetMaterial(std::move(material), resizeSprite);
return true;
}
/*!
* \brief Sets the texture of the sprite from a name
*
* Tries to get a texture from the TextureLibrary and then the TextureManager (which will treat the name as a path)
* Fails if the texture name is not a part of the TextureLibrary nor the TextureManager (which fails if it couldn't load the texture from its filepath)
*
* \param textureName Named texture for the sprite
* \param resizeSprite Should the sprite be resized to the texture size?
*
* \return True if the texture was found or loaded from its name/path, false if it couldn't
*
* \remark The sprite material gets copied to prevent accidentally changing other drawable materials
*/
bool Sprite::SetTexture(String textureName, bool resizeSprite)
{
TextureRef texture = TextureLibrary::Query(textureName);
if (!texture)
{
texture = TextureManager::Get(textureName);
if (!texture)
{
NazaraError("Failed to get texture \"" + textureName + "\"");
return false;
}
}
SetTexture(std::move(texture), resizeSprite);
return true;
}
/*!
* \brief Updates the data of the sprite
*

View File

@@ -202,8 +202,8 @@ namespace Nz
void TextSprite::MakeBoundingVolume() const
{
Rectf bounds(m_localBounds);
Vector2f max = bounds.GetMaximum();
Vector2f min = bounds.GetMinimum();
Vector2f max = m_scale * bounds.GetMaximum();
Vector2f min = m_scale * bounds.GetMinimum();
m_boundingVolume.Set(min.x * Vector3f::Right() + min.y * Vector3f::Down(), max.x * Vector3f::Right() + max.y * Vector3f::Down());
}

View File

@@ -127,7 +127,7 @@ namespace Nz
* \remark Produces a NazaraAssert if cursor position is greather than the capacity
*/
void NetPacket::InitStream(std::size_t minCapacity, UInt64 cursorPos, UInt32 openMode)
void NetPacket::InitStream(std::size_t minCapacity, UInt64 cursorPos, OpenModeFlags openMode)
{
NazaraAssert(minCapacity >= cursorPos, "Cannot init stream with a smaller capacity than wanted cursor pos");
@@ -146,7 +146,7 @@ namespace Nz
if (!m_buffer)
m_buffer = std::make_unique<ByteArray>();
m_buffer->Resize(static_cast<std::size_t>(cursorPos));
m_buffer->Resize(minCapacity);
m_memoryStream.SetBuffer(m_buffer.get(), openMode);
m_memoryStream.SetCursorPos(cursorPos);

View File

@@ -385,7 +385,7 @@ namespace Nz
* \remark Produces a NazaraError because it is a special stream
*/
bool TcpClient::SetCursorPos(UInt64 offset)
bool TcpClient::SetCursorPos(UInt64 /*offset*/)
{
NazaraError("SetCursorPos() cannot be used on sequential streams");
return false;

View File

@@ -437,6 +437,10 @@ namespace Nz
return result;
#else
NazaraUnused(fdarray);
NazaraUnused(nfds);
NazaraUnused(timeout);
if (error)
*error = SocketError_NotSupported;

View File

@@ -10,7 +10,7 @@
namespace Nz
{
Collider2D::~Collider2D() = default;
/******************************** BoxCollider2D *********************************/
BoxCollider2D::BoxCollider2D(const Vector2f& size, float radius) :
@@ -84,4 +84,25 @@ namespace Nz
{
return std::vector<cpShape*>();
}
/******************************** SegmentCollider2D *********************************/
float SegmentCollider2D::ComputeInertialMatrix(float mass) const
{
return static_cast<float>(cpMomentForSegment(mass, cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness));
}
ColliderType2D SegmentCollider2D::GetType() const
{
return ColliderType2D_Segment;
}
std::vector<cpShape*> SegmentCollider2D::CreateShapes(RigidBody2D* body) const
{
std::vector<cpShape*> shapes;
shapes.push_back(cpSegmentShapeNew(body->GetHandle(), cpv(m_first.x, m_first.y), cpv(m_second.x, m_second.y), m_thickness));
return shapes;
}
}

View File

@@ -2,8 +2,8 @@
// This file is part of the "Nazara Engine - Physics 2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics3D/Config.hpp>
#if NAZARA_PHYSICS_MANAGE_MEMORY
#include <Nazara/Physics2D/Config.hpp>
#if NAZARA_PHYSICS2D_MANAGE_MEMORY
#include <Nazara/Core/MemoryManager.hpp>
#include <new> // Nécessaire ?

View File

@@ -24,7 +24,7 @@ namespace Nz
Vector2f PhysWorld2D::GetGravity() const
{
cpVect gravity = cpSpaceGetGravity(m_handle);
return Vector2f(gravity.x, gravity.y);
return Vector2f(Vector2<cpFloat>(gravity.x, gravity.y));
}
cpSpace* PhysWorld2D::GetHandle() const

View File

@@ -22,13 +22,11 @@ namespace Nz
m_geom(),
m_world(world),
m_gravityFactor(1.f),
m_mass(0.f)
m_mass(1.f)
{
NazaraAssert(m_world, "Invalid world");
m_handle = cpBodyNew(0.f, 0.f);
cpBodySetUserData(m_handle, this);
cpSpaceAddBody(m_world->GetHandle(), m_handle);
Create();
SetGeom(geom);
SetMass(mass);
@@ -43,9 +41,7 @@ namespace Nz
NazaraAssert(m_world, "Invalid world");
NazaraAssert(m_geom, "Invalid geometry");
m_handle = cpBodyNew(0.f, 0.f);
cpBodySetUserData(m_handle, this);
cpSpaceAddBody(m_world->GetHandle(), m_handle);
Create();
SetGeom(object.GetGeom());
SetMass(object.GetMass());
@@ -77,7 +73,7 @@ namespace Nz
switch (coordSys)
{
case CoordSys_Global:
cpBodyApplyForceAtWorldPoint(m_handle, cpv(force.x, force.y), cpv(force.x, force.y));
cpBodyApplyForceAtWorldPoint(m_handle, cpv(force.x, force.y), cpv(point.x, point.y));
break;
case CoordSys_Local:
@@ -169,19 +165,60 @@ namespace Nz
cpBodySetAngularVelocity(m_handle, angularVelocity);
}
void RigidBody2D::SetGeom(Collider2DRef geom)
{
// We have no public way of getting rid of an existing geom without removing the whole body
// So let's save some attributes of the body, destroy it and rebuild it
if (m_geom)
{
cpVect pos = cpBodyGetPosition(m_handle);
cpFloat mass = cpBodyGetMass(m_handle);
cpFloat moment = cpBodyGetMoment(m_handle);
cpFloat rot = cpBodyGetAngle(m_handle);
cpVect vel = cpBodyGetVelocity(m_handle);
Destroy();
Create(mass, moment);
cpBodySetAngle(m_handle, rot);
cpBodySetPosition(m_handle, pos);
cpBodySetVelocity(m_handle, vel);
}
if (geom)
m_geom = geom;
else
m_geom = NullCollider2D::New();
m_shapes = m_geom->CreateShapes(this);
cpSpace* space = m_world->GetHandle();
for (cpShape* shape : m_shapes)
cpSpaceAddShape(space, shape);
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
}
void RigidBody2D::SetMass(float mass)
{
if (m_mass > 0.f)
{
if (mass > 0.f)
{
cpBodySetMass(m_handle, mass);
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
}
else
cpBodySetType(m_handle, CP_BODY_TYPE_STATIC);
}
else if (mass > 0.f)
{
if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC)
{
cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC);
cpBodySetMass(m_handle, mass);
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
}
}
m_mass = mass;
@@ -196,6 +233,8 @@ namespace Nz
void RigidBody2D::SetPosition(const Vector2f& position)
{
cpBodySetPosition(m_handle, cpv(position.x, position.y));
if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC)
cpSpaceReindexShapesForBody(m_world->GetHandle(), m_handle);
}
void RigidBody2D::SetRotation(float rotation)
@@ -230,22 +269,26 @@ namespace Nz
return *this;
}
void RigidBody2D::Create(float mass, float moment)
{
m_handle = cpBodyNew(mass, moment);
cpBodySetUserData(m_handle, this);
cpSpaceAddBody(m_world->GetHandle(), m_handle);
}
void RigidBody2D::Destroy()
{
cpSpace* space = m_world->GetHandle();
for (cpShape* shape : m_shapes)
{
cpSpaceRemoveShape(space, shape);
cpShapeFree(shape);
}
if (m_handle)
{
cpSpaceRemoveBody(space, m_handle);
cpBodyFree(m_handle);
}
void RigidBody2D::SetGeom(Collider2DRef geom)
{
if (geom)
m_geom = geom;
else
m_geom = NullCollider2D::New();
m_shapes = m_geom->CreateShapes(this);
}
}
}

View File

@@ -3,7 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics3D/Config.hpp>
#if NAZARA_PHYSICS_MANAGE_MEMORY
#if NAZARA_PHYSICS3D_MANAGE_MEMORY
#include <Nazara/Core/MemoryManager.hpp>
#include <new> // Nécessaire ?

View File

@@ -795,6 +795,7 @@ namespace Nz
NazaraAssert(attachmentIndex < m_impl->attachments.size(), "Invalid attachment index");
NazaraAssert(!m_impl->attachments[attachmentIndex].isBuffer, "Invalid attachment state");
NazaraUnused(texture);
NazaraUnused(attachmentIndex);
InvalidateTargets();
}

View File

@@ -15,7 +15,7 @@
namespace Nz
{
RenderWindow::RenderWindow(VideoMode mode, const String& title, UInt32 style, const ContextParameters& parameters) :
RenderWindow::RenderWindow(VideoMode mode, const String& title, WindowStyleFlags style, const ContextParameters& parameters) :
RenderTarget(), Window()
{
ErrorFlags flags(ErrorFlag_ThrowException, true);
@@ -121,7 +121,7 @@ namespace Nz
return true;
}
bool RenderWindow::Create(VideoMode mode, const String& title, UInt32 style, const ContextParameters& parameters)
bool RenderWindow::Create(VideoMode mode, const String& title, WindowStyleFlags style, const ContextParameters& parameters)
{
m_parameters = parameters;
return Window::Create(mode, title, style);

View File

@@ -742,7 +742,7 @@ namespace Nz
Vector3f halfLengths = lengths/2.f;
// Face +X
transform.MakeTransform(Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, 0.f, -90.f));
transform.MakeTransform(Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, -90.f, 180.f));
GeneratePlane(Vector2ui(subdivision.z, subdivision.y), Vector2f(lengths.z, lengths.y), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset);
indexOffset += xVertexCount;
indices += xIndexCount;
@@ -776,7 +776,7 @@ namespace Nz
vertexPointers.uvPtr += yVertexCount;
// Face +Z
transform.MakeTransform(Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(-90.f, 90.f, 90.f));
transform.MakeTransform(Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(90.f, 0.f, 0.f));
GeneratePlane(Vector2ui(subdivision.x, subdivision.y), Vector2f(lengths.x, lengths.y), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset);
indexOffset += zVertexCount;
indices += zIndexCount;
@@ -793,7 +793,7 @@ namespace Nz
vertexPointers.uvPtr += zVertexCount;
// Face -X
transform.MakeTransform(-Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, 0.f, 90.f));
transform.MakeTransform(-Vector3f::UnitX() * halfLengths.x, EulerAnglesf(-90.f, 90.f, 180.f));
GeneratePlane(Vector2ui(subdivision.z, subdivision.y), Vector2f(lengths.z, lengths.y), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset);
indexOffset += xVertexCount;
indices += xIndexCount;
@@ -810,7 +810,7 @@ namespace Nz
vertexPointers.uvPtr += xVertexCount;
// Face -Y
transform.MakeTransform(-Vector3f::UnitY() * halfLengths.y, EulerAnglesf(0.f, 0.f, 180.f));
transform.MakeTransform(-Vector3f::UnitY() * halfLengths.y, EulerAnglesf(0.f, 180.f, 180.f));
GeneratePlane(Vector2ui(subdivision.x, subdivision.z), Vector2f(lengths.x, lengths.z), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset);
indexOffset += yVertexCount;
indices += yIndexCount;
@@ -827,7 +827,7 @@ namespace Nz
vertexPointers.uvPtr += yVertexCount;
// Face -Z
transform.MakeTransform(-Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(-90.f, -90.f, 90.f));
transform.MakeTransform(-Vector3f::UnitZ() * halfLengths.z, EulerAnglesf(90.f, 180.f, 0.f));
GeneratePlane(Vector2ui(subdivision.x, subdivision.y), Vector2f(lengths.x, lengths.y), Matrix4f::ConcatenateAffine(matrix, transform), textureCoords, vertexPointers, indices, nullptr, indexOffset);
indexOffset += zVertexCount;
indices += zIndexCount;

View File

@@ -174,15 +174,15 @@ namespace Nz
if (header.format.flags & DDPF_RGB)
{
// Reverse bits for our masks
info.redMask = ReverseBits(header.format.redMask);
info.greenMask = ReverseBits(header.format.greenMask);
info.blueMask = ReverseBits(header.format.blueMask);
info.redMask = header.format.redMask;
info.greenMask = header.format.greenMask;
info.blueMask = header.format.blueMask;
}
else if (header.format.flags & DDPF_LUMINANCE)
info.redMask = ReverseBits(header.format.redMask);
info.redMask = header.format.redMask;
if (header.format.flags & (DDPF_ALPHA | DDPF_ALPHAPIXELS))
info.alphaMask = ReverseBits(header.format.alphaMask);
info.alphaMask = header.format.alphaMask;
*format = PixelFormat::IdentifyFormat(info);
if (!PixelFormat::IsValid(*format))

View File

@@ -81,15 +81,14 @@ namespace Nz
return false;
}
/// Création du mesh
// Le moteur ne supporte plus les animations image-clé, nous ne pouvons charger qu'en statique
if (!mesh->CreateStatic()) // Ne devrait jamais échouer
// Since the engine no longer supports keyframe animations, let's make a static mesh
if (!mesh->CreateStatic())
{
NazaraInternalError("Failed to create mesh");
return false;
}
/// Chargement des skins
// Extract skins (texture name)
if (header.num_skins > 0)
{
mesh->SetMaterialCount(header.num_skins);
@@ -109,16 +108,15 @@ namespace Nz
}
}
/// Chargement des submesh
// Actuellement le loader ne charge qu'un submesh
IndexBufferRef indexBuffer = IndexBuffer::New(false, header.num_tris*3, parameters.storage, BufferUsage_Static);
/// Lecture des triangles
// Extract triangles data
std::vector<MD2_Triangle> triangles(header.num_tris);
stream.SetCursorPos(header.offset_tris);
stream.Read(&triangles[0], header.num_tris*sizeof(MD2_Triangle));
// And convert them into an index buffer
BufferMapper<IndexBuffer> indexMapper(indexBuffer, BufferAccess_DiscardAndWrite);
UInt16* index = static_cast<UInt16*>(indexMapper.GetPointer());
@@ -135,7 +133,7 @@ namespace Nz
SwapBytes(&triangles[i].texCoords[2], sizeof(UInt16));
#endif
// On respécifie le triangle dans l'ordre attendu
// Reverse winding order
*index++ = triangles[i].vertices[0];
*index++ = triangles[i].vertices[2];
*index++ = triangles[i].vertices[1];
@@ -143,10 +141,11 @@ namespace Nz
indexMapper.Unmap();
// Optimize if requested (improves cache locality)
if (parameters.optimizeIndexBuffers)
indexBuffer->Optimize();
/// Lecture des coordonnées de texture
// Extracting texture coordinates
std::vector<MD2_TexCoord> texCoords(header.num_st);
stream.SetCursorPos(header.offset_st);
@@ -168,15 +167,15 @@ namespace Nz
return false;
}
/// Chargement des vertices
// Extracting vertices
stream.SetCursorPos(header.offset_frames);
std::unique_ptr<MD2_Vertex[]> vertices(new MD2_Vertex[header.num_vertices]);
std::vector<MD2_Vertex> vertices(header.num_vertices);
Vector3f scale, translate;
stream.Read(scale, sizeof(Vector3f));
stream.Read(translate, sizeof(Vector3f));
stream.Read(nullptr, 16*sizeof(char)); // Nom de la frame, inutile ici
stream.Read(vertices.get(), header.num_vertices*sizeof(MD2_Vertex));
stream.Read(nullptr, 16*sizeof(char)); //< Frame name, unused
stream.Read(vertices.data(), header.num_vertices*sizeof(MD2_Vertex));
#ifdef NAZARA_BIG_ENDIAN
SwapBytes(&scale.x, sizeof(float));
@@ -196,23 +195,26 @@ namespace Nz
BufferMapper<VertexBuffer> vertexMapper(vertexBuffer, BufferAccess_DiscardAndWrite);
MeshVertex* vertex = static_cast<MeshVertex*>(vertexMapper.GetPointer());
/// Chargement des coordonnées de texture
const unsigned int indexFix[3] = {0, 2, 1}; // Pour respécifier les indices dans le bon ordre
// Loading texture coordinates
const unsigned int indexFix[3] = {0, 2, 1};
Vector2f invSkinSize(1.f / header.skinwidth, 1.f / header.skinheight);
for (unsigned int i = 0; i < header.num_tris; ++i)
{
for (unsigned int j = 0; j < 3; ++j)
{
const unsigned int fixedIndex = indexFix[j];
const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]];
float u = static_cast<float>(texC.u) / header.skinwidth;
float v = static_cast<float>(texC.v) / header.skinheight;
const unsigned int fixedIndex = indexFix[j]; //< Reverse winding order
vertex[triangles[i].vertices[fixedIndex]].uv.Set(u, (parameters.flipUVs) ? 1.f - v : v);
const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]];
Vector2f uv(texC.u, texC.v);
uv *= invSkinSize;
vertex[triangles[i].vertices[fixedIndex]].uv.Set(parameters.texCoordOffset + uv * parameters.texCoordScale);
}
}
/// Chargement des positions
// Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices
// Loading vertex position
// Align the model to our coordinates system
Quaternionf rotationQuat = EulerAnglesf(-90.f, 90.f, 0.f);
Nz::Matrix4f matrix = Matrix4f::Transform(translate, rotationQuat, scale);
matrix *= parameters.matrix;

View File

@@ -184,7 +184,7 @@ namespace Nz
}
vertices->position = finalPos;
vertices->uv.Set(vertex.uv.x, (parameters.flipUVs) ? 1.f - vertex.uv.y : vertex.uv.y); // Inversion des UV si demandé
vertices->uv.Set(parameters.texCoordOffset + vertex.uv * parameters.texCoordScale);
vertices++;
}
@@ -254,7 +254,7 @@ namespace Nz
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.storage);
BufferMapper<VertexBuffer> vertexMapper(vertexBuffer, BufferAccess_WriteOnly);
MeshVertex* vertex = static_cast<MeshVertex*>(vertexMapper.GetPointer());
MeshVertex* vertices = static_cast<MeshVertex*>(vertexMapper.GetPointer());
for (const MD5MeshParser::Vertex& md5Vertex : md5Mesh.vertices)
{
// Skinning MD5 (Formule d'Id Tech)
@@ -268,9 +268,9 @@ namespace Nz
}
// On retourne le modèle dans le bon sens
vertex->position = matrix * finalPos;
vertex->uv.Set(md5Vertex.uv.x, (parameters.flipUVs) ? 1.f - md5Vertex.uv.y : md5Vertex.uv.y); // Inversion des UV si demandé
vertex++;
vertices->position = matrix * finalPos;
vertices->uv.Set(parameters.texCoordOffset + md5Vertex.uv * parameters.texCoordScale);
vertices++;
}
vertexMapper.Unmap();

View File

@@ -331,19 +331,19 @@ namespace Nz
Emit(mat.specular.b / 255.f);
EmitLine();
if (mat.alpha != 1.f)
if (!NumberEquals(mat.alpha, 1.f))
{
Emit("d ");
EmitLine(mat.alpha);
}
if (mat.refractionIndex != 1.f)
if (!NumberEquals(mat.refractionIndex, 1.f))
{
Emit("ni ");
EmitLine(mat.refractionIndex);
}
if (mat.shininess != 1.f)
if (!NumberEquals(mat.shininess, 1.f))
{
Emit("ns ");
EmitLine(mat.shininess);

View File

@@ -265,8 +265,8 @@ namespace Nz
if (vertexIndices.texCoord > 0)
{
const Vector3f& uvw = texCoords[vertexIndices.texCoord-1];
vertex.uv.Set(uvw.x, (parameters.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé
Vector2f uv = Vector2f(texCoords[vertexIndices.texCoord - 1]);
vertex.uv.Set(parameters.texCoordOffset + uv * parameters.texCoordScale);
}
else
hasTexCoords = false;

View File

@@ -128,17 +128,17 @@ namespace Nz
UInt32 faceReserve = 0;
UInt32 vertexReserve = 0;
unsigned int matCount = 0;
auto GetMaterial = [&] (const String& meshName, const String& matName) -> Mesh*
auto GetMaterial = [&] (const String& mesh, const String& mat) -> Mesh*
{
auto& map = meshesByName[meshName];
auto it = map.find(matName);
auto& map = meshesByName[mesh];
auto it = map.find(mat);
if (it == map.end())
it = map.insert(std::make_pair(matName, MatPair(Mesh(), matCount++))).first;
it = map.insert(std::make_pair(mat, MatPair(Mesh(), matCount++))).first;
Mesh& mesh = it->second.first;
Mesh& meshData = it->second.first;
mesh.faces.reserve(faceReserve);
mesh.vertices.reserve(vertexReserve);
meshData.faces.reserve(faceReserve);
meshData.vertices.reserve(vertexReserve);
faceReserve = 0;
vertexReserve = 0;
@@ -550,19 +550,19 @@ namespace Nz
EmitLine(pair.second.size());
EmitLine();
for (std::size_t meshIndex : pair.second)
for (std::size_t index : pair.second)
{
const Mesh& mesh = m_meshes[meshIndex];
const Mesh& mesh = m_meshes[index];
Emit("g ");
EmitLine(mesh.name);
EmitLine();
Emit("# face count: ");
EmitLine(mesh.faces.size());
Emit("# vertex count: ");
EmitLine(mesh.vertices.size());
for (const Face& face : mesh.faces)
{
Emit('f');

View File

@@ -825,6 +825,44 @@ namespace Nz
return GetLevelSize(m_sharedImage->width, level);
}
bool Image::HasAlpha() const
{
NazaraAssert(m_sharedImage != &emptyImage, "Image must be valid");
if (!PixelFormat::HasAlpha(m_sharedImage->format))
return false;
if (!PixelFormat::IsCompressed(m_sharedImage->format))
{
const PixelFormatInfo& info = PixelFormat::GetInfo(m_sharedImage->format);
const UInt8* pixel = GetConstPixels();
Bitset<> workingBitset;
std::size_t pixelCount = m_sharedImage->width * m_sharedImage->height * ((m_sharedImage->type == ImageType_Cubemap) ? 6 : m_sharedImage->depth);
if (pixelCount == 0)
return false;
auto seq = workingBitset.Read(GetConstPixels(), info.bitsPerPixel);
do
{
workingBitset &= info.alphaMask;
if (workingBitset.Count() != info.alphaMask.Count()) //< Means that at least one bit of the alpha mask of this pixel is disabled
return true;
workingBitset.Clear();
workingBitset.Read(seq, info.bitsPerPixel);
}
while (--pixelCount > 0);
return false;
}
else
{
// FIXME: Currently, we assume the pixel format is already the right one
return true;
}
}
bool Image::IsValid() const
{
return m_sharedImage != &emptyImage;
@@ -1441,7 +1479,7 @@ namespace Nz
SharedImage::PixelContainer levels(m_sharedImage->levels.size());
for (unsigned int i = 0; i < levels.size(); ++i)
{
unsigned int size = GetMemoryUsage(i);
std::size_t size = GetMemoryUsage(i);
levels[i].reset(new UInt8[size]);
std::memcpy(levels[i].get(), m_sharedImage->levels[i].get(), size);
}

View File

@@ -75,6 +75,7 @@ namespace Nz
Font* SimpleTextDrawer::GetFont(std::size_t index) const
{
NazaraAssert(index == 0, "Font index out of range");
NazaraUnused(index);
return m_font;
}

View File

@@ -11,7 +11,7 @@
namespace Nz
{
SoftwareBuffer::SoftwareBuffer(Buffer* /*parent*/, BufferType type)
SoftwareBuffer::SoftwareBuffer(Buffer* /*parent*/, BufferType /*type*/)
{
}

View File

@@ -45,7 +45,7 @@ namespace Nz
bool VertexBuffer::Fill(const void* data, unsigned int startVertex, unsigned int length, bool forceDiscard)
{
unsigned int stride = m_vertexDeclaration->GetStride();
std::size_t stride = m_vertexDeclaration->GetStride();
return FillRaw(data, startVertex*stride, length*stride, forceDiscard);
}

View File

@@ -24,6 +24,11 @@ namespace Nz
width(0)
{
}
VideoMode::VideoMode(unsigned int w, unsigned int h) :
VideoMode(w, h, GetDesktopMode().bitsPerPixel)
{
}
VideoMode::VideoMode(unsigned int w, unsigned int h, UInt8 bpp) :
bitsPerPixel(bpp),

View File

@@ -81,8 +81,9 @@ namespace Nz
{
}
bool WindowImpl::Create(const VideoMode& mode, const String& title, UInt32 style)
bool WindowImpl::Create(const VideoMode& mode, const String& title, WindowStyleFlags style)
{
bool async = (style & WindowStyle_Threaded) != 0;
bool fullscreen = (style & WindowStyle_Fullscreen) != 0;
DWORD win32Style, win32StyleEx;
unsigned int x, y;
@@ -147,19 +148,25 @@ namespace Nz
m_callback = 0;
#if NAZARA_UTILITY_THREADED_WINDOW
Mutex mutex;
ConditionVariable condition;
m_threadActive = true;
m_eventListener = true;
m_ownsWindow = true;
m_sizemove = false;
m_style = style;
// On attend que la fenêtre soit créée
mutex.Lock();
m_thread = Thread(WindowThread, &m_handle, win32StyleEx, title.GetWideString().data(), win32Style, x, y, width, height, this, &mutex, &condition);
condition.Wait(&mutex);
mutex.Unlock();
#else
m_handle = CreateWindowExW(win32StyleEx, className, title.GetWideString().data(), win32Style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), this);
#endif
if (async)
{
Mutex mutex;
ConditionVariable condition;
m_threadActive = true;
// On attend que la fenêtre soit créée
mutex.Lock();
m_thread = Thread(WindowThread, &m_handle, win32StyleEx, title, win32Style, fullscreen, Rectui(x, y, width, height), this, &mutex, &condition);
condition.Wait(&mutex);
mutex.Unlock();
}
else
m_handle = CreateWindowExW(win32StyleEx, className, title.GetWideString().data(), win32Style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), this);
if (!m_handle)
{
@@ -167,26 +174,8 @@ namespace Nz
return false;
}
if (fullscreen)
{
SetForegroundWindow(m_handle);
ShowWindow(m_handle, SW_SHOW);
}
m_eventListener = true;
m_ownsWindow = true;
#if !NAZARA_UTILITY_THREADED_WINDOW
m_sizemove = false;
#endif
m_style = style;
// Récupération de la position/taille de la fenêtre (Après sa création)
RECT clientRect, windowRect;
GetClientRect(m_handle, &clientRect);
GetWindowRect(m_handle, &windowRect);
m_position.Set(windowRect.left, windowRect.top);
m_size.Set(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
if (!async)
PrepareWindow(fullscreen);
return true;
}
@@ -203,9 +192,7 @@ namespace Nz
m_eventListener = false;
m_ownsWindow = false;
#if !NAZARA_UTILITY_THREADED_WINDOW
m_sizemove = false;
#endif
m_style = RetrieveStyle(m_handle);
RECT clientRect, windowRect;
@@ -222,18 +209,21 @@ namespace Nz
{
if (m_ownsWindow)
{
#if NAZARA_UTILITY_THREADED_WINDOW
if (m_thread.IsJoinable())
if (m_style & WindowStyle_Threaded)
{
m_threadActive = false;
PostMessageW(m_handle, WM_NULL, 0, 0); // Pour réveiller le thread
if (m_thread.IsJoinable())
{
m_threadActive = false;
PostMessageW(m_handle, WM_NULL, 0, 0); // Wake up our thread
m_thread.Join();
m_thread.Join();
}
}
else
{
if (m_handle)
DestroyWindow(m_handle);
}
#else
if (m_handle)
DestroyWindow(m_handle);
#endif
}
else
SetEventListener(false);
@@ -269,7 +259,7 @@ namespace Nz
return m_size;
}
UInt32 WindowImpl::GetStyle() const
WindowStyleFlags WindowImpl::GetStyle() const
{
return m_style;
}
@@ -280,7 +270,7 @@ namespace Nz
if (titleSize == 0)
return String();
titleSize++; // Caractère nul
titleSize++; // \0
std::unique_ptr<wchar_t[]> wTitle(new wchar_t[titleSize]);
GetWindowTextW(m_handle, wTitle.get(), titleSize);
@@ -525,7 +515,6 @@ namespace Nz
return true; // Afin que Windows ne ferme pas la fenêtre automatiquement
}
#if !NAZARA_UTILITY_THREADED_WINDOW
case WM_ENTERSIZEMOVE:
{
m_sizemove = true;
@@ -536,6 +525,10 @@ namespace Nz
{
m_sizemove = false;
// In case of threaded window, size and move events are not blocked
if (m_style & WindowStyle_Threaded)
break;
// On vérifie ce qui a changé
RECT clientRect, windowRect;
GetClientRect(m_handle, &clientRect);
@@ -565,7 +558,6 @@ namespace Nz
m_parent->PushEvent(event);
}
}
#endif
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
@@ -789,15 +781,23 @@ namespace Nz
case WM_MOVE:
{
if (m_sizemove && (m_style & WindowStyle_Threaded) == 0)
break;
RECT windowRect;
GetWindowRect(m_handle, &windowRect);
WindowEvent event;
event.type = WindowEventType_Moved;
event.position.x = windowRect.left;
event.position.y = windowRect.top;
m_parent->PushEvent(event);
Vector2i position(windowRect.left, windowRect.top);
if (m_position != position)
{
m_position = position;
WindowEvent event;
event.type = WindowEventType_Moved;
event.position.x = position.x;
event.position.y = position.y;
m_parent->PushEvent(event);
}
break;
}
@@ -852,27 +852,26 @@ namespace Nz
case WM_SIZE:
{
#if NAZARA_UTILITY_THREADED_WINDOW
if (wParam != SIZE_MINIMIZED)
#else
if (!m_sizemove && wParam != SIZE_MINIMIZED)
#endif
{
RECT rect;
GetClientRect(m_handle, &rect);
if (m_sizemove && (m_style & WindowStyle_Threaded) == 0)
break;
Vector2ui size(rect.right-rect.left, rect.bottom-rect.top); // On récupère uniquement la taille de la zone client
if (m_size == size)
break;
if (wParam == SIZE_MINIMIZED)
break;
m_size = size;
RECT rect;
GetClientRect(m_handle, &rect);
WindowEvent event;
event.type = WindowEventType_Resized;
event.size.width = size.x;
event.size.height = size.y;
m_parent->PushEvent(event);
}
Vector2ui size(rect.right-rect.left, rect.bottom-rect.top); // On récupère uniquement la taille de la zone client
if (m_size == size)
break;
m_size = size;
WindowEvent event;
event.type = WindowEventType_Resized;
event.size.width = size.x;
event.size.height = size.y;
m_parent->PushEvent(event);
break;
}
@@ -963,6 +962,23 @@ namespace Nz
return false;
}
void WindowImpl::PrepareWindow(bool fullscreen)
{
if (fullscreen)
{
SetForegroundWindow(m_handle);
ShowWindow(m_handle, SW_SHOW);
}
// Cache window position/size after creation
RECT clientRect, windowRect;
GetClientRect(m_handle, &clientRect);
GetWindowRect(m_handle, &windowRect);
m_position.Set(windowRect.left, windowRect.top);
m_size.Set(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
}
bool WindowImpl::Initialize()
{
// Nous devons faire un type Unicode pour que la fenêtre le soit également
@@ -1177,15 +1193,17 @@ namespace Nz
return style;
}
#if NAZARA_UTILITY_THREADED_WINDOW
void WindowImpl::WindowThread(HWND* handle, DWORD styleEx, const wchar_t* title, DWORD style, unsigned int x, unsigned int y, unsigned int width, unsigned int height, WindowImpl* window, Mutex* mutex, ConditionVariable* condition)
void WindowImpl::WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition)
{
HWND& winHandle = *handle;
winHandle = CreateWindowExW(styleEx, className, title, style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), window);
winHandle = CreateWindowExW(styleEx, className, title.GetWideString().data(), style, dimensions.x, dimensions.y, dimensions.width, dimensions.height, nullptr, nullptr, GetModuleHandle(nullptr), window);
if (winHandle)
window->PrepareWindow(fullscreen);
mutex->Lock();
condition->Signal();
mutex->Unlock(); // mutex et condition sont considérés invalides à partir d'ici
mutex->Unlock(); // mutex and condition may be destroyed after this line
if (!winHandle)
return;
@@ -1195,5 +1213,4 @@ namespace Nz
DestroyWindow(winHandle);
}
#endif
}

View File

@@ -12,6 +12,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Keyboard.hpp>
@@ -22,10 +23,8 @@
namespace Nz
{
#if NAZARA_UTILITY_THREADED_WINDOW
class ConditionVariable;
class Mutex;
#endif
class Window;
#undef IsMinimized // Conflit avec la méthode du même nom
@@ -38,7 +37,7 @@ namespace Nz
WindowImpl(WindowImpl&&) = delete; ///TODO?
~WindowImpl() = default;
bool Create(const VideoMode& mode, const String& title, UInt32 style);
bool Create(const VideoMode& mode, const String& title, WindowStyleFlags style);
bool Create(WindowHandle handle);
void Destroy();
@@ -50,7 +49,7 @@ namespace Nz
unsigned int GetHeight() const;
Vector2i GetPosition() const;
Vector2ui GetSize() const;
UInt32 GetStyle() const;
WindowStyleFlags GetStyle() const;
String GetTitle() const;
unsigned int GetWidth() const;
@@ -84,38 +83,31 @@ namespace Nz
private:
bool HandleMessage(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
void PrepareWindow(bool fullscreen);
static Keyboard::Key ConvertVirtualKey(WPARAM key, LPARAM flags);
static LRESULT CALLBACK MessageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
static UInt32 RetrieveStyle(HWND window);
#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, WindowImpl* window, Mutex* mutex, ConditionVariable* condition);
#endif
static void WindowThread(HWND* handle, DWORD styleEx, const String& title, DWORD style, bool fullscreen, const Rectui& dimensions, WindowImpl* window, Mutex* mutex, ConditionVariable* condition);
HCURSOR m_cursor;
HWND m_handle;
LONG_PTR m_callback;
UInt32 m_style;
WindowStyleFlags m_style;
Vector2i m_maxSize;
Vector2i m_minSize;
Vector2i m_mousePos;
Vector2i m_position;
Vector2ui m_size;
#if NAZARA_UTILITY_THREADED_WINDOW
Thread m_thread;
#endif
Window* m_parent;
bool m_eventListener;
bool m_keyRepeat;
bool m_mouseInside;
bool m_ownsWindow;
#if !NAZARA_UTILITY_THREADED_WINDOW
bool m_sizemove;
#endif
bool m_smoothScrolling;
#if NAZARA_UTILITY_THREADED_WINDOW
bool m_threadActive;
#endif
short m_scrolling;
};
}

View File

@@ -34,7 +34,7 @@ namespace Nz
Destroy();
}
bool Window::Create(VideoMode mode, const String& title, UInt32 style)
bool Window::Create(VideoMode mode, const String& title, WindowStyleFlags style)
{
// Si la fenêtre est déjà ouverte, nous conservons sa position
bool opened = IsOpen();
@@ -66,6 +66,8 @@ namespace Nz
else if (style & WindowStyle_Closable || style & WindowStyle_Resizable)
style |= WindowStyle_Titlebar;
m_asyncWindow = (style & WindowStyle_Threaded) != 0;
std::unique_ptr<WindowImpl> impl = std::make_unique<WindowImpl>(this);
if (!impl->Create(mode, title, style))
{
@@ -107,6 +109,7 @@ namespace Nz
{
Destroy();
m_asyncWindow = false;
m_impl = new WindowImpl(this);
if (!m_impl->Create(handle))
{
@@ -225,7 +228,7 @@ namespace Nz
return m_impl->GetSize();
}
UInt32 Window::GetStyle() const
WindowStyleFlags Window::GetStyle() const
{
#if NAZARA_UTILITY_SAFE
if (!m_impl)
@@ -313,11 +316,8 @@ namespace Nz
}
#endif
#if NAZARA_UTILITY_THREADED_WINDOW
LockGuard lock(m_eventMutex);
#else
m_impl->ProcessEvents(false);
#endif
if (!m_asyncWindow)
m_impl->ProcessEvents(false);
if (!m_events.empty())
{
@@ -335,10 +335,19 @@ namespace Nz
void Window::ProcessEvents(bool block)
{
NazaraAssert(m_impl, "Window not created");
NazaraUnused(block);
#if !NAZARA_UTILITY_THREADED_WINDOW
m_impl->ProcessEvents(block);
#endif
if (!m_asyncWindow)
m_impl->ProcessEvents(block);
else
{
LockGuard eventLock(m_eventMutex);
for (const WindowEvent& event : m_pendingEvents)
HandleEvent(event);
m_pendingEvents.clear();
}
}
void Window::SetCursor(WindowCursor cursor)
@@ -383,25 +392,13 @@ namespace Nz
}
#endif
#if NAZARA_UTILITY_THREADED_WINDOW
m_impl->SetEventListener(listener);
if (!listener)
{
// On vide la pile des évènements
LockGuard lock(m_eventMutex);
// Empty the event queue
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 Window::SetFocus()
@@ -589,22 +586,11 @@ namespace Nz
}
#endif
#if NAZARA_UTILITY_THREADED_WINDOW
LockGuard lock(m_eventMutex);
if (m_events.empty())
if (!m_asyncWindow)
{
m_waitForEvent = true;
m_eventConditionMutex.Lock();
m_eventMutex.Unlock();
m_eventCondition.Wait(&m_eventConditionMutex);
m_eventMutex.Lock();
m_eventConditionMutex.Unlock();
m_waitForEvent = false;
}
while (m_events.empty())
m_impl->ProcessEvents(true);
if (!m_events.empty())
{
if (event)
*event = m_events.front();
@@ -612,19 +598,33 @@ namespace Nz
return true;
}
else
{
LockGuard lock(m_eventMutex);
return false;
#else
while (m_events.empty())
m_impl->ProcessEvents(true);
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 (event)
*event = m_events.front();
if (!m_events.empty())
{
if (event)
*event = m_events.front();
m_events.pop();
m_events.pop();
return true;
#endif
return true;
}
return false;
}
}
bool Window::OnWindowCreated()

View File

@@ -23,32 +23,32 @@ namespace Nz
switch (key)
{
// Lettres
case Keyboard::A: keysym = XK_A; break;
case Keyboard::B: keysym = XK_B; break;
case Keyboard::C: keysym = XK_C; break;
case Keyboard::D: keysym = XK_D; break;
case Keyboard::E: keysym = XK_E; break;
case Keyboard::F: keysym = XK_F; break;
case Keyboard::G: keysym = XK_G; break;
case Keyboard::H: keysym = XK_H; break;
case Keyboard::I: keysym = XK_I; break;
case Keyboard::J: keysym = XK_J; break;
case Keyboard::K: keysym = XK_K; break;
case Keyboard::L: keysym = XK_L; break;
case Keyboard::M: keysym = XK_M; break;
case Keyboard::N: keysym = XK_N; break;
case Keyboard::O: keysym = XK_O; break;
case Keyboard::P: keysym = XK_P; break;
case Keyboard::Q: keysym = XK_Q; break;
case Keyboard::R: keysym = XK_R; break;
case Keyboard::S: keysym = XK_S; break;
case Keyboard::T: keysym = XK_T; break;
case Keyboard::U: keysym = XK_U; break;
case Keyboard::V: keysym = XK_V; break;
case Keyboard::W: keysym = XK_W; break;
case Keyboard::X: keysym = XK_X; break;
case Keyboard::Y: keysym = XK_Y; break;
case Keyboard::Z: keysym = XK_Z; break;
case Keyboard::A: keysym = XK_a; break;
case Keyboard::B: keysym = XK_b; break;
case Keyboard::C: keysym = XK_c; break;
case Keyboard::D: keysym = XK_d; break;
case Keyboard::E: keysym = XK_e; break;
case Keyboard::F: keysym = XK_f; break;
case Keyboard::G: keysym = XK_g; break;
case Keyboard::H: keysym = XK_h; break;
case Keyboard::I: keysym = XK_i; break;
case Keyboard::J: keysym = XK_j; break;
case Keyboard::K: keysym = XK_k; break;
case Keyboard::L: keysym = XK_l; break;
case Keyboard::M: keysym = XK_m; break;
case Keyboard::N: keysym = XK_n; break;
case Keyboard::O: keysym = XK_o; break;
case Keyboard::P: keysym = XK_p; break;
case Keyboard::Q: keysym = XK_q; break;
case Keyboard::R: keysym = XK_r; break;
case Keyboard::S: keysym = XK_s; break;
case Keyboard::T: keysym = XK_t; break;
case Keyboard::U: keysym = XK_u; break;
case Keyboard::V: keysym = XK_v; break;
case Keyboard::W: keysym = XK_w; break;
case Keyboard::X: keysym = XK_x; break;
case Keyboard::Y: keysym = XK_y; break;
case Keyboard::Z: keysym = XK_z; break;
// Touches de fonction
case Keyboard::F1: keysym = XK_F1; break;
@@ -248,6 +248,8 @@ namespace Nz
xcb_keysym_t keySym = GetKeySym(key);
xcb_keycode_t realKeyCode = XCB_NO_SYMBOL;
xcb_key_symbols_t* keySymbols = X11::XCBKeySymbolsAlloc(connection);
if (!keySymbols)
{
@@ -261,6 +263,20 @@ namespace Nz
NazaraError("Failed to get key code");
return false;
}
// One keysym is associated with multiple key codes, we have to find the matching one ...
int i = 0;
while (keyCode.get()[i] != XCB_NO_SYMBOL)
{
xcb_keycode_t toTry = keyCode.get()[i];
if (keySym == xcb_key_symbols_get_keysym(keySymbols, toTry, 0))
{
realKeyCode = toTry;
break;
}
++i;
}
X11::XCBKeySymbolsFree(keySymbols);
ScopedXCB<xcb_generic_error_t> error(nullptr);
@@ -281,7 +297,7 @@ namespace Nz
}
// Check our keycode
return (keymap->keys[*keyCode.get() / 8] & (1 << (*keyCode.get() % 8))) != 0;
return (keymap->keys[realKeyCode / 8] & (1 << (realKeyCode % 8))) != 0;
}
bool EventImpl::IsMouseButtonPressed(Mouse::Button button)

View File

@@ -113,7 +113,7 @@ namespace Nz
UpdateEventQueue(nullptr);
}
bool WindowImpl::Create(const VideoMode& mode, const String& title, UInt32 style)
bool WindowImpl::Create(const VideoMode& mode, const String& title, WindowStyleFlags style)
{
bool fullscreen = (style & Nz::WindowStyle_Fullscreen) != 0;
m_eventListener = true;
@@ -203,17 +203,18 @@ namespace Nz
// Set the window's name
SetTitle(title);
#if NAZARA_UTILITY_THREADED_WINDOW
Mutex mutex;
ConditionVariable condition;
m_threadActive = true;
if (m_style & WindowStyle_Threaded)
{
Mutex mutex;
ConditionVariable condition;
m_threadActive = true;
// We wait that thread is well launched
mutex.Lock();
m_thread = Thread(WindowThread, this, &mutex, &condition);
condition.Wait(&mutex);
mutex.Unlock();
#endif
// Wait until the thread is ready
mutex.Lock();
m_thread = Thread(WindowThread, this, &mutex, &condition);
condition.Wait(&mutex);
mutex.Unlock();
}
// Set fullscreen video mode and switch to fullscreen if necessary
if (fullscreen)
@@ -275,13 +276,15 @@ namespace Nz
{
if (m_ownsWindow)
{
#if NAZARA_UTILITY_THREADED_WINDOW
if (m_thread.IsJoinable())
if (m_style & WindowStyle_Threaded)
{
m_threadActive = false;
m_thread.Join();
if (m_thread.IsJoinable())
{
m_threadActive = false;
m_thread.Join();
}
}
#else
// Destroy the window
if (m_window && m_ownsWindow)
{
@@ -293,13 +296,11 @@ namespace Nz
xcb_destroy_window(
connection,
m_window
))
)
)))
NazaraError("Failed to destroy window");
xcb_flush(connection);
}
#endif
}
else
SetEventListener(false);
@@ -335,7 +336,7 @@ namespace Nz
return Vector2ui(m_size_hints.width, m_size_hints.height);
}
UInt32 WindowImpl::GetStyle() const
WindowStyleFlags WindowImpl::GetStyle() const
{
return m_style;
}
@@ -1247,7 +1248,7 @@ namespace Nz
char32_t codePoint = GetRepresentation(keysym);
// WTF if (std::isprint(codePoint, std::locale(""))) + handle combining ?
// if (std::isprint(codePoint)) Is not working ? + handle combining ?
{
WindowEvent event;
event.type = Nz::WindowEventType_TextEntered;
@@ -1405,7 +1406,7 @@ namespace Nz
// Catch reparent events to properly apply fullscreen on
// some "strange" window managers (like Awesome) which
// seem to make use of temporary parents during mapping
if (m_style & Nz::WindowStyle_Fullscreen)
if (m_style & WindowStyle_Fullscreen)
SwitchToFullscreen();
break;
@@ -1685,12 +1686,11 @@ namespace Nz
));
}
#if NAZARA_UTILITY_THREADED_WINDOW
void WindowImpl::WindowThread(WindowImpl* window, Mutex* mutex, ConditionVariable* condition)
{
mutex->Lock();
condition->Signal();
mutex->Unlock(); // mutex et condition sont considérés invalides à partir d'ici
mutex->Unlock(); // mutex and condition may be destroyed after this line
if (!window->m_window)
return;
@@ -1700,5 +1700,4 @@ namespace Nz
window->Destroy();
}
#endif
}

View File

@@ -20,10 +20,8 @@
namespace Nz
{
#if NAZARA_UTILITY_THREADED_WINDOW
class ConditionVariable;
class Mutex;
#endif
class Cursor;
class Icon;
class VideoMode;
@@ -37,7 +35,7 @@ namespace Nz
WindowImpl(WindowImpl&&) = delete; ///TODO?
~WindowImpl();
bool Create(const VideoMode& mode, const String& title, UInt32 style);
bool Create(const VideoMode& mode, const String& title, WindowStyleFlags style);
bool Create(WindowHandle handle);
void Destroy();
@@ -49,7 +47,7 @@ namespace Nz
unsigned int GetHeight() const;
Vector2i GetPosition() const;
Vector2ui GetSize() const;
UInt32 GetStyle() const;
WindowStyleFlags GetStyle() const;
String GetTitle() const;
unsigned int GetWidth() const;
@@ -103,25 +101,19 @@ namespace Nz
bool UpdateNormalHints();
void UpdateEventQueue(xcb_generic_event_t* event);
#if NAZARA_UTILITY_THREADED_WINDOW
static void WindowThread(WindowImpl* window, Mutex* mutex, ConditionVariable* condition);
#endif
xcb_window_t m_window;
xcb_screen_t* m_screen;
xcb_randr_get_screen_info_reply_t m_oldVideoMode;
xcb_size_hints_t m_size_hints;
UInt32 m_style;
#if NAZARA_UTILITY_THREADED_WINDOW
Thread m_thread;
#endif
WindowStyleFlags m_style;
Window* m_parent;
bool m_eventListener;
bool m_ownsWindow;
bool m_smoothScrolling;
#if NAZARA_UTILITY_THREADED_WINDOW
bool m_threadActive;
#endif
short m_scrolling;
Vector2i m_mousePos;
bool m_keyRepeat;