A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Oui en réfléchissant je pourrai éviter le singleton facilement, en rendant les attibuts du singleton statique pour que tout se remette bien à jour pour toutes les instances d'un même type de gestionnaire de ressources, en laissant la classe non copiable, est le problème est réglé, bref, je vais faire ça.
Je pense que std::recursive_mutex fait cela... (En tout cas je ne peux pas créer deux instances de cette classe et pourtant elle n'a pas l'apparence d'un singleton)
Tu n'as aucun besoin de rendre tes données statiques si le but est qu'elles se remettent bien à jour!!!
Le but du mot clé static est uniquement de faire en sorte que l'instance de la donnée soit unique dans une unité de compilation donnée... Ici, l'unicité de la donnée (non seulement au niveau d'une unité de compilation, mais aussi au niveau de l'application toute entière) s'obtient simplement en veillant à ne créer effectivement qu'une seule instance de la donnée en question... Et il n'y a rien de magique ni aucune nécessité de rendre une donnée magique pour atteindre ce but
Si tu veux faire en sorte que les modifications apportée par une fonction soient répercutées sur une données qui n'appartient pas à la fonction, tu la passe par référence, et basta![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Mais, rendre la classe non copiable n'empêche pas de pouvoir créer plusieurs instances de celle-ci, si ?
Donc si je fais une variable non statique je devrait la mettre à jour dans nc1 et nc2 si je supprime un id dans l'un des deux gestionnaires de ressource de la même famille.
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 NonCopiable nc1; NonCopiable nc2;
A moins de faire, une factory (plutôt qu'un singleton), qui se charge de vérifier si, l'instance n'est pas déjà créée.
Mais un singleton est fort similaire à une factory (je trouver) car il renvoie une référence sur l'unique objet crée.
Le pattern factory il me semble sert plutôt à cloner pour éviter un slicing.
Non, en effet, rendre ta classe non copiable n'empêchera qu'une seule et unique chose : la création d'une copie non voulue ...
Donc si je fais une variable non statique je devrait la mettre à jour dans nc1 et nc2 si je supprime un id dans l'un des deux gestionnaires de ressource de la même famille.
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 NonCopiable nc1; NonCopiable nc2;
A moins de faire, une factory (plutôt qu'un singleton), qui se charge de vérifier si, l'instance n'est pas déjà créée.
Mais un singleton est fort similaire à une factory (je trouver) car il renvoie une référence sur l'unique objet crée.
Le pattern factory il me semble sert plutôt à cloner pour éviter un slicing.[/QUOTE]C'est pourquoi tu dois veiller à ne créer qu'une instance de la classe qui t'intéresse dans la classe qui concerne le contexte dans lequel elle doit être utilisée.
Ton application / ta bibliothèque n'est qu'un grand jeu de poupées russes... Tu as le contexte qui correspond à l'application qui va créer une (et une seule ! ) instance de chaque classe qui correspond à d'autres contextes comme les données métier, les vues graphiques, la gestion des sons ou de la communication réseau et, chacun de ces contextes spécifique créera une instance (unique !) des classes qui ont pour but de maintenir les données propres à ces différents contextes.
Au final, comme tu n'as qu'une seule instance de l'application, tu n'as qu'une seule instance des différents contextes qu'elle utilise et... une seule instance des classes qui s'occupent du maintien "en vie" de tes ressources. Autrement dit, l'unicité des instances est garantie par la manière dont ton application / ta bibliothèque est construite elle-même![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Ok, je vois mieux comment je dois faire là.
Je possède en effet une classe application, je pourrai donc créer les objets unique à partir de cette classe. (Et au pire utiliser l'amitier pour empêcher la création ailleurs)
Au départ je voulais en fait éviter de devoir dépendre d'un contexte pour pouvoir instancier des classes (et donc pouvoir créer les objets unique en dehors de la classe Application au cas ou le développeur ne voudrais pas dépendre d'un contexte)
Mais c'était peut être une mauvais idée...
Toutefois je peux modifier le gestionnaire de ressource facilement pour me passer du singleton, et faire une variable statique dans cette classe pour que tout les objets partagent les mêmes ressources.
Je pense que c'est ce qui serait le mieux.
A vrai dire, je te le déconseille...
Bien sur, cela te permettrait de placer le constructeur dans l'accessibilité privée et t'assurer que ton objet ne sera construit que par une classe bien précise, mais, d'un autre coté, cela va plus ou moins à l'encontre du DIP (Dependancies Inversion Principe) qui nous dit que tout devrait dépendre d'interface et non d'élément de plus ou moins haut niveau. Or, en déclarant une classe amie, tu place malgré tout une dépendance aussi bien de la classe amie vers la classe qui déclare cette amitié que l'inverse.
Alors, bien sur, on peut assouplir ce principe en se disant que cela doit, en tout état de cause, être vrai pour les communications "inter-modules" mais qu'il n'est pas particulièrement important de le respecter à l'intérieur d'un module donné. Ce n'est pas faux dans le sens où tu pourrais déclarer la classe qui s'occupe du contexte sonore comme amie de la classe qui s'occupe de maintenir les ressources sonores et sans doute faire pareil avec les différents modules.
Par contre, si tu décide de rendre ta classe Application amie des classes correspondant aux différents contextes, tu est "hors module", et là, cela devient dangereux![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Ouf, ce système de context me semble pas si simple à mettre en place, ça me fait pensé à opengl ou il faut partager un contexte entre plusieurs thread, le partager, changer les états, etc..., de plus les contextes ne peuvent être actif que dans un seul thread à la fois, mais au départ je voulais que les gestionnaires de ressources puisse être accessible par tout les modules, et pas seulement, par le contexte graphique..., ceci est plus dangereux certes car il faut que, quand un gestionnaire de ressource n'est plus utilisé il faut qu'il soit encore accessible par tout les autres modules, mais,ça devient moins dangereux je trouve avec des pointeurs intelligent, qui, eux, partagent les ressources entre les différents module en s'assurant que les ressources soient détruite au bon moment. (C'est à dire quand elles ne sont plus référencées null part)
Bref ce système de contexte c'est de l'histoire ancienne pour moi, les nouvelles version de opengl n'utilisent plus ça et je pense que cette mode va avoir tendance à disparaître au profit de techniques plus récentes. (A cause de la programmation parallèle)
En fait, plutôt que de parler de contexte, je devrais plutôt parler de "modules", dans le sens où c'est ce pour quoi je milite... Et le principal objectif à atteindre est d'en arriver à avoir des modules les plus indépendants possibles les uns des autres : Le module son n'a absolument rien à voir avec le module "réseau" qui n'a lui-même absolument pas besoin de connaitre les ressources utilisées par le module "affichage / vue".
Une fois que tu as compris cela, tu te rend compte que ces instances que tu veux rendre globales -- afin de les rendre disponibles entre les différents modules -- n'ont absolument aucune raison d'être pour la simple et bonne raison... qu'il n'y a aucune instance d'aucune classe qui doit réellement traverser la frontière des différents modules.
La seule exception notable, c'est le module regroupant les données métier qui reste, malgré tout, le module central autour duquel gravitent tous les autres modules. Et encore : tu ne devras jamais transmettre une instance d'une classe ayant sémantique d'entité issue de ton module business en entier vers un autre module, quel qu'il soit. Au pire, tu transmettra un identifiant spécifique et quelques données connexes qui pourraient parfaitement n'être que des types primitifs ou des données équivalentes (une position, si tu y tiens, une chaine de caractères dans le pire des cas, ...)
Et, une fois que ces différents modules sont capables de fonctionner tout seuls, il "n'y a plus qu'à" mettre certains contrôleurs en places qui permettront à tous tes modules de communiquer ensemble (ex : le fait que le lancé d'un sort occasionne l'émission d'un son déterminé ou le fait qu'un message reçu au travers du module réseau occasionne le déplacement d'un pnj au niveau du business et que ce déplacement se répercute sur la position à laquelle ce pnj est affiché au niveau de l'affichage).
Quoi qu'il en soit, la règle est toujours la même : diviser pour mieux régner et limiter les informations qui sont transmises entre les modules au minimum strictement indispensable pour que cela fonctionne![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Oui sauf que ici le gestionnaire de ressource, ne dépend pas d'un module, de plus je n'initialise pas les ressources et les utilise au même endroit, en fait, je charge toutes les textures, sons, etc... dans une méthode load, je crée les objets dans une méthode init en leur passant les ressources que je récupère avec un alias que je passe au gestionnaire de ressource et ensuite, et je les utilisent dans un autre module, donc je me retrouve avec un module de chargement, un module d'initialisation et un module d'affichage.
Et le développeur peut charger et utiliser les ressources là ou il le veut, mais, j'ai toujours besoin d'avoir accès aux gestionnaire de ressource pour l'utiliser dans les différents modules.
De plus toutes mes classes sont template, et on peut très bien enregistrer plusieurs gestionnaire de ressource dans un cache, pour ensuite le réutiliser plus tard et le cache peut aussi lui être de différent type si les ressources peuvent être chargée avec une classe dérivée et utilisée avec une classe de base. (Le cache va alors convertir les pointeurs des gestionnaires de ressources dérivés et celui de base)
Donc bon, comme j'essaye de te le dire depuis quelques posts déjà, je ne peux pas faire comme ça, vu que je veux séparer le chargement et l'utilisation dans plusieurs modules.
Mon code ressemble à quelque chose comme ceci.
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 void CustomAppli::onLoad() { //Charge toutes les ressources du jeux. (images, sons, modèles 3D, etc...) TextureManager& tm = TextureManager::Instance(); tm.fromFileWithAlias("path", "texture1"); etc... } void CustomAppli::onInit() { //Intialise tout les objets du jeux, les commandes ainsi que les entity systèmes qui stockeront et mettrons à jour les entitiés du jeux TextureManager& tm = TextureManager::Instance(); Entity entity = Tile(tm.getResourceByAlias("texture1"), Vec3f(0, 0, 0,), Vec3f(100, 100, 0), IntRect(0, 0, 100, 100)); etc... Engine::addEntity(entity); } void CustomAppli::onRender(RenderComponent* rc) { //Dessine les objets sur les composant de rendu, la string correspond à un groupe d'objets et on peut dessiner les objets sur plusieurs composants différents, on peut aussi passer des shaders. rc->drawOnComponent("E_TILE"); } void CustomAppli::onDisplay(RenderWindow* window) { //Affiche des guis, overlay, etc... sur la fenêtre. (Au dessus des composants de rendu, à ce stade tout les objets de la frame courante du jeux son affiché) } void CustomAppli::onUpdate(Event event) { //Met à jour les objets du jeux. } void CustomAppli::onExec() { //Effectue d'autre traitement en fin de boucle comme par exemple, recevoir des messages réseau. }
Bref ceci me permet d'avoir toute la boucle principale du jeux dans une seule classe, et tout ce qui est définitions des entités dans d'autre classes, et de pouvoir interagir plus facilement entre la boucle principale et les différents objets du jeux.
Pour réduire le code j'ai aussi fait un système qui permet de sérialiser les objets avant de les transférer d'un programme à l'autre lors des envois réseaux.
Bref, je peut donc tenir tous les modules dans une seule classe sans devoir passer par une classe pour le rendu qui charge puis qui utilise les ressources, une autre qui effectue les mises à jours, etc..., ce que je trouve quand même être assez lourd. (Enfin, tout du moins, dans les autres moteurs de jeux, je ne m'en sortait pas bien avec leur système.)
Je trouve que lors de l'utilisation, pouvoir utiliser tout les modules dans une seule classes sans devoir passer des objets ou ce genre de choses est beaucoup plus simple, plus intuitif, si je dois commencer à faire des choses du genre, on doit dériver de tel classe (ou de tel module) pour pouvoir charger les textures et les rendre, cela va vite devenir plus compliqué à l'utilisation, plutôt que d'avoir une variable globale, et de l'utiliser dans diverses méthodes.
Cela ne m'a jamais posé de problème jusqu'à présent même dans un context multi-thread, d'ailleurs ici j'utilise plusieurs threads (un pour mettre à jour, un pour gérer les événements et un pour afficher et il est possible que plus tard j'en utilise encore d'autres)
Dernière modification par Invité ; 15/10/2014 à 11h42.
Et pourquoi ne créerais tu donc pas une fonction membre load dans la classe qui te sert de "façade" à tes différents modules
Tu crées une fonction load qui charge les objets et les textures dans la facade de ton module... d'affichage et une autre fonction load qui charge les sons dans la facade de ton... module son, et basta !!!
Tu ne dois pas avoir de fonction init!!!je crée les objets dans une méthode init
Mettons que tu utilises OpenGl pour l'affichage. Tu crées une classe nommée FacadeAffichage, AffichageContext ou ce que tu veux dont le constructeur s'assure de créer un contexte OpenGL valide et dont le destructeur s'occupe d'en faire le ménage. Tu y ajoutes une instance de ton gestionnaire d'objets opengl et une instance de ton gestionnaire de textures sous une forme proche deEt tu crées une classe Application qui prend une forme proche de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 class GlContext{ public: GlContext(int argc, char ** argv, std::string const & title); ~GlContext(); void loadObect(/* ... */); void loadTexture(/* ... */); void draw(); // trace tous les objets void draw(UnType id,/* ... */); //trace uniquement l'objet id avec les paramètres nécessaires private: ObjectManager objects_; TextureManager textures_; }; GlContext::GlContext(int argc, char ** argv, std::string const & title){ glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); glutInitWindowPosition(200,200); glutInitWindowSize(640,480); glutCreateWindow(title.c_str()); /* initialisation des librairies liées à OpenGL */ GLenum err = glewInit(); if (err != GLEW_OK) { std::string msg("Anomalie aVec Glew, impossible d'utiliser OpenGL : "); msg.append((char*)glewGetErrorString(err)); throw std::runtime_error(msg); } // Initialisation de SDL_Image int ok = IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG); if (!ok) { throw std::runtime_error("Anomalie aVec SDL_image : impossible de charger une texture"); } // couleur du fond : gris foncé glClearColor(0.4, 0.4, 0.4, 1.0); /// met l'horloge à jour beginTime_ =mktime(&startTime_); } GlContext::~GlContext(){ // terminaison de SDL_Image IMG_Quit(); }
Bien sur, tu fais pareil pour les différents modules (son, réseau, whatever).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 class Application{ public: Application(int argc, char ** argv, std::string const & title): contextGl_(arc,argv,title){ loadGlContext(); } void run(); private: void loadGlContext(){ glContext_.loadObject(/* ... */); /* ... */; glContext_.loadTexture(/* ... */); /* ... */ } GlContext contxtGL_; /* ... */ };
Cela te permet d'avoir une fonction main réellement dépouillée prenant la forme de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 int main(int argc, char ** argv){ Application app(arc, argv, "le titre sympa"); // toute l'initialisation se fait ici app.run(); // l'application s'exécute return 0; // ~Application est appelé ici, le ménage est fait, bonsoir et merci!!! }Pourquoi vouloir transmettre des ressources entre les modulesen leur passant les ressources que je récupère avec un alias que je passe au gestionnaire de ressource et ensuite, et je les utilisent dans un autre module, donc je me retrouve avec un module de chargement, un module d'initialisation et un module d'affichage.Chaque module a besoin de ressources qui leur sont propres que diable!!!! Un module son n'a aucun besoin d'avoir une texture, un module d'affichage n'a aucun besoin de disposer d'un flux récupéré du résau et un module réseau n'a aucun besoin de disposer d'un son b...del de m...de!!!
Tu devras sans doute prévoir un moyen d'identifier les différentes ressources, afin de permettre une communication correcte, mais cela ne va pas plus loin !!!
Non!!!Et le développeur peut charger et utiliser les ressources là ou il le veut, mais, j'ai toujours besoin d'avoir accès aux gestionnaire de ressource pour l'utiliser dans les différents modules.
Si l'utilisateur veut charger une ressource nécessaire au module d'affichage, il doit le faire dans le contexte qui englobe le contexte d'affichage (autrement dit, dans l'application), mais il ne peut le faire qu'au travers du module d'affichage!!!! idem pour n'importe quel autre module!!!!
Rien ne t'empêche de templatiser tes classes... Un gestionnaire de XXX va très certainement se comporter de la même manière qu'un gestionnaire de YYY... Mais cela n'empêche que le gestionnaire de XXX doit se trouver dans une classe qui sert de facade au module qui en a réellement besoin, nulle part ailleurs!!!De plus toutes mes classes sont template, et on peut très bien enregistrer plusieurs gestionnaire de ressource dans un cache, pour ensuite le réutiliser plus tard et le cache peut aussi lui être de différent type si les ressources peuvent être chargée avec une classe dérivée et utilisée avec une classe de base. (Le cache va alors convertir les pointeurs des gestionnaires de ressources dérivés et celui de base)
C'est, justement, la raison pour laquelle la gestion des ressources utilisées par un module spécifique doit être déléguée spécifiquement à ce module particulierDonc bon, comme j'essaye de te le dire depuis quelques posts déjà, je ne peux pas faire comme ça, vu que je veux séparer le chargement et l'utilisation dans plusieurs modules.
Et moi, je te dis qu'il n'y a aucun besoin d'avoir un singleton (ou un monostate), je te dis que, tu n'as besoin que d'une chose : inciter l'utilisateur a créer une instance de la facade des différents modules dont il a besoin, et utiliser les fonctions de cette facade.Mon code ressemble à quelque chose comme ceci.
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 void CustomAppli::onLoad() { //Charge toutes les ressources du jeux. (images, sons, modèles 3D, etc...) TextureManager& tm = TextureManager::Instance(); tm.fromFileWithAlias("path", "texture1"); etc... } void CustomAppli::onInit() { //Intialise tout les objets du jeux, les commandes ainsi que les entity systèmes qui stockeront et mettrons à jour les entitiés du jeux TextureManager& tm = TextureManager::Instance(); Entity entity = Tile(tm.getResourceByAlias("texture1"), Vec3f(0, 0, 0,), Vec3f(100, 100, 0), IntRect(0, 0, 100, 100)); etc... Engine::addEntity(entity); } void CustomAppli::onRender(RenderComponent* rc) { //Dessine les objets sur les composant de rendu, la string correspond à un groupe d'objets et on peut dessiner les objets sur plusieurs composants différents, on peut aussi passer des shaders. rc->drawOnComponent("E_TILE"); } void CustomAppli::onDisplay(RenderWindow* window) { //Affiche des guis, overlay, etc... sur la fenêtre. (Au dessus des composants de rendu, à ce stade tout les objets de la frame courante du jeux son affiché) } void CustomAppli::onUpdate(Event event) { //Met à jour les objets du jeux. } void CustomAppli::onExec() { //Effectue d'autre traitement en fin de boucle comme par exemple, recevoir des messages réseau. }
Tu remarquera que l'exemple que je viens de te donner est finalement très similaire à celui que tu me propose... Si ce n'est que je n'utilise pas de singleton ni de monostate : je m'assure que les gestionnaires de ressources soient simplement créé (et détruits) en meme temps que contexte / modules qui les utilise
Et la manière dont je te présente les choses le fait aussi... Tout ce qu'il y a à faire, c'est d'invoquer la fonction run et d'en adapter le comportement à l'application créée.Bref ceci me permet d'avoir toute la boucle principale du jeux dans une seule classe, et tout ce qui est définitions des entités dans d'autre classes, et de pouvoir interagir plus facilement entre la boucle principale et les différents objets du jeux.
Alors, bien sur, il faut envisager la transmission de messages entre certains modules, mais ce n'est jamais qu'un système signal /slot à mettre en place (boost::signals2 est l'idéal pour cela)
Oui, et alors ?Pour réduire le code j'ai aussi fait un système qui permet de sérialiser les objets avant de les transférer d'un programme à l'autre lors des envois réseaux.
Bien sur qu'il faut une classe qui fournit l'accès à toutes les fonctionnalités exposées à l'utilisateur, bien sur qu'il faut pouvoir créer une instance de cette classe, mais le singleton n'est pas le passage obligéBref, je peut donc tenir tous les modules dans une seule classe sans devoir passer par une classe pour le rendu qui charge puis qui utilise les ressources, une autre qui effectue les mises à jours, etc..., ce que je trouve quand même être assez lourd. (Enfin, tout du moins, dans les autres moteurs de jeux, je ne m'en sortait pas bien avec leur système.)Il ne s'agit pas de cela, bien au contraire!!!Je trouve que lors de l'utilisation, pouvoir utiliser tout les modules dans une seule classes sans devoir passer des objets ou ce genre de choses est beaucoup plus simple, plus intuitif, si je dois commencer à faire des choses du genre, on doit dériver de tel classe (ou de tel module) pour pouvoir charger les textures et les rendre, cela va vite devenir plus compliqué à l'utilisation, plutôt que d'avoir une variable globale, et de l'utiliser dans diverses méthodes.
Au sein du module, il n'est pas impossible que tu doive, effectivement, envisager de transmettre une référence sur le gestionnaire de ressource utilisé par le module. Mais l'utilisateur du module n'a, à la limite, même pas besoin de savoir qu'il y a un gestionnaire de ressource qui entre en jeu!!! Tout ce qu'il doit savoir, c'est comment charger une ressource et comment indiquer quelle ressource spéciique doit être utilisée lorsque l'on veut spécifiquement utiliser le module sur une ressource particulière!
Et, lorsque tu décide apporter une modification quelconque, combien de fonction en moyenne dois tu modifier pour résoudre tous les problèmes occasionnés par l'évolution :quesiton:Cela ne m'a jamais posé de problème jusqu'à présent même dans un context multi-thread, d'ailleurs ici j'utilise plusieurs threads (un pour mettre à jour, un pour gérer les événements et un pour afficher et il est possible que plus tard j'en utilise encore d'autres)
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Ok bah je pense que je vais forcer l'utilisateur, à utiliser un context différent (pour le son, les textures, les shaders, etc...) et faire une seule méthode pour load et initialise, je note ça dans les améliorations à faire.
Après tout je n'ai qu'à faire deux chose : une classe context avec les différentes fonctions de chargements (que je vais passer template car il y aura possibilité de créer plusieurs contextes pour charger des ressources de type différents), et retiré le singleton.
Mais bon ça sera juste un contexte de chargement, après il faudra que je trouve un moyen de récupérer les ressources via le context mais je possède un système de signal et de slots pour ça.
Bon voila j'avais déjà fait cela avant en fait je me demande pourquoi j'ai changé.
En fait pour avoir un contexte graphique il suffit de dérivé de la classe Application et le contexte graphique se détruit à la destruction de l'application gui. (il y a deux constructeurs pour la classe application, un pour avoir un contexte graphique et un autre pour ne pas avoir de contexte graphique)
La classe ResourceCache qui ne fait rien d'autre que de contenir plusieurs contextes d'un même type. (ou bien les gestionnaires de ressources qui servent de contexte) cela dépendait de quel contexte j'avais besoin) je les déclarais dans la classe qui dérive de l'application gui ainsi seul cette classe à accès au contexte pour les ressources graphiques et les ressources étaient détruite en même temps que les gestionnaires de ressources ou le cache servant de contexte.
Bref, je vais repasser à se système là car en y réfléchissant c'est vrai que que en dehors de l'application gui, on a pas besoin d'accéder à des textures et de toute façon sans contexte graphique opengl on ne peux pas charger de textures. (Sinon elles ne s'affichent pas)
Partager