-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Primera versión del gestor de recursos. #58
base: master
Are you sure you want to change the base?
Conversation
Implementación de un TextureManager usando el template ResourceManager, como ejemplo. Modificada App para que cargue una textura a modo de ejemplo.
/** | ||
* @brief deinicializa el gestor de recursos. | ||
**/ | ||
void deinit() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yo pondría el nombre release
, dispose
o algo así, prefiriendo en este caso dispose
. deinit no lo había oído nunca, aunque he visto que existe por ahí. Pero dispose tiene un significado mucho más claro.
Que os parece hacer que el gestor de recursos vaya a una nueva rama develop hasta que esté completo? Creo que aún tiene bastante que madurar y cambiar porque va a ser parte importante del engine. |
|
||
private: | ||
|
||
std::map< std::string, T* > resources; /**< @brief Mapa que mapea strings a recursos. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Este comment debería ir en la línea de arriba ¿no?
Estoy de acuerdo con @adrigm dado que es algo que va para largo y creo que es clave para el proyecto. |
Al respecto, creo que estaría bien definir una convención concreta para nombrar a los métodos init / release, y aplicarlo siempre |
for( typename std::map< std::string, T* >::iterator it = resources.begin(); it != resources.end(); it++ ) | ||
{ | ||
deinitResource( (*it).second ); | ||
delete (*it).second; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creo que ya borras el recurso dentro de deinitResource
, ¿lo puedes confirmar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ni caso, me he equivocado con freeResource
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No,
Mi idea inicial es que todo lo referente allocatación y manejo de la memoria esté implementado en ResourceManager. Este, contiene dos funciones virtuales puras, initResource y deinitResource. initResource es la encargada de implementar como se carga el recurso en cuestión. deinitResource en principio esta por si antes de deallocatar la memória del recurso, hubiera que liberar algo mas relacionado a el, me explico?
Como puedes ver, ahora mismo se hace new y delete dentro del ResourceManager. Inicialmente, mi idea era simplemente reservar la memória, y dentro de initResource/deinitResource llamar a un placement new/delete. De esta manera, no estariamos atados a ningun paradigma de programación. En cambio, si el recurso necesita a la fuerza un parametro en su constructora, no compilaria. Lo veis muy liado?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Si no lo entiendo mal de/initResource son un (Template Method Pattern)[http://en.wikipedia.org/wiki/Template_method_pattern]
Me he bajado la rama a mi local y viéndolo en el editor ya me queda más claro.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Efectivamente, seria eso. También puede ser que los nombres escogidos no sean los mejores :)
Yo lo que intento con mi implementación, ahora mismo, és lo sigüiente:
- Aprovechar el máximo posible el código para ahorrar tiempo en implementaciones y posibles bugs
- Que la gestión de la memória recaiga absolutamente en el gestor. El objetivo, es que, en un futuro, si distintos tipos de recursos requieren distintas politicas de alocatación, estas se puedan definir con allocators.
- Intentar que sea lo mas flexible posible, es decir, que por un lado puedas usar recursos independientemente del paradigma de inicializacion usado (ya sea con constructor o con funciones si el recurso es POD), y por el otro, que no ate al usuario del motor a los recursos predefinidos en este. Si el usuario para su juego necesita un recurso no soportado por el motor, que pueda crear un gestor de recursos rapidamente a partir del que proporcionemo nosotros.
yo utilizo init y cleanup, es como está implementado en App y en el SceneManager. En señal de inicialización y tareas de limpieza. |
Pues propongo usar como convencion el formato init/cleanUp que usa @adrigm . Estaria bien actualizar la wiki. |
Acabo de actualizar la wiki con esa convención |
int size = this->resources.size(); | ||
for( typename std::map< std::string, T* >::iterator it = resources.begin(); it != resources.end(); it++ ) | ||
{ | ||
deinitResource( (*it).second ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aquí debería ser this->deinitResource()
Bueno, ahora según la convención que hemos discutido sería this->cleanUpResource()
pero me refiero a que hay bastantes llamadas a métodos internos que no están usando el this->
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, le hago una repasada.
@ArnauPrat, A mi lo que no me acaba de convencer es tener un objeto para cada tipo de recurso, es decir un textureManager, soundManager, ... No sería mejor algo integrado? |
Más que un ResourceManager en realidad es un Resource. Es decir, en mi opinión, habría que tener un Luego, para cada recurso que queramos añadir, simplemente hay que hacer una clase derivada de Resource para gestionar cómo debe gestionarse dicho recurso (cargar los datos, o hacer un release) El ResourceManager entonces sólo se encarga de gestionar, comprueba que un recurso no se carga dos veces, etc, pero no sabe nada de cómo cargarlo, ni siquiera sabe el tipo de dato que carga. Esta es la idea: Esto ya está casi así de hecho. |
Buenas, antes de nada, buen trabajo! Esta es la primera vez que comento y me gustaría hacer algunos apuntos en cuanto al API de esta clase. Creo que añadir el nombre Resource a cada método es algo redundante, puesto que la clase ya se llama ResourceManager podría omitirse y así acortar los nombres, en mi opinión ya se sobre entienden. Propongo esta interfaz: ResourceManager
public:
- init()
- cleanUp()
- get(string fileName);
- delete(string fileName);
protected:
- T* load(string fileName)
- void release(T* resource)
Un ejemplo: ResourceManager resourceManager = new ResourceManager();
resourceManager.init();
Resource *resource = resourceManager.get('Data/textures/bird.jpg')
...
resourceManager.delete('Data/textures/bird.jpg')
...
resourceManager.cleanUp(); |
@rickyah, tú método es lo que había pensado, pero como hacemos que se nos devuelva un recurso? Me explico: Tu tienes tu clase Abstracta Resource que heredan todos los tipos de recursos y que tendrá sus métodos virtuales puros Load, Cleanup, ... que cada recurso implementará convenientemente, hasta ahí bien. Ahora como gestionas el recurso pedido para que devuelva un recurso adecuado, no puedes tener un método Get genérico ya que cada recurso devolverá un tipo de dato distinto. |
Yo hago mi propuesta que era algo así: https://gist.github.com/adrigm/7405117 Es algo rudimentario, pero creo que es simple. Su utilización sería:
El AssetManager se encargaría internamente de comprobar si ya está cargada y devolver el puntero adecuado, o si no, cargarla y devolver el puntero. En caso de no poder cargarla podría devover una textura vacía por defecto impidiendo que falle el engine. |
Yo así lo veo perfecto @adrigm y pondría el path en el init. Por cierto los parámetros con el "the" delante entran en la guía de estilo? Es que he visto que por el ejemplo la clase Log no utiliza esta "convención" |
@titoneo, es de un antiguo proyecto mío en lo que lo usaba. Como veáis si lo metemos en la guía o lo descartamos para todas las clases. |
Podríamos include tener algo como addPath("...") para que el usuario añada varias carpetas donde quiere buscar recursos |
Con templates y castings se puede hacer bien, y es más extensible que la solución que propones. Estoy haciendo un POC |
@rickyah, en que sentido sería más extensible? |
Generas tu clase Resource que sepa como cargarlo, y ya puedes usarlo en el resource manager. Yo de todas maneras acabo mi idea y os la pongo por un gist, guste o no, se meta o no al final, algo aprenderé y así lo debatimos, que al final es de lo que va todo esto :) |
@rickyah Sí, esa es la pega de mi método que si se quieren añadir nuevos recursos hay que tocar el AssetManager. Veamos la que nos planteas tú! |
Puede que tarde un poco, que tengo c++, y sobre todo las templates oxidadas :( |
Aquí está el gist con mi prueba de concepto. Está hecho mal y pronto, pero es para mostraos qué os parece antes de irme a la cama |
Buenos dias,
Aun así, he de reconocer que no son diferencias cruciales/determinantes, así que si lo creeis conveniente, adelante. |
Mi opinión a tus consideraciones:
|
Gracias @rickyah , estoy de acuerdo con tus observaciones. |
Personalmente a mi, de las 3 propuestas que se han hecho, @adrigm @ArnauPrat y @rickyah la que más me convence es la de @rickyah puesto que creo que es la más sencilla y mas potente a la hora de extender su funcionalidad. La de @adrigm le veía fallos a la hora de tener que añadir un nuevo recurso, que habría que modificar la clase y añadir métodos y la propuesta de @ArnauPrat le veo el fallo de tener un manager por cada tipo de recurso |
@RdlP votas por la de @ArnauPrat o por la de @rickyah ? A mi de las 3 (incluida la mía) la que más me convence por ahora es la de @rickyah, claro está con los consecuentes ampliaciones para manejo de rutas y demás. |
Perdón, me he equivocado en el comentario, quería decir que la más simple y extensible me parece es la de @rickyah así que voto por ella. P.D Voy a modificar mi comentario anterior para expresarme bien. |
La versón de @rickyah es objetivamente la mejor teniendo en cuenta las necesidades actuales, así que optaria por ella. |
Esta noche iré mirando como mejorarlo, ya que como dije ese código esta hecho de cualquier manera y hay bastante que discutir, por ejemplo el hecho de que pidas un recurso con el tipo y te devuelva un puntero a ese tipo :P |
Si no lo he entendido mal, realmente ya estás devolviendo un puntero al recurso del tipo, GDE::ImageResource. Lo que pasa es que implementamos GDE::ImageResource usando sf::Texture, de ahi que tengamos que usar el getData, correcto? Si la implementación Texture fuera nuestra, el getData no haria falta, me equivoco? |
Me refiero a que haces Se podría discutir a ver qué es lo más claro. |
Sí, dado que los objetos SFML reciben referencias no punteros. Sería mejor devolver referencias a menos que se pida un puntero. |
Oído! |
@rickyah mejor aún! Que pensáis sobre los nombres de las funciones? No os parecen mejor sin la palabra resource en cada uno? Quiero decir, en la clase ResourceManager veo bien que se le añadan, por ejemplo: registerResource |
A mi me parece bien sin la palabra resource, pero entonces nombrar bien la variable de la instancia del manager: Así si 👍
Así no 👎
|
Yo usaría más la palabra Asset que Resource. Resource los usan los sistemas para otros menesteres como iconos de la aplicación, manifiests... Además que Asset es más corto que Resource que puede parecer tonto, pero es una consideración. En cuanto al uso reduandante de la palabra Asset/Resource estoy de acuerdo en que se puedo omitir. Yo usaria assetManager->get(); |
Mmm, yo preferiria que si diga Resource, creo que le da legibilidad al código, y que solo diga "get()", se me hace corto, :P además la mayoria de lo IDEs tienen autocompletado por lo que no se gana tiempo de tipeo digamos :P, |
A parte de que forma sea más clara, os diré que, a menos desde mi punto de vista, me interesa que se haga uso de templates y formas de diseño avanzadas para aprender. Usar clases de forma básica no es complicado, más bien es lo sencillo, lo realmente interesante y que cuesta es usar bien los templates y tener claras ciertas estructuras y su utilidad, por lo que veo muy interesante que cuando se haga el gestor de recursos, se explique por que de cada cosa y como funciona. Soys unos cracks! :) |
Ojo cuidao que los templates pueden ser un peligro, por un lado para entenderlos, que la metaprogramación con templates puede ser muy oscura. Y además pueden hacer subir el tiempo de compilación un huevo y la yema del otro. Pero puestos a enfangarnos podemos empezar por aquí: http://loki-lib.sourceforge.net/ |
Hay una muy buena página para lo básico de C++03, y está en español!, http://c.conclase.net/curso/index.php, tiene ejemplos sencillos de practicamente todo el lenguaje, manejor de excepciones, templates, herencia etc etc. |
Qué pasa con esto al final??, se va a mergear o no?? Así vamos creando el módulo que corresponde según la nueva organización y seguimos avanzando con el proyecto... que parece que está muriendo un poco... |
Mañana voy a poner al día un poco el proyecto y a organizarlo un poco mejor, no sé si @rickyah al final se ha puesto o no, si no lo ha hecho hay que ponerse ya para como bien dices avanzar. Necesitamos empezar a organizarnos mejor para que el proyecto no se pare cuando alguno no esté disponible como ha sido mi caso estas últimas semanas. |
Yo también he estado un poco ocupado pero ahora tengo vacaciones. Voy a mirar cómo hacer todo esto por que mi solución usa RTTI (dynamic_cast), y eso tampoco suele ser aceptable. |
@rickyah Qué es lo qué estás tratando de solucionar?? Así me lo pongo a ver también :P y de paso me voy metiendo un poco más en el código del ResourceManager |
A ver ni caso que no se ni donde vivo últimamente xD. Cosas que hay que hacer: implementar el gist partiendo de master con la nueva organización del fichero. Como no tengo nada hecho creare una rama en mi repo para ello y lo pondré aquí para que podáis mirarlo/clonarlo Cuando lo tenga hecho hago un PR y lo revisamos Lo que pasa que acabo de llegar hace 3 dias a mi tierra por vacaciones y claro, visitar a la familia por un lado, comilona por otro, chupito por otro lado y no da tiempo. Mañana empezaré a estar más liberado :) @adrigm en otro orden de cosas, como eres editor de genbetadev, mírate gameinstitute.com |
Implementación de un TextureManager usando el template ResourceManager, como ejemplo.
Modificada App para que cargue una textura a modo de ejemplo.