Game Development Community

Implementing Dynamic Image Loader

by Jonathan R Hopkins · in Technical Issues · 06/19/2009 (1:26 pm) · 0 replies

Hello again to everyone - hopefully this will be the last big issue I have.

I am trying to figure out how to implement this feature into my game. Its a piece of C++ code that should allow me to force the game to load/unload images whenever I want, thereby allowing me to manage memory and avoid exponentially eating up the player's resources.

The code is here: www.garagegames.com/community/resources/view/10656

And I have copied the C++ exactly below. I've already mentioned earlier what I have done to try to get it to work, but that seems to throw people off, so if someone could tell me what they would do, step by step, to implement the code in their own engine - I would really appreciate it. Thank you very much!

Just in case there is relevance to what I've done already, this is what I tried doing to make it work. Which, by the way, my game isn't finding it:

- I dropped the file "DynamicImageLoader.cc" into the "enginesourceT2D" folder and then added it to the project from within Visual C++ 2008 Express by choosing "Project > Add existing Item". Looking at the Solution Explorer within C++ 2008 express, the file is currently sitting within: Solution > TorqueGameBuilder > DynamicImageLoader.

//---------------------------------------------------------------------------------------------
// DynamicImageLoader 
// Author: William Hilke
// Contact Email: whilke@gmail.com
//---------------------------------------------------------------------------------------------


//Engine based ehancements for my TorqueScript DynamicImagLoader class.

#include "console/console.h"
#include "console/consoleInternal.h"
#include "console/consoleTypes.h"
#include "T2D/t2dImageMapDatablock.h"



//-----------------------------------------------------------------------------
// Force the ImageMap to load into memory.
//-----------------------------------------------------------------------------
ConsoleMethod(t2dImageMapDatablock, LoadImageMap, void, 2, 2, "Load Imagemap into memory.")
{
	object->lockImageMap();
}

//-----------------------------------------------------------------------------
// Release our lock on the ImageMap. If no one else has this locked, it will get removed from memory.
//-----------------------------------------------------------------------------
ConsoleMethod(t2dImageMapDatablock, UnloadImageMap, void, 2, 2, "Release our lock on the ImageMap.")
{
	object->unlockImageMap();
}

And here is the Torque Script side of things:

//---------------------------------------------------------------------------------------------
// DynamicImageLoader 
// Author: William Hilke
// Contact Email: whilke@gmail.com
//---------------------------------------------------------------------------------------------


// Create a new object to group ImagesBlocks together.
function NewDynamicImageLoader(%callback)
{
   %var = new ScriptObject()
   {
      class = DynamicImageLoader;
      mImageCount = 0;  
      mImages     = 0;
      mDatablocks = 0;
      mCallbackFunc = %callback;
      mLoaded     = false;
   };
   
   %var.mImages = new SimSet();
   %var.mDatablocks = new SimSet();

   return %var;
}

//deconstructor - this will make sure all dynamic objects get
//cleaned up.
function DynamicImageLoader::OnRemove(%this)
{
   %this.clear();
   %this.mImages.delete();
   %this.mDatablocks.delete();
}

//Add an imagemap to get loaded by the Load() function.
function DynamicImageLoader::Add(%this,%imageMap)
{
   %this.mDatablocks.Add(%imageMap);
   %this.mImageCount++;
}

//Remove an ImageMapDatablock from the loader.
//If you have allowUnload="1" and this is the last
//instance of the imagemap, then the image will get
//unloaded from the graphics card.
function DynamicImageLoader::Remove(%this,%imageMap)
{
   //find the index of this imageMap
   //we use the index as the lookup into the loaded images.
   for(%i = 0; %i < %this.mImageCount; %i++)
   {
      %imgMap = %this.mDatablocks.getObject(%i);
      if ( %imgMap == %imageMap )
      {
         //first check if we have our c++ changes loaded.
         if ( %imgMap.isMethod("UnloadImageMap") )
         {
            //tell the ImageMap to unload the image from memory.
            %imgMap.UnloadImageMap();
         }
         else
         {
            //fall back to our static sprite array.
            if (%this.mImages.getCount() > %i)
            {
               %spr = %this.mImages.getObject(%i);
               %this.mImages.remove(%spr);
               %spr.delete();
            }
         }

         
         %this.mDatablocks.remove(%imgMap);

         %this.mImageCount--;
         if (%this.mImageCount < 0)
            %this.mImageCount = 0;

         return true;
      }
   }
   
   return false;
}

//This will remove all loaded imagemaps
//If you have allowUnload="1" and this is the last
//instance of the imagemap, then the image will get
//unloaded from the graphics card.
function DynamicImageLoader::clear(%this)
{
   //see if we were using our custom c++ changes.
   %count = %this.mDatablocks.getCount();
   if ( %count > 0 && %this.mDatablocks.getObject(0).isMethod("UnloadImageMap") )
   {  
      //we need to loop through all the ImageMaps and tell
      //them to unload.
      for(%i = 0; %i < %this.mDatablocks.getCount(); %i++)
      {
         %obj = %this.mDatablocks.getObject(%i);
         %obj.UnloadImageMap();
      }
   }
   else
   {
      //mImages contains sub objects that we want to delete.
      while( %this.mImages.getCount() > 0 )
      {
         %obj = %this.mImages.getObject(0);
         %this.mImages.remove(%obj);
         %obj.delete();
      }
   }

   %this.mDatablocks.clear();
   %this.mImageCount = 0;
   %this.mLoaded = false; // reset the object to be used again.
}

//Once you are ready to load a set of ImageMaps
//This will run through and create hidden StaticSprites
//for each ImageMap. This will also call the callback
//function for each ImageMap loaded, if you specified it.
function DynamicImageLoader::Load(%this)
{
   //if we've already loaded this object, then fail out.
   if (%this.mLoaded)
      return false;
      
   for(%i = 0; %i < %this.mImageCount; %i++)
   {
      %imgMap = %this.mDatablocks.getObject(%i);
      
      //first check if we have our c++ changes loaded.
      if ( %imgMap.isMethod("LoadImageMap") )
      {
         // we can just tell the imageMap to load the data into memory.
         %imgMap.LoadImageMap();
      }
      else
      {
         //fallback to using hidden static sprites.
         %spr = new t2dStaticSprite();
         %spr.setVisible(false);
         %spr.setImageMap( %this.mDatablocks.getObject(%i) );
         %this.mImages.add(%spr);
      }
      
      //if a callback was configured, call it with the image index just loaded
      //and the total images in this set.
      if (%this.mCallbackFunc !$= "")
      {
         %evalStr = %this.mCallbackFunc @ "(" @ %i+1 @ "," @ %this.mImageCount @ ");" ;
         eval(%evalStr);
      }
   }
   
   %this.mLoaded = true;   //this will make sure we don't try and load
                     //the ImageMaps again.
   return true;
}


The line in particular in the Torque script that isn't working is the verification:

isMethod("UnloadImageMap")

I'm guessing this probably means I haven't nearly set it up right, but that's as far as I can figure it out.

Thank you.