Merge remote-tracking branch 'horstbaerbel/master' into unstable

This commit is contained in:
Aloshi 2013-06-14 06:22:17 -05:00
commit b3fd961986
8 changed files with 120 additions and 88 deletions

View file

@ -28,17 +28,13 @@ void AudioManager::mixAudio(void *unused, Uint8 *stream, int len)
} }
//mix sample into stream //mix sample into stream
SDL_MixAudio(stream, &(sound->getData()[sound->getPosition()]), restLength, SDL_MIX_MAXVOLUME); SDL_MixAudio(stream, &(sound->getData()[sound->getPosition()]), restLength, SDL_MIX_MAXVOLUME);
if (sound->getPosition() + restLength >= sound->getLength()) if (sound->getPosition() + restLength < sound->getLength())
{
//if the position is beyond the end of the buffer, stop playing the sample
sound->stop();
}
else
{ {
//sample hasn't ended yet //sample hasn't ended yet
sound->setPosition(sound->getPosition() + restLength);
stillPlaying = true; stillPlaying = true;
} }
//set new sound position. if this is at or beyond the end of the sample, it will stop automatically
sound->setPosition(sound->getPosition() + restLength);
} }
//advance to next sound //advance to next sound
++soundIt; ++soundIt;

View file

@ -70,6 +70,7 @@ void Font::initLibrary()
} }
Font::Font(std::string path, int size) Font::Font(std::string path, int size)
: fontScale(1.0f)
{ {
mPath = path; mPath = path;
mSize = size; mSize = size;
@ -84,18 +85,7 @@ void Font::init()
mMaxGlyphHeight = 0; mMaxGlyphHeight = 0;
if(FT_New_Face(sLibrary, mPath.c_str(), 0, &face))
{
LOG(LogError) << "Error creating font face! (path: " << mPath.c_str();
return;
}
//FT_Set_Char_Size(face, 0, size * 64, getDpiX(), getDpiY());
FT_Set_Pixel_Sizes(face, 0, mSize);
buildAtlas(); buildAtlas();
FT_Done_Face(face);
} }
void Font::deinit() void Font::deinit()
@ -106,6 +96,15 @@ void Font::deinit()
void Font::buildAtlas() void Font::buildAtlas()
{ {
if(FT_New_Face(sLibrary, mPath.c_str(), 0, &face))
{
LOG(LogError) << "Error creating font face! (path: " << mPath.c_str();
return;
}
//FT_Set_Char_Size(face, 0, size * 64, getDpiX(), getDpiY());
FT_Set_Pixel_Sizes(face, 0, mSize);
//find the size we should use //find the size we should use
FT_GlyphSlot g = face->glyph; FT_GlyphSlot g = face->glyph;
int w = 0; int w = 0;
@ -130,8 +129,6 @@ void Font::buildAtlas()
textureWidth = w; textureWidth = w;
textureHeight = h; textureHeight = h;
//create the texture //create the texture
glGenTextures(1, &textureID); glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID); glBindTexture(GL_TEXTURE_2D, textureID);
@ -171,7 +168,7 @@ void Font::buildAtlas()
if(x + g->bitmap.width >= textureWidth) if(x + g->bitmap.width >= textureWidth)
{ {
x = 0; x = 0;
y += maxHeight; y += maxHeight + 1; //leave one pixel of space between glyphs
maxHeight = 0; maxHeight = 0;
} }
@ -185,23 +182,34 @@ void Font::buildAtlas()
charData[i].texY = y; charData[i].texY = y;
charData[i].texW = g->bitmap.width; charData[i].texW = g->bitmap.width;
charData[i].texH = g->bitmap.rows; charData[i].texH = g->bitmap.rows;
charData[i].advX = g->metrics.horiAdvance >> 6; charData[i].advX = g->metrics.horiAdvance / 64.0f;
charData[i].advY = g->advance.y >> 6; charData[i].advY = g->metrics.vertAdvance / 64.0f;
charData[i].bearingY = g->metrics.horiBearingY >> 6; charData[i].bearingY = g->metrics.horiBearingY / 64.0f;
if(charData[i].texH > mMaxGlyphHeight) if(charData[i].texH > mMaxGlyphHeight)
mMaxGlyphHeight = charData[i].texH; mMaxGlyphHeight = charData[i].texH;
x += g->bitmap.width; x += g->bitmap.width + 1; //leave one pixel of space between glyphs
}
if(y >= textureHeight)
{
LOG(LogError) << "Error - font size exceeded texture size! If you were doing something reasonable, tell Aloshi to fix it!";
} }
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
FT_Done_Face(face);
if((y + maxHeight) >= textureHeight)
{
//failed to create a proper font texture
LOG(LogError) << "Error - font with size " << mSize << " exceeded texture size! Trying again...";
//try a 3/4th smaller size and redo initialization
fontScale *= 1.25f;
mSize = (int)(mSize * (1.0f / fontScale));
deinit();
init();
}
else {
LOG(LogInfo) << "Created font with size " << mSize << std::endl;
}
//std::cout << "generated texture \"" << textureID << "\" (w: " << w << " h: " << h << ")" << std::endl; //std::cout << "generated texture \"" << textureID << "\" (w: " << w << " h: " << h << ")" << std::endl;
} }
@ -249,62 +257,62 @@ void Font::drawText(std::string text, int startx, int starty, int color)
return; return;
} }
starty += mMaxGlyphHeight;
//padding (another 0.5% is added to the bottom through the sizeText function)
starty += (int)(mMaxGlyphHeight * 0.1f);
int pointCount = text.length() * 2; int pointCount = text.length() * 2;
point* points = new point[pointCount]; point* points = new point[pointCount];
tex* texs = new tex[pointCount]; tex* texs = new tex[pointCount];
GLubyte* colors = new GLubyte[pointCount * 3 * 4]; GLubyte* colors = new GLubyte[pointCount * 3 * 4];
glBindTexture(GL_TEXTURE_2D, textureID); glBindTexture(GL_TEXTURE_2D, textureID);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//texture atlas width/height //texture atlas width/height
float tw = (float)textureWidth; float tw = (float)textureWidth;
float th = (float)textureHeight; float th = (float)textureHeight;
int p = 0;
int i = 0;
float x = (float)startx; float x = (float)startx;
float y = (float)starty; float y = starty + mMaxGlyphHeight * 1.1f * fontScale; //padding (another 0.5% is added to the bottom through the sizeText function)
for(; p < pointCount; i++, p++)
int p = 0;
for(int i = 0; p < pointCount; i++, p++)
{ {
unsigned char letter = text[i]; unsigned char letter = text[i];
if(letter < 32 || letter >= 128) if(letter < 32 || letter >= 128)
letter = 127; //print [X] if character is not standard ASCII letter = 127; //print [X] if character is not standard ASCII
points[p].pos0x = x; points[p].pos0y = y + charData[letter].texH - charData[letter].bearingY; points[p].pos0x = x;
points[p].pos1x = x + charData[letter].texW; points[p].pos1y = y - charData[letter].bearingY; points[p].pos0y = y + (charData[letter].texH - charData[letter].bearingY) * fontScale;
points[p].pos2x = x; points[p].pos2y = y - charData[letter].bearingY; points[p].pos1x = x + charData[letter].texW * fontScale;
points[p].pos1y = y - charData[letter].bearingY * fontScale;
texs[p].tex0x = charData[letter].texX / tw; texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th; points[p].pos2x = x;
texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw; texs[p].tex1y = charData[letter].texY / th; points[p].pos2y = points[p].pos1y;
texs[p].tex2x = charData[letter].texX / tw; texs[p].tex2y = charData[letter].texY / th;
texs[p].tex0x = charData[letter].texX / tw;
texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th;
texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw;
texs[p].tex1y = charData[letter].texY / th;
texs[p].tex2x = texs[p].tex0x;
texs[p].tex2y = texs[p].tex1y;
p++; p++;
points[p].pos0x = x; points[p].pos0y = y + charData[letter].texH - charData[letter].bearingY; points[p].pos0x = points[p-1].pos0x;
points[p].pos1x = x + charData[letter].texW; points[p].pos1y = y - charData[letter].bearingY; points[p].pos0y = points[p-1].pos0y;
points[p].pos2x = x + charData[letter].texW; points[p].pos2y = y + charData[letter].texH - charData[letter].bearingY; points[p].pos1x = points[p-1].pos1x;
points[p].pos1y = points[p-1].pos1y;
points[p].pos2x = points[p-1].pos1x;
points[p].pos2y = points[p-1].pos0y;
texs[p].tex0x = charData[letter].texX / tw; texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th; texs[p].tex0x = texs[p-1].tex0x;
texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw; texs[p].tex1y = charData[letter].texY / th; texs[p].tex0y = texs[p-1].tex0y;
texs[p].tex2x = texs[p].tex1x; texs[p].tex2y = texs[p].tex0y; texs[p].tex1x = texs[p-1].tex1x;
texs[p].tex1y = texs[p-1].tex1y;
texs[p].tex2x = texs[p-1].tex1x;
texs[p].tex2y = texs[p-1].tex0y;
x += charData[letter].advX * fontScale;
x += charData[letter].advX;
} }
Renderer::buildGLColorArray(colors, color, pointCount * 3); Renderer::buildGLColorArray(colors, color, pointCount * 3);
@ -340,18 +348,17 @@ void Font::sizeText(std::string text, int* w, int* h)
if(letter < 32 || letter >= 128) if(letter < 32 || letter >= 128)
letter = 127; letter = 127;
cwidth += charData[letter].advX; cwidth += charData[letter].advX * fontScale;
} }
if(w != NULL) if(w != NULL)
*w = cwidth; *w = cwidth;
if(h != NULL) if(h != NULL)
*h = (int)(mMaxGlyphHeight + mMaxGlyphHeight * 0.5f); *h = (int)(mMaxGlyphHeight * 1.5f * fontScale);
} }
int Font::getHeight() int Font::getHeight()
{ {
return (int)(mMaxGlyphHeight * 1.5f); return (int)(mMaxGlyphHeight * 1.5f * fontScale);
} }

View file

@ -26,10 +26,10 @@ public:
int texW; int texW;
int texH; int texH;
int advX; float advX;
int advY; float advY;
int bearingY; float bearingY;
}; };
charPosData charData[128]; charPosData charData[128];
@ -58,6 +58,7 @@ private:
int textureWidth; //OpenGL texture width int textureWidth; //OpenGL texture width
int textureHeight; //OpenGL texture height int textureHeight; //OpenGL texture height
int mMaxGlyphHeight; int mMaxGlyphHeight;
float fontScale; //!<Font scale factor. It is > 1.0 if the font would be to big for the texture
std::string mPath; std::string mPath;
int mSize; int mSize;

View file

@ -20,19 +20,29 @@ std::vector<unsigned char> ImageIO::loadFromMemoryRGBA32(const unsigned char * d
FIBITMAP * fiBitmap = FreeImage_LoadFromMemory(format, fiMemory); FIBITMAP * fiBitmap = FreeImage_LoadFromMemory(format, fiMemory);
if (fiBitmap != nullptr) if (fiBitmap != nullptr)
{ {
//loaded. convert to 32bit //loaded. convert to 32bit if necessary
FIBITMAP * fiConverted = nullptr;
if (FreeImage_GetBPP(fiBitmap) != 32)
{
FIBITMAP * fiConverted = FreeImage_ConvertTo32Bits(fiBitmap); FIBITMAP * fiConverted = FreeImage_ConvertTo32Bits(fiBitmap);
if (fiConverted != nullptr) if (fiConverted != nullptr)
{ {
width = FreeImage_GetWidth(fiConverted); //free original bitmap data
height = FreeImage_GetHeight(fiConverted); FreeImage_Unload(fiBitmap);
unsigned int pitch = FreeImage_GetPitch(fiConverted); fiBitmap = fiConverted;
}
}
if (fiBitmap != nullptr)
{
width = FreeImage_GetWidth(fiBitmap);
height = FreeImage_GetHeight(fiBitmap);
unsigned int pitch = FreeImage_GetPitch(fiBitmap);
//loop through scanlines and add all pixel data to the return vector //loop through scanlines and add all pixel data to the return vector
//this is necessary, because width*height*bpp might not be == pitch //this is necessary, because width*height*bpp might not be == pitch
unsigned char * tempData = new unsigned char[width * height * 4]; unsigned char * tempData = new unsigned char[width * height * 4];
for (size_t i = 0; i < height; i++) for (size_t i = 0; i < height; i++)
{ {
const BYTE * scanLine = FreeImage_GetScanLine(fiConverted, i); const BYTE * scanLine = FreeImage_GetScanLine(fiBitmap, i);
memcpy(tempData + (i * width * 4), scanLine, width * 4); memcpy(tempData + (i * width * 4), scanLine, width * 4);
} }
//convert from BGRA to RGBA //convert from BGRA to RGBA
@ -47,14 +57,16 @@ std::vector<unsigned char> ImageIO::loadFromMemoryRGBA32(const unsigned char * d
((RGBQUAD *)tempData)[i] = rgba; ((RGBQUAD *)tempData)[i] = rgba;
} }
rawData = std::vector<unsigned char>(tempData, tempData + width * height * 4); rawData = std::vector<unsigned char>(tempData, tempData + width * height * 4);
//free converted data
FreeImage_Unload(fiConverted);
}
//free bitmap data //free bitmap data
FreeImage_Unload(fiBitmap); FreeImage_Unload(fiBitmap);
} }
} }
else else
{
LOG(LogError) << "Error - Failed to load image from memory!";
}
}
else
{ {
LOG(LogError) << "Error - File type unknown/unsupported!"; LOG(LogError) << "Error - File type unknown/unsupported!";
} }

View file

@ -41,7 +41,7 @@ namespace Renderer
} }
//ATM it is best to just leave the window icon alone on windows. //ATM it is best to just leave the window icon alone on windows.
//When compiled as a Windows application, ES at least has an icon int the taskbar //When compiled as a Windows application, ES at least has an icon in the taskbar
//The method below looks pretty shite as alpha isn't taken into account... //The method below looks pretty shite as alpha isn't taken into account...
#ifndef WIN32 #ifndef WIN32
//try loading PNG from memory //try loading PNG from memory
@ -51,9 +51,9 @@ namespace Renderer
if (!rawData.empty()) { if (!rawData.empty()) {
//SDL interprets each pixel as a 32-bit number, so our masks must depend on the endianness (byte order) of the machine //SDL interprets each pixel as a 32-bit number, so our masks must depend on the endianness (byte order) of the machine
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 rmask = 0xff000000; Uint32 gmask = 0x00ff0000; Uint32 bmask = 0x0000ff00; Uint32 amask = 0x000000ff; Uint32 rmask = 0xff000000; Uint32 gmask = 0x0000ff00; Uint32 bmask = 0x00ff0000; Uint32 amask = 0x000000ff;
#else #else
Uint32 rmask = 0x000000ff; Uint32 gmask = 0x0000ff00; Uint32 bmask = 0x00ff0000;Uint32 amask = 0xff000000; Uint32 rmask = 0x000000ff; Uint32 gmask = 0x00ff0000; Uint32 bmask = 0x0000ff00; Uint32 amask = 0xff000000;
#endif #endif
//try creating SDL surface from logo data //try creating SDL surface from logo data
SDL_Surface * logoSurface = SDL_CreateRGBSurfaceFrom((void *)rawData.data(), width, height, 32, width*4, rmask, gmask, bmask, amask); SDL_Surface * logoSurface = SDL_CreateRGBSurfaceFrom((void *)rawData.data(), width, height, 32, width*4, rmask, gmask, bmask, amask);

View file

@ -82,18 +82,19 @@ void Sound::play()
if(mSampleData == NULL) if(mSampleData == NULL)
return; return;
SDL_LockAudio();
if (playing) if (playing)
{ {
//replay from start. rewind the sample to the beginning //replay from start. rewind the sample to the beginning
SDL_LockAudio();
mSamplePos = 0; mSamplePos = 0;
SDL_UnlockAudio();
} }
else else
{ {
//flag our sample as playing //flag our sample as playing
playing = true; playing = true;
} }
SDL_UnlockAudio();
//tell the AudioManager to start playing samples //tell the AudioManager to start playing samples
AudioManager::getInstance()->play(); AudioManager::getInstance()->play();
} }
@ -126,6 +127,8 @@ void Sound::setPosition(Uint32 newPosition)
{ {
mSamplePos = newPosition; mSamplePos = newPosition;
if (mSamplePos >= mSampleLength) { if (mSamplePos >= mSampleLength) {
//got to or beyond the end of the sample. stop playing
playing = false;
mSamplePos = 0; mSamplePos = 0;
} }
} }

View file

@ -215,6 +215,8 @@ void VolumeControl::deinit()
#error TODO: Not implemented for MacOS yet!!! #error TODO: Not implemented for MacOS yet!!!
#elif defined(__linux__) #elif defined(__linux__)
if (mixerHandle != nullptr) { if (mixerHandle != nullptr) {
snd_mixer_detach(mixerHandle, mixerCard);
snd_mixer_free(mixerHandle);
snd_mixer_close(mixerHandle); snd_mixer_close(mixerHandle);
mixerHandle = nullptr; mixerHandle = nullptr;
mixerElem = nullptr; mixerElem = nullptr;

View file

@ -3,6 +3,7 @@
#include <SDL.h> #include <SDL.h>
#include <iostream> #include <iostream>
#include <iomanip>
#include "Renderer.h" #include "Renderer.h"
#include "components/GuiGameList.h" #include "components/GuiGameList.h"
#include "SystemData.h" #include "SystemData.h"
@ -201,12 +202,22 @@ int main(int argc, char* argv[])
if(DRAWFRAMERATE) if(DRAWFRAMERATE)
{ {
float framerate = 1/((float)deltaTime)*1000; static int timeElapsed = 0;
static int nrOfFrames = 0;
static std::string fpsString;
nrOfFrames++;
timeElapsed += deltaTime;
//wait until half a second has passed to recalculate fps
if (timeElapsed >= 500) {
std::stringstream ss; std::stringstream ss;
ss << framerate; ss << std::fixed << std::setprecision(1) << (1000.0f * (float)nrOfFrames / (float)timeElapsed) << "fps, ";
std::string fps; ss << std::fixed << std::setprecision(2) << ((float)timeElapsed / (float)nrOfFrames) << "ms";
ss >> fps; fpsString = ss.str();
Renderer::drawText(fps, 50, 50, 0x00FF00FF, Renderer::getDefaultFont(Renderer::MEDIUM)); nrOfFrames = 0;
timeElapsed = 0;
}
Renderer::drawText(fpsString, 50, 50, 0x00FF00FF, Renderer::getDefaultFont(Renderer::MEDIUM));
} }
//sleep if we're past our threshold //sleep if we're past our threshold