mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 22:31:09 +08:00
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:
commit
57194f4d4b
@ -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 :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user