Source code changes.
* Changed newlines to \n. * Removed whitespace before colons. * Fixed several alignments.
This commit is contained in:
parent
b27cbd5036
commit
f24ca9a840
268 changed files with 40227 additions and 40227 deletions
|
@ -1,109 +1,109 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void alCheckError(const std::string& file, unsigned int line)
|
||||
{
|
||||
// Get the last error
|
||||
ALenum errorCode = alGetError();
|
||||
|
||||
if (errorCode != AL_NO_ERROR)
|
||||
{
|
||||
std::string error, description;
|
||||
|
||||
// Decode the error code
|
||||
switch (errorCode)
|
||||
{
|
||||
case AL_INVALID_NAME :
|
||||
{
|
||||
error = "AL_INVALID_NAME";
|
||||
description = "an unacceptable name has been specified";
|
||||
break;
|
||||
}
|
||||
|
||||
case AL_INVALID_ENUM :
|
||||
{
|
||||
error = "AL_INVALID_ENUM";
|
||||
description = "an unacceptable value has been specified for an enumerated argument";
|
||||
break;
|
||||
}
|
||||
|
||||
case AL_INVALID_VALUE :
|
||||
{
|
||||
error = "AL_INVALID_VALUE";
|
||||
description = "a numeric argument is out of range";
|
||||
break;
|
||||
}
|
||||
|
||||
case AL_INVALID_OPERATION :
|
||||
{
|
||||
error = "AL_INVALID_OPERATION";
|
||||
description = "the specified operation is not allowed in the current state";
|
||||
break;
|
||||
}
|
||||
|
||||
case AL_OUT_OF_MEMORY :
|
||||
{
|
||||
error = "AL_OUT_OF_MEMORY";
|
||||
description = "there is not enough memory left to execute the command";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Log the error
|
||||
err() << "An internal OpenAL call failed in "
|
||||
<< file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : "
|
||||
<< error << ", " << description
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Make sure that OpenAL is initialized
|
||||
////////////////////////////////////////////////////////////
|
||||
void ensureALInit()
|
||||
{
|
||||
// The audio device is instantiated on demand rather than at global startup,
|
||||
// which solves a lot of weird crashes and errors.
|
||||
// It is destroyed at global exit which is fine.
|
||||
|
||||
static AudioDevice globalDevice;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void alCheckError(const std::string& file, unsigned int line)
|
||||
{
|
||||
// Get the last error
|
||||
ALenum errorCode = alGetError();
|
||||
|
||||
if (errorCode != AL_NO_ERROR)
|
||||
{
|
||||
std::string error, description;
|
||||
|
||||
// Decode the error code
|
||||
switch (errorCode)
|
||||
{
|
||||
case AL_INVALID_NAME:
|
||||
{
|
||||
error = "AL_INVALID_NAME";
|
||||
description = "an unacceptable name has been specified";
|
||||
break;
|
||||
}
|
||||
|
||||
case AL_INVALID_ENUM:
|
||||
{
|
||||
error = "AL_INVALID_ENUM";
|
||||
description = "an unacceptable value has been specified for an enumerated argument";
|
||||
break;
|
||||
}
|
||||
|
||||
case AL_INVALID_VALUE:
|
||||
{
|
||||
error = "AL_INVALID_VALUE";
|
||||
description = "a numeric argument is out of range";
|
||||
break;
|
||||
}
|
||||
|
||||
case AL_INVALID_OPERATION:
|
||||
{
|
||||
error = "AL_INVALID_OPERATION";
|
||||
description = "the specified operation is not allowed in the current state";
|
||||
break;
|
||||
}
|
||||
|
||||
case AL_OUT_OF_MEMORY:
|
||||
{
|
||||
error = "AL_OUT_OF_MEMORY";
|
||||
description = "there is not enough memory left to execute the command";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Log the error
|
||||
err() << "An internal OpenAL call failed in "
|
||||
<< file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : "
|
||||
<< error << ", " << description
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Make sure that OpenAL is initialized
|
||||
////////////////////////////////////////////////////////////
|
||||
void ensureALInit()
|
||||
{
|
||||
// The audio device is instantiated on demand rather than at global startup,
|
||||
// which solves a lot of weird crashes and errors.
|
||||
// It is destroyed at global exit which is fine.
|
||||
|
||||
static AudioDevice globalDevice;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,78 +1,78 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_ALCHECK_HPP
|
||||
#define SFML_ALCHECK_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <al.h>
|
||||
#include <alc.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Let's define a macro to quickly check every OpenAL API calls
|
||||
////////////////////////////////////////////////////////////
|
||||
#ifdef SFML_DEBUG
|
||||
|
||||
// If in debug mode, perform a test on every call
|
||||
#define alCheck(x) x; sf::priv::alCheckError(__FILE__, __LINE__);
|
||||
|
||||
#else
|
||||
|
||||
// Else, we don't add any overhead
|
||||
#define alCheck(Func) (Func)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Check the last OpenAL error
|
||||
///
|
||||
/// \param file Source file where the call is located
|
||||
/// \param line Line number of the source file where the call is located
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void alCheckError(const std::string& file, unsigned int line);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Make sure that OpenAL is initialized
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void ensureALInit();
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_ALCHECK_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_ALCHECK_HPP
|
||||
#define SFML_ALCHECK_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <al.h>
|
||||
#include <alc.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Let's define a macro to quickly check every OpenAL API calls
|
||||
////////////////////////////////////////////////////////////
|
||||
#ifdef SFML_DEBUG
|
||||
|
||||
// If in debug mode, perform a test on every call
|
||||
#define alCheck(x) x; sf::priv::alCheckError(__FILE__, __LINE__);
|
||||
|
||||
#else
|
||||
|
||||
// Else, we don't add any overhead
|
||||
#define alCheck(Func) (Func)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Check the last OpenAL error
|
||||
///
|
||||
/// \param file Source file where the call is located
|
||||
/// \param line Line number of the source file where the call is located
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void alCheckError(const std::string& file, unsigned int line);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Make sure that OpenAL is initialized
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void ensureALInit();
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_ALCHECK_HPP
|
||||
|
|
|
@ -1,125 +1,125 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/Audio/Listener.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
ALCdevice* audioDevice = NULL;
|
||||
ALCcontext* audioContext = NULL;
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
AudioDevice::AudioDevice()
|
||||
{
|
||||
// Create the device
|
||||
audioDevice = alcOpenDevice(NULL);
|
||||
|
||||
if (audioDevice)
|
||||
{
|
||||
// Create the context
|
||||
audioContext = alcCreateContext(audioDevice, NULL);
|
||||
|
||||
if (audioContext)
|
||||
{
|
||||
// Set the context as the current one (we'll only need one)
|
||||
alcMakeContextCurrent(audioContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to create the audio context" << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to open the audio device" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
AudioDevice::~AudioDevice()
|
||||
{
|
||||
// Destroy the context
|
||||
alcMakeContextCurrent(NULL);
|
||||
if (audioContext)
|
||||
alcDestroyContext(audioContext);
|
||||
|
||||
// Destroy the device
|
||||
if (audioDevice)
|
||||
alcCloseDevice(audioDevice);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool AudioDevice::isExtensionSupported(const std::string& extension)
|
||||
{
|
||||
ensureALInit();
|
||||
|
||||
if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
|
||||
return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
|
||||
else
|
||||
return alIsExtensionPresent(extension.c_str()) != AL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
|
||||
{
|
||||
ensureALInit();
|
||||
|
||||
// Find the good format according to the number of channels
|
||||
int format = 0;
|
||||
switch (channelCount)
|
||||
{
|
||||
case 1 : format = AL_FORMAT_MONO16; break;
|
||||
case 2 : format = AL_FORMAT_STEREO16; break;
|
||||
case 4 : format = alGetEnumValue("AL_FORMAT_QUAD16"); break;
|
||||
case 6 : format = alGetEnumValue("AL_FORMAT_51CHN16"); break;
|
||||
case 7 : format = alGetEnumValue("AL_FORMAT_61CHN16"); break;
|
||||
case 8 : format = alGetEnumValue("AL_FORMAT_71CHN16"); break;
|
||||
default : format = 0; break;
|
||||
}
|
||||
|
||||
// Fixes a bug on OS X
|
||||
if (format == -1)
|
||||
format = 0;
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/Audio/Listener.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
ALCdevice* audioDevice = NULL;
|
||||
ALCcontext* audioContext = NULL;
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
AudioDevice::AudioDevice()
|
||||
{
|
||||
// Create the device
|
||||
audioDevice = alcOpenDevice(NULL);
|
||||
|
||||
if (audioDevice)
|
||||
{
|
||||
// Create the context
|
||||
audioContext = alcCreateContext(audioDevice, NULL);
|
||||
|
||||
if (audioContext)
|
||||
{
|
||||
// Set the context as the current one (we'll only need one)
|
||||
alcMakeContextCurrent(audioContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to create the audio context" << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to open the audio device" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
AudioDevice::~AudioDevice()
|
||||
{
|
||||
// Destroy the context
|
||||
alcMakeContextCurrent(NULL);
|
||||
if (audioContext)
|
||||
alcDestroyContext(audioContext);
|
||||
|
||||
// Destroy the device
|
||||
if (audioDevice)
|
||||
alcCloseDevice(audioDevice);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool AudioDevice::isExtensionSupported(const std::string& extension)
|
||||
{
|
||||
ensureALInit();
|
||||
|
||||
if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
|
||||
return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
|
||||
else
|
||||
return alIsExtensionPresent(extension.c_str()) != AL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
|
||||
{
|
||||
ensureALInit();
|
||||
|
||||
// Find the good format according to the number of channels
|
||||
int format = 0;
|
||||
switch (channelCount)
|
||||
{
|
||||
case 1: format = AL_FORMAT_MONO16; break;
|
||||
case 2: format = AL_FORMAT_STEREO16; break;
|
||||
case 4: format = alGetEnumValue("AL_FORMAT_QUAD16"); break;
|
||||
case 6: format = alGetEnumValue("AL_FORMAT_51CHN16"); break;
|
||||
case 7: format = alGetEnumValue("AL_FORMAT_61CHN16"); break;
|
||||
case 8: format = alGetEnumValue("AL_FORMAT_71CHN16"); break;
|
||||
default: format = 0; break;
|
||||
}
|
||||
|
||||
// Fixes a bug on OS X
|
||||
if (format == -1)
|
||||
format = 0;
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,91 +1,91 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_AUDIODEVICE_HPP
|
||||
#define SFML_AUDIODEVICE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief High-level wrapper around the audio API, it manages
|
||||
/// the creation and destruction of the audio device and
|
||||
/// context and stores the device capabilities
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class AudioDevice
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
AudioDevice();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~AudioDevice();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if an OpenAL extension is supported
|
||||
///
|
||||
/// This functions automatically finds whether it
|
||||
/// is an AL or ALC extension, and calls the corresponding
|
||||
/// function.
|
||||
///
|
||||
/// \param extension Name of the extension to test
|
||||
///
|
||||
/// \return True if the extension is supported, false if not
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static bool isExtensionSupported(const std::string& extension);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the OpenAL format that matches the given number of channels
|
||||
///
|
||||
/// \param channelCount Number of channels
|
||||
///
|
||||
/// \return Corresponding format
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static int getFormatFromChannelCount(unsigned int channelCount);
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_AUDIODEVICE_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_AUDIODEVICE_HPP
|
||||
#define SFML_AUDIODEVICE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief High-level wrapper around the audio API, it manages
|
||||
/// the creation and destruction of the audio device and
|
||||
/// context and stores the device capabilities
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class AudioDevice
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
AudioDevice();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~AudioDevice();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if an OpenAL extension is supported
|
||||
///
|
||||
/// This functions automatically finds whether it
|
||||
/// is an AL or ALC extension, and calls the corresponding
|
||||
/// function.
|
||||
///
|
||||
/// \param extension Name of the extension to test
|
||||
///
|
||||
/// \return True if the extension is supported, false if not
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static bool isExtensionSupported(const std::string& extension);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the OpenAL format that matches the given number of channels
|
||||
///
|
||||
/// \param channelCount Number of channels
|
||||
///
|
||||
/// \return Corresponding format
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static int getFormatFromChannelCount(unsigned int channelCount);
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_AUDIODEVICE_HPP
|
||||
|
|
|
@ -1,65 +1,65 @@
|
|||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Audio)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${SRCROOT}/ALCheck.cpp
|
||||
${SRCROOT}/ALCheck.hpp
|
||||
${SRCROOT}/AudioDevice.cpp
|
||||
${SRCROOT}/AudioDevice.hpp
|
||||
${INCROOT}/Export.hpp
|
||||
${SRCROOT}/Listener.cpp
|
||||
${INCROOT}/Listener.hpp
|
||||
${SRCROOT}/Music.cpp
|
||||
${INCROOT}/Music.hpp
|
||||
${SRCROOT}/Sound.cpp
|
||||
${INCROOT}/Sound.hpp
|
||||
${SRCROOT}/SoundBuffer.cpp
|
||||
${INCROOT}/SoundBuffer.hpp
|
||||
${SRCROOT}/SoundBufferRecorder.cpp
|
||||
${INCROOT}/SoundBufferRecorder.hpp
|
||||
${SRCROOT}/SoundFile.cpp
|
||||
${SRCROOT}/SoundFile.hpp
|
||||
${SRCROOT}/SoundRecorder.cpp
|
||||
${INCROOT}/SoundRecorder.hpp
|
||||
${SRCROOT}/SoundSource.cpp
|
||||
${INCROOT}/SoundSource.hpp
|
||||
${SRCROOT}/SoundStream.cpp
|
||||
${INCROOT}/SoundStream.hpp
|
||||
)
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# let CMake know about our additional audio libraries paths (on Windows and OSX)
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/windows")
|
||||
elseif(SFML_OS_MACOSX)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/osx")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/android")
|
||||
endif()
|
||||
|
||||
# find external libraries
|
||||
if(NOT SFML_OS_ANDROID)
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(Sndfile REQUIRED)
|
||||
else()
|
||||
find_host_package(OpenAL REQUIRED)
|
||||
find_host_package(Sndfile REQUIRED)
|
||||
endif()
|
||||
include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
|
||||
|
||||
# build the list of external libraries to link
|
||||
if(SFML_OS_ANDROID)
|
||||
list(APPEND AUDIO_EXT_LIBS -landroid -lOpenSLES)
|
||||
endif()
|
||||
list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY})
|
||||
|
||||
# define the sfml-audio target
|
||||
sfml_add_library(sfml-audio
|
||||
SOURCES ${SRC}
|
||||
DEPENDS sfml-system
|
||||
EXTERNAL_LIBS ${AUDIO_EXT_LIBS})
|
||||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Audio)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${SRCROOT}/ALCheck.cpp
|
||||
${SRCROOT}/ALCheck.hpp
|
||||
${SRCROOT}/AudioDevice.cpp
|
||||
${SRCROOT}/AudioDevice.hpp
|
||||
${INCROOT}/Export.hpp
|
||||
${SRCROOT}/Listener.cpp
|
||||
${INCROOT}/Listener.hpp
|
||||
${SRCROOT}/Music.cpp
|
||||
${INCROOT}/Music.hpp
|
||||
${SRCROOT}/Sound.cpp
|
||||
${INCROOT}/Sound.hpp
|
||||
${SRCROOT}/SoundBuffer.cpp
|
||||
${INCROOT}/SoundBuffer.hpp
|
||||
${SRCROOT}/SoundBufferRecorder.cpp
|
||||
${INCROOT}/SoundBufferRecorder.hpp
|
||||
${SRCROOT}/SoundFile.cpp
|
||||
${SRCROOT}/SoundFile.hpp
|
||||
${SRCROOT}/SoundRecorder.cpp
|
||||
${INCROOT}/SoundRecorder.hpp
|
||||
${SRCROOT}/SoundSource.cpp
|
||||
${INCROOT}/SoundSource.hpp
|
||||
${SRCROOT}/SoundStream.cpp
|
||||
${INCROOT}/SoundStream.hpp
|
||||
)
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# let CMake know about our additional audio libraries paths (on Windows and OSX)
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/windows")
|
||||
elseif(SFML_OS_MACOSX)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/osx")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/android")
|
||||
endif()
|
||||
|
||||
# find external libraries
|
||||
if(NOT SFML_OS_ANDROID)
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(Sndfile REQUIRED)
|
||||
else()
|
||||
find_host_package(OpenAL REQUIRED)
|
||||
find_host_package(Sndfile REQUIRED)
|
||||
endif()
|
||||
include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
|
||||
|
||||
# build the list of external libraries to link
|
||||
if(SFML_OS_ANDROID)
|
||||
list(APPEND AUDIO_EXT_LIBS -landroid -lOpenSLES)
|
||||
endif()
|
||||
list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY})
|
||||
|
||||
# define the sfml-audio target
|
||||
sfml_add_library(sfml-audio
|
||||
SOURCES ${SRC}
|
||||
DEPENDS sfml-system
|
||||
EXTERNAL_LIBS ${AUDIO_EXT_LIBS})
|
||||
|
|
|
@ -1,145 +1,145 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/Listener.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
float listenerVolume = 100.f;
|
||||
sf::Vector3f listenerPosition (0.f, 0.f, 0.f);
|
||||
sf::Vector3f listenerDirection(0.f, 0.f, -1.f);
|
||||
sf::Vector3f listenerUpVector (0.f, 1.f, 0.f);
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setGlobalVolume(float volume)
|
||||
{
|
||||
if (volume != listenerVolume)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
alCheck(alListenerf(AL_GAIN, volume * 0.01f));
|
||||
listenerVolume = volume;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float Listener::getGlobalVolume()
|
||||
{
|
||||
return listenerVolume;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setPosition(float x, float y, float z)
|
||||
{
|
||||
setPosition(Vector3f(x, y, z));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setPosition(const Vector3f& position)
|
||||
{
|
||||
if (position != listenerPosition)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));
|
||||
listenerPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3f Listener::getPosition()
|
||||
{
|
||||
return listenerPosition;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setDirection(float x, float y, float z)
|
||||
{
|
||||
setDirection(Vector3f(x, y, z));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setDirection(const Vector3f& direction)
|
||||
{
|
||||
if (direction != listenerDirection)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
float orientation[] = {direction.x, direction.y, direction.z, listenerUpVector.x, listenerUpVector.y, listenerUpVector.z};
|
||||
alCheck(alListenerfv(AL_ORIENTATION, orientation));
|
||||
listenerDirection = direction;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3f Listener::getDirection()
|
||||
{
|
||||
return listenerDirection;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setUpVector(float x, float y, float z)
|
||||
{
|
||||
setUpVector(Vector3f(x, y, z));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setUpVector(const Vector3f& upVector)
|
||||
{
|
||||
if (upVector != listenerUpVector)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
float orientation[] = {listenerDirection.x, listenerDirection.y, listenerDirection.z, upVector.x, upVector.y, upVector.z};
|
||||
alCheck(alListenerfv(AL_ORIENTATION, orientation));
|
||||
listenerUpVector = upVector;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3f Listener::getUpVector()
|
||||
{
|
||||
return listenerUpVector;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/Listener.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
float listenerVolume = 100.f;
|
||||
sf::Vector3f listenerPosition (0.f, 0.f, 0.f);
|
||||
sf::Vector3f listenerDirection(0.f, 0.f, -1.f);
|
||||
sf::Vector3f listenerUpVector (0.f, 1.f, 0.f);
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setGlobalVolume(float volume)
|
||||
{
|
||||
if (volume != listenerVolume)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
alCheck(alListenerf(AL_GAIN, volume * 0.01f));
|
||||
listenerVolume = volume;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float Listener::getGlobalVolume()
|
||||
{
|
||||
return listenerVolume;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setPosition(float x, float y, float z)
|
||||
{
|
||||
setPosition(Vector3f(x, y, z));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setPosition(const Vector3f& position)
|
||||
{
|
||||
if (position != listenerPosition)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));
|
||||
listenerPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3f Listener::getPosition()
|
||||
{
|
||||
return listenerPosition;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setDirection(float x, float y, float z)
|
||||
{
|
||||
setDirection(Vector3f(x, y, z));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setDirection(const Vector3f& direction)
|
||||
{
|
||||
if (direction != listenerDirection)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
float orientation[] = {direction.x, direction.y, direction.z, listenerUpVector.x, listenerUpVector.y, listenerUpVector.z};
|
||||
alCheck(alListenerfv(AL_ORIENTATION, orientation));
|
||||
listenerDirection = direction;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3f Listener::getDirection()
|
||||
{
|
||||
return listenerDirection;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setUpVector(float x, float y, float z)
|
||||
{
|
||||
setUpVector(Vector3f(x, y, z));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Listener::setUpVector(const Vector3f& upVector)
|
||||
{
|
||||
if (upVector != listenerUpVector)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
float orientation[] = {listenerDirection.x, listenerDirection.y, listenerDirection.z, upVector.x, upVector.y, upVector.z};
|
||||
alCheck(alListenerfv(AL_ORIENTATION, orientation));
|
||||
listenerUpVector = upVector;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3f Listener::getUpVector()
|
||||
{
|
||||
return listenerUpVector;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,151 +1,151 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/Music.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/Audio/SoundFile.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Music::Music() :
|
||||
m_file (new priv::SoundFile),
|
||||
m_duration()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Music::~Music()
|
||||
{
|
||||
// We must stop before destroying the file
|
||||
stop();
|
||||
|
||||
delete m_file;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Music::openFromFile(const std::string& filename)
|
||||
{
|
||||
// First stop the music if it was already running
|
||||
stop();
|
||||
|
||||
// Open the underlying sound file
|
||||
if (!m_file->openRead(filename))
|
||||
return false;
|
||||
|
||||
// Perform common initializations
|
||||
initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Music::openFromMemory(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
// First stop the music if it was already running
|
||||
stop();
|
||||
|
||||
// Open the underlying sound file
|
||||
if (!m_file->openRead(data, sizeInBytes))
|
||||
return false;
|
||||
|
||||
// Perform common initializations
|
||||
initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Music::openFromStream(InputStream& stream)
|
||||
{
|
||||
// First stop the music if it was already running
|
||||
stop();
|
||||
|
||||
// Open the underlying sound file
|
||||
if (!m_file->openRead(stream))
|
||||
return false;
|
||||
|
||||
// Perform common initializations
|
||||
initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Music::getDuration() const
|
||||
{
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Music::onGetData(SoundStream::Chunk& data)
|
||||
{
|
||||
Lock lock(m_mutex);
|
||||
|
||||
// Fill the chunk parameters
|
||||
data.samples = &m_samples[0];
|
||||
data.sampleCount = m_file->read(&m_samples[0], m_samples.size());
|
||||
|
||||
// Check if we have reached the end of the audio file
|
||||
return data.sampleCount == m_samples.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Music::onSeek(Time timeOffset)
|
||||
{
|
||||
Lock lock(m_mutex);
|
||||
|
||||
m_file->seek(timeOffset);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Music::initialize()
|
||||
{
|
||||
// Compute the music duration
|
||||
m_duration = seconds(static_cast<float>(m_file->getSampleCount()) / m_file->getSampleRate() / m_file->getChannelCount());
|
||||
|
||||
// Resize the internal buffer so that it can contain 1 second of audio samples
|
||||
m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount());
|
||||
|
||||
// Initialize the stream
|
||||
SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate());
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/Music.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/Audio/SoundFile.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Music::Music() :
|
||||
m_file (new priv::SoundFile),
|
||||
m_duration()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Music::~Music()
|
||||
{
|
||||
// We must stop before destroying the file
|
||||
stop();
|
||||
|
||||
delete m_file;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Music::openFromFile(const std::string& filename)
|
||||
{
|
||||
// First stop the music if it was already running
|
||||
stop();
|
||||
|
||||
// Open the underlying sound file
|
||||
if (!m_file->openRead(filename))
|
||||
return false;
|
||||
|
||||
// Perform common initializations
|
||||
initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Music::openFromMemory(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
// First stop the music if it was already running
|
||||
stop();
|
||||
|
||||
// Open the underlying sound file
|
||||
if (!m_file->openRead(data, sizeInBytes))
|
||||
return false;
|
||||
|
||||
// Perform common initializations
|
||||
initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Music::openFromStream(InputStream& stream)
|
||||
{
|
||||
// First stop the music if it was already running
|
||||
stop();
|
||||
|
||||
// Open the underlying sound file
|
||||
if (!m_file->openRead(stream))
|
||||
return false;
|
||||
|
||||
// Perform common initializations
|
||||
initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Music::getDuration() const
|
||||
{
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Music::onGetData(SoundStream::Chunk& data)
|
||||
{
|
||||
Lock lock(m_mutex);
|
||||
|
||||
// Fill the chunk parameters
|
||||
data.samples = &m_samples[0];
|
||||
data.sampleCount = m_file->read(&m_samples[0], m_samples.size());
|
||||
|
||||
// Check if we have reached the end of the audio file
|
||||
return data.sampleCount == m_samples.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Music::onSeek(Time timeOffset)
|
||||
{
|
||||
Lock lock(m_mutex);
|
||||
|
||||
m_file->seek(timeOffset);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Music::initialize()
|
||||
{
|
||||
// Compute the music duration
|
||||
m_duration = seconds(static_cast<float>(m_file->getSampleCount()) / m_file->getSampleRate() / m_file->getChannelCount());
|
||||
|
||||
// Resize the internal buffer so that it can contain 1 second of audio samples
|
||||
m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount());
|
||||
|
||||
// Initialize the stream
|
||||
SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate());
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,200 +1,200 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/Sound.hpp>
|
||||
#include <SFML/Audio/SoundBuffer.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::Sound() :
|
||||
m_buffer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::Sound(const SoundBuffer& buffer) :
|
||||
m_buffer(NULL)
|
||||
{
|
||||
setBuffer(buffer);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::Sound(const Sound& copy) :
|
||||
SoundSource(copy),
|
||||
m_buffer (NULL)
|
||||
{
|
||||
if (copy.m_buffer)
|
||||
setBuffer(*copy.m_buffer);
|
||||
setLoop(copy.getLoop());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::~Sound()
|
||||
{
|
||||
stop();
|
||||
if (m_buffer)
|
||||
m_buffer->detachSound(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::play()
|
||||
{
|
||||
alCheck(alSourcePlay(m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::pause()
|
||||
{
|
||||
alCheck(alSourcePause(m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::stop()
|
||||
{
|
||||
alCheck(alSourceStop(m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::setBuffer(const SoundBuffer& buffer)
|
||||
{
|
||||
// First detach from the previous buffer
|
||||
if (m_buffer)
|
||||
{
|
||||
stop();
|
||||
m_buffer->detachSound(this);
|
||||
}
|
||||
|
||||
// Assign and use the new buffer
|
||||
m_buffer = &buffer;
|
||||
m_buffer->attachSound(this);
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, m_buffer->m_buffer));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::setLoop(bool loop)
|
||||
{
|
||||
alCheck(alSourcei(m_source, AL_LOOPING, loop));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::setPlayingOffset(Time timeOffset)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds()));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const SoundBuffer* Sound::getBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Sound::getLoop() const
|
||||
{
|
||||
ALint loop;
|
||||
alCheck(alGetSourcei(m_source, AL_LOOPING, &loop));
|
||||
|
||||
return loop != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Sound::getPlayingOffset() const
|
||||
{
|
||||
ALfloat secs = 0.f;
|
||||
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
|
||||
|
||||
return seconds(secs);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::Status Sound::getStatus() const
|
||||
{
|
||||
return SoundSource::getStatus();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound& Sound::operator =(const Sound& right)
|
||||
{
|
||||
// Here we don't use the copy-and-swap idiom, because it would mess up
|
||||
// the list of sound instances contained in the buffers
|
||||
|
||||
// Detach the sound instance from the previous buffer (if any)
|
||||
if (m_buffer)
|
||||
{
|
||||
stop();
|
||||
m_buffer->detachSound(this);
|
||||
m_buffer = NULL;
|
||||
}
|
||||
|
||||
// Copy the sound attributes
|
||||
if (right.m_buffer)
|
||||
setBuffer(*right.m_buffer);
|
||||
setLoop(right.getLoop());
|
||||
setPitch(right.getPitch());
|
||||
setVolume(right.getVolume());
|
||||
setPosition(right.getPosition());
|
||||
setRelativeToListener(right.isRelativeToListener());
|
||||
setMinDistance(right.getMinDistance());
|
||||
setAttenuation(right.getAttenuation());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::resetBuffer()
|
||||
{
|
||||
// First stop the sound in case it is playing
|
||||
stop();
|
||||
|
||||
// Detach the buffer
|
||||
if (m_buffer)
|
||||
{
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
m_buffer->detachSound(this);
|
||||
m_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/Sound.hpp>
|
||||
#include <SFML/Audio/SoundBuffer.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::Sound() :
|
||||
m_buffer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::Sound(const SoundBuffer& buffer) :
|
||||
m_buffer(NULL)
|
||||
{
|
||||
setBuffer(buffer);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::Sound(const Sound& copy) :
|
||||
SoundSource(copy),
|
||||
m_buffer (NULL)
|
||||
{
|
||||
if (copy.m_buffer)
|
||||
setBuffer(*copy.m_buffer);
|
||||
setLoop(copy.getLoop());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::~Sound()
|
||||
{
|
||||
stop();
|
||||
if (m_buffer)
|
||||
m_buffer->detachSound(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::play()
|
||||
{
|
||||
alCheck(alSourcePlay(m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::pause()
|
||||
{
|
||||
alCheck(alSourcePause(m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::stop()
|
||||
{
|
||||
alCheck(alSourceStop(m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::setBuffer(const SoundBuffer& buffer)
|
||||
{
|
||||
// First detach from the previous buffer
|
||||
if (m_buffer)
|
||||
{
|
||||
stop();
|
||||
m_buffer->detachSound(this);
|
||||
}
|
||||
|
||||
// Assign and use the new buffer
|
||||
m_buffer = &buffer;
|
||||
m_buffer->attachSound(this);
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, m_buffer->m_buffer));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::setLoop(bool loop)
|
||||
{
|
||||
alCheck(alSourcei(m_source, AL_LOOPING, loop));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::setPlayingOffset(Time timeOffset)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds()));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const SoundBuffer* Sound::getBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Sound::getLoop() const
|
||||
{
|
||||
ALint loop;
|
||||
alCheck(alGetSourcei(m_source, AL_LOOPING, &loop));
|
||||
|
||||
return loop != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Sound::getPlayingOffset() const
|
||||
{
|
||||
ALfloat secs = 0.f;
|
||||
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
|
||||
|
||||
return seconds(secs);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound::Status Sound::getStatus() const
|
||||
{
|
||||
return SoundSource::getStatus();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sound& Sound::operator =(const Sound& right)
|
||||
{
|
||||
// Here we don't use the copy-and-swap idiom, because it would mess up
|
||||
// the list of sound instances contained in the buffers
|
||||
|
||||
// Detach the sound instance from the previous buffer (if any)
|
||||
if (m_buffer)
|
||||
{
|
||||
stop();
|
||||
m_buffer->detachSound(this);
|
||||
m_buffer = NULL;
|
||||
}
|
||||
|
||||
// Copy the sound attributes
|
||||
if (right.m_buffer)
|
||||
setBuffer(*right.m_buffer);
|
||||
setLoop(right.getLoop());
|
||||
setPitch(right.getPitch());
|
||||
setVolume(right.getVolume());
|
||||
setPosition(right.getPosition());
|
||||
setRelativeToListener(right.isRelativeToListener());
|
||||
setMinDistance(right.getMinDistance());
|
||||
setAttenuation(right.getAttenuation());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sound::resetBuffer()
|
||||
{
|
||||
// First stop the sound in case it is playing
|
||||
stop();
|
||||
|
||||
// Detach the buffer
|
||||
if (m_buffer)
|
||||
{
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
m_buffer->detachSound(this);
|
||||
m_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,286 +1,286 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundBuffer.hpp>
|
||||
#include <SFML/Audio/SoundFile.hpp>
|
||||
#include <SFML/Audio/Sound.hpp>
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::SoundBuffer() :
|
||||
m_buffer (0),
|
||||
m_duration()
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
// Create the buffer
|
||||
alCheck(alGenBuffers(1, &m_buffer));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
|
||||
m_buffer (0),
|
||||
m_samples (copy.m_samples),
|
||||
m_duration(copy.m_duration),
|
||||
m_sounds () // don't copy the attached sounds
|
||||
{
|
||||
// Create the buffer
|
||||
alCheck(alGenBuffers(1, &m_buffer));
|
||||
|
||||
// Update the internal buffer with the new samples
|
||||
update(copy.getChannelCount(), copy.getSampleRate());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::~SoundBuffer()
|
||||
{
|
||||
// First detach the buffer from the sounds that use it (to avoid OpenAL errors)
|
||||
for (SoundList::const_iterator it = m_sounds.begin(); it != m_sounds.end(); ++it)
|
||||
(*it)->resetBuffer();
|
||||
|
||||
// Destroy the buffer
|
||||
if (m_buffer)
|
||||
alCheck(alDeleteBuffers(1, &m_buffer));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromFile(const std::string& filename)
|
||||
{
|
||||
priv::SoundFile file;
|
||||
if (file.openRead(filename))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
priv::SoundFile file;
|
||||
if (file.openRead(data, sizeInBytes))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromStream(InputStream& stream)
|
||||
{
|
||||
priv::SoundFile file;
|
||||
if (file.openRead(stream))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate)
|
||||
{
|
||||
if (samples && sampleCount && channelCount && sampleRate)
|
||||
{
|
||||
// Copy the new audio samples
|
||||
m_samples.assign(samples, samples + sampleCount);
|
||||
|
||||
// Update the internal buffer with the new samples
|
||||
return update(channelCount, sampleRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error...
|
||||
err() << "Failed to load sound buffer from samples ("
|
||||
<< "array: " << samples << ", "
|
||||
<< "count: " << sampleCount << ", "
|
||||
<< "channels: " << channelCount << ", "
|
||||
<< "samplerate: " << sampleRate << ")"
|
||||
<< std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::saveToFile(const std::string& filename) const
|
||||
{
|
||||
// Create the sound file in write mode
|
||||
priv::SoundFile file;
|
||||
if (file.openWrite(filename, getChannelCount(), getSampleRate()))
|
||||
{
|
||||
// Write the samples to the opened file
|
||||
file.write(&m_samples[0], m_samples.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Int16* SoundBuffer::getSamples() const
|
||||
{
|
||||
return m_samples.empty() ? NULL : &m_samples[0];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t SoundBuffer::getSampleCount() const
|
||||
{
|
||||
return m_samples.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundBuffer::getSampleRate() const
|
||||
{
|
||||
ALint sampleRate;
|
||||
alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate));
|
||||
|
||||
return sampleRate;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundBuffer::getChannelCount() const
|
||||
{
|
||||
ALint channelCount;
|
||||
alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount));
|
||||
|
||||
return channelCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time SoundBuffer::getDuration() const
|
||||
{
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
|
||||
{
|
||||
SoundBuffer temp(right);
|
||||
|
||||
std::swap(m_samples, temp.m_samples);
|
||||
std::swap(m_buffer, temp.m_buffer);
|
||||
std::swap(m_duration, temp.m_duration);
|
||||
std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::initialize(priv::SoundFile& file)
|
||||
{
|
||||
// Retrieve the sound parameters
|
||||
std::size_t sampleCount = file.getSampleCount();
|
||||
unsigned int channelCount = file.getChannelCount();
|
||||
unsigned int sampleRate = file.getSampleRate();
|
||||
|
||||
// Read the samples from the provided file
|
||||
m_samples.resize(sampleCount);
|
||||
if (file.read(&m_samples[0], sampleCount) == sampleCount)
|
||||
{
|
||||
// Update the internal buffer with the new samples
|
||||
return update(channelCount, sampleRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate)
|
||||
{
|
||||
// Check parameters
|
||||
if (!channelCount || !sampleRate || m_samples.empty())
|
||||
return false;
|
||||
|
||||
// Find the good format according to the number of channels
|
||||
ALenum format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
|
||||
|
||||
// Check if the format is valid
|
||||
if (format == 0)
|
||||
{
|
||||
err() << "Failed to load sound buffer (unsupported number of channels: " << channelCount << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// First make a copy of the list of sounds so we can reattach later
|
||||
SoundList sounds(m_sounds);
|
||||
|
||||
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
|
||||
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
|
||||
(*it)->resetBuffer();
|
||||
|
||||
// Fill the buffer
|
||||
ALsizei size = static_cast<ALsizei>(m_samples.size()) * sizeof(Int16);
|
||||
alCheck(alBufferData(m_buffer, format, &m_samples[0], size, sampleRate));
|
||||
|
||||
// Compute the duration
|
||||
m_duration = seconds(static_cast<float>(m_samples.size()) / sampleRate / channelCount);
|
||||
|
||||
// Now reattach the buffer to the sounds that use it
|
||||
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
|
||||
(*it)->setBuffer(*this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundBuffer::attachSound(Sound* sound) const
|
||||
{
|
||||
m_sounds.insert(sound);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundBuffer::detachSound(Sound* sound) const
|
||||
{
|
||||
m_sounds.erase(sound);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundBuffer.hpp>
|
||||
#include <SFML/Audio/SoundFile.hpp>
|
||||
#include <SFML/Audio/Sound.hpp>
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::SoundBuffer() :
|
||||
m_buffer (0),
|
||||
m_duration()
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
// Create the buffer
|
||||
alCheck(alGenBuffers(1, &m_buffer));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
|
||||
m_buffer (0),
|
||||
m_samples (copy.m_samples),
|
||||
m_duration(copy.m_duration),
|
||||
m_sounds () // don't copy the attached sounds
|
||||
{
|
||||
// Create the buffer
|
||||
alCheck(alGenBuffers(1, &m_buffer));
|
||||
|
||||
// Update the internal buffer with the new samples
|
||||
update(copy.getChannelCount(), copy.getSampleRate());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer::~SoundBuffer()
|
||||
{
|
||||
// First detach the buffer from the sounds that use it (to avoid OpenAL errors)
|
||||
for (SoundList::const_iterator it = m_sounds.begin(); it != m_sounds.end(); ++it)
|
||||
(*it)->resetBuffer();
|
||||
|
||||
// Destroy the buffer
|
||||
if (m_buffer)
|
||||
alCheck(alDeleteBuffers(1, &m_buffer));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromFile(const std::string& filename)
|
||||
{
|
||||
priv::SoundFile file;
|
||||
if (file.openRead(filename))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
priv::SoundFile file;
|
||||
if (file.openRead(data, sizeInBytes))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromStream(InputStream& stream)
|
||||
{
|
||||
priv::SoundFile file;
|
||||
if (file.openRead(stream))
|
||||
return initialize(file);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate)
|
||||
{
|
||||
if (samples && sampleCount && channelCount && sampleRate)
|
||||
{
|
||||
// Copy the new audio samples
|
||||
m_samples.assign(samples, samples + sampleCount);
|
||||
|
||||
// Update the internal buffer with the new samples
|
||||
return update(channelCount, sampleRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error...
|
||||
err() << "Failed to load sound buffer from samples ("
|
||||
<< "array: " << samples << ", "
|
||||
<< "count: " << sampleCount << ", "
|
||||
<< "channels: " << channelCount << ", "
|
||||
<< "samplerate: " << sampleRate << ")"
|
||||
<< std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::saveToFile(const std::string& filename) const
|
||||
{
|
||||
// Create the sound file in write mode
|
||||
priv::SoundFile file;
|
||||
if (file.openWrite(filename, getChannelCount(), getSampleRate()))
|
||||
{
|
||||
// Write the samples to the opened file
|
||||
file.write(&m_samples[0], m_samples.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Int16* SoundBuffer::getSamples() const
|
||||
{
|
||||
return m_samples.empty() ? NULL : &m_samples[0];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t SoundBuffer::getSampleCount() const
|
||||
{
|
||||
return m_samples.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundBuffer::getSampleRate() const
|
||||
{
|
||||
ALint sampleRate;
|
||||
alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate));
|
||||
|
||||
return sampleRate;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundBuffer::getChannelCount() const
|
||||
{
|
||||
ALint channelCount;
|
||||
alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount));
|
||||
|
||||
return channelCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time SoundBuffer::getDuration() const
|
||||
{
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
|
||||
{
|
||||
SoundBuffer temp(right);
|
||||
|
||||
std::swap(m_samples, temp.m_samples);
|
||||
std::swap(m_buffer, temp.m_buffer);
|
||||
std::swap(m_duration, temp.m_duration);
|
||||
std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::initialize(priv::SoundFile& file)
|
||||
{
|
||||
// Retrieve the sound parameters
|
||||
std::size_t sampleCount = file.getSampleCount();
|
||||
unsigned int channelCount = file.getChannelCount();
|
||||
unsigned int sampleRate = file.getSampleRate();
|
||||
|
||||
// Read the samples from the provided file
|
||||
m_samples.resize(sampleCount);
|
||||
if (file.read(&m_samples[0], sampleCount) == sampleCount)
|
||||
{
|
||||
// Update the internal buffer with the new samples
|
||||
return update(channelCount, sampleRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate)
|
||||
{
|
||||
// Check parameters
|
||||
if (!channelCount || !sampleRate || m_samples.empty())
|
||||
return false;
|
||||
|
||||
// Find the good format according to the number of channels
|
||||
ALenum format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
|
||||
|
||||
// Check if the format is valid
|
||||
if (format == 0)
|
||||
{
|
||||
err() << "Failed to load sound buffer (unsupported number of channels: " << channelCount << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// First make a copy of the list of sounds so we can reattach later
|
||||
SoundList sounds(m_sounds);
|
||||
|
||||
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
|
||||
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
|
||||
(*it)->resetBuffer();
|
||||
|
||||
// Fill the buffer
|
||||
ALsizei size = static_cast<ALsizei>(m_samples.size()) * sizeof(Int16);
|
||||
alCheck(alBufferData(m_buffer, format, &m_samples[0], size, sampleRate));
|
||||
|
||||
// Compute the duration
|
||||
m_duration = seconds(static_cast<float>(m_samples.size()) / sampleRate / channelCount);
|
||||
|
||||
// Now reattach the buffer to the sounds that use it
|
||||
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
|
||||
(*it)->setBuffer(*this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundBuffer::attachSound(Sound* sound) const
|
||||
{
|
||||
m_sounds.insert(sound);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundBuffer::detachSound(Sound* sound) const
|
||||
{
|
||||
m_sounds.erase(sound);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,68 +1,68 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundBufferRecorder.hpp>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBufferRecorder::onStart()
|
||||
{
|
||||
m_samples.clear();
|
||||
m_buffer = SoundBuffer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBufferRecorder::onProcessSamples(const Int16* samples, std::size_t sampleCount)
|
||||
{
|
||||
std::copy(samples, samples + sampleCount, std::back_inserter(m_samples));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundBufferRecorder::onStop()
|
||||
{
|
||||
if (!m_samples.empty())
|
||||
m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), 1, getSampleRate());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const SoundBuffer& SoundBufferRecorder::getBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundBufferRecorder.hpp>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBufferRecorder::onStart()
|
||||
{
|
||||
m_samples.clear();
|
||||
m_buffer = SoundBuffer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundBufferRecorder::onProcessSamples(const Int16* samples, std::size_t sampleCount)
|
||||
{
|
||||
std::copy(samples, samples + sampleCount, std::back_inserter(m_samples));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundBufferRecorder::onStop()
|
||||
{
|
||||
if (!m_samples.empty())
|
||||
m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), 1, getSampleRate());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const SoundBuffer& SoundBufferRecorder::getBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,451 +1,451 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundFile.hpp>
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
#include <SFML/System/Android/ResourceStream.hpp>
|
||||
#endif
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Convert a string to lower case
|
||||
std::string toLower(std::string str)
|
||||
{
|
||||
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
||||
*i = static_cast<char>(std::tolower(*i));
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFile::SoundFile() :
|
||||
m_file (NULL),
|
||||
m_sampleCount (0),
|
||||
m_channelCount(0),
|
||||
m_sampleRate (0)
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
|
||||
m_resourceStream = NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFile::~SoundFile()
|
||||
{
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
|
||||
if (m_resourceStream)
|
||||
delete (priv::ResourceStream*)m_resourceStream;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t SoundFile::getSampleCount() const
|
||||
{
|
||||
return m_sampleCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundFile::getChannelCount() const
|
||||
{
|
||||
return m_channelCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundFile::getSampleRate() const
|
||||
{
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFile::openRead(const std::string& filename)
|
||||
{
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
|
||||
// If the file is already opened, first close it
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
// Open the sound file
|
||||
SF_INFO fileInfo;
|
||||
fileInfo.format = 0;
|
||||
m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the internal state from the loaded information
|
||||
initialize(fileInfo);
|
||||
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
if (m_resourceStream)
|
||||
delete (priv::ResourceStream*)m_resourceStream;
|
||||
|
||||
m_resourceStream = new priv::ResourceStream(filename);
|
||||
return openRead(*(priv::ResourceStream*)m_resourceStream);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFile::openRead(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
// If the file is already opened, first close it
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
// Prepare the memory I/O structure
|
||||
SF_VIRTUAL_IO io;
|
||||
io.get_filelen = &Memory::getLength;
|
||||
io.read = &Memory::read;
|
||||
io.seek = &Memory::seek;
|
||||
io.tell = &Memory::tell;
|
||||
|
||||
// Initialize the memory data
|
||||
m_memory.begin = static_cast<const char*>(data);
|
||||
m_memory.current = m_memory.begin;
|
||||
m_memory.size = sizeInBytes;
|
||||
|
||||
// Open the sound file
|
||||
SF_INFO fileInfo;
|
||||
fileInfo.format = 0;
|
||||
m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the internal state from the loaded information
|
||||
initialize(fileInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFile::openRead(InputStream& stream)
|
||||
{
|
||||
// If the file is already opened, first close it
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
// Prepare the memory I/O structure
|
||||
SF_VIRTUAL_IO io;
|
||||
io.get_filelen = &Stream::getLength;
|
||||
io.read = &Stream::read;
|
||||
io.seek = &Stream::seek;
|
||||
io.tell = &Stream::tell;
|
||||
|
||||
// Initialize the stream data
|
||||
m_stream.source = &stream;
|
||||
m_stream.size = stream.getSize();
|
||||
|
||||
// Make sure that the stream's reading position is at the beginning
|
||||
stream.seek(0);
|
||||
|
||||
// Open the sound file
|
||||
SF_INFO fileInfo;
|
||||
fileInfo.format = 0;
|
||||
m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the internal state from the loaded information
|
||||
initialize(fileInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate)
|
||||
{
|
||||
// If the file is already opened, first close it
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
// Find the right format according to the file extension
|
||||
int format = getFormatFromFilename(filename);
|
||||
if (format == -1)
|
||||
{
|
||||
// Error : unrecognized extension
|
||||
err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fill the sound infos with parameters
|
||||
SF_INFO fileInfos;
|
||||
fileInfos.channels = channelCount;
|
||||
fileInfos.samplerate = sampleRate;
|
||||
fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16);
|
||||
|
||||
// Open the sound file for writing
|
||||
m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the sound parameters
|
||||
m_channelCount = channelCount;
|
||||
m_sampleRate = sampleRate;
|
||||
m_sampleCount = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t SoundFile::read(Int16* data, std::size_t sampleCount)
|
||||
{
|
||||
if (m_file && data && sampleCount)
|
||||
return static_cast<std::size_t>(sf_read_short(m_file, data, sampleCount));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFile::write(const Int16* data, std::size_t sampleCount)
|
||||
{
|
||||
if (m_file && data && sampleCount)
|
||||
{
|
||||
// Write small chunks instead of everything at once,
|
||||
// to avoid a stack overflow in libsndfile (happens only with OGG format)
|
||||
while (sampleCount > 0)
|
||||
{
|
||||
std::size_t count = sampleCount > 10000 ? 10000 : sampleCount;
|
||||
sf_write_short(m_file, data, count);
|
||||
data += count;
|
||||
sampleCount -= count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFile::seek(Time timeOffset)
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
sf_count_t frameOffset = static_cast<sf_count_t>(timeOffset.asSeconds() * m_sampleRate);
|
||||
sf_seek(m_file, frameOffset, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFile::initialize(SF_INFO fileInfo)
|
||||
{
|
||||
// Save the sound properties
|
||||
m_channelCount = fileInfo.channels;
|
||||
m_sampleRate = fileInfo.samplerate;
|
||||
m_sampleCount = static_cast<std::size_t>(fileInfo.frames) * fileInfo.channels;
|
||||
|
||||
// Enable scaling for Vorbis files (float samples)
|
||||
// @todo enable when it's faster (it currently has to iterate over the *whole* music)
|
||||
//if (fileInfo.format & SF_FORMAT_VORBIS)
|
||||
// sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int SoundFile::getFormatFromFilename(const std::string& filename)
|
||||
{
|
||||
// Extract the extension
|
||||
std::string ext = "wav";
|
||||
std::string::size_type pos = filename.find_last_of(".");
|
||||
if (pos != std::string::npos)
|
||||
ext = toLower(filename.substr(pos + 1));
|
||||
|
||||
// Match every supported extension with its format constant
|
||||
if (ext == "wav" ) return SF_FORMAT_WAV;
|
||||
if (ext == "aif" ) return SF_FORMAT_AIFF;
|
||||
if (ext == "aiff" ) return SF_FORMAT_AIFF;
|
||||
if (ext == "au" ) return SF_FORMAT_AU;
|
||||
if (ext == "raw" ) return SF_FORMAT_RAW;
|
||||
if (ext == "paf" ) return SF_FORMAT_PAF;
|
||||
if (ext == "svx" ) return SF_FORMAT_SVX;
|
||||
if (ext == "nist" ) return SF_FORMAT_NIST;
|
||||
if (ext == "voc" ) return SF_FORMAT_VOC;
|
||||
if (ext == "sf" ) return SF_FORMAT_IRCAM;
|
||||
if (ext == "w64" ) return SF_FORMAT_W64;
|
||||
if (ext == "mat4" ) return SF_FORMAT_MAT4;
|
||||
if (ext == "mat5" ) return SF_FORMAT_MAT5;
|
||||
if (ext == "pvf" ) return SF_FORMAT_PVF;
|
||||
if (ext == "xi" ) return SF_FORMAT_XI;
|
||||
if (ext == "htk" ) return SF_FORMAT_HTK;
|
||||
if (ext == "sds" ) return SF_FORMAT_SDS;
|
||||
if (ext == "avr" ) return SF_FORMAT_AVR;
|
||||
if (ext == "sd2" ) return SF_FORMAT_SD2;
|
||||
if (ext == "flac" ) return SF_FORMAT_FLAC;
|
||||
if (ext == "caf" ) return SF_FORMAT_CAF;
|
||||
if (ext == "wve" ) return SF_FORMAT_WVE;
|
||||
if (ext == "ogg" ) return SF_FORMAT_OGG;
|
||||
if (ext == "mpc2k") return SF_FORMAT_MPC2K;
|
||||
if (ext == "rf64" ) return SF_FORMAT_RF64;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Memory::getLength(void* user)
|
||||
{
|
||||
Memory* memory = static_cast<Memory*>(user);
|
||||
return memory->size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user)
|
||||
{
|
||||
Memory* memory = static_cast<Memory*>(user);
|
||||
|
||||
sf_count_t position = tell(user);
|
||||
if (position + count >= memory->size)
|
||||
count = memory->size - position;
|
||||
|
||||
std::memcpy(ptr, memory->current, static_cast<std::size_t>(count));
|
||||
memory->current += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
|
||||
{
|
||||
Memory* memory = static_cast<Memory*>(user);
|
||||
sf_count_t position = 0;
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET : position = offset; break;
|
||||
case SEEK_CUR : position = memory->current - memory->begin + offset; break;
|
||||
case SEEK_END : position = memory->size - offset; break;
|
||||
default : position = 0; break;
|
||||
}
|
||||
|
||||
if (position >= memory->size)
|
||||
position = memory->size - 1;
|
||||
else if (position < 0)
|
||||
position = 0;
|
||||
|
||||
memory->current = memory->begin + position;
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Memory::tell(void* user)
|
||||
{
|
||||
Memory* memory = static_cast<Memory*>(user);
|
||||
return memory->current - memory->begin;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Stream::getLength(void* userData)
|
||||
{
|
||||
Stream* stream = static_cast<Stream*>(userData);
|
||||
return stream->size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData)
|
||||
{
|
||||
Stream* stream = static_cast<Stream*>(userData);
|
||||
Int64 position = stream->source->tell();
|
||||
if (position != -1)
|
||||
{
|
||||
if (count > stream->size - position)
|
||||
count = stream->size - position;
|
||||
return stream->source->read(reinterpret_cast<char*>(ptr), count);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData)
|
||||
{
|
||||
Stream* stream = static_cast<Stream*>(userData);
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET : return stream->source->seek(offset);
|
||||
case SEEK_CUR : return stream->source->seek(stream->source->tell() + offset);
|
||||
case SEEK_END : return stream->source->seek(stream->size - offset);
|
||||
default : return stream->source->seek(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Stream::tell(void* userData)
|
||||
{
|
||||
Stream* stream = static_cast<Stream*>(userData);
|
||||
return stream->source->tell();
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundFile.hpp>
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
#include <SFML/System/Android/ResourceStream.hpp>
|
||||
#endif
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Convert a string to lower case
|
||||
std::string toLower(std::string str)
|
||||
{
|
||||
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
||||
*i = static_cast<char>(std::tolower(*i));
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFile::SoundFile() :
|
||||
m_file (NULL),
|
||||
m_sampleCount (0),
|
||||
m_channelCount(0),
|
||||
m_sampleRate (0)
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
|
||||
m_resourceStream = NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFile::~SoundFile()
|
||||
{
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
|
||||
if (m_resourceStream)
|
||||
delete (priv::ResourceStream*)m_resourceStream;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t SoundFile::getSampleCount() const
|
||||
{
|
||||
return m_sampleCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundFile::getChannelCount() const
|
||||
{
|
||||
return m_channelCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundFile::getSampleRate() const
|
||||
{
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFile::openRead(const std::string& filename)
|
||||
{
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
|
||||
// If the file is already opened, first close it
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
// Open the sound file
|
||||
SF_INFO fileInfo;
|
||||
fileInfo.format = 0;
|
||||
m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the internal state from the loaded information
|
||||
initialize(fileInfo);
|
||||
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
if (m_resourceStream)
|
||||
delete (priv::ResourceStream*)m_resourceStream;
|
||||
|
||||
m_resourceStream = new priv::ResourceStream(filename);
|
||||
return openRead(*(priv::ResourceStream*)m_resourceStream);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFile::openRead(const void* data, std::size_t sizeInBytes)
|
||||
{
|
||||
// If the file is already opened, first close it
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
// Prepare the memory I/O structure
|
||||
SF_VIRTUAL_IO io;
|
||||
io.get_filelen = &Memory::getLength;
|
||||
io.read = &Memory::read;
|
||||
io.seek = &Memory::seek;
|
||||
io.tell = &Memory::tell;
|
||||
|
||||
// Initialize the memory data
|
||||
m_memory.begin = static_cast<const char*>(data);
|
||||
m_memory.current = m_memory.begin;
|
||||
m_memory.size = sizeInBytes;
|
||||
|
||||
// Open the sound file
|
||||
SF_INFO fileInfo;
|
||||
fileInfo.format = 0;
|
||||
m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the internal state from the loaded information
|
||||
initialize(fileInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFile::openRead(InputStream& stream)
|
||||
{
|
||||
// If the file is already opened, first close it
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
// Prepare the memory I/O structure
|
||||
SF_VIRTUAL_IO io;
|
||||
io.get_filelen = &Stream::getLength;
|
||||
io.read = &Stream::read;
|
||||
io.seek = &Stream::seek;
|
||||
io.tell = &Stream::tell;
|
||||
|
||||
// Initialize the stream data
|
||||
m_stream.source = &stream;
|
||||
m_stream.size = stream.getSize();
|
||||
|
||||
// Make sure that the stream's reading position is at the beginning
|
||||
stream.seek(0);
|
||||
|
||||
// Open the sound file
|
||||
SF_INFO fileInfo;
|
||||
fileInfo.format = 0;
|
||||
m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the internal state from the loaded information
|
||||
initialize(fileInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate)
|
||||
{
|
||||
// If the file is already opened, first close it
|
||||
if (m_file)
|
||||
sf_close(m_file);
|
||||
|
||||
// Find the right format according to the file extension
|
||||
int format = getFormatFromFilename(filename);
|
||||
if (format == -1)
|
||||
{
|
||||
// Error: unrecognized extension
|
||||
err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fill the sound infos with parameters
|
||||
SF_INFO fileInfos;
|
||||
fileInfos.channels = channelCount;
|
||||
fileInfos.samplerate = sampleRate;
|
||||
fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16);
|
||||
|
||||
// Open the sound file for writing
|
||||
m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
|
||||
if (!m_file)
|
||||
{
|
||||
err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the sound parameters
|
||||
m_channelCount = channelCount;
|
||||
m_sampleRate = sampleRate;
|
||||
m_sampleCount = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t SoundFile::read(Int16* data, std::size_t sampleCount)
|
||||
{
|
||||
if (m_file && data && sampleCount)
|
||||
return static_cast<std::size_t>(sf_read_short(m_file, data, sampleCount));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFile::write(const Int16* data, std::size_t sampleCount)
|
||||
{
|
||||
if (m_file && data && sampleCount)
|
||||
{
|
||||
// Write small chunks instead of everything at once,
|
||||
// to avoid a stack overflow in libsndfile (happens only with OGG format)
|
||||
while (sampleCount > 0)
|
||||
{
|
||||
std::size_t count = sampleCount > 10000 ? 10000 : sampleCount;
|
||||
sf_write_short(m_file, data, count);
|
||||
data += count;
|
||||
sampleCount -= count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFile::seek(Time timeOffset)
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
sf_count_t frameOffset = static_cast<sf_count_t>(timeOffset.asSeconds() * m_sampleRate);
|
||||
sf_seek(m_file, frameOffset, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundFile::initialize(SF_INFO fileInfo)
|
||||
{
|
||||
// Save the sound properties
|
||||
m_channelCount = fileInfo.channels;
|
||||
m_sampleRate = fileInfo.samplerate;
|
||||
m_sampleCount = static_cast<std::size_t>(fileInfo.frames) * fileInfo.channels;
|
||||
|
||||
// Enable scaling for Vorbis files (float samples)
|
||||
// @todo enable when it's faster (it currently has to iterate over the *whole* music)
|
||||
//if (fileInfo.format & SF_FORMAT_VORBIS)
|
||||
// sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int SoundFile::getFormatFromFilename(const std::string& filename)
|
||||
{
|
||||
// Extract the extension
|
||||
std::string ext = "wav";
|
||||
std::string::size_type pos = filename.find_last_of(".");
|
||||
if (pos != std::string::npos)
|
||||
ext = toLower(filename.substr(pos + 1));
|
||||
|
||||
// Match every supported extension with its format constant
|
||||
if (ext == "wav" ) return SF_FORMAT_WAV;
|
||||
if (ext == "aif" ) return SF_FORMAT_AIFF;
|
||||
if (ext == "aiff" ) return SF_FORMAT_AIFF;
|
||||
if (ext == "au" ) return SF_FORMAT_AU;
|
||||
if (ext == "raw" ) return SF_FORMAT_RAW;
|
||||
if (ext == "paf" ) return SF_FORMAT_PAF;
|
||||
if (ext == "svx" ) return SF_FORMAT_SVX;
|
||||
if (ext == "nist" ) return SF_FORMAT_NIST;
|
||||
if (ext == "voc" ) return SF_FORMAT_VOC;
|
||||
if (ext == "sf" ) return SF_FORMAT_IRCAM;
|
||||
if (ext == "w64" ) return SF_FORMAT_W64;
|
||||
if (ext == "mat4" ) return SF_FORMAT_MAT4;
|
||||
if (ext == "mat5" ) return SF_FORMAT_MAT5;
|
||||
if (ext == "pvf" ) return SF_FORMAT_PVF;
|
||||
if (ext == "xi" ) return SF_FORMAT_XI;
|
||||
if (ext == "htk" ) return SF_FORMAT_HTK;
|
||||
if (ext == "sds" ) return SF_FORMAT_SDS;
|
||||
if (ext == "avr" ) return SF_FORMAT_AVR;
|
||||
if (ext == "sd2" ) return SF_FORMAT_SD2;
|
||||
if (ext == "flac" ) return SF_FORMAT_FLAC;
|
||||
if (ext == "caf" ) return SF_FORMAT_CAF;
|
||||
if (ext == "wve" ) return SF_FORMAT_WVE;
|
||||
if (ext == "ogg" ) return SF_FORMAT_OGG;
|
||||
if (ext == "mpc2k") return SF_FORMAT_MPC2K;
|
||||
if (ext == "rf64" ) return SF_FORMAT_RF64;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Memory::getLength(void* user)
|
||||
{
|
||||
Memory* memory = static_cast<Memory*>(user);
|
||||
return memory->size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user)
|
||||
{
|
||||
Memory* memory = static_cast<Memory*>(user);
|
||||
|
||||
sf_count_t position = tell(user);
|
||||
if (position + count >= memory->size)
|
||||
count = memory->size - position;
|
||||
|
||||
std::memcpy(ptr, memory->current, static_cast<std::size_t>(count));
|
||||
memory->current += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
|
||||
{
|
||||
Memory* memory = static_cast<Memory*>(user);
|
||||
sf_count_t position = 0;
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET: position = offset; break;
|
||||
case SEEK_CUR: position = memory->current - memory->begin + offset; break;
|
||||
case SEEK_END: position = memory->size - offset; break;
|
||||
default: position = 0; break;
|
||||
}
|
||||
|
||||
if (position >= memory->size)
|
||||
position = memory->size - 1;
|
||||
else if (position < 0)
|
||||
position = 0;
|
||||
|
||||
memory->current = memory->begin + position;
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Memory::tell(void* user)
|
||||
{
|
||||
Memory* memory = static_cast<Memory*>(user);
|
||||
return memory->current - memory->begin;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Stream::getLength(void* userData)
|
||||
{
|
||||
Stream* stream = static_cast<Stream*>(userData);
|
||||
return stream->size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData)
|
||||
{
|
||||
Stream* stream = static_cast<Stream*>(userData);
|
||||
Int64 position = stream->source->tell();
|
||||
if (position != -1)
|
||||
{
|
||||
if (count > stream->size - position)
|
||||
count = stream->size - position;
|
||||
return stream->source->read(reinterpret_cast<char*>(ptr), count);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData)
|
||||
{
|
||||
Stream* stream = static_cast<Stream*>(userData);
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET: return stream->source->seek(offset);
|
||||
case SEEK_CUR: return stream->source->seek(stream->source->tell() + offset);
|
||||
case SEEK_END: return stream->source->seek(stream->size - offset);
|
||||
default: return stream->source->seek(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
sf_count_t SoundFile::Stream::tell(void* userData)
|
||||
{
|
||||
Stream* stream = static_cast<Stream*>(userData);
|
||||
return stream->source->tell();
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,231 +1,231 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOUNDFILE_HPP
|
||||
#define SFML_SOUNDFILE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <sndfile.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class InputStream;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Provide read and write access to sound files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SoundFile : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFile();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~SoundFile();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the total number of audio samples in the file
|
||||
///
|
||||
/// \return Number of samples
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t getSampleCount() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the number of channels used by the sound
|
||||
///
|
||||
/// \return Number of channels (1 = mono, 2 = stereo)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int getChannelCount() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the sample rate of the sound
|
||||
///
|
||||
/// \return Sample rate, in samples per second
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int getSampleRate() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file for reading
|
||||
///
|
||||
/// \param filename Path of the sound file to load
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openRead(const std::string& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file in memory for reading
|
||||
///
|
||||
/// \param data Pointer to the file data in memory
|
||||
/// \param sizeInBytes Size of the data to load, in bytes
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openRead(const void* data, std::size_t sizeInBytes);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file from a custom stream for reading
|
||||
///
|
||||
/// \param stream Source stream to read from
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openRead(InputStream& stream);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief a the sound file for writing
|
||||
///
|
||||
/// \param filename Path of the sound file to write
|
||||
/// \param channelCount Number of channels in the sound
|
||||
/// \param sampleRate Sample rate of the sound
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read audio samples from the loaded sound
|
||||
///
|
||||
/// \param data Pointer to the sample array to fill
|
||||
/// \param sampleCount Number of samples to read
|
||||
///
|
||||
/// \return Number of samples actually read (may be less than \a sampleCount)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t read(Int16* data, std::size_t sampleCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Write audio samples to the file
|
||||
///
|
||||
/// \param data Pointer to the sample array to write
|
||||
/// \param sampleCount Number of samples to write
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void write(const Int16* data, std::size_t sampleCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Change the current read position in the file
|
||||
///
|
||||
/// \param timeOffset New playing position, from the beginning of the file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void seek(Time timeOffset);
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Initialize the internal state of the sound file
|
||||
///
|
||||
/// This function is called by all the openRead functions.
|
||||
///
|
||||
/// \param fileInfo Information about the loaded sound file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void initialize(SF_INFO fileInfo);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the internal format of an audio file according to
|
||||
/// its filename extension
|
||||
///
|
||||
/// \param filename Filename to check
|
||||
///
|
||||
/// \return Internal format matching the filename (-1 if no match)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static int getFormatFromFilename(const std::string& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Data and callbacks for opening from memory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
struct Memory
|
||||
{
|
||||
const char* begin;
|
||||
const char* current;
|
||||
sf_count_t size;
|
||||
|
||||
static sf_count_t getLength(void* user);
|
||||
static sf_count_t read(void* ptr, sf_count_t count, void* user);
|
||||
static sf_count_t seek(sf_count_t offset, int whence, void* user);
|
||||
static sf_count_t tell(void* user);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Data and callbacks for opening from stream
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
struct Stream
|
||||
{
|
||||
InputStream* source;
|
||||
Int64 size;
|
||||
|
||||
static sf_count_t getLength(void* user);
|
||||
static sf_count_t read(void* ptr, sf_count_t count, void* user);
|
||||
static sf_count_t seek(sf_count_t offset, int whence, void* user);
|
||||
static sf_count_t tell(void* user);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
SNDFILE* m_file; ///< File descriptor
|
||||
Memory m_memory; ///< Memory reading info
|
||||
Stream m_stream; ///< Stream reading info
|
||||
std::size_t m_sampleCount; ///< Total number of samples in the file
|
||||
unsigned int m_channelCount; ///< Number of channels used by the sound
|
||||
unsigned int m_sampleRate; ///< Number of samples per second
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
void* m_resourceStream; ///< Asset file streamer (if loaded from file)
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOUNDFILE_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOUNDFILE_HPP
|
||||
#define SFML_SOUNDFILE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include <sndfile.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class InputStream;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Provide read and write access to sound files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SoundFile : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundFile();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~SoundFile();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the total number of audio samples in the file
|
||||
///
|
||||
/// \return Number of samples
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t getSampleCount() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the number of channels used by the sound
|
||||
///
|
||||
/// \return Number of channels (1 = mono, 2 = stereo)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int getChannelCount() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the sample rate of the sound
|
||||
///
|
||||
/// \return Sample rate, in samples per second
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int getSampleRate() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file for reading
|
||||
///
|
||||
/// \param filename Path of the sound file to load
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openRead(const std::string& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file in memory for reading
|
||||
///
|
||||
/// \param data Pointer to the file data in memory
|
||||
/// \param sizeInBytes Size of the data to load, in bytes
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openRead(const void* data, std::size_t sizeInBytes);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Open a sound file from a custom stream for reading
|
||||
///
|
||||
/// \param stream Source stream to read from
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openRead(InputStream& stream);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief a the sound file for writing
|
||||
///
|
||||
/// \param filename Path of the sound file to write
|
||||
/// \param channelCount Number of channels in the sound
|
||||
/// \param sampleRate Sample rate of the sound
|
||||
///
|
||||
/// \return True if the file was successfully opened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Read audio samples from the loaded sound
|
||||
///
|
||||
/// \param data Pointer to the sample array to fill
|
||||
/// \param sampleCount Number of samples to read
|
||||
///
|
||||
/// \return Number of samples actually read (may be less than \a sampleCount)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t read(Int16* data, std::size_t sampleCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Write audio samples to the file
|
||||
///
|
||||
/// \param data Pointer to the sample array to write
|
||||
/// \param sampleCount Number of samples to write
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void write(const Int16* data, std::size_t sampleCount);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Change the current read position in the file
|
||||
///
|
||||
/// \param timeOffset New playing position, from the beginning of the file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void seek(Time timeOffset);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Initialize the internal state of the sound file
|
||||
///
|
||||
/// This function is called by all the openRead functions.
|
||||
///
|
||||
/// \param fileInfo Information about the loaded sound file
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void initialize(SF_INFO fileInfo);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the internal format of an audio file according to
|
||||
/// its filename extension
|
||||
///
|
||||
/// \param filename Filename to check
|
||||
///
|
||||
/// \return Internal format matching the filename (-1 if no match)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static int getFormatFromFilename(const std::string& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Data and callbacks for opening from memory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
struct Memory
|
||||
{
|
||||
const char* begin;
|
||||
const char* current;
|
||||
sf_count_t size;
|
||||
|
||||
static sf_count_t getLength(void* user);
|
||||
static sf_count_t read(void* ptr, sf_count_t count, void* user);
|
||||
static sf_count_t seek(sf_count_t offset, int whence, void* user);
|
||||
static sf_count_t tell(void* user);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Data and callbacks for opening from stream
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
struct Stream
|
||||
{
|
||||
InputStream* source;
|
||||
Int64 size;
|
||||
|
||||
static sf_count_t getLength(void* user);
|
||||
static sf_count_t read(void* ptr, sf_count_t count, void* user);
|
||||
static sf_count_t seek(sf_count_t offset, int whence, void* user);
|
||||
static sf_count_t tell(void* user);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
SNDFILE* m_file; ///< File descriptor
|
||||
Memory m_memory; ///< Memory reading info
|
||||
Stream m_stream; ///< Stream reading info
|
||||
std::size_t m_sampleCount; ///< Total number of samples in the file
|
||||
unsigned int m_channelCount; ///< Number of channels used by the sound
|
||||
unsigned int m_sampleRate; ///< Number of samples per second
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
void* m_resourceStream; ///< Asset file streamer (if loaded from file)
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOUNDFILE_HPP
|
||||
|
|
|
@ -1,290 +1,290 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundRecorder.hpp>
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/System/Sleep.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4355) // 'this' used in base member initializer list
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
ALCdevice* captureDevice = NULL;
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundRecorder::SoundRecorder() :
|
||||
m_thread (&SoundRecorder::record, this),
|
||||
m_sampleRate (0),
|
||||
m_processingInterval(milliseconds(100)),
|
||||
m_isCapturing (false)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
// Set the device name to the default device
|
||||
m_deviceName = getDefaultDevice();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundRecorder::~SoundRecorder()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundRecorder::start(unsigned int sampleRate)
|
||||
{
|
||||
// Check if the device can do audio capture
|
||||
if (!isAvailable())
|
||||
{
|
||||
err() << "Failed to start capture : your system cannot capture audio data (call SoundRecorder::isAvailable to check it)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that another capture is not already running
|
||||
if (captureDevice)
|
||||
{
|
||||
err() << "Trying to start audio capture, but another capture is already running" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Open the capture device for capturing 16 bits mono samples
|
||||
captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, AL_FORMAT_MONO16, sampleRate);
|
||||
if (!captureDevice)
|
||||
{
|
||||
err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear the array of samples
|
||||
m_samples.clear();
|
||||
|
||||
// Store the sample rate
|
||||
m_sampleRate = sampleRate;
|
||||
|
||||
// Notify derived class
|
||||
if (onStart())
|
||||
{
|
||||
// Start the capture
|
||||
alcCaptureStart(captureDevice);
|
||||
|
||||
// Start the capture in a new thread, to avoid blocking the main thread
|
||||
m_isCapturing = true;
|
||||
m_thread.launch();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::stop()
|
||||
{
|
||||
// Stop the capturing thread
|
||||
m_isCapturing = false;
|
||||
m_thread.wait();
|
||||
|
||||
// Notify derived class
|
||||
onStop();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundRecorder::getSampleRate() const
|
||||
{
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::vector<std::string> SoundRecorder::getAvailableDevices()
|
||||
{
|
||||
std::vector<std::string> deviceNameList;
|
||||
|
||||
const ALchar *deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||
if (deviceList)
|
||||
{
|
||||
while (*deviceList)
|
||||
{
|
||||
deviceNameList.push_back(deviceList);
|
||||
deviceList += std::strlen(deviceList) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return deviceNameList;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string SoundRecorder::getDefaultDevice()
|
||||
{
|
||||
return alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundRecorder::setDevice(const std::string& name)
|
||||
{
|
||||
// Store the device name
|
||||
if (name.empty())
|
||||
m_deviceName = getDefaultDevice();
|
||||
else
|
||||
m_deviceName = name;
|
||||
|
||||
if (m_isCapturing)
|
||||
{
|
||||
// Stop the capturing thread
|
||||
m_isCapturing = false;
|
||||
m_thread.wait();
|
||||
|
||||
// Open the requested capture device for capturing 16 bits mono samples
|
||||
captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, AL_FORMAT_MONO16, m_sampleRate);
|
||||
if (!captureDevice)
|
||||
{
|
||||
// Notify derived class
|
||||
onStop();
|
||||
|
||||
err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start the capture
|
||||
alcCaptureStart(captureDevice);
|
||||
|
||||
// Start the capture in a new thread, to avoid blocking the main thread
|
||||
m_isCapturing = true;
|
||||
m_thread.launch();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& SoundRecorder::getDevice() const
|
||||
{
|
||||
return m_deviceName;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundRecorder::isAvailable()
|
||||
{
|
||||
return (priv::AudioDevice::isExtensionSupported("ALC_EXT_CAPTURE") != AL_FALSE) ||
|
||||
(priv::AudioDevice::isExtensionSupported("ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::setProcessingInterval(sf::Time interval)
|
||||
{
|
||||
m_processingInterval = interval;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundRecorder::onStart()
|
||||
{
|
||||
// Nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::onStop()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::record()
|
||||
{
|
||||
while (m_isCapturing)
|
||||
{
|
||||
// Process available samples
|
||||
processCapturedSamples();
|
||||
|
||||
// Don't bother the CPU while waiting for more captured data
|
||||
sleep(m_processingInterval);
|
||||
}
|
||||
|
||||
// Capture is finished : clean up everything
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::processCapturedSamples()
|
||||
{
|
||||
// Get the number of samples available
|
||||
ALCint samplesAvailable;
|
||||
alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable);
|
||||
|
||||
if (samplesAvailable > 0)
|
||||
{
|
||||
// Get the recorded samples
|
||||
m_samples.resize(samplesAvailable);
|
||||
alcCaptureSamples(captureDevice, &m_samples[0], samplesAvailable);
|
||||
|
||||
// Forward them to the derived class
|
||||
if (!onProcessSamples(&m_samples[0], m_samples.size()))
|
||||
{
|
||||
// The user wants to stop the capture
|
||||
m_isCapturing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::cleanup()
|
||||
{
|
||||
// Stop the capture
|
||||
alcCaptureStop(captureDevice);
|
||||
|
||||
// Get the samples left in the buffer
|
||||
processCapturedSamples();
|
||||
|
||||
// Close the device
|
||||
alcCaptureCloseDevice(captureDevice);
|
||||
captureDevice = NULL;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundRecorder.hpp>
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/System/Sleep.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4355) // 'this' used in base member initializer list
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
ALCdevice* captureDevice = NULL;
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundRecorder::SoundRecorder() :
|
||||
m_thread (&SoundRecorder::record, this),
|
||||
m_sampleRate (0),
|
||||
m_processingInterval(milliseconds(100)),
|
||||
m_isCapturing (false)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
// Set the device name to the default device
|
||||
m_deviceName = getDefaultDevice();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundRecorder::~SoundRecorder()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundRecorder::start(unsigned int sampleRate)
|
||||
{
|
||||
// Check if the device can do audio capture
|
||||
if (!isAvailable())
|
||||
{
|
||||
err() << "Failed to start capture: your system cannot capture audio data (call SoundRecorder::isAvailable to check it)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that another capture is not already running
|
||||
if (captureDevice)
|
||||
{
|
||||
err() << "Trying to start audio capture, but another capture is already running" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Open the capture device for capturing 16 bits mono samples
|
||||
captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, AL_FORMAT_MONO16, sampleRate);
|
||||
if (!captureDevice)
|
||||
{
|
||||
err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear the array of samples
|
||||
m_samples.clear();
|
||||
|
||||
// Store the sample rate
|
||||
m_sampleRate = sampleRate;
|
||||
|
||||
// Notify derived class
|
||||
if (onStart())
|
||||
{
|
||||
// Start the capture
|
||||
alcCaptureStart(captureDevice);
|
||||
|
||||
// Start the capture in a new thread, to avoid blocking the main thread
|
||||
m_isCapturing = true;
|
||||
m_thread.launch();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::stop()
|
||||
{
|
||||
// Stop the capturing thread
|
||||
m_isCapturing = false;
|
||||
m_thread.wait();
|
||||
|
||||
// Notify derived class
|
||||
onStop();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundRecorder::getSampleRate() const
|
||||
{
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::vector<std::string> SoundRecorder::getAvailableDevices()
|
||||
{
|
||||
std::vector<std::string> deviceNameList;
|
||||
|
||||
const ALchar *deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||
if (deviceList)
|
||||
{
|
||||
while (*deviceList)
|
||||
{
|
||||
deviceNameList.push_back(deviceList);
|
||||
deviceList += std::strlen(deviceList) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return deviceNameList;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string SoundRecorder::getDefaultDevice()
|
||||
{
|
||||
return alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundRecorder::setDevice(const std::string& name)
|
||||
{
|
||||
// Store the device name
|
||||
if (name.empty())
|
||||
m_deviceName = getDefaultDevice();
|
||||
else
|
||||
m_deviceName = name;
|
||||
|
||||
if (m_isCapturing)
|
||||
{
|
||||
// Stop the capturing thread
|
||||
m_isCapturing = false;
|
||||
m_thread.wait();
|
||||
|
||||
// Open the requested capture device for capturing 16 bits mono samples
|
||||
captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, AL_FORMAT_MONO16, m_sampleRate);
|
||||
if (!captureDevice)
|
||||
{
|
||||
// Notify derived class
|
||||
onStop();
|
||||
|
||||
err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start the capture
|
||||
alcCaptureStart(captureDevice);
|
||||
|
||||
// Start the capture in a new thread, to avoid blocking the main thread
|
||||
m_isCapturing = true;
|
||||
m_thread.launch();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& SoundRecorder::getDevice() const
|
||||
{
|
||||
return m_deviceName;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundRecorder::isAvailable()
|
||||
{
|
||||
return (priv::AudioDevice::isExtensionSupported("ALC_EXT_CAPTURE") != AL_FALSE) ||
|
||||
(priv::AudioDevice::isExtensionSupported("ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::setProcessingInterval(sf::Time interval)
|
||||
{
|
||||
m_processingInterval = interval;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundRecorder::onStart()
|
||||
{
|
||||
// Nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::onStop()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::record()
|
||||
{
|
||||
while (m_isCapturing)
|
||||
{
|
||||
// Process available samples
|
||||
processCapturedSamples();
|
||||
|
||||
// Don't bother the CPU while waiting for more captured data
|
||||
sleep(m_processingInterval);
|
||||
}
|
||||
|
||||
// Capture is finished: clean up everything
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::processCapturedSamples()
|
||||
{
|
||||
// Get the number of samples available
|
||||
ALCint samplesAvailable;
|
||||
alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable);
|
||||
|
||||
if (samplesAvailable > 0)
|
||||
{
|
||||
// Get the recorded samples
|
||||
m_samples.resize(samplesAvailable);
|
||||
alcCaptureSamples(captureDevice, &m_samples[0], samplesAvailable);
|
||||
|
||||
// Forward them to the derived class
|
||||
if (!onProcessSamples(&m_samples[0], m_samples.size()))
|
||||
{
|
||||
// The user wants to stop the capture
|
||||
m_isCapturing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundRecorder::cleanup()
|
||||
{
|
||||
// Stop the capture
|
||||
alcCaptureStop(captureDevice);
|
||||
|
||||
// Get the samples left in the buffer
|
||||
processCapturedSamples();
|
||||
|
||||
// Close the device
|
||||
alcCaptureCloseDevice(captureDevice);
|
||||
captureDevice = NULL;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,194 +1,194 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundSource.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundSource::SoundSource()
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
alCheck(alGenSources(1, &m_source));
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundSource::SoundSource(const SoundSource& copy)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
alCheck(alGenSources(1, &m_source));
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
|
||||
setPitch(copy.getPitch());
|
||||
setVolume(copy.getVolume());
|
||||
setPosition(copy.getPosition());
|
||||
setRelativeToListener(copy.isRelativeToListener());
|
||||
setMinDistance(copy.getMinDistance());
|
||||
setAttenuation(copy.getAttenuation());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundSource::~SoundSource()
|
||||
{
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
alCheck(alDeleteSources(1, &m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setPitch(float pitch)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_PITCH, pitch));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setVolume(float volume)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_GAIN, volume * 0.01f));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setPosition(float x, float y, float z)
|
||||
{
|
||||
alCheck(alSource3f(m_source, AL_POSITION, x, y, z));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setPosition(const Vector3f& position)
|
||||
{
|
||||
setPosition(position.x, position.y, position.z);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setRelativeToListener(bool relative)
|
||||
{
|
||||
alCheck(alSourcei(m_source, AL_SOURCE_RELATIVE, relative));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setMinDistance(float distance)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_REFERENCE_DISTANCE, distance));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setAttenuation(float attenuation)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float SoundSource::getPitch() const
|
||||
{
|
||||
ALfloat pitch;
|
||||
alCheck(alGetSourcef(m_source, AL_PITCH, &pitch));
|
||||
|
||||
return pitch;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float SoundSource::getVolume() const
|
||||
{
|
||||
ALfloat gain;
|
||||
alCheck(alGetSourcef(m_source, AL_GAIN, &gain));
|
||||
|
||||
return gain * 100.f;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3f SoundSource::getPosition() const
|
||||
{
|
||||
Vector3f position;
|
||||
alCheck(alGetSource3f(m_source, AL_POSITION, &position.x, &position.y, &position.z));
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundSource::isRelativeToListener() const
|
||||
{
|
||||
ALint relative;
|
||||
alCheck(alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative));
|
||||
|
||||
return relative != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float SoundSource::getMinDistance() const
|
||||
{
|
||||
ALfloat distance;
|
||||
alCheck(alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance));
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float SoundSource::getAttenuation() const
|
||||
{
|
||||
ALfloat attenuation;
|
||||
alCheck(alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation));
|
||||
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundSource::Status SoundSource::getStatus() const
|
||||
{
|
||||
ALint status;
|
||||
alCheck(alGetSourcei(m_source, AL_SOURCE_STATE, &status));
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case AL_INITIAL :
|
||||
case AL_STOPPED : return Stopped;
|
||||
case AL_PAUSED : return Paused;
|
||||
case AL_PLAYING : return Playing;
|
||||
}
|
||||
|
||||
return Stopped;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundSource.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundSource::SoundSource()
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
alCheck(alGenSources(1, &m_source));
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundSource::SoundSource(const SoundSource& copy)
|
||||
{
|
||||
priv::ensureALInit();
|
||||
|
||||
alCheck(alGenSources(1, &m_source));
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
|
||||
setPitch(copy.getPitch());
|
||||
setVolume(copy.getVolume());
|
||||
setPosition(copy.getPosition());
|
||||
setRelativeToListener(copy.isRelativeToListener());
|
||||
setMinDistance(copy.getMinDistance());
|
||||
setAttenuation(copy.getAttenuation());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundSource::~SoundSource()
|
||||
{
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
alCheck(alDeleteSources(1, &m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setPitch(float pitch)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_PITCH, pitch));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setVolume(float volume)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_GAIN, volume * 0.01f));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setPosition(float x, float y, float z)
|
||||
{
|
||||
alCheck(alSource3f(m_source, AL_POSITION, x, y, z));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setPosition(const Vector3f& position)
|
||||
{
|
||||
setPosition(position.x, position.y, position.z);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setRelativeToListener(bool relative)
|
||||
{
|
||||
alCheck(alSourcei(m_source, AL_SOURCE_RELATIVE, relative));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setMinDistance(float distance)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_REFERENCE_DISTANCE, distance));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundSource::setAttenuation(float attenuation)
|
||||
{
|
||||
alCheck(alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float SoundSource::getPitch() const
|
||||
{
|
||||
ALfloat pitch;
|
||||
alCheck(alGetSourcef(m_source, AL_PITCH, &pitch));
|
||||
|
||||
return pitch;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float SoundSource::getVolume() const
|
||||
{
|
||||
ALfloat gain;
|
||||
alCheck(alGetSourcef(m_source, AL_GAIN, &gain));
|
||||
|
||||
return gain * 100.f;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector3f SoundSource::getPosition() const
|
||||
{
|
||||
Vector3f position;
|
||||
alCheck(alGetSource3f(m_source, AL_POSITION, &position.x, &position.y, &position.z));
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundSource::isRelativeToListener() const
|
||||
{
|
||||
ALint relative;
|
||||
alCheck(alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative));
|
||||
|
||||
return relative != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float SoundSource::getMinDistance() const
|
||||
{
|
||||
ALfloat distance;
|
||||
alCheck(alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance));
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float SoundSource::getAttenuation() const
|
||||
{
|
||||
ALfloat attenuation;
|
||||
alCheck(alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation));
|
||||
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundSource::Status SoundSource::getStatus() const
|
||||
{
|
||||
ALint status;
|
||||
alCheck(alGetSourcei(m_source, AL_SOURCE_STATE, &status));
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case AL_INITIAL:
|
||||
case AL_STOPPED: return Stopped;
|
||||
case AL_PAUSED: return Paused;
|
||||
case AL_PLAYING: return Playing;
|
||||
}
|
||||
|
||||
return Stopped;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,469 +1,469 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundStream.hpp>
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/System/Sleep.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4355) // 'this' used in base member initializer list
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundStream::SoundStream() :
|
||||
m_thread (&SoundStream::streamData, this),
|
||||
m_threadMutex (),
|
||||
m_threadStartState(Stopped),
|
||||
m_isStreaming (false),
|
||||
m_channelCount (0),
|
||||
m_sampleRate (0),
|
||||
m_format (0),
|
||||
m_loop (false),
|
||||
m_samplesProcessed(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundStream::~SoundStream()
|
||||
{
|
||||
// Stop the sound if it was playing
|
||||
|
||||
// Request the thread to terminate
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
m_isStreaming = false;
|
||||
}
|
||||
|
||||
// Wait for the thread to terminate
|
||||
m_thread.wait();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate)
|
||||
{
|
||||
m_channelCount = channelCount;
|
||||
m_sampleRate = sampleRate;
|
||||
|
||||
// Deduce the format from the number of channels
|
||||
m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
|
||||
|
||||
// Check if the format is valid
|
||||
if (m_format == 0)
|
||||
{
|
||||
m_channelCount = 0;
|
||||
m_sampleRate = 0;
|
||||
err() << "Unsupported number of channels (" << m_channelCount << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::play()
|
||||
{
|
||||
// Check if the sound parameters have been set
|
||||
if (m_format == 0)
|
||||
{
|
||||
err() << "Failed to play audio stream: sound parameters have not been initialized (call initialize() first)" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
bool isStreaming = false;
|
||||
Status threadStartState = Stopped;
|
||||
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
|
||||
isStreaming = m_isStreaming;
|
||||
threadStartState = m_threadStartState;
|
||||
}
|
||||
|
||||
|
||||
if (isStreaming && (threadStartState == Paused))
|
||||
{
|
||||
// If the sound is paused, resume it
|
||||
Lock lock(m_threadMutex);
|
||||
m_threadStartState = Playing;
|
||||
alCheck(alSourcePlay(m_source));
|
||||
return;
|
||||
}
|
||||
else if (isStreaming && (threadStartState == Playing))
|
||||
{
|
||||
// If the sound is playing, stop it and continue as if it was stopped
|
||||
stop();
|
||||
}
|
||||
|
||||
// Move to the beginning
|
||||
onSeek(Time::Zero);
|
||||
|
||||
// Start updating the stream in a separate thread to avoid blocking the application
|
||||
m_samplesProcessed = 0;
|
||||
m_isStreaming = true;
|
||||
m_threadStartState = Playing;
|
||||
m_thread.launch();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::pause()
|
||||
{
|
||||
// Handle pause() being called before the thread has started
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
|
||||
if (!m_isStreaming)
|
||||
return;
|
||||
|
||||
m_threadStartState = Paused;
|
||||
}
|
||||
|
||||
alCheck(alSourcePause(m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::stop()
|
||||
{
|
||||
// Request the thread to terminate
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
m_isStreaming = false;
|
||||
}
|
||||
|
||||
// Wait for the thread to terminate
|
||||
m_thread.wait();
|
||||
|
||||
// Move to the beginning
|
||||
onSeek(Time::Zero);
|
||||
|
||||
// Reset the playing position
|
||||
m_samplesProcessed = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundStream::getChannelCount() const
|
||||
{
|
||||
return m_channelCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundStream::getSampleRate() const
|
||||
{
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundStream::Status SoundStream::getStatus() const
|
||||
{
|
||||
Status status = SoundSource::getStatus();
|
||||
|
||||
// To compensate for the lag between play() and alSourceplay()
|
||||
if (status == Stopped)
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
|
||||
if (m_isStreaming)
|
||||
status = m_threadStartState;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::setPlayingOffset(Time timeOffset)
|
||||
{
|
||||
// Get old playing status
|
||||
Status oldStatus = getStatus();
|
||||
|
||||
// Stop the stream
|
||||
stop();
|
||||
|
||||
// Let the derived class update the current position
|
||||
onSeek(timeOffset);
|
||||
|
||||
// Restart streaming
|
||||
m_samplesProcessed = static_cast<Uint64>(timeOffset.asSeconds() * m_sampleRate * m_channelCount);
|
||||
|
||||
if (oldStatus == Stopped)
|
||||
return;
|
||||
|
||||
m_isStreaming = true;
|
||||
m_threadStartState = oldStatus;
|
||||
m_thread.launch();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time SoundStream::getPlayingOffset() const
|
||||
{
|
||||
if (m_sampleRate && m_channelCount)
|
||||
{
|
||||
ALfloat secs = 0.f;
|
||||
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
|
||||
|
||||
return seconds(secs + static_cast<float>(m_samplesProcessed) / m_sampleRate / m_channelCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Time::Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::setLoop(bool loop)
|
||||
{
|
||||
m_loop = loop;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundStream::getLoop() const
|
||||
{
|
||||
return m_loop;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::streamData()
|
||||
{
|
||||
bool requestStop = false;
|
||||
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
|
||||
// Check if the thread was launched Stopped
|
||||
if (m_threadStartState == Stopped)
|
||||
{
|
||||
m_isStreaming = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the buffers
|
||||
alCheck(alGenBuffers(BufferCount, m_buffers));
|
||||
for (int i = 0; i < BufferCount; ++i)
|
||||
m_endBuffers[i] = false;
|
||||
|
||||
// Fill the queue
|
||||
requestStop = fillQueue();
|
||||
|
||||
// Play the sound
|
||||
alCheck(alSourcePlay(m_source));
|
||||
|
||||
// Check if the thread was launched Paused
|
||||
if (m_threadStartState == Paused)
|
||||
alCheck(alSourcePause(m_source));
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
if (!m_isStreaming)
|
||||
break;
|
||||
}
|
||||
|
||||
// The stream has been interrupted!
|
||||
if (SoundSource::getStatus() == Stopped)
|
||||
{
|
||||
if (!requestStop)
|
||||
{
|
||||
// Just continue
|
||||
alCheck(alSourcePlay(m_source));
|
||||
}
|
||||
else
|
||||
{
|
||||
// End streaming
|
||||
Lock lock(m_threadMutex);
|
||||
m_isStreaming = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the number of buffers that have been processed (ie. ready for reuse)
|
||||
ALint nbProcessed = 0;
|
||||
alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed));
|
||||
|
||||
while (nbProcessed--)
|
||||
{
|
||||
// Pop the first unused buffer from the queue
|
||||
ALuint buffer;
|
||||
alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
|
||||
|
||||
// Find its number
|
||||
unsigned int bufferNum = 0;
|
||||
for (int i = 0; i < BufferCount; ++i)
|
||||
if (m_buffers[i] == buffer)
|
||||
{
|
||||
bufferNum = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// Retrieve its size and add it to the samples count
|
||||
if (m_endBuffers[bufferNum])
|
||||
{
|
||||
// This was the last buffer: reset the sample count
|
||||
m_samplesProcessed = 0;
|
||||
m_endBuffers[bufferNum] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ALint size, bits;
|
||||
alCheck(alGetBufferi(buffer, AL_SIZE, &size));
|
||||
alCheck(alGetBufferi(buffer, AL_BITS, &bits));
|
||||
|
||||
// Bits can be 0 if the format or parameters are corrupt, avoid division by zero
|
||||
if (bits == 0)
|
||||
{
|
||||
err() << "Bits in sound stream are 0: make sure that the audio format is not corrupt "
|
||||
<< "and initialize() has been called correctly" << std::endl;
|
||||
|
||||
// Abort streaming (exit main loop)
|
||||
Lock lock(m_threadMutex);
|
||||
m_isStreaming = false;
|
||||
requestStop = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_samplesProcessed += size / (bits / 8);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill it and push it back into the playing queue
|
||||
if (!requestStop)
|
||||
{
|
||||
if (fillAndPushBuffer(bufferNum))
|
||||
requestStop = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Leave some time for the other threads if the stream is still playing
|
||||
if (SoundSource::getStatus() != Stopped)
|
||||
sleep(milliseconds(10));
|
||||
}
|
||||
|
||||
// Stop the playback
|
||||
alCheck(alSourceStop(m_source));
|
||||
|
||||
// Unqueue any buffer left in the queue
|
||||
clearQueue();
|
||||
|
||||
// Delete the buffers
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
alCheck(alDeleteBuffers(BufferCount, m_buffers));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundStream::fillAndPushBuffer(unsigned int bufferNum)
|
||||
{
|
||||
bool requestStop = false;
|
||||
|
||||
// Acquire audio data
|
||||
Chunk data = {NULL, 0};
|
||||
if (!onGetData(data))
|
||||
{
|
||||
// Mark the buffer as the last one (so that we know when to reset the playing position)
|
||||
m_endBuffers[bufferNum] = true;
|
||||
|
||||
// Check if the stream must loop or stop
|
||||
if (m_loop)
|
||||
{
|
||||
// Return to the beginning of the stream source
|
||||
onSeek(Time::Zero);
|
||||
|
||||
// If we previously had no data, try to fill the buffer once again
|
||||
if (!data.samples || (data.sampleCount == 0))
|
||||
{
|
||||
return fillAndPushBuffer(bufferNum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not looping: request stop
|
||||
requestStop = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the buffer if some data was returned
|
||||
if (data.samples && data.sampleCount)
|
||||
{
|
||||
unsigned int buffer = m_buffers[bufferNum];
|
||||
|
||||
// Fill the buffer
|
||||
ALsizei size = static_cast<ALsizei>(data.sampleCount) * sizeof(Int16);
|
||||
alCheck(alBufferData(buffer, m_format, data.samples, size, m_sampleRate));
|
||||
|
||||
// Push it into the sound queue
|
||||
alCheck(alSourceQueueBuffers(m_source, 1, &buffer));
|
||||
}
|
||||
|
||||
return requestStop;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundStream::fillQueue()
|
||||
{
|
||||
// Fill and enqueue all the available buffers
|
||||
bool requestStop = false;
|
||||
for (int i = 0; (i < BufferCount) && !requestStop; ++i)
|
||||
{
|
||||
if (fillAndPushBuffer(i))
|
||||
requestStop = true;
|
||||
}
|
||||
|
||||
return requestStop;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::clearQueue()
|
||||
{
|
||||
// Get the number of buffers still in the queue
|
||||
ALint nbQueued;
|
||||
alCheck(alGetSourcei(m_source, AL_BUFFERS_QUEUED, &nbQueued));
|
||||
|
||||
// Unqueue them all
|
||||
ALuint buffer;
|
||||
for (ALint i = 0; i < nbQueued; ++i)
|
||||
alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Audio/SoundStream.hpp>
|
||||
#include <SFML/Audio/AudioDevice.hpp>
|
||||
#include <SFML/Audio/ALCheck.hpp>
|
||||
#include <SFML/System/Sleep.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4355) // 'this' used in base member initializer list
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundStream::SoundStream() :
|
||||
m_thread (&SoundStream::streamData, this),
|
||||
m_threadMutex (),
|
||||
m_threadStartState(Stopped),
|
||||
m_isStreaming (false),
|
||||
m_channelCount (0),
|
||||
m_sampleRate (0),
|
||||
m_format (0),
|
||||
m_loop (false),
|
||||
m_samplesProcessed(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundStream::~SoundStream()
|
||||
{
|
||||
// Stop the sound if it was playing
|
||||
|
||||
// Request the thread to terminate
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
m_isStreaming = false;
|
||||
}
|
||||
|
||||
// Wait for the thread to terminate
|
||||
m_thread.wait();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate)
|
||||
{
|
||||
m_channelCount = channelCount;
|
||||
m_sampleRate = sampleRate;
|
||||
|
||||
// Deduce the format from the number of channels
|
||||
m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
|
||||
|
||||
// Check if the format is valid
|
||||
if (m_format == 0)
|
||||
{
|
||||
m_channelCount = 0;
|
||||
m_sampleRate = 0;
|
||||
err() << "Unsupported number of channels (" << m_channelCount << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::play()
|
||||
{
|
||||
// Check if the sound parameters have been set
|
||||
if (m_format == 0)
|
||||
{
|
||||
err() << "Failed to play audio stream: sound parameters have not been initialized (call initialize() first)" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
bool isStreaming = false;
|
||||
Status threadStartState = Stopped;
|
||||
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
|
||||
isStreaming = m_isStreaming;
|
||||
threadStartState = m_threadStartState;
|
||||
}
|
||||
|
||||
|
||||
if (isStreaming && (threadStartState == Paused))
|
||||
{
|
||||
// If the sound is paused, resume it
|
||||
Lock lock(m_threadMutex);
|
||||
m_threadStartState = Playing;
|
||||
alCheck(alSourcePlay(m_source));
|
||||
return;
|
||||
}
|
||||
else if (isStreaming && (threadStartState == Playing))
|
||||
{
|
||||
// If the sound is playing, stop it and continue as if it was stopped
|
||||
stop();
|
||||
}
|
||||
|
||||
// Move to the beginning
|
||||
onSeek(Time::Zero);
|
||||
|
||||
// Start updating the stream in a separate thread to avoid blocking the application
|
||||
m_samplesProcessed = 0;
|
||||
m_isStreaming = true;
|
||||
m_threadStartState = Playing;
|
||||
m_thread.launch();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::pause()
|
||||
{
|
||||
// Handle pause() being called before the thread has started
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
|
||||
if (!m_isStreaming)
|
||||
return;
|
||||
|
||||
m_threadStartState = Paused;
|
||||
}
|
||||
|
||||
alCheck(alSourcePause(m_source));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::stop()
|
||||
{
|
||||
// Request the thread to terminate
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
m_isStreaming = false;
|
||||
}
|
||||
|
||||
// Wait for the thread to terminate
|
||||
m_thread.wait();
|
||||
|
||||
// Move to the beginning
|
||||
onSeek(Time::Zero);
|
||||
|
||||
// Reset the playing position
|
||||
m_samplesProcessed = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundStream::getChannelCount() const
|
||||
{
|
||||
return m_channelCount;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SoundStream::getSampleRate() const
|
||||
{
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SoundStream::Status SoundStream::getStatus() const
|
||||
{
|
||||
Status status = SoundSource::getStatus();
|
||||
|
||||
// To compensate for the lag between play() and alSourceplay()
|
||||
if (status == Stopped)
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
|
||||
if (m_isStreaming)
|
||||
status = m_threadStartState;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::setPlayingOffset(Time timeOffset)
|
||||
{
|
||||
// Get old playing status
|
||||
Status oldStatus = getStatus();
|
||||
|
||||
// Stop the stream
|
||||
stop();
|
||||
|
||||
// Let the derived class update the current position
|
||||
onSeek(timeOffset);
|
||||
|
||||
// Restart streaming
|
||||
m_samplesProcessed = static_cast<Uint64>(timeOffset.asSeconds() * m_sampleRate * m_channelCount);
|
||||
|
||||
if (oldStatus == Stopped)
|
||||
return;
|
||||
|
||||
m_isStreaming = true;
|
||||
m_threadStartState = oldStatus;
|
||||
m_thread.launch();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time SoundStream::getPlayingOffset() const
|
||||
{
|
||||
if (m_sampleRate && m_channelCount)
|
||||
{
|
||||
ALfloat secs = 0.f;
|
||||
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
|
||||
|
||||
return seconds(secs + static_cast<float>(m_samplesProcessed) / m_sampleRate / m_channelCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Time::Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::setLoop(bool loop)
|
||||
{
|
||||
m_loop = loop;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundStream::getLoop() const
|
||||
{
|
||||
return m_loop;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::streamData()
|
||||
{
|
||||
bool requestStop = false;
|
||||
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
|
||||
// Check if the thread was launched Stopped
|
||||
if (m_threadStartState == Stopped)
|
||||
{
|
||||
m_isStreaming = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the buffers
|
||||
alCheck(alGenBuffers(BufferCount, m_buffers));
|
||||
for (int i = 0; i < BufferCount; ++i)
|
||||
m_endBuffers[i] = false;
|
||||
|
||||
// Fill the queue
|
||||
requestStop = fillQueue();
|
||||
|
||||
// Play the sound
|
||||
alCheck(alSourcePlay(m_source));
|
||||
|
||||
// Check if the thread was launched Paused
|
||||
if (m_threadStartState == Paused)
|
||||
alCheck(alSourcePause(m_source));
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
{
|
||||
Lock lock(m_threadMutex);
|
||||
if (!m_isStreaming)
|
||||
break;
|
||||
}
|
||||
|
||||
// The stream has been interrupted!
|
||||
if (SoundSource::getStatus() == Stopped)
|
||||
{
|
||||
if (!requestStop)
|
||||
{
|
||||
// Just continue
|
||||
alCheck(alSourcePlay(m_source));
|
||||
}
|
||||
else
|
||||
{
|
||||
// End streaming
|
||||
Lock lock(m_threadMutex);
|
||||
m_isStreaming = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the number of buffers that have been processed (ie. ready for reuse)
|
||||
ALint nbProcessed = 0;
|
||||
alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed));
|
||||
|
||||
while (nbProcessed--)
|
||||
{
|
||||
// Pop the first unused buffer from the queue
|
||||
ALuint buffer;
|
||||
alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
|
||||
|
||||
// Find its number
|
||||
unsigned int bufferNum = 0;
|
||||
for (int i = 0; i < BufferCount; ++i)
|
||||
if (m_buffers[i] == buffer)
|
||||
{
|
||||
bufferNum = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// Retrieve its size and add it to the samples count
|
||||
if (m_endBuffers[bufferNum])
|
||||
{
|
||||
// This was the last buffer: reset the sample count
|
||||
m_samplesProcessed = 0;
|
||||
m_endBuffers[bufferNum] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ALint size, bits;
|
||||
alCheck(alGetBufferi(buffer, AL_SIZE, &size));
|
||||
alCheck(alGetBufferi(buffer, AL_BITS, &bits));
|
||||
|
||||
// Bits can be 0 if the format or parameters are corrupt, avoid division by zero
|
||||
if (bits == 0)
|
||||
{
|
||||
err() << "Bits in sound stream are 0: make sure that the audio format is not corrupt "
|
||||
<< "and initialize() has been called correctly" << std::endl;
|
||||
|
||||
// Abort streaming (exit main loop)
|
||||
Lock lock(m_threadMutex);
|
||||
m_isStreaming = false;
|
||||
requestStop = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_samplesProcessed += size / (bits / 8);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill it and push it back into the playing queue
|
||||
if (!requestStop)
|
||||
{
|
||||
if (fillAndPushBuffer(bufferNum))
|
||||
requestStop = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Leave some time for the other threads if the stream is still playing
|
||||
if (SoundSource::getStatus() != Stopped)
|
||||
sleep(milliseconds(10));
|
||||
}
|
||||
|
||||
// Stop the playback
|
||||
alCheck(alSourceStop(m_source));
|
||||
|
||||
// Unqueue any buffer left in the queue
|
||||
clearQueue();
|
||||
|
||||
// Delete the buffers
|
||||
alCheck(alSourcei(m_source, AL_BUFFER, 0));
|
||||
alCheck(alDeleteBuffers(BufferCount, m_buffers));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundStream::fillAndPushBuffer(unsigned int bufferNum)
|
||||
{
|
||||
bool requestStop = false;
|
||||
|
||||
// Acquire audio data
|
||||
Chunk data = {NULL, 0};
|
||||
if (!onGetData(data))
|
||||
{
|
||||
// Mark the buffer as the last one (so that we know when to reset the playing position)
|
||||
m_endBuffers[bufferNum] = true;
|
||||
|
||||
// Check if the stream must loop or stop
|
||||
if (m_loop)
|
||||
{
|
||||
// Return to the beginning of the stream source
|
||||
onSeek(Time::Zero);
|
||||
|
||||
// If we previously had no data, try to fill the buffer once again
|
||||
if (!data.samples || (data.sampleCount == 0))
|
||||
{
|
||||
return fillAndPushBuffer(bufferNum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not looping: request stop
|
||||
requestStop = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the buffer if some data was returned
|
||||
if (data.samples && data.sampleCount)
|
||||
{
|
||||
unsigned int buffer = m_buffers[bufferNum];
|
||||
|
||||
// Fill the buffer
|
||||
ALsizei size = static_cast<ALsizei>(data.sampleCount) * sizeof(Int16);
|
||||
alCheck(alBufferData(buffer, m_format, data.samples, size, m_sampleRate));
|
||||
|
||||
// Push it into the sound queue
|
||||
alCheck(alSourceQueueBuffers(m_source, 1, &buffer));
|
||||
}
|
||||
|
||||
return requestStop;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SoundStream::fillQueue()
|
||||
{
|
||||
// Fill and enqueue all the available buffers
|
||||
bool requestStop = false;
|
||||
for (int i = 0; (i < BufferCount) && !requestStop; ++i)
|
||||
{
|
||||
if (fillAndPushBuffer(i))
|
||||
requestStop = true;
|
||||
}
|
||||
|
||||
return requestStop;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SoundStream::clearQueue()
|
||||
{
|
||||
// Get the number of buffers still in the queue
|
||||
ALint nbQueued;
|
||||
alCheck(alGetSourcei(m_source, AL_BUFFERS_QUEUED, &nbQueued));
|
||||
|
||||
// Unqueue them all
|
||||
ALuint buffer;
|
||||
for (ALint i = 0; i < nbQueued; ++i)
|
||||
alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
|
||||
# include the SFML specific macros
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/Macros.cmake)
|
||||
|
||||
# let CMake know about our additional libraries paths
|
||||
# include the SFML specific macros
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/Macros.cmake)
|
||||
|
||||
# let CMake know about our additional libraries paths
|
||||
if (SFML_OS_WINDOWS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
|
||||
if(SFML_COMPILER_GCC)
|
||||
if(ARCH_32BITS)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x86")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x86")
|
||||
elseif(ARCH_64BITS)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x64")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x64")
|
||||
endif()
|
||||
elseif(SFML_COMPILER_MSVC)
|
||||
if(ARCH_32BITS)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x86")
|
||||
elseif(ARCH_64BITS)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x64")
|
||||
endif()
|
||||
endif()
|
||||
elseif(SFML_OS_MACOSX)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/lib/")
|
||||
elseif(SFML_OS_IOS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-ios/")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-android/${ANDROID_ABI}")
|
||||
endif()
|
||||
|
||||
# add the SFML sources path
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||
|
||||
# define the path of our additional CMake modules
|
||||
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/")
|
||||
|
||||
# set the output directory for SFML libraries
|
||||
set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib")
|
||||
|
||||
# add the modules subdirectories
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
|
||||
if(SFML_COMPILER_GCC)
|
||||
if(ARCH_32BITS)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x86")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x86")
|
||||
elseif(ARCH_64BITS)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x64")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x64")
|
||||
endif()
|
||||
elseif(SFML_COMPILER_MSVC)
|
||||
if(ARCH_32BITS)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x86")
|
||||
elseif(ARCH_64BITS)
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x64")
|
||||
endif()
|
||||
endif()
|
||||
elseif(SFML_OS_MACOSX)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/lib/")
|
||||
elseif(SFML_OS_IOS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-ios/")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-android/${ANDROID_ABI}")
|
||||
endif()
|
||||
|
||||
# add the SFML sources path
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||
|
||||
# define the path of our additional CMake modules
|
||||
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/")
|
||||
|
||||
# set the output directory for SFML libraries
|
||||
set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib")
|
||||
|
||||
# add the modules subdirectories
|
||||
add_subdirectory(System)
|
||||
if(SFML_OS_WINDOWS OR SFML_OS_ANDROID OR SFML_OS_IOS)
|
||||
add_subdirectory(Main)
|
||||
endif()
|
||||
add_subdirectory(Window)
|
||||
if(SFML_OS_WINDOWS OR SFML_OS_ANDROID OR SFML_OS_IOS)
|
||||
add_subdirectory(Main)
|
||||
endif()
|
||||
add_subdirectory(Window)
|
||||
add_subdirectory(Network)
|
||||
add_subdirectory(Graphics)
|
||||
if(NOT SFML_OS_IOS)
|
||||
add_subdirectory(Audio)
|
||||
endif()
|
||||
add_subdirectory(Audio)
|
||||
endif()
|
||||
|
|
|
@ -1,168 +1,168 @@
|
|||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Graphics)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Graphics)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${SRCROOT}/BlendMode.cpp
|
||||
${INCROOT}/BlendMode.hpp
|
||||
${SRCROOT}/Color.cpp
|
||||
${INCROOT}/Color.hpp
|
||||
${INCROOT}/Export.hpp
|
||||
${SRCROOT}/Font.cpp
|
||||
${INCROOT}/Font.hpp
|
||||
${INCROOT}/Glyph.hpp
|
||||
${SRCROOT}/GLCheck.cpp
|
||||
${SRCROOT}/GLCheck.hpp
|
||||
${SRCROOT}/GLExtensions.hpp
|
||||
${SRCROOT}/GLExtensions.cpp
|
||||
${SRCROOT}/Image.cpp
|
||||
${INCROOT}/Image.hpp
|
||||
${SRCROOT}/ImageLoader.cpp
|
||||
${SRCROOT}/ImageLoader.hpp
|
||||
${INCROOT}/PrimitiveType.hpp
|
||||
${INCROOT}/Rect.hpp
|
||||
${INCROOT}/Rect.inl
|
||||
${SRCROOT}/RenderStates.cpp
|
||||
${INCROOT}/RenderStates.hpp
|
||||
${SRCROOT}/RenderTexture.cpp
|
||||
${INCROOT}/RenderTexture.hpp
|
||||
${SRCROOT}/RenderTarget.cpp
|
||||
${INCROOT}/RenderTarget.hpp
|
||||
${SRCROOT}/RenderWindow.cpp
|
||||
${INCROOT}/RenderWindow.hpp
|
||||
${SRCROOT}/Shader.cpp
|
||||
${INCROOT}/Shader.hpp
|
||||
${SRCROOT}/Texture.cpp
|
||||
${INCROOT}/Texture.hpp
|
||||
${SRCROOT}/TextureSaver.cpp
|
||||
${SRCROOT}/TextureSaver.hpp
|
||||
${SRCROOT}/Transform.cpp
|
||||
${INCROOT}/Transform.hpp
|
||||
${SRCROOT}/Transformable.cpp
|
||||
${INCROOT}/Transformable.hpp
|
||||
${SRCROOT}/View.cpp
|
||||
${INCROOT}/View.hpp
|
||||
${SRCROOT}/Vertex.cpp
|
||||
${INCROOT}/Vertex.hpp
|
||||
)
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# drawables sources
|
||||
set(DRAWABLES_SRC
|
||||
${INCROOT}/Drawable.hpp
|
||||
${SRCROOT}/Shape.cpp
|
||||
${INCROOT}/Shape.hpp
|
||||
${SRCROOT}/CircleShape.cpp
|
||||
${INCROOT}/CircleShape.hpp
|
||||
${SRCROOT}/RectangleShape.cpp
|
||||
${INCROOT}/RectangleShape.hpp
|
||||
${SRCROOT}/ConvexShape.cpp
|
||||
${INCROOT}/ConvexShape.hpp
|
||||
${SRCROOT}/Sprite.cpp
|
||||
${INCROOT}/Sprite.hpp
|
||||
${SRCROOT}/Text.cpp
|
||||
${INCROOT}/Text.hpp
|
||||
${SRCROOT}/VertexArray.cpp
|
||||
${INCROOT}/VertexArray.hpp
|
||||
)
|
||||
source_group("drawables" FILES ${DRAWABLES_SRC})
|
||||
|
||||
# render-texture sources
|
||||
set(RENDER_TEXTURE_SRC
|
||||
${SRCROOT}/RenderTextureImpl.cpp
|
||||
${SRCROOT}/RenderTextureImpl.hpp
|
||||
${SRCROOT}/RenderTextureImplFBO.cpp
|
||||
${SRCROOT}/RenderTextureImplFBO.hpp
|
||||
${SRCROOT}/RenderTextureImplDefault.cpp
|
||||
${SRCROOT}/RenderTextureImplDefault.hpp
|
||||
)
|
||||
source_group("render texture" FILES ${RENDER_TEXTURE_SRC})
|
||||
|
||||
# stb_image sources
|
||||
set(STB_SRC
|
||||
${SRCROOT}/stb_image/stb_image.h
|
||||
${SRCROOT}/stb_image/stb_image_write.h
|
||||
)
|
||||
source_group("stb_image" FILES ${STB_SRC})
|
||||
|
||||
# let CMake know about our additional graphics libraries paths (on Windows and OSX)
|
||||
if(SFML_OS_WINDOWS OR SFML_OS_MACOSX)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Graphics)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Graphics)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${SRCROOT}/BlendMode.cpp
|
||||
${INCROOT}/BlendMode.hpp
|
||||
${SRCROOT}/Color.cpp
|
||||
${INCROOT}/Color.hpp
|
||||
${INCROOT}/Export.hpp
|
||||
${SRCROOT}/Font.cpp
|
||||
${INCROOT}/Font.hpp
|
||||
${INCROOT}/Glyph.hpp
|
||||
${SRCROOT}/GLCheck.cpp
|
||||
${SRCROOT}/GLCheck.hpp
|
||||
${SRCROOT}/GLExtensions.hpp
|
||||
${SRCROOT}/GLExtensions.cpp
|
||||
${SRCROOT}/Image.cpp
|
||||
${INCROOT}/Image.hpp
|
||||
${SRCROOT}/ImageLoader.cpp
|
||||
${SRCROOT}/ImageLoader.hpp
|
||||
${INCROOT}/PrimitiveType.hpp
|
||||
${INCROOT}/Rect.hpp
|
||||
${INCROOT}/Rect.inl
|
||||
${SRCROOT}/RenderStates.cpp
|
||||
${INCROOT}/RenderStates.hpp
|
||||
${SRCROOT}/RenderTexture.cpp
|
||||
${INCROOT}/RenderTexture.hpp
|
||||
${SRCROOT}/RenderTarget.cpp
|
||||
${INCROOT}/RenderTarget.hpp
|
||||
${SRCROOT}/RenderWindow.cpp
|
||||
${INCROOT}/RenderWindow.hpp
|
||||
${SRCROOT}/Shader.cpp
|
||||
${INCROOT}/Shader.hpp
|
||||
${SRCROOT}/Texture.cpp
|
||||
${INCROOT}/Texture.hpp
|
||||
${SRCROOT}/TextureSaver.cpp
|
||||
${SRCROOT}/TextureSaver.hpp
|
||||
${SRCROOT}/Transform.cpp
|
||||
${INCROOT}/Transform.hpp
|
||||
${SRCROOT}/Transformable.cpp
|
||||
${INCROOT}/Transformable.hpp
|
||||
${SRCROOT}/View.cpp
|
||||
${INCROOT}/View.hpp
|
||||
${SRCROOT}/Vertex.cpp
|
||||
${INCROOT}/Vertex.hpp
|
||||
)
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# drawables sources
|
||||
set(DRAWABLES_SRC
|
||||
${INCROOT}/Drawable.hpp
|
||||
${SRCROOT}/Shape.cpp
|
||||
${INCROOT}/Shape.hpp
|
||||
${SRCROOT}/CircleShape.cpp
|
||||
${INCROOT}/CircleShape.hpp
|
||||
${SRCROOT}/RectangleShape.cpp
|
||||
${INCROOT}/RectangleShape.hpp
|
||||
${SRCROOT}/ConvexShape.cpp
|
||||
${INCROOT}/ConvexShape.hpp
|
||||
${SRCROOT}/Sprite.cpp
|
||||
${INCROOT}/Sprite.hpp
|
||||
${SRCROOT}/Text.cpp
|
||||
${INCROOT}/Text.hpp
|
||||
${SRCROOT}/VertexArray.cpp
|
||||
${INCROOT}/VertexArray.hpp
|
||||
)
|
||||
source_group("drawables" FILES ${DRAWABLES_SRC})
|
||||
|
||||
# render-texture sources
|
||||
set(RENDER_TEXTURE_SRC
|
||||
${SRCROOT}/RenderTextureImpl.cpp
|
||||
${SRCROOT}/RenderTextureImpl.hpp
|
||||
${SRCROOT}/RenderTextureImplFBO.cpp
|
||||
${SRCROOT}/RenderTextureImplFBO.hpp
|
||||
${SRCROOT}/RenderTextureImplDefault.cpp
|
||||
${SRCROOT}/RenderTextureImplDefault.hpp
|
||||
)
|
||||
source_group("render texture" FILES ${RENDER_TEXTURE_SRC})
|
||||
|
||||
# stb_image sources
|
||||
set(STB_SRC
|
||||
${SRCROOT}/stb_image/stb_image.h
|
||||
${SRCROOT}/stb_image/stb_image_write.h
|
||||
)
|
||||
source_group("stb_image" FILES ${STB_SRC})
|
||||
|
||||
# let CMake know about our additional graphics libraries paths (on Windows and OSX)
|
||||
if(SFML_OS_WINDOWS OR SFML_OS_MACOSX)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
|
||||
endif()
|
||||
|
||||
# let CMake know about our additional graphics libraries paths
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows/freetype")
|
||||
# let CMake know about our additional graphics libraries paths
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows/freetype")
|
||||
elseif(SFML_OS_MACOSX)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx/freetype2")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
|
||||
elseif(SFML_OS_IOS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios/freetype2")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android/freetype")
|
||||
endif()
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx/freetype2")
|
||||
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
|
||||
elseif(SFML_OS_IOS)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios/freetype2")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android")
|
||||
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android/freetype")
|
||||
endif()
|
||||
|
||||
# find external libraries
|
||||
if(NOT SFML_OPENGL_ES)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(GLEW REQUIRED)
|
||||
if(SFML_OS_LINUX)
|
||||
find_package(X11 REQUIRED)
|
||||
endif()
|
||||
include_directories(${FREETYPE_INCLUDE_DIRS} ${GLEW_INCLUDE_PATH} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR})
|
||||
endif()
|
||||
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
|
||||
find_package(EGL REQUIRED)
|
||||
find_package(GLES REQUIRED)
|
||||
include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
|
||||
endif()
|
||||
if(SFML_OS_ANDROID)
|
||||
find_host_package(JPEG REQUIRED)
|
||||
find_host_package(Freetype REQUIRED)
|
||||
else()
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(Freetype REQUIRED)
|
||||
endif()
|
||||
include_directories(${FREETYPE_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR})
|
||||
|
||||
# build the list of external libraries to link
|
||||
if(NOT SFML_OPENGL_ES)
|
||||
list(APPEND GRAPHICS_EXT_LIBS ${GLEW_LIBRARY} ${OPENGL_gl_LIBRARY})
|
||||
if(SFML_OS_LINUX)
|
||||
list(APPEND GRAPHICS_EXT_LIBS ${X11_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
|
||||
list(APPEND GRAPHICS_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
|
||||
endif()
|
||||
# find external libraries
|
||||
if(NOT SFML_OPENGL_ES)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(GLEW REQUIRED)
|
||||
if(SFML_OS_LINUX)
|
||||
find_package(X11 REQUIRED)
|
||||
endif()
|
||||
include_directories(${FREETYPE_INCLUDE_DIRS} ${GLEW_INCLUDE_PATH} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR})
|
||||
endif()
|
||||
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
|
||||
find_package(EGL REQUIRED)
|
||||
find_package(GLES REQUIRED)
|
||||
include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
|
||||
endif()
|
||||
if(SFML_OS_ANDROID)
|
||||
find_host_package(JPEG REQUIRED)
|
||||
find_host_package(Freetype REQUIRED)
|
||||
else()
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(Freetype REQUIRED)
|
||||
endif()
|
||||
include_directories(${FREETYPE_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR})
|
||||
|
||||
# build the list of external libraries to link
|
||||
if(NOT SFML_OPENGL_ES)
|
||||
list(APPEND GRAPHICS_EXT_LIBS ${GLEW_LIBRARY} ${OPENGL_gl_LIBRARY})
|
||||
if(SFML_OS_LINUX)
|
||||
list(APPEND GRAPHICS_EXT_LIBS ${X11_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
|
||||
list(APPEND GRAPHICS_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
|
||||
endif()
|
||||
if(SFML_OS_IOS)
|
||||
list(APPEND GRAPHICS_EXT_LIBS "-framework OpenGLES")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
list(APPEND GRAPHICS_EXT_LIBS "-framework OpenGLES")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
list(APPEND GRAPHICS_EXT_LIBS -lz)
|
||||
endif()
|
||||
list(APPEND GRAPHICS_EXT_LIBS ${FREETYPE_LIBRARY} ${JPEG_LIBRARY})
|
||||
|
||||
# add preprocessor symbols
|
||||
if(NOT SFML_OPENGL_ES)
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
endif()
|
||||
add_definitions(-DSTBI_FAILURE_USERMSG)
|
||||
|
||||
# ImageLoader.cpp must be compiled with the -fno-strict-aliasing
|
||||
# when gcc is used; otherwise saving PNGs may crash in stb_image_write
|
||||
if(SFML_COMPILER_GCC)
|
||||
set_source_files_properties(${SRCROOT}/ImageLoader.cpp PROPERTIES COMPILE_FLAGS -fno-strict-aliasing)
|
||||
endif()
|
||||
|
||||
# define the sfml-graphics target
|
||||
sfml_add_library(sfml-graphics
|
||||
SOURCES ${SRC} ${DRAWABLES_SRC} ${RENDER_TEXTURE_SRC} ${STB_SRC}
|
||||
DEPENDS sfml-window sfml-system
|
||||
EXTERNAL_LIBS ${GRAPHICS_EXT_LIBS})
|
||||
endif()
|
||||
list(APPEND GRAPHICS_EXT_LIBS ${FREETYPE_LIBRARY} ${JPEG_LIBRARY})
|
||||
|
||||
# add preprocessor symbols
|
||||
if(NOT SFML_OPENGL_ES)
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
endif()
|
||||
add_definitions(-DSTBI_FAILURE_USERMSG)
|
||||
|
||||
# ImageLoader.cpp must be compiled with the -fno-strict-aliasing
|
||||
# when gcc is used; otherwise saving PNGs may crash in stb_image_write
|
||||
if(SFML_COMPILER_GCC)
|
||||
set_source_files_properties(${SRCROOT}/ImageLoader.cpp PROPERTIES COMPILE_FLAGS -fno-strict-aliasing)
|
||||
endif()
|
||||
|
||||
# define the sfml-graphics target
|
||||
sfml_add_library(sfml-graphics
|
||||
SOURCES ${SRC} ${DRAWABLES_SRC} ${RENDER_TEXTURE_SRC} ${STB_SRC}
|
||||
DEPENDS sfml-window sfml-system
|
||||
EXTERNAL_LIBS ${GRAPHICS_EXT_LIBS})
|
||||
|
|
|
@ -1,137 +1,137 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Color.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// Static member data
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color Color::Black(0, 0, 0);
|
||||
const Color Color::White(255, 255, 255);
|
||||
const Color Color::Red(255, 0, 0);
|
||||
const Color Color::Green(0, 255, 0);
|
||||
const Color Color::Blue(0, 0, 255);
|
||||
const Color Color::Yellow(255, 255, 0);
|
||||
const Color Color::Magenta(255, 0, 255);
|
||||
const Color Color::Cyan(0, 255, 255);
|
||||
const Color Color::Transparent(0, 0, 0, 0);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color::Color() :
|
||||
r(0),
|
||||
g(0),
|
||||
b(0),
|
||||
a(255)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color::Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha) :
|
||||
r(red),
|
||||
g(green),
|
||||
b(blue),
|
||||
a(alpha)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const Color& left, const Color& right)
|
||||
{
|
||||
return (left.r == right.r) &&
|
||||
(left.g == right.g) &&
|
||||
(left.b == right.b) &&
|
||||
(left.a == right.a);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(const Color& left, const Color& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color operator +(const Color& left, const Color& right)
|
||||
{
|
||||
return Color(Uint8(std::min(int(left.r) + right.r, 255)),
|
||||
Uint8(std::min(int(left.g) + right.g, 255)),
|
||||
Uint8(std::min(int(left.b) + right.b, 255)),
|
||||
Uint8(std::min(int(left.a) + right.a, 255)));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color operator -(const Color& left, const Color& right)
|
||||
{
|
||||
return Color(Uint8(std::max(int(left.r) - right.r, 0)),
|
||||
Uint8(std::max(int(left.g) - right.g, 0)),
|
||||
Uint8(std::max(int(left.b) - right.b, 0)),
|
||||
Uint8(std::max(int(left.a) - right.a, 0)));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color operator *(const Color& left, const Color& right)
|
||||
{
|
||||
return Color(Uint8(int(left.r) * right.r / 255),
|
||||
Uint8(int(left.g) * right.g / 255),
|
||||
Uint8(int(left.b) * right.b / 255),
|
||||
Uint8(int(left.a) * right.a / 255));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color& operator +=(Color& left, const Color& right)
|
||||
{
|
||||
return left = left + right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color& operator -=(Color& left, const Color& right)
|
||||
{
|
||||
return left = left - right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color& operator *=(Color& left, const Color& right)
|
||||
{
|
||||
return left = left * right;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Color.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// Static member data
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color Color::Black(0, 0, 0);
|
||||
const Color Color::White(255, 255, 255);
|
||||
const Color Color::Red(255, 0, 0);
|
||||
const Color Color::Green(0, 255, 0);
|
||||
const Color Color::Blue(0, 0, 255);
|
||||
const Color Color::Yellow(255, 255, 0);
|
||||
const Color Color::Magenta(255, 0, 255);
|
||||
const Color Color::Cyan(0, 255, 255);
|
||||
const Color Color::Transparent(0, 0, 0, 0);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color::Color() :
|
||||
r(0),
|
||||
g(0),
|
||||
b(0),
|
||||
a(255)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color::Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha) :
|
||||
r(red),
|
||||
g(green),
|
||||
b(blue),
|
||||
a(alpha)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const Color& left, const Color& right)
|
||||
{
|
||||
return (left.r == right.r) &&
|
||||
(left.g == right.g) &&
|
||||
(left.b == right.b) &&
|
||||
(left.a == right.a);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(const Color& left, const Color& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color operator +(const Color& left, const Color& right)
|
||||
{
|
||||
return Color(Uint8(std::min(int(left.r) + right.r, 255)),
|
||||
Uint8(std::min(int(left.g) + right.g, 255)),
|
||||
Uint8(std::min(int(left.b) + right.b, 255)),
|
||||
Uint8(std::min(int(left.a) + right.a, 255)));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color operator -(const Color& left, const Color& right)
|
||||
{
|
||||
return Color(Uint8(std::max(int(left.r) - right.r, 0)),
|
||||
Uint8(std::max(int(left.g) - right.g, 0)),
|
||||
Uint8(std::max(int(left.b) - right.b, 0)),
|
||||
Uint8(std::max(int(left.a) - right.a, 0)));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color operator *(const Color& left, const Color& right)
|
||||
{
|
||||
return Color(Uint8(int(left.r) * right.r / 255),
|
||||
Uint8(int(left.g) * right.g / 255),
|
||||
Uint8(int(left.b) * right.b / 255),
|
||||
Uint8(int(left.a) * right.a / 255));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color& operator +=(Color& left, const Color& right)
|
||||
{
|
||||
return left = left + right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color& operator -=(Color& left, const Color& right)
|
||||
{
|
||||
return left = left - right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color& operator *=(Color& left, const Color& right)
|
||||
{
|
||||
return left = left * right;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,112 +1,112 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void glCheckError(const char* file, unsigned int line)
|
||||
{
|
||||
// Get the last error
|
||||
GLenum errorCode = glGetError();
|
||||
|
||||
if (errorCode != GL_NO_ERROR)
|
||||
{
|
||||
std::string fileString(file);
|
||||
std::string error = "unknown error";
|
||||
std::string description = "no description";
|
||||
|
||||
// Decode the error code
|
||||
switch (errorCode)
|
||||
{
|
||||
case GL_INVALID_ENUM :
|
||||
{
|
||||
error = "GL_INVALID_ENUM";
|
||||
description = "an unacceptable value has been specified for an enumerated argument";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_INVALID_VALUE :
|
||||
{
|
||||
error = "GL_INVALID_VALUE";
|
||||
description = "a numeric argument is out of range";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_INVALID_OPERATION :
|
||||
{
|
||||
error = "GL_INVALID_OPERATION";
|
||||
description = "the specified operation is not allowed in the current state";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_STACK_OVERFLOW :
|
||||
{
|
||||
error = "GL_STACK_OVERFLOW";
|
||||
description = "this command would cause a stack overflow";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_STACK_UNDERFLOW :
|
||||
{
|
||||
error = "GL_STACK_UNDERFLOW";
|
||||
description = "this command would cause a stack underflow";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_OUT_OF_MEMORY :
|
||||
{
|
||||
error = "GL_OUT_OF_MEMORY";
|
||||
description = "there is not enough memory left to execute the command";
|
||||
break;
|
||||
}
|
||||
|
||||
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION :
|
||||
{
|
||||
error = "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||
description = "the object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\"";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Log the error
|
||||
err() << "An internal OpenGL call failed in "
|
||||
<< fileString.substr(fileString.find_last_of("\\/") + 1) << " (" << line << ") : "
|
||||
<< error << ", " << description
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void glCheckError(const char* file, unsigned int line)
|
||||
{
|
||||
// Get the last error
|
||||
GLenum errorCode = glGetError();
|
||||
|
||||
if (errorCode != GL_NO_ERROR)
|
||||
{
|
||||
std::string fileString(file);
|
||||
std::string error = "unknown error";
|
||||
std::string description = "no description";
|
||||
|
||||
// Decode the error code
|
||||
switch (errorCode)
|
||||
{
|
||||
case GL_INVALID_ENUM:
|
||||
{
|
||||
error = "GL_INVALID_ENUM";
|
||||
description = "an unacceptable value has been specified for an enumerated argument";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
{
|
||||
error = "GL_INVALID_VALUE";
|
||||
description = "a numeric argument is out of range";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
{
|
||||
error = "GL_INVALID_OPERATION";
|
||||
description = "the specified operation is not allowed in the current state";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_STACK_OVERFLOW:
|
||||
{
|
||||
error = "GL_STACK_OVERFLOW";
|
||||
description = "this command would cause a stack overflow";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_STACK_UNDERFLOW:
|
||||
{
|
||||
error = "GL_STACK_UNDERFLOW";
|
||||
description = "this command would cause a stack underflow";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
{
|
||||
error = "GL_OUT_OF_MEMORY";
|
||||
description = "there is not enough memory left to execute the command";
|
||||
break;
|
||||
}
|
||||
|
||||
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
{
|
||||
error = "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||
description = "the object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\"";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Log the error
|
||||
err() << "An internal OpenGL call failed in "
|
||||
<< fileString.substr(fileString.find_last_of("\\/") + 1) << " (" << line << ") : "
|
||||
<< error << ", " << description
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,69 +1,69 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_GLCHECK_HPP
|
||||
#define SFML_GLCHECK_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/Graphics/GLExtensions.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Let's define a macro to quickly check every OpenGL API calls
|
||||
////////////////////////////////////////////////////////////
|
||||
#ifdef SFML_DEBUG
|
||||
|
||||
// In debug mode, perform a test on every OpenGL call
|
||||
#define glCheck(x) x; sf::priv::glCheckError(__FILE__, __LINE__);
|
||||
|
||||
#else
|
||||
|
||||
// Else, we don't add any overhead
|
||||
#define glCheck(call) (call)
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check the last OpenGL error
|
||||
///
|
||||
/// \param file Source file where the call is located
|
||||
/// \param line Line number of the source file where the call is located
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void glCheckError(const char* file, unsigned int line);
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GLCHECK_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_GLCHECK_HPP
|
||||
#define SFML_GLCHECK_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/Graphics/GLExtensions.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Let's define a macro to quickly check every OpenGL API calls
|
||||
////////////////////////////////////////////////////////////
|
||||
#ifdef SFML_DEBUG
|
||||
|
||||
// In debug mode, perform a test on every OpenGL call
|
||||
#define glCheck(x) x; sf::priv::glCheckError(__FILE__, __LINE__);
|
||||
|
||||
#else
|
||||
|
||||
// Else, we don't add any overhead
|
||||
#define glCheck(call) (call)
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check the last OpenGL error
|
||||
///
|
||||
/// \param file Source file where the call is located
|
||||
/// \param line Line number of the source file where the call is located
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void glCheckError(const char* file, unsigned int line);
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GLCHECK_HPP
|
||||
|
|
|
@ -1,58 +1,58 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/GLExtensions.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void ensureExtensionsInit()
|
||||
{
|
||||
#if !defined(SFML_OPENGL_ES)
|
||||
static bool initialized = false;
|
||||
if (!initialized)
|
||||
{
|
||||
GLenum status = glewInit();
|
||||
if (status == GLEW_OK)
|
||||
{
|
||||
initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to initialize GLEW, " << glewGetErrorString(status) << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/GLExtensions.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void ensureExtensionsInit()
|
||||
{
|
||||
#if !defined(SFML_OPENGL_ES)
|
||||
static bool initialized = false;
|
||||
if (!initialized)
|
||||
{
|
||||
GLenum status = glewInit();
|
||||
if (status == GLEW_OK)
|
||||
{
|
||||
initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to initialize GLEW, " << glewGetErrorString(status) << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,130 +1,130 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_GLEXTENSIONS_HPP
|
||||
#define SFML_GLEXTENSIONS_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
#ifdef SFML_OPENGL_ES
|
||||
|
||||
#include <SFML/OpenGL.hpp>
|
||||
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
// Hack to make transparency working on some Android devices
|
||||
#define GLEXT_blend_func_separate false
|
||||
#define GLEXT_blend_equation_separate false
|
||||
#else
|
||||
#define GLEXT_blend_func_separate GL_OES_blend_func_separate
|
||||
#define GLEXT_blend_equation_separate GL_OES_blend_equation_separate
|
||||
#endif
|
||||
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateOES
|
||||
#define GLEXT_glBlendEquationSeparate glBlendEquationSeparateOES
|
||||
#define GLEXT_framebuffer_object GL_OES_framebuffer_object
|
||||
#define GLEXT_glGenFramebuffers glGenFramebuffersOES
|
||||
#define GLEXT_glGenRenderbuffers glGenRenderbuffersOES
|
||||
#define GLEXT_glBindFramebuffer glBindFramebufferOES
|
||||
#define GLEXT_glBindRenderbuffer glBindRenderbufferOES
|
||||
#define GLEXT_glDeleteFramebuffers glDeleteFramebuffersOES
|
||||
#define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersOES
|
||||
#define GLEXT_glRenderbufferStorage glRenderbufferStorageOES
|
||||
#define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferOES
|
||||
#define GLEXT_glFramebufferTexture2D glFramebufferTexture2DOES
|
||||
#define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusOES
|
||||
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
|
||||
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
|
||||
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_OES
|
||||
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES
|
||||
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES
|
||||
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
|
||||
#define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT16_OES
|
||||
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES
|
||||
#define GLEXT_texture_non_power_of_two false
|
||||
#define GLEXT_multitexture true
|
||||
#define GLEXT_glClientActiveTexture glClientActiveTexture
|
||||
#define GLEXT_glActiveTexture glActiveTexture
|
||||
#define GLEXT_GL_TEXTURE0 GL_TEXTURE0
|
||||
#define GLEXT_glBlendEquation glBlendEquationOES
|
||||
#define GLEXT_GL_FUNC_ADD GL_FUNC_ADD_OES
|
||||
#define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT_OES
|
||||
|
||||
#else
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <SFML/OpenGL.hpp>
|
||||
|
||||
#define GLEXT_blend_func_separate GLEW_EXT_blend_func_separate
|
||||
#define GLEXT_blend_equation_separate GLEW_EXT_blend_equation_separate
|
||||
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateEXT
|
||||
#define GLEXT_glBlendEquationSeparate glBlendEquationSeparateEXT
|
||||
#define GLEXT_framebuffer_object GLEW_EXT_framebuffer_object
|
||||
#define GLEXT_glGenFramebuffers glGenFramebuffersEXT
|
||||
#define GLEXT_glGenRenderbuffers glGenRenderbuffersEXT
|
||||
#define GLEXT_glBindFramebuffer glBindFramebufferEXT
|
||||
#define GLEXT_glBindRenderbuffer glBindRenderbufferEXT
|
||||
#define GLEXT_glDeleteFramebuffers glDeleteFramebuffersEXT
|
||||
#define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersEXT
|
||||
#define GLEXT_glRenderbufferStorage glRenderbufferStorageEXT
|
||||
#define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferEXT
|
||||
#define GLEXT_glFramebufferTexture2D glFramebufferTexture2DEXT
|
||||
#define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusEXT
|
||||
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
|
||||
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT
|
||||
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_EXT
|
||||
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
|
||||
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
|
||||
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
|
||||
#define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT
|
||||
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
|
||||
#define GLEXT_texture_non_power_of_two GLEW_ARB_texture_non_power_of_two
|
||||
#define GLEXT_multitexture GLEW_ARB_multitexture
|
||||
#define GLEXT_glClientActiveTexture glClientActiveTextureARB
|
||||
#define GLEXT_glActiveTexture glActiveTextureARB
|
||||
#define GLEXT_GL_TEXTURE0 GL_TEXTURE0_ARB
|
||||
#define GLEXT_glBlendEquation glBlendEquation
|
||||
#define GLEXT_GL_FUNC_ADD GL_FUNC_ADD
|
||||
#define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT
|
||||
|
||||
#endif
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Make sure that extensions are initialized
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void ensureExtensionsInit();
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GLEXTENSIONS_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_GLEXTENSIONS_HPP
|
||||
#define SFML_GLEXTENSIONS_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
#ifdef SFML_OPENGL_ES
|
||||
|
||||
#include <SFML/OpenGL.hpp>
|
||||
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
// Hack to make transparency working on some Android devices
|
||||
#define GLEXT_blend_func_separate false
|
||||
#define GLEXT_blend_equation_separate false
|
||||
#else
|
||||
#define GLEXT_blend_func_separate GL_OES_blend_func_separate
|
||||
#define GLEXT_blend_equation_separate GL_OES_blend_equation_separate
|
||||
#endif
|
||||
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateOES
|
||||
#define GLEXT_glBlendEquationSeparate glBlendEquationSeparateOES
|
||||
#define GLEXT_framebuffer_object GL_OES_framebuffer_object
|
||||
#define GLEXT_glGenFramebuffers glGenFramebuffersOES
|
||||
#define GLEXT_glGenRenderbuffers glGenRenderbuffersOES
|
||||
#define GLEXT_glBindFramebuffer glBindFramebufferOES
|
||||
#define GLEXT_glBindRenderbuffer glBindRenderbufferOES
|
||||
#define GLEXT_glDeleteFramebuffers glDeleteFramebuffersOES
|
||||
#define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersOES
|
||||
#define GLEXT_glRenderbufferStorage glRenderbufferStorageOES
|
||||
#define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferOES
|
||||
#define GLEXT_glFramebufferTexture2D glFramebufferTexture2DOES
|
||||
#define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusOES
|
||||
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
|
||||
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
|
||||
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_OES
|
||||
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES
|
||||
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES
|
||||
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
|
||||
#define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT16_OES
|
||||
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES
|
||||
#define GLEXT_texture_non_power_of_two false
|
||||
#define GLEXT_multitexture true
|
||||
#define GLEXT_glClientActiveTexture glClientActiveTexture
|
||||
#define GLEXT_glActiveTexture glActiveTexture
|
||||
#define GLEXT_GL_TEXTURE0 GL_TEXTURE0
|
||||
#define GLEXT_glBlendEquation glBlendEquationOES
|
||||
#define GLEXT_GL_FUNC_ADD GL_FUNC_ADD_OES
|
||||
#define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT_OES
|
||||
|
||||
#else
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <SFML/OpenGL.hpp>
|
||||
|
||||
#define GLEXT_blend_func_separate GLEW_EXT_blend_func_separate
|
||||
#define GLEXT_blend_equation_separate GLEW_EXT_blend_equation_separate
|
||||
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateEXT
|
||||
#define GLEXT_glBlendEquationSeparate glBlendEquationSeparateEXT
|
||||
#define GLEXT_framebuffer_object GLEW_EXT_framebuffer_object
|
||||
#define GLEXT_glGenFramebuffers glGenFramebuffersEXT
|
||||
#define GLEXT_glGenRenderbuffers glGenRenderbuffersEXT
|
||||
#define GLEXT_glBindFramebuffer glBindFramebufferEXT
|
||||
#define GLEXT_glBindRenderbuffer glBindRenderbufferEXT
|
||||
#define GLEXT_glDeleteFramebuffers glDeleteFramebuffersEXT
|
||||
#define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersEXT
|
||||
#define GLEXT_glRenderbufferStorage glRenderbufferStorageEXT
|
||||
#define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferEXT
|
||||
#define GLEXT_glFramebufferTexture2D glFramebufferTexture2DEXT
|
||||
#define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusEXT
|
||||
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
|
||||
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT
|
||||
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_EXT
|
||||
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
|
||||
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
|
||||
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
|
||||
#define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT
|
||||
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
|
||||
#define GLEXT_texture_non_power_of_two GLEW_ARB_texture_non_power_of_two
|
||||
#define GLEXT_multitexture GLEW_ARB_multitexture
|
||||
#define GLEXT_glClientActiveTexture glClientActiveTextureARB
|
||||
#define GLEXT_glActiveTexture glActiveTextureARB
|
||||
#define GLEXT_GL_TEXTURE0 GL_TEXTURE0_ARB
|
||||
#define GLEXT_glBlendEquation glBlendEquation
|
||||
#define GLEXT_GL_FUNC_ADD GL_FUNC_ADD
|
||||
#define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT
|
||||
|
||||
#endif
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Make sure that extensions are initialized
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void ensureExtensionsInit();
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GLEXTENSIONS_HPP
|
||||
|
|
|
@ -1,344 +1,344 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include <SFML/Graphics/ImageLoader.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
#include <SFML/System/Android/ResourceStream.hpp>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Image::Image() :
|
||||
m_size(0, 0)
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
|
||||
m_stream = NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Image::~Image()
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
|
||||
if (m_stream)
|
||||
delete (priv::ResourceStream*)m_stream;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::create(unsigned int width, unsigned int height, const Color& color)
|
||||
{
|
||||
if (width && height)
|
||||
{
|
||||
// Assign the new size
|
||||
m_size.x = width;
|
||||
m_size.y = height;
|
||||
|
||||
// Resize the pixel buffer
|
||||
m_pixels.resize(width * height * 4);
|
||||
|
||||
// Fill it with the specified color
|
||||
Uint8* ptr = &m_pixels[0];
|
||||
Uint8* end = ptr + m_pixels.size();
|
||||
while (ptr < end)
|
||||
{
|
||||
*ptr++ = color.r;
|
||||
*ptr++ = color.g;
|
||||
*ptr++ = color.b;
|
||||
*ptr++ = color.a;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an empty image
|
||||
m_size.x = 0;
|
||||
m_size.y = 0;
|
||||
m_pixels.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::create(unsigned int width, unsigned int height, const Uint8* pixels)
|
||||
{
|
||||
if (pixels && width && height)
|
||||
{
|
||||
// Assign the new size
|
||||
m_size.x = width;
|
||||
m_size.y = height;
|
||||
|
||||
// Copy the pixels
|
||||
std::size_t size = width * height * 4;
|
||||
m_pixels.resize(size);
|
||||
std::memcpy(&m_pixels[0], pixels, size); // faster than vector::assign
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an empty image
|
||||
m_size.x = 0;
|
||||
m_size.y = 0;
|
||||
m_pixels.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Image::loadFromFile(const std::string& filename)
|
||||
{
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
|
||||
return priv::ImageLoader::getInstance().loadImageFromFile(filename, m_pixels, m_size);
|
||||
|
||||
#else
|
||||
|
||||
if (m_stream)
|
||||
delete (priv::ResourceStream*)m_stream;
|
||||
|
||||
m_stream = new priv::ResourceStream(filename);
|
||||
return loadFromStream(*(priv::ResourceStream*)m_stream);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Image::loadFromMemory(const void* data, std::size_t size)
|
||||
{
|
||||
return priv::ImageLoader::getInstance().loadImageFromMemory(data, size, m_pixels, m_size);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Image::loadFromStream(InputStream& stream)
|
||||
{
|
||||
return priv::ImageLoader::getInstance().loadImageFromStream(stream, m_pixels, m_size);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Image::saveToFile(const std::string& filename) const
|
||||
{
|
||||
return priv::ImageLoader::getInstance().saveImageToFile(filename, m_pixels, m_size);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2u Image::getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::createMaskFromColor(const Color& color, Uint8 alpha)
|
||||
{
|
||||
// Make sure that the image is not empty
|
||||
if (!m_pixels.empty())
|
||||
{
|
||||
// Replace the alpha of the pixels that match the transparent color
|
||||
Uint8* ptr = &m_pixels[0];
|
||||
Uint8* end = ptr + m_pixels.size();
|
||||
while (ptr < end)
|
||||
{
|
||||
if ((ptr[0] == color.r) && (ptr[1] == color.g) && (ptr[2] == color.b) && (ptr[3] == color.a))
|
||||
ptr[3] = alpha;
|
||||
ptr += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect, bool applyAlpha)
|
||||
{
|
||||
// Make sure that both images are valid
|
||||
if ((source.m_size.x == 0) || (source.m_size.y == 0) || (m_size.x == 0) || (m_size.y == 0))
|
||||
return;
|
||||
|
||||
// Adjust the source rectangle
|
||||
IntRect srcRect = sourceRect;
|
||||
if (srcRect.width == 0 || (srcRect.height == 0))
|
||||
{
|
||||
srcRect.left = 0;
|
||||
srcRect.top = 0;
|
||||
srcRect.width = source.m_size.x;
|
||||
srcRect.height = source.m_size.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (srcRect.left < 0) srcRect.left = 0;
|
||||
if (srcRect.top < 0) srcRect.top = 0;
|
||||
if (srcRect.width > static_cast<int>(source.m_size.x)) srcRect.width = source.m_size.x;
|
||||
if (srcRect.height > static_cast<int>(source.m_size.y)) srcRect.height = source.m_size.y;
|
||||
}
|
||||
|
||||
// Then find the valid bounds of the destination rectangle
|
||||
int width = srcRect.width;
|
||||
int height = srcRect.height;
|
||||
if (destX + width > m_size.x) width = m_size.x - destX;
|
||||
if (destY + height > m_size.y) height = m_size.y - destY;
|
||||
|
||||
// Make sure the destination area is valid
|
||||
if ((width <= 0) || (height <= 0))
|
||||
return;
|
||||
|
||||
// Precompute as much as possible
|
||||
int pitch = width * 4;
|
||||
int rows = height;
|
||||
int srcStride = source.m_size.x * 4;
|
||||
int dstStride = m_size.x * 4;
|
||||
const Uint8* srcPixels = &source.m_pixels[0] + (srcRect.left + srcRect.top * source.m_size.x) * 4;
|
||||
Uint8* dstPixels = &m_pixels[0] + (destX + destY * m_size.x) * 4;
|
||||
|
||||
// Copy the pixels
|
||||
if (applyAlpha)
|
||||
{
|
||||
// Interpolation using alpha values, pixel by pixel (slower)
|
||||
for (int i = 0; i < rows; ++i)
|
||||
{
|
||||
for (int j = 0; j < width; ++j)
|
||||
{
|
||||
// Get a direct pointer to the components of the current pixel
|
||||
const Uint8* src = srcPixels + j * 4;
|
||||
Uint8* dst = dstPixels + j * 4;
|
||||
|
||||
// Interpolate RGBA components using the alpha value of the source pixel
|
||||
Uint8 alpha = src[3];
|
||||
dst[0] = (src[0] * alpha + dst[0] * (255 - alpha)) / 255;
|
||||
dst[1] = (src[1] * alpha + dst[1] * (255 - alpha)) / 255;
|
||||
dst[2] = (src[2] * alpha + dst[2] * (255 - alpha)) / 255;
|
||||
dst[3] = alpha + dst[3] * (255 - alpha) / 255;
|
||||
}
|
||||
|
||||
srcPixels += srcStride;
|
||||
dstPixels += dstStride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Optimized copy ignoring alpha values, row by row (faster)
|
||||
for (int i = 0; i < rows; ++i)
|
||||
{
|
||||
std::memcpy(dstPixels, srcPixels, pitch);
|
||||
srcPixels += srcStride;
|
||||
dstPixels += dstStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::setPixel(unsigned int x, unsigned int y, const Color& color)
|
||||
{
|
||||
Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4];
|
||||
*pixel++ = color.r;
|
||||
*pixel++ = color.g;
|
||||
*pixel++ = color.b;
|
||||
*pixel++ = color.a;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color Image::getPixel(unsigned int x, unsigned int y) const
|
||||
{
|
||||
const Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4];
|
||||
return Color(pixel[0], pixel[1], pixel[2], pixel[3]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Uint8* Image::getPixelsPtr() const
|
||||
{
|
||||
if (!m_pixels.empty())
|
||||
{
|
||||
return &m_pixels[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Trying to access the pixels of an empty image" << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::flipHorizontally()
|
||||
{
|
||||
if (!m_pixels.empty())
|
||||
{
|
||||
std::size_t rowSize = m_size.x * 4;
|
||||
|
||||
for (std::size_t y = 0; y < m_size.y; ++y)
|
||||
{
|
||||
std::vector<Uint8>::iterator left = m_pixels.begin() + y * rowSize;
|
||||
std::vector<Uint8>::iterator right = m_pixels.begin() + (y + 1) * rowSize - 4;
|
||||
|
||||
for (std::size_t x = 0; x < m_size.x / 2; ++x)
|
||||
{
|
||||
std::swap_ranges(left, left + 4, right);
|
||||
|
||||
left += 4;
|
||||
right -= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::flipVertically()
|
||||
{
|
||||
if (!m_pixels.empty())
|
||||
{
|
||||
std::size_t rowSize = m_size.x * 4;
|
||||
|
||||
std::vector<Uint8>::iterator top = m_pixels.begin();
|
||||
std::vector<Uint8>::iterator bottom = m_pixels.end() - rowSize;
|
||||
|
||||
for (std::size_t y = 0; y < m_size.y / 2; ++y)
|
||||
{
|
||||
std::swap_ranges(top, top + rowSize, bottom);
|
||||
|
||||
top += rowSize;
|
||||
bottom -= rowSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include <SFML/Graphics/ImageLoader.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
#include <SFML/System/Android/ResourceStream.hpp>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Image::Image() :
|
||||
m_size(0, 0)
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
|
||||
m_stream = NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Image::~Image()
|
||||
{
|
||||
#ifdef SFML_SYSTEM_ANDROID
|
||||
|
||||
if (m_stream)
|
||||
delete (priv::ResourceStream*)m_stream;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::create(unsigned int width, unsigned int height, const Color& color)
|
||||
{
|
||||
if (width && height)
|
||||
{
|
||||
// Assign the new size
|
||||
m_size.x = width;
|
||||
m_size.y = height;
|
||||
|
||||
// Resize the pixel buffer
|
||||
m_pixels.resize(width * height * 4);
|
||||
|
||||
// Fill it with the specified color
|
||||
Uint8* ptr = &m_pixels[0];
|
||||
Uint8* end = ptr + m_pixels.size();
|
||||
while (ptr < end)
|
||||
{
|
||||
*ptr++ = color.r;
|
||||
*ptr++ = color.g;
|
||||
*ptr++ = color.b;
|
||||
*ptr++ = color.a;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an empty image
|
||||
m_size.x = 0;
|
||||
m_size.y = 0;
|
||||
m_pixels.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::create(unsigned int width, unsigned int height, const Uint8* pixels)
|
||||
{
|
||||
if (pixels && width && height)
|
||||
{
|
||||
// Assign the new size
|
||||
m_size.x = width;
|
||||
m_size.y = height;
|
||||
|
||||
// Copy the pixels
|
||||
std::size_t size = width * height * 4;
|
||||
m_pixels.resize(size);
|
||||
std::memcpy(&m_pixels[0], pixels, size); // faster than vector::assign
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an empty image
|
||||
m_size.x = 0;
|
||||
m_size.y = 0;
|
||||
m_pixels.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Image::loadFromFile(const std::string& filename)
|
||||
{
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
|
||||
return priv::ImageLoader::getInstance().loadImageFromFile(filename, m_pixels, m_size);
|
||||
|
||||
#else
|
||||
|
||||
if (m_stream)
|
||||
delete (priv::ResourceStream*)m_stream;
|
||||
|
||||
m_stream = new priv::ResourceStream(filename);
|
||||
return loadFromStream(*(priv::ResourceStream*)m_stream);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Image::loadFromMemory(const void* data, std::size_t size)
|
||||
{
|
||||
return priv::ImageLoader::getInstance().loadImageFromMemory(data, size, m_pixels, m_size);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Image::loadFromStream(InputStream& stream)
|
||||
{
|
||||
return priv::ImageLoader::getInstance().loadImageFromStream(stream, m_pixels, m_size);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Image::saveToFile(const std::string& filename) const
|
||||
{
|
||||
return priv::ImageLoader::getInstance().saveImageToFile(filename, m_pixels, m_size);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2u Image::getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::createMaskFromColor(const Color& color, Uint8 alpha)
|
||||
{
|
||||
// Make sure that the image is not empty
|
||||
if (!m_pixels.empty())
|
||||
{
|
||||
// Replace the alpha of the pixels that match the transparent color
|
||||
Uint8* ptr = &m_pixels[0];
|
||||
Uint8* end = ptr + m_pixels.size();
|
||||
while (ptr < end)
|
||||
{
|
||||
if ((ptr[0] == color.r) && (ptr[1] == color.g) && (ptr[2] == color.b) && (ptr[3] == color.a))
|
||||
ptr[3] = alpha;
|
||||
ptr += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect, bool applyAlpha)
|
||||
{
|
||||
// Make sure that both images are valid
|
||||
if ((source.m_size.x == 0) || (source.m_size.y == 0) || (m_size.x == 0) || (m_size.y == 0))
|
||||
return;
|
||||
|
||||
// Adjust the source rectangle
|
||||
IntRect srcRect = sourceRect;
|
||||
if (srcRect.width == 0 || (srcRect.height == 0))
|
||||
{
|
||||
srcRect.left = 0;
|
||||
srcRect.top = 0;
|
||||
srcRect.width = source.m_size.x;
|
||||
srcRect.height = source.m_size.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (srcRect.left < 0) srcRect.left = 0;
|
||||
if (srcRect.top < 0) srcRect.top = 0;
|
||||
if (srcRect.width > static_cast<int>(source.m_size.x)) srcRect.width = source.m_size.x;
|
||||
if (srcRect.height > static_cast<int>(source.m_size.y)) srcRect.height = source.m_size.y;
|
||||
}
|
||||
|
||||
// Then find the valid bounds of the destination rectangle
|
||||
int width = srcRect.width;
|
||||
int height = srcRect.height;
|
||||
if (destX + width > m_size.x) width = m_size.x - destX;
|
||||
if (destY + height > m_size.y) height = m_size.y - destY;
|
||||
|
||||
// Make sure the destination area is valid
|
||||
if ((width <= 0) || (height <= 0))
|
||||
return;
|
||||
|
||||
// Precompute as much as possible
|
||||
int pitch = width * 4;
|
||||
int rows = height;
|
||||
int srcStride = source.m_size.x * 4;
|
||||
int dstStride = m_size.x * 4;
|
||||
const Uint8* srcPixels = &source.m_pixels[0] + (srcRect.left + srcRect.top * source.m_size.x) * 4;
|
||||
Uint8* dstPixels = &m_pixels[0] + (destX + destY * m_size.x) * 4;
|
||||
|
||||
// Copy the pixels
|
||||
if (applyAlpha)
|
||||
{
|
||||
// Interpolation using alpha values, pixel by pixel (slower)
|
||||
for (int i = 0; i < rows; ++i)
|
||||
{
|
||||
for (int j = 0; j < width; ++j)
|
||||
{
|
||||
// Get a direct pointer to the components of the current pixel
|
||||
const Uint8* src = srcPixels + j * 4;
|
||||
Uint8* dst = dstPixels + j * 4;
|
||||
|
||||
// Interpolate RGBA components using the alpha value of the source pixel
|
||||
Uint8 alpha = src[3];
|
||||
dst[0] = (src[0] * alpha + dst[0] * (255 - alpha)) / 255;
|
||||
dst[1] = (src[1] * alpha + dst[1] * (255 - alpha)) / 255;
|
||||
dst[2] = (src[2] * alpha + dst[2] * (255 - alpha)) / 255;
|
||||
dst[3] = alpha + dst[3] * (255 - alpha) / 255;
|
||||
}
|
||||
|
||||
srcPixels += srcStride;
|
||||
dstPixels += dstStride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Optimized copy ignoring alpha values, row by row (faster)
|
||||
for (int i = 0; i < rows; ++i)
|
||||
{
|
||||
std::memcpy(dstPixels, srcPixels, pitch);
|
||||
srcPixels += srcStride;
|
||||
dstPixels += dstStride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::setPixel(unsigned int x, unsigned int y, const Color& color)
|
||||
{
|
||||
Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4];
|
||||
*pixel++ = color.r;
|
||||
*pixel++ = color.g;
|
||||
*pixel++ = color.b;
|
||||
*pixel++ = color.a;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Color Image::getPixel(unsigned int x, unsigned int y) const
|
||||
{
|
||||
const Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4];
|
||||
return Color(pixel[0], pixel[1], pixel[2], pixel[3]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Uint8* Image::getPixelsPtr() const
|
||||
{
|
||||
if (!m_pixels.empty())
|
||||
{
|
||||
return &m_pixels[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Trying to access the pixels of an empty image" << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::flipHorizontally()
|
||||
{
|
||||
if (!m_pixels.empty())
|
||||
{
|
||||
std::size_t rowSize = m_size.x * 4;
|
||||
|
||||
for (std::size_t y = 0; y < m_size.y; ++y)
|
||||
{
|
||||
std::vector<Uint8>::iterator left = m_pixels.begin() + y * rowSize;
|
||||
std::vector<Uint8>::iterator right = m_pixels.begin() + (y + 1) * rowSize - 4;
|
||||
|
||||
for (std::size_t x = 0; x < m_size.x / 2; ++x)
|
||||
{
|
||||
std::swap_ranges(left, left + 4, right);
|
||||
|
||||
left += 4;
|
||||
right -= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Image::flipVertically()
|
||||
{
|
||||
if (!m_pixels.empty())
|
||||
{
|
||||
std::size_t rowSize = m_size.x * 4;
|
||||
|
||||
std::vector<Uint8>::iterator top = m_pixels.begin();
|
||||
std::vector<Uint8>::iterator bottom = m_pixels.end() - rowSize;
|
||||
|
||||
for (std::size_t y = 0; y < m_size.y / 2; ++y)
|
||||
{
|
||||
std::swap_ranges(top, top + rowSize, bottom);
|
||||
|
||||
top += rowSize;
|
||||
bottom -= rowSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,321 +1,321 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/ImageLoader.hpp>
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <SFML/Graphics/stb_image/stb_image.h>
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <SFML/Graphics/stb_image/stb_image_write.h>
|
||||
extern "C"
|
||||
{
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
}
|
||||
#include <cctype>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Convert a string to lower case
|
||||
std::string toLower(std::string str)
|
||||
{
|
||||
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
||||
*i = static_cast<char>(std::tolower(*i));
|
||||
return str;
|
||||
}
|
||||
|
||||
// stb_image callbacks that operate on a sf::InputStream
|
||||
int read(void* user, char* data, int size)
|
||||
{
|
||||
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
|
||||
return static_cast<int>(stream->read(data, size));
|
||||
}
|
||||
void skip(void* user, unsigned int size)
|
||||
{
|
||||
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
|
||||
stream->seek(stream->tell() + size);
|
||||
}
|
||||
int eof(void* user)
|
||||
{
|
||||
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
|
||||
return stream->tell() >= stream->getSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ImageLoader& ImageLoader::getInstance()
|
||||
{
|
||||
static ImageLoader Instance;
|
||||
|
||||
return Instance;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ImageLoader::ImageLoader()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ImageLoader::~ImageLoader()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::loadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, Vector2u& size)
|
||||
{
|
||||
// Clear the array (just in case)
|
||||
pixels.clear();
|
||||
|
||||
// Load the image and get a pointer to the pixels in memory
|
||||
int width, height, channels;
|
||||
unsigned char* ptr = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (ptr && width && height)
|
||||
{
|
||||
// Assign the image properties
|
||||
size.x = width;
|
||||
size.y = height;
|
||||
|
||||
// Copy the loaded pixels to the pixel buffer
|
||||
pixels.resize(width * height * 4);
|
||||
memcpy(&pixels[0], ptr, pixels.size());
|
||||
|
||||
// Free the loaded pixels (they are now in our own pixel buffer)
|
||||
stbi_image_free(ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error, failed to load the image
|
||||
err() << "Failed to load image \"" << filename << "\". Reason : " << stbi_failure_reason() << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::loadImageFromMemory(const void* data, std::size_t dataSize, std::vector<Uint8>& pixels, Vector2u& size)
|
||||
{
|
||||
// Check input parameters
|
||||
if (data && dataSize)
|
||||
{
|
||||
// Clear the array (just in case)
|
||||
pixels.clear();
|
||||
|
||||
// Load the image and get a pointer to the pixels in memory
|
||||
int width, height, channels;
|
||||
const unsigned char* buffer = static_cast<const unsigned char*>(data);
|
||||
unsigned char* ptr = stbi_load_from_memory(buffer, static_cast<int>(dataSize), &width, &height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (ptr && width && height)
|
||||
{
|
||||
// Assign the image properties
|
||||
size.x = width;
|
||||
size.y = height;
|
||||
|
||||
// Copy the loaded pixels to the pixel buffer
|
||||
pixels.resize(width * height * 4);
|
||||
memcpy(&pixels[0], ptr, pixels.size());
|
||||
|
||||
// Free the loaded pixels (they are now in our own pixel buffer)
|
||||
stbi_image_free(ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error, failed to load the image
|
||||
err() << "Failed to load image from memory. Reason : " << stbi_failure_reason() << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to load image from memory, no data provided" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, Vector2u& size)
|
||||
{
|
||||
// Clear the array (just in case)
|
||||
pixels.clear();
|
||||
|
||||
// Make sure that the stream's reading position is at the beginning
|
||||
stream.seek(0);
|
||||
|
||||
// Setup the stb_image callbacks
|
||||
stbi_io_callbacks callbacks;
|
||||
callbacks.read = &read;
|
||||
callbacks.skip = &skip;
|
||||
callbacks.eof = &eof;
|
||||
|
||||
// Load the image and get a pointer to the pixels in memory
|
||||
int width, height, channels;
|
||||
unsigned char* ptr = stbi_load_from_callbacks(&callbacks, &stream, &width, &height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (ptr && width && height)
|
||||
{
|
||||
// Assign the image properties
|
||||
size.x = width;
|
||||
size.y = height;
|
||||
|
||||
// Copy the loaded pixels to the pixel buffer
|
||||
pixels.resize(width * height * 4);
|
||||
memcpy(&pixels[0], ptr, pixels.size());
|
||||
|
||||
// Free the loaded pixels (they are now in our own pixel buffer)
|
||||
stbi_image_free(ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error, failed to load the image
|
||||
err() << "Failed to load image from stream. Reason : " << stbi_failure_reason() << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, const Vector2u& size)
|
||||
{
|
||||
// Make sure the image is not empty
|
||||
if (!pixels.empty() && (size.x > 0) && (size.y > 0))
|
||||
{
|
||||
// Deduce the image type from its extension
|
||||
if (filename.size() > 3)
|
||||
{
|
||||
// Extract the extension
|
||||
std::string extension = toLower(filename.substr(filename.size() - 3));
|
||||
|
||||
if (extension == "bmp")
|
||||
{
|
||||
// BMP format
|
||||
if (stbi_write_bmp(filename.c_str(), size.x, size.y, 4, &pixels[0]))
|
||||
return true;
|
||||
}
|
||||
else if (extension == "tga")
|
||||
{
|
||||
// TGA format
|
||||
if (stbi_write_tga(filename.c_str(), size.x, size.y, 4, &pixels[0]))
|
||||
return true;
|
||||
}
|
||||
else if (extension == "png")
|
||||
{
|
||||
// PNG format
|
||||
if (stbi_write_png(filename.c_str(), size.x, size.y, 4, &pixels[0], 0))
|
||||
return true;
|
||||
}
|
||||
else if (extension == "jpg")
|
||||
{
|
||||
// JPG format
|
||||
if (writeJpg(filename, pixels, size.x, size.y))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err() << "Failed to save image \"" << filename << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
|
||||
{
|
||||
// Open the file to write in
|
||||
FILE* file = fopen(filename.c_str(), "wb");
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
// Initialize the error handler
|
||||
jpeg_compress_struct compressInfos;
|
||||
jpeg_error_mgr errorManager;
|
||||
compressInfos.err = jpeg_std_error(&errorManager);
|
||||
|
||||
// Initialize all the writing and compression infos
|
||||
jpeg_create_compress(&compressInfos);
|
||||
compressInfos.image_width = width;
|
||||
compressInfos.image_height = height;
|
||||
compressInfos.input_components = 3;
|
||||
compressInfos.in_color_space = JCS_RGB;
|
||||
jpeg_stdio_dest(&compressInfos, file);
|
||||
jpeg_set_defaults(&compressInfos);
|
||||
jpeg_set_quality(&compressInfos, 90, TRUE);
|
||||
|
||||
// Get rid of the aplha channel
|
||||
std::vector<Uint8> buffer(width * height * 3);
|
||||
for (std::size_t i = 0; i < width * height; ++i)
|
||||
{
|
||||
buffer[i * 3 + 0] = pixels[i * 4 + 0];
|
||||
buffer[i * 3 + 1] = pixels[i * 4 + 1];
|
||||
buffer[i * 3 + 2] = pixels[i * 4 + 2];
|
||||
}
|
||||
Uint8* ptr = &buffer[0];
|
||||
|
||||
// Start compression
|
||||
jpeg_start_compress(&compressInfos, TRUE);
|
||||
|
||||
// Write each row of the image
|
||||
while (compressInfos.next_scanline < compressInfos.image_height)
|
||||
{
|
||||
JSAMPROW rawPointer = ptr + (compressInfos.next_scanline * width * 3);
|
||||
jpeg_write_scanlines(&compressInfos, &rawPointer, 1);
|
||||
}
|
||||
|
||||
// Finish compression
|
||||
jpeg_finish_compress(&compressInfos);
|
||||
jpeg_destroy_compress(&compressInfos);
|
||||
|
||||
// Close the file
|
||||
fclose(file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/ImageLoader.hpp>
|
||||
#include <SFML/System/InputStream.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <SFML/Graphics/stb_image/stb_image.h>
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <SFML/Graphics/stb_image/stb_image_write.h>
|
||||
extern "C"
|
||||
{
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
}
|
||||
#include <cctype>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Convert a string to lower case
|
||||
std::string toLower(std::string str)
|
||||
{
|
||||
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
||||
*i = static_cast<char>(std::tolower(*i));
|
||||
return str;
|
||||
}
|
||||
|
||||
// stb_image callbacks that operate on a sf::InputStream
|
||||
int read(void* user, char* data, int size)
|
||||
{
|
||||
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
|
||||
return static_cast<int>(stream->read(data, size));
|
||||
}
|
||||
void skip(void* user, unsigned int size)
|
||||
{
|
||||
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
|
||||
stream->seek(stream->tell() + size);
|
||||
}
|
||||
int eof(void* user)
|
||||
{
|
||||
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
|
||||
return stream->tell() >= stream->getSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ImageLoader& ImageLoader::getInstance()
|
||||
{
|
||||
static ImageLoader Instance;
|
||||
|
||||
return Instance;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ImageLoader::ImageLoader()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ImageLoader::~ImageLoader()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::loadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, Vector2u& size)
|
||||
{
|
||||
// Clear the array (just in case)
|
||||
pixels.clear();
|
||||
|
||||
// Load the image and get a pointer to the pixels in memory
|
||||
int width, height, channels;
|
||||
unsigned char* ptr = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (ptr && width && height)
|
||||
{
|
||||
// Assign the image properties
|
||||
size.x = width;
|
||||
size.y = height;
|
||||
|
||||
// Copy the loaded pixels to the pixel buffer
|
||||
pixels.resize(width * height * 4);
|
||||
memcpy(&pixels[0], ptr, pixels.size());
|
||||
|
||||
// Free the loaded pixels (they are now in our own pixel buffer)
|
||||
stbi_image_free(ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error, failed to load the image
|
||||
err() << "Failed to load image \"" << filename << "\". Reason: " << stbi_failure_reason() << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::loadImageFromMemory(const void* data, std::size_t dataSize, std::vector<Uint8>& pixels, Vector2u& size)
|
||||
{
|
||||
// Check input parameters
|
||||
if (data && dataSize)
|
||||
{
|
||||
// Clear the array (just in case)
|
||||
pixels.clear();
|
||||
|
||||
// Load the image and get a pointer to the pixels in memory
|
||||
int width, height, channels;
|
||||
const unsigned char* buffer = static_cast<const unsigned char*>(data);
|
||||
unsigned char* ptr = stbi_load_from_memory(buffer, static_cast<int>(dataSize), &width, &height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (ptr && width && height)
|
||||
{
|
||||
// Assign the image properties
|
||||
size.x = width;
|
||||
size.y = height;
|
||||
|
||||
// Copy the loaded pixels to the pixel buffer
|
||||
pixels.resize(width * height * 4);
|
||||
memcpy(&pixels[0], ptr, pixels.size());
|
||||
|
||||
// Free the loaded pixels (they are now in our own pixel buffer)
|
||||
stbi_image_free(ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error, failed to load the image
|
||||
err() << "Failed to load image from memory. Reason: " << stbi_failure_reason() << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err() << "Failed to load image from memory, no data provided" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, Vector2u& size)
|
||||
{
|
||||
// Clear the array (just in case)
|
||||
pixels.clear();
|
||||
|
||||
// Make sure that the stream's reading position is at the beginning
|
||||
stream.seek(0);
|
||||
|
||||
// Setup the stb_image callbacks
|
||||
stbi_io_callbacks callbacks;
|
||||
callbacks.read = &read;
|
||||
callbacks.skip = &skip;
|
||||
callbacks.eof = &eof;
|
||||
|
||||
// Load the image and get a pointer to the pixels in memory
|
||||
int width, height, channels;
|
||||
unsigned char* ptr = stbi_load_from_callbacks(&callbacks, &stream, &width, &height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (ptr && width && height)
|
||||
{
|
||||
// Assign the image properties
|
||||
size.x = width;
|
||||
size.y = height;
|
||||
|
||||
// Copy the loaded pixels to the pixel buffer
|
||||
pixels.resize(width * height * 4);
|
||||
memcpy(&pixels[0], ptr, pixels.size());
|
||||
|
||||
// Free the loaded pixels (they are now in our own pixel buffer)
|
||||
stbi_image_free(ptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error, failed to load the image
|
||||
err() << "Failed to load image from stream. Reason: " << stbi_failure_reason() << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, const Vector2u& size)
|
||||
{
|
||||
// Make sure the image is not empty
|
||||
if (!pixels.empty() && (size.x > 0) && (size.y > 0))
|
||||
{
|
||||
// Deduce the image type from its extension
|
||||
if (filename.size() > 3)
|
||||
{
|
||||
// Extract the extension
|
||||
std::string extension = toLower(filename.substr(filename.size() - 3));
|
||||
|
||||
if (extension == "bmp")
|
||||
{
|
||||
// BMP format
|
||||
if (stbi_write_bmp(filename.c_str(), size.x, size.y, 4, &pixels[0]))
|
||||
return true;
|
||||
}
|
||||
else if (extension == "tga")
|
||||
{
|
||||
// TGA format
|
||||
if (stbi_write_tga(filename.c_str(), size.x, size.y, 4, &pixels[0]))
|
||||
return true;
|
||||
}
|
||||
else if (extension == "png")
|
||||
{
|
||||
// PNG format
|
||||
if (stbi_write_png(filename.c_str(), size.x, size.y, 4, &pixels[0], 0))
|
||||
return true;
|
||||
}
|
||||
else if (extension == "jpg")
|
||||
{
|
||||
// JPG format
|
||||
if (writeJpg(filename, pixels, size.x, size.y))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err() << "Failed to save image \"" << filename << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool ImageLoader::writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
|
||||
{
|
||||
// Open the file to write in
|
||||
FILE* file = fopen(filename.c_str(), "wb");
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
// Initialize the error handler
|
||||
jpeg_compress_struct compressInfos;
|
||||
jpeg_error_mgr errorManager;
|
||||
compressInfos.err = jpeg_std_error(&errorManager);
|
||||
|
||||
// Initialize all the writing and compression infos
|
||||
jpeg_create_compress(&compressInfos);
|
||||
compressInfos.image_width = width;
|
||||
compressInfos.image_height = height;
|
||||
compressInfos.input_components = 3;
|
||||
compressInfos.in_color_space = JCS_RGB;
|
||||
jpeg_stdio_dest(&compressInfos, file);
|
||||
jpeg_set_defaults(&compressInfos);
|
||||
jpeg_set_quality(&compressInfos, 90, TRUE);
|
||||
|
||||
// Get rid of the aplha channel
|
||||
std::vector<Uint8> buffer(width * height * 3);
|
||||
for (std::size_t i = 0; i < width * height; ++i)
|
||||
{
|
||||
buffer[i * 3 + 0] = pixels[i * 4 + 0];
|
||||
buffer[i * 3 + 1] = pixels[i * 4 + 1];
|
||||
buffer[i * 3 + 2] = pixels[i * 4 + 2];
|
||||
}
|
||||
Uint8* ptr = &buffer[0];
|
||||
|
||||
// Start compression
|
||||
jpeg_start_compress(&compressInfos, TRUE);
|
||||
|
||||
// Write each row of the image
|
||||
while (compressInfos.next_scanline < compressInfos.image_height)
|
||||
{
|
||||
JSAMPROW rawPointer = ptr + (compressInfos.next_scanline * width * 3);
|
||||
jpeg_write_scanlines(&compressInfos, &rawPointer, 1);
|
||||
}
|
||||
|
||||
// Finish compression
|
||||
jpeg_finish_compress(&compressInfos);
|
||||
jpeg_destroy_compress(&compressInfos);
|
||||
|
||||
// Close the file
|
||||
fclose(file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,141 +1,141 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_IMAGELOADER_HPP
|
||||
#define SFML_IMAGELOADER_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class InputStream;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load/save image files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class ImageLoader : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the unique instance of the class
|
||||
///
|
||||
/// \return Reference to the ImageLoader instance
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static ImageLoader& getInstance();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load an image from a file on disk
|
||||
///
|
||||
/// \param filename Path of image file to load
|
||||
/// \param pixels Array of pixels to fill with loaded image
|
||||
/// \param size Size of loaded image, in pixels
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool loadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, Vector2u& size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load an image from a file in memory
|
||||
///
|
||||
/// \param data Pointer to the file data in memory
|
||||
/// \param dataSize Size of the data to load, in bytes
|
||||
/// \param pixels Array of pixels to fill with loaded image
|
||||
/// \param size Size of loaded image, in pixels
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool loadImageFromMemory(const void* data, std::size_t dataSize, std::vector<Uint8>& pixels, Vector2u& size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load an image from a custom stream
|
||||
///
|
||||
/// \param stream Source stream to read from
|
||||
/// \param pixels Array of pixels to fill with loaded image
|
||||
/// \param size Size of loaded image, in pixels
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, Vector2u& size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Save an array of pixels as an image file
|
||||
///
|
||||
/// \param filename Path of image file to save
|
||||
/// \param pixels Array of pixels to save to image
|
||||
/// \param size Size of image to save, in pixels
|
||||
///
|
||||
/// \return True if saving was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, const Vector2u& size);
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ImageLoader();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ImageLoader();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Save an image file in JPEG format
|
||||
///
|
||||
/// \param filename Path of image file to save
|
||||
/// \param pixels Array of pixels to save to image
|
||||
/// \param width Width of image to save, in pixels
|
||||
/// \param height Height of image to save, in pixels
|
||||
///
|
||||
/// \return True if saving was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height);
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_IMAGELOADER_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_IMAGELOADER_HPP
|
||||
#define SFML_IMAGELOADER_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class InputStream;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load/save image files
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class ImageLoader : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the unique instance of the class
|
||||
///
|
||||
/// \return Reference to the ImageLoader instance
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static ImageLoader& getInstance();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load an image from a file on disk
|
||||
///
|
||||
/// \param filename Path of image file to load
|
||||
/// \param pixels Array of pixels to fill with loaded image
|
||||
/// \param size Size of loaded image, in pixels
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool loadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, Vector2u& size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load an image from a file in memory
|
||||
///
|
||||
/// \param data Pointer to the file data in memory
|
||||
/// \param dataSize Size of the data to load, in bytes
|
||||
/// \param pixels Array of pixels to fill with loaded image
|
||||
/// \param size Size of loaded image, in pixels
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool loadImageFromMemory(const void* data, std::size_t dataSize, std::vector<Uint8>& pixels, Vector2u& size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load an image from a custom stream
|
||||
///
|
||||
/// \param stream Source stream to read from
|
||||
/// \param pixels Array of pixels to fill with loaded image
|
||||
/// \param size Size of loaded image, in pixels
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, Vector2u& size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Save an array of pixels as an image file
|
||||
///
|
||||
/// \param filename Path of image file to save
|
||||
/// \param pixels Array of pixels to save to image
|
||||
/// \param size Size of image to save, in pixels
|
||||
///
|
||||
/// \return True if saving was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, const Vector2u& size);
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ImageLoader();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ImageLoader();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Save an image file in JPEG format
|
||||
///
|
||||
/// \param filename Path of image file to save
|
||||
/// \param pixels Array of pixels to save to image
|
||||
/// \param width Width of image to save, in pixels
|
||||
/// \param height Height of image to save, in pixels
|
||||
///
|
||||
/// \return True if saving was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height);
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_IMAGELOADER_HPP
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,155 +1,155 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderTexture.hpp>
|
||||
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
|
||||
#include <SFML/Graphics/RenderTextureImplDefault.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTexture::RenderTexture() :
|
||||
m_impl(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTexture::~RenderTexture()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer)
|
||||
{
|
||||
// Create the texture
|
||||
if (!m_texture.create(width, height))
|
||||
{
|
||||
err() << "Impossible to create render texture (failed to create the target texture)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We disable smoothing by default for render textures
|
||||
setSmooth(false);
|
||||
|
||||
// Create the implementation
|
||||
delete m_impl;
|
||||
if (priv::RenderTextureImplFBO::isAvailable())
|
||||
{
|
||||
// Use frame-buffer object (FBO)
|
||||
m_impl = new priv::RenderTextureImplFBO;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use default implementation
|
||||
m_impl = new priv::RenderTextureImplDefault;
|
||||
}
|
||||
|
||||
// Initialize the render texture
|
||||
if (!m_impl->create(width, height, m_texture.m_texture, depthBuffer))
|
||||
return false;
|
||||
|
||||
// We can now initialize the render target part
|
||||
RenderTarget::initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTexture::setSmooth(bool smooth)
|
||||
{
|
||||
m_texture.setSmooth(smooth);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::isSmooth() const
|
||||
{
|
||||
return m_texture.isSmooth();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTexture::setRepeated(bool repeated)
|
||||
{
|
||||
m_texture.setRepeated(repeated);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::isRepeated() const
|
||||
{
|
||||
return m_texture.isRepeated();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::setActive(bool active)
|
||||
{
|
||||
return m_impl && m_impl->activate(active);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTexture::display()
|
||||
{
|
||||
// Update the target texture
|
||||
if (setActive(true))
|
||||
{
|
||||
m_impl->updateTexture(m_texture.m_texture);
|
||||
m_texture.m_pixelsFlipped = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2u RenderTexture::getSize() const
|
||||
{
|
||||
return m_texture.getSize();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Texture& RenderTexture::getTexture() const
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::activate(bool active)
|
||||
{
|
||||
return setActive(active);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderTexture.hpp>
|
||||
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
|
||||
#include <SFML/Graphics/RenderTextureImplDefault.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTexture::RenderTexture() :
|
||||
m_impl(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTexture::~RenderTexture()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer)
|
||||
{
|
||||
// Create the texture
|
||||
if (!m_texture.create(width, height))
|
||||
{
|
||||
err() << "Impossible to create render texture (failed to create the target texture)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We disable smoothing by default for render textures
|
||||
setSmooth(false);
|
||||
|
||||
// Create the implementation
|
||||
delete m_impl;
|
||||
if (priv::RenderTextureImplFBO::isAvailable())
|
||||
{
|
||||
// Use frame-buffer object (FBO)
|
||||
m_impl = new priv::RenderTextureImplFBO;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use default implementation
|
||||
m_impl = new priv::RenderTextureImplDefault;
|
||||
}
|
||||
|
||||
// Initialize the render texture
|
||||
if (!m_impl->create(width, height, m_texture.m_texture, depthBuffer))
|
||||
return false;
|
||||
|
||||
// We can now initialize the render target part
|
||||
RenderTarget::initialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTexture::setSmooth(bool smooth)
|
||||
{
|
||||
m_texture.setSmooth(smooth);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::isSmooth() const
|
||||
{
|
||||
return m_texture.isSmooth();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTexture::setRepeated(bool repeated)
|
||||
{
|
||||
m_texture.setRepeated(repeated);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::isRepeated() const
|
||||
{
|
||||
return m_texture.isRepeated();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::setActive(bool active)
|
||||
{
|
||||
return m_impl && m_impl->activate(active);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTexture::display()
|
||||
{
|
||||
// Update the target texture
|
||||
if (setActive(true))
|
||||
{
|
||||
m_impl->updateTexture(m_texture.m_texture);
|
||||
m_texture.m_pixelsFlipped = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2u RenderTexture::getSize() const
|
||||
{
|
||||
return m_texture.getSize();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Texture& RenderTexture::getTexture() const
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTexture::activate(bool active)
|
||||
{
|
||||
return setActive(active);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderTextureImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTextureImpl::~RenderTextureImpl()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderTextureImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTextureImpl::~RenderTextureImpl()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,89 +1,89 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_RENDERTEXTUREIMPL_HPP
|
||||
#define SFML_RENDERTEXTUREIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Abstract base class for render-texture implementations
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class RenderTextureImpl : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual ~RenderTextureImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create the render texture implementation
|
||||
///
|
||||
/// \param width Width of the texture to render to
|
||||
/// \param height Height of the texture to render to
|
||||
/// \param textureId OpenGL identifier of the target texture
|
||||
/// \param depthBuffer Is a depth buffer requested?
|
||||
///
|
||||
/// \return True if creation has been successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate or deactivate the render texture for rendering
|
||||
///
|
||||
/// \param active True to activate, false to deactivate
|
||||
///
|
||||
/// \return True on success, false on failure
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool activate(bool active) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Update the pixels of the target texture
|
||||
///
|
||||
/// \param textureId OpenGL identifier of the target texture
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void updateTexture(unsigned int textureId) = 0;
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_RENDERTEXTUREIMPL_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_RENDERTEXTUREIMPL_HPP
|
||||
#define SFML_RENDERTEXTUREIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Abstract base class for render-texture implementations
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class RenderTextureImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual ~RenderTextureImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create the render texture implementation
|
||||
///
|
||||
/// \param width Width of the texture to render to
|
||||
/// \param height Height of the texture to render to
|
||||
/// \param textureId OpenGL identifier of the target texture
|
||||
/// \param depthBuffer Is a depth buffer requested?
|
||||
///
|
||||
/// \return True if creation has been successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate or deactivate the render texture for rendering
|
||||
///
|
||||
/// \param active True to activate, false to deactivate
|
||||
///
|
||||
/// \return True on success, false on failure
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool activate(bool active) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Update the pixels of the target texture
|
||||
///
|
||||
/// \param textureId OpenGL identifier of the target texture
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void updateTexture(unsigned int textureId) = 0;
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_RENDERTEXTUREIMPL_HPP
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class RenderTextureImplDefault : public RenderTextureImpl, GlResource
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
|
@ -58,7 +58,7 @@ public :
|
|||
////////////////////////////////////////////////////////////
|
||||
~RenderTextureImplDefault();
|
||||
|
||||
private :
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create the render texture implementation
|
||||
|
|
|
@ -1,147 +1,147 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTextureImplFBO::RenderTextureImplFBO() :
|
||||
m_frameBuffer(0),
|
||||
m_depthBuffer(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTextureImplFBO::~RenderTextureImplFBO()
|
||||
{
|
||||
ensureGlContext();
|
||||
|
||||
// Destroy the depth buffer
|
||||
if (m_depthBuffer)
|
||||
{
|
||||
GLuint depthBuffer = static_cast<GLuint>(m_depthBuffer);
|
||||
glCheck(GLEXT_glDeleteRenderbuffers(1, &depthBuffer));
|
||||
}
|
||||
|
||||
// Destroy the frame buffer
|
||||
if (m_frameBuffer)
|
||||
{
|
||||
GLuint frameBuffer = static_cast<GLuint>(m_frameBuffer);
|
||||
glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
|
||||
}
|
||||
|
||||
// Delete the context
|
||||
delete m_context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTextureImplFBO::isAvailable()
|
||||
{
|
||||
ensureGlContext();
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
priv::ensureExtensionsInit();
|
||||
|
||||
return GLEXT_framebuffer_object != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
|
||||
{
|
||||
// Create the context
|
||||
m_context = new Context;
|
||||
|
||||
// Create the framebuffer object
|
||||
GLuint frameBuffer = 0;
|
||||
glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer));
|
||||
m_frameBuffer = static_cast<unsigned int>(frameBuffer);
|
||||
if (!m_frameBuffer)
|
||||
{
|
||||
err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer));
|
||||
|
||||
// Create the depth buffer if requested
|
||||
if (depthBuffer)
|
||||
{
|
||||
GLuint depth = 0;
|
||||
glCheck(GLEXT_glGenRenderbuffers(1, &depth));
|
||||
m_depthBuffer = static_cast<unsigned int>(depth);
|
||||
if (!m_depthBuffer)
|
||||
{
|
||||
err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthBuffer));
|
||||
glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height));
|
||||
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthBuffer));
|
||||
}
|
||||
|
||||
// Link the texture to the frame buffer
|
||||
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTextureImplFBO::RenderTextureImplFBO() :
|
||||
m_frameBuffer(0),
|
||||
m_depthBuffer(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTextureImplFBO::~RenderTextureImplFBO()
|
||||
{
|
||||
ensureGlContext();
|
||||
|
||||
// Destroy the depth buffer
|
||||
if (m_depthBuffer)
|
||||
{
|
||||
GLuint depthBuffer = static_cast<GLuint>(m_depthBuffer);
|
||||
glCheck(GLEXT_glDeleteRenderbuffers(1, &depthBuffer));
|
||||
}
|
||||
|
||||
// Destroy the frame buffer
|
||||
if (m_frameBuffer)
|
||||
{
|
||||
GLuint frameBuffer = static_cast<GLuint>(m_frameBuffer);
|
||||
glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
|
||||
}
|
||||
|
||||
// Delete the context
|
||||
delete m_context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTextureImplFBO::isAvailable()
|
||||
{
|
||||
ensureGlContext();
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
priv::ensureExtensionsInit();
|
||||
|
||||
return GLEXT_framebuffer_object != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
|
||||
{
|
||||
// Create the context
|
||||
m_context = new Context;
|
||||
|
||||
// Create the framebuffer object
|
||||
GLuint frameBuffer = 0;
|
||||
glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer));
|
||||
m_frameBuffer = static_cast<unsigned int>(frameBuffer);
|
||||
if (!m_frameBuffer)
|
||||
{
|
||||
err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer));
|
||||
|
||||
// Create the depth buffer if requested
|
||||
if (depthBuffer)
|
||||
{
|
||||
GLuint depth = 0;
|
||||
glCheck(GLEXT_glGenRenderbuffers(1, &depth));
|
||||
m_depthBuffer = static_cast<unsigned int>(depth);
|
||||
if (!m_depthBuffer)
|
||||
{
|
||||
err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthBuffer));
|
||||
glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height));
|
||||
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthBuffer));
|
||||
}
|
||||
|
||||
// Link the texture to the frame buffer
|
||||
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));
|
||||
|
||||
// A final check, just to be sure...
|
||||
GLenum status = glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
|
||||
GLenum status = glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
|
||||
if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
|
||||
err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTextureImplFBO::activate(bool active)
|
||||
{
|
||||
return m_context->setActive(active);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTextureImplFBO::updateTexture(unsigned int)
|
||||
{
|
||||
glCheck(glFlush());
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
{
|
||||
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
|
||||
err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTextureImplFBO::activate(bool active)
|
||||
{
|
||||
return m_context->setActive(active);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderTextureImplFBO::updateTexture(unsigned int)
|
||||
{
|
||||
glCheck(glFlush());
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,115 +1,115 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_RENDERTEXTUREIMPLFBO_HPP
|
||||
#define SFML_RENDERTEXTUREIMPLFBO_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderTextureImpl.hpp>
|
||||
#include <SFML/Window/Context.hpp>
|
||||
#include <SFML/Window/GlResource.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Specialization of RenderTextureImpl using the
|
||||
/// FrameBuffer Object OpenGL extension
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class RenderTextureImplFBO : public RenderTextureImpl, GlResource
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTextureImplFBO();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~RenderTextureImplFBO();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check whether the system supports FBOs or not
|
||||
///
|
||||
/// \return True if FBO render textures are supported
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static bool isAvailable();
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create the render texture implementation
|
||||
///
|
||||
/// \param width Width of the texture to render to
|
||||
/// \param height Height of the texture to render to
|
||||
/// \param textureId OpenGL identifier of the target texture
|
||||
/// \param depthBuffer Is a depth buffer requested?
|
||||
///
|
||||
/// \return True if creation has been successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate or deactivate the render texture for rendering
|
||||
///
|
||||
/// \param active True to activate, false to deactivate
|
||||
///
|
||||
/// \return True on success, false on failure
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool activate(bool active);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Update the pixels of the target texture
|
||||
///
|
||||
/// \param textureId OpenGL identifier of the target texture
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void updateTexture(unsigned textureId);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Context* m_context; ///< Needs a separate OpenGL context for not messing up the other ones
|
||||
unsigned int m_frameBuffer; ///< OpenGL frame buffer object
|
||||
unsigned int m_depthBuffer; ///< Optional depth buffer attached to the frame buffer
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_RENDERTEXTUREIMPLFBO_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_RENDERTEXTUREIMPLFBO_HPP
|
||||
#define SFML_RENDERTEXTUREIMPLFBO_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderTextureImpl.hpp>
|
||||
#include <SFML/Window/Context.hpp>
|
||||
#include <SFML/Window/GlResource.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Specialization of RenderTextureImpl using the
|
||||
/// FrameBuffer Object OpenGL extension
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class RenderTextureImplFBO : public RenderTextureImpl, GlResource
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTextureImplFBO();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~RenderTextureImplFBO();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check whether the system supports FBOs or not
|
||||
///
|
||||
/// \return True if FBO render textures are supported
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static bool isAvailable();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create the render texture implementation
|
||||
///
|
||||
/// \param width Width of the texture to render to
|
||||
/// \param height Height of the texture to render to
|
||||
/// \param textureId OpenGL identifier of the target texture
|
||||
/// \param depthBuffer Is a depth buffer requested?
|
||||
///
|
||||
/// \return True if creation has been successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate or deactivate the render texture for rendering
|
||||
///
|
||||
/// \param active True to activate, false to deactivate
|
||||
///
|
||||
/// \return True on success, false on failure
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool activate(bool active);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Update the pixels of the target texture
|
||||
///
|
||||
/// \param textureId OpenGL identifier of the target texture
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void updateTexture(unsigned textureId);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Context* m_context; ///< Needs a separate OpenGL context for not messing up the other ones
|
||||
unsigned int m_frameBuffer; ///< OpenGL frame buffer object
|
||||
unsigned int m_depthBuffer; ///< Optional depth buffer attached to the frame buffer
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_RENDERTEXTUREIMPLFBO_HPP
|
||||
|
|
|
@ -1,117 +1,117 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderWindow::RenderWindow()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderWindow::RenderWindow(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings)
|
||||
{
|
||||
// Don't call the base class constructor because it contains virtual function calls
|
||||
create(mode, title, style, settings);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderWindow::RenderWindow(WindowHandle handle, const ContextSettings& settings)
|
||||
{
|
||||
// Don't call the base class constructor because it contains virtual function calls
|
||||
create(handle, settings);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderWindow::~RenderWindow()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderWindow::activate(bool active)
|
||||
{
|
||||
return setActive(active);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2u RenderWindow::getSize() const
|
||||
{
|
||||
return Window::getSize();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Image RenderWindow::capture() const
|
||||
{
|
||||
Image image;
|
||||
if (setActive())
|
||||
{
|
||||
int width = static_cast<int>(getSize().x);
|
||||
int height = static_cast<int>(getSize().y);
|
||||
|
||||
// copy rows one by one and flip them (OpenGL's origin is bottom while SFML's origin is top)
|
||||
std::vector<Uint8> pixels(width * height * 4);
|
||||
for (int i = 0; i < height; ++i)
|
||||
{
|
||||
Uint8* ptr = &pixels[i * width * 4];
|
||||
glCheck(glReadPixels(0, height - i - 1, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr));
|
||||
}
|
||||
|
||||
image.create(width, height, &pixels[0]);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderWindow::onCreate()
|
||||
{
|
||||
// Just initialize the render target part
|
||||
RenderTarget::initialize();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderWindow::onResize()
|
||||
{
|
||||
// Update the current view (recompute the viewport, which is stored in relative coordinates)
|
||||
setView(getView());
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderWindow::RenderWindow()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderWindow::RenderWindow(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings)
|
||||
{
|
||||
// Don't call the base class constructor because it contains virtual function calls
|
||||
create(mode, title, style, settings);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderWindow::RenderWindow(WindowHandle handle, const ContextSettings& settings)
|
||||
{
|
||||
// Don't call the base class constructor because it contains virtual function calls
|
||||
create(handle, settings);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderWindow::~RenderWindow()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderWindow::activate(bool active)
|
||||
{
|
||||
return setActive(active);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2u RenderWindow::getSize() const
|
||||
{
|
||||
return Window::getSize();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Image RenderWindow::capture() const
|
||||
{
|
||||
Image image;
|
||||
if (setActive())
|
||||
{
|
||||
int width = static_cast<int>(getSize().x);
|
||||
int height = static_cast<int>(getSize().y);
|
||||
|
||||
// copy rows one by one and flip them (OpenGL's origin is bottom while SFML's origin is top)
|
||||
std::vector<Uint8> pixels(width * height * 4);
|
||||
for (int i = 0; i < height; ++i)
|
||||
{
|
||||
Uint8* ptr = &pixels[i * width * 4];
|
||||
glCheck(glReadPixels(0, height - i - 1, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr));
|
||||
}
|
||||
|
||||
image.create(width, height, &pixels[0]);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderWindow::onCreate()
|
||||
{
|
||||
// Just initialize the render target part
|
||||
RenderTarget::initialize();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void RenderWindow::onResize()
|
||||
{
|
||||
// Update the current view (recompute the viewport, which is stored in relative coordinates)
|
||||
setView(getView());
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,305 +1,305 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Shape.hpp>
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Compute the normal of a segment
|
||||
sf::Vector2f computeNormal(const sf::Vector2f& p1, const sf::Vector2f& p2)
|
||||
{
|
||||
sf::Vector2f normal(p1.y - p2.y, p2.x - p1.x);
|
||||
float length = std::sqrt(normal.x * normal.x + normal.y * normal.y);
|
||||
if (length != 0.f)
|
||||
normal /= length;
|
||||
return normal;
|
||||
}
|
||||
|
||||
// Compute the dot product of two vectors
|
||||
float dotProduct(const sf::Vector2f& p1, const sf::Vector2f& p2)
|
||||
{
|
||||
return p1.x * p2.x + p1.y * p2.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Shape::~Shape()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setTexture(const Texture* texture, bool resetRect)
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
// Recompute the texture area if requested, or if there was no texture & rect before
|
||||
if (resetRect || (!m_texture && (m_textureRect == sf::IntRect())))
|
||||
setTextureRect(IntRect(0, 0, texture->getSize().x, texture->getSize().y));
|
||||
}
|
||||
|
||||
// Assign the new texture
|
||||
m_texture = texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Texture* Shape::getTexture() const
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setTextureRect(const IntRect& rect)
|
||||
{
|
||||
m_textureRect = rect;
|
||||
updateTexCoords();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const IntRect& Shape::getTextureRect() const
|
||||
{
|
||||
return m_textureRect;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setFillColor(const Color& color)
|
||||
{
|
||||
m_fillColor = color;
|
||||
updateFillColors();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color& Shape::getFillColor() const
|
||||
{
|
||||
return m_fillColor;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setOutlineColor(const Color& color)
|
||||
{
|
||||
m_outlineColor = color;
|
||||
updateOutlineColors();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color& Shape::getOutlineColor() const
|
||||
{
|
||||
return m_outlineColor;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setOutlineThickness(float thickness)
|
||||
{
|
||||
m_outlineThickness = thickness;
|
||||
update(); // recompute everything because the whole shape must be offset
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float Shape::getOutlineThickness() const
|
||||
{
|
||||
return m_outlineThickness;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Shape::getLocalBounds() const
|
||||
{
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Shape::getGlobalBounds() const
|
||||
{
|
||||
return getTransform().transformRect(getLocalBounds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Shape::Shape() :
|
||||
m_texture (NULL),
|
||||
m_textureRect (),
|
||||
m_fillColor (255, 255, 255),
|
||||
m_outlineColor (255, 255, 255),
|
||||
m_outlineThickness(0),
|
||||
m_vertices (TrianglesFan),
|
||||
m_outlineVertices (TrianglesStrip),
|
||||
m_insideBounds (),
|
||||
m_bounds ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::update()
|
||||
{
|
||||
// Get the total number of points of the shape
|
||||
unsigned int count = getPointCount();
|
||||
if (count < 3)
|
||||
{
|
||||
m_vertices.resize(0);
|
||||
m_outlineVertices.resize(0);
|
||||
return;
|
||||
}
|
||||
|
||||
m_vertices.resize(count + 2); // + 2 for center and repeated first point
|
||||
|
||||
// Position
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
m_vertices[i + 1].position = getPoint(i);
|
||||
m_vertices[count + 1].position = m_vertices[1].position;
|
||||
|
||||
// Update the bounding rectangle
|
||||
m_vertices[0] = m_vertices[1]; // so that the result of getBounds() is correct
|
||||
m_insideBounds = m_vertices.getBounds();
|
||||
|
||||
// Compute the center and make it the first vertex
|
||||
m_vertices[0].position.x = m_insideBounds.left + m_insideBounds.width / 2;
|
||||
m_vertices[0].position.y = m_insideBounds.top + m_insideBounds.height / 2;
|
||||
|
||||
// Color
|
||||
updateFillColors();
|
||||
|
||||
// Texture coordinates
|
||||
updateTexCoords();
|
||||
|
||||
// Outline
|
||||
updateOutline();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::draw(RenderTarget& target, RenderStates states) const
|
||||
{
|
||||
states.transform *= getTransform();
|
||||
|
||||
// Render the inside
|
||||
states.texture = m_texture;
|
||||
target.draw(m_vertices, states);
|
||||
|
||||
// Render the outline
|
||||
if (m_outlineThickness != 0)
|
||||
{
|
||||
states.texture = NULL;
|
||||
target.draw(m_outlineVertices, states);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::updateFillColors()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
|
||||
m_vertices[i].color = m_fillColor;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::updateTexCoords()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
|
||||
{
|
||||
float xratio = m_insideBounds.width > 0 ? (m_vertices[i].position.x - m_insideBounds.left) / m_insideBounds.width : 0;
|
||||
float yratio = m_insideBounds.height > 0 ? (m_vertices[i].position.y - m_insideBounds.top) / m_insideBounds.height : 0;
|
||||
m_vertices[i].texCoords.x = m_textureRect.left + m_textureRect.width * xratio;
|
||||
m_vertices[i].texCoords.y = m_textureRect.top + m_textureRect.height * yratio;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::updateOutline()
|
||||
{
|
||||
unsigned int count = m_vertices.getVertexCount() - 2;
|
||||
m_outlineVertices.resize((count + 1) * 2);
|
||||
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
unsigned int index = i + 1;
|
||||
|
||||
// Get the two segments shared by the current point
|
||||
Vector2f p0 = (i == 0) ? m_vertices[count].position : m_vertices[index - 1].position;
|
||||
Vector2f p1 = m_vertices[index].position;
|
||||
Vector2f p2 = m_vertices[index + 1].position;
|
||||
|
||||
// Compute their normal
|
||||
Vector2f n1 = computeNormal(p0, p1);
|
||||
Vector2f n2 = computeNormal(p1, p2);
|
||||
|
||||
// Make sure that the normals point towards the outside of the shape
|
||||
// (this depends on the order in which the points were defined)
|
||||
if (dotProduct(n1, m_vertices[0].position - p1) > 0)
|
||||
n1 = -n1;
|
||||
if (dotProduct(n2, m_vertices[0].position - p1) > 0)
|
||||
n2 = -n2;
|
||||
|
||||
// Combine them to get the extrusion direction
|
||||
float factor = 1.f + (n1.x * n2.x + n1.y * n2.y);
|
||||
Vector2f normal = (n1 + n2) / factor;
|
||||
|
||||
// Update the outline points
|
||||
m_outlineVertices[i * 2 + 0].position = p1;
|
||||
m_outlineVertices[i * 2 + 1].position = p1 + normal * m_outlineThickness;
|
||||
}
|
||||
|
||||
// Duplicate the first point at the end, to close the outline
|
||||
m_outlineVertices[count * 2 + 0].position = m_outlineVertices[0].position;
|
||||
m_outlineVertices[count * 2 + 1].position = m_outlineVertices[1].position;
|
||||
|
||||
// Update outline colors
|
||||
updateOutlineColors();
|
||||
|
||||
// Update the shape's bounds
|
||||
m_bounds = m_outlineVertices.getBounds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::updateOutlineColors()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_outlineVertices.getVertexCount(); ++i)
|
||||
m_outlineVertices[i].color = m_outlineColor;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Shape.hpp>
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Compute the normal of a segment
|
||||
sf::Vector2f computeNormal(const sf::Vector2f& p1, const sf::Vector2f& p2)
|
||||
{
|
||||
sf::Vector2f normal(p1.y - p2.y, p2.x - p1.x);
|
||||
float length = std::sqrt(normal.x * normal.x + normal.y * normal.y);
|
||||
if (length != 0.f)
|
||||
normal /= length;
|
||||
return normal;
|
||||
}
|
||||
|
||||
// Compute the dot product of two vectors
|
||||
float dotProduct(const sf::Vector2f& p1, const sf::Vector2f& p2)
|
||||
{
|
||||
return p1.x * p2.x + p1.y * p2.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Shape::~Shape()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setTexture(const Texture* texture, bool resetRect)
|
||||
{
|
||||
if (texture)
|
||||
{
|
||||
// Recompute the texture area if requested, or if there was no texture & rect before
|
||||
if (resetRect || (!m_texture && (m_textureRect == sf::IntRect())))
|
||||
setTextureRect(IntRect(0, 0, texture->getSize().x, texture->getSize().y));
|
||||
}
|
||||
|
||||
// Assign the new texture
|
||||
m_texture = texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Texture* Shape::getTexture() const
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setTextureRect(const IntRect& rect)
|
||||
{
|
||||
m_textureRect = rect;
|
||||
updateTexCoords();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const IntRect& Shape::getTextureRect() const
|
||||
{
|
||||
return m_textureRect;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setFillColor(const Color& color)
|
||||
{
|
||||
m_fillColor = color;
|
||||
updateFillColors();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color& Shape::getFillColor() const
|
||||
{
|
||||
return m_fillColor;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setOutlineColor(const Color& color)
|
||||
{
|
||||
m_outlineColor = color;
|
||||
updateOutlineColors();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color& Shape::getOutlineColor() const
|
||||
{
|
||||
return m_outlineColor;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::setOutlineThickness(float thickness)
|
||||
{
|
||||
m_outlineThickness = thickness;
|
||||
update(); // recompute everything because the whole shape must be offset
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float Shape::getOutlineThickness() const
|
||||
{
|
||||
return m_outlineThickness;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Shape::getLocalBounds() const
|
||||
{
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Shape::getGlobalBounds() const
|
||||
{
|
||||
return getTransform().transformRect(getLocalBounds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Shape::Shape() :
|
||||
m_texture (NULL),
|
||||
m_textureRect (),
|
||||
m_fillColor (255, 255, 255),
|
||||
m_outlineColor (255, 255, 255),
|
||||
m_outlineThickness(0),
|
||||
m_vertices (TrianglesFan),
|
||||
m_outlineVertices (TrianglesStrip),
|
||||
m_insideBounds (),
|
||||
m_bounds ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::update()
|
||||
{
|
||||
// Get the total number of points of the shape
|
||||
unsigned int count = getPointCount();
|
||||
if (count < 3)
|
||||
{
|
||||
m_vertices.resize(0);
|
||||
m_outlineVertices.resize(0);
|
||||
return;
|
||||
}
|
||||
|
||||
m_vertices.resize(count + 2); // + 2 for center and repeated first point
|
||||
|
||||
// Position
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
m_vertices[i + 1].position = getPoint(i);
|
||||
m_vertices[count + 1].position = m_vertices[1].position;
|
||||
|
||||
// Update the bounding rectangle
|
||||
m_vertices[0] = m_vertices[1]; // so that the result of getBounds() is correct
|
||||
m_insideBounds = m_vertices.getBounds();
|
||||
|
||||
// Compute the center and make it the first vertex
|
||||
m_vertices[0].position.x = m_insideBounds.left + m_insideBounds.width / 2;
|
||||
m_vertices[0].position.y = m_insideBounds.top + m_insideBounds.height / 2;
|
||||
|
||||
// Color
|
||||
updateFillColors();
|
||||
|
||||
// Texture coordinates
|
||||
updateTexCoords();
|
||||
|
||||
// Outline
|
||||
updateOutline();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::draw(RenderTarget& target, RenderStates states) const
|
||||
{
|
||||
states.transform *= getTransform();
|
||||
|
||||
// Render the inside
|
||||
states.texture = m_texture;
|
||||
target.draw(m_vertices, states);
|
||||
|
||||
// Render the outline
|
||||
if (m_outlineThickness != 0)
|
||||
{
|
||||
states.texture = NULL;
|
||||
target.draw(m_outlineVertices, states);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::updateFillColors()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
|
||||
m_vertices[i].color = m_fillColor;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::updateTexCoords()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
|
||||
{
|
||||
float xratio = m_insideBounds.width > 0 ? (m_vertices[i].position.x - m_insideBounds.left) / m_insideBounds.width : 0;
|
||||
float yratio = m_insideBounds.height > 0 ? (m_vertices[i].position.y - m_insideBounds.top) / m_insideBounds.height : 0;
|
||||
m_vertices[i].texCoords.x = m_textureRect.left + m_textureRect.width * xratio;
|
||||
m_vertices[i].texCoords.y = m_textureRect.top + m_textureRect.height * yratio;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::updateOutline()
|
||||
{
|
||||
unsigned int count = m_vertices.getVertexCount() - 2;
|
||||
m_outlineVertices.resize((count + 1) * 2);
|
||||
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
unsigned int index = i + 1;
|
||||
|
||||
// Get the two segments shared by the current point
|
||||
Vector2f p0 = (i == 0) ? m_vertices[count].position : m_vertices[index - 1].position;
|
||||
Vector2f p1 = m_vertices[index].position;
|
||||
Vector2f p2 = m_vertices[index + 1].position;
|
||||
|
||||
// Compute their normal
|
||||
Vector2f n1 = computeNormal(p0, p1);
|
||||
Vector2f n2 = computeNormal(p1, p2);
|
||||
|
||||
// Make sure that the normals point towards the outside of the shape
|
||||
// (this depends on the order in which the points were defined)
|
||||
if (dotProduct(n1, m_vertices[0].position - p1) > 0)
|
||||
n1 = -n1;
|
||||
if (dotProduct(n2, m_vertices[0].position - p1) > 0)
|
||||
n2 = -n2;
|
||||
|
||||
// Combine them to get the extrusion direction
|
||||
float factor = 1.f + (n1.x * n2.x + n1.y * n2.y);
|
||||
Vector2f normal = (n1 + n2) / factor;
|
||||
|
||||
// Update the outline points
|
||||
m_outlineVertices[i * 2 + 0].position = p1;
|
||||
m_outlineVertices[i * 2 + 1].position = p1 + normal * m_outlineThickness;
|
||||
}
|
||||
|
||||
// Duplicate the first point at the end, to close the outline
|
||||
m_outlineVertices[count * 2 + 0].position = m_outlineVertices[0].position;
|
||||
m_outlineVertices[count * 2 + 1].position = m_outlineVertices[1].position;
|
||||
|
||||
// Update outline colors
|
||||
updateOutlineColors();
|
||||
|
||||
// Update the shape's bounds
|
||||
m_bounds = m_outlineVertices.getBounds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shape::updateOutlineColors()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_outlineVertices.getVertexCount(); ++i)
|
||||
m_outlineVertices[i].color = m_outlineColor;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,174 +1,174 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Sprite.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Sprite::Sprite() :
|
||||
m_texture (NULL),
|
||||
m_textureRect()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sprite::Sprite(const Texture& texture) :
|
||||
m_texture (NULL),
|
||||
m_textureRect()
|
||||
{
|
||||
setTexture(texture);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sprite::Sprite(const Texture& texture, const IntRect& rectangle) :
|
||||
m_texture (NULL),
|
||||
m_textureRect()
|
||||
{
|
||||
setTexture(texture);
|
||||
setTextureRect(rectangle);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::setTexture(const Texture& texture, bool resetRect)
|
||||
{
|
||||
// Recompute the texture area if requested, or if there was no valid texture & rect before
|
||||
if (resetRect || (!m_texture && (m_textureRect == sf::IntRect())))
|
||||
setTextureRect(IntRect(0, 0, texture.getSize().x, texture.getSize().y));
|
||||
|
||||
// Assign the new texture
|
||||
m_texture = &texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::setTextureRect(const IntRect& rectangle)
|
||||
{
|
||||
if (rectangle != m_textureRect)
|
||||
{
|
||||
m_textureRect = rectangle;
|
||||
updatePositions();
|
||||
updateTexCoords();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::setColor(const Color& color)
|
||||
{
|
||||
// Update the vertices' color
|
||||
m_vertices[0].color = color;
|
||||
m_vertices[1].color = color;
|
||||
m_vertices[2].color = color;
|
||||
m_vertices[3].color = color;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Texture* Sprite::getTexture() const
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const IntRect& Sprite::getTextureRect() const
|
||||
{
|
||||
return m_textureRect;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color& Sprite::getColor() const
|
||||
{
|
||||
return m_vertices[0].color;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Sprite::getLocalBounds() const
|
||||
{
|
||||
float width = static_cast<float>(std::abs(m_textureRect.width));
|
||||
float height = static_cast<float>(std::abs(m_textureRect.height));
|
||||
|
||||
return FloatRect(0.f, 0.f, width, height);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Sprite::getGlobalBounds() const
|
||||
{
|
||||
return getTransform().transformRect(getLocalBounds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::draw(RenderTarget& target, RenderStates states) const
|
||||
{
|
||||
if (m_texture)
|
||||
{
|
||||
states.transform *= getTransform();
|
||||
states.texture = m_texture;
|
||||
target.draw(m_vertices, 4, TrianglesStrip, states);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::updatePositions()
|
||||
{
|
||||
FloatRect bounds = getLocalBounds();
|
||||
|
||||
m_vertices[0].position = Vector2f(0, 0);
|
||||
m_vertices[1].position = Vector2f(0, bounds.height);
|
||||
m_vertices[2].position = Vector2f(bounds.width, 0);
|
||||
m_vertices[3].position = Vector2f(bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::updateTexCoords()
|
||||
{
|
||||
float left = static_cast<float>(m_textureRect.left);
|
||||
float right = left + m_textureRect.width;
|
||||
float top = static_cast<float>(m_textureRect.top);
|
||||
float bottom = top + m_textureRect.height;
|
||||
|
||||
m_vertices[0].texCoords = Vector2f(left, top);
|
||||
m_vertices[1].texCoords = Vector2f(left, bottom);
|
||||
m_vertices[2].texCoords = Vector2f(right, top);
|
||||
m_vertices[3].texCoords = Vector2f(right, bottom);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Sprite.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Sprite::Sprite() :
|
||||
m_texture (NULL),
|
||||
m_textureRect()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sprite::Sprite(const Texture& texture) :
|
||||
m_texture (NULL),
|
||||
m_textureRect()
|
||||
{
|
||||
setTexture(texture);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Sprite::Sprite(const Texture& texture, const IntRect& rectangle) :
|
||||
m_texture (NULL),
|
||||
m_textureRect()
|
||||
{
|
||||
setTexture(texture);
|
||||
setTextureRect(rectangle);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::setTexture(const Texture& texture, bool resetRect)
|
||||
{
|
||||
// Recompute the texture area if requested, or if there was no valid texture & rect before
|
||||
if (resetRect || (!m_texture && (m_textureRect == sf::IntRect())))
|
||||
setTextureRect(IntRect(0, 0, texture.getSize().x, texture.getSize().y));
|
||||
|
||||
// Assign the new texture
|
||||
m_texture = &texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::setTextureRect(const IntRect& rectangle)
|
||||
{
|
||||
if (rectangle != m_textureRect)
|
||||
{
|
||||
m_textureRect = rectangle;
|
||||
updatePositions();
|
||||
updateTexCoords();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::setColor(const Color& color)
|
||||
{
|
||||
// Update the vertices' color
|
||||
m_vertices[0].color = color;
|
||||
m_vertices[1].color = color;
|
||||
m_vertices[2].color = color;
|
||||
m_vertices[3].color = color;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Texture* Sprite::getTexture() const
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const IntRect& Sprite::getTextureRect() const
|
||||
{
|
||||
return m_textureRect;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color& Sprite::getColor() const
|
||||
{
|
||||
return m_vertices[0].color;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Sprite::getLocalBounds() const
|
||||
{
|
||||
float width = static_cast<float>(std::abs(m_textureRect.width));
|
||||
float height = static_cast<float>(std::abs(m_textureRect.height));
|
||||
|
||||
return FloatRect(0.f, 0.f, width, height);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Sprite::getGlobalBounds() const
|
||||
{
|
||||
return getTransform().transformRect(getLocalBounds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::draw(RenderTarget& target, RenderStates states) const
|
||||
{
|
||||
if (m_texture)
|
||||
{
|
||||
states.transform *= getTransform();
|
||||
states.texture = m_texture;
|
||||
target.draw(m_vertices, 4, TrianglesStrip, states);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::updatePositions()
|
||||
{
|
||||
FloatRect bounds = getLocalBounds();
|
||||
|
||||
m_vertices[0].position = Vector2f(0, 0);
|
||||
m_vertices[1].position = Vector2f(0, bounds.height);
|
||||
m_vertices[2].position = Vector2f(bounds.width, 0);
|
||||
m_vertices[3].position = Vector2f(bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Sprite::updateTexCoords()
|
||||
{
|
||||
float left = static_cast<float>(m_textureRect.left);
|
||||
float right = left + m_textureRect.width;
|
||||
float top = static_cast<float>(m_textureRect.top);
|
||||
float bottom = top + m_textureRect.height;
|
||||
|
||||
m_vertices[0].texCoords = Vector2f(left, top);
|
||||
m_vertices[1].texCoords = Vector2f(left, bottom);
|
||||
m_vertices[2].texCoords = Vector2f(right, top);
|
||||
m_vertices[3].texCoords = Vector2f(right, bottom);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,411 +1,411 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Text.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Text::Text() :
|
||||
m_string (),
|
||||
m_font (NULL),
|
||||
m_characterSize (30),
|
||||
m_style (Regular),
|
||||
m_color (255, 255, 255),
|
||||
m_vertices (Triangles),
|
||||
m_bounds (),
|
||||
m_geometryNeedUpdate(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Text::Text(const String& string, const Font& font, unsigned int characterSize) :
|
||||
m_string (string),
|
||||
m_font (&font),
|
||||
m_characterSize (characterSize),
|
||||
m_style (Regular),
|
||||
m_color (255, 255, 255),
|
||||
m_vertices (Triangles),
|
||||
m_bounds (),
|
||||
m_geometryNeedUpdate(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setString(const String& string)
|
||||
{
|
||||
if (m_string != string)
|
||||
{
|
||||
m_string = string;
|
||||
m_geometryNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setFont(const Font& font)
|
||||
{
|
||||
if (m_font != &font)
|
||||
{
|
||||
m_font = &font;
|
||||
m_geometryNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setCharacterSize(unsigned int size)
|
||||
{
|
||||
if (m_characterSize != size)
|
||||
{
|
||||
m_characterSize = size;
|
||||
m_geometryNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setStyle(Uint32 style)
|
||||
{
|
||||
if (m_style != style)
|
||||
{
|
||||
m_style = style;
|
||||
m_geometryNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setColor(const Color& color)
|
||||
{
|
||||
if (color != m_color)
|
||||
{
|
||||
m_color = color;
|
||||
|
||||
// Change vertex colors directly, no need to update whole geometry
|
||||
// (if geometry is updated anyway, we can skip this step)
|
||||
if (!m_geometryNeedUpdate)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
|
||||
m_vertices[i].color = m_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const String& Text::getString() const
|
||||
{
|
||||
return m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Font* Text::getFont() const
|
||||
{
|
||||
return m_font;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Text::getCharacterSize() const
|
||||
{
|
||||
return m_characterSize;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 Text::getStyle() const
|
||||
{
|
||||
return m_style;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color& Text::getColor() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2f Text::findCharacterPos(std::size_t index) const
|
||||
{
|
||||
// Make sure that we have a valid font
|
||||
if (!m_font)
|
||||
return Vector2f();
|
||||
|
||||
// Adjust the index if it's out of range
|
||||
if (index > m_string.getSize())
|
||||
index = m_string.getSize();
|
||||
|
||||
// Precompute the variables needed by the algorithm
|
||||
bool bold = (m_style & Bold) != 0;
|
||||
float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
|
||||
float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
|
||||
|
||||
// Compute the position
|
||||
Vector2f position;
|
||||
Uint32 prevChar = 0;
|
||||
for (std::size_t i = 0; i < index; ++i)
|
||||
{
|
||||
Uint32 curChar = m_string[i];
|
||||
|
||||
// Apply the kerning offset
|
||||
position.x += static_cast<float>(m_font->getKerning(prevChar, curChar, m_characterSize));
|
||||
prevChar = curChar;
|
||||
|
||||
// Handle special characters
|
||||
switch (curChar)
|
||||
{
|
||||
case ' ' : position.x += hspace; continue;
|
||||
case '\t' : position.x += hspace * 4; continue;
|
||||
case '\n' : position.y += vspace; position.x = 0; continue;
|
||||
}
|
||||
|
||||
// For regular characters, add the advance offset of the glyph
|
||||
position.x += static_cast<float>(m_font->getGlyph(curChar, m_characterSize, bold).advance);
|
||||
}
|
||||
|
||||
// Transform the position to global coordinates
|
||||
position = getTransform().transformPoint(position);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Text::getLocalBounds() const
|
||||
{
|
||||
ensureGeometryUpdate();
|
||||
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Text::getGlobalBounds() const
|
||||
{
|
||||
return getTransform().transformRect(getLocalBounds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::draw(RenderTarget& target, RenderStates states) const
|
||||
{
|
||||
if (m_font)
|
||||
{
|
||||
ensureGeometryUpdate();
|
||||
|
||||
states.transform *= getTransform();
|
||||
states.texture = &m_font->getTexture(m_characterSize);
|
||||
target.draw(m_vertices, states);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::ensureGeometryUpdate() const
|
||||
{
|
||||
// Do nothing, if geometry has not changed
|
||||
if (!m_geometryNeedUpdate)
|
||||
return;
|
||||
|
||||
// Mark geometry as updated
|
||||
m_geometryNeedUpdate = false;
|
||||
|
||||
// Clear the previous geometry
|
||||
m_vertices.clear();
|
||||
m_bounds = FloatRect();
|
||||
|
||||
// No font: nothing to draw
|
||||
if (!m_font)
|
||||
return;
|
||||
|
||||
// No text: nothing to draw
|
||||
if (m_string.isEmpty())
|
||||
return;
|
||||
|
||||
// Compute values related to the text style
|
||||
bool bold = (m_style & Bold) != 0;
|
||||
bool underlined = (m_style & Underlined) != 0;
|
||||
bool strikeThrough = (m_style & StrikeThrough) != 0;
|
||||
float italic = (m_style & Italic) ? 0.208f : 0.f; // 12 degrees
|
||||
float underlineOffset = m_font->getUnderlinePosition(m_characterSize);
|
||||
float underlineThickness = m_font->getUnderlineThickness(m_characterSize);
|
||||
|
||||
// Compute the location of the strike through dynamically
|
||||
// We use the center point of the lowercase 'x' glyph as the reference
|
||||
// We reuse the underline thickness as the thickness of the strike through as well
|
||||
FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, bold).bounds;
|
||||
float strikeThroughOffset = xBounds.top + xBounds.height / 2.f;
|
||||
|
||||
// Precompute the variables needed by the algorithm
|
||||
float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
|
||||
float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
|
||||
float x = 0.f;
|
||||
float y = static_cast<float>(m_characterSize);
|
||||
|
||||
// Create one quad for each character
|
||||
float minX = static_cast<float>(m_characterSize);
|
||||
float minY = static_cast<float>(m_characterSize);
|
||||
float maxX = 0.f;
|
||||
float maxY = 0.f;
|
||||
Uint32 prevChar = 0;
|
||||
for (std::size_t i = 0; i < m_string.getSize(); ++i)
|
||||
{
|
||||
Uint32 curChar = m_string[i];
|
||||
|
||||
// Apply the kerning offset
|
||||
x += static_cast<float>(m_font->getKerning(prevChar, curChar, m_characterSize));
|
||||
prevChar = curChar;
|
||||
|
||||
// If we're using the underlined style and there's a new line, draw a line
|
||||
if (underlined && (curChar == L'\n'))
|
||||
{
|
||||
float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f);
|
||||
float bottom = top + std::floor(underlineThickness + 0.5f);
|
||||
|
||||
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
|
||||
}
|
||||
|
||||
// If we're using the strike through style and there's a new line, draw a line across all characters
|
||||
if (strikeThrough && (curChar == L'\n'))
|
||||
{
|
||||
float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f);
|
||||
float bottom = top + std::floor(underlineThickness + 0.5f);
|
||||
|
||||
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
|
||||
}
|
||||
|
||||
// Handle special characters
|
||||
if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n'))
|
||||
{
|
||||
// Update the current bounds (min coordinates)
|
||||
minX = std::min(minX, x);
|
||||
minY = std::min(minY, y);
|
||||
|
||||
switch (curChar)
|
||||
{
|
||||
case ' ' : x += hspace; break;
|
||||
case '\t' : x += hspace * 4; break;
|
||||
case '\n' : y += vspace; x = 0; break;
|
||||
}
|
||||
|
||||
// Update the current bounds (max coordinates)
|
||||
maxX = std::max(maxX, x);
|
||||
maxY = std::max(maxY, y);
|
||||
|
||||
// Next glyph, no need to create a quad for whitespace
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract the current glyph's description
|
||||
const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, bold);
|
||||
|
||||
float left = glyph.bounds.left;
|
||||
float top = glyph.bounds.top;
|
||||
float right = glyph.bounds.left + glyph.bounds.width;
|
||||
float bottom = glyph.bounds.top + glyph.bounds.height;
|
||||
|
||||
float u1 = static_cast<float>(glyph.textureRect.left);
|
||||
float v1 = static_cast<float>(glyph.textureRect.top);
|
||||
float u2 = static_cast<float>(glyph.textureRect.left + glyph.textureRect.width);
|
||||
float v2 = static_cast<float>(glyph.textureRect.top + glyph.textureRect.height);
|
||||
|
||||
// Add a quad for the current character
|
||||
m_vertices.append(Vertex(Vector2f(x + left - italic * top, y + top), m_color, Vector2f(u1, v1)));
|
||||
m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1)));
|
||||
m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2)));
|
||||
m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2)));
|
||||
m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1)));
|
||||
m_vertices.append(Vertex(Vector2f(x + right - italic * bottom, y + bottom), m_color, Vector2f(u2, v2)));
|
||||
|
||||
// Update the current bounds
|
||||
minX = std::min(minX, x + left - italic * bottom);
|
||||
maxX = std::max(maxX, x + right - italic * top);
|
||||
minY = std::min(minY, y + top);
|
||||
maxY = std::max(maxY, y + bottom);
|
||||
|
||||
// Advance to the next character
|
||||
x += glyph.advance;
|
||||
}
|
||||
|
||||
// If we're using the underlined style, add the last line
|
||||
if (underlined)
|
||||
{
|
||||
float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f);
|
||||
float bottom = top + std::floor(underlineThickness + 0.5f);
|
||||
|
||||
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
|
||||
}
|
||||
|
||||
// If we're using the strike through style, add the last line across all characters
|
||||
if (strikeThrough)
|
||||
{
|
||||
float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f);
|
||||
float bottom = top + std::floor(underlineThickness + 0.5f);
|
||||
|
||||
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
|
||||
}
|
||||
|
||||
// Update the bounding rectangle
|
||||
m_bounds.left = minX;
|
||||
m_bounds.top = minY;
|
||||
m_bounds.width = maxX - minX;
|
||||
m_bounds.height = maxY - minY;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Text.hpp>
|
||||
#include <SFML/Graphics/Texture.hpp>
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Text::Text() :
|
||||
m_string (),
|
||||
m_font (NULL),
|
||||
m_characterSize (30),
|
||||
m_style (Regular),
|
||||
m_color (255, 255, 255),
|
||||
m_vertices (Triangles),
|
||||
m_bounds (),
|
||||
m_geometryNeedUpdate(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Text::Text(const String& string, const Font& font, unsigned int characterSize) :
|
||||
m_string (string),
|
||||
m_font (&font),
|
||||
m_characterSize (characterSize),
|
||||
m_style (Regular),
|
||||
m_color (255, 255, 255),
|
||||
m_vertices (Triangles),
|
||||
m_bounds (),
|
||||
m_geometryNeedUpdate(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setString(const String& string)
|
||||
{
|
||||
if (m_string != string)
|
||||
{
|
||||
m_string = string;
|
||||
m_geometryNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setFont(const Font& font)
|
||||
{
|
||||
if (m_font != &font)
|
||||
{
|
||||
m_font = &font;
|
||||
m_geometryNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setCharacterSize(unsigned int size)
|
||||
{
|
||||
if (m_characterSize != size)
|
||||
{
|
||||
m_characterSize = size;
|
||||
m_geometryNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setStyle(Uint32 style)
|
||||
{
|
||||
if (m_style != style)
|
||||
{
|
||||
m_style = style;
|
||||
m_geometryNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::setColor(const Color& color)
|
||||
{
|
||||
if (color != m_color)
|
||||
{
|
||||
m_color = color;
|
||||
|
||||
// Change vertex colors directly, no need to update whole geometry
|
||||
// (if geometry is updated anyway, we can skip this step)
|
||||
if (!m_geometryNeedUpdate)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
|
||||
m_vertices[i].color = m_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const String& Text::getString() const
|
||||
{
|
||||
return m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Font* Text::getFont() const
|
||||
{
|
||||
return m_font;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Text::getCharacterSize() const
|
||||
{
|
||||
return m_characterSize;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 Text::getStyle() const
|
||||
{
|
||||
return m_style;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Color& Text::getColor() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Vector2f Text::findCharacterPos(std::size_t index) const
|
||||
{
|
||||
// Make sure that we have a valid font
|
||||
if (!m_font)
|
||||
return Vector2f();
|
||||
|
||||
// Adjust the index if it's out of range
|
||||
if (index > m_string.getSize())
|
||||
index = m_string.getSize();
|
||||
|
||||
// Precompute the variables needed by the algorithm
|
||||
bool bold = (m_style & Bold) != 0;
|
||||
float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
|
||||
float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
|
||||
|
||||
// Compute the position
|
||||
Vector2f position;
|
||||
Uint32 prevChar = 0;
|
||||
for (std::size_t i = 0; i < index; ++i)
|
||||
{
|
||||
Uint32 curChar = m_string[i];
|
||||
|
||||
// Apply the kerning offset
|
||||
position.x += static_cast<float>(m_font->getKerning(prevChar, curChar, m_characterSize));
|
||||
prevChar = curChar;
|
||||
|
||||
// Handle special characters
|
||||
switch (curChar)
|
||||
{
|
||||
case ' ': position.x += hspace; continue;
|
||||
case '\t': position.x += hspace * 4; continue;
|
||||
case '\n': position.y += vspace; position.x = 0; continue;
|
||||
}
|
||||
|
||||
// For regular characters, add the advance offset of the glyph
|
||||
position.x += static_cast<float>(m_font->getGlyph(curChar, m_characterSize, bold).advance);
|
||||
}
|
||||
|
||||
// Transform the position to global coordinates
|
||||
position = getTransform().transformPoint(position);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Text::getLocalBounds() const
|
||||
{
|
||||
ensureGeometryUpdate();
|
||||
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
FloatRect Text::getGlobalBounds() const
|
||||
{
|
||||
return getTransform().transformRect(getLocalBounds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::draw(RenderTarget& target, RenderStates states) const
|
||||
{
|
||||
if (m_font)
|
||||
{
|
||||
ensureGeometryUpdate();
|
||||
|
||||
states.transform *= getTransform();
|
||||
states.texture = &m_font->getTexture(m_characterSize);
|
||||
target.draw(m_vertices, states);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::ensureGeometryUpdate() const
|
||||
{
|
||||
// Do nothing, if geometry has not changed
|
||||
if (!m_geometryNeedUpdate)
|
||||
return;
|
||||
|
||||
// Mark geometry as updated
|
||||
m_geometryNeedUpdate = false;
|
||||
|
||||
// Clear the previous geometry
|
||||
m_vertices.clear();
|
||||
m_bounds = FloatRect();
|
||||
|
||||
// No font: nothing to draw
|
||||
if (!m_font)
|
||||
return;
|
||||
|
||||
// No text: nothing to draw
|
||||
if (m_string.isEmpty())
|
||||
return;
|
||||
|
||||
// Compute values related to the text style
|
||||
bool bold = (m_style & Bold) != 0;
|
||||
bool underlined = (m_style & Underlined) != 0;
|
||||
bool strikeThrough = (m_style & StrikeThrough) != 0;
|
||||
float italic = (m_style & Italic) ? 0.208f : 0.f; // 12 degrees
|
||||
float underlineOffset = m_font->getUnderlinePosition(m_characterSize);
|
||||
float underlineThickness = m_font->getUnderlineThickness(m_characterSize);
|
||||
|
||||
// Compute the location of the strike through dynamically
|
||||
// We use the center point of the lowercase 'x' glyph as the reference
|
||||
// We reuse the underline thickness as the thickness of the strike through as well
|
||||
FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, bold).bounds;
|
||||
float strikeThroughOffset = xBounds.top + xBounds.height / 2.f;
|
||||
|
||||
// Precompute the variables needed by the algorithm
|
||||
float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
|
||||
float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
|
||||
float x = 0.f;
|
||||
float y = static_cast<float>(m_characterSize);
|
||||
|
||||
// Create one quad for each character
|
||||
float minX = static_cast<float>(m_characterSize);
|
||||
float minY = static_cast<float>(m_characterSize);
|
||||
float maxX = 0.f;
|
||||
float maxY = 0.f;
|
||||
Uint32 prevChar = 0;
|
||||
for (std::size_t i = 0; i < m_string.getSize(); ++i)
|
||||
{
|
||||
Uint32 curChar = m_string[i];
|
||||
|
||||
// Apply the kerning offset
|
||||
x += static_cast<float>(m_font->getKerning(prevChar, curChar, m_characterSize));
|
||||
prevChar = curChar;
|
||||
|
||||
// If we're using the underlined style and there's a new line, draw a line
|
||||
if (underlined && (curChar == L'\n'))
|
||||
{
|
||||
float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f);
|
||||
float bottom = top + std::floor(underlineThickness + 0.5f);
|
||||
|
||||
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
|
||||
}
|
||||
|
||||
// If we're using the strike through style and there's a new line, draw a line across all characters
|
||||
if (strikeThrough && (curChar == L'\n'))
|
||||
{
|
||||
float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f);
|
||||
float bottom = top + std::floor(underlineThickness + 0.5f);
|
||||
|
||||
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
|
||||
}
|
||||
|
||||
// Handle special characters
|
||||
if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n'))
|
||||
{
|
||||
// Update the current bounds (min coordinates)
|
||||
minX = std::min(minX, x);
|
||||
minY = std::min(minY, y);
|
||||
|
||||
switch (curChar)
|
||||
{
|
||||
case ' ': x += hspace; break;
|
||||
case '\t': x += hspace * 4; break;
|
||||
case '\n': y += vspace; x = 0; break;
|
||||
}
|
||||
|
||||
// Update the current bounds (max coordinates)
|
||||
maxX = std::max(maxX, x);
|
||||
maxY = std::max(maxY, y);
|
||||
|
||||
// Next glyph, no need to create a quad for whitespace
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract the current glyph's description
|
||||
const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, bold);
|
||||
|
||||
float left = glyph.bounds.left;
|
||||
float top = glyph.bounds.top;
|
||||
float right = glyph.bounds.left + glyph.bounds.width;
|
||||
float bottom = glyph.bounds.top + glyph.bounds.height;
|
||||
|
||||
float u1 = static_cast<float>(glyph.textureRect.left);
|
||||
float v1 = static_cast<float>(glyph.textureRect.top);
|
||||
float u2 = static_cast<float>(glyph.textureRect.left + glyph.textureRect.width);
|
||||
float v2 = static_cast<float>(glyph.textureRect.top + glyph.textureRect.height);
|
||||
|
||||
// Add a quad for the current character
|
||||
m_vertices.append(Vertex(Vector2f(x + left - italic * top, y + top), m_color, Vector2f(u1, v1)));
|
||||
m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1)));
|
||||
m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2)));
|
||||
m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2)));
|
||||
m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1)));
|
||||
m_vertices.append(Vertex(Vector2f(x + right - italic * bottom, y + bottom), m_color, Vector2f(u2, v2)));
|
||||
|
||||
// Update the current bounds
|
||||
minX = std::min(minX, x + left - italic * bottom);
|
||||
maxX = std::max(maxX, x + right - italic * top);
|
||||
minY = std::min(minY, y + top);
|
||||
maxY = std::max(maxY, y + bottom);
|
||||
|
||||
// Advance to the next character
|
||||
x += glyph.advance;
|
||||
}
|
||||
|
||||
// If we're using the underlined style, add the last line
|
||||
if (underlined)
|
||||
{
|
||||
float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f);
|
||||
float bottom = top + std::floor(underlineThickness + 0.5f);
|
||||
|
||||
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
|
||||
}
|
||||
|
||||
// If we're using the strike through style, add the last line across all characters
|
||||
if (strikeThrough)
|
||||
{
|
||||
float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f);
|
||||
float bottom = top + std::floor(underlineThickness + 0.5f);
|
||||
|
||||
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
|
||||
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
|
||||
}
|
||||
|
||||
// Update the bounding rectangle
|
||||
m_bounds.left = minX;
|
||||
m_bounds.top = minY;
|
||||
m_bounds.width = maxX - minX;
|
||||
m_bounds.height = maxY - minY;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class TextureSaver
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
|
@ -59,7 +59,7 @@ public :
|
|||
////////////////////////////////////////////////////////////
|
||||
~TextureSaver();
|
||||
|
||||
private :
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
|
|
|
@ -1,240 +1,240 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/View.hpp>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
View::View() :
|
||||
m_center (),
|
||||
m_size (),
|
||||
m_rotation (0),
|
||||
m_viewport (0, 0, 1, 1),
|
||||
m_transformUpdated (false),
|
||||
m_invTransformUpdated(false)
|
||||
{
|
||||
reset(FloatRect(0, 0, 1000, 1000));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
View::View(const FloatRect& rectangle) :
|
||||
m_center (),
|
||||
m_size (),
|
||||
m_rotation (0),
|
||||
m_viewport (0, 0, 1, 1),
|
||||
m_transformUpdated (false),
|
||||
m_invTransformUpdated(false)
|
||||
{
|
||||
reset(rectangle);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
View::View(const Vector2f& center, const Vector2f& size) :
|
||||
m_center (center),
|
||||
m_size (size),
|
||||
m_rotation (0),
|
||||
m_viewport (0, 0, 1, 1),
|
||||
m_transformUpdated (false),
|
||||
m_invTransformUpdated(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setCenter(float x, float y)
|
||||
{
|
||||
m_center.x = x;
|
||||
m_center.y = y;
|
||||
|
||||
m_transformUpdated = false;
|
||||
m_invTransformUpdated = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setCenter(const Vector2f& center)
|
||||
{
|
||||
setCenter(center.x, center.y);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setSize(float width, float height)
|
||||
{
|
||||
m_size.x = width;
|
||||
m_size.y = height;
|
||||
|
||||
m_transformUpdated = false;
|
||||
m_invTransformUpdated = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setSize(const Vector2f& size)
|
||||
{
|
||||
setSize(size.x, size.y);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setRotation(float angle)
|
||||
{
|
||||
m_rotation = static_cast<float>(fmod(angle, 360));
|
||||
if (m_rotation < 0)
|
||||
m_rotation += 360.f;
|
||||
|
||||
m_transformUpdated = false;
|
||||
m_invTransformUpdated = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setViewport(const FloatRect& viewport)
|
||||
{
|
||||
m_viewport = viewport;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::reset(const FloatRect& rectangle)
|
||||
{
|
||||
m_center.x = rectangle.left + rectangle.width / 2.f;
|
||||
m_center.y = rectangle.top + rectangle.height / 2.f;
|
||||
m_size.x = rectangle.width;
|
||||
m_size.y = rectangle.height;
|
||||
m_rotation = 0;
|
||||
|
||||
m_transformUpdated = false;
|
||||
m_invTransformUpdated = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Vector2f& View::getCenter() const
|
||||
{
|
||||
return m_center;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Vector2f& View::getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float View::getRotation() const
|
||||
{
|
||||
return m_rotation;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const FloatRect& View::getViewport() const
|
||||
{
|
||||
return m_viewport;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::move(float offsetX, float offsetY)
|
||||
{
|
||||
setCenter(m_center.x + offsetX, m_center.y + offsetY);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::move(const Vector2f& offset)
|
||||
{
|
||||
setCenter(m_center + offset);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::rotate(float angle)
|
||||
{
|
||||
setRotation(m_rotation + angle);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::zoom(float factor)
|
||||
{
|
||||
setSize(m_size.x * factor, m_size.y * factor);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Transform& View::getTransform() const
|
||||
{
|
||||
// Recompute the matrix if needed
|
||||
if (!m_transformUpdated)
|
||||
{
|
||||
// Rotation components
|
||||
float angle = m_rotation * 3.141592654f / 180.f;
|
||||
float cosine = static_cast<float>(std::cos(angle));
|
||||
float sine = static_cast<float>(std::sin(angle));
|
||||
float tx = -m_center.x * cosine - m_center.y * sine + m_center.x;
|
||||
float ty = m_center.x * sine - m_center.y * cosine + m_center.y;
|
||||
|
||||
// Projection components
|
||||
float a = 2.f / m_size.x;
|
||||
float b = -2.f / m_size.y;
|
||||
float c = -a * m_center.x;
|
||||
float d = -b * m_center.y;
|
||||
|
||||
// Rebuild the projection matrix
|
||||
m_transform = Transform( a * cosine, a * sine, a * tx + c,
|
||||
-b * sine, b * cosine, b * ty + d,
|
||||
0.f, 0.f, 1.f);
|
||||
m_transformUpdated = true;
|
||||
}
|
||||
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Transform& View::getInverseTransform() const
|
||||
{
|
||||
// Recompute the matrix if needed
|
||||
if (!m_invTransformUpdated)
|
||||
{
|
||||
m_inverseTransform = getTransform().getInverse();
|
||||
m_invTransformUpdated = true;
|
||||
}
|
||||
|
||||
return m_inverseTransform;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/View.hpp>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
View::View() :
|
||||
m_center (),
|
||||
m_size (),
|
||||
m_rotation (0),
|
||||
m_viewport (0, 0, 1, 1),
|
||||
m_transformUpdated (false),
|
||||
m_invTransformUpdated(false)
|
||||
{
|
||||
reset(FloatRect(0, 0, 1000, 1000));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
View::View(const FloatRect& rectangle) :
|
||||
m_center (),
|
||||
m_size (),
|
||||
m_rotation (0),
|
||||
m_viewport (0, 0, 1, 1),
|
||||
m_transformUpdated (false),
|
||||
m_invTransformUpdated(false)
|
||||
{
|
||||
reset(rectangle);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
View::View(const Vector2f& center, const Vector2f& size) :
|
||||
m_center (center),
|
||||
m_size (size),
|
||||
m_rotation (0),
|
||||
m_viewport (0, 0, 1, 1),
|
||||
m_transformUpdated (false),
|
||||
m_invTransformUpdated(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setCenter(float x, float y)
|
||||
{
|
||||
m_center.x = x;
|
||||
m_center.y = y;
|
||||
|
||||
m_transformUpdated = false;
|
||||
m_invTransformUpdated = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setCenter(const Vector2f& center)
|
||||
{
|
||||
setCenter(center.x, center.y);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setSize(float width, float height)
|
||||
{
|
||||
m_size.x = width;
|
||||
m_size.y = height;
|
||||
|
||||
m_transformUpdated = false;
|
||||
m_invTransformUpdated = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setSize(const Vector2f& size)
|
||||
{
|
||||
setSize(size.x, size.y);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setRotation(float angle)
|
||||
{
|
||||
m_rotation = static_cast<float>(fmod(angle, 360));
|
||||
if (m_rotation < 0)
|
||||
m_rotation += 360.f;
|
||||
|
||||
m_transformUpdated = false;
|
||||
m_invTransformUpdated = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::setViewport(const FloatRect& viewport)
|
||||
{
|
||||
m_viewport = viewport;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::reset(const FloatRect& rectangle)
|
||||
{
|
||||
m_center.x = rectangle.left + rectangle.width / 2.f;
|
||||
m_center.y = rectangle.top + rectangle.height / 2.f;
|
||||
m_size.x = rectangle.width;
|
||||
m_size.y = rectangle.height;
|
||||
m_rotation = 0;
|
||||
|
||||
m_transformUpdated = false;
|
||||
m_invTransformUpdated = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Vector2f& View::getCenter() const
|
||||
{
|
||||
return m_center;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Vector2f& View::getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float View::getRotation() const
|
||||
{
|
||||
return m_rotation;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const FloatRect& View::getViewport() const
|
||||
{
|
||||
return m_viewport;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::move(float offsetX, float offsetY)
|
||||
{
|
||||
setCenter(m_center.x + offsetX, m_center.y + offsetY);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::move(const Vector2f& offset)
|
||||
{
|
||||
setCenter(m_center + offset);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::rotate(float angle)
|
||||
{
|
||||
setRotation(m_rotation + angle);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void View::zoom(float factor)
|
||||
{
|
||||
setSize(m_size.x * factor, m_size.y * factor);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Transform& View::getTransform() const
|
||||
{
|
||||
// Recompute the matrix if needed
|
||||
if (!m_transformUpdated)
|
||||
{
|
||||
// Rotation components
|
||||
float angle = m_rotation * 3.141592654f / 180.f;
|
||||
float cosine = static_cast<float>(std::cos(angle));
|
||||
float sine = static_cast<float>(std::sin(angle));
|
||||
float tx = -m_center.x * cosine - m_center.y * sine + m_center.x;
|
||||
float ty = m_center.x * sine - m_center.y * cosine + m_center.y;
|
||||
|
||||
// Projection components
|
||||
float a = 2.f / m_size.x;
|
||||
float b = -2.f / m_size.y;
|
||||
float c = -a * m_center.x;
|
||||
float d = -b * m_center.y;
|
||||
|
||||
// Rebuild the projection matrix
|
||||
m_transform = Transform( a * cosine, a * sine, a * tx + c,
|
||||
-b * sine, b * cosine, b * ty + d,
|
||||
0.f, 0.f, 1.f);
|
||||
m_transformUpdated = true;
|
||||
}
|
||||
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Transform& View::getInverseTransform() const
|
||||
{
|
||||
// Recompute the matrix if needed
|
||||
if (!m_invTransformUpdated)
|
||||
{
|
||||
m_inverseTransform = getTransform().getInverse();
|
||||
m_invTransformUpdated = true;
|
||||
}
|
||||
|
||||
return m_inverseTransform;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Main)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Main)
|
||||
|
||||
# sources
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(SRC ${SRC} ${SRCROOT}/MainWin32.cpp)
|
||||
elseif(SFML_OS_IOS)
|
||||
set(SRC ${SRC} ${SRCROOT}/MainiOS.mm)
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(SRC ${SRC} ${SRCROOT}/MainAndroid.cpp)
|
||||
else()
|
||||
return()
|
||||
endif()
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# define the sfml-main target
|
||||
add_library(sfml-main STATIC ${SRC})
|
||||
|
||||
# set the debug suffix
|
||||
set_target_properties(sfml-main PROPERTIES DEBUG_POSTFIX -d)
|
||||
|
||||
# insert the major version number in the output filename
|
||||
set_target_properties(sfml-main PROPERTIES OUTPUT_NAME "sfml-main")
|
||||
|
||||
# set the target's folder (for IDEs that support it, e.g. Visual Studio)
|
||||
set_target_properties(sfml-main PROPERTIES FOLDER "SFML")
|
||||
|
||||
# setup the install rule
|
||||
install(TARGETS sfml-main ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel)
|
||||
|
||||
# because of a current limitation on Android (which prevents one library
|
||||
# from depending on shared libraries), we need a boostrap activity which
|
||||
# will load our shared libraries manually
|
||||
if(SFML_OS_ANDROID)
|
||||
sfml_add_library(sfml-activity SOURCES ${PROJECT_SOURCE_DIR}/src/SFML/Main/SFMLActivity.cpp)
|
||||
endif()
|
||||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Main)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Main)
|
||||
|
||||
# sources
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(SRC ${SRC} ${SRCROOT}/MainWin32.cpp)
|
||||
elseif(SFML_OS_IOS)
|
||||
set(SRC ${SRC} ${SRCROOT}/MainiOS.mm)
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(SRC ${SRC} ${SRCROOT}/MainAndroid.cpp)
|
||||
else()
|
||||
return()
|
||||
endif()
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# define the sfml-main target
|
||||
add_library(sfml-main STATIC ${SRC})
|
||||
|
||||
# set the debug suffix
|
||||
set_target_properties(sfml-main PROPERTIES DEBUG_POSTFIX -d)
|
||||
|
||||
# insert the major version number in the output filename
|
||||
set_target_properties(sfml-main PROPERTIES OUTPUT_NAME "sfml-main")
|
||||
|
||||
# set the target's folder (for IDEs that support it, e.g. Visual Studio)
|
||||
set_target_properties(sfml-main PROPERTIES FOLDER "SFML")
|
||||
|
||||
# setup the install rule
|
||||
install(TARGETS sfml-main ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel)
|
||||
|
||||
# because of a current limitation on Android (which prevents one library
|
||||
# from depending on shared libraries), we need a boostrap activity which
|
||||
# will load our shared libraries manually
|
||||
if(SFML_OS_ANDROID)
|
||||
sfml_add_library(sfml-activity SOURCES ${PROJECT_SOURCE_DIR}/src/SFML/Main/SFMLActivity.cpp)
|
||||
endif()
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,54 +1,54 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
|
||||
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Windows specific: we define the WinMain entry point,
|
||||
// so that developers can use the standard main function
|
||||
// even in a Win32 Application project, and thus keep a
|
||||
// portable code
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
#ifdef SFML_SYSTEM_WINDOWS
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
extern int main(int argc, char* argv[]);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
|
||||
{
|
||||
return main(__argc, __argv);
|
||||
}
|
||||
|
||||
#endif // SFML_SYSTEM_WINDOWS
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
|
||||
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Windows specific: we define the WinMain entry point,
|
||||
// so that developers can use the standard main function
|
||||
// even in a Win32 Application project, and thus keep a
|
||||
// portable code
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
#ifdef SFML_SYSTEM_WINDOWS
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
extern int main(int argc, char* argv[]);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
|
||||
{
|
||||
return main(__argc, __argv);
|
||||
}
|
||||
|
||||
#endif // SFML_SYSTEM_WINDOWS
|
||||
|
||||
|
|
|
@ -1,63 +1,63 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
|
||||
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// iOS specific: SFML needs to hook the main function, to
|
||||
// launch the iOS application (event loop), and then call the
|
||||
// user main from inside it.
|
||||
//
|
||||
// Our strategy is to rename the user main to 'sfmlMain' with
|
||||
// a macro (see Main.hpp), and call this modified main ourselves.
|
||||
//
|
||||
// Note that half of this trick (the sfmlMain placeholders and
|
||||
// the application delegate) is defined sfml-window; see there
|
||||
// for the full implementation.
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
#ifdef SFML_SYSTEM_IOS
|
||||
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Note: we intentionally drop command line arguments,
|
||||
// there's no such thing as a command line on an iOS device :)
|
||||
|
||||
// Important: "SFAppDelegate" must always match the name of the
|
||||
// application delegate class defined in sfml-window
|
||||
|
||||
return UIApplicationMain(argc, argv, nil, @"SFAppDelegate");
|
||||
}
|
||||
|
||||
#endif // SFML_SYSTEM_IOS
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
|
||||
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// iOS specific: SFML needs to hook the main function, to
|
||||
// launch the iOS application (event loop), and then call the
|
||||
// user main from inside it.
|
||||
//
|
||||
// Our strategy is to rename the user main to 'sfmlMain' with
|
||||
// a macro (see Main.hpp), and call this modified main ourselves.
|
||||
//
|
||||
// Note that half of this trick (the sfmlMain placeholders and
|
||||
// the application delegate) is defined sfml-window; see there
|
||||
// for the full implementation.
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
#ifdef SFML_SYSTEM_IOS
|
||||
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Note: we intentionally drop command line arguments,
|
||||
// there's no such thing as a command line on an iOS device :)
|
||||
|
||||
// Important: "SFAppDelegate" must always match the name of the
|
||||
// application delegate class defined in sfml-window
|
||||
|
||||
return UIApplicationMain(argc, argv, nil, @"SFAppDelegate");
|
||||
}
|
||||
|
||||
#endif // SFML_SYSTEM_IOS
|
||||
|
|
|
@ -1,57 +1,57 @@
|
|||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Network)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Network)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${INCROOT}/Export.hpp
|
||||
${SRCROOT}/Ftp.cpp
|
||||
${INCROOT}/Ftp.hpp
|
||||
${SRCROOT}/Http.cpp
|
||||
${INCROOT}/Http.hpp
|
||||
${SRCROOT}/IpAddress.cpp
|
||||
${INCROOT}/IpAddress.hpp
|
||||
${SRCROOT}/Packet.cpp
|
||||
${INCROOT}/Packet.hpp
|
||||
${SRCROOT}/Socket.cpp
|
||||
${INCROOT}/Socket.hpp
|
||||
${SRCROOT}/SocketImpl.hpp
|
||||
${INCROOT}/SocketHandle.hpp
|
||||
${SRCROOT}/SocketSelector.cpp
|
||||
${INCROOT}/SocketSelector.hpp
|
||||
${SRCROOT}/TcpListener.cpp
|
||||
${INCROOT}/TcpListener.hpp
|
||||
${SRCROOT}/TcpSocket.cpp
|
||||
${INCROOT}/TcpSocket.hpp
|
||||
${SRCROOT}/UdpSocket.cpp
|
||||
${INCROOT}/UdpSocket.hpp
|
||||
)
|
||||
|
||||
# add platform specific sources
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(SRC
|
||||
${SRC}
|
||||
${SRCROOT}/Win32/SocketImpl.cpp
|
||||
${SRCROOT}/Win32/SocketImpl.hpp
|
||||
)
|
||||
else()
|
||||
set(SRC
|
||||
${SRC}
|
||||
${SRCROOT}/Unix/SocketImpl.cpp
|
||||
${SRCROOT}/Unix/SocketImpl.hpp
|
||||
)
|
||||
endif()
|
||||
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# build the list of external libraries to link
|
||||
set(NETWORK_EXT_LIBS)
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(NETWORK_EXT_LIBS ${NETWORK_EXT_LIBS} ws2_32)
|
||||
endif()
|
||||
|
||||
# define the sfml-network target
|
||||
sfml_add_library(sfml-network
|
||||
SOURCES ${SRC}
|
||||
DEPENDS sfml-system
|
||||
EXTERNAL_LIBS ${NETWORK_EXT_LIBS})
|
||||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Network)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Network)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${INCROOT}/Export.hpp
|
||||
${SRCROOT}/Ftp.cpp
|
||||
${INCROOT}/Ftp.hpp
|
||||
${SRCROOT}/Http.cpp
|
||||
${INCROOT}/Http.hpp
|
||||
${SRCROOT}/IpAddress.cpp
|
||||
${INCROOT}/IpAddress.hpp
|
||||
${SRCROOT}/Packet.cpp
|
||||
${INCROOT}/Packet.hpp
|
||||
${SRCROOT}/Socket.cpp
|
||||
${INCROOT}/Socket.hpp
|
||||
${SRCROOT}/SocketImpl.hpp
|
||||
${INCROOT}/SocketHandle.hpp
|
||||
${SRCROOT}/SocketSelector.cpp
|
||||
${INCROOT}/SocketSelector.hpp
|
||||
${SRCROOT}/TcpListener.cpp
|
||||
${INCROOT}/TcpListener.hpp
|
||||
${SRCROOT}/TcpSocket.cpp
|
||||
${INCROOT}/TcpSocket.hpp
|
||||
${SRCROOT}/UdpSocket.cpp
|
||||
${INCROOT}/UdpSocket.hpp
|
||||
)
|
||||
|
||||
# add platform specific sources
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(SRC
|
||||
${SRC}
|
||||
${SRCROOT}/Win32/SocketImpl.cpp
|
||||
${SRCROOT}/Win32/SocketImpl.hpp
|
||||
)
|
||||
else()
|
||||
set(SRC
|
||||
${SRC}
|
||||
${SRCROOT}/Unix/SocketImpl.cpp
|
||||
${SRCROOT}/Unix/SocketImpl.hpp
|
||||
)
|
||||
endif()
|
||||
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# build the list of external libraries to link
|
||||
set(NETWORK_EXT_LIBS)
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(NETWORK_EXT_LIBS ${NETWORK_EXT_LIBS} ws2_32)
|
||||
endif()
|
||||
|
||||
# define the sfml-network target
|
||||
sfml_add_library(sfml-network
|
||||
SOURCES ${SRC}
|
||||
DEPENDS sfml-system
|
||||
EXTERNAL_LIBS ${NETWORK_EXT_LIBS})
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,415 +1,415 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Convert a string to lower case
|
||||
std::string toLower(std::string str)
|
||||
{
|
||||
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
||||
*i = static_cast<char>(std::tolower(*i));
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Request::Request(const std::string& uri, Method method, const std::string& body)
|
||||
{
|
||||
setMethod(method);
|
||||
setUri(uri);
|
||||
setHttpVersion(1, 0);
|
||||
setBody(body);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setField(const std::string& field, const std::string& value)
|
||||
{
|
||||
m_fields[toLower(field)] = value;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setMethod(Http::Request::Method method)
|
||||
{
|
||||
m_method = method;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setUri(const std::string& uri)
|
||||
{
|
||||
m_uri = uri;
|
||||
|
||||
// Make sure it starts with a '/'
|
||||
if (m_uri.empty() || (m_uri[0] != '/'))
|
||||
m_uri.insert(0, "/");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setHttpVersion(unsigned int major, unsigned int minor)
|
||||
{
|
||||
m_majorVersion = major;
|
||||
m_minorVersion = minor;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setBody(const std::string& body)
|
||||
{
|
||||
m_body = body;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string Http::Request::prepare() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
// Convert the method to its string representation
|
||||
std::string method;
|
||||
switch (m_method)
|
||||
{
|
||||
default :
|
||||
case Get : method = "GET"; break;
|
||||
case Post : method = "POST"; break;
|
||||
case Head : method = "HEAD"; break;
|
||||
case Put : method = "PUT"; break;
|
||||
case Delete : method = "DELETE"; break;
|
||||
}
|
||||
|
||||
// Write the first line containing the request type
|
||||
out << method << " " << m_uri << " ";
|
||||
out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n";
|
||||
|
||||
// Write fields
|
||||
for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i)
|
||||
{
|
||||
out << i->first << ": " << i->second << "\r\n";
|
||||
}
|
||||
|
||||
// Use an extra \r\n to separate the header from the body
|
||||
out << "\r\n";
|
||||
|
||||
// Add the body
|
||||
out << m_body;
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Http::Request::hasField(const std::string& field) const
|
||||
{
|
||||
return m_fields.find(toLower(field)) != m_fields.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response::Response() :
|
||||
m_status (ConnectionFailed),
|
||||
m_majorVersion(0),
|
||||
m_minorVersion(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Http::Response::getField(const std::string& field) const
|
||||
{
|
||||
FieldTable::const_iterator it = m_fields.find(toLower(field));
|
||||
if (it != m_fields.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const std::string empty = "";
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response::Status Http::Response::getStatus() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Http::Response::getMajorHttpVersion() const
|
||||
{
|
||||
return m_majorVersion;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Http::Response::getMinorHttpVersion() const
|
||||
{
|
||||
return m_minorVersion;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Http::Response::getBody() const
|
||||
{
|
||||
return m_body;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Response::parse(const std::string& data)
|
||||
{
|
||||
std::istringstream in(data);
|
||||
|
||||
// Extract the HTTP version from the first line
|
||||
std::string version;
|
||||
if (in >> version)
|
||||
{
|
||||
if ((version.size() >= 8) && (version[6] == '.') &&
|
||||
(toLower(version.substr(0, 5)) == "http/") &&
|
||||
isdigit(version[5]) && isdigit(version[7]))
|
||||
{
|
||||
m_majorVersion = version[5] - '0';
|
||||
m_minorVersion = version[7] - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid HTTP version
|
||||
m_status = InvalidResponse;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the status code from the first line
|
||||
int status;
|
||||
if (in >> status)
|
||||
{
|
||||
m_status = static_cast<Status>(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid status code
|
||||
m_status = InvalidResponse;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore the end of the first line
|
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// Parse the other lines, which contain fields, one by one
|
||||
parseFields(in);
|
||||
|
||||
m_body.clear();
|
||||
|
||||
// Determine whether the transfer is chunked
|
||||
if (toLower(getField("transfer-encoding")) != "chunked")
|
||||
{
|
||||
// Not chunked - just read everything at once
|
||||
std::copy(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::back_inserter(m_body));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Chunked - have to read chunk by chunk
|
||||
std::size_t length;
|
||||
|
||||
// Read all chunks, identified by a chunk-size not being 0
|
||||
while (in >> std::hex >> length)
|
||||
{
|
||||
// Drop the rest of the line (chunk-extension)
|
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// Copy the actual content data
|
||||
std::istreambuf_iterator<char> it(in);
|
||||
for (std::size_t i = 0; i < length; i++)
|
||||
m_body.push_back(*it++);
|
||||
}
|
||||
|
||||
// Drop the rest of the line (chunk-extension)
|
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// Read all trailers (if present)
|
||||
parseFields(in);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Response::parseFields(std::istream &in)
|
||||
{
|
||||
std::string line;
|
||||
while (std::getline(in, line) && (line.size() > 2))
|
||||
{
|
||||
std::string::size_type pos = line.find(": ");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
// Extract the field name and its value
|
||||
std::string field = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 2);
|
||||
|
||||
// Remove any trailing \r
|
||||
if (!value.empty() && (*value.rbegin() == '\r'))
|
||||
value.erase(value.size() - 1);
|
||||
|
||||
// Add the field
|
||||
m_fields[toLower(field)] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Http() :
|
||||
m_host(),
|
||||
m_port(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Http(const std::string& host, unsigned short port)
|
||||
{
|
||||
setHost(host, port);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::setHost(const std::string& host, unsigned short port)
|
||||
{
|
||||
// Check the protocol
|
||||
if (toLower(host.substr(0, 7)) == "http://")
|
||||
{
|
||||
// HTTP protocol
|
||||
m_hostName = host.substr(7);
|
||||
m_port = (port != 0 ? port : 80);
|
||||
}
|
||||
else if (toLower(host.substr(0, 8)) == "https://")
|
||||
{
|
||||
// HTTPS protocol -- unsupported (requires encryption and certificates and stuff...)
|
||||
err() << "HTTPS protocol is not supported by sf::Http" << std::endl;
|
||||
m_hostName = "";
|
||||
m_port = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Undefined protocol - use HTTP
|
||||
m_hostName = host;
|
||||
m_port = (port != 0 ? port : 80);
|
||||
}
|
||||
|
||||
// Remove any trailing '/' from the host name
|
||||
if (!m_hostName.empty() && (*m_hostName.rbegin() == '/'))
|
||||
m_hostName.erase(m_hostName.size() - 1);
|
||||
|
||||
m_host = IpAddress(m_hostName);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response Http::sendRequest(const Http::Request& request, Time timeout)
|
||||
{
|
||||
// First make sure that the request is valid -- add missing mandatory fields
|
||||
Request toSend(request);
|
||||
if (!toSend.hasField("From"))
|
||||
{
|
||||
toSend.setField("From", "user@sfml-dev.org");
|
||||
}
|
||||
if (!toSend.hasField("User-Agent"))
|
||||
{
|
||||
toSend.setField("User-Agent", "libsfml-network/2.x");
|
||||
}
|
||||
if (!toSend.hasField("Host"))
|
||||
{
|
||||
toSend.setField("Host", m_hostName);
|
||||
}
|
||||
if (!toSend.hasField("Content-Length"))
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << toSend.m_body.size();
|
||||
toSend.setField("Content-Length", out.str());
|
||||
}
|
||||
if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type"))
|
||||
{
|
||||
toSend.setField("Content-Type", "application/x-www-form-urlencoded");
|
||||
}
|
||||
if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection"))
|
||||
{
|
||||
toSend.setField("Connection", "close");
|
||||
}
|
||||
|
||||
// Prepare the response
|
||||
Response received;
|
||||
|
||||
// Connect the socket to the host
|
||||
if (m_connection.connect(m_host, m_port, timeout) == Socket::Done)
|
||||
{
|
||||
// Convert the request to string and send it through the connected socket
|
||||
std::string requestStr = toSend.prepare();
|
||||
|
||||
if (!requestStr.empty())
|
||||
{
|
||||
// Send it through the socket
|
||||
if (m_connection.send(requestStr.c_str(), requestStr.size()) == Socket::Done)
|
||||
{
|
||||
// Wait for the server's response
|
||||
std::string receivedStr;
|
||||
std::size_t size = 0;
|
||||
char buffer[1024];
|
||||
while (m_connection.receive(buffer, sizeof(buffer), size) == Socket::Done)
|
||||
{
|
||||
receivedStr.append(buffer, buffer + size);
|
||||
}
|
||||
|
||||
// Build the Response object from the received data
|
||||
received.parse(receivedStr);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
m_connection.disconnect();
|
||||
}
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Convert a string to lower case
|
||||
std::string toLower(std::string str)
|
||||
{
|
||||
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
||||
*i = static_cast<char>(std::tolower(*i));
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Request::Request(const std::string& uri, Method method, const std::string& body)
|
||||
{
|
||||
setMethod(method);
|
||||
setUri(uri);
|
||||
setHttpVersion(1, 0);
|
||||
setBody(body);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setField(const std::string& field, const std::string& value)
|
||||
{
|
||||
m_fields[toLower(field)] = value;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setMethod(Http::Request::Method method)
|
||||
{
|
||||
m_method = method;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setUri(const std::string& uri)
|
||||
{
|
||||
m_uri = uri;
|
||||
|
||||
// Make sure it starts with a '/'
|
||||
if (m_uri.empty() || (m_uri[0] != '/'))
|
||||
m_uri.insert(0, "/");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setHttpVersion(unsigned int major, unsigned int minor)
|
||||
{
|
||||
m_majorVersion = major;
|
||||
m_minorVersion = minor;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::setBody(const std::string& body)
|
||||
{
|
||||
m_body = body;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string Http::Request::prepare() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
// Convert the method to its string representation
|
||||
std::string method;
|
||||
switch (m_method)
|
||||
{
|
||||
default:
|
||||
case Get: method = "GET"; break;
|
||||
case Post: method = "POST"; break;
|
||||
case Head: method = "HEAD"; break;
|
||||
case Put: method = "PUT"; break;
|
||||
case Delete: method = "DELETE"; break;
|
||||
}
|
||||
|
||||
// Write the first line containing the request type
|
||||
out << method << " " << m_uri << " ";
|
||||
out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n";
|
||||
|
||||
// Write fields
|
||||
for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i)
|
||||
{
|
||||
out << i->first << ": " << i->second << "\r\n";
|
||||
}
|
||||
|
||||
// Use an extra \r\n to separate the header from the body
|
||||
out << "\r\n";
|
||||
|
||||
// Add the body
|
||||
out << m_body;
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Http::Request::hasField(const std::string& field) const
|
||||
{
|
||||
return m_fields.find(toLower(field)) != m_fields.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response::Response() :
|
||||
m_status (ConnectionFailed),
|
||||
m_majorVersion(0),
|
||||
m_minorVersion(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Http::Response::getField(const std::string& field) const
|
||||
{
|
||||
FieldTable::const_iterator it = m_fields.find(toLower(field));
|
||||
if (it != m_fields.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const std::string empty = "";
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response::Status Http::Response::getStatus() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Http::Response::getMajorHttpVersion() const
|
||||
{
|
||||
return m_majorVersion;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Http::Response::getMinorHttpVersion() const
|
||||
{
|
||||
return m_minorVersion;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Http::Response::getBody() const
|
||||
{
|
||||
return m_body;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Response::parse(const std::string& data)
|
||||
{
|
||||
std::istringstream in(data);
|
||||
|
||||
// Extract the HTTP version from the first line
|
||||
std::string version;
|
||||
if (in >> version)
|
||||
{
|
||||
if ((version.size() >= 8) && (version[6] == '.') &&
|
||||
(toLower(version.substr(0, 5)) == "http/") &&
|
||||
isdigit(version[5]) && isdigit(version[7]))
|
||||
{
|
||||
m_majorVersion = version[5] - '0';
|
||||
m_minorVersion = version[7] - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid HTTP version
|
||||
m_status = InvalidResponse;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the status code from the first line
|
||||
int status;
|
||||
if (in >> status)
|
||||
{
|
||||
m_status = static_cast<Status>(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid status code
|
||||
m_status = InvalidResponse;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore the end of the first line
|
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// Parse the other lines, which contain fields, one by one
|
||||
parseFields(in);
|
||||
|
||||
m_body.clear();
|
||||
|
||||
// Determine whether the transfer is chunked
|
||||
if (toLower(getField("transfer-encoding")) != "chunked")
|
||||
{
|
||||
// Not chunked - just read everything at once
|
||||
std::copy(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::back_inserter(m_body));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Chunked - have to read chunk by chunk
|
||||
std::size_t length;
|
||||
|
||||
// Read all chunks, identified by a chunk-size not being 0
|
||||
while (in >> std::hex >> length)
|
||||
{
|
||||
// Drop the rest of the line (chunk-extension)
|
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// Copy the actual content data
|
||||
std::istreambuf_iterator<char> it(in);
|
||||
for (std::size_t i = 0; i < length; i++)
|
||||
m_body.push_back(*it++);
|
||||
}
|
||||
|
||||
// Drop the rest of the line (chunk-extension)
|
||||
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
|
||||
// Read all trailers (if present)
|
||||
parseFields(in);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Response::parseFields(std::istream &in)
|
||||
{
|
||||
std::string line;
|
||||
while (std::getline(in, line) && (line.size() > 2))
|
||||
{
|
||||
std::string::size_type pos = line.find(": ");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
// Extract the field name and its value
|
||||
std::string field = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 2);
|
||||
|
||||
// Remove any trailing \r
|
||||
if (!value.empty() && (*value.rbegin() == '\r'))
|
||||
value.erase(value.size() - 1);
|
||||
|
||||
// Add the field
|
||||
m_fields[toLower(field)] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Http() :
|
||||
m_host(),
|
||||
m_port(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Http(const std::string& host, unsigned short port)
|
||||
{
|
||||
setHost(host, port);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::setHost(const std::string& host, unsigned short port)
|
||||
{
|
||||
// Check the protocol
|
||||
if (toLower(host.substr(0, 7)) == "http://")
|
||||
{
|
||||
// HTTP protocol
|
||||
m_hostName = host.substr(7);
|
||||
m_port = (port != 0 ? port : 80);
|
||||
}
|
||||
else if (toLower(host.substr(0, 8)) == "https://")
|
||||
{
|
||||
// HTTPS protocol -- unsupported (requires encryption and certificates and stuff...)
|
||||
err() << "HTTPS protocol is not supported by sf::Http" << std::endl;
|
||||
m_hostName = "";
|
||||
m_port = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Undefined protocol - use HTTP
|
||||
m_hostName = host;
|
||||
m_port = (port != 0 ? port : 80);
|
||||
}
|
||||
|
||||
// Remove any trailing '/' from the host name
|
||||
if (!m_hostName.empty() && (*m_hostName.rbegin() == '/'))
|
||||
m_hostName.erase(m_hostName.size() - 1);
|
||||
|
||||
m_host = IpAddress(m_hostName);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response Http::sendRequest(const Http::Request& request, Time timeout)
|
||||
{
|
||||
// First make sure that the request is valid -- add missing mandatory fields
|
||||
Request toSend(request);
|
||||
if (!toSend.hasField("From"))
|
||||
{
|
||||
toSend.setField("From", "user@sfml-dev.org");
|
||||
}
|
||||
if (!toSend.hasField("User-Agent"))
|
||||
{
|
||||
toSend.setField("User-Agent", "libsfml-network/2.x");
|
||||
}
|
||||
if (!toSend.hasField("Host"))
|
||||
{
|
||||
toSend.setField("Host", m_hostName);
|
||||
}
|
||||
if (!toSend.hasField("Content-Length"))
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << toSend.m_body.size();
|
||||
toSend.setField("Content-Length", out.str());
|
||||
}
|
||||
if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type"))
|
||||
{
|
||||
toSend.setField("Content-Type", "application/x-www-form-urlencoded");
|
||||
}
|
||||
if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection"))
|
||||
{
|
||||
toSend.setField("Connection", "close");
|
||||
}
|
||||
|
||||
// Prepare the response
|
||||
Response received;
|
||||
|
||||
// Connect the socket to the host
|
||||
if (m_connection.connect(m_host, m_port, timeout) == Socket::Done)
|
||||
{
|
||||
// Convert the request to string and send it through the connected socket
|
||||
std::string requestStr = toSend.prepare();
|
||||
|
||||
if (!requestStr.empty())
|
||||
{
|
||||
// Send it through the socket
|
||||
if (m_connection.send(requestStr.c_str(), requestStr.size()) == Socket::Done)
|
||||
{
|
||||
// Wait for the server's response
|
||||
std::string receivedStr;
|
||||
std::size_t size = 0;
|
||||
char buffer[1024];
|
||||
while (m_connection.receive(buffer, sizeof(buffer), size) == Socket::Done)
|
||||
{
|
||||
receivedStr.append(buffer, buffer + size);
|
||||
}
|
||||
|
||||
// Build the Response object from the received data
|
||||
received.parse(receivedStr);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
m_connection.disconnect();
|
||||
}
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,255 +1,255 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/IpAddress.hpp>
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
sf::Uint32 resolve(const std::string& address)
|
||||
{
|
||||
if (address == "255.255.255.255")
|
||||
{
|
||||
// The broadcast address needs to be handled explicitely,
|
||||
// because it is also the value returned by inet_addr on error
|
||||
return INADDR_BROADCAST;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx")
|
||||
sf::Uint32 ip = inet_addr(address.c_str());
|
||||
if (ip != INADDR_NONE)
|
||||
return ip;
|
||||
|
||||
// Not a valid address, try to convert it as a host name
|
||||
addrinfo hints;
|
||||
std::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
addrinfo* result = NULL;
|
||||
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
|
||||
freeaddrinfo(result);
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
|
||||
// Not a valid address nor a host name
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const IpAddress IpAddress::None;
|
||||
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
|
||||
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress() :
|
||||
m_address(0)
|
||||
{
|
||||
// We're using 0 (INADDR_ANY) instead of INADDR_NONE to represent the invalid address,
|
||||
// because the latter is also the broadcast address (255.255.255.255); it's ok because
|
||||
// SFML doesn't publicly use INADDR_ANY (it is always used implicitely)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(const std::string& address) :
|
||||
m_address(resolve(address))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(const char* address) :
|
||||
m_address(resolve(address))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
|
||||
m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(Uint32 address) :
|
||||
m_address(htonl(address))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string IpAddress::toString() const
|
||||
{
|
||||
in_addr address;
|
||||
address.s_addr = m_address;
|
||||
|
||||
return inet_ntoa(address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 IpAddress::toInteger() const
|
||||
{
|
||||
return ntohl(m_address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress IpAddress::getLocalAddress()
|
||||
{
|
||||
// The method here is to connect a UDP socket to anyone (here to localhost),
|
||||
// and get the local socket address with the getsockname function.
|
||||
// UDP connection will not send anything to the network, so this function won't cause any overhead.
|
||||
|
||||
IpAddress localAddress;
|
||||
|
||||
// Create the socket
|
||||
SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == priv::SocketImpl::invalidSocket())
|
||||
return localAddress;
|
||||
|
||||
// Connect the socket to localhost on any port
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9);
|
||||
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
{
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
// Get the local address of the socket connection
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
|
||||
{
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
// Close the socket
|
||||
priv::SocketImpl::close(sock);
|
||||
|
||||
// Finally build the IP address
|
||||
localAddress = IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress IpAddress::getPublicAddress(Time timeout)
|
||||
{
|
||||
// The trick here is more complicated, because the only way
|
||||
// to get our public IP address is to get it from a distant computer.
|
||||
// Here we get the web page from http://www.sfml-dev.org/ip-provider.php
|
||||
// and parse the result to extract our IP address
|
||||
// (not very hard: the web page contains only our IP address).
|
||||
|
||||
Http server("www.sfml-dev.org");
|
||||
Http::Request request("/ip-provider.php", Http::Request::Get);
|
||||
Http::Response page = server.sendRequest(request, timeout);
|
||||
if (page.getStatus() == Http::Response::Ok)
|
||||
return IpAddress(page.getBody());
|
||||
|
||||
// Something failed: return an invalid address
|
||||
return IpAddress();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return left.toInteger() == right.toInteger();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return left.toInteger() < right.toInteger();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return right < left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(right < left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(left < right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::istream& operator >>(std::istream& stream, IpAddress& address)
|
||||
{
|
||||
std::string str;
|
||||
stream >> str;
|
||||
address = IpAddress(str);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::ostream& operator <<(std::ostream& stream, const IpAddress& address)
|
||||
{
|
||||
return stream << address.toString();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/IpAddress.hpp>
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
sf::Uint32 resolve(const std::string& address)
|
||||
{
|
||||
if (address == "255.255.255.255")
|
||||
{
|
||||
// The broadcast address needs to be handled explicitely,
|
||||
// because it is also the value returned by inet_addr on error
|
||||
return INADDR_BROADCAST;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx")
|
||||
sf::Uint32 ip = inet_addr(address.c_str());
|
||||
if (ip != INADDR_NONE)
|
||||
return ip;
|
||||
|
||||
// Not a valid address, try to convert it as a host name
|
||||
addrinfo hints;
|
||||
std::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
addrinfo* result = NULL;
|
||||
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
|
||||
freeaddrinfo(result);
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
|
||||
// Not a valid address nor a host name
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const IpAddress IpAddress::None;
|
||||
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
|
||||
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress() :
|
||||
m_address(0)
|
||||
{
|
||||
// We're using 0 (INADDR_ANY) instead of INADDR_NONE to represent the invalid address,
|
||||
// because the latter is also the broadcast address (255.255.255.255); it's ok because
|
||||
// SFML doesn't publicly use INADDR_ANY (it is always used implicitely)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(const std::string& address) :
|
||||
m_address(resolve(address))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(const char* address) :
|
||||
m_address(resolve(address))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
|
||||
m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress::IpAddress(Uint32 address) :
|
||||
m_address(htonl(address))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string IpAddress::toString() const
|
||||
{
|
||||
in_addr address;
|
||||
address.s_addr = m_address;
|
||||
|
||||
return inet_ntoa(address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 IpAddress::toInteger() const
|
||||
{
|
||||
return ntohl(m_address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress IpAddress::getLocalAddress()
|
||||
{
|
||||
// The method here is to connect a UDP socket to anyone (here to localhost),
|
||||
// and get the local socket address with the getsockname function.
|
||||
// UDP connection will not send anything to the network, so this function won't cause any overhead.
|
||||
|
||||
IpAddress localAddress;
|
||||
|
||||
// Create the socket
|
||||
SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == priv::SocketImpl::invalidSocket())
|
||||
return localAddress;
|
||||
|
||||
// Connect the socket to localhost on any port
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9);
|
||||
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
{
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
// Get the local address of the socket connection
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
|
||||
{
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
// Close the socket
|
||||
priv::SocketImpl::close(sock);
|
||||
|
||||
// Finally build the IP address
|
||||
localAddress = IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress IpAddress::getPublicAddress(Time timeout)
|
||||
{
|
||||
// The trick here is more complicated, because the only way
|
||||
// to get our public IP address is to get it from a distant computer.
|
||||
// Here we get the web page from http://www.sfml-dev.org/ip-provider.php
|
||||
// and parse the result to extract our IP address
|
||||
// (not very hard: the web page contains only our IP address).
|
||||
|
||||
Http server("www.sfml-dev.org");
|
||||
Http::Request request("/ip-provider.php", Http::Request::Get);
|
||||
Http::Response page = server.sendRequest(request, timeout);
|
||||
if (page.getStatus() == Http::Response::Ok)
|
||||
return IpAddress(page.getBody());
|
||||
|
||||
// Something failed: return an invalid address
|
||||
return IpAddress();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return left.toInteger() == right.toInteger();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return left.toInteger() < right.toInteger();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return right < left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(right < left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return !(left < right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::istream& operator >>(std::istream& stream, IpAddress& address)
|
||||
{
|
||||
std::string str;
|
||||
stream >> str;
|
||||
address = IpAddress(str);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::ostream& operator <<(std::ostream& stream, const IpAddress& address)
|
||||
{
|
||||
return stream << address.toString();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,144 +1,144 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Socket(Type type) :
|
||||
m_type (type),
|
||||
m_socket (priv::SocketImpl::invalidSocket()),
|
||||
m_isBlocking(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::~Socket()
|
||||
{
|
||||
// Close the socket before it gets destructed
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::setBlocking(bool blocking)
|
||||
{
|
||||
// Apply if the socket is already created
|
||||
if (m_socket != priv::SocketImpl::invalidSocket())
|
||||
priv::SocketImpl::setBlocking(m_socket, blocking);
|
||||
|
||||
m_isBlocking = blocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Socket::isBlocking() const
|
||||
{
|
||||
return m_isBlocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle Socket::getHandle() const
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::create()
|
||||
{
|
||||
// Don't create the socket if it already exists
|
||||
if (m_socket == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
SocketHandle handle = socket(PF_INET, m_type == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
|
||||
create(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::create(SocketHandle handle)
|
||||
{
|
||||
// Don't create the socket if it already exists
|
||||
if (m_socket == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Assign the new handle
|
||||
m_socket = handle;
|
||||
|
||||
// Set the current blocking state
|
||||
setBlocking(m_isBlocking);
|
||||
|
||||
if (m_type == Tcp)
|
||||
{
|
||||
// Disable the Nagle algorithm (ie. removes buffering of TCP packets)
|
||||
int yes = 1;
|
||||
if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to set socket option \"TCP_NODELAY\" ; "
|
||||
<< "all your TCP packets will be buffered" << std::endl;
|
||||
}
|
||||
|
||||
// On Mac OS X, disable the SIGPIPE signal on disconnection
|
||||
#ifdef SFML_SYSTEM_MACOS
|
||||
if (setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to set socket option \"SO_NOSIGPIPE\"" << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable broadcast by default for UDP sockets
|
||||
int yes = 1;
|
||||
if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to enable broadcast on UDP socket" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::close()
|
||||
{
|
||||
// Close the socket
|
||||
if (m_socket != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
priv::SocketImpl::close(m_socket);
|
||||
m_socket = priv::SocketImpl::invalidSocket();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Socket(Type type) :
|
||||
m_type (type),
|
||||
m_socket (priv::SocketImpl::invalidSocket()),
|
||||
m_isBlocking(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::~Socket()
|
||||
{
|
||||
// Close the socket before it gets destructed
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::setBlocking(bool blocking)
|
||||
{
|
||||
// Apply if the socket is already created
|
||||
if (m_socket != priv::SocketImpl::invalidSocket())
|
||||
priv::SocketImpl::setBlocking(m_socket, blocking);
|
||||
|
||||
m_isBlocking = blocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Socket::isBlocking() const
|
||||
{
|
||||
return m_isBlocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle Socket::getHandle() const
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::create()
|
||||
{
|
||||
// Don't create the socket if it already exists
|
||||
if (m_socket == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
SocketHandle handle = socket(PF_INET, m_type == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
|
||||
create(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::create(SocketHandle handle)
|
||||
{
|
||||
// Don't create the socket if it already exists
|
||||
if (m_socket == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Assign the new handle
|
||||
m_socket = handle;
|
||||
|
||||
// Set the current blocking state
|
||||
setBlocking(m_isBlocking);
|
||||
|
||||
if (m_type == Tcp)
|
||||
{
|
||||
// Disable the Nagle algorithm (ie. removes buffering of TCP packets)
|
||||
int yes = 1;
|
||||
if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to set socket option \"TCP_NODELAY\" ; "
|
||||
<< "all your TCP packets will be buffered" << std::endl;
|
||||
}
|
||||
|
||||
// On Mac OS X, disable the SIGPIPE signal on disconnection
|
||||
#ifdef SFML_SYSTEM_MACOS
|
||||
if (setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to set socket option \"SO_NOSIGPIPE\"" << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable broadcast by default for UDP sockets
|
||||
int yes = 1;
|
||||
if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to enable broadcast on UDP socket" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::close()
|
||||
{
|
||||
// Close the socket
|
||||
if (m_socket != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
priv::SocketImpl::close(m_socket);
|
||||
m_socket = priv::SocketImpl::invalidSocket();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
#include <SFML/Network/Win32/SocketImpl.hpp>
|
||||
|
||||
#else
|
||||
|
||||
#include <SFML/Network/Unix/SocketImpl.hpp>
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
#include <SFML/Network/Win32/SocketImpl.hpp>
|
||||
|
||||
#else
|
||||
|
||||
#include <SFML/Network/Unix/SocketImpl.hpp>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,205 +1,205 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/SocketSelector.hpp>
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
struct SocketSelector::SocketSelectorImpl
|
||||
{
|
||||
fd_set allSockets; ///< Set containing all the sockets handles
|
||||
fd_set socketsReady; ///< Set containing handles of the sockets that are ready
|
||||
int maxSocket; ///< Maximum socket handle
|
||||
int socketCount; ///< Number of socket handles
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::SocketSelector() :
|
||||
m_impl(new SocketSelectorImpl)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::SocketSelector(const SocketSelector& copy) :
|
||||
m_impl(new SocketSelectorImpl(*copy.m_impl))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::~SocketSelector()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::add(Socket& socket)
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
if (m_impl->socketCount >= FD_SETSIZE)
|
||||
{
|
||||
err() << "The socket can't be added to the selector because the "
|
||||
<< "selector is full. This is a limitation of your operating "
|
||||
<< "system's FD_SETSIZE setting.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (FD_ISSET(handle, &m_impl->allSockets))
|
||||
return;
|
||||
|
||||
m_impl->socketCount++;
|
||||
|
||||
#else
|
||||
|
||||
if (handle >= FD_SETSIZE)
|
||||
{
|
||||
err() << "The socket can't be added to the selector because its "
|
||||
<< "ID is too high. This is a limitation of your operating "
|
||||
<< "system's FD_SETSIZE setting.";
|
||||
return;
|
||||
}
|
||||
|
||||
// SocketHandle is an int in POSIX
|
||||
m_impl->maxSocket = std::max(m_impl->maxSocket, handle);
|
||||
|
||||
#endif
|
||||
|
||||
FD_SET(handle, &m_impl->allSockets);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::remove(Socket& socket)
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
if (!FD_ISSET(handle, &m_impl->allSockets))
|
||||
return;
|
||||
|
||||
m_impl->socketCount--;
|
||||
|
||||
#else
|
||||
|
||||
if (handle >= FD_SETSIZE)
|
||||
return;
|
||||
|
||||
#endif
|
||||
|
||||
FD_CLR(handle, &m_impl->allSockets);
|
||||
FD_CLR(handle, &m_impl->socketsReady);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::clear()
|
||||
{
|
||||
FD_ZERO(&m_impl->allSockets);
|
||||
FD_ZERO(&m_impl->socketsReady);
|
||||
|
||||
m_impl->maxSocket = 0;
|
||||
m_impl->socketCount = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketSelector::wait(Time timeout)
|
||||
{
|
||||
// Setup the timeout
|
||||
timeval time;
|
||||
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
|
||||
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
|
||||
|
||||
// Initialize the set that will contain the sockets that are ready
|
||||
m_impl->socketsReady = m_impl->allSockets;
|
||||
|
||||
// Wait until one of the sockets is ready for reading, or timeout is reached
|
||||
// The first parameter is ignored on Windows
|
||||
int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL);
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketSelector::isReady(Socket& socket) const
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
|
||||
#if !defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
if (handle >= FD_SETSIZE)
|
||||
return false;
|
||||
|
||||
#endif
|
||||
|
||||
return FD_ISSET(handle, &m_impl->socketsReady) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector& SocketSelector::operator =(const SocketSelector& right)
|
||||
{
|
||||
SocketSelector temp(right);
|
||||
|
||||
std::swap(m_impl, temp.m_impl);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/SocketSelector.hpp>
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
struct SocketSelector::SocketSelectorImpl
|
||||
{
|
||||
fd_set allSockets; ///< Set containing all the sockets handles
|
||||
fd_set socketsReady; ///< Set containing handles of the sockets that are ready
|
||||
int maxSocket; ///< Maximum socket handle
|
||||
int socketCount; ///< Number of socket handles
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::SocketSelector() :
|
||||
m_impl(new SocketSelectorImpl)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::SocketSelector(const SocketSelector& copy) :
|
||||
m_impl(new SocketSelectorImpl(*copy.m_impl))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::~SocketSelector()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::add(Socket& socket)
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
if (m_impl->socketCount >= FD_SETSIZE)
|
||||
{
|
||||
err() << "The socket can't be added to the selector because the "
|
||||
<< "selector is full. This is a limitation of your operating "
|
||||
<< "system's FD_SETSIZE setting.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (FD_ISSET(handle, &m_impl->allSockets))
|
||||
return;
|
||||
|
||||
m_impl->socketCount++;
|
||||
|
||||
#else
|
||||
|
||||
if (handle >= FD_SETSIZE)
|
||||
{
|
||||
err() << "The socket can't be added to the selector because its "
|
||||
<< "ID is too high. This is a limitation of your operating "
|
||||
<< "system's FD_SETSIZE setting.";
|
||||
return;
|
||||
}
|
||||
|
||||
// SocketHandle is an int in POSIX
|
||||
m_impl->maxSocket = std::max(m_impl->maxSocket, handle);
|
||||
|
||||
#endif
|
||||
|
||||
FD_SET(handle, &m_impl->allSockets);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::remove(Socket& socket)
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
if (!FD_ISSET(handle, &m_impl->allSockets))
|
||||
return;
|
||||
|
||||
m_impl->socketCount--;
|
||||
|
||||
#else
|
||||
|
||||
if (handle >= FD_SETSIZE)
|
||||
return;
|
||||
|
||||
#endif
|
||||
|
||||
FD_CLR(handle, &m_impl->allSockets);
|
||||
FD_CLR(handle, &m_impl->socketsReady);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::clear()
|
||||
{
|
||||
FD_ZERO(&m_impl->allSockets);
|
||||
FD_ZERO(&m_impl->socketsReady);
|
||||
|
||||
m_impl->maxSocket = 0;
|
||||
m_impl->socketCount = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketSelector::wait(Time timeout)
|
||||
{
|
||||
// Setup the timeout
|
||||
timeval time;
|
||||
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
|
||||
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
|
||||
|
||||
// Initialize the set that will contain the sockets that are ready
|
||||
m_impl->socketsReady = m_impl->allSockets;
|
||||
|
||||
// Wait until one of the sockets is ready for reading, or timeout is reached
|
||||
// The first parameter is ignored on Windows
|
||||
int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL);
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketSelector::isReady(Socket& socket) const
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
|
||||
#if !defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
if (handle >= FD_SETSIZE)
|
||||
return false;
|
||||
|
||||
#endif
|
||||
|
||||
return FD_ISSET(handle, &m_impl->socketsReady) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector& SocketSelector::operator =(const SocketSelector& right)
|
||||
{
|
||||
SocketSelector temp(right);
|
||||
|
||||
std::swap(m_impl, temp.m_impl);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,124 +1,124 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/TcpListener.hpp>
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpListener::TcpListener() :
|
||||
Socket(Tcp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpListener::getLocalPort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the local end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpListener::listen(unsigned short port)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Bind the socket to the specified port
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
|
||||
if (bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
{
|
||||
// Not likely to happen, but...
|
||||
err() << "Failed to bind listener socket to port " << port << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Listen to the bound port
|
||||
if (::listen(getHandle(), 0) == -1)
|
||||
{
|
||||
// Oops, socket is deaf
|
||||
err() << "Failed to listen to port " << port << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void TcpListener::close()
|
||||
{
|
||||
// Simply close the socket
|
||||
Socket::close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpListener::accept(TcpSocket& socket)
|
||||
{
|
||||
// Make sure that we're listening
|
||||
if (getHandle() == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
err() << "Failed to accept a new connection, the socket is not listening" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Accept a new connection
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength length = sizeof(address);
|
||||
SocketHandle remote = ::accept(getHandle(), reinterpret_cast<sockaddr*>(&address), &length);
|
||||
|
||||
// Check for errors
|
||||
if (remote == priv::SocketImpl::invalidSocket())
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// Initialize the new connected socket
|
||||
socket.close();
|
||||
socket.create(remote);
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/TcpListener.hpp>
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpListener::TcpListener() :
|
||||
Socket(Tcp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpListener::getLocalPort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the local end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpListener::listen(unsigned short port)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Bind the socket to the specified port
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
|
||||
if (bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
{
|
||||
// Not likely to happen, but...
|
||||
err() << "Failed to bind listener socket to port " << port << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Listen to the bound port
|
||||
if (::listen(getHandle(), 0) == -1)
|
||||
{
|
||||
// Oops, socket is deaf
|
||||
err() << "Failed to listen to port " << port << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void TcpListener::close()
|
||||
{
|
||||
// Simply close the socket
|
||||
Socket::close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpListener::accept(TcpSocket& socket)
|
||||
{
|
||||
// Make sure that we're listening
|
||||
if (getHandle() == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
err() << "Failed to accept a new connection, the socket is not listening" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Accept a new connection
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength length = sizeof(address);
|
||||
SocketHandle remote = ::accept(getHandle(), reinterpret_cast<sockaddr*>(&address), &length);
|
||||
|
||||
// Check for errors
|
||||
if (remote == priv::SocketImpl::invalidSocket())
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// Initialize the new connected socket
|
||||
socket.close();
|
||||
socket.create(remote);
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,382 +1,382 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/Network/IpAddress.hpp>
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Define the low-level send/receive flags, which depend on the OS
|
||||
#ifdef SFML_SYSTEM_LINUX
|
||||
const int flags = MSG_NOSIGNAL;
|
||||
#else
|
||||
const int flags = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket::TcpSocket() :
|
||||
Socket(Tcp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpSocket::getLocalPort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the local end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress TcpSocket::getRemoteAddress() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the remote end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the address
|
||||
return IpAddress::None;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpSocket::getRemotePort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the remote end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Create the remote address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
|
||||
|
||||
if (timeout <= Time::Zero)
|
||||
{
|
||||
// ----- We're not using a timeout: just try to connect -----
|
||||
|
||||
// Connect the socket
|
||||
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// Connection succeeded
|
||||
return Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ----- We're using a timeout: we'll need a few tricks to make it work -----
|
||||
|
||||
// Save the previous blocking state
|
||||
bool blocking = isBlocking();
|
||||
|
||||
// Switch to non-blocking to enable our connection timeout
|
||||
if (blocking)
|
||||
setBlocking(false);
|
||||
|
||||
// Try to connect to the remote address
|
||||
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0)
|
||||
{
|
||||
// We got instantly connected! (it may no happen a lot...)
|
||||
setBlocking(blocking);
|
||||
return Done;
|
||||
}
|
||||
|
||||
// Get the error status
|
||||
Status status = priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// If we were in non-blocking mode, return immediatly
|
||||
if (!blocking)
|
||||
return status;
|
||||
|
||||
// Otherwise, wait until something happens to our socket (success, timeout or error)
|
||||
if (status == Socket::NotReady)
|
||||
{
|
||||
// Setup the selector
|
||||
fd_set selector;
|
||||
FD_ZERO(&selector);
|
||||
FD_SET(getHandle(), &selector);
|
||||
|
||||
// Setup the timeout
|
||||
timeval time;
|
||||
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
|
||||
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
|
||||
|
||||
// Wait for something to write on our socket (which means that the connection request has returned)
|
||||
if (select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time) > 0)
|
||||
{
|
||||
// At this point the connection may have been either accepted or refused.
|
||||
// To know whether it's a success or a failure, we must check the address of the connected peer
|
||||
if (getRemoteAddress() != sf::IpAddress::None)
|
||||
{
|
||||
// Connection accepted
|
||||
status = Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Connection refused
|
||||
status = priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to connect before timeout is over
|
||||
status = priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
}
|
||||
|
||||
// Switch back to blocking mode
|
||||
setBlocking(true);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void TcpSocket::disconnect()
|
||||
{
|
||||
// Close the socket
|
||||
close();
|
||||
|
||||
// Reset the pending packet data
|
||||
m_pendingPacket = PendingPacket();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::send(const void* data, std::size_t size)
|
||||
{
|
||||
// Check the parameters
|
||||
if (!data || (size == 0))
|
||||
{
|
||||
err() << "Cannot send data over the network (no data to send)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Loop until every byte has been sent
|
||||
int sent = 0;
|
||||
int sizeToSend = static_cast<int>(size);
|
||||
for (int length = 0; length < sizeToSend; length += sent)
|
||||
{
|
||||
// Send a chunk of data
|
||||
sent = ::send(getHandle(), static_cast<const char*>(data) + length, sizeToSend - length, flags);
|
||||
|
||||
// Check for errors
|
||||
if (sent < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
received = 0;
|
||||
|
||||
// Check the destination buffer
|
||||
if (!data)
|
||||
{
|
||||
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Receive a chunk of bytes
|
||||
int sizeReceived = recv(getHandle(), static_cast<char*>(data), static_cast<int>(size), flags);
|
||||
|
||||
// Check the number of bytes received
|
||||
if (sizeReceived > 0)
|
||||
{
|
||||
received = static_cast<std::size_t>(sizeReceived);
|
||||
return Done;
|
||||
}
|
||||
else if (sizeReceived == 0)
|
||||
{
|
||||
return Socket::Disconnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::send(Packet& packet)
|
||||
{
|
||||
// TCP is a stream protocol, it doesn't preserve messages boundaries.
|
||||
// This means that we have to send the packet size first, so that the
|
||||
// receiver knows the actual end of the packet in the data stream.
|
||||
|
||||
// We allocate an extra memory block so that the size can be sent
|
||||
// together with the data in a single call. This may seem inefficient,
|
||||
// but it is actually required to avoid partial send, which could cause
|
||||
// data corruption on the receiving end.
|
||||
|
||||
// Get the data to send from the packet
|
||||
std::size_t size = 0;
|
||||
const void* data = packet.onSend(size);
|
||||
|
||||
// First convert the packet size to network byte order
|
||||
Uint32 packetSize = htonl(static_cast<Uint32>(size));
|
||||
|
||||
// Allocate memory for the data block to send
|
||||
std::vector<char> blockToSend(sizeof(packetSize) + size);
|
||||
|
||||
// Copy the packet size and data into the block to send
|
||||
std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
|
||||
if (size > 0)
|
||||
std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
|
||||
|
||||
// Send the data block
|
||||
return send(&blockToSend[0], blockToSend.size());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::receive(Packet& packet)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
packet.clear();
|
||||
|
||||
// We start by getting the size of the incoming packet
|
||||
Uint32 packetSize = 0;
|
||||
std::size_t received = 0;
|
||||
if (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
|
||||
{
|
||||
// Loop until we've received the entire size of the packet
|
||||
// (even a 4 byte variable may be received in more than one call)
|
||||
while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
|
||||
{
|
||||
char* data = reinterpret_cast<char*>(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived;
|
||||
Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received);
|
||||
m_pendingPacket.SizeReceived += received;
|
||||
|
||||
if (status != Done)
|
||||
return status;
|
||||
}
|
||||
|
||||
// The packet size has been fully received
|
||||
packetSize = ntohl(m_pendingPacket.Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The packet size has already been received in a previous call
|
||||
packetSize = ntohl(m_pendingPacket.Size);
|
||||
}
|
||||
|
||||
// Loop until we receive all the packet data
|
||||
char buffer[1024];
|
||||
while (m_pendingPacket.Data.size() < packetSize)
|
||||
{
|
||||
// Receive a chunk of data
|
||||
std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - m_pendingPacket.Data.size()), sizeof(buffer));
|
||||
Status status = receive(buffer, sizeToGet, received);
|
||||
if (status != Done)
|
||||
return status;
|
||||
|
||||
// Append it into the packet
|
||||
if (received > 0)
|
||||
{
|
||||
m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received);
|
||||
char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received;
|
||||
std::memcpy(begin, buffer, received);
|
||||
}
|
||||
}
|
||||
|
||||
// We have received all the packet data: we can copy it to the user packet
|
||||
if (!m_pendingPacket.Data.empty())
|
||||
packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size());
|
||||
|
||||
// Clear the pending packet data
|
||||
m_pendingPacket = PendingPacket();
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket::PendingPacket::PendingPacket() :
|
||||
Size (0),
|
||||
SizeReceived(0),
|
||||
Data ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/Network/IpAddress.hpp>
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Define the low-level send/receive flags, which depend on the OS
|
||||
#ifdef SFML_SYSTEM_LINUX
|
||||
const int flags = MSG_NOSIGNAL;
|
||||
#else
|
||||
const int flags = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket::TcpSocket() :
|
||||
Socket(Tcp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpSocket::getLocalPort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the local end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IpAddress TcpSocket::getRemoteAddress() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the remote end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the address
|
||||
return IpAddress::None;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpSocket::getRemotePort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the remote end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Create the remote address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
|
||||
|
||||
if (timeout <= Time::Zero)
|
||||
{
|
||||
// ----- We're not using a timeout: just try to connect -----
|
||||
|
||||
// Connect the socket
|
||||
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// Connection succeeded
|
||||
return Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ----- We're using a timeout: we'll need a few tricks to make it work -----
|
||||
|
||||
// Save the previous blocking state
|
||||
bool blocking = isBlocking();
|
||||
|
||||
// Switch to non-blocking to enable our connection timeout
|
||||
if (blocking)
|
||||
setBlocking(false);
|
||||
|
||||
// Try to connect to the remote address
|
||||
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0)
|
||||
{
|
||||
// We got instantly connected! (it may no happen a lot...)
|
||||
setBlocking(blocking);
|
||||
return Done;
|
||||
}
|
||||
|
||||
// Get the error status
|
||||
Status status = priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// If we were in non-blocking mode, return immediatly
|
||||
if (!blocking)
|
||||
return status;
|
||||
|
||||
// Otherwise, wait until something happens to our socket (success, timeout or error)
|
||||
if (status == Socket::NotReady)
|
||||
{
|
||||
// Setup the selector
|
||||
fd_set selector;
|
||||
FD_ZERO(&selector);
|
||||
FD_SET(getHandle(), &selector);
|
||||
|
||||
// Setup the timeout
|
||||
timeval time;
|
||||
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
|
||||
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
|
||||
|
||||
// Wait for something to write on our socket (which means that the connection request has returned)
|
||||
if (select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time) > 0)
|
||||
{
|
||||
// At this point the connection may have been either accepted or refused.
|
||||
// To know whether it's a success or a failure, we must check the address of the connected peer
|
||||
if (getRemoteAddress() != sf::IpAddress::None)
|
||||
{
|
||||
// Connection accepted
|
||||
status = Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Connection refused
|
||||
status = priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to connect before timeout is over
|
||||
status = priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
}
|
||||
|
||||
// Switch back to blocking mode
|
||||
setBlocking(true);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void TcpSocket::disconnect()
|
||||
{
|
||||
// Close the socket
|
||||
close();
|
||||
|
||||
// Reset the pending packet data
|
||||
m_pendingPacket = PendingPacket();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::send(const void* data, std::size_t size)
|
||||
{
|
||||
// Check the parameters
|
||||
if (!data || (size == 0))
|
||||
{
|
||||
err() << "Cannot send data over the network (no data to send)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Loop until every byte has been sent
|
||||
int sent = 0;
|
||||
int sizeToSend = static_cast<int>(size);
|
||||
for (int length = 0; length < sizeToSend; length += sent)
|
||||
{
|
||||
// Send a chunk of data
|
||||
sent = ::send(getHandle(), static_cast<const char*>(data) + length, sizeToSend - length, flags);
|
||||
|
||||
// Check for errors
|
||||
if (sent < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
received = 0;
|
||||
|
||||
// Check the destination buffer
|
||||
if (!data)
|
||||
{
|
||||
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Receive a chunk of bytes
|
||||
int sizeReceived = recv(getHandle(), static_cast<char*>(data), static_cast<int>(size), flags);
|
||||
|
||||
// Check the number of bytes received
|
||||
if (sizeReceived > 0)
|
||||
{
|
||||
received = static_cast<std::size_t>(sizeReceived);
|
||||
return Done;
|
||||
}
|
||||
else if (sizeReceived == 0)
|
||||
{
|
||||
return Socket::Disconnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::send(Packet& packet)
|
||||
{
|
||||
// TCP is a stream protocol, it doesn't preserve messages boundaries.
|
||||
// This means that we have to send the packet size first, so that the
|
||||
// receiver knows the actual end of the packet in the data stream.
|
||||
|
||||
// We allocate an extra memory block so that the size can be sent
|
||||
// together with the data in a single call. This may seem inefficient,
|
||||
// but it is actually required to avoid partial send, which could cause
|
||||
// data corruption on the receiving end.
|
||||
|
||||
// Get the data to send from the packet
|
||||
std::size_t size = 0;
|
||||
const void* data = packet.onSend(size);
|
||||
|
||||
// First convert the packet size to network byte order
|
||||
Uint32 packetSize = htonl(static_cast<Uint32>(size));
|
||||
|
||||
// Allocate memory for the data block to send
|
||||
std::vector<char> blockToSend(sizeof(packetSize) + size);
|
||||
|
||||
// Copy the packet size and data into the block to send
|
||||
std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
|
||||
if (size > 0)
|
||||
std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
|
||||
|
||||
// Send the data block
|
||||
return send(&blockToSend[0], blockToSend.size());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::receive(Packet& packet)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
packet.clear();
|
||||
|
||||
// We start by getting the size of the incoming packet
|
||||
Uint32 packetSize = 0;
|
||||
std::size_t received = 0;
|
||||
if (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
|
||||
{
|
||||
// Loop until we've received the entire size of the packet
|
||||
// (even a 4 byte variable may be received in more than one call)
|
||||
while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
|
||||
{
|
||||
char* data = reinterpret_cast<char*>(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived;
|
||||
Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received);
|
||||
m_pendingPacket.SizeReceived += received;
|
||||
|
||||
if (status != Done)
|
||||
return status;
|
||||
}
|
||||
|
||||
// The packet size has been fully received
|
||||
packetSize = ntohl(m_pendingPacket.Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The packet size has already been received in a previous call
|
||||
packetSize = ntohl(m_pendingPacket.Size);
|
||||
}
|
||||
|
||||
// Loop until we receive all the packet data
|
||||
char buffer[1024];
|
||||
while (m_pendingPacket.Data.size() < packetSize)
|
||||
{
|
||||
// Receive a chunk of data
|
||||
std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - m_pendingPacket.Data.size()), sizeof(buffer));
|
||||
Status status = receive(buffer, sizeToGet, received);
|
||||
if (status != Done)
|
||||
return status;
|
||||
|
||||
// Append it into the packet
|
||||
if (received > 0)
|
||||
{
|
||||
m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received);
|
||||
char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received;
|
||||
std::memcpy(begin, buffer, received);
|
||||
}
|
||||
}
|
||||
|
||||
// We have received all the packet data: we can copy it to the user packet
|
||||
if (!m_pendingPacket.Data.empty())
|
||||
packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size());
|
||||
|
||||
// Clear the pending packet data
|
||||
m_pendingPacket = PendingPacket();
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket::PendingPacket::PendingPacket() :
|
||||
Size (0),
|
||||
SizeReceived(0),
|
||||
Data ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,193 +1,193 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/UdpSocket.hpp>
|
||||
#include <SFML/Network/IpAddress.hpp>
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
UdpSocket::UdpSocket() :
|
||||
Socket (Udp),
|
||||
m_buffer(MaxDatagramSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short UdpSocket::getLocalPort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the local end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::bind(unsigned short port)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Bind the socket
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
|
||||
if (::bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
{
|
||||
err() << "Failed to bind socket to port " << port << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void UdpSocket::unbind()
|
||||
{
|
||||
// Simply close the socket
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Make sure that all the data will fit in one datagram
|
||||
if (size > MaxDatagramSize)
|
||||
{
|
||||
err() << "Cannot send data over the network "
|
||||
<< "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Build the target address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
|
||||
|
||||
// Send the data (unlike TCP, all the data is always sent in one call)
|
||||
int sent = sendto(getHandle(), static_cast<const char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), sizeof(address));
|
||||
|
||||
// Check for errors
|
||||
if (sent < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
received = 0;
|
||||
remoteAddress = IpAddress();
|
||||
remotePort = 0;
|
||||
|
||||
// Check the destination buffer
|
||||
if (!data)
|
||||
{
|
||||
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Data that will be filled with the other computer's address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, 0);
|
||||
|
||||
// Receive a chunk of bytes
|
||||
priv::SocketImpl::AddrLength addressSize = sizeof(address);
|
||||
int sizeReceived = recvfrom(getHandle(), static_cast<char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), &addressSize);
|
||||
|
||||
// Check for errors
|
||||
if (sizeReceived < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// Fill the sender informations
|
||||
received = static_cast<std::size_t>(sizeReceived);
|
||||
remoteAddress = IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
remotePort = ntohs(address.sin_port);
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort)
|
||||
{
|
||||
// UDP is a datagram-oriented protocol (as opposed to TCP which is a stream protocol).
|
||||
// Sending one datagram is almost safe: it may be lost but if it's received, then its data
|
||||
// is guaranteed to be ok. However, splitting a packet into multiple datagrams would be highly
|
||||
// unreliable, since datagrams may be reordered, dropped or mixed between different sources.
|
||||
// That's why SFML imposes a limit on packet size so that they can be sent in a single datagram.
|
||||
// This also removes the overhead associated to packets -- there's no size to send in addition
|
||||
// to the packet's data.
|
||||
|
||||
// Get the data to send from the packet
|
||||
std::size_t size = 0;
|
||||
const void* data = packet.onSend(size);
|
||||
|
||||
// Send it
|
||||
return send(data, size, remoteAddress, remotePort);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||
{
|
||||
// See the detailed comment in send(Packet) above.
|
||||
|
||||
// Receive the datagram
|
||||
std::size_t received = 0;
|
||||
Status status = receive(&m_buffer[0], m_buffer.size(), received, remoteAddress, remotePort);
|
||||
|
||||
// If we received valid data, we can copy it to the user packet
|
||||
packet.clear();
|
||||
if ((status == Done) && (received > 0))
|
||||
packet.onReceive(&m_buffer[0], received);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/UdpSocket.hpp>
|
||||
#include <SFML/Network/IpAddress.hpp>
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
UdpSocket::UdpSocket() :
|
||||
Socket (Udp),
|
||||
m_buffer(MaxDatagramSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short UdpSocket::getLocalPort() const
|
||||
{
|
||||
if (getHandle() != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Retrieve informations about the local end of the socket
|
||||
sockaddr_in address;
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||
{
|
||||
return ntohs(address.sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to retrieve the port
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::bind(unsigned short port)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Bind the socket
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
|
||||
if (::bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
{
|
||||
err() << "Failed to bind socket to port " << port << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void UdpSocket::unbind()
|
||||
{
|
||||
// Simply close the socket
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Make sure that all the data will fit in one datagram
|
||||
if (size > MaxDatagramSize)
|
||||
{
|
||||
err() << "Cannot send data over the network "
|
||||
<< "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Build the target address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
|
||||
|
||||
// Send the data (unlike TCP, all the data is always sent in one call)
|
||||
int sent = sendto(getHandle(), static_cast<const char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), sizeof(address));
|
||||
|
||||
// Check for errors
|
||||
if (sent < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
received = 0;
|
||||
remoteAddress = IpAddress();
|
||||
remotePort = 0;
|
||||
|
||||
// Check the destination buffer
|
||||
if (!data)
|
||||
{
|
||||
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Data that will be filled with the other computer's address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, 0);
|
||||
|
||||
// Receive a chunk of bytes
|
||||
priv::SocketImpl::AddrLength addressSize = sizeof(address);
|
||||
int sizeReceived = recvfrom(getHandle(), static_cast<char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), &addressSize);
|
||||
|
||||
// Check for errors
|
||||
if (sizeReceived < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
// Fill the sender informations
|
||||
received = static_cast<std::size_t>(sizeReceived);
|
||||
remoteAddress = IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
remotePort = ntohs(address.sin_port);
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort)
|
||||
{
|
||||
// UDP is a datagram-oriented protocol (as opposed to TCP which is a stream protocol).
|
||||
// Sending one datagram is almost safe: it may be lost but if it's received, then its data
|
||||
// is guaranteed to be ok. However, splitting a packet into multiple datagrams would be highly
|
||||
// unreliable, since datagrams may be reordered, dropped or mixed between different sources.
|
||||
// That's why SFML imposes a limit on packet size so that they can be sent in a single datagram.
|
||||
// This also removes the overhead associated to packets -- there's no size to send in addition
|
||||
// to the packet's data.
|
||||
|
||||
// Get the data to send from the packet
|
||||
std::size_t size = 0;
|
||||
const void* data = packet.onSend(size);
|
||||
|
||||
// Send it
|
||||
return send(data, size, remoteAddress, remotePort);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||
{
|
||||
// See the detailed comment in send(Packet) above.
|
||||
|
||||
// Receive the datagram
|
||||
std::size_t received = 0;
|
||||
Status status = receive(&m_buffer[0], m_buffer.size(), received, remoteAddress, remotePort);
|
||||
|
||||
// If we received valid data, we can copy it to the user packet
|
||||
packet.clear();
|
||||
if ((status == Done) && (received > 0))
|
||||
packet.onReceive(&m_buffer[0], received);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,104 +1,104 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Unix/SocketImpl.hpp>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_addr.s_addr = htonl(address);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
#if defined(SFML_SYSTEM_MACOS)
|
||||
addr.sin_len = sizeof(addr);
|
||||
#endif
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle SocketImpl::invalidSocket()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::close(SocketHandle sock)
|
||||
{
|
||||
::close(sock);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::setBlocking(SocketHandle sock, bool block)
|
||||
{
|
||||
int status = fcntl(sock, F_GETFL);
|
||||
if (block)
|
||||
fcntl(sock, F_SETFL, status & ~O_NONBLOCK);
|
||||
else
|
||||
fcntl(sock, F_SETFL, status | O_NONBLOCK);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketImpl::getErrorStatus()
|
||||
{
|
||||
// The followings are sometimes equal to EWOULDBLOCK,
|
||||
// so we have to make a special case for them in order
|
||||
// to avoid having double values in the switch case
|
||||
if ((errno == EAGAIN) || (errno == EINPROGRESS))
|
||||
return Socket::NotReady;
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
case EWOULDBLOCK : return Socket::NotReady;
|
||||
case ECONNABORTED : return Socket::Disconnected;
|
||||
case ECONNRESET : return Socket::Disconnected;
|
||||
case ETIMEDOUT : return Socket::Disconnected;
|
||||
case ENETRESET : return Socket::Disconnected;
|
||||
case ENOTCONN : return Socket::Disconnected;
|
||||
case EPIPE : return Socket::Disconnected;
|
||||
default : return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Unix/SocketImpl.hpp>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_addr.s_addr = htonl(address);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
#if defined(SFML_SYSTEM_MACOS)
|
||||
addr.sin_len = sizeof(addr);
|
||||
#endif
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle SocketImpl::invalidSocket()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::close(SocketHandle sock)
|
||||
{
|
||||
::close(sock);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::setBlocking(SocketHandle sock, bool block)
|
||||
{
|
||||
int status = fcntl(sock, F_GETFL);
|
||||
if (block)
|
||||
fcntl(sock, F_SETFL, status & ~O_NONBLOCK);
|
||||
else
|
||||
fcntl(sock, F_SETFL, status | O_NONBLOCK);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketImpl::getErrorStatus()
|
||||
{
|
||||
// The followings are sometimes equal to EWOULDBLOCK,
|
||||
// so we have to make a special case for them in order
|
||||
// to avoid having double values in the switch case
|
||||
if ((errno == EAGAIN) || (errno == EINPROGRESS))
|
||||
return Socket::NotReady;
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
case EWOULDBLOCK: return Socket::NotReady;
|
||||
case ECONNABORTED: return Socket::Disconnected;
|
||||
case ECONNRESET: return Socket::Disconnected;
|
||||
case ETIMEDOUT: return Socket::Disconnected;
|
||||
case ENETRESET: return Socket::Disconnected;
|
||||
case ENOTCONN: return Socket::Disconnected;
|
||||
case EPIPE: return Socket::Disconnected;
|
||||
default: return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,109 +1,109 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOCKETIMPL_HPP
|
||||
#define SFML_SOCKETIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Helper class implementing all the non-portable
|
||||
/// socket stuff; this is the Unix version
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SocketImpl
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef socklen_t AddrLength;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create an internal sockaddr_in address
|
||||
///
|
||||
/// \param address Target address
|
||||
/// \param port Target port
|
||||
///
|
||||
/// \return sockaddr_in ready to be used by socket functions
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static sockaddr_in createAddress(Uint32 address, unsigned short port);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the value of the invalid socket
|
||||
///
|
||||
/// \return Special value of the invalid socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static SocketHandle invalidSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close and destroy a socket
|
||||
///
|
||||
/// \param sock Handle of the socket to close
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void close(SocketHandle sock);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set a socket as blocking or non-blocking
|
||||
///
|
||||
/// \param sock Handle of the socket
|
||||
/// \param block New blocking state of the socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void setBlocking(SocketHandle sock, bool block);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the last socket error status
|
||||
///
|
||||
/// \return Status corresponding to the last socket error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Socket::Status getErrorStatus();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETIMPL_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOCKETIMPL_HPP
|
||||
#define SFML_SOCKETIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Helper class implementing all the non-portable
|
||||
/// socket stuff; this is the Unix version
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SocketImpl
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef socklen_t AddrLength;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create an internal sockaddr_in address
|
||||
///
|
||||
/// \param address Target address
|
||||
/// \param port Target port
|
||||
///
|
||||
/// \return sockaddr_in ready to be used by socket functions
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static sockaddr_in createAddress(Uint32 address, unsigned short port);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the value of the invalid socket
|
||||
///
|
||||
/// \return Special value of the invalid socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static SocketHandle invalidSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close and destroy a socket
|
||||
///
|
||||
/// \param sock Handle of the socket to close
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void close(SocketHandle sock);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set a socket as blocking or non-blocking
|
||||
///
|
||||
/// \param sock Handle of the socket
|
||||
/// \param block New blocking state of the socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void setBlocking(SocketHandle sock, bool block);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the last socket error status
|
||||
///
|
||||
/// \return Status corresponding to the last socket error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Socket::Status getErrorStatus();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETIMPL_HPP
|
||||
|
|
|
@ -1,112 +1,112 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Win32/SocketImpl.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_addr.s_addr = htonl(address);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle SocketImpl::invalidSocket()
|
||||
{
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::close(SocketHandle sock)
|
||||
{
|
||||
closesocket(sock);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::setBlocking(SocketHandle sock, bool block)
|
||||
{
|
||||
u_long blocking = block ? 0 : 1;
|
||||
ioctlsocket(sock, FIONBIO, &blocking);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketImpl::getErrorStatus()
|
||||
{
|
||||
switch (WSAGetLastError())
|
||||
{
|
||||
case WSAEWOULDBLOCK : return Socket::NotReady;
|
||||
case WSAEALREADY : return Socket::NotReady;
|
||||
case WSAECONNABORTED : return Socket::Disconnected;
|
||||
case WSAECONNRESET : return Socket::Disconnected;
|
||||
case WSAETIMEDOUT : return Socket::Disconnected;
|
||||
case WSAENETRESET : return Socket::Disconnected;
|
||||
case WSAENOTCONN : return Socket::Disconnected;
|
||||
case WSAEISCONN : return Socket::Done; // when connecting a non-blocking socket
|
||||
default : return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Windows needs some initialization and cleanup to get
|
||||
// sockets working properly... so let's create a class that will
|
||||
// do it automatically
|
||||
////////////////////////////////////////////////////////////
|
||||
struct SocketInitializer
|
||||
{
|
||||
SocketInitializer()
|
||||
{
|
||||
WSADATA init;
|
||||
WSAStartup(MAKEWORD(2, 2), &init);
|
||||
}
|
||||
|
||||
~SocketInitializer()
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
};
|
||||
|
||||
SocketInitializer globalInitializer;
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Win32/SocketImpl.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_addr.s_addr = htonl(address);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle SocketImpl::invalidSocket()
|
||||
{
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::close(SocketHandle sock)
|
||||
{
|
||||
closesocket(sock);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketImpl::setBlocking(SocketHandle sock, bool block)
|
||||
{
|
||||
u_long blocking = block ? 0 : 1;
|
||||
ioctlsocket(sock, FIONBIO, &blocking);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketImpl::getErrorStatus()
|
||||
{
|
||||
switch (WSAGetLastError())
|
||||
{
|
||||
case WSAEWOULDBLOCK: return Socket::NotReady;
|
||||
case WSAEALREADY: return Socket::NotReady;
|
||||
case WSAECONNABORTED: return Socket::Disconnected;
|
||||
case WSAECONNRESET: return Socket::Disconnected;
|
||||
case WSAETIMEDOUT: return Socket::Disconnected;
|
||||
case WSAENETRESET: return Socket::Disconnected;
|
||||
case WSAENOTCONN: return Socket::Disconnected;
|
||||
case WSAEISCONN: return Socket::Done; // when connecting a non-blocking socket
|
||||
default: return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Windows needs some initialization and cleanup to get
|
||||
// sockets working properly... so let's create a class that will
|
||||
// do it automatically
|
||||
////////////////////////////////////////////////////////////
|
||||
struct SocketInitializer
|
||||
{
|
||||
SocketInitializer()
|
||||
{
|
||||
WSADATA init;
|
||||
WSAStartup(MAKEWORD(2, 2), &init);
|
||||
}
|
||||
|
||||
~SocketInitializer()
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
};
|
||||
|
||||
SocketInitializer globalInitializer;
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,112 +1,112 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOCKETIMPL_HPP
|
||||
#define SFML_SOCKETIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#ifdef _WIN32_WINDOWS
|
||||
#undef _WIN32_WINDOWS
|
||||
#endif
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINDOWS 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Helper class implementing all the non-portable
|
||||
/// socket stuff; this is the Windows version
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SocketImpl
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef int AddrLength;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create an internal sockaddr_in address
|
||||
///
|
||||
/// \param address Target address
|
||||
/// \param port Target port
|
||||
///
|
||||
/// \return sockaddr_in ready to be used by socket functions
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static sockaddr_in createAddress(Uint32 address, unsigned short port);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the value of the invalid socket
|
||||
///
|
||||
/// \return Special value of the invalid socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static SocketHandle invalidSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close and destroy a socket
|
||||
///
|
||||
/// \param sock Handle of the socket to close
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void close(SocketHandle sock);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set a socket as blocking or non-blocking
|
||||
///
|
||||
/// \param sock Handle of the socket
|
||||
/// \param block New blocking state of the socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void setBlocking(SocketHandle sock, bool block);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the last socket error status
|
||||
///
|
||||
/// \return Status corresponding to the last socket error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Socket::Status getErrorStatus();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETIMPL_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_SOCKETIMPL_HPP
|
||||
#define SFML_SOCKETIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#ifdef _WIN32_WINDOWS
|
||||
#undef _WIN32_WINDOWS
|
||||
#endif
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINDOWS 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Helper class implementing all the non-portable
|
||||
/// socket stuff; this is the Windows version
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SocketImpl
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef int AddrLength;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create an internal sockaddr_in address
|
||||
///
|
||||
/// \param address Target address
|
||||
/// \param port Target port
|
||||
///
|
||||
/// \return sockaddr_in ready to be used by socket functions
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static sockaddr_in createAddress(Uint32 address, unsigned short port);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the value of the invalid socket
|
||||
///
|
||||
/// \return Special value of the invalid socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static SocketHandle invalidSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close and destroy a socket
|
||||
///
|
||||
/// \param sock Handle of the socket to close
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void close(SocketHandle sock);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set a socket as blocking or non-blocking
|
||||
///
|
||||
/// \param sock Handle of the socket
|
||||
/// \param block New blocking state of the socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void setBlocking(SocketHandle sock, bool block);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the last socket error status
|
||||
///
|
||||
/// \return Status corresponding to the last socket error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Socket::Status getErrorStatus();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETIMPL_HPP
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class SFML_SYSTEM_API ResourceStream : public InputStream
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
|
@ -97,7 +97,7 @@ public :
|
|||
////////////////////////////////////////////////////////////
|
||||
Int64 getSize();
|
||||
|
||||
private :
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
|
|
|
@ -1,99 +1,99 @@
|
|||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/System)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/System)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${SRCROOT}/Clock.cpp
|
||||
${INCROOT}/Clock.hpp
|
||||
${SRCROOT}/Err.cpp
|
||||
${INCROOT}/Err.hpp
|
||||
${INCROOT}/Export.hpp
|
||||
${INCROOT}/InputStream.hpp
|
||||
${SRCROOT}/Lock.cpp
|
||||
${INCROOT}/Lock.hpp
|
||||
${SRCROOT}/Mutex.cpp
|
||||
${INCROOT}/Mutex.hpp
|
||||
${INCROOT}/NonCopyable.hpp
|
||||
${SRCROOT}/Sleep.cpp
|
||||
${INCROOT}/Sleep.hpp
|
||||
${SRCROOT}/String.cpp
|
||||
${INCROOT}/String.hpp
|
||||
${INCROOT}/String.inl
|
||||
${SRCROOT}/Thread.cpp
|
||||
${INCROOT}/Thread.hpp
|
||||
${INCROOT}/Thread.inl
|
||||
${SRCROOT}/ThreadLocal.cpp
|
||||
${INCROOT}/ThreadLocal.hpp
|
||||
${INCROOT}/ThreadLocalPtr.hpp
|
||||
${INCROOT}/ThreadLocalPtr.inl
|
||||
${SRCROOT}/Time.cpp
|
||||
${INCROOT}/Time.hpp
|
||||
${INCROOT}/Utf.hpp
|
||||
${INCROOT}/Utf.inl
|
||||
${INCROOT}/Vector2.hpp
|
||||
${INCROOT}/Vector2.inl
|
||||
${INCROOT}/Vector3.hpp
|
||||
${INCROOT}/Vector3.inl
|
||||
)
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# add platform specific sources
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Win32/ClockImpl.cpp
|
||||
${SRCROOT}/Win32/ClockImpl.hpp
|
||||
${SRCROOT}/Win32/MutexImpl.cpp
|
||||
${SRCROOT}/Win32/MutexImpl.hpp
|
||||
${SRCROOT}/Win32/SleepImpl.cpp
|
||||
${SRCROOT}/Win32/SleepImpl.hpp
|
||||
${SRCROOT}/Win32/ThreadImpl.cpp
|
||||
${SRCROOT}/Win32/ThreadImpl.hpp
|
||||
${SRCROOT}/Win32/ThreadLocalImpl.cpp
|
||||
${SRCROOT}/Win32/ThreadLocalImpl.hpp
|
||||
)
|
||||
source_group("windows" FILES ${PLATFORM_SRC})
|
||||
else()
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Unix/ClockImpl.cpp
|
||||
${SRCROOT}/Unix/ClockImpl.hpp
|
||||
${SRCROOT}/Unix/MutexImpl.cpp
|
||||
${SRCROOT}/Unix/MutexImpl.hpp
|
||||
${SRCROOT}/Unix/SleepImpl.cpp
|
||||
${SRCROOT}/Unix/SleepImpl.hpp
|
||||
${SRCROOT}/Unix/ThreadImpl.cpp
|
||||
${SRCROOT}/Unix/ThreadImpl.hpp
|
||||
${SRCROOT}/Unix/ThreadLocalImpl.cpp
|
||||
${SRCROOT}/Unix/ThreadLocalImpl.hpp
|
||||
)
|
||||
|
||||
if(SFML_OS_ANDROID)
|
||||
set(PLATFORM_SRC ${PLATFORM_SRC}
|
||||
${SRCROOT}/Android/Activity.hpp
|
||||
${SRCROOT}/Android/Activity.cpp
|
||||
${SRCROOT}/Android/ResourceStream.cpp
|
||||
${SRCROOT}/Android/ResourceStream.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
source_group("unix" FILES ${PLATFORM_SRC})
|
||||
endif()
|
||||
|
||||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/System)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/System)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${SRCROOT}/Clock.cpp
|
||||
${INCROOT}/Clock.hpp
|
||||
${SRCROOT}/Err.cpp
|
||||
${INCROOT}/Err.hpp
|
||||
${INCROOT}/Export.hpp
|
||||
${INCROOT}/InputStream.hpp
|
||||
${SRCROOT}/Lock.cpp
|
||||
${INCROOT}/Lock.hpp
|
||||
${SRCROOT}/Mutex.cpp
|
||||
${INCROOT}/Mutex.hpp
|
||||
${INCROOT}/NonCopyable.hpp
|
||||
${SRCROOT}/Sleep.cpp
|
||||
${INCROOT}/Sleep.hpp
|
||||
${SRCROOT}/String.cpp
|
||||
${INCROOT}/String.hpp
|
||||
${INCROOT}/String.inl
|
||||
${SRCROOT}/Thread.cpp
|
||||
${INCROOT}/Thread.hpp
|
||||
${INCROOT}/Thread.inl
|
||||
${SRCROOT}/ThreadLocal.cpp
|
||||
${INCROOT}/ThreadLocal.hpp
|
||||
${INCROOT}/ThreadLocalPtr.hpp
|
||||
${INCROOT}/ThreadLocalPtr.inl
|
||||
${SRCROOT}/Time.cpp
|
||||
${INCROOT}/Time.hpp
|
||||
${INCROOT}/Utf.hpp
|
||||
${INCROOT}/Utf.inl
|
||||
${INCROOT}/Vector2.hpp
|
||||
${INCROOT}/Vector2.inl
|
||||
${INCROOT}/Vector3.hpp
|
||||
${INCROOT}/Vector3.inl
|
||||
)
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# add platform specific sources
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Win32/ClockImpl.cpp
|
||||
${SRCROOT}/Win32/ClockImpl.hpp
|
||||
${SRCROOT}/Win32/MutexImpl.cpp
|
||||
${SRCROOT}/Win32/MutexImpl.hpp
|
||||
${SRCROOT}/Win32/SleepImpl.cpp
|
||||
${SRCROOT}/Win32/SleepImpl.hpp
|
||||
${SRCROOT}/Win32/ThreadImpl.cpp
|
||||
${SRCROOT}/Win32/ThreadImpl.hpp
|
||||
${SRCROOT}/Win32/ThreadLocalImpl.cpp
|
||||
${SRCROOT}/Win32/ThreadLocalImpl.hpp
|
||||
)
|
||||
source_group("windows" FILES ${PLATFORM_SRC})
|
||||
else()
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Unix/ClockImpl.cpp
|
||||
${SRCROOT}/Unix/ClockImpl.hpp
|
||||
${SRCROOT}/Unix/MutexImpl.cpp
|
||||
${SRCROOT}/Unix/MutexImpl.hpp
|
||||
${SRCROOT}/Unix/SleepImpl.cpp
|
||||
${SRCROOT}/Unix/SleepImpl.hpp
|
||||
${SRCROOT}/Unix/ThreadImpl.cpp
|
||||
${SRCROOT}/Unix/ThreadImpl.hpp
|
||||
${SRCROOT}/Unix/ThreadLocalImpl.cpp
|
||||
${SRCROOT}/Unix/ThreadLocalImpl.hpp
|
||||
)
|
||||
|
||||
if(SFML_OS_ANDROID)
|
||||
set(PLATFORM_SRC ${PLATFORM_SRC}
|
||||
${SRCROOT}/Android/Activity.hpp
|
||||
${SRCROOT}/Android/Activity.cpp
|
||||
${SRCROOT}/Android/ResourceStream.cpp
|
||||
${SRCROOT}/Android/ResourceStream.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
source_group("unix" FILES ${PLATFORM_SRC})
|
||||
endif()
|
||||
|
||||
# build the list of external libraries to link
|
||||
if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX)
|
||||
list(APPEND SYSTEM_EXT_LIBS pthread)
|
||||
endif()
|
||||
if(SFML_OS_LINUX)
|
||||
list(APPEND SYSTEM_EXT_LIBS rt)
|
||||
endif()
|
||||
if(SFML_OS_WINDOWS)
|
||||
list(APPEND SYSTEM_EXT_LIBS winmm)
|
||||
endif()
|
||||
if(SFML_OS_ANDROID)
|
||||
list(APPEND SYSTEM_EXT_LIBS android log)
|
||||
endif()
|
||||
|
||||
# define the sfml-system target
|
||||
sfml_add_library(sfml-system
|
||||
SOURCES ${SRC} ${PLATFORM_SRC}
|
||||
EXTERNAL_LIBS ${SYSTEM_EXT_LIBS})
|
||||
list(APPEND SYSTEM_EXT_LIBS pthread)
|
||||
endif()
|
||||
if(SFML_OS_LINUX)
|
||||
list(APPEND SYSTEM_EXT_LIBS rt)
|
||||
endif()
|
||||
if(SFML_OS_WINDOWS)
|
||||
list(APPEND SYSTEM_EXT_LIBS winmm)
|
||||
endif()
|
||||
if(SFML_OS_ANDROID)
|
||||
list(APPEND SYSTEM_EXT_LIBS android log)
|
||||
endif()
|
||||
|
||||
# define the sfml-system target
|
||||
sfml_add_library(sfml-system
|
||||
SOURCES ${SRC} ${PLATFORM_SRC}
|
||||
EXTERNAL_LIBS ${SYSTEM_EXT_LIBS})
|
||||
|
|
|
@ -1,63 +1,63 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Clock.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/ClockImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/ClockImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Clock::Clock() :
|
||||
m_startTime(priv::ClockImpl::getCurrentTime())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Clock::getElapsedTime() const
|
||||
{
|
||||
return priv::ClockImpl::getCurrentTime() - m_startTime;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Clock::restart()
|
||||
{
|
||||
Time now = priv::ClockImpl::getCurrentTime();
|
||||
Time elapsed = now - m_startTime;
|
||||
m_startTime = now;
|
||||
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Clock.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/ClockImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/ClockImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Clock::Clock() :
|
||||
m_startTime(priv::ClockImpl::getCurrentTime())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Clock::getElapsedTime() const
|
||||
{
|
||||
return priv::ClockImpl::getCurrentTime() - m_startTime;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time Clock::restart()
|
||||
{
|
||||
Time now = priv::ClockImpl::getCurrentTime();
|
||||
Time elapsed = now - m_startTime;
|
||||
m_startTime = now;
|
||||
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,110 +1,110 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <streambuf>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// This class will be used as the default streambuf of sf::Err,
|
||||
// it outputs to stderr by default (to keep the default behaviour)
|
||||
class DefaultErrStreamBuf : public std::streambuf
|
||||
{
|
||||
public :
|
||||
|
||||
DefaultErrStreamBuf()
|
||||
{
|
||||
// Allocate the write buffer
|
||||
static const int size = 64;
|
||||
char* buffer = new char[size];
|
||||
setp(buffer, buffer + size);
|
||||
}
|
||||
|
||||
~DefaultErrStreamBuf()
|
||||
{
|
||||
// Synchronize
|
||||
sync();
|
||||
|
||||
// Delete the write buffer
|
||||
delete[] pbase();
|
||||
}
|
||||
|
||||
private :
|
||||
|
||||
virtual int overflow(int character)
|
||||
{
|
||||
if ((character != EOF) && (pptr() != epptr()))
|
||||
{
|
||||
// Valid character
|
||||
return sputc(static_cast<char>(character));
|
||||
}
|
||||
else if (character != EOF)
|
||||
{
|
||||
// Not enough space in the buffer: synchronize output and try again
|
||||
sync();
|
||||
return overflow(character);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid character: synchronize output
|
||||
return sync();
|
||||
}
|
||||
}
|
||||
|
||||
virtual int sync()
|
||||
{
|
||||
// Check if there is something into the write buffer
|
||||
if (pbase() != pptr())
|
||||
{
|
||||
// Print the contents of the write buffer into the standard error output
|
||||
std::size_t size = static_cast<int>(pptr() - pbase());
|
||||
fwrite(pbase(), 1, size, stderr);
|
||||
|
||||
// Reset the pointer position to the beginning of the write buffer
|
||||
setp(pbase(), epptr());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
std::ostream& err()
|
||||
{
|
||||
static DefaultErrStreamBuf buffer;
|
||||
static std::ostream stream(&buffer);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <streambuf>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// This class will be used as the default streambuf of sf::Err,
|
||||
// it outputs to stderr by default (to keep the default behaviour)
|
||||
class DefaultErrStreamBuf : public std::streambuf
|
||||
{
|
||||
public:
|
||||
|
||||
DefaultErrStreamBuf()
|
||||
{
|
||||
// Allocate the write buffer
|
||||
static const int size = 64;
|
||||
char* buffer = new char[size];
|
||||
setp(buffer, buffer + size);
|
||||
}
|
||||
|
||||
~DefaultErrStreamBuf()
|
||||
{
|
||||
// Synchronize
|
||||
sync();
|
||||
|
||||
// Delete the write buffer
|
||||
delete[] pbase();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual int overflow(int character)
|
||||
{
|
||||
if ((character != EOF) && (pptr() != epptr()))
|
||||
{
|
||||
// Valid character
|
||||
return sputc(static_cast<char>(character));
|
||||
}
|
||||
else if (character != EOF)
|
||||
{
|
||||
// Not enough space in the buffer: synchronize output and try again
|
||||
sync();
|
||||
return overflow(character);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid character: synchronize output
|
||||
return sync();
|
||||
}
|
||||
}
|
||||
|
||||
virtual int sync()
|
||||
{
|
||||
// Check if there is something into the write buffer
|
||||
if (pbase() != pptr())
|
||||
{
|
||||
// Print the contents of the write buffer into the standard error output
|
||||
std::size_t size = static_cast<int>(pptr() - pbase());
|
||||
fwrite(pbase(), 1, size, stderr);
|
||||
|
||||
// Reset the pointer position to the beginning of the write buffer
|
||||
setp(pbase(), epptr());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
std::ostream& err()
|
||||
{
|
||||
static DefaultErrStreamBuf buffer;
|
||||
static std::ostream stream(&buffer);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Lock::Lock(Mutex& mutex) :
|
||||
m_mutex(mutex)
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Lock::~Lock()
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Lock::Lock(Mutex& mutex) :
|
||||
m_mutex(mutex)
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Lock::~Lock()
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,66 +1,66 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/MutexImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/MutexImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Mutex::Mutex()
|
||||
{
|
||||
m_mutexImpl = new priv::MutexImpl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
delete m_mutexImpl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Mutex::lock()
|
||||
{
|
||||
m_mutexImpl->lock();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Mutex::unlock()
|
||||
{
|
||||
m_mutexImpl->unlock();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/MutexImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/MutexImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Mutex::Mutex()
|
||||
{
|
||||
m_mutexImpl = new priv::MutexImpl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
delete m_mutexImpl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Mutex::lock()
|
||||
{
|
||||
m_mutexImpl->lock();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Mutex::unlock()
|
||||
{
|
||||
m_mutexImpl->unlock();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Sleep.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/SleepImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/SleepImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void sleep(Time duration)
|
||||
{
|
||||
if (duration >= Time::Zero)
|
||||
priv::sleepImpl(duration);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Sleep.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/SleepImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/SleepImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void sleep(Time duration)
|
||||
{
|
||||
if (duration >= Time::Zero)
|
||||
priv::sleepImpl(duration);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,400 +1,400 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/String.hpp>
|
||||
#include <SFML/System/Utf.hpp>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::size_t String::InvalidPos = std::basic_string<Uint32>::npos;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(char ansiChar, const std::locale& locale)
|
||||
{
|
||||
m_string += Utf32::decodeAnsi(ansiChar, locale);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(wchar_t wideChar)
|
||||
{
|
||||
m_string += Utf32::decodeWide(wideChar);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(Uint32 utf32Char)
|
||||
{
|
||||
m_string += utf32Char;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const char* ansiString, const std::locale& locale)
|
||||
{
|
||||
if (ansiString)
|
||||
{
|
||||
std::size_t length = strlen(ansiString);
|
||||
if (length > 0)
|
||||
{
|
||||
m_string.reserve(length + 1);
|
||||
Utf32::fromAnsi(ansiString, ansiString + length, std::back_inserter(m_string), locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::string& ansiString, const std::locale& locale)
|
||||
{
|
||||
m_string.reserve(ansiString.length() + 1);
|
||||
Utf32::fromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_string), locale);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const wchar_t* wideString)
|
||||
{
|
||||
if (wideString)
|
||||
{
|
||||
std::size_t length = std::wcslen(wideString);
|
||||
if (length > 0)
|
||||
{
|
||||
m_string.reserve(length + 1);
|
||||
Utf32::fromWide(wideString, wideString + length, std::back_inserter(m_string));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::wstring& wideString)
|
||||
{
|
||||
m_string.reserve(wideString.length() + 1);
|
||||
Utf32::fromWide(wideString.begin(), wideString.end(), std::back_inserter(m_string));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const Uint32* utf32String)
|
||||
{
|
||||
if (utf32String)
|
||||
m_string = utf32String;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::basic_string<Uint32>& utf32String) :
|
||||
m_string(utf32String)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const String& copy) :
|
||||
m_string(copy.m_string)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::operator std::string() const
|
||||
{
|
||||
return toAnsiString();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::operator std::wstring() const
|
||||
{
|
||||
return toWideString();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string String::toAnsiString(const std::locale& locale) const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::string output;
|
||||
output.reserve(m_string.length() + 1);
|
||||
|
||||
// Convert
|
||||
Utf32::toAnsi(m_string.begin(), m_string.end(), std::back_inserter(output), 0, locale);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::wstring String::toWideString() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::wstring output;
|
||||
output.reserve(m_string.length() + 1);
|
||||
|
||||
// Convert
|
||||
Utf32::toWide(m_string.begin(), m_string.end(), std::back_inserter(output), 0);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint8> String::toUtf8() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::basic_string<Uint8> output;
|
||||
output.reserve(m_string.length());
|
||||
|
||||
// Convert
|
||||
Utf32::toUtf8(m_string.begin(), m_string.end(), std::back_inserter(output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint16> String::toUtf16() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::basic_string<Uint16> output;
|
||||
output.reserve(m_string.length());
|
||||
|
||||
// Convert
|
||||
Utf32::toUtf16(m_string.begin(), m_string.end(), std::back_inserter(output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint32> String::toUtf32() const
|
||||
{
|
||||
return m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String& String::operator =(const String& right)
|
||||
{
|
||||
m_string = right.m_string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String& String::operator +=(const String& right)
|
||||
{
|
||||
m_string += right.m_string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 String::operator [](std::size_t index) const
|
||||
{
|
||||
return m_string[index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32& String::operator [](std::size_t index)
|
||||
{
|
||||
return m_string[index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::clear()
|
||||
{
|
||||
m_string.clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t String::getSize() const
|
||||
{
|
||||
return m_string.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool String::isEmpty() const
|
||||
{
|
||||
return m_string.empty();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::erase(std::size_t position, std::size_t count)
|
||||
{
|
||||
m_string.erase(position, count);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::insert(std::size_t position, const String& str)
|
||||
{
|
||||
m_string.insert(position, str.m_string);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t String::find(const String& str, std::size_t start) const
|
||||
{
|
||||
return m_string.find(str.m_string, start);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::replace(std::size_t position, std::size_t length, const String& replaceWith)
|
||||
{
|
||||
m_string.replace(position, length, replaceWith.m_string);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::replace(const String& searchFor, const String& replaceWith)
|
||||
{
|
||||
std::size_t step = replaceWith.getSize();
|
||||
std::size_t len = searchFor.getSize();
|
||||
std::size_t pos = find(searchFor);
|
||||
|
||||
// Replace each occurence of search
|
||||
while (pos != InvalidPos)
|
||||
{
|
||||
replace(pos, len, replaceWith);
|
||||
pos = find(searchFor, pos + step);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String String::substring(std::size_t position, std::size_t length) const
|
||||
{
|
||||
return m_string.substr(position, length);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Uint32* String::getData() const
|
||||
{
|
||||
return m_string.c_str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::Iterator String::begin()
|
||||
{
|
||||
return m_string.begin();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::ConstIterator String::begin() const
|
||||
{
|
||||
return m_string.begin();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::Iterator String::end()
|
||||
{
|
||||
return m_string.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::ConstIterator String::end() const
|
||||
{
|
||||
return m_string.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const String& left, const String& right)
|
||||
{
|
||||
return left.m_string == right.m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(const String& left, const String& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <(const String& left, const String& right)
|
||||
{
|
||||
return left.m_string < right.m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >(const String& left, const String& right)
|
||||
{
|
||||
return right < left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <=(const String& left, const String& right)
|
||||
{
|
||||
return !(right < left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >=(const String& left, const String& right)
|
||||
{
|
||||
return !(left < right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String operator +(const String& left, const String& right)
|
||||
{
|
||||
String string = left;
|
||||
string += right;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/String.hpp>
|
||||
#include <SFML/System/Utf.hpp>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::size_t String::InvalidPos = std::basic_string<Uint32>::npos;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(char ansiChar, const std::locale& locale)
|
||||
{
|
||||
m_string += Utf32::decodeAnsi(ansiChar, locale);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(wchar_t wideChar)
|
||||
{
|
||||
m_string += Utf32::decodeWide(wideChar);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(Uint32 utf32Char)
|
||||
{
|
||||
m_string += utf32Char;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const char* ansiString, const std::locale& locale)
|
||||
{
|
||||
if (ansiString)
|
||||
{
|
||||
std::size_t length = strlen(ansiString);
|
||||
if (length > 0)
|
||||
{
|
||||
m_string.reserve(length + 1);
|
||||
Utf32::fromAnsi(ansiString, ansiString + length, std::back_inserter(m_string), locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::string& ansiString, const std::locale& locale)
|
||||
{
|
||||
m_string.reserve(ansiString.length() + 1);
|
||||
Utf32::fromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_string), locale);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const wchar_t* wideString)
|
||||
{
|
||||
if (wideString)
|
||||
{
|
||||
std::size_t length = std::wcslen(wideString);
|
||||
if (length > 0)
|
||||
{
|
||||
m_string.reserve(length + 1);
|
||||
Utf32::fromWide(wideString, wideString + length, std::back_inserter(m_string));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::wstring& wideString)
|
||||
{
|
||||
m_string.reserve(wideString.length() + 1);
|
||||
Utf32::fromWide(wideString.begin(), wideString.end(), std::back_inserter(m_string));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const Uint32* utf32String)
|
||||
{
|
||||
if (utf32String)
|
||||
m_string = utf32String;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::basic_string<Uint32>& utf32String) :
|
||||
m_string(utf32String)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const String& copy) :
|
||||
m_string(copy.m_string)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::operator std::string() const
|
||||
{
|
||||
return toAnsiString();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::operator std::wstring() const
|
||||
{
|
||||
return toWideString();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string String::toAnsiString(const std::locale& locale) const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::string output;
|
||||
output.reserve(m_string.length() + 1);
|
||||
|
||||
// Convert
|
||||
Utf32::toAnsi(m_string.begin(), m_string.end(), std::back_inserter(output), 0, locale);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::wstring String::toWideString() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::wstring output;
|
||||
output.reserve(m_string.length() + 1);
|
||||
|
||||
// Convert
|
||||
Utf32::toWide(m_string.begin(), m_string.end(), std::back_inserter(output), 0);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint8> String::toUtf8() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::basic_string<Uint8> output;
|
||||
output.reserve(m_string.length());
|
||||
|
||||
// Convert
|
||||
Utf32::toUtf8(m_string.begin(), m_string.end(), std::back_inserter(output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint16> String::toUtf16() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::basic_string<Uint16> output;
|
||||
output.reserve(m_string.length());
|
||||
|
||||
// Convert
|
||||
Utf32::toUtf16(m_string.begin(), m_string.end(), std::back_inserter(output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::basic_string<Uint32> String::toUtf32() const
|
||||
{
|
||||
return m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String& String::operator =(const String& right)
|
||||
{
|
||||
m_string = right.m_string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String& String::operator +=(const String& right)
|
||||
{
|
||||
m_string += right.m_string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 String::operator [](std::size_t index) const
|
||||
{
|
||||
return m_string[index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32& String::operator [](std::size_t index)
|
||||
{
|
||||
return m_string[index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::clear()
|
||||
{
|
||||
m_string.clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t String::getSize() const
|
||||
{
|
||||
return m_string.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool String::isEmpty() const
|
||||
{
|
||||
return m_string.empty();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::erase(std::size_t position, std::size_t count)
|
||||
{
|
||||
m_string.erase(position, count);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::insert(std::size_t position, const String& str)
|
||||
{
|
||||
m_string.insert(position, str.m_string);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t String::find(const String& str, std::size_t start) const
|
||||
{
|
||||
return m_string.find(str.m_string, start);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::replace(std::size_t position, std::size_t length, const String& replaceWith)
|
||||
{
|
||||
m_string.replace(position, length, replaceWith.m_string);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::replace(const String& searchFor, const String& replaceWith)
|
||||
{
|
||||
std::size_t step = replaceWith.getSize();
|
||||
std::size_t len = searchFor.getSize();
|
||||
std::size_t pos = find(searchFor);
|
||||
|
||||
// Replace each occurence of search
|
||||
while (pos != InvalidPos)
|
||||
{
|
||||
replace(pos, len, replaceWith);
|
||||
pos = find(searchFor, pos + step);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String String::substring(std::size_t position, std::size_t length) const
|
||||
{
|
||||
return m_string.substr(position, length);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Uint32* String::getData() const
|
||||
{
|
||||
return m_string.c_str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::Iterator String::begin()
|
||||
{
|
||||
return m_string.begin();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::ConstIterator String::begin() const
|
||||
{
|
||||
return m_string.begin();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::Iterator String::end()
|
||||
{
|
||||
return m_string.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::ConstIterator String::end() const
|
||||
{
|
||||
return m_string.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const String& left, const String& right)
|
||||
{
|
||||
return left.m_string == right.m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(const String& left, const String& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <(const String& left, const String& right)
|
||||
{
|
||||
return left.m_string < right.m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >(const String& left, const String& right)
|
||||
{
|
||||
return right < left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <=(const String& left, const String& right)
|
||||
{
|
||||
return !(right < left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >=(const String& left, const String& right)
|
||||
{
|
||||
return !(left < right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String operator +(const String& left, const String& right)
|
||||
{
|
||||
String string = left;
|
||||
string += right;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,86 +1,86 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Thread.hpp>
|
||||
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/ThreadImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/ThreadImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Thread::~Thread()
|
||||
{
|
||||
wait();
|
||||
delete m_entryPoint;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::launch()
|
||||
{
|
||||
wait();
|
||||
m_impl = new priv::ThreadImpl(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::wait()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->wait();
|
||||
delete m_impl;
|
||||
m_impl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::terminate()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->terminate();
|
||||
delete m_impl;
|
||||
m_impl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::run()
|
||||
{
|
||||
m_entryPoint->run();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Thread.hpp>
|
||||
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/ThreadImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/ThreadImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Thread::~Thread()
|
||||
{
|
||||
wait();
|
||||
delete m_entryPoint;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::launch()
|
||||
{
|
||||
wait();
|
||||
m_impl = new priv::ThreadImpl(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::wait()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->wait();
|
||||
delete m_impl;
|
||||
m_impl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::terminate()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->terminate();
|
||||
delete m_impl;
|
||||
m_impl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Thread::run()
|
||||
{
|
||||
m_entryPoint->run();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,67 +1,67 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/ThreadLocal.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/ThreadLocalImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/ThreadLocalImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocal::ThreadLocal(void* value)
|
||||
{
|
||||
m_impl = new priv::ThreadLocalImpl;
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocal::~ThreadLocal()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadLocal::setValue(void* value)
|
||||
{
|
||||
m_impl->setValue(value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadLocal::getValue() const
|
||||
{
|
||||
return m_impl->getValue();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/ThreadLocal.hpp>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
#include <SFML/System/Win32/ThreadLocalImpl.hpp>
|
||||
#else
|
||||
#include <SFML/System/Unix/ThreadLocalImpl.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocal::ThreadLocal(void* value)
|
||||
{
|
||||
m_impl = new priv::ThreadLocalImpl;
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocal::~ThreadLocal()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadLocal::setValue(void* value)
|
||||
{
|
||||
m_impl->setValue(value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadLocal::getValue() const
|
||||
{
|
||||
return m_impl->getValue();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class ClockImpl
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current time
|
||||
|
|
|
@ -1,69 +1,69 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Unix/MutexImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
// Make it recursive to follow the expected behaviour
|
||||
pthread_mutexattr_t attributes;
|
||||
pthread_mutexattr_init(&attributes);
|
||||
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
pthread_mutex_init(&m_mutex, &attributes);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Unix/MutexImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
// Make it recursive to follow the expected behaviour
|
||||
pthread_mutexattr_t attributes;
|
||||
pthread_mutexattr_init(&attributes);
|
||||
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
pthread_mutex_init(&m_mutex, &attributes);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,83 +1,83 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_MUTEXIMPL_HPP
|
||||
#define SFML_MUTEXIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of mutexes
|
||||
////////////////////////////////////////////////////////////
|
||||
class MutexImpl : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Lock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void lock();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unlock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void unlock();
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
pthread_mutex_t m_mutex; ///< pthread handle of the mutex
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_MUTEXIMPL_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_MUTEXIMPL_HPP
|
||||
#define SFML_MUTEXIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of mutexes
|
||||
////////////////////////////////////////////////////////////
|
||||
class MutexImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Lock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void lock();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unlock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
pthread_mutex_t m_mutex; ///< pthread handle of the mutex
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_MUTEXIMPL_HPP
|
||||
|
|
|
@ -1,94 +1,94 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Unix/ThreadImpl.hpp>
|
||||
#include <SFML/System/Thread.hpp>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl::ThreadImpl(Thread* owner) :
|
||||
m_isActive(true)
|
||||
{
|
||||
m_isActive = pthread_create(&m_thread, NULL, &ThreadImpl::entryPoint, owner) == 0;
|
||||
|
||||
if (!m_isActive)
|
||||
std::cerr << "Failed to create thread" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::wait()
|
||||
{
|
||||
if (m_isActive)
|
||||
{
|
||||
assert(pthread_equal(pthread_self(), m_thread) == 0); // A thread cannot wait for itself!
|
||||
pthread_join(m_thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::terminate()
|
||||
{
|
||||
if (m_isActive)
|
||||
{
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
pthread_cancel(m_thread);
|
||||
#else
|
||||
// See http://stackoverflow.com/questions/4610086/pthread-cancel-al
|
||||
pthread_kill(m_thread, SIGUSR1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadImpl::entryPoint(void* userData)
|
||||
{
|
||||
// The Thread instance is stored in the user data
|
||||
Thread* owner = static_cast<Thread*>(userData);
|
||||
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
// Tell the thread to handle cancel requests immediatly
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
#endif
|
||||
|
||||
// Forward to the owner
|
||||
owner->run();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Unix/ThreadImpl.hpp>
|
||||
#include <SFML/System/Thread.hpp>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl::ThreadImpl(Thread* owner) :
|
||||
m_isActive(true)
|
||||
{
|
||||
m_isActive = pthread_create(&m_thread, NULL, &ThreadImpl::entryPoint, owner) == 0;
|
||||
|
||||
if (!m_isActive)
|
||||
std::cerr << "Failed to create thread" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::wait()
|
||||
{
|
||||
if (m_isActive)
|
||||
{
|
||||
assert(pthread_equal(pthread_self(), m_thread) == 0); // A thread cannot wait for itself!
|
||||
pthread_join(m_thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::terminate()
|
||||
{
|
||||
if (m_isActive)
|
||||
{
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
pthread_cancel(m_thread);
|
||||
#else
|
||||
// See http://stackoverflow.com/questions/4610086/pthread-cancel-al
|
||||
pthread_kill(m_thread, SIGUSR1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadImpl::entryPoint(void* userData)
|
||||
{
|
||||
// The Thread instance is stored in the user data
|
||||
Thread* owner = static_cast<Thread*>(userData);
|
||||
|
||||
#ifndef SFML_SYSTEM_ANDROID
|
||||
// Tell the thread to handle cancel requests immediatly
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
#endif
|
||||
|
||||
// Forward to the owner
|
||||
owner->run();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,93 +1,93 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_THREADIMPL_HPP
|
||||
#define SFML_THREADIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Thread;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of threads
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadImpl : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor, launch the thread
|
||||
///
|
||||
/// \param owner The Thread instance to run
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl(Thread* owner);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Wait until the thread finishes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void wait();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Terminate the thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void terminate();
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Global entry point for all threads
|
||||
///
|
||||
/// \param userData User-defined data (contains the Thread instance)
|
||||
///
|
||||
/// \return Os specific error code
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void* entryPoint(void* userData);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
pthread_t m_thread; ///< pthread thread instance
|
||||
bool m_isActive; ///< Thread state (active or inactive)
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADIMPL_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_THREADIMPL_HPP
|
||||
#define SFML_THREADIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Thread;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of threads
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor, launch the thread
|
||||
///
|
||||
/// \param owner The Thread instance to run
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl(Thread* owner);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Wait until the thread finishes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void wait();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Terminate the thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void terminate();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Global entry point for all threads
|
||||
///
|
||||
/// \param userData User-defined data (contains the Thread instance)
|
||||
///
|
||||
/// \return Os specific error code
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void* entryPoint(void* userData);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
pthread_t m_thread; ///< pthread thread instance
|
||||
bool m_isActive; ///< Thread state (active or inactive)
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADIMPL_HPP
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Unix/ThreadLocalImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::ThreadLocalImpl()
|
||||
{
|
||||
pthread_key_create(&m_key, NULL);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::~ThreadLocalImpl()
|
||||
{
|
||||
pthread_key_delete(m_key);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadLocalImpl::setValue(void* value)
|
||||
{
|
||||
pthread_setspecific(m_key, value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadLocalImpl::getValue() const
|
||||
{
|
||||
return pthread_getspecific(m_key);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Unix/ThreadLocalImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::ThreadLocalImpl()
|
||||
{
|
||||
pthread_key_create(&m_key, NULL);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::~ThreadLocalImpl()
|
||||
{
|
||||
pthread_key_delete(m_key);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadLocalImpl::setValue(void* value)
|
||||
{
|
||||
pthread_setspecific(m_key, value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadLocalImpl::getValue() const
|
||||
{
|
||||
return pthread_getspecific(m_key);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,87 +1,87 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_THREADLOCALIMPL_HPP
|
||||
#define SFML_THREADLOCALIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of thread-local storage
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadLocalImpl : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor -- allocate the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor -- free the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the thread-specific value of the variable
|
||||
///
|
||||
/// \param value Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setValue(void* value);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Retrieve the thread-specific value of the variable
|
||||
///
|
||||
/// \return Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void* getValue() const;
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
pthread_key_t m_key; ///< Index of our thread-local storage slot
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADLOCALIMPL_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_THREADLOCALIMPL_HPP
|
||||
#define SFML_THREADLOCALIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unix implementation of thread-local storage
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadLocalImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor -- allocate the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor -- free the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the thread-specific value of the variable
|
||||
///
|
||||
/// \param value Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setValue(void* value);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Retrieve the thread-specific value of the variable
|
||||
///
|
||||
/// \return Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void* getValue() const;
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
pthread_key_t m_key; ///< Index of our thread-local storage slot
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADLOCALIMPL_HPP
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class ClockImpl
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the current time
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Win32/MutexImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
InitializeCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
DeleteCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::lock()
|
||||
{
|
||||
EnterCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::unlock()
|
||||
{
|
||||
LeaveCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Win32/MutexImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
InitializeCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
DeleteCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::lock()
|
||||
{
|
||||
EnterCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void MutexImpl::unlock()
|
||||
{
|
||||
LeaveCriticalSection(&m_mutex);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,83 +1,83 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_MUTEXIMPL_HPP
|
||||
#define SFML_MUTEXIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of mutexes
|
||||
////////////////////////////////////////////////////////////
|
||||
class MutexImpl : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Lock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void lock();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unlock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void unlock();
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
CRITICAL_SECTION m_mutex; ///< Win32 handle of the mutex
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_MUTEXIMPL_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_MUTEXIMPL_HPP
|
||||
#define SFML_MUTEXIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of mutexes
|
||||
////////////////////////////////////////////////////////////
|
||||
class MutexImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~MutexImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Lock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void lock();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Unlock the mutex
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
CRITICAL_SECTION m_mutex; ///< Win32 handle of the mutex
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_MUTEXIMPL_HPP
|
||||
|
|
|
@ -1,93 +1,93 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Win32/ThreadImpl.hpp>
|
||||
#include <SFML/System/Thread.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cassert>
|
||||
#include <process.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl::ThreadImpl(Thread* owner)
|
||||
{
|
||||
m_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &ThreadImpl::entryPoint, owner, 0, &m_threadId));
|
||||
|
||||
if (!m_thread)
|
||||
err() << "Failed to create thread" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl::~ThreadImpl()
|
||||
{
|
||||
if (m_thread)
|
||||
CloseHandle(m_thread);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::wait()
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
assert(m_threadId != GetCurrentThreadId()); // A thread cannot wait for itself!
|
||||
WaitForSingleObject(m_thread, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::terminate()
|
||||
{
|
||||
if (m_thread)
|
||||
TerminateThread(m_thread, 0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int __stdcall ThreadImpl::entryPoint(void* userData)
|
||||
{
|
||||
// The Thread instance is stored in the user data
|
||||
Thread* owner = static_cast<Thread*>(userData);
|
||||
|
||||
// Forward to the owner
|
||||
owner->run();
|
||||
|
||||
// Optional, but it is cleaner
|
||||
_endthreadex(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Win32/ThreadImpl.hpp>
|
||||
#include <SFML/System/Thread.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <cassert>
|
||||
#include <process.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl::ThreadImpl(Thread* owner)
|
||||
{
|
||||
m_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &ThreadImpl::entryPoint, owner, 0, &m_threadId));
|
||||
|
||||
if (!m_thread)
|
||||
err() << "Failed to create thread" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl::~ThreadImpl()
|
||||
{
|
||||
if (m_thread)
|
||||
CloseHandle(m_thread);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::wait()
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
assert(m_threadId != GetCurrentThreadId()); // A thread cannot wait for itself!
|
||||
WaitForSingleObject(m_thread, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadImpl::terminate()
|
||||
{
|
||||
if (m_thread)
|
||||
TerminateThread(m_thread, 0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int __stdcall ThreadImpl::entryPoint(void* userData)
|
||||
{
|
||||
// The Thread instance is stored in the user data
|
||||
Thread* owner = static_cast<Thread*>(userData);
|
||||
|
||||
// Forward to the owner
|
||||
owner->run();
|
||||
|
||||
// Optional, but it is cleaner
|
||||
_endthreadex(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,109 +1,109 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_THREADIMPL_HPP
|
||||
#define SFML_THREADIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
// Fix for unaligned stack with clang and GCC on Windows XP 32-bit
|
||||
#if defined(SFML_SYSTEM_WINDOWS) && (defined(__clang__) || defined(__GNUC__))
|
||||
|
||||
#define ALIGN_STACK __attribute__((__force_align_arg_pointer__))
|
||||
|
||||
#else
|
||||
|
||||
#define ALIGN_STACK
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Thread;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of threads
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadImpl : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor, launch the thread
|
||||
///
|
||||
/// \param owner The Thread instance to run
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl(Thread* owner);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ThreadImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Wait until the thread finishes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void wait();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Terminate the thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void terminate();
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Global entry point for all threads
|
||||
///
|
||||
/// \param userData User-defined data (contains the Thread instance)
|
||||
///
|
||||
/// \return OS specific error code
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ALIGN_STACK static unsigned int __stdcall entryPoint(void* userData);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
HANDLE m_thread; ///< Win32 thread handle
|
||||
unsigned int m_threadId; ///< Win32 thread identifier
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADIMPL_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_THREADIMPL_HPP
|
||||
#define SFML_THREADIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
// Fix for unaligned stack with clang and GCC on Windows XP 32-bit
|
||||
#if defined(SFML_SYSTEM_WINDOWS) && (defined(__clang__) || defined(__GNUC__))
|
||||
|
||||
#define ALIGN_STACK __attribute__((__force_align_arg_pointer__))
|
||||
|
||||
#else
|
||||
|
||||
#define ALIGN_STACK
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Thread;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of threads
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor, launch the thread
|
||||
///
|
||||
/// \param owner The Thread instance to run
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadImpl(Thread* owner);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ThreadImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Wait until the thread finishes
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void wait();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Terminate the thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void terminate();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Global entry point for all threads
|
||||
///
|
||||
/// \param userData User-defined data (contains the Thread instance)
|
||||
///
|
||||
/// \return OS specific error code
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ALIGN_STACK static unsigned int __stdcall entryPoint(void* userData);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
HANDLE m_thread; ///< Win32 thread handle
|
||||
unsigned int m_threadId; ///< Win32 thread identifier
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADIMPL_HPP
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Win32/ThreadLocalImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::ThreadLocalImpl()
|
||||
{
|
||||
m_index = TlsAlloc();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::~ThreadLocalImpl()
|
||||
{
|
||||
TlsFree(m_index);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadLocalImpl::setValue(void* value)
|
||||
{
|
||||
TlsSetValue(m_index, value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadLocalImpl::getValue() const
|
||||
{
|
||||
return TlsGetValue(m_index);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Win32/ThreadLocalImpl.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::ThreadLocalImpl()
|
||||
{
|
||||
m_index = TlsAlloc();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl::~ThreadLocalImpl()
|
||||
{
|
||||
TlsFree(m_index);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void ThreadLocalImpl::setValue(void* value)
|
||||
{
|
||||
TlsSetValue(m_index, value);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void* ThreadLocalImpl::getValue() const
|
||||
{
|
||||
return TlsGetValue(m_index);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,87 +1,87 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_THREADLOCALIMPL_HPP
|
||||
#define SFML_THREADLOCALIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of thread-local storage
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadLocalImpl : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor -- allocate the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor -- free the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the thread-specific value of the variable
|
||||
///
|
||||
/// \param value Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setValue(void* value);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Retrieve the thread-specific value of the variable
|
||||
///
|
||||
/// \return Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void* getValue() const;
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
DWORD m_index; ///< Index of our thread-local storage slot
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADLOCALIMPL_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_THREADLOCALIMPL_HPP
|
||||
#define SFML_THREADLOCALIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Windows implementation of thread-local storage
|
||||
////////////////////////////////////////////////////////////
|
||||
class ThreadLocalImpl : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor -- allocate the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor -- free the storage
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~ThreadLocalImpl();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the thread-specific value of the variable
|
||||
///
|
||||
/// \param value Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void setValue(void* value);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Retrieve the thread-specific value of the variable
|
||||
///
|
||||
/// \return Value of the variable for this thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void* getValue() const;
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
DWORD m_index; ///< Index of our thread-local storage slot
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_THREADLOCALIMPL_HPP
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class InputImpl
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if a key is pressed
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class JoystickImpl
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Perform the global initialization of the joystick module
|
||||
|
@ -100,7 +100,7 @@ public :
|
|||
////////////////////////////////////////////////////////////
|
||||
JoystickState update();
|
||||
|
||||
private :
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class SensorImpl
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Perform the global initialization of the sensor module
|
||||
|
@ -98,7 +98,7 @@ public :
|
|||
////////////////////////////////////////////////////////////
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
private :
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the default Android sensor matching the sensor type
|
||||
|
|
|
@ -515,117 +515,117 @@ Keyboard::Key WindowImplAndroid::androidKeyToSF(int32_t key)
|
|||
{
|
||||
switch (key)
|
||||
{
|
||||
case AKEYCODE_UNKNOWN :
|
||||
case AKEYCODE_SOFT_LEFT :
|
||||
case AKEYCODE_SOFT_RIGHT :
|
||||
case AKEYCODE_HOME : return Keyboard::Unknown;
|
||||
case AKEYCODE_BACK : return Keyboard::Escape;
|
||||
case AKEYCODE_CALL :
|
||||
case AKEYCODE_ENDCALL : return Keyboard::Unknown;
|
||||
case AKEYCODE_0 : return Keyboard::Num0;
|
||||
case AKEYCODE_1 : return Keyboard::Num1;
|
||||
case AKEYCODE_2 : return Keyboard::Num2;
|
||||
case AKEYCODE_3 : return Keyboard::Num3;
|
||||
case AKEYCODE_4 : return Keyboard::Num4;
|
||||
case AKEYCODE_5 : return Keyboard::Num5;
|
||||
case AKEYCODE_6 : return Keyboard::Num6;
|
||||
case AKEYCODE_7 : return Keyboard::Num7;
|
||||
case AKEYCODE_8 : return Keyboard::Num8;
|
||||
case AKEYCODE_9 : return Keyboard::Num9;
|
||||
case AKEYCODE_STAR :
|
||||
case AKEYCODE_POUND :
|
||||
case AKEYCODE_DPAD_UP :
|
||||
case AKEYCODE_DPAD_DOWN :
|
||||
case AKEYCODE_DPAD_LEFT :
|
||||
case AKEYCODE_DPAD_RIGHT :
|
||||
case AKEYCODE_DPAD_CENTER :
|
||||
case AKEYCODE_VOLUME_UP :
|
||||
case AKEYCODE_VOLUME_DOWN :
|
||||
case AKEYCODE_POWER :
|
||||
case AKEYCODE_CAMERA :
|
||||
case AKEYCODE_CLEAR : return Keyboard::Unknown;
|
||||
case AKEYCODE_A : return Keyboard::A;
|
||||
case AKEYCODE_B : return Keyboard::B;
|
||||
case AKEYCODE_C : return Keyboard::C;
|
||||
case AKEYCODE_D : return Keyboard::D;
|
||||
case AKEYCODE_E : return Keyboard::E;
|
||||
case AKEYCODE_F : return Keyboard::F;
|
||||
case AKEYCODE_G : return Keyboard::G;
|
||||
case AKEYCODE_H : return Keyboard::H;
|
||||
case AKEYCODE_I : return Keyboard::I;
|
||||
case AKEYCODE_J : return Keyboard::J;
|
||||
case AKEYCODE_K : return Keyboard::K;
|
||||
case AKEYCODE_L : return Keyboard::L;
|
||||
case AKEYCODE_M : return Keyboard::M;
|
||||
case AKEYCODE_N : return Keyboard::N;
|
||||
case AKEYCODE_O : return Keyboard::O;
|
||||
case AKEYCODE_P : return Keyboard::P;
|
||||
case AKEYCODE_Q : return Keyboard::Q;
|
||||
case AKEYCODE_R : return Keyboard::R;
|
||||
case AKEYCODE_S : return Keyboard::S;
|
||||
case AKEYCODE_T : return Keyboard::T;
|
||||
case AKEYCODE_U : return Keyboard::U;
|
||||
case AKEYCODE_V : return Keyboard::V;
|
||||
case AKEYCODE_W : return Keyboard::W;
|
||||
case AKEYCODE_X : return Keyboard::X;
|
||||
case AKEYCODE_Y : return Keyboard::Y;
|
||||
case AKEYCODE_Z : return Keyboard::Z;
|
||||
case AKEYCODE_COMMA : return Keyboard::Comma;
|
||||
case AKEYCODE_PERIOD : return Keyboard::Period;
|
||||
case AKEYCODE_ALT_LEFT : return Keyboard::LAlt;
|
||||
case AKEYCODE_ALT_RIGHT : return Keyboard::RAlt;
|
||||
case AKEYCODE_SHIFT_LEFT : return Keyboard::LShift;
|
||||
case AKEYCODE_SHIFT_RIGHT : return Keyboard::RShift;
|
||||
case AKEYCODE_TAB : return Keyboard::Tab;
|
||||
case AKEYCODE_SPACE : return Keyboard::Space;
|
||||
case AKEYCODE_SYM :
|
||||
case AKEYCODE_EXPLORER :
|
||||
case AKEYCODE_ENVELOPE : return Keyboard::Unknown;
|
||||
case AKEYCODE_ENTER : return Keyboard::Return;
|
||||
case AKEYCODE_DEL : return Keyboard::Delete;
|
||||
case AKEYCODE_GRAVE : return Keyboard::Tilde;
|
||||
case AKEYCODE_MINUS : return Keyboard::Subtract;
|
||||
case AKEYCODE_EQUALS : return Keyboard::Equal;
|
||||
case AKEYCODE_LEFT_BRACKET : return Keyboard::LBracket;
|
||||
case AKEYCODE_RIGHT_BRACKET : return Keyboard::RBracket;
|
||||
case AKEYCODE_BACKSLASH : return Keyboard::BackSlash;
|
||||
case AKEYCODE_SEMICOLON : return Keyboard::SemiColon;
|
||||
case AKEYCODE_APOSTROPHE : return Keyboard::Quote;
|
||||
case AKEYCODE_SLASH : return Keyboard::Slash;
|
||||
case AKEYCODE_AT :
|
||||
case AKEYCODE_NUM :
|
||||
case AKEYCODE_HEADSETHOOK :
|
||||
case AKEYCODE_FOCUS : // *Camera* focus
|
||||
case AKEYCODE_PLUS :
|
||||
case AKEYCODE_MENU :
|
||||
case AKEYCODE_NOTIFICATION :
|
||||
case AKEYCODE_SEARCH :
|
||||
case AKEYCODE_MEDIA_PLAY_PAUSE :
|
||||
case AKEYCODE_MEDIA_STOP :
|
||||
case AKEYCODE_MEDIA_NEXT :
|
||||
case AKEYCODE_MEDIA_PREVIOUS :
|
||||
case AKEYCODE_MEDIA_REWIND :
|
||||
case AKEYCODE_MEDIA_FAST_FORWARD :
|
||||
case AKEYCODE_MUTE : return Keyboard::Unknown;
|
||||
case AKEYCODE_PAGE_UP : return Keyboard::PageUp;
|
||||
case AKEYCODE_PAGE_DOWN : return Keyboard::PageDown;
|
||||
case AKEYCODE_PICTSYMBOLS :
|
||||
case AKEYCODE_SWITCH_CHARSET :
|
||||
case AKEYCODE_BUTTON_A :
|
||||
case AKEYCODE_BUTTON_B :
|
||||
case AKEYCODE_BUTTON_C :
|
||||
case AKEYCODE_BUTTON_X :
|
||||
case AKEYCODE_BUTTON_Y :
|
||||
case AKEYCODE_BUTTON_Z :
|
||||
case AKEYCODE_BUTTON_L1 :
|
||||
case AKEYCODE_BUTTON_R1 :
|
||||
case AKEYCODE_BUTTON_L2 :
|
||||
case AKEYCODE_BUTTON_R2 :
|
||||
case AKEYCODE_BUTTON_THUMBL :
|
||||
case AKEYCODE_BUTTON_THUMBR :
|
||||
case AKEYCODE_BUTTON_START :
|
||||
case AKEYCODE_BUTTON_SELECT :
|
||||
case AKEYCODE_BUTTON_MODE : return Keyboard::Unknown;
|
||||
case AKEYCODE_UNKNOWN:
|
||||
case AKEYCODE_SOFT_LEFT:
|
||||
case AKEYCODE_SOFT_RIGHT:
|
||||
case AKEYCODE_HOME: return Keyboard::Unknown;
|
||||
case AKEYCODE_BACK: return Keyboard::Escape;
|
||||
case AKEYCODE_CALL:
|
||||
case AKEYCODE_ENDCALL: return Keyboard::Unknown;
|
||||
case AKEYCODE_0: return Keyboard::Num0;
|
||||
case AKEYCODE_1: return Keyboard::Num1;
|
||||
case AKEYCODE_2: return Keyboard::Num2;
|
||||
case AKEYCODE_3: return Keyboard::Num3;
|
||||
case AKEYCODE_4: return Keyboard::Num4;
|
||||
case AKEYCODE_5: return Keyboard::Num5;
|
||||
case AKEYCODE_6: return Keyboard::Num6;
|
||||
case AKEYCODE_7: return Keyboard::Num7;
|
||||
case AKEYCODE_8: return Keyboard::Num8;
|
||||
case AKEYCODE_9: return Keyboard::Num9;
|
||||
case AKEYCODE_STAR:
|
||||
case AKEYCODE_POUND:
|
||||
case AKEYCODE_DPAD_UP:
|
||||
case AKEYCODE_DPAD_DOWN:
|
||||
case AKEYCODE_DPAD_LEFT:
|
||||
case AKEYCODE_DPAD_RIGHT:
|
||||
case AKEYCODE_DPAD_CENTER:
|
||||
case AKEYCODE_VOLUME_UP:
|
||||
case AKEYCODE_VOLUME_DOWN:
|
||||
case AKEYCODE_POWER:
|
||||
case AKEYCODE_CAMERA:
|
||||
case AKEYCODE_CLEAR: return Keyboard::Unknown;
|
||||
case AKEYCODE_A: return Keyboard::A;
|
||||
case AKEYCODE_B: return Keyboard::B;
|
||||
case AKEYCODE_C: return Keyboard::C;
|
||||
case AKEYCODE_D: return Keyboard::D;
|
||||
case AKEYCODE_E: return Keyboard::E;
|
||||
case AKEYCODE_F: return Keyboard::F;
|
||||
case AKEYCODE_G: return Keyboard::G;
|
||||
case AKEYCODE_H: return Keyboard::H;
|
||||
case AKEYCODE_I: return Keyboard::I;
|
||||
case AKEYCODE_J: return Keyboard::J;
|
||||
case AKEYCODE_K: return Keyboard::K;
|
||||
case AKEYCODE_L: return Keyboard::L;
|
||||
case AKEYCODE_M: return Keyboard::M;
|
||||
case AKEYCODE_N: return Keyboard::N;
|
||||
case AKEYCODE_O: return Keyboard::O;
|
||||
case AKEYCODE_P: return Keyboard::P;
|
||||
case AKEYCODE_Q: return Keyboard::Q;
|
||||
case AKEYCODE_R: return Keyboard::R;
|
||||
case AKEYCODE_S: return Keyboard::S;
|
||||
case AKEYCODE_T: return Keyboard::T;
|
||||
case AKEYCODE_U: return Keyboard::U;
|
||||
case AKEYCODE_V: return Keyboard::V;
|
||||
case AKEYCODE_W: return Keyboard::W;
|
||||
case AKEYCODE_X: return Keyboard::X;
|
||||
case AKEYCODE_Y: return Keyboard::Y;
|
||||
case AKEYCODE_Z: return Keyboard::Z;
|
||||
case AKEYCODE_COMMA: return Keyboard::Comma;
|
||||
case AKEYCODE_PERIOD: return Keyboard::Period;
|
||||
case AKEYCODE_ALT_LEFT: return Keyboard::LAlt;
|
||||
case AKEYCODE_ALT_RIGHT: return Keyboard::RAlt;
|
||||
case AKEYCODE_SHIFT_LEFT: return Keyboard::LShift;
|
||||
case AKEYCODE_SHIFT_RIGHT: return Keyboard::RShift;
|
||||
case AKEYCODE_TAB: return Keyboard::Tab;
|
||||
case AKEYCODE_SPACE: return Keyboard::Space;
|
||||
case AKEYCODE_SYM:
|
||||
case AKEYCODE_EXPLORER:
|
||||
case AKEYCODE_ENVELOPE: return Keyboard::Unknown;
|
||||
case AKEYCODE_ENTER: return Keyboard::Return;
|
||||
case AKEYCODE_DEL: return Keyboard::Delete;
|
||||
case AKEYCODE_GRAVE: return Keyboard::Tilde;
|
||||
case AKEYCODE_MINUS: return Keyboard::Subtract;
|
||||
case AKEYCODE_EQUALS: return Keyboard::Equal;
|
||||
case AKEYCODE_LEFT_BRACKET: return Keyboard::LBracket;
|
||||
case AKEYCODE_RIGHT_BRACKET: return Keyboard::RBracket;
|
||||
case AKEYCODE_BACKSLASH: return Keyboard::BackSlash;
|
||||
case AKEYCODE_SEMICOLON: return Keyboard::SemiColon;
|
||||
case AKEYCODE_APOSTROPHE: return Keyboard::Quote;
|
||||
case AKEYCODE_SLASH: return Keyboard::Slash;
|
||||
case AKEYCODE_AT:
|
||||
case AKEYCODE_NUM:
|
||||
case AKEYCODE_HEADSETHOOK:
|
||||
case AKEYCODE_FOCUS: // *Camera* focus
|
||||
case AKEYCODE_PLUS:
|
||||
case AKEYCODE_MENU:
|
||||
case AKEYCODE_NOTIFICATION:
|
||||
case AKEYCODE_SEARCH:
|
||||
case AKEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case AKEYCODE_MEDIA_STOP:
|
||||
case AKEYCODE_MEDIA_NEXT:
|
||||
case AKEYCODE_MEDIA_PREVIOUS:
|
||||
case AKEYCODE_MEDIA_REWIND:
|
||||
case AKEYCODE_MEDIA_FAST_FORWARD:
|
||||
case AKEYCODE_MUTE: return Keyboard::Unknown;
|
||||
case AKEYCODE_PAGE_UP: return Keyboard::PageUp;
|
||||
case AKEYCODE_PAGE_DOWN: return Keyboard::PageDown;
|
||||
case AKEYCODE_PICTSYMBOLS:
|
||||
case AKEYCODE_SWITCH_CHARSET:
|
||||
case AKEYCODE_BUTTON_A:
|
||||
case AKEYCODE_BUTTON_B:
|
||||
case AKEYCODE_BUTTON_C:
|
||||
case AKEYCODE_BUTTON_X:
|
||||
case AKEYCODE_BUTTON_Y:
|
||||
case AKEYCODE_BUTTON_Z:
|
||||
case AKEYCODE_BUTTON_L1:
|
||||
case AKEYCODE_BUTTON_R1:
|
||||
case AKEYCODE_BUTTON_L2:
|
||||
case AKEYCODE_BUTTON_R2:
|
||||
case AKEYCODE_BUTTON_THUMBL:
|
||||
case AKEYCODE_BUTTON_THUMBR:
|
||||
case AKEYCODE_BUTTON_START:
|
||||
case AKEYCODE_BUTTON_SELECT:
|
||||
case AKEYCODE_BUTTON_MODE: return Keyboard::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class WindowImplAndroid : public WindowImpl
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Construct the window implementation from an existing control
|
||||
|
@ -157,7 +157,7 @@ public :
|
|||
static void forwardEvent(const Event& event);
|
||||
static WindowImplAndroid* singleInstance;
|
||||
|
||||
protected :
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Process incoming events from the operating system
|
||||
|
|
|
@ -1,246 +1,246 @@
|
|||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Window)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Window)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${SRCROOT}/Context.cpp
|
||||
${INCROOT}/Context.hpp
|
||||
${INCROOT}/Export.hpp
|
||||
${SRCROOT}/GlContext.cpp
|
||||
${SRCROOT}/GlContext.hpp
|
||||
${SRCROOT}/GlResource.cpp
|
||||
${INCROOT}/GlResource.hpp
|
||||
${INCROOT}/ContextSettings.hpp
|
||||
${INCROOT}/Event.hpp
|
||||
${SRCROOT}/InputImpl.hpp
|
||||
${INCROOT}/Joystick.hpp
|
||||
${SRCROOT}/Joystick.cpp
|
||||
${SRCROOT}/JoystickImpl.hpp
|
||||
${SRCROOT}/JoystickManager.cpp
|
||||
${SRCROOT}/JoystickManager.hpp
|
||||
${INCROOT}/Keyboard.hpp
|
||||
${SRCROOT}/Keyboard.cpp
|
||||
${INCROOT}/Mouse.hpp
|
||||
${SRCROOT}/Mouse.cpp
|
||||
${INCROOT}/Touch.hpp
|
||||
${SRCROOT}/Touch.cpp
|
||||
${INCROOT}/Sensor.hpp
|
||||
${SRCROOT}/Sensor.cpp
|
||||
${SRCROOT}/SensorImpl.hpp
|
||||
${SRCROOT}/SensorManager.cpp
|
||||
${SRCROOT}/SensorManager.hpp
|
||||
${SRCROOT}/VideoMode.cpp
|
||||
${INCROOT}/VideoMode.hpp
|
||||
${SRCROOT}/VideoModeImpl.hpp
|
||||
${SRCROOT}/Window.cpp
|
||||
${INCROOT}/Window.hpp
|
||||
${INCROOT}/WindowHandle.hpp
|
||||
${SRCROOT}/WindowImpl.cpp
|
||||
${SRCROOT}/WindowImpl.hpp
|
||||
${INCROOT}/WindowStyle.hpp
|
||||
)
|
||||
if(SFML_OPENGL_ES AND NOT SFML_OS_IOS)
|
||||
list(APPEND SRC ${SRCROOT}/EGLCheck.cpp)
|
||||
list(APPEND SRC ${SRCROOT}/EGLCheck.hpp)
|
||||
list(APPEND SRC ${SRCROOT}/EglContext.cpp)
|
||||
list(APPEND SRC ${SRCROOT}/EglContext.hpp)
|
||||
endif()
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# add platform specific sources
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Win32/WglContext.cpp
|
||||
${SRCROOT}/Win32/WglContext.hpp
|
||||
${SRCROOT}/Win32/InputImpl.cpp
|
||||
${SRCROOT}/Win32/InputImpl.hpp
|
||||
${SRCROOT}/Win32/JoystickImpl.cpp
|
||||
${SRCROOT}/Win32/JoystickImpl.hpp
|
||||
${SRCROOT}/Win32/SensorImpl.hpp
|
||||
${SRCROOT}/Win32/SensorImpl.cpp
|
||||
${SRCROOT}/Win32/VideoModeImpl.cpp
|
||||
${SRCROOT}/Win32/WindowImplWin32.cpp
|
||||
${SRCROOT}/Win32/WindowImplWin32.hpp
|
||||
)
|
||||
source_group("windows" FILES ${PLATFORM_SRC})
|
||||
|
||||
# make sure that we use the Unicode version of the Win API functions
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Unix/Display.cpp
|
||||
${SRCROOT}/Unix/Display.hpp
|
||||
${SRCROOT}/Unix/InputImpl.cpp
|
||||
${SRCROOT}/Unix/InputImpl.hpp
|
||||
${SRCROOT}/Unix/SensorImpl.cpp
|
||||
${SRCROOT}/Unix/SensorImpl.hpp
|
||||
${SRCROOT}/Unix/VideoModeImpl.cpp
|
||||
${SRCROOT}/Unix/WindowImplX11.cpp
|
||||
${SRCROOT}/Unix/WindowImplX11.hpp
|
||||
)
|
||||
if(NOT SFML_OPENGL_ES)
|
||||
set(PLATFORM_SRC
|
||||
${PLATFORM_SRC}
|
||||
${SRCROOT}/Unix/GlxContext.cpp
|
||||
${SRCROOT}/Unix/GlxContext.hpp
|
||||
)
|
||||
endif()
|
||||
if(SFML_OS_LINUX)
|
||||
set(PLATFORM_SRC
|
||||
${PLATFORM_SRC}
|
||||
${SRCROOT}/Unix/JoystickImpl.cpp
|
||||
${SRCROOT}/Unix/JoystickImpl.hpp
|
||||
)
|
||||
elseif(SFML_OS_FREEBSD)
|
||||
set(PLATFORM_SRC
|
||||
${PLATFORM_SRC}
|
||||
${SRCROOT}/FreeBSD/JoystickImpl.cpp
|
||||
${SRCROOT}/FreeBSD/JoystickImpl.hpp
|
||||
)
|
||||
endif()
|
||||
source_group("unix" FILES ${PLATFORM_SRC})
|
||||
elseif(SFML_OS_MACOSX)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/OSX/cpp_objc_conversion.h
|
||||
${SRCROOT}/OSX/cpp_objc_conversion.mm
|
||||
${SRCROOT}/OSX/cg_sf_conversion.hpp
|
||||
${SRCROOT}/OSX/cg_sf_conversion.cpp
|
||||
${SRCROOT}/OSX/InputImpl.mm
|
||||
${SRCROOT}/OSX/InputImpl.hpp
|
||||
${SRCROOT}/OSX/HIDInputManager.hpp
|
||||
${SRCROOT}/OSX/HIDInputManager.mm
|
||||
${SRCROOT}/OSX/HIDJoystickManager.hpp
|
||||
${SRCROOT}/OSX/HIDJoystickManager.cpp
|
||||
${SRCROOT}/OSX/JoystickImpl.cpp
|
||||
${SRCROOT}/OSX/JoystickImpl.hpp
|
||||
${SRCROOT}/OSX/SensorImpl.cpp
|
||||
${SRCROOT}/OSX/SensorImpl.hpp
|
||||
${SRCROOT}/OSX/SFApplication.h
|
||||
${SRCROOT}/OSX/SFApplication.m
|
||||
${SRCROOT}/OSX/SFApplicationDelegate.h
|
||||
${SRCROOT}/OSX/SFApplicationDelegate.m
|
||||
${SRCROOT}/OSX/SFContext.hpp
|
||||
${SRCROOT}/OSX/SFContext.mm
|
||||
${SRCROOT}/OSX/SFKeyboardModifiersHelper.h
|
||||
${SRCROOT}/OSX/SFKeyboardModifiersHelper.mm
|
||||
${SRCROOT}/OSX/SFOpenGLView.h
|
||||
${SRCROOT}/OSX/SFOpenGLView.mm
|
||||
${SRCROOT}/OSX/SFSilentResponder.h
|
||||
${SRCROOT}/OSX/SFSilentResponder.m
|
||||
${SRCROOT}/OSX/SFWindow.h
|
||||
${SRCROOT}/OSX/SFWindow.m
|
||||
${SRCROOT}/OSX/SFWindowController.h
|
||||
${SRCROOT}/OSX/SFWindowController.mm
|
||||
${SRCROOT}/OSX/SFViewController.h
|
||||
${SRCROOT}/OSX/SFViewController.mm
|
||||
${SRCROOT}/OSX/VideoModeImpl.cpp
|
||||
${SRCROOT}/OSX/WindowImplCocoa.hpp
|
||||
${SRCROOT}/OSX/WindowImplCocoa.mm
|
||||
${SRCROOT}/OSX/WindowImplDelegateProtocol.h
|
||||
${SRCROOT}/OSX/AutoreleasePoolWrapper.h
|
||||
${SRCROOT}/OSX/AutoreleasePoolWrapper.mm
|
||||
)
|
||||
source_group("mac" FILES ${PLATFORM_SRC})
|
||||
elseif(SFML_OS_IOS)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/iOS/EaglContext.mm
|
||||
${SRCROOT}/iOS/EaglContext.hpp
|
||||
${SRCROOT}/iOS/InputImpl.mm
|
||||
${SRCROOT}/iOS/InputImpl.hpp
|
||||
${SRCROOT}/iOS/JoystickImpl.mm
|
||||
${SRCROOT}/iOS/JoystickImpl.hpp
|
||||
${SRCROOT}/iOS/SensorImpl.mm
|
||||
${SRCROOT}/iOS/SensorImpl.hpp
|
||||
${SRCROOT}/iOS/VideoModeImpl.mm
|
||||
${SRCROOT}/iOS/WindowImplUIKit.hpp
|
||||
${SRCROOT}/iOS/WindowImplUIKit.mm
|
||||
${SRCROOT}/iOS/ObjCType.hpp
|
||||
${SRCROOT}/iOS/SFAppDelegate.hpp
|
||||
${SRCROOT}/iOS/SFAppDelegate.mm
|
||||
${SRCROOT}/iOS/SFView.hpp
|
||||
${SRCROOT}/iOS/SFView.mm
|
||||
${SRCROOT}/iOS/SFViewController.hpp
|
||||
${SRCROOT}/iOS/SFViewController.mm
|
||||
${SRCROOT}/iOS/SFMain.hpp
|
||||
${SRCROOT}/iOS/SFMain.mm
|
||||
)
|
||||
source_group("ios" FILES ${PLATFORM_SRC})
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Android/WindowImplAndroid.hpp
|
||||
${SRCROOT}/Android/WindowImplAndroid.cpp
|
||||
${SRCROOT}/Android/VideoModeImpl.cpp
|
||||
${SRCROOT}/Android/InputImpl.hpp
|
||||
${SRCROOT}/Android/InputImpl.cpp
|
||||
${SRCROOT}/Android/JoystickImpl.hpp
|
||||
${SRCROOT}/Android/JoystickImpl.cpp
|
||||
${SRCROOT}/Android/SensorImpl.hpp
|
||||
${SRCROOT}/Android/SensorImpl.cpp
|
||||
)
|
||||
source_group("android" FILES ${PLATFORM_SRC})
|
||||
endif()
|
||||
|
||||
# find external libraries
|
||||
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
||||
find_package(X11 REQUIRED)
|
||||
if(NOT X11_Xrandr_FOUND)
|
||||
message(FATAL_ERROR "Xrandr library not found")
|
||||
endif()
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
|
||||
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Window)
|
||||
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Window)
|
||||
|
||||
# all source files
|
||||
set(SRC
|
||||
${SRCROOT}/Context.cpp
|
||||
${INCROOT}/Context.hpp
|
||||
${INCROOT}/Export.hpp
|
||||
${SRCROOT}/GlContext.cpp
|
||||
${SRCROOT}/GlContext.hpp
|
||||
${SRCROOT}/GlResource.cpp
|
||||
${INCROOT}/GlResource.hpp
|
||||
${INCROOT}/ContextSettings.hpp
|
||||
${INCROOT}/Event.hpp
|
||||
${SRCROOT}/InputImpl.hpp
|
||||
${INCROOT}/Joystick.hpp
|
||||
${SRCROOT}/Joystick.cpp
|
||||
${SRCROOT}/JoystickImpl.hpp
|
||||
${SRCROOT}/JoystickManager.cpp
|
||||
${SRCROOT}/JoystickManager.hpp
|
||||
${INCROOT}/Keyboard.hpp
|
||||
${SRCROOT}/Keyboard.cpp
|
||||
${INCROOT}/Mouse.hpp
|
||||
${SRCROOT}/Mouse.cpp
|
||||
${INCROOT}/Touch.hpp
|
||||
${SRCROOT}/Touch.cpp
|
||||
${INCROOT}/Sensor.hpp
|
||||
${SRCROOT}/Sensor.cpp
|
||||
${SRCROOT}/SensorImpl.hpp
|
||||
${SRCROOT}/SensorManager.cpp
|
||||
${SRCROOT}/SensorManager.hpp
|
||||
${SRCROOT}/VideoMode.cpp
|
||||
${INCROOT}/VideoMode.hpp
|
||||
${SRCROOT}/VideoModeImpl.hpp
|
||||
${SRCROOT}/Window.cpp
|
||||
${INCROOT}/Window.hpp
|
||||
${INCROOT}/WindowHandle.hpp
|
||||
${SRCROOT}/WindowImpl.cpp
|
||||
${SRCROOT}/WindowImpl.hpp
|
||||
${INCROOT}/WindowStyle.hpp
|
||||
)
|
||||
if(SFML_OPENGL_ES AND NOT SFML_OS_IOS)
|
||||
list(APPEND SRC ${SRCROOT}/EGLCheck.cpp)
|
||||
list(APPEND SRC ${SRCROOT}/EGLCheck.hpp)
|
||||
list(APPEND SRC ${SRCROOT}/EglContext.cpp)
|
||||
list(APPEND SRC ${SRCROOT}/EglContext.hpp)
|
||||
endif()
|
||||
source_group("" FILES ${SRC})
|
||||
|
||||
# add platform specific sources
|
||||
if(SFML_OS_WINDOWS)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Win32/WglContext.cpp
|
||||
${SRCROOT}/Win32/WglContext.hpp
|
||||
${SRCROOT}/Win32/InputImpl.cpp
|
||||
${SRCROOT}/Win32/InputImpl.hpp
|
||||
${SRCROOT}/Win32/JoystickImpl.cpp
|
||||
${SRCROOT}/Win32/JoystickImpl.hpp
|
||||
${SRCROOT}/Win32/SensorImpl.hpp
|
||||
${SRCROOT}/Win32/SensorImpl.cpp
|
||||
${SRCROOT}/Win32/VideoModeImpl.cpp
|
||||
${SRCROOT}/Win32/WindowImplWin32.cpp
|
||||
${SRCROOT}/Win32/WindowImplWin32.hpp
|
||||
)
|
||||
source_group("windows" FILES ${PLATFORM_SRC})
|
||||
|
||||
# make sure that we use the Unicode version of the Win API functions
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Unix/Display.cpp
|
||||
${SRCROOT}/Unix/Display.hpp
|
||||
${SRCROOT}/Unix/InputImpl.cpp
|
||||
${SRCROOT}/Unix/InputImpl.hpp
|
||||
${SRCROOT}/Unix/SensorImpl.cpp
|
||||
${SRCROOT}/Unix/SensorImpl.hpp
|
||||
${SRCROOT}/Unix/VideoModeImpl.cpp
|
||||
${SRCROOT}/Unix/WindowImplX11.cpp
|
||||
${SRCROOT}/Unix/WindowImplX11.hpp
|
||||
)
|
||||
if(NOT SFML_OPENGL_ES)
|
||||
set(PLATFORM_SRC
|
||||
${PLATFORM_SRC}
|
||||
${SRCROOT}/Unix/GlxContext.cpp
|
||||
${SRCROOT}/Unix/GlxContext.hpp
|
||||
)
|
||||
endif()
|
||||
if(SFML_OS_LINUX)
|
||||
set(PLATFORM_SRC
|
||||
${PLATFORM_SRC}
|
||||
${SRCROOT}/Unix/JoystickImpl.cpp
|
||||
${SRCROOT}/Unix/JoystickImpl.hpp
|
||||
)
|
||||
elseif(SFML_OS_FREEBSD)
|
||||
set(PLATFORM_SRC
|
||||
${PLATFORM_SRC}
|
||||
${SRCROOT}/FreeBSD/JoystickImpl.cpp
|
||||
${SRCROOT}/FreeBSD/JoystickImpl.hpp
|
||||
)
|
||||
endif()
|
||||
source_group("unix" FILES ${PLATFORM_SRC})
|
||||
elseif(SFML_OS_MACOSX)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/OSX/cpp_objc_conversion.h
|
||||
${SRCROOT}/OSX/cpp_objc_conversion.mm
|
||||
${SRCROOT}/OSX/cg_sf_conversion.hpp
|
||||
${SRCROOT}/OSX/cg_sf_conversion.cpp
|
||||
${SRCROOT}/OSX/InputImpl.mm
|
||||
${SRCROOT}/OSX/InputImpl.hpp
|
||||
${SRCROOT}/OSX/HIDInputManager.hpp
|
||||
${SRCROOT}/OSX/HIDInputManager.mm
|
||||
${SRCROOT}/OSX/HIDJoystickManager.hpp
|
||||
${SRCROOT}/OSX/HIDJoystickManager.cpp
|
||||
${SRCROOT}/OSX/JoystickImpl.cpp
|
||||
${SRCROOT}/OSX/JoystickImpl.hpp
|
||||
${SRCROOT}/OSX/SensorImpl.cpp
|
||||
${SRCROOT}/OSX/SensorImpl.hpp
|
||||
${SRCROOT}/OSX/SFApplication.h
|
||||
${SRCROOT}/OSX/SFApplication.m
|
||||
${SRCROOT}/OSX/SFApplicationDelegate.h
|
||||
${SRCROOT}/OSX/SFApplicationDelegate.m
|
||||
${SRCROOT}/OSX/SFContext.hpp
|
||||
${SRCROOT}/OSX/SFContext.mm
|
||||
${SRCROOT}/OSX/SFKeyboardModifiersHelper.h
|
||||
${SRCROOT}/OSX/SFKeyboardModifiersHelper.mm
|
||||
${SRCROOT}/OSX/SFOpenGLView.h
|
||||
${SRCROOT}/OSX/SFOpenGLView.mm
|
||||
${SRCROOT}/OSX/SFSilentResponder.h
|
||||
${SRCROOT}/OSX/SFSilentResponder.m
|
||||
${SRCROOT}/OSX/SFWindow.h
|
||||
${SRCROOT}/OSX/SFWindow.m
|
||||
${SRCROOT}/OSX/SFWindowController.h
|
||||
${SRCROOT}/OSX/SFWindowController.mm
|
||||
${SRCROOT}/OSX/SFViewController.h
|
||||
${SRCROOT}/OSX/SFViewController.mm
|
||||
${SRCROOT}/OSX/VideoModeImpl.cpp
|
||||
${SRCROOT}/OSX/WindowImplCocoa.hpp
|
||||
${SRCROOT}/OSX/WindowImplCocoa.mm
|
||||
${SRCROOT}/OSX/WindowImplDelegateProtocol.h
|
||||
${SRCROOT}/OSX/AutoreleasePoolWrapper.h
|
||||
${SRCROOT}/OSX/AutoreleasePoolWrapper.mm
|
||||
)
|
||||
source_group("mac" FILES ${PLATFORM_SRC})
|
||||
elseif(SFML_OS_IOS)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/iOS/EaglContext.mm
|
||||
${SRCROOT}/iOS/EaglContext.hpp
|
||||
${SRCROOT}/iOS/InputImpl.mm
|
||||
${SRCROOT}/iOS/InputImpl.hpp
|
||||
${SRCROOT}/iOS/JoystickImpl.mm
|
||||
${SRCROOT}/iOS/JoystickImpl.hpp
|
||||
${SRCROOT}/iOS/SensorImpl.mm
|
||||
${SRCROOT}/iOS/SensorImpl.hpp
|
||||
${SRCROOT}/iOS/VideoModeImpl.mm
|
||||
${SRCROOT}/iOS/WindowImplUIKit.hpp
|
||||
${SRCROOT}/iOS/WindowImplUIKit.mm
|
||||
${SRCROOT}/iOS/ObjCType.hpp
|
||||
${SRCROOT}/iOS/SFAppDelegate.hpp
|
||||
${SRCROOT}/iOS/SFAppDelegate.mm
|
||||
${SRCROOT}/iOS/SFView.hpp
|
||||
${SRCROOT}/iOS/SFView.mm
|
||||
${SRCROOT}/iOS/SFViewController.hpp
|
||||
${SRCROOT}/iOS/SFViewController.mm
|
||||
${SRCROOT}/iOS/SFMain.hpp
|
||||
${SRCROOT}/iOS/SFMain.mm
|
||||
)
|
||||
source_group("ios" FILES ${PLATFORM_SRC})
|
||||
elseif(SFML_OS_ANDROID)
|
||||
set(PLATFORM_SRC
|
||||
${SRCROOT}/Android/WindowImplAndroid.hpp
|
||||
${SRCROOT}/Android/WindowImplAndroid.cpp
|
||||
${SRCROOT}/Android/VideoModeImpl.cpp
|
||||
${SRCROOT}/Android/InputImpl.hpp
|
||||
${SRCROOT}/Android/InputImpl.cpp
|
||||
${SRCROOT}/Android/JoystickImpl.hpp
|
||||
${SRCROOT}/Android/JoystickImpl.cpp
|
||||
${SRCROOT}/Android/SensorImpl.hpp
|
||||
${SRCROOT}/Android/SensorImpl.cpp
|
||||
)
|
||||
source_group("android" FILES ${PLATFORM_SRC})
|
||||
endif()
|
||||
|
||||
# find external libraries
|
||||
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
||||
find_package(X11 REQUIRED)
|
||||
if(NOT X11_Xrandr_FOUND)
|
||||
message(FATAL_ERROR "Xrandr library not found")
|
||||
endif()
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
endif()
|
||||
if(NOT SFML_OPENGL_ES)
|
||||
find_package(OpenGL REQUIRED)
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
||||
find_package(X11 REQUIRED)
|
||||
if(NOT X11_Xrandr_FOUND)
|
||||
message(FATAL_ERROR "Xrandr library not found")
|
||||
endif()
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
find_package(X11 REQUIRED)
|
||||
if(NOT X11_Xrandr_FOUND)
|
||||
message(FATAL_ERROR "Xrandr library not found")
|
||||
endif()
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
endif()
|
||||
if(SFML_OS_LINUX)
|
||||
find_package(UDev REQUIRED)
|
||||
if(NOT UDEV_FOUND)
|
||||
message(FATAL_ERROR "udev library not found")
|
||||
endif()
|
||||
find_package(UDev REQUIRED)
|
||||
if(NOT UDEV_FOUND)
|
||||
message(FATAL_ERROR "udev library not found")
|
||||
endif()
|
||||
include_directories(${UDEV_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
|
||||
find_package(EGL REQUIRED)
|
||||
find_package(GLES REQUIRED)
|
||||
include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
|
||||
find_package(EGL REQUIRED)
|
||||
find_package(GLES REQUIRED)
|
||||
include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
# build the list of external libraries to link
|
||||
# build the list of external libraries to link
|
||||
if(SFML_OS_WINDOWS)
|
||||
list(APPEND WINDOW_EXT_LIBS winmm gdi32)
|
||||
elseif(SFML_OS_LINUX)
|
||||
list(APPEND WINDOW_EXT_LIBS winmm gdi32)
|
||||
elseif(SFML_OS_LINUX)
|
||||
list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} ${UDEV_LIBRARIES})
|
||||
elseif(SFML_OS_FREEBSD)
|
||||
elseif(SFML_OS_FREEBSD)
|
||||
list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} usbhid)
|
||||
elseif(SFML_OS_MACOSX)
|
||||
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
|
||||
elseif(SFML_OS_IOS)
|
||||
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework UIKit -framework CoreGraphics -framework QuartzCore -framework CoreMotion")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
list(APPEND WINDOW_EXT_LIBS "-landroid")
|
||||
endif()
|
||||
if(SFML_OPENGL_ES)
|
||||
if(SFML_OS_LINUX)
|
||||
list(APPEND WINDOW_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
|
||||
elseif(SFML_OS_IOS)
|
||||
list(APPEND WINDOW_EXT_LIBS "-framework OpenGLES")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
list(APPEND WINDOW_EXT_LIBS "-lEGL -lGLESv1_CM")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND WINDOW_EXT_LIBS ${OPENGL_gl_LIBRARY})
|
||||
endif()
|
||||
|
||||
# define the sfml-window target
|
||||
sfml_add_library(sfml-window
|
||||
SOURCES ${SRC} ${PLATFORM_SRC}
|
||||
DEPENDS sfml-system
|
||||
EXTERNAL_LIBS ${WINDOW_EXT_LIBS})
|
||||
elseif(SFML_OS_MACOSX)
|
||||
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
|
||||
elseif(SFML_OS_IOS)
|
||||
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework UIKit -framework CoreGraphics -framework QuartzCore -framework CoreMotion")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
list(APPEND WINDOW_EXT_LIBS "-landroid")
|
||||
endif()
|
||||
if(SFML_OPENGL_ES)
|
||||
if(SFML_OS_LINUX)
|
||||
list(APPEND WINDOW_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
|
||||
elseif(SFML_OS_IOS)
|
||||
list(APPEND WINDOW_EXT_LIBS "-framework OpenGLES")
|
||||
elseif(SFML_OS_ANDROID)
|
||||
list(APPEND WINDOW_EXT_LIBS "-lEGL -lGLESv1_CM")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND WINDOW_EXT_LIBS ${OPENGL_gl_LIBRARY})
|
||||
endif()
|
||||
|
||||
# define the sfml-window target
|
||||
sfml_add_library(sfml-window
|
||||
SOURCES ${SRC} ${PLATFORM_SRC}
|
||||
DEPENDS sfml-system
|
||||
EXTERNAL_LIBS ${WINDOW_EXT_LIBS})
|
||||
|
|
|
@ -1,63 +1,63 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/Context.hpp>
|
||||
#include <SFML/Window/GlContext.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Context::Context()
|
||||
{
|
||||
m_context = priv::GlContext::create();
|
||||
setActive(true);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Context::~Context()
|
||||
{
|
||||
delete m_context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Context::setActive(bool active)
|
||||
{
|
||||
return m_context->setActive(active);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Context::Context(const ContextSettings& settings, unsigned int width, unsigned int height)
|
||||
{
|
||||
m_context = priv::GlContext::create(settings, width, height);
|
||||
setActive(true);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/Context.hpp>
|
||||
#include <SFML/Window/GlContext.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
Context::Context()
|
||||
{
|
||||
m_context = priv::GlContext::create();
|
||||
setActive(true);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Context::~Context()
|
||||
{
|
||||
delete m_context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Context::setActive(bool active)
|
||||
{
|
||||
return m_context->setActive(active);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Context::Context(const ContextSettings& settings, unsigned int width, unsigned int height)
|
||||
{
|
||||
m_context = priv::GlContext::create(settings, width, height);
|
||||
setActive(true);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -50,55 +50,55 @@ void eglCheckError(const char* file, unsigned int line)
|
|||
// Decode the error code returned
|
||||
switch (errorCode)
|
||||
{
|
||||
case EGL_NOT_INITIALIZED :
|
||||
case EGL_NOT_INITIALIZED:
|
||||
{
|
||||
error = "EGL_NOT_INITIALIZED";
|
||||
description = "EGL is not initialized, or could not be initialized, for the specified display";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_ACCESS :
|
||||
case EGL_BAD_ACCESS:
|
||||
{
|
||||
error = "EGL_BAD_ACCESS";
|
||||
description = "EGL cannot access a requested resource (for example, a context is bound in another thread)";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_ALLOC :
|
||||
case EGL_BAD_ALLOC:
|
||||
{
|
||||
error = "EGL_BAD_ALLOC";
|
||||
description = "EGL failed to allocate resources for the requested operation";
|
||||
break;
|
||||
}
|
||||
case EGL_BAD_ATTRIBUTE :
|
||||
case EGL_BAD_ATTRIBUTE:
|
||||
{
|
||||
error = "EGL_BAD_ATTRIBUTE";
|
||||
description = "an unrecognized attribute or attribute value was passed in an attribute list";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_CONTEXT :
|
||||
case EGL_BAD_CONTEXT:
|
||||
{
|
||||
error = "EGL_BAD_CONTEXT";
|
||||
description = "an EGLContext argument does not name a valid EGLContext";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_CONFIG :
|
||||
case EGL_BAD_CONFIG:
|
||||
{
|
||||
error = "EGL_BAD_CONFIG";
|
||||
description = "an EGLConfig argument does not name a valid EGLConfig";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_CURRENT_SURFACE :
|
||||
case EGL_BAD_CURRENT_SURFACE:
|
||||
{
|
||||
error = "EGL_BAD_CURRENT_SURFACE";
|
||||
description = "the current surface of the calling thread is a window, pbuffer, or pixmap that is no longer valid";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_DISPLAY :
|
||||
case EGL_BAD_DISPLAY:
|
||||
{
|
||||
error = "EGL_BAD_DISPLAY";
|
||||
description = "an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on the specified EGLDisplay";
|
||||
|
@ -106,42 +106,42 @@ void eglCheckError(const char* file, unsigned int line)
|
|||
}
|
||||
|
||||
|
||||
case EGL_BAD_SURFACE :
|
||||
case EGL_BAD_SURFACE:
|
||||
{
|
||||
error = "EGL_BAD_SURFACE";
|
||||
description = "an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) configured for rendering";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_MATCH :
|
||||
case EGL_BAD_MATCH:
|
||||
{
|
||||
error = "EGL_BAD_MATCH";
|
||||
description = "arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth or stencil) not allocated by an otherwise valid surface";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_PARAMETER :
|
||||
case EGL_BAD_PARAMETER:
|
||||
{
|
||||
error = "EGL_BAD_PARAMETER";
|
||||
description = "one or more argument values are invalid";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_NATIVE_PIXMAP :
|
||||
case EGL_BAD_NATIVE_PIXMAP:
|
||||
{
|
||||
error = "EGL_BAD_NATIVE_PIXMAP";
|
||||
description = "an EGLNativePixmapType argument does not refer to a valid native pixmap";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_NATIVE_WINDOW :
|
||||
case EGL_BAD_NATIVE_WINDOW:
|
||||
{
|
||||
error = "EGL_BAD_NATIVE_WINDOW";
|
||||
description = "an EGLNativeWindowType argument does not refer to a valid native window";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_CONTEXT_LOST :
|
||||
case EGL_CONTEXT_LOST:
|
||||
{
|
||||
error = "EGL_CONTEXT_LOST";
|
||||
description = "a power management event has occured. The application must destroy all contexts and reinitialise client API state and objects to continue rendering";
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace priv
|
|||
{
|
||||
class EglContext : public GlContext
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new context, not associated to a window
|
||||
|
@ -102,7 +102,7 @@ public :
|
|||
/// This can avoid some visual artifacts, and limit the framerate
|
||||
/// to a good value (but not constant across different computers).
|
||||
///
|
||||
/// \param enabled : True to enable v-sync, false to deactivate
|
||||
/// \param enabled: True to enable v-sync, false to deactivate
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void setVerticalSyncEnabled(bool enabled);
|
||||
|
@ -123,7 +123,7 @@ public :
|
|||
/// This function must be called when the activity (re)start, or
|
||||
/// when the orientation change.
|
||||
///
|
||||
/// \param window : The native window type
|
||||
/// \param window: The native window type
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void createSurface(EGLNativeWindowType window);
|
||||
|
@ -163,7 +163,7 @@ public :
|
|||
static XVisualInfo selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings);
|
||||
#endif
|
||||
|
||||
private :
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class JoystickImpl
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Perform the global initialization of the joystick module
|
||||
|
@ -107,7 +107,7 @@ public :
|
|||
////////////////////////////////////////////////////////////
|
||||
JoystickState update();
|
||||
|
||||
private :
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
|
|
|
@ -1,300 +1,300 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/GlContext.hpp>
|
||||
#include <SFML/System/ThreadLocalPtr.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/OpenGL.hpp>
|
||||
#include <set>
|
||||
#include <cstdlib>
|
||||
#ifdef SFML_SYSTEM_IOS
|
||||
#include <OpenGLES/ES1/gl.h>
|
||||
#else
|
||||
#include <SFML/Window/glext/glext.h>
|
||||
#endif
|
||||
|
||||
#if !defined(SFML_OPENGL_ES)
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
#include <SFML/Window/Win32/WglContext.hpp>
|
||||
typedef sf::priv::WglContext ContextType;
|
||||
|
||||
#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
|
||||
|
||||
#include <SFML/Window/Unix/GlxContext.hpp>
|
||||
typedef sf::priv::GlxContext ContextType;
|
||||
|
||||
#elif defined(SFML_SYSTEM_MACOS)
|
||||
|
||||
#include <SFML/Window/OSX/SFContext.hpp>
|
||||
typedef sf::priv::SFContext ContextType;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if defined(SFML_SYSTEM_IOS)
|
||||
|
||||
#include <SFML/Window/iOS/EaglContext.hpp>
|
||||
typedef sf::priv::EaglContext ContextType;
|
||||
|
||||
#else
|
||||
|
||||
#include <SFML/Window/EglContext.hpp>
|
||||
typedef sf::priv::EglContext ContextType;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// This per-thread variable holds the current context for each thread
|
||||
sf::ThreadLocalPtr<sf::priv::GlContext> currentContext(NULL);
|
||||
|
||||
// The hidden, inactive context that will be shared with all other contexts
|
||||
ContextType* sharedContext = NULL;
|
||||
|
||||
// Internal contexts
|
||||
sf::ThreadLocalPtr<sf::priv::GlContext> internalContext(NULL);
|
||||
std::set<sf::priv::GlContext*> internalContexts;
|
||||
sf::Mutex internalContextsMutex;
|
||||
|
||||
// Check if the internal context of the current thread is valid
|
||||
bool hasInternalContext()
|
||||
{
|
||||
// The internal context can be null...
|
||||
if (!internalContext)
|
||||
return false;
|
||||
|
||||
// ... or non-null but deleted from the list of internal contexts
|
||||
sf::Lock lock(internalContextsMutex);
|
||||
return internalContexts.find(internalContext) != internalContexts.end();
|
||||
}
|
||||
|
||||
// Retrieve the internal context for the current thread
|
||||
sf::priv::GlContext* getInternalContext()
|
||||
{
|
||||
if (!hasInternalContext())
|
||||
{
|
||||
internalContext = sf::priv::GlContext::create();
|
||||
sf::Lock lock(internalContextsMutex);
|
||||
internalContexts.insert(internalContext);
|
||||
}
|
||||
|
||||
return internalContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::globalInit()
|
||||
{
|
||||
// Create the shared context
|
||||
sharedContext = new ContextType(NULL);
|
||||
sharedContext->initialize();
|
||||
|
||||
// This call makes sure that:
|
||||
// - the shared context is inactive (it must never be)
|
||||
// - another valid context is activated in the current thread
|
||||
sharedContext->setActive(false);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::globalCleanup()
|
||||
{
|
||||
// Destroy the shared context
|
||||
delete sharedContext;
|
||||
sharedContext = NULL;
|
||||
|
||||
// Destroy the internal contexts
|
||||
sf::Lock lock(internalContextsMutex);
|
||||
for (std::set<GlContext*>::iterator it = internalContexts.begin(); it != internalContexts.end(); ++it)
|
||||
delete *it;
|
||||
internalContexts.clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::ensureContext()
|
||||
{
|
||||
// If there's no active context on the current thread, activate an internal one
|
||||
if (!currentContext)
|
||||
getInternalContext()->setActive(true);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext* GlContext::create()
|
||||
{
|
||||
GlContext* context = new ContextType(sharedContext);
|
||||
context->initialize();
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel)
|
||||
{
|
||||
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||
ensureContext();
|
||||
|
||||
// Create the context
|
||||
GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
|
||||
context->initialize();
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height)
|
||||
{
|
||||
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||
ensureContext();
|
||||
|
||||
// Create the context
|
||||
GlContext* context = new ContextType(sharedContext, settings, width, height);
|
||||
context->initialize();
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext::~GlContext()
|
||||
{
|
||||
// Deactivate the context before killing it, unless we're inside Cleanup()
|
||||
if (sharedContext)
|
||||
setActive(false);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const ContextSettings& GlContext::getSettings() const
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool GlContext::setActive(bool active)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
if (this != currentContext)
|
||||
{
|
||||
// Activate the context
|
||||
if (makeCurrent())
|
||||
{
|
||||
// Set it as the new current context for this thread
|
||||
currentContext = this;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This context is already the active one on this thread, don't do anything
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this == currentContext)
|
||||
{
|
||||
// To deactivate the context, we actually activate another one so that we make
|
||||
// sure that there is always an active context for subsequent graphics operations
|
||||
return getInternalContext()->setActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This context is not the active one on this thread, don't do anything
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext::GlContext()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing)
|
||||
{
|
||||
return std::abs(static_cast<int>(bitsPerPixel - colorBits)) +
|
||||
std::abs(static_cast<int>(settings.depthBits - depthBits)) +
|
||||
std::abs(static_cast<int>(settings.stencilBits - stencilBits)) +
|
||||
std::abs(static_cast<int>(settings.antialiasingLevel - antialiasing));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::initialize()
|
||||
{
|
||||
// Activate the context
|
||||
setActive(true);
|
||||
|
||||
// Retrieve the context version number
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
if (version)
|
||||
{
|
||||
// The beginning of the returned string is "major.minor" (this is standard)
|
||||
m_settings.majorVersion = version[0] - '0';
|
||||
m_settings.minorVersion = version[2] - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't get the version number, assume 2.0
|
||||
m_settings.majorVersion = 2;
|
||||
m_settings.minorVersion = 0;
|
||||
}
|
||||
|
||||
// Enable antialiasing if needed
|
||||
if (m_settings.antialiasingLevel > 0)
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/GlContext.hpp>
|
||||
#include <SFML/System/ThreadLocalPtr.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/OpenGL.hpp>
|
||||
#include <set>
|
||||
#include <cstdlib>
|
||||
#ifdef SFML_SYSTEM_IOS
|
||||
#include <OpenGLES/ES1/gl.h>
|
||||
#else
|
||||
#include <SFML/Window/glext/glext.h>
|
||||
#endif
|
||||
|
||||
#if !defined(SFML_OPENGL_ES)
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
#include <SFML/Window/Win32/WglContext.hpp>
|
||||
typedef sf::priv::WglContext ContextType;
|
||||
|
||||
#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
|
||||
|
||||
#include <SFML/Window/Unix/GlxContext.hpp>
|
||||
typedef sf::priv::GlxContext ContextType;
|
||||
|
||||
#elif defined(SFML_SYSTEM_MACOS)
|
||||
|
||||
#include <SFML/Window/OSX/SFContext.hpp>
|
||||
typedef sf::priv::SFContext ContextType;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if defined(SFML_SYSTEM_IOS)
|
||||
|
||||
#include <SFML/Window/iOS/EaglContext.hpp>
|
||||
typedef sf::priv::EaglContext ContextType;
|
||||
|
||||
#else
|
||||
|
||||
#include <SFML/Window/EglContext.hpp>
|
||||
typedef sf::priv::EglContext ContextType;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// This per-thread variable holds the current context for each thread
|
||||
sf::ThreadLocalPtr<sf::priv::GlContext> currentContext(NULL);
|
||||
|
||||
// The hidden, inactive context that will be shared with all other contexts
|
||||
ContextType* sharedContext = NULL;
|
||||
|
||||
// Internal contexts
|
||||
sf::ThreadLocalPtr<sf::priv::GlContext> internalContext(NULL);
|
||||
std::set<sf::priv::GlContext*> internalContexts;
|
||||
sf::Mutex internalContextsMutex;
|
||||
|
||||
// Check if the internal context of the current thread is valid
|
||||
bool hasInternalContext()
|
||||
{
|
||||
// The internal context can be null...
|
||||
if (!internalContext)
|
||||
return false;
|
||||
|
||||
// ... or non-null but deleted from the list of internal contexts
|
||||
sf::Lock lock(internalContextsMutex);
|
||||
return internalContexts.find(internalContext) != internalContexts.end();
|
||||
}
|
||||
|
||||
// Retrieve the internal context for the current thread
|
||||
sf::priv::GlContext* getInternalContext()
|
||||
{
|
||||
if (!hasInternalContext())
|
||||
{
|
||||
internalContext = sf::priv::GlContext::create();
|
||||
sf::Lock lock(internalContextsMutex);
|
||||
internalContexts.insert(internalContext);
|
||||
}
|
||||
|
||||
return internalContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::globalInit()
|
||||
{
|
||||
// Create the shared context
|
||||
sharedContext = new ContextType(NULL);
|
||||
sharedContext->initialize();
|
||||
|
||||
// This call makes sure that:
|
||||
// - the shared context is inactive (it must never be)
|
||||
// - another valid context is activated in the current thread
|
||||
sharedContext->setActive(false);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::globalCleanup()
|
||||
{
|
||||
// Destroy the shared context
|
||||
delete sharedContext;
|
||||
sharedContext = NULL;
|
||||
|
||||
// Destroy the internal contexts
|
||||
sf::Lock lock(internalContextsMutex);
|
||||
for (std::set<GlContext*>::iterator it = internalContexts.begin(); it != internalContexts.end(); ++it)
|
||||
delete *it;
|
||||
internalContexts.clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::ensureContext()
|
||||
{
|
||||
// If there's no active context on the current thread, activate an internal one
|
||||
if (!currentContext)
|
||||
getInternalContext()->setActive(true);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext* GlContext::create()
|
||||
{
|
||||
GlContext* context = new ContextType(sharedContext);
|
||||
context->initialize();
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel)
|
||||
{
|
||||
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||
ensureContext();
|
||||
|
||||
// Create the context
|
||||
GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
|
||||
context->initialize();
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height)
|
||||
{
|
||||
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||
ensureContext();
|
||||
|
||||
// Create the context
|
||||
GlContext* context = new ContextType(sharedContext, settings, width, height);
|
||||
context->initialize();
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext::~GlContext()
|
||||
{
|
||||
// Deactivate the context before killing it, unless we're inside Cleanup()
|
||||
if (sharedContext)
|
||||
setActive(false);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const ContextSettings& GlContext::getSettings() const
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool GlContext::setActive(bool active)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
if (this != currentContext)
|
||||
{
|
||||
// Activate the context
|
||||
if (makeCurrent())
|
||||
{
|
||||
// Set it as the new current context for this thread
|
||||
currentContext = this;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This context is already the active one on this thread, don't do anything
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this == currentContext)
|
||||
{
|
||||
// To deactivate the context, we actually activate another one so that we make
|
||||
// sure that there is always an active context for subsequent graphics operations
|
||||
return getInternalContext()->setActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This context is not the active one on this thread, don't do anything
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext::GlContext()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing)
|
||||
{
|
||||
return std::abs(static_cast<int>(bitsPerPixel - colorBits)) +
|
||||
std::abs(static_cast<int>(settings.depthBits - depthBits)) +
|
||||
std::abs(static_cast<int>(settings.stencilBits - stencilBits)) +
|
||||
std::abs(static_cast<int>(settings.antialiasingLevel - antialiasing));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::initialize()
|
||||
{
|
||||
// Activate the context
|
||||
setActive(true);
|
||||
|
||||
// Retrieve the context version number
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
if (version)
|
||||
{
|
||||
// The beginning of the returned string is "major.minor" (this is standard)
|
||||
m_settings.majorVersion = version[0] - '0';
|
||||
m_settings.minorVersion = version[2] - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't get the version number, assume 2.0
|
||||
m_settings.majorVersion = 2;
|
||||
m_settings.minorVersion = 0;
|
||||
}
|
||||
|
||||
// Enable antialiasing if needed
|
||||
if (m_settings.antialiasingLevel > 0)
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -1,234 +1,234 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_GLCONTEXT_HPP
|
||||
#define SFML_GLCONTEXT_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/Window/ContextSettings.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
class WindowImpl;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Abstract class representing an OpenGL context
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class GlContext : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Perform the global initialization
|
||||
///
|
||||
/// This function is called once, before the very first OpenGL
|
||||
/// resource is created. It makes sure that everything is ready
|
||||
/// for contexts to work properly.
|
||||
/// Note: this function doesn't need to be thread-safe, as it
|
||||
/// can be called only once.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void globalInit();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Perform the global cleanup
|
||||
///
|
||||
/// This function is called after the very last OpenGL resource
|
||||
/// is destroyed. It makes sure that everything that was
|
||||
/// created by initialize() is properly released.
|
||||
/// Note: this function doesn't need to be thread-safe, as it
|
||||
/// can be called only once.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void globalCleanup();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Ensures that an OpenGL context is active in the current thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void ensureContext();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new context, not associated to a window
|
||||
///
|
||||
/// This function automatically chooses the specialized class
|
||||
/// to use according to the OS.
|
||||
///
|
||||
/// \return Pointer to the created context (don't forget to delete it)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static GlContext* create();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new context attached to a window
|
||||
///
|
||||
/// This function automatically chooses the specialized class
|
||||
/// to use according to the OS.
|
||||
///
|
||||
/// \param settings Creation parameters
|
||||
/// \param owner Pointer to the owner window
|
||||
/// \param bitsPerPixel Pixel depth (in bits per pixel)
|
||||
///
|
||||
/// \return Pointer to the created context
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static GlContext* create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new context that embeds its own rendering target
|
||||
///
|
||||
/// This function automatically chooses the specialized class
|
||||
/// to use according to the OS.
|
||||
///
|
||||
/// \param settings Creation parameters
|
||||
/// \param width Back buffer width
|
||||
/// \param height Back buffer height
|
||||
///
|
||||
/// \return Pointer to the created context
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static GlContext* create(const ContextSettings& settings, unsigned int width, unsigned int height);
|
||||
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual ~GlContext();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the settings of the context
|
||||
///
|
||||
/// Note that these settings may be different than the ones
|
||||
/// passed to the constructor; they are indeed adjusted if the
|
||||
/// original settings are not directly supported by the system.
|
||||
///
|
||||
/// \return Structure containing the settings
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const ContextSettings& getSettings() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate or deactivate the context as the current target for rendering
|
||||
///
|
||||
/// A context is active only on the current thread, if you want to
|
||||
/// make it active on another thread you have to deactivate it
|
||||
/// on the previous thread first if it was active.
|
||||
/// Only one context can be active on a thread at a time, thus
|
||||
/// the context previously active (if any) automatically gets deactivated.
|
||||
///
|
||||
/// \param active True to activate, false to deactivate
|
||||
///
|
||||
/// \return True if operation was successful, false otherwise
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool setActive(bool active);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Display what has been rendered to the context so far
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void display() = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Enable or disable vertical synchronization
|
||||
///
|
||||
/// Activating vertical synchronization will limit the number
|
||||
/// of frames displayed to the refresh rate of the monitor.
|
||||
/// This can avoid some visual artifacts, and limit the framerate
|
||||
/// to a good value (but not constant across different computers).
|
||||
///
|
||||
/// \param enabled True to enable v-sync, false to deactivate
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void setVerticalSyncEnabled(bool enabled) = 0;
|
||||
|
||||
protected :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// This constructor is meant for derived classes only.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate the context as the current target
|
||||
/// for rendering
|
||||
///
|
||||
/// \return True on success, false if any error happened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool makeCurrent() = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Evaluate a pixel format configuration
|
||||
///
|
||||
/// This functions can be used by implementations that have
|
||||
/// several valid formats and want to get the best one.
|
||||
/// A score is returned for the given configuration: the
|
||||
/// lower the score is, the better the configuration is.
|
||||
///
|
||||
/// \param bitsPerPixel Requested pixel depth (bits per pixel)
|
||||
/// \param settings Requested additionnal settings
|
||||
/// \param colorBits Color bits of the configuration to evaluate
|
||||
/// \param depthBits Depth bits of the configuration to evaluate
|
||||
/// \param stencilBits Stencil bits of the configuration to evaluate
|
||||
/// \param antialiasing Antialiasing level of the configuration to evaluate
|
||||
///
|
||||
/// \return Score of the configuration
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
ContextSettings m_settings; ///< Creation settings of the context
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Perform various initializations after the context construction
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void initialize();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GLCONTEXT_HPP
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_GLCONTEXT_HPP
|
||||
#define SFML_GLCONTEXT_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Config.hpp>
|
||||
#include <SFML/Window/ContextSettings.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
class WindowImpl;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Abstract class representing an OpenGL context
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class GlContext : NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Perform the global initialization
|
||||
///
|
||||
/// This function is called once, before the very first OpenGL
|
||||
/// resource is created. It makes sure that everything is ready
|
||||
/// for contexts to work properly.
|
||||
/// Note: this function doesn't need to be thread-safe, as it
|
||||
/// can be called only once.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void globalInit();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Perform the global cleanup
|
||||
///
|
||||
/// This function is called after the very last OpenGL resource
|
||||
/// is destroyed. It makes sure that everything that was
|
||||
/// created by initialize() is properly released.
|
||||
/// Note: this function doesn't need to be thread-safe, as it
|
||||
/// can be called only once.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void globalCleanup();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Ensures that an OpenGL context is active in the current thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void ensureContext();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new context, not associated to a window
|
||||
///
|
||||
/// This function automatically chooses the specialized class
|
||||
/// to use according to the OS.
|
||||
///
|
||||
/// \return Pointer to the created context (don't forget to delete it)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static GlContext* create();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new context attached to a window
|
||||
///
|
||||
/// This function automatically chooses the specialized class
|
||||
/// to use according to the OS.
|
||||
///
|
||||
/// \param settings Creation parameters
|
||||
/// \param owner Pointer to the owner window
|
||||
/// \param bitsPerPixel Pixel depth (in bits per pixel)
|
||||
///
|
||||
/// \return Pointer to the created context
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static GlContext* create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new context that embeds its own rendering target
|
||||
///
|
||||
/// This function automatically chooses the specialized class
|
||||
/// to use according to the OS.
|
||||
///
|
||||
/// \param settings Creation parameters
|
||||
/// \param width Back buffer width
|
||||
/// \param height Back buffer height
|
||||
///
|
||||
/// \return Pointer to the created context
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static GlContext* create(const ContextSettings& settings, unsigned int width, unsigned int height);
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual ~GlContext();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the settings of the context
|
||||
///
|
||||
/// Note that these settings may be different than the ones
|
||||
/// passed to the constructor; they are indeed adjusted if the
|
||||
/// original settings are not directly supported by the system.
|
||||
///
|
||||
/// \return Structure containing the settings
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const ContextSettings& getSettings() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate or deactivate the context as the current target for rendering
|
||||
///
|
||||
/// A context is active only on the current thread, if you want to
|
||||
/// make it active on another thread you have to deactivate it
|
||||
/// on the previous thread first if it was active.
|
||||
/// Only one context can be active on a thread at a time, thus
|
||||
/// the context previously active (if any) automatically gets deactivated.
|
||||
///
|
||||
/// \param active True to activate, false to deactivate
|
||||
///
|
||||
/// \return True if operation was successful, false otherwise
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool setActive(bool active);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Display what has been rendered to the context so far
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void display() = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Enable or disable vertical synchronization
|
||||
///
|
||||
/// Activating vertical synchronization will limit the number
|
||||
/// of frames displayed to the refresh rate of the monitor.
|
||||
/// This can avoid some visual artifacts, and limit the framerate
|
||||
/// to a good value (but not constant across different computers).
|
||||
///
|
||||
/// \param enabled True to enable v-sync, false to deactivate
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void setVerticalSyncEnabled(bool enabled) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// This constructor is meant for derived classes only.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate the context as the current target
|
||||
/// for rendering
|
||||
///
|
||||
/// \return True on success, false if any error happened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool makeCurrent() = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Evaluate a pixel format configuration
|
||||
///
|
||||
/// This functions can be used by implementations that have
|
||||
/// several valid formats and want to get the best one.
|
||||
/// A score is returned for the given configuration: the
|
||||
/// lower the score is, the better the configuration is.
|
||||
///
|
||||
/// \param bitsPerPixel Requested pixel depth (bits per pixel)
|
||||
/// \param settings Requested additionnal settings
|
||||
/// \param colorBits Color bits of the configuration to evaluate
|
||||
/// \param depthBits Depth bits of the configuration to evaluate
|
||||
/// \param stencilBits Stencil bits of the configuration to evaluate
|
||||
/// \param antialiasing Antialiasing level of the configuration to evaluate
|
||||
///
|
||||
/// \return Score of the configuration
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
ContextSettings m_settings; ///< Creation settings of the context
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Perform various initializations after the context construction
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void initialize();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_GLCONTEXT_HPP
|
||||
|
|
|
@ -1,85 +1,85 @@
|
|||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/GlResource.hpp>
|
||||
#include <SFML/Window/GlContext.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// OpenGL resources counter and its mutex
|
||||
unsigned int count = 0;
|
||||
sf::Mutex mutex;
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
GlResource::GlResource()
|
||||
{
|
||||
{
|
||||
// Protect from concurrent access
|
||||
Lock lock(mutex);
|
||||
|
||||
// If this is the very first resource, trigger the global context initialization
|
||||
if (count == 0)
|
||||
priv::GlContext::globalInit();
|
||||
|
||||
// Increment the resources counter
|
||||
count++;
|
||||
}
|
||||
|
||||
// Now make sure that there is an active OpenGL context in the current thread
|
||||
priv::GlContext::ensureContext();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlResource::~GlResource()
|
||||
{
|
||||
// Protect from concurrent access
|
||||
Lock lock(mutex);
|
||||
|
||||
// Decrement the resources counter
|
||||
count--;
|
||||
|
||||
// If there's no more resource alive, we can trigger the global context cleanup
|
||||
if (count == 0)
|
||||
priv::GlContext::globalCleanup();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlResource::ensureGlContext()
|
||||
{
|
||||
priv::GlContext::ensureContext();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/GlResource.hpp>
|
||||
#include <SFML/Window/GlContext.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// OpenGL resources counter and its mutex
|
||||
unsigned int count = 0;
|
||||
sf::Mutex mutex;
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
GlResource::GlResource()
|
||||
{
|
||||
{
|
||||
// Protect from concurrent access
|
||||
Lock lock(mutex);
|
||||
|
||||
// If this is the very first resource, trigger the global context initialization
|
||||
if (count == 0)
|
||||
priv::GlContext::globalInit();
|
||||
|
||||
// Increment the resources counter
|
||||
count++;
|
||||
}
|
||||
|
||||
// Now make sure that there is an active OpenGL context in the current thread
|
||||
priv::GlContext::ensureContext();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlResource::~GlResource()
|
||||
{
|
||||
// Protect from concurrent access
|
||||
Lock lock(mutex);
|
||||
|
||||
// Decrement the resources counter
|
||||
count--;
|
||||
|
||||
// If there's no more resource alive, we can trigger the global context cleanup
|
||||
if (count == 0)
|
||||
priv::GlContext::globalCleanup();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlResource::ensureGlContext()
|
||||
{
|
||||
priv::GlContext::ensureContext();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class JoystickManager : NonCopyable
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the global unique instance of the manager
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace priv
|
|||
////////////////////////////////////////////////////////////
|
||||
class PoolWrapper : NonCopyable
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
|
|
|
@ -54,7 +54,7 @@ typedef std::vector<IOHIDElementRef> IOHIDElements;
|
|||
////////////////////////////////////////////////////////////
|
||||
class HIDInputManager : NonCopyable
|
||||
{
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the unique instance of the class
|
||||
|
@ -86,7 +86,7 @@ public :
|
|||
////////////////////////////////////////////////////////////
|
||||
bool isMouseButtonPressed(Mouse::Button button);
|
||||
|
||||
public :
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the usb location ID of a given device
|
||||
|
@ -130,7 +130,7 @@ public :
|
|||
////////////////////////////////////////////////////////////
|
||||
static Keyboard::Key nonLocalizedKeys(UniChar virtualKeycode);
|
||||
|
||||
private :
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
|
@ -247,7 +247,7 @@ private :
|
|||
////////////////////////////////////////////////////////////
|
||||
static UInt8 usageToVirtualCode(UInt32 usage);
|
||||
|
||||
private :
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
|
|
|
@ -367,7 +367,7 @@ void HIDInputManager::loadKey(IOHIDElementRef key)
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// These are known to be unbound :
|
||||
// These are known to be unbound:
|
||||
// Supposed Virtual | HID | Supposed Key
|
||||
// ===============================================
|
||||
// 0x1b | 0x2d | Hyphen
|
||||
|
@ -390,7 +390,7 @@ void HIDInputManager::loadKey(IOHIDElementRef key)
|
|||
} /* if (error == noErr) */
|
||||
else
|
||||
{
|
||||
sf::err() << "Cannot translate the virtual key code, error : "
|
||||
sf::err() << "Cannot translate the virtual key code, error: "
|
||||
<< error
|
||||
<< std::endl;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue