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);
////////////////////////////////////////////////////////////
/// \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 :
////////////////////////////////////////////////////////////

View File

@ -32,10 +32,13 @@
#include <SFML/System/Resource.hpp>
#include <string>
#include <vector>
#include <set>
namespace sf
{
class Sound;
////////////////////////////////////////////////////////////
/// \brief Storage for audio samples defining a sound
///
@ -220,12 +223,34 @@ private :
////////////////////////////////////////////////////////////
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
////////////////////////////////////////////////////////////
unsigned int myBuffer; ///< OpenAL buffer identifier
std::vector<Int16> mySamples; ///< Samples buffer
float myDuration; ///< Sound duration, in seconds
mutable SoundList mySounds; ///< List of sounds that are using this buffer
};
} // namespace sf

View File

@ -1,94 +1,94 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 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>
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
std::cerr << "An internal OpenAL call failed in "
<< file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : "
<< error << ", " << description
<< std::endl;
}
}
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 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>
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
std::cerr << "An internal OpenAL call failed in "
<< file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : "
<< error << ", " << description
<< std::endl;
}
}
////////////////////////////////////////////////////////////
@ -98,11 +98,11 @@ void EnsureALInit()
{
// The audio device is instanciated 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.
// It is destroyed at global exit which is fine.
static AudioDevice globalDevice;
}
} // namespace priv
} // namespace sf
} // namespace priv
} // namespace sf

View File

@ -65,6 +65,8 @@ myBuffer (NULL)
Sound::~Sound()
{
Stop();
if (myBuffer)
myBuffer->DetachSound(this);
}
@ -92,7 +94,16 @@ void Sound::Stop()
////////////////////////////////////////////////////////////
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->AttachSound(this);
ALCheck(alSourcei(mySource, AL_BUFFER, myBuffer->myBuffer));
}
@ -148,12 +159,41 @@ Sound::Status Sound::GetStatus() const
////////////////////////////////////////////////////////////
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);
std::swap(myBuffer, temp.myBuffer);
// Detach the sound instance from the previous buffer (if any)
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;
}
////////////////////////////////////////////////////////////
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

View File

@ -27,6 +27,7 @@
////////////////////////////////////////////////////////////
#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 <iostream>
@ -49,10 +50,10 @@ myDuration(0.f)
////////////////////////////////////////////////////////////
SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
Resource<SoundBuffer>(copy),
myBuffer (0),
mySamples (copy.mySamples),
myDuration (copy.myDuration)
myBuffer (0),
mySamples (copy.mySamples),
myDuration(copy.myDuration),
mySounds () // don't copy the attached sounds
{
// Create the buffer
ALCheck(alGenBuffers(1, &myBuffer));
@ -65,6 +66,11 @@ myDuration (copy.myDuration)
////////////////////////////////////////////////////////////
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)
ALCheck(alDeleteBuffers(1, &myBuffer));
}
@ -223,9 +229,10 @@ SoundBuffer& SoundBuffer::operator =(const SoundBuffer& other)
{
SoundBuffer temp(other);
mySamples.swap(temp.mySamples);
std::swap(mySamples, temp.mySamples);
std::swap(myBuffer, temp.myBuffer);
std::swap(myDuration, temp.myDuration);
std::swap(mySounds, temp.mySounds); // swap sounds too, so that they are detached when temp is destroyed
return *this;
}
@ -258,4 +265,18 @@ bool SoundBuffer::Update(unsigned int channelsCount, unsigned int sampleRate)
return true;
}
////////////////////////////////////////////////////////////
void SoundBuffer::AttachSound(Sound* sound) const
{
mySounds.insert(sound);
}
////////////////////////////////////////////////////////////
void SoundBuffer::DetachSound(Sound* sound) const
{
mySounds.erase(sound);
}
} // namespace sf

View File

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

View File

@ -222,12 +222,12 @@ void Text::Render(RenderTarget&, Renderer& renderer) const
renderer.SetTexture(&myFont->GetImage(myCharacterSize));
// Computes values related to the text style
bool bold = (myStyle & Bold) != 0;
bool underlined = (myStyle & Underlined) != 0;
float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees
float outlineOffset = myCharacterSize * 0.1f;
float outlineThick = myCharacterSize * (bold ? 0.1f : 0.07f);
FloatRect outlineCoords = myFont->GetImage(myCharacterSize).GetTexCoords(IntRect(1, 1, 1, 1));
bool bold = (myStyle & Bold) != 0;
bool underlined = (myStyle & Underlined) != 0;
float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees
float underlineOffset = myCharacterSize * 0.1f;
float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f);
FloatRect underlineCoords = myFont->GetImage(myCharacterSize).GetTexCoords(IntRect(1, 1, 1, 1));
// Initialize the rendering coordinates
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 (underlined && (curChar == L'\n'))
{
float top = y + outlineOffset;
float bottom = top + outlineThick;
float top = y + underlineOffset;
float bottom = top + underlineThickness;
renderer.Begin(Renderer::QuadList);
renderer.AddVertex(0, top, outlineCoords.Left, outlineCoords.Top);
renderer.AddVertex(x, top, outlineCoords.Right, outlineCoords.Top);
renderer.AddVertex(x, bottom, outlineCoords.Right, outlineCoords.Bottom);
renderer.AddVertex(0, bottom, outlineCoords.Left, outlineCoords.Bottom);
renderer.AddVertex(0, top, underlineCoords.Left, underlineCoords.Top);
renderer.AddVertex(x, top, underlineCoords.Right, underlineCoords.Top);
renderer.AddVertex(x, bottom, underlineCoords.Right, underlineCoords.Bottom);
renderer.AddVertex(0, bottom, underlineCoords.Left, underlineCoords.Bottom);
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 (underlined)
{
float top = y + outlineOffset;
float bottom = top + outlineThick;
float top = y + underlineOffset;
float bottom = top + underlineThickness;
renderer.Begin(Renderer::QuadList);
renderer.AddVertex(0, top, outlineCoords.Left, outlineCoords.Top);
renderer.AddVertex(x, top, outlineCoords.Right, outlineCoords.Top);
renderer.AddVertex(x, bottom, outlineCoords.Right, outlineCoords.Bottom);
renderer.AddVertex(0, bottom, outlineCoords.Left, outlineCoords.Bottom);
renderer.AddVertex(0, top, underlineCoords.Left, underlineCoords.Top);
renderer.AddVertex(x, top, underlineCoords.Right, underlineCoords.Top);
renderer.AddVertex(x, bottom, underlineCoords.Right, underlineCoords.Bottom);
renderer.AddVertex(0, bottom, underlineCoords.Left, underlineCoords.Bottom);
renderer.End();
}
}
@ -323,17 +323,15 @@ void Text::UpdateRect() const
return;
// Initial values
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 space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
float curWidth = 0;
float curHeight = 0;
float width = 0;
float height = 0;
Uint32 prevChar = 0;
bool bold = (myStyle & Bold) != 0;
float charSize = static_cast<float>(myCharacterSize);
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
float curWidth = 0;
float curHeight = 0;
float width = 0;
float height = 0;
Uint32 prevChar = 0;
// Go through each character
for (std::size_t i = 0; i < myString.GetSize(); ++i)
@ -395,8 +393,11 @@ void Text::UpdateRect() const
// Add a slight height if we're using the underlined style
if (myStyle & Underlined)
{
if (curHeight < charSize + outlineOffset + outlineThick)
height += outlineOffset + outlineThick;
float underlineOffset = myCharacterSize * 0.1f;
float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f);
if (curHeight < charSize + underlineOffset + underlineThickness)
height += underlineOffset + underlineThickness;
}
// Finally update the rectangle