Bonjour,
j'essaye de precharger des textures en memoire, pour un chargement plus dynamique.
Voici ma classe qui va garder tout en memoire...
class Memory
{
public:
Memory() {};
~Memory()
{
std::cout << "Call ~Memory() " << std::endl;
}
/// Pas important.
void preload(const std::string& pack)
{
Reader* own_reader = new Reader();
Node* child = own_reader->Read(pack);
m_nodes.insert(std::make_pair(Filesystem::extractFilename(pack),
std::make_pair(own_reader, child)));
}
/// Ceci, marche a merveille ! Aucune exception levée
void loadGFX(const std::string& pack, const long id)
{
try
{
Node& node(m_nodes[pack].second->find(id));
MemoryRessource<sf::Texture>* res = new MemoryRessource<sf::Texture>(node.get(m_nodes[pack].first->stream()));
m_loaded_gfx.insert(std::make_pair(MemoryKey(node.getId(), node.getOffset()), res));
}
catch(...)
{
throw false;
}
}
Node& operator [] (const std::string& key) { return *(m_nodes[key].second); }
Node& operator [] (const char* key) { return *(m_nodes[std::string(key)].second); }
inline bool isLoaded(const MemoryKey& key) { return m_loaded_gfx.find(key) != m_loaded_gfx.end(); }
template<class S>
static inline S& getGFX(const long id) /// longer to perform ...!
{
std::for_each(std::begin(m_loaded_gfx), std::end(m_loaded_gfx), [&](std::pair<MemoryKey, MemoryRessource<sf::Texture>*> res)
{
if(res.first.first == id) { return res.second->get(); }
});
}
/// Retournera un sf::Texture
template<class S>
static inline S& getGFX(const MemoryKey& key)
{
return m_loaded_gfx[key]->get();
}
private:
static std::map<std::string, std::pair<Reader*, Node*>> m_nodes;
static std::map<MemoryKey, MemoryRessource<sf::Texture>*> m_loaded_gfx;
};
En premier, je fais un void preload(), pas important, cela va remplir le membre m_nodes.
Ensuite, je vais faire loadGFX() avec un identifiant. Cela va charger une sf::Texture dans m_loaded_gfx.
Voici la classe MemoryRessource:
template<class S>
class MemoryRessource
{
public:
MemoryRessource() {}
MemoryRessource(const std::vector<char>& bytes) :
m_buffer()
{
if(!m_buffer.loadFromMemory(&bytes[0], bytes.size()))
{
std::cout << "Failed to load from memory ! " << std::endl;
throw false;
}
else
{
std::cout << "Loaded " << bytes.size() << std::endl;
}
}
~MemoryRessource()
{
std::cout << "Destroying !"<<std::endl;
}
inline const S& get() const { return m_buffer; }
private:
S m_buffer;
};
On remarquera que si le loadFromMemory est mauvais, une exception est levée, et attrapée dans loadGFX.
Jusqu'ici , tout va bien.
Voici maintenant le main :
short SplashScreen::Run()
{
/// Preloading archives
std::for_each(std::begin(Config::ARCHIVES), std::end(Config::ARCHIVES), [&](const std::string& pack)
{
std::string full_name = pack;
full_name += Config::EXT;
m_game.getMemory().preload(full_name); // Tout va bien ...
});
Memory mem;
Node& gfx(mem["Graphics"]);
std::vector<long> ids_to_load = {2, 5};
std::for_each(std::begin(ids_to_load), std::end(ids_to_load), [&](long id)
{
try
{
mem.loadGFX("Graphics", id);
}
catch(...)
{
std::cout << "Could not load: " << "Graphics:" << id << std::endl;
}
});
/// Aucune exception levée, nous avons donc nos sf::Texture chargés en mémoire
std::cout << "loading texture into sprite ......."<<std::endl;
sf::Sprite s_sprite(mem.getGFX<sf::Texture>(static_cast<long>(2)));
std::cout << "OK loaded"<<std::endl;
/// Rendering loop
while(m_game.getRenderer().getApp().isOpen() && m_game.isRunning())
{
/// Clearing the window
m_game.getRenderer().getApp().clear();
sf::Event event;
while(m_game.getRenderer().getApp().pollEvent(event))
{
/// Event handling
/// SFML
if(event.type == sf::Event::Closed)
{
/// This will automatically terminate the networker thread & nicely exit the game
m_game.crash();
}
}
/// Drawings (SFML)
/// The sprite (background)
m_game.getRenderer().getApp().draw(s_sprite);
/// Displayings
m_game.getRenderer().getApp().display();
}
return -1;
}
Bref, aucune erreur d'affichée malgrès les nombreuses conditions et try{}, pourtant: écran blanc :|
Une idée quelqu'un ?
Merci d'avance, nico
il y a également l'inférence de type et les range-based for qui pourrait simplifier le code, si je ne me trompe pas :
for (auto& pack : Config::ARCHIVES)
{
//[...]
}
Petit changement.... Maintenant j'ai un écran noir :/
Voici, la boucle principale:
short SplashScreen::Run()
{
sf::Sprite splash_screen;
bool connect_attempt = false, splash_load = false;
/// Running loading thread
m_game.runPreloader();
/// Rendering loop
while(m_game.getRenderer().getApp().isOpen() && m_game.isRunning())
{
/// Clearing the window
m_game.getRenderer().getApp().clear();
sf::Event event;
while(m_game.getRenderer().getApp().pollEvent(event))
{
/// Event handling
/// SFGUI
m_desktop.HandleEvent(event);
/// SFML
if(event.type == sf::Event::Closed)
{
/// This will automatically terminate the networker thread & nicely exit the game
m_game.crash();
}
}
if(!splash_load)
{
try
{
Memory& memory(m_game.getMemory());
splash_screen.setTexture(memory.getTexture(static_cast<long>(5)));
splash_load = true;
std::cout << "Set Texture!"<<std::endl;
}
catch(bool)
{
std::cout << "Failed to set texture"<<std::endl;
}
}
/// Drawings (SFML)
/// The sprite (background)
if(splash_load)
{
m_game.getRenderer().getApp().draw(splash_screen);
}
m_game.getRenderer().getApp().resetGLStates();
/// Displayings
m_desktop.Update(0.f);
m_game.getRenderer().display(m_game.getRenderer().getApp());
m_game.getRenderer().getApp().display();
}
return -1;
}
La fonction m_game.runPreloader(); va precharger les images dans l'instance de m_game.getMemory().
Ensuite, voici le header de la classe Memory:
typedef std::pair<long, long> MemoryKey;
// ID, Offset
template<class S>
class MemoryRessource
{
public:
MemoryRessource() {}
MemoryRessource(const std::vector<char>& bytes) :
m_buffer()
{
if(!m_buffer.loadFromMemory(&bytes[0], bytes.size()))
{
std::cout << "Failed to load from memory ! " << std::endl;
throw false;
}
else
{
std::cout << "loadFromMemory: OK. @ address: " << &m_buffer << std::endl;
}
}
~MemoryRessource()
{
std::cout << "Destroying !"<<std::endl;
}
inline S& get() {
std::cout << "Get texture (width=" << m_buffer.getSize().x << "; height=" << m_buffer.getSize().y << ")" << std::endl;
return m_buffer;
}
private:
S m_buffer;
};
class Memory
{
public:
Memory() :
m_nodes(),
m_loaded_gfx(),
m_mtx_loader(PTHREAD_MUTEX_INITIALIZER),
m_percent(0)
{}
~Memory()
{
std::cout << "Call ~Memory() " << std::endl;
}
void loadPackage(const std::string& pack)
{
Reader* own_reader = new Reader();
Node* child = own_reader->Read(pack);
m_nodes.insert(std::make_pair(Filesystem::extractFilename(pack),
std::make_pair(own_reader, child)));
}
void loadGraphic(const long id)
{
try
{
Node& node(m_nodes[m_graphicPackage].second->find(id));
MemoryRessource<sf::Texture>* res = new MemoryRessource<sf::Texture>(node.get(m_nodes[m_graphicPackage].first->stream()));
m_loaded_gfx.insert(std::make_pair(MemoryKey(node.getId(), node.getOffset()), res));
}
catch(bool)
{
throw false;
}
}
Node& operator[] (const std::string& key) { return *(m_nodes[key].second); }
inline sf::Texture& getTexture(const MemoryKey& key) { return m_loaded_gfx[key]->get(); }
inline sf::Texture& getTexture(const long key)
{
for(auto& res : m_loaded_gfx)
{
if(res.first.first == key)
{
return res.second->get();
}
}
/// In case we didn't found id... !
throw false;
}
inline bool isLoaded(const MemoryKey& key) { return m_loaded_gfx.find(key) != m_loaded_gfx.end(); }
inline pthread_mutex_t* getMutex() { return &m_mtx_loader; }
inline long& getPercent() { return m_percent; }
private:
std::map<std::string, std::pair<Reader*, Node*>> m_nodes;
std::map<MemoryKey, MemoryRessource<sf::Texture>*> m_loaded_gfx;
pthread_mutex_t m_mtx_loader;
long m_percent;
const std::string m_graphicPackage = "Graphics";
};
Le chargement se passe bien.
En tout cas, voici le debug...:
(http://img11.imageshack.us/img11/6849/bugecrannoir.png)
Le truc vraiment etrange, c'est que c'est la meme adresse apres chargement, et quand je tente d'y acceder.
De plus, la taille affichée sur la console est la bonne.
Une idée d'où vient le probleme ?
merci, nico