Is it possible to use level specific datablocks to populate data in the iTGB editors create tab?
by Jon Shattuck · in iTorque 2D · 03/03/2009 (10:16 am) · 22 replies
Our project is going to have a large amount of art that we do not want to be loaded all at once into memory when the game starts. We can get around this by loading a datablock for each level only when it is needed while the game is running. The problem is this is misleading in the editor as each level shows all the assets in the create tab. Is there a way we can make the editor load a level specific datablock instead of the datablocks.cs located in the managed folder? I know resources would normally perform this task, but my understanding is that resources do not work on the iPhone
About the author
#2
Thanks again for the help!
03/03/2009 (1:02 pm)
Thanks for the reply Marc, what files would you suggest I look at? I have been digging around in the *.ed.cs files, and the /common/gameScripts directory. But I have yet to find a place where I can exec my level specific datablock files and see them actually appear in the editor. Am I way off in where I am looking? Thanks again for the help!
#3
and these
So, Assumming my project's default level is "DemoLevel.t2d", I make a file called "DemoLevelDatablocks.cs" and wrap the datablocks in a semset called $CurrentLevelDatablockSet (like how $managedDatablockSet works).
03/03/2009 (2:44 pm)
I added this to the bottom of my gameScripts/datablocks.cs to get something similar//-Mat if we are in the editor, we need to load the level-specific datablocks
if( isToolBuild() ) {
//-Mat in case we are loading a new scene from the GUI interface
exec("game/gameScripts/gameFunctions.cs");
%level = LoadProjectLastLevel();
loadCurrentLevelDatablocks( %level );
}and these
function LoadProjectLastLevel()
{
%projectFile = "project.t2dProj";
%xml = new ScriptObject() { class = "XML"; };
%lastlevel = "";
if( %xml.beginRead( %projectFile ) )
{
if( %xml.readClassBegin( "TorqueProject" ) )
{
%lastlevel = %xml.readField( "LastLevel" );
echo( "-Mat LastLevel:" SPC %lastlevel );
%xml.readClassEnd();
}
%xml.endRead();
}
// Delete the object
%xml.delete();
return %lastlevel;
}
function loadCurrentLevelDatablocks( %levelfile ) {
//load level datablocks and add them to the all datablocks list
%start = strlen( "game/data/levels/" );
%end = strlen( %levelfile ) - %start - 4;//remove ".cs"
%datablocksFile = getSubStr( %levelfile, %start, %end );
%datablocksFile = "game/gamescripts/" @ %datablocksFile @ "Datablocks.cs";
echo( "-Mat loading:" SPC %datablocksFile );
exec( %datablocksFile );
%count = $CurrentLevelDatablockSet.getCount();
for( %i = 0; %i < %count; %i++ ) {
$managedDatablockSet.add( $CurrentLevelDatablockSet.getObject( %i ) );
}
}So, Assumming my project's default level is "DemoLevel.t2d", I make a file called "DemoLevelDatablocks.cs" and wrap the datablocks in a semset called $CurrentLevelDatablockSet (like how $managedDatablockSet works).
#4
I looked into adding this into the tgb\torsion\tools 1.2.torsion\common\gameScripts\levelManagement.cs
From my debugging, this function is called every time a level is loaded in the editor, which is what I want. Currently I am trying to exec from a hard coded directory, but if I can get this to work I could use %levelFile to get the desired file to be loaded. However, when watching the log output on this it throws an error saying it cannot find the file.
for some reason it is adding /Depot/GamesFolder/Main/tgb/common/gameScripts onto the correct path directory.
Am I unable to access MyGame/game/gameScripts/levelOneDatablocks.cs from this location? If so is there somewhere else I can call my script every time a level is loaded that would give me access to my game/gameScripts directory?
I tried adding this into the /GamesFolder/Main/games/MyGame/common/gameScripts/levelManagement.cs but it seems this version of level management only takes place in game, and I need this to work in the editor.
I appreciate all the help!
03/04/2009 (1:38 pm)
This works the first time the engine is loaded, but if I open a new scene, it does not seem to run a second time to populate the create tab with the assets for that specific level. Is there a way to make gameScripts/datablocks.cs be called each time a level is loaded or is it only called once when the editor is first opened? I looked into adding this into the tgb\torsion\tools 1.2.torsion\common\gameScripts\levelManagement.cs
function t2dSceneWindow::loadLevel(%sceneWindow, %levelFile)
{
exec( "./Depot/GamesFolder/Main/games/MyGame/game/gameScripts/levelOneDatablocks.cs" );
%count = $CurrentLevelDatablockSet.getCount();
for( %i = 0; %i < %count; %i++ )
$managedDatablockSet.add( $CurrentLevelDatablockSet.getObject( %i ) );
...From my debugging, this function is called every time a level is loaded in the editor, which is what I want. Currently I am trying to exec from a hard coded directory, but if I can get this to work I could use %levelFile to get the desired file to be loaded. However, when watching the log output on this it throws an error saying it cannot find the file.
Missing file: /Depot/GamesFolder/Main/tgb/common/gameScripts/Depot/GamesFolder/Main/games/MyGame/game/gameScripts/levelOneDatablocks.cs!
for some reason it is adding /Depot/GamesFolder/Main/tgb/common/gameScripts onto the correct path directory.
Am I unable to access MyGame/game/gameScripts/levelOneDatablocks.cs from this location? If so is there somewhere else I can call my script every time a level is loaded that would give me access to my game/gameScripts directory?
I tried adding this into the /GamesFolder/Main/games/MyGame/common/gameScripts/levelManagement.cs but it seems this version of level management only takes place in game, and I need this to work in the editor.
I appreciate all the help!
#5
exec( "./Depot/GamesFolder/Main/games/MyGame/game/gameScripts/levelOneDatablocks.cs"
The '.' in the beginning tells Torque to load from the current mod path, which may work from inside your game, but the editor will interpret that differently.
Try it without '.' and see what you get.
03/04/2009 (4:15 pm)
Here's your problemexec( "./Depot/GamesFolder/Main/games/MyGame/game/gameScripts/levelOneDatablocks.cs"
The '.' in the beginning tells Torque to load from the current mod path, which may work from inside your game, but the editor will interpret that differently.
Try it without '.' and see what you get.
#6
Any suggestions on how I would go about clearing out the create tab before the new assets are loaded in from the level specific datablock?
03/05/2009 (12:55 pm)
Thanks! that did it, I now have level specific datablocks loading whenever a new level is loaded. One new problem that has popped up is the create tab (which I am assuming is a GUI object) does not get cleared out. This means that each time a new level is loaded, the previous level's content is never removed from the create tab. Any suggestions on how I would go about clearing out the create tab before the new assets are loaded in from the level specific datablock?
#7
Somthing like this:
03/05/2009 (1:32 pm)
change you loadCurrentLevelDatablocks() to delete the contents of $CurrentLevelDatablockSet before adding actually loading the new fileSomthing like this:
function loadCurrentLevelDatablocks( %levelfile ) {
//load level datablocks and add them to the all datablocks list
%start = strlen( "game/data/levels/" );
%end = strlen( %levelfile ) - %start - 4;//remove ".cs"
%datablocksFile = getSubStr( %levelfile, %start, %end );
%datablocksFile = "game/gamescripts/" @ %datablocksFile @ "Datablocks.cs";
echo( "-Mat loading:" SPC %datablocksFile );
%count = $CurrentLevelDatablockSet.getCount();
for( %i = 0; %i < %count; %i++ ) {
%object = $CurrentLevelDatablockSet.getObject( %i );
$managedDatablockSet.remove( %object );
}
$CurrentLevelDatablockSet.clear();
exec( %datablocksFile );
%count = $CurrentLevelDatablockSet.getCount();
for( %i = 0; %i < %count; %i++ ) {
$managedDatablockSet.add( $CurrentLevelDatablockSet.getObject( %i ) );
}
#8
I definitely know the asset is removed from the list because I can place the asset into the scene but when I run the game it wont show up. Any suggestions on how I would go about forcing the create tab to reset/clean itself so that all the old assets are removed?
03/06/2009 (7:42 am)
That definitely removes the assets from the $managedDatablockSet, and $CurrentLevelDatablockSet, but it does not remove the assets from the create tab in the editor. This seems awfully strange to me as you would think if the datablock for the asset no longer exists it would remove it from the create tab. I definitely know the asset is removed from the list because I can place the asset into the scene but when I run the game it wont show up. Any suggestions on how I would go about forcing the create tab to reset/clean itself so that all the old assets are removed?
#9
03/06/2009 (10:12 am)
I would check out the script in the "tgb" folder that populates that tab and see exactly what it does. There's probably a function like "rebuildDatablocks()" or something in there that you could call from your script to force a refresh.
#10
03/09/2009 (7:27 am)
Looks like $CurrentLevelDatablockSet.deleteContents(); works in removing the assets from the create tab list.
#11
load the new assets everytime you open a scene based on the filename. Simply changed the loadCurrentLevel
to:
This way the initial load works and the reload works. Only issue is you have to goto the menu "ProjectS" and select refresh object library to get the image/animation assets to the right to refresh.
05/13/2009 (11:01 am)
Thanks for all your work this guys, I used this myself and it works great. I modified it simply so it wouldload the new assets everytime you open a scene based on the filename. Simply changed the loadCurrentLevel
to:
//load level datablocks and add them to the all datablocks list
%pos = strstr(%levelFile, "game/data/levels/" );
%start = strlen("game/data/levels/");
%start = %start + %pos;
%end = strlen( %levelfile ) - %start - 4;//remove ".cs"
%datablocksFile = getSubStr( %levelfile, %start, %end );
%datablocksFile = "game/gamescripts/" @ %datablocksFile @ "Datablocks.cs";
%count = $CurrentLevelDatablockSet.getCount();
for( %i = 0; %i < %count; %i++ ) {
%object = $CurrentLevelDatablockSet.getObject( %i );
$managedDatablockSet.remove( %object );
}
$CurrentLevelDatablockSet.deleteContents();
...This way the initial load works and the reload works. Only issue is you have to goto the menu "ProjectS" and select refresh object library to get the image/animation assets to the right to refresh.
#12
What I have after going through this thread is:
My editor is empty, if I exec files in the if(isToolBuild()) then I can get the assets loaded into the editor so I can continue work, but it would be nice if I could get it dynamically loading for the level I am working on.
When I load my game it does seem to dynamically load assets, however it does not seem to unload them.
05/20/2009 (1:50 pm)
I followed through this process as best as I could, I think I am close to getting it working. My goal is to have the editor load up assets per level, and also for my game to unload assets that are no longer needed and load up ones that are as levels are switched.What I have after going through this thread is:
My editor is empty, if I exec files in the if(isToolBuild()) then I can get the assets loaded into the editor so I can continue work, but it would be nice if I could get it dynamically loading for the level I am working on.
When I load my game it does seem to dynamically load assets, however it does not seem to unload them.
#13
Mine seem to unload when I switch levels but I've done very little testing in that regard to be honest. I have several menu's that I dynamically load/unload and then launch into my test level. Everything works fine normally. However if I forget to delete the game/managed/datablocks.cs datablock entries then it crashes on the iphone device running out of memory.
05/20/2009 (2:14 pm)
Make sure you empty the game/managed/datablocks.cs file frequently. The editor likes to copy all your datablock entries back into it. Everything in that file gets loaded for all levels.Mine seem to unload when I switch levels but I've done very little testing in that regard to be honest. I have several menu's that I dynamically load/unload and then launch into my test level. Everything works fine normally. However if I forget to delete the game/managed/datablocks.cs datablock entries then it crashes on the iphone device running out of memory.
#14
Also, possibly related to my previously mentioned issues, when I put my game onto the phone it now gets a terribly bad framerate.
05/20/2009 (2:26 pm)
Thanks for the heads up, my game/managed/datablocks.cs is empty at this time but I wouldn't be surprised if I run into that in the future.Also, possibly related to my previously mentioned issues, when I put my game onto the phone it now gets a terribly bad framerate.
#15
05/20/2009 (2:36 pm)
I always use preload = true and allow unload = false, because I've noticed bad framerates when I don't use that. Maybe that's part of the problem?
#16
I'm getting the gist of this thread, but want to know which code to put in which file. Confused, I notice none of the above code references /game/managed/*datablocks.cs, but /game/gamescripts/datablocks.cs.
Right now, in my /game/managed folder, I managed to break up the datablocks.cs file to three different files, based on the needs: splashscreendatablocks.cs, mainmenudatablocks.cs, and gamedatablocks.cs.
Should I be moving these new datablocks files to the gamescripts folder instead?
My /game/gamescripts/datablocks.cs file is empty. To this point, I've never used or understood datablocks, so consider this and my handy GPGT book as a crash course study.
Thanks.
06/03/2009 (6:39 am)
Ok, guys. Hope you can help out a newbie here, and I just found this thread. As my game continues to build in size and sprite objects, I've gotten to a point where my iPhone build only loads one out of around 15 times due to the watchdog timer.I'm getting the gist of this thread, but want to know which code to put in which file. Confused, I notice none of the above code references /game/managed/*datablocks.cs, but /game/gamescripts/datablocks.cs.
Right now, in my /game/managed folder, I managed to break up the datablocks.cs file to three different files, based on the needs: splashscreendatablocks.cs, mainmenudatablocks.cs, and gamedatablocks.cs.
Should I be moving these new datablocks files to the gamescripts folder instead?
My /game/gamescripts/datablocks.cs file is empty. To this point, I've never used or understood datablocks, so consider this and my handy GPGT book as a crash course study.
Thanks.
#17
Then, when you create a powerup, you use the datablock to populate it's fields.
imagemapdatablocks in particular will load data unless you specify preload = false; so including a bunch of them in one file will probably load a bunch of data. It's best to load your datablocks just before you need them (most likely at a loading screen, e.g. level load)
Now, "managed/datablocks" is the file that the editor uses to save it's datablocks, most notably, all the image maps you create. In particular , it pulls them from a list it keeps ($managedDatablockSet). If you want to load all your data at once (and suffer the consequences), don't change anything, otherwise, you'll want to split up those datablocks in groups (like you seem to have started to do), and load them separately.
"gamescripts/datablocks" is loaded, but not modified, by the editor. You can take advantage of this to load global datablocks, or add a script like above to load the appropriate datablocks.
A common usage is in a shooter game, you may want to load level-specifc enemy datablocks for the ship's images and enemy types. You would want to put these in a separate file and load them just before you load the level, then delete them when the level is done.
When editing that level (and that level only), you'd probably want the editor to load those datablocks, but override the editor to not save them to the "managed/datablocks.cs", so that you can keep them level-specific. If you don't, you may end up loading all of your datablocks on init, instead of on each level load.
06/03/2009 (2:18 pm)
Basically, datablocks are just that, blocks of data. Use them like templates, or to group data. For example, say you have a class "PowerUp", you may have a couple different datablocks like "WeaponPowerUp" and "HealthPowerUp", that would define the same variables common to a PowerUp, but set to different values that each type of PowerUp needs, like this;datablock PlayerData(WeaponPowerUp)
{
speed = 5;
type = "weapon";
imageMap = "WeaponPowerUpImageMap"
};
datablock PlayerData(HealthPowerUp)
{
speed = 10;
type = "health";
imageMap = "HealthPowerUpImageMap"
};Then, when you create a powerup, you use the datablock to populate it's fields.
imagemapdatablocks in particular will load data unless you specify preload = false; so including a bunch of them in one file will probably load a bunch of data. It's best to load your datablocks just before you need them (most likely at a loading screen, e.g. level load)
Now, "managed/datablocks" is the file that the editor uses to save it's datablocks, most notably, all the image maps you create. In particular , it pulls them from a list it keeps ($managedDatablockSet). If you want to load all your data at once (and suffer the consequences), don't change anything, otherwise, you'll want to split up those datablocks in groups (like you seem to have started to do), and load them separately.
"gamescripts/datablocks" is loaded, but not modified, by the editor. You can take advantage of this to load global datablocks, or add a script like above to load the appropriate datablocks.
A common usage is in a shooter game, you may want to load level-specifc enemy datablocks for the ship's images and enemy types. You would want to put these in a separate file and load them just before you load the level, then delete them when the level is done.
When editing that level (and that level only), you'd probably want the editor to load those datablocks, but override the editor to not save them to the "managed/datablocks.cs", so that you can keep them level-specific. If you don't, you may end up loading all of your datablocks on init, instead of on each level load.
#18
So, how do I tell the editor to load that particular datablock so I can keep working in it, and override the editor not to save them into datablocks.cs?
Also, I added the code from Bret's post (#11), and the console.log file shows that it can't execute the functions getCount and deleteContents... Where are those functions, are they loaded later in the script and I'm executing them too early, or did I forget to implement them somewhere?
Another weird issue I had was when I decided to tweak one of the levels (t2d file) in the editor by adding a "Use Mouse Events" checkmark. I didn't see any of the graphics, but at the time, I didn't need to since I only needed to make one change. Needless to say, the level failed to load on screen afterwards. Luckily, I had a backup of the file, but I don't see anything different (other than the added line for the mouse events) between the two t2d files... ?
06/03/2009 (10:23 pm)
Ok, I was a bit freaked out when I moved my sprites into game_datablocks.cs and when I loaded the game.t2d file, it looked empty.So, how do I tell the editor to load that particular datablock so I can keep working in it, and override the editor not to save them into datablocks.cs?
Also, I added the code from Bret's post (#11), and the console.log file shows that it can't execute the functions getCount and deleteContents... Where are those functions, are they loaded later in the script and I'm executing them too early, or did I forget to implement them somewhere?
Another weird issue I had was when I decided to tweak one of the levels (t2d file) in the editor by adding a "Use Mouse Events" checkmark. I didn't see any of the graphics, but at the time, I didn't need to since I only needed to make one change. Needless to say, the level failed to load on screen afterwards. Luckily, I had a backup of the file, but I don't see anything different (other than the added line for the mouse events) between the two t2d files... ?
#19
This seems to be the only issue for me at this point... I was hoping I didn't need to worry so much about memory management and cleanup. I'm using sceneWindow2D.endLevel();, but I'm convinced it's choking when trying to reload more of the datablocks without cleaning up the first batch.
06/05/2009 (12:09 am)
Please help me out here - the game is loading fine now that I've moved a small splash screen to the front, drastically reducing launch time to 12 seconds. However, I think the memory is getting jammed up, because it fails back to the Home screen after loading a few levels - going from splash to main menu to game to another game level... Probably because the code above doesn't work - the console log still shows that getCount and getObject are unknown functions.This seems to be the only issue for me at this point... I was hoping I didn't need to worry so much about memory management and cleanup. I'm using sceneWindow2D.endLevel();, but I'm convinced it's choking when trying to reload more of the datablocks without cleaning up the first batch.
#20
06/05/2009 (6:53 am)
Make sure you don't have a typo. Mine doesn't report any errors for those two functions.
Torque 3D Owner Marc Dreamora Schaerer
Gayasoft