EffectRef SoundEngine::loadEffect(InputSourceRef inputSource)
{
    FMOD_RESULT result = FMOD_OK;
    FMOD::Sound *sound = NULL;
    
    if (inputSource->isFile())
    {
        result = system->createSound(inputSource->getFilePath().c_str(), FMOD_DEFAULT, NULL, &sound);
    }
    else
    {
        auto buffer = inputSource->loadDataSource()->getBuffer();
        
        FMOD_CREATESOUNDEXINFO exinfo;
        memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
        exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
        exinfo.length = buffer.getDataSize();
        
        result = system->createSound(static_cast<const char*>(buffer.getData()), FMOD_DEFAULT | FMOD_OPENMEMORY, &exinfo, &sound);
    }
    
    if (result)
    {
        throw FMODException(result);
    }
    else
    {
        return make_shared<Effect>(inputSource, sound);
    }
}
 void TextureAtlas::init(InputSourceRef inputSource, bool useMipmap)
 {
     XmlTree doc(inputSource->loadDataSource());
     
     auto texturePath = doc.getChild("TextureAtlas").getAttributeValue<string>("imagePath");
     auto textureSource = inputSource->getSubSource(texturePath);
     
     texture = textureManager.getTexture(textureSource, useMipmap);
     float width = texture->getWidth();
     float height = texture->getHeight();
     
     // ---
     
     for (auto spriteElement = doc.begin("TextureAtlas/sprite"); spriteElement != doc.end(); ++spriteElement)
     {
         auto spritePath = spriteElement->getAttributeValue<string>("n");
         
         auto x = spriteElement->getAttributeValue<float>("x");
         auto y = spriteElement->getAttributeValue<float>("y");
         auto w = spriteElement->getAttributeValue<float>("w");
         auto h = spriteElement->getAttributeValue<float>("h");
         auto rotated = spriteElement->hasAttribute("r");
         
         float ox, oy;
         float ow, oh;
         
         if (rotated)
         {
             oy = spriteElement->getAttributeValue<float>("oX", 0);
             ox = spriteElement->getAttributeValue<float>("oY", 0);
             ow = spriteElement->getAttributeValue<float>("oW", h);
             oh = spriteElement->getAttributeValue<float>("oH", w);
         }
         else
         {
             ox = spriteElement->getAttributeValue<float>("oX", 0);
             oy = spriteElement->getAttributeValue<float>("oY", 0);
             ow = spriteElement->getAttributeValue<float>("oW", w);
             oh = spriteElement->getAttributeValue<float>("oH", h);
         }
         
         float u1 = x / width;
         float v1 = y / height;
         
         float u2 = (x + w) / width;
         float v2 = (y + h) / height;
         
         sprites[spritePath] = make_shared<Sprite>(texture, w, h, ox, oy, ow, oh, rotated, u1, v1, u2, v2);
     }
 }
void XFont::read(InputSourceRef inputSource)
{
    if (inputSource->isFile())
    {
        ifstream in(inputSource->getFilePath().c_str(), ifstream::binary);
        readFromStream(in);
        in.close();
    }
    else
    {
        DataSourceRef resource = inputSource->loadDataSource();
        Buffer &buffer = resource->getBuffer();

        ReadStreamBuffer tmp(buffer);
        istream in(&tmp);
        readFromStream(in);
    }
}
FollowablePath::FollowablePath(InputSourceRef inputSource, int mode)
:
mode(mode)
{
    if (inputSource->isFile())
    {
        ifstream in(inputSource->getFilePath().c_str(), ifstream::binary);
        readFromStream(in);
        in.close();
    }
    else
    {
        DataSourceRef resource = inputSource->loadDataSource();
        Buffer &buffer = resource->getBuffer();
        
        ReadStreamBuffer tmp(buffer);
        istream in(&tmp);
        readFromStream(in);
    }
}
 std::pair<FontData*, FontAtlas*> FontManager::fetchFontDataAndAtlas(InputSourceRef source)
 {
     auto in = source->loadDataSource()->createStream(); // CAN THROW
     
     string version;
     in->readFixedString(&version, 10);
     
     if (version != "XFONT.003")
     {
         throw runtime_error("Font: WRONG FORMAT");
     }
     
     // ---
     
     int glyphCount;
     in->readLittle(&glyphCount);
     
     auto data = new FontData(glyphCount);
     
     in->readLittle(&data->baseSize);
     in->readLittle(&data->height);
     in->readLittle(&data->ascent);
     in->readLittle(&data->descent);
     in->readLittle(&data->spaceAdvance);
     in->readLittle(&data->strikethroughFactor);
     in->readLittle(&data->underlineOffset);
     in->readLittle(&data->lineThickness);
     
     int atlasWidth;
     int atlasHeight;
     int atlasPadding;
     int unitMargin;
     int unitPadding;
     
     in->readLittle(&atlasWidth);
     in->readLittle(&atlasHeight);
     in->readLittle(&atlasPadding);
     in->readLittle(&unitMargin);
     in->readLittle(&unitPadding);
     
     auto atlas = new FontAtlas(atlasWidth, atlasHeight);
     
     for (int i = 0; i < glyphCount; i++)
     {
         int glyphChar;
         int glyphWidth;
         int glyphHeight;
         int glyphLeftExtent;
         int glyphTopExtent;
         int glyphAtlasX;
         int glyphAtlasY;
         
         in->readLittle(&glyphChar);
         data->glyphs[(wchar_t)glyphChar] = i;
         
         in->readLittle(&data->advance[i]);
         in->readLittle(&glyphWidth);
         in->readLittle(&glyphHeight);
         in->readLittle(&glyphLeftExtent);
         in->readLittle(&glyphTopExtent);
         in->readLittle(&glyphAtlasX);
         in->readLittle(&glyphAtlasY);
         
         auto glyphData = new unsigned char[glyphWidth * glyphHeight];
         in->readData(glyphData, glyphWidth * glyphHeight);
         atlas->addGlyph(glyphData, glyphAtlasX + atlasPadding + unitMargin, glyphAtlasY + atlasPadding + unitMargin, glyphWidth, glyphHeight);
         delete[] glyphData;
         
         data->w[i] = glyphWidth + unitPadding * 2;
         data->h[i] = glyphHeight + unitPadding * 2;
         data->le[i] = glyphLeftExtent - unitPadding;
         data->te[i] = glyphTopExtent + unitPadding;
         
         int x = glyphAtlasX + atlasPadding + unitMargin - unitPadding;
         int y = glyphAtlasY + atlasPadding + unitMargin - unitPadding;
         
         data->u1[i] = x / (float)atlasWidth;
         data->v1[i] = y / (float)atlasHeight;
         data->u2[i] = (x + data->w[i]) / (float)atlasWidth;
         data->v2[i] = (y + data->h[i]) / (float)atlasHeight;
     }
     
     return make_pair(data, atlas);
 }