Synchronized with trunk

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1372 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
LaurentGom 2010-01-26 10:52:36 +00:00
commit 57194f4d4b
7 changed files with 234 additions and 137 deletions

View File

@ -201,6 +201,17 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sound& operator =(const Sound& right); Sound& operator =(const Sound& right);
////////////////////////////////////////////////////////////
/// \brief Reset the internal buffer of the sound
///
/// This function is for internal use only, you don't have
/// to use it. It is called by the sf::SoundBuffer that
/// this sound uses, when it is destroyed in order to prevent
/// the sound from using a dead buffer.
///
////////////////////////////////////////////////////////////
void ResetBuffer();
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -32,10 +32,13 @@
#include <SFML/System/Resource.hpp> #include <SFML/System/Resource.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
#include <set>
namespace sf namespace sf
{ {
class Sound;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Storage for audio samples defining a sound /// \brief Storage for audio samples defining a sound
/// ///
@ -220,12 +223,34 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Update(unsigned int channelsCount, unsigned int sampleRate); bool Update(unsigned int channelsCount, unsigned int sampleRate);
////////////////////////////////////////////////////////////
/// \brief Add a sound to the list of sounds that use this buffer
///
/// \param sound Sound instance to attach
///
////////////////////////////////////////////////////////////
void AttachSound(Sound* sound) const;
////////////////////////////////////////////////////////////
/// \brief Remove a sound from the list of sounds that use this buffer
///
/// \param sound Sound instance to detach
///
////////////////////////////////////////////////////////////
void DetachSound(Sound* sound) const;
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef std::set<Sound*> SoundList; ///< Set of unique sound instances
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int myBuffer; ///< OpenAL buffer identifier unsigned int myBuffer; ///< OpenAL buffer identifier
std::vector<Int16> mySamples; ///< Samples buffer std::vector<Int16> mySamples; ///< Samples buffer
float myDuration; ///< Sound duration, in seconds float myDuration; ///< Sound duration, in seconds
mutable SoundList mySounds; ///< List of sounds that are using this buffer
}; };
} // namespace sf } // namespace sf

View File

@ -98,7 +98,7 @@ void EnsureALInit()
{ {
// The audio device is instanciated on demand rather than at global startup, // The audio device is instanciated on demand rather than at global startup,
// which solves a lot of weird crashes and errors. // which solves a lot of weird crashes and errors.
/// It is destroyed at global exit which is fine. // It is destroyed at global exit which is fine.
static AudioDevice globalDevice; static AudioDevice globalDevice;
} }

View File

@ -65,6 +65,8 @@ myBuffer (NULL)
Sound::~Sound() Sound::~Sound()
{ {
Stop(); Stop();
if (myBuffer)
myBuffer->DetachSound(this);
} }
@ -92,7 +94,16 @@ void Sound::Stop()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Sound::SetBuffer(const SoundBuffer& buffer) void Sound::SetBuffer(const SoundBuffer& buffer)
{ {
// First detach from the previous buffer
if (myBuffer)
{
Stop();
myBuffer->DetachSound(this);
}
// Assign and use the new buffer
myBuffer = &buffer; myBuffer = &buffer;
myBuffer->AttachSound(this);
ALCheck(alSourcei(mySource, AL_BUFFER, myBuffer->myBuffer)); ALCheck(alSourcei(mySource, AL_BUFFER, myBuffer->myBuffer));
} }
@ -148,12 +159,41 @@ Sound::Status Sound::GetStatus() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sound& Sound::operator =(const Sound& right) Sound& Sound::operator =(const Sound& right)
{ {
Sound temp(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
std::swap(mySource, temp.mySource); // Detach the sound instance from the previous buffer (if any)
std::swap(myBuffer, temp.myBuffer); if (myBuffer)
{
Stop();
myBuffer->DetachSound(this);
myBuffer = NULL;
}
// Copy the sound attributes
if (right.myBuffer)
SetBuffer(*right.myBuffer);
SetLoop(right.GetLoop());
SetPitch(right.GetPitch());
SetVolume(right.GetVolume());
SetPosition(right.GetPosition());
SetRelativeToListener(right.IsRelativeToListener());
SetMinDistance(right.GetMinDistance());
SetAttenuation(right.GetAttenuation());
return *this; return *this;
} }
////////////////////////////////////////////////////////////
void Sound::ResetBuffer()
{
// First stop the sound in case it is playing
Stop();
// Detach the buffer
ALCheck(alSourcei(mySource, AL_BUFFER, 0));
myBuffer = NULL;
}
} // namespace sf } // namespace sf

View File

@ -27,6 +27,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/SoundBuffer.hpp> #include <SFML/Audio/SoundBuffer.hpp>
#include <SFML/Audio/SoundFile.hpp> #include <SFML/Audio/SoundFile.hpp>
#include <SFML/Audio/Sound.hpp>
#include <SFML/Audio/AudioDevice.hpp> #include <SFML/Audio/AudioDevice.hpp>
#include <SFML/Audio/ALCheck.hpp> #include <SFML/Audio/ALCheck.hpp>
#include <iostream> #include <iostream>
@ -49,10 +50,10 @@ myDuration(0.f)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundBuffer::SoundBuffer(const SoundBuffer& copy) : SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
Resource<SoundBuffer>(copy),
myBuffer (0), myBuffer (0),
mySamples (copy.mySamples), mySamples (copy.mySamples),
myDuration (copy.myDuration) myDuration(copy.myDuration),
mySounds () // don't copy the attached sounds
{ {
// Create the buffer // Create the buffer
ALCheck(alGenBuffers(1, &myBuffer)); ALCheck(alGenBuffers(1, &myBuffer));
@ -65,6 +66,11 @@ myDuration (copy.myDuration)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundBuffer::~SoundBuffer() SoundBuffer::~SoundBuffer()
{ {
// First detach the buffer from the sounds that use it (to avoid OpenAL errors)
for (SoundList::const_iterator it = mySounds.begin(); it != mySounds.end(); ++it)
(*it)->ResetBuffer();
// Destroy the buffer
if (myBuffer) if (myBuffer)
ALCheck(alDeleteBuffers(1, &myBuffer)); ALCheck(alDeleteBuffers(1, &myBuffer));
} }
@ -223,9 +229,10 @@ SoundBuffer& SoundBuffer::operator =(const SoundBuffer& other)
{ {
SoundBuffer temp(other); SoundBuffer temp(other);
mySamples.swap(temp.mySamples); std::swap(mySamples, temp.mySamples);
std::swap(myBuffer, temp.myBuffer); std::swap(myBuffer, temp.myBuffer);
std::swap(myDuration, temp.myDuration); std::swap(myDuration, temp.myDuration);
std::swap(mySounds, temp.mySounds); // swap sounds too, so that they are detached when temp is destroyed
return *this; return *this;
} }
@ -258,4 +265,18 @@ bool SoundBuffer::Update(unsigned int channelsCount, unsigned int sampleRate)
return true; return true;
} }
////////////////////////////////////////////////////////////
void SoundBuffer::AttachSound(Sound* sound) const
{
mySounds.insert(sound);
}
////////////////////////////////////////////////////////////
void SoundBuffer::DetachSound(Sound* sound) const
{
mySounds.erase(sound);
}
} // namespace sf } // namespace sf

View File

@ -59,8 +59,7 @@ myPixelsFlipped (false)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Copy constructor /// Copy constructor
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Image::Image(const Image& copy) : Image::Image(const Image& copy)
Resource<Image>(copy)
{ {
// First make sure that the source image is up-to-date // First make sure that the source image is up-to-date
copy.EnsureArrayUpdate(); copy.EnsureArrayUpdate();

View File

@ -225,9 +225,9 @@ void Text::Render(RenderTarget&, Renderer& renderer) const
bool bold = (myStyle & Bold) != 0; bool bold = (myStyle & Bold) != 0;
bool underlined = (myStyle & Underlined) != 0; bool underlined = (myStyle & Underlined) != 0;
float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees
float outlineOffset = myCharacterSize * 0.1f; float underlineOffset = myCharacterSize * 0.1f;
float outlineThick = myCharacterSize * (bold ? 0.1f : 0.07f); float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f);
FloatRect outlineCoords = myFont->GetImage(myCharacterSize).GetTexCoords(IntRect(1, 1, 1, 1)); FloatRect underlineCoords = myFont->GetImage(myCharacterSize).GetTexCoords(IntRect(1, 1, 1, 1));
// Initialize the rendering coordinates // Initialize the rendering coordinates
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
@ -252,14 +252,14 @@ void Text::Render(RenderTarget&, Renderer& renderer) const
// If we're using the underlined style and there's a new line, draw a line // If we're using the underlined style and there's a new line, draw a line
if (underlined && (curChar == L'\n')) if (underlined && (curChar == L'\n'))
{ {
float top = y + outlineOffset; float top = y + underlineOffset;
float bottom = top + outlineThick; float bottom = top + underlineThickness;
renderer.Begin(Renderer::QuadList); renderer.Begin(Renderer::QuadList);
renderer.AddVertex(0, top, outlineCoords.Left, outlineCoords.Top); renderer.AddVertex(0, top, underlineCoords.Left, underlineCoords.Top);
renderer.AddVertex(x, top, outlineCoords.Right, outlineCoords.Top); renderer.AddVertex(x, top, underlineCoords.Right, underlineCoords.Top);
renderer.AddVertex(x, bottom, outlineCoords.Right, outlineCoords.Bottom); renderer.AddVertex(x, bottom, underlineCoords.Right, underlineCoords.Bottom);
renderer.AddVertex(0, bottom, outlineCoords.Left, outlineCoords.Bottom); renderer.AddVertex(0, bottom, underlineCoords.Left, underlineCoords.Bottom);
renderer.End(); renderer.End();
} }
@ -293,14 +293,14 @@ void Text::Render(RenderTarget&, Renderer& renderer) const
// If we're using the underlined style, add the last line // If we're using the underlined style, add the last line
if (underlined) if (underlined)
{ {
float top = y + outlineOffset; float top = y + underlineOffset;
float bottom = top + outlineThick; float bottom = top + underlineThickness;
renderer.Begin(Renderer::QuadList); renderer.Begin(Renderer::QuadList);
renderer.AddVertex(0, top, outlineCoords.Left, outlineCoords.Top); renderer.AddVertex(0, top, underlineCoords.Left, underlineCoords.Top);
renderer.AddVertex(x, top, outlineCoords.Right, outlineCoords.Top); renderer.AddVertex(x, top, underlineCoords.Right, underlineCoords.Top);
renderer.AddVertex(x, bottom, outlineCoords.Right, outlineCoords.Bottom); renderer.AddVertex(x, bottom, underlineCoords.Right, underlineCoords.Bottom);
renderer.AddVertex(0, bottom, outlineCoords.Left, outlineCoords.Bottom); renderer.AddVertex(0, bottom, underlineCoords.Left, underlineCoords.Bottom);
renderer.End(); renderer.End();
} }
} }
@ -324,8 +324,6 @@ void Text::UpdateRect() const
// Initial values // Initial values
bool bold = (myStyle & Bold) != 0; bool bold = (myStyle & Bold) != 0;
float outlineOffset = myCharacterSize * 0.1f;
float outlineThick = myCharacterSize * (bold ? 0.1f : 0.07f);
float charSize = static_cast<float>(myCharacterSize); float charSize = static_cast<float>(myCharacterSize);
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize)); float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
@ -395,8 +393,11 @@ void Text::UpdateRect() const
// Add a slight height if we're using the underlined style // Add a slight height if we're using the underlined style
if (myStyle & Underlined) if (myStyle & Underlined)
{ {
if (curHeight < charSize + outlineOffset + outlineThick) float underlineOffset = myCharacterSize * 0.1f;
height += outlineOffset + outlineThick; float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f);
if (curHeight < charSize + underlineOffset + underlineThickness)
height += underlineOffset + underlineThickness;
} }
// Finally update the rectangle // Finally update the rectangle