Resources Manager

Previous topic - Next topic

Dark Schneider

For those who like to have a centralized resources manager, use the Load, Unload, Get and Release functions of this ResourceManager so you will not have repeated resources or memory leaks (panic functions like Dispose or ReleasexxxAll  ;) ).

Be sure to use the correct one when loading an anim, because it really is a sprite, so you need to use the LoadAnim, but all later access are like a sprite.

Code (glbasic) Select

// --------------------------------- //
// TYPE ResourceManager
// --------------------------------- //
CONSTANT ResourceManagerVersionMajor%=1, ResourceManagerVersionMinor%=0, ResourceManagerVersionBuild%=0, ResourceManagerVersionRevision%=4

//! Resources Manager
//!
//! Author: Dark Schneider
//!
//! Centralized management of a resources pool

//-------------//
// --- API --- //
//-------------//
//
//! API summary
//! ---------------
//!
//! FUNCTION ResourceManagerDispose: -> clear all resources
//!
//! FUNCTION ResourceManagerLoadxxx: filename$ -> load an element, uses the complete filename$ as element.name$, including the path, important if using SETCURRENTDIR(); return its ID
//!
//! FUNCTION ResourceManagerUnloadxxxByxxx: -> decrement element counter, if 0 (not used by anything) then release it; return FALSE if element doesn't exists
//!
//! FUNCTION ResourceManagerReleasexxxByxxx: -> release the resource directly bypassing element counter; return FALSE if element doesn't exists
//!
//! FUNCTION ResourceManagerReleasexxxAll: -> release all the resources of that type (Sprites or Sounds)
//!
//! FUNCTION ResourceManagerGetxxxyyy: -> return element ID or name$, if doesn't exists it returns -1 or ""
//!
//! FUNCTION ResourceManagerGetxxxIDLoad: -> return element ID, if doesn't exists it loads it


//---------------------//
// --- DEFINITIONS --- //
//---------------------//


//---------------//
// --- TYPES --- //
//---------------//
TYPE TResourceManagerNode
name$
id%
count%=0
ENDTYPE


//-------------------//
// --- VARIABLES --- //
//-------------------//
GLOBAL ResourceManagerSprites[] AS TResourceManagerNode, ResourceManagerSounds[] AS TResourceManagerNode


//-------------------//
// --- FUNCTIONS --- //
//-------------------//
//! FUNCTIONS

//! Releases all the resources
FUNCTION ResourceManagerDispose:
ResourceManagerReleaseSpritesAll()
ResourceManagerReleaseSoundsAll()
ENDFUNCTION


//! Loads a SPRITE
// \param filename$ - file to load
// \return ID of the sprite
FUNCTION ResourceManagerLoadSprite: filename$
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(filename$, ResourceManagerSprites[])
IF l_var<0
l_var=ResourceManagerLoadSpriteAux(filename$)
ELSE
INC ResourceManagerSprites[l_var].count
l_var=ResourceManagerSprites[l_var].id
ENDIF
RETURN l_var
ENDFUNCTION


//! Loads an ANIM, see LOADANIM for more details
// \param filename$ - file to load
// \param width% - width of each frame
// \param height% - height of each frame
// \return ID of the sprite
FUNCTION ResourceManagerLoadAnim: filename$, width%, height%
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(filename$, ResourceManagerSprites[])
IF l_var<0
l_var=ResourceManagerLoadAnimAux(filename$, width, height)
ELSE
INC ResourceManagerSprites[l_var].count
l_var=ResourceManagerSprites[l_var].id
ENDIF
RETURN l_var
ENDFUNCTION


//! Loads a SOUND, see LOADSOUND for more details
// \param filename$ - file to load
// \param buffer% - number of buffers of the sound
// \return ID of the sound
FUNCTION ResourceManagerLoadSound: filename$, buffer%
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(filename$, ResourceManagerSounds[])
IF l_var<0
l_var=ResourceManagerLoadSoundAux(filename$, buffer)
ELSE
INC ResourceManagerSounds[l_var].count
l_var=ResourceManagerSounds[l_var].id
ENDIF
RETURN l_var
ENDFUNCTION


//! Unloads ONE copy of the SPRITE, if the resource is not used by anything, it is released
// \param name$ - name of the element to unload
// \return true, or false if the element doesn't exists
FUNCTION ResourceManagerUnloadSpriteByName: name$
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(name$, ResourceManagerSprites[])
IF l_var<0
RETURN FALSE
ELSE
DEC ResourceManagerSprites[l_var].count
IF ResourceManagerSprites[l_var].count<=0 THEN ResourceManagerReleaseSpriteAux(l_var)
ENDIF
RETURN TRUE
ENDFUNCTION


//! Unloads ONE copy of the SPRITE, if the resource is not used by anything, it is released
// \param id% - ID of the element to unload
// \return true, or false if the element doesn't exists
FUNCTION ResourceManagerUnloadSpriteByID: id%
LOCAL l_var%=ResourceManagerSearchNodeByIDAux(id, ResourceManagerSprites[])
IF l_var<0
RETURN FALSE
ELSE
DEC ResourceManagerSprites[l_var].count
IF ResourceManagerSprites[l_var].count<=0 THEN ResourceManagerReleaseSpriteAux(l_var)
ENDIF
RETURN TRUE
ENDFUNCTION


//! Unloads ONE copy of the SOUND, if the resource is not used by anything, it is released
// \param name$ - name of the element to unload
// \return true, or false if the element doesn't exists
FUNCTION ResourceManagerUnloadSoundByName: name$
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(name$, ResourceManagerSounds[])
IF l_var<0
RETURN FALSE
ELSE
DEC ResourceManagerSounds[l_var].count
IF ResourceManagerSounds[l_var].count<=0 THEN ResourceManagerReleaseSoundAux(l_var)
ENDIF
RETURN TRUE
ENDFUNCTION


//! Unloads ONE copy of the SOUND, if the resource is not used by anything, it is released
// \param id% - ID of the element to unload
// \return true, or false if the element doesn't exists
FUNCTION ResourceManagerUnloadSoundByID: id%
LOCAL l_var%=ResourceManagerSearchNodeByIDAux(id, ResourceManagerSounds[])
IF l_var<0
RETURN FALSE
ELSE
DEC ResourceManagerSounds[l_var].count
IF ResourceManagerSounds[l_var].count<=0 THEN ResourceManagerReleaseSoundAux(l_var)
ENDIF
RETURN TRUE
ENDFUNCTION


//! Releases the SPRITE
// \param name$ - name of the element to unload
// \return true, or false if the element doesn't exists
FUNCTION ResourceManagerReleaseSpriteByName: name$
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(name$, ResourceManagerSprites[])
IF l_var<0
RETURN FALSE
ELSE
ResourceManagerReleaseSpriteAux(l_var)
ENDIF
RETURN TRUE
ENDFUNCTION


//! Releases the SPRITE
// \param id% - ID of the element to unload
// \return true, or false if the element doesn't exists
FUNCTION ResourceManagerReleaseSpriteByID: id%
LOCAL l_var%=ResourceManagerSearchNodeByIDAux(id, ResourceManagerSprites[])
IF l_var<0
RETURN FALSE
ELSE
ResourceManagerReleaseSpriteAux(l_var)
ENDIF
RETURN TRUE
ENDFUNCTION


//! Releases the SOUND
// \param name$ - name of the element to unload
// \return true, or false if the element doesn't exists
FUNCTION ResourceManagerReleaseSoundByName: name$
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(name$, ResourceManagerSounds[])
IF l_var<0
RETURN FALSE
ELSE
ResourceManagerReleaseSoundAux(l_var)
ENDIF
RETURN TRUE
ENDFUNCTION


//! Releases the SOUND
// \param id% - ID of the element to unload
// \return true, or false if the element doesn't exists
FUNCTION ResourceManagerReleaseSoundByID: id%
LOCAL l_var%=ResourceManagerSearchNodeByIDAux(id, ResourceManagerSounds[])
IF l_var<0
RETURN FALSE
ELSE
ResourceManagerReleaseSoundAux(l_var)
ENDIF
RETURN TRUE
ENDFUNCTION


//! Releases ALL the SPRITES
FUNCTION ResourceManagerReleaseSpritesAll:
FOREACH sprite IN ResourceManagerSprites[]
LOADSPRITE "xx", sprite.id
NEXT
DIM ResourceManagerSprites[0]
ENDFUNCTION


//! Releases ALL the SOUNDS
FUNCTION ResourceManagerReleaseSoundsAll:
FOREACH sound IN ResourceManagerSounds[]
LOADSOUND "xx", sound.id, 1
NEXT
DIM ResourceManagerSounds[0]
ENDFUNCTION


//! Gets SPRITE ID
// \param name$ - name of the element
// \return ID of the element, -1 if it doesn't exists
FUNCTION ResourceManagerGetSpriteID: name$
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(name$, ResourceManagerSprites[])
IF l_var<0
RETURN -1
ENDIF
RETURN ResourceManagerSprites[l_var].id
ENDFUNCTION


//! Gets SPRITE ID, if it doesn't exists, loads it
// \param name$ - name of the element
// \return ID of the element
FUNCTION ResourceManagerGetSpriteIDLoad: name$
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(name$, ResourceManagerSprites[])
IF l_var<0
l_var=ResourceManagerLoadSpriteAux(name$)
ELSE
l_var=ResourceManagerSprites[l_var].id
ENDIF
RETURN l_var
ENDFUNCTION


//! Gets ANIM ID, if it doesn't exists, loads it
// \param name$ - name of the element
// \param width% - width of each frame
// \param height% - height of each frame
// \return ID of the element
FUNCTION ResourceManagerGetAnimIDLoad: name$, width%, height%
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(name$, ResourceManagerSprites[])
IF l_var<0
l_var=ResourceManagerLoadAnimAux(name$, width, height)
ELSE
l_var=ResourceManagerSprites[l_var].id
ENDIF
RETURN l_var
ENDFUNCTION


//! Gets SPRITE name
// \param id% - ID of the element
// \return name of the element, "" if it doesn't exists
FUNCTION ResourceManagerGetSpriteName$: id%
LOCAL l_var%=ResourceManagerSearchNodeByIDAux(id, ResourceManagerSprites[])
IF l_var<0
RETURN ""
ENDIF
RETURN ResourceManagerSprites[l_var].name$
ENDFUNCTION


//! Gets SOUND ID
// \param name$ - name of the element
// \return ID of the element, -1 if it doesn't exists
FUNCTION ResourceManagerGetSoundID: name$
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(name$, ResourceManagerSounds[])
IF l_var<0
RETURN -1
ENDIF
RETURN ResourceManagerSounds[l_var].id
ENDFUNCTION


//! Gets SOUND ID, if it doesn't exists, loads it
// \param name$ - name of the element
// \param buffer% - number of buffers of the sound
// \return ID of the element
FUNCTION ResourceManagerGetSoundIDLoad: name$, buffer%
LOCAL l_var%=ResourceManagerSearchNodeByNameAux(name$, ResourceManagerSounds[])
IF l_var<0
l_var=ResourceManagerLoadSoundAux(name$, buffer)
ELSE
l_var=ResourceManagerSounds[l_var].id
ENDIF
RETURN l_var
ENDFUNCTION


//! Gets SOUND name
// \param id% - ID of the element
// \return name of the element, "" if it doesn't exists
FUNCTION ResourceManagerGetSoundName$: id%
LOCAL l_var%=ResourceManagerSearchNodeByIDAux(id, ResourceManagerSounds[])
IF l_var<0
RETURN ""
ENDIF
RETURN ResourceManagerSounds[l_var].name$
ENDFUNCTION





//----------------------------//
// --- AUXILIAR FUNCTIONS --- //
// ---     DO NOT USE     --- //
//----------------------------//
//! Loads a SPRITE and adds it to resources pool
// \param filename$ - file to load
// \return ID of the sprite
@FUNCTION ResourceManagerLoadSpriteAux: filename$
LOCAL l_node AS TResourceManagerNode
IF DOESFILEEXIST(filename$)=FALSE THEN RETURN -1
l_node.name$=filename$
l_node.id=GENSPRITE(); LOADSPRITE filename$, l_node.id
INC l_node.count
DIMPUSH ResourceManagerSprites[], l_node
RETURN l_node.id
ENDFUNCTION


//! Loads an ANIM and adds it to resources pool
// \param filename$ - file to load
// \param width% - width of each frame
// \param height% - height of each frame
// \return ID of the sprite
@FUNCTION ResourceManagerLoadAnimAux: filename$, width%, height%
LOCAL l_node AS TResourceManagerNode
IF DOESFILEEXIST(filename$)=FALSE THEN RETURN -1
l_node.name$=filename$
l_node.id=GENSPRITE(); LOADANIM filename$, l_node.id, width, height
INC l_node.count
DIMPUSH ResourceManagerSprites[], l_node
RETURN l_node.id
ENDFUNCTION


//! Loads a SOUND and adds it to resources pool
// \param filename$ - file to load
// \param buffer% - number of buffers of the sound
// \return ID of the sound
@FUNCTION ResourceManagerLoadSoundAux: filename$, buffer%
LOCAL l_node AS TResourceManagerNode
IF DOESFILEEXIST(filename$)=FALSE THEN RETURN -1
l_node.name$=filename$
l_node.id=GENSOUND(); LOADSOUND filename$, l_node.id, buffer
INC l_node.count
DIMPUSH ResourceManagerSounds[], l_node
RETURN l_node.id
ENDFUNCTION


//! Releases a SPRITE and remove it from resources pool
// \param index% - element index in the resources pool
@FUNCTION ResourceManagerReleaseSpriteAux: index%
LOADSPRITE "xx", ResourceManagerSprites[index].id
DIMDEL ResourceManagerSprites[], index
ENDFUNCTION


//! Releases a SOUND and remove it from resources pool
// \param index% - element index in the resources pool
@FUNCTION ResourceManagerReleaseSoundAux: index%
LOADSOUND "xx", ResourceManagerSounds[index].id, 1
DIMDEL ResourceManagerSounds[], index
ENDFUNCTION


//! Search a node in the resources pool
// \param name$ - name of the resource
// \param nodes[] AS TResourceManagerNode - array to do search
// \return position of the node, -1 if not found
@FUNCTION ResourceManagerSearchNodeByNameAux: name$, nodes[] AS TResourceManagerNode
LOCAL l_result%=0
FOREACH node IN nodes[]
IF node.name$=name$ THEN RETURN l_result
INC l_result
NEXT
RETURN -1
ENDFUNCTION


//! Search a node in the resources pool
// \param id% - ID of the resource
// \param nodes[] AS TResourceManagerNode - array to do search
// \return position of the node, -1 if not found
@FUNCTION ResourceManagerSearchNodeByIDAux: id%, nodes[] AS TResourceManagerNode
LOCAL l_result%=0
FOREACH node IN nodes[]
IF node.id=id THEN RETURN l_result
INC l_result
NEXT
RETURN -1
ENDFUNCTION


Dark Schneider

Corrected a mistake on ResourceManagerGetxxxIDLoad functions.

Wampus

Thanks for the useful code.

Dark Schneider

Now with comments, fixed the ResourceManagerGetSoundIDLoad() function.