Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [CPP Source] - Load Assets using PhysicsFS  (Read 3362 times)

0 Members and 1 Guest are viewing this topic.

Mikey

  • Newbie
  • *
  • Posts: 10
    • MSN Messenger - mrking2910@googlemail.com
    • View Profile
[CPP Source] - Load Assets using PhysicsFS
« on: July 17, 2011, 06:26:13 pm »
Hey folks,

    I have spent a few hours knocking up a quick method for loading assets (images, fonts, etc.) using the PhysicsFS library.

 Feel free to rip it apart as much as you like, though please take a moment just to let me know what it's being used in as well as any changes that have been made to make it more efficient.

 Thanks :)


 Mikey


PLEASE NOTE: This is to be used in conjunction with the PhysFS library, and all initialisation, adding of paths etc. has to be done using the standard PhysFS methods.

PhysFSLoader.hpp
Code: [Select]

// ----------------------------------------------------------------------------------------------------
// Title: SFML PhysFS Asset Loader
// Description: Load Assets (Images, Fonts, etc.) using the PhysFS library.
// Revision: 1 (17 July 2011)
// Author(s): Michael R. King (mrking2910@gmail.com)
// Dependencies: SFML (http://www.sfml-dev.org/) (Designed for version 2.0)
// PhysFS (http://icculus.org/physfs/) (Designed for version 2.0.2)
// Notes: Will only load the assets.
// ----------------------------------------------------------------------------------------------------

// - Include Protection -
#ifndef _H_SFML_PHYSFS_LOADER_
#define _H_SFML_PHYSFS_LOADER_

// - Include SFML -
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

// - Include PhysFS -
#include <physfs.h>

// - Include in SFML Namespace -
namespace sf
{
// - Error Codes -
enum PFSL_Error
{
PFSL_Error_None,
PFSL_Error_PhysFSNotReady,
PFSL_Error_InvalidFileHandle,
PFSL_Error_FileNotFound,
PFSL_Error_LoadFailed,
PFSL_Error_FileTooBig,
PFLS_Error_NotEnoughRead
};

// - Loader Class Declaration -
class PhysFSLoader
{
protected:
PFSL_Error m_lastError;
PHYSFS_sint64 m_maxFileSize;
char* m_fileBuffer;
PHYSFS_sint64 m_fileSize;

protected:
bool doLoad(sf::String Filename);

public:
PFSL_Error GetLastError();
void SetMaxFileSize(PHYSFS_sint64 Size);
bool Load(sf::Font* Object, sf::String Filename);
bool Load(sf::Image* Object, sf::String Filename);
bool Load(sf::SoundBuffer* Object, sf::String Filename);

public:
PhysFSLoader();
~PhysFSLoader();
};

}

#endif //_H_SFML_PHYSFS_LOADER_


PhysFSLoader.cpp
Code: [Select]

#include <PhysFSLoader.hpp>

namespace sf
{
// - Shared loading routine -
bool PhysFSLoader::doLoad(sf::String Filename)
{
// - Check if PhysFS is initialised -
if(PHYSFS_isInit() == 0)
{
m_lastError = PFSL_Error_PhysFSNotReady;
return false;
}

// - Check if file exists -
if(! PHYSFS_exists(Filename.ToAnsiString().c_str()))
{
m_lastError = PFSL_Error_FileNotFound;
return false;
}

// - Attempt to open file -
PHYSFS_file* fileObj = PHYSFS_openRead(Filename.ToAnsiString().c_str());
if(fileObj == NULL)
{
m_lastError = PFSL_Error_InvalidFileHandle;
return false;
}

// - Check file size -
PHYSFS_sint64 fSize = PHYSFS_fileLength(fileObj);
if(fSize > m_maxFileSize)
{
m_lastError = PFSL_Error_FileTooBig;
return false;
}

// - Read data -
m_fileBuffer = new char [fSize];
PHYSFS_sint64 totalRead = PHYSFS_read(fileObj, m_fileBuffer, 1, fSize);
if(totalRead != fSize)
{
m_lastError = PFLS_Error_NotEnoughRead;
delete m_fileBuffer;
m_fileBuffer = NULL;
return false;
}
return true;
}

// - Return Last Error -
PFSL_Error PhysFSLoader::GetLastError()
{
return m_lastError;
}

// - Set Filesize Limit -
void PhysFSLoader::SetMaxFileSize(PHYSFS_sint64 Size)
{
m_maxFileSize = Size;
}

// - Load Font -
bool PhysFSLoader::Load(sf::Font* Object, sf::String Filename)
{
m_lastError = PFSL_Error_None;
if(doLoad(Filename))
{
if(Object->LoadFromMemory(m_fileBuffer, m_fileSize))
{
delete m_fileBuffer;
m_fileBuffer = NULL;
return true;
}
delete m_fileBuffer;
m_fileBuffer = NULL;
m_lastError = PFSL_Error_LoadFailed;
}
return false;
}

// - Load Image -
bool PhysFSLoader::Load(sf::Image* Object, sf::String Filename)
{
m_lastError = PFSL_Error_None;
if(doLoad(Filename))
{
if(Object->LoadFromMemory(m_fileBuffer, m_fileSize))
{
delete m_fileBuffer;
m_fileBuffer = NULL;
return true;
}
delete m_fileBuffer;
m_fileBuffer = NULL;
m_lastError = PFSL_Error_LoadFailed;
}
return false;
}

// - Load Sound Buffer -
bool PhysFSLoader::Load(sf::SoundBuffer* Object, sf::String Filename)
{
m_lastError = PFSL_Error_None;
if(doLoad(Filename))
{
if(Object->LoadFromMemory(m_fileBuffer, m_fileSize))
{
delete m_fileBuffer;
m_fileBuffer = NULL;
return true;
}
delete m_fileBuffer;
m_fileBuffer = NULL;
m_lastError = PFSL_Error_LoadFailed;
}
return false;
}

// - Constructor -
PhysFSLoader::PhysFSLoader()
{
m_fileBuffer = NULL;
m_lastError = PFSL_Error_None;
m_maxFileSize = 4194304; // 4 MB Limit
}

// - Deconstructor -
PhysFSLoader::~PhysFSLoader()
{
if(m_fileBuffer)
{
delete m_fileBuffer;
m_fileBuffer = NULL;
}
}
}


Usage
Code: [Select]

#include <physfs.h>
#include <physFSLoader.hpp>

#include <SFML\Graphics.hpp>

void main()
{
PHYSFS_init(NULL);

PHYSFS_addToSearchPath("test.zip", 1);

sf::PhysFSLoader Loader;

sf::Image MyImage;

Loader.Load(&MyImage, "test.jpg");
}
Regards,

 Mike

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
[CPP Source] - Load Assets using PhysicsFS
« Reply #1 on: July 21, 2011, 03:00:48 am »
You know... I actually helped design sf::InputStream for just this kind of thing.

Using it, you wouldn't have to dump the whole file to memory before loading it.  You could just load it normally.

What's more, you wouldn't have to write separate loaders for images/sounds/fonts/whatever.

See this thread:

http://www.sfml-dev.org/forum/viewtopic.php?t=5007

Mikey

  • Newbie
  • *
  • Posts: 10
    • MSN Messenger - mrking2910@googlemail.com
    • View Profile
[CPP Source] - Load Assets using PhysicsFS
« Reply #2 on: July 21, 2011, 08:00:46 am »
As stated on the first post, It's just a quick dirty method lol.. I haven't delved that deep in the documentation of SFML as of yet to provide the most efficient way of doing it.

 But thanks for the link, I'll have a dig about and see about updating the method thoroughly when I have the time available :)
Regards,

 Mike

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
[CPP Source] - Load Assets using PhysicsFS
« Reply #3 on: July 21, 2011, 04:33:14 pm »
Some other things I notice:

- you're using new[], but you're cleaning up with delete.  You should be cleaning up with delete[].  You probably are leaking massive memory as a result.

Remember:
new -> delete
new[] -> delete[]

Don't mix-and-match

- I don't think your font loader will work because I'm pretty sure the memory buffer has to stay available for the lifetime of the font (since it does continual seeks/reads and character data is needed).  In your case you're deleteing the buffer right away which will cause sf::Font to read from a bad pointer.

Mikey

  • Newbie
  • *
  • Posts: 10
    • MSN Messenger - mrking2910@googlemail.com
    • View Profile
[CPP Source] - Load Assets using PhysicsFS
« Reply #4 on: July 22, 2011, 01:06:35 pm »
Yeah, got some right noobish mistakes there huh? lol.


 Lesson to be learnt.. Don't put fingers to keyboard before first cup of morning coffee has taken effect.
Regards,

 Mike