How is NiftyGUI asset loading done?

I was wondering, when are the image files mentioned on the NiftyGUI xml file loaded? Is every file loaded when you use nifty.fromXml() or they are only loaded when you use nifty.gotoScreen()? And then, does it load from every screen or just the one you’re going to?



I wanted to know because I’m making a loading screen (which relies on NiftyGUI) and I’m not sure if it’s useless or not to load the interface files.



Thanks.

The best way to know is to use a file that doesn’t exist in your XML. Your app will crash if it doesn’t find the image. Depending at which moment the app will crash will give you the information you seek.

There’s something weird happening:



I added a large image file to my screen like this:

[xml]

<screen id=“start” controller=“cardkingdom.client.MainMenuState”>

<layer id=“layer_background” backgroundColor="#ffff" childLayout=“center” visibleToMouse=“true”>

<image filename=“client/Textures/big_image.jpg”></image>

</layer>

[…]

[/xml]



and on the initialize method of MainMenuState (which is called after Nifty is showing everything on the screen), if I do this:

[java]long start = System.currentTimeMillis();

_app.getAssetManager().loadTexture(“client/Textures/big_image.jpg”);

long end = System.currentTimeMillis();

System.out.println("Took: "+(end-start));



start = System.currentTimeMillis();

_app.getAssetManager().loadTexture(“client/Textures/big_image.jpg”);

end = System.currentTimeMillis();

System.out.println("Took: "+(end-start));[/java]

This is the result:

Took: 487

Took: 0



are Nifty loaded files stored somewhere else?

You’re loading the image twice.



The first time, it’s loaded from disk, the second time from the cache.

Yes, I know that… but big_image.jpg is already on the screen when I call that first loadTexture, shoudn’t it be loaded from the cache on that first call?

I did other tests, these were my results:



Without “big_image.jpg” on my gui .xml file, nifty.fromXml() takes 400ms~ (there are other images on the file). If I add “big_image.jpg” to the xml file, it goes up to 950ms~. If I load “big_image.jpg” before calling nifty.fromXml(), fromXml still takes 950ms~ to run. If I load “big_image.jpg” after Nifty has loaded it, it takes 450ms~ to load it (when it should be already on the asset manager.)



I also removed the “big_image.jpg” from the “start” screen and put it in another screen (one that isn’t used), fromXml() still takes 950ms~ to run, so I’m assuming it does load every image on the file and not just from the current screen.



I read somewhere that Nifty uses the AssetManager to load files, is this wrong? My GUI files aren’t that big, but I still would like to load them on my preloader and have Nifty use the preloaded files.

Yes, nifty uses the assetmanager.

wow. helpful, thanks.

I guess you’ll have to look in the source. I tried to find it in jME-source but I haven’t located it yet (didn’t look to hard). If you find out please tell us in this thread, I got curious now that you asked the question :slight_smile:

Void is a pretty regular visitor to this forum and I imagine will be able to reply in a bit more detail…

From Niftys perspective images are loaded in fromXml() - or in general when a screen is created and not when it is shown.



The actual loading of the resource is done in the SPI implementation for jME (public class com.jme3.niftygui.RenderImageJme implements de.lessvoid.nifty.spi.render.RenderImage …) which uses this code to create the texture:



[java]Texture2D texture = (Texture2D) display.getAssetManager().loadTexture(key);[/java]

1 Like

So, am I wrong to expect files loaded before fromXml() to be used by nifty?

I don’t know how the assetManager works internally but I think when you use the same key (= filename) for it and the assetManager already has a resource with that key/name I suppose it will simply reuse this resource and it won’t load it again. Wouldn’t make much sense otherwise. You can look at com.jme3.niftygui.RenderImageJme to check how this is done.



But maybe Sir @normen can clarify this :wink:

I don’t think the MainMenuState.initialize() is necessarily called after the images were loaded, its the ScreenController of that screen after all isn’t it? The assetManager does cache images though yes (depending on memory ofc).

I also tested on a button press instead of the initialize method, the image was clearly on the screen but still took time to load when I pressed the button (and like I said, one of my tests was loading the image before calling fromXml(), and nifty loaded the image even though I already had it loaded).

Then I don’t know why they are not cached, an explanation would be that if nifty finds them on the classpath first it loads them from there. Do you use the Nifty AppState like in our examples?

You mean extending the AbstractAppState and implementing the ScreenController?

Uh, sorry, I wasn’t thinking right, theres no default AppState for nifty anymore, anyway how do you create your nifty instance? Can you please make a test case for this issue?

TestC.java

[java]

import com.jme3.app.SimpleApplication;

import com.jme3.niftygui.NiftyJmeDisplay;



import de.lessvoid.nifty.Nifty;



public class TestC extends SimpleApplication {

private Nifty _nifty;

private NiftyJmeDisplay _niftyDisplay;



@Override

public void simpleInitApp() {

long start, end;



_niftyDisplay = new NiftyJmeDisplay(getAssetManager(), getInputManager(), getAudioRenderer(), getGuiViewPort());

_nifty = _niftyDisplay.getNifty();



start = System.currentTimeMillis();

_nifty.fromXml("gui.xml", "start");

end = System.currentTimeMillis();



System.out.println("Took: "+(end-start));



start = System.currentTimeMillis();

assetManager.loadTexture("Textures/Terrain/Pond/Pond.jpg");

end = System.currentTimeMillis();



System.out.println("Took: "+(end-start));



start = System.currentTimeMillis();

assetManager.loadTexture("Textures/Terrain/Pond/Pond.jpg");

end = System.currentTimeMillis();



System.out.println("Took: "+(end-start));



getGuiViewPort().addProcessor(_niftyDisplay);

}



public static void main(String[] args) {

TestC app = new TestC();

app.start();

}

}[/java]



[xml]<?xml version="1.0" encoding="UTF-8"?>

<nifty xmlns="http://nifty-gui.sourceforge.net/nifty-1.3.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://nifty-gui.sourceforge.net/nifty-1.3.xsd http://nifty-gui.sourceforge.net/nifty-1.3.xsd">

<useControls filename="nifty-default-controls.xml" />

<useStyles filename="nifty-default-styles.xml" />



<screen id="start" controller="basic.TestC">

<layer id="layer_background" backgroundColor="#ffff" childLayout="center" visibleToMouse="true">

<image filename="Textures/Terrain/Pond/Pond.jpg" width="100%" height="100%"></image>

</layer>

</screen>



</nifty>

[/xml]



A bigger image would probably be better but I could not find any in the default assets.

2 Likes

If the image is that large could it just be that it is being dropped from the cache during all the other loading that is going on at startup?