I’ve followed niftygui tutorial to implement a ProgressBar control, I’d like to use it as a LoadingNodeState to show progress of loading process. I’m able to set progressbar value, but I can’t see progressbar changing on screen while loading application.
How to do it?
[xml]
<?xml version=“1.0” encoding=“UTF-8”?>
<nifty xmlns=“http://nifty-gui.sourceforge.net/nifty.xsd” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=“http://nifty-gui.sourceforge.net/nifty.xsd http://nifty-gui.sourceforge.net/nifty.xsd”>
<!-- this is our nifty little progressbar control -->
<controlDefinition name=“progressbar” controller=“it.F1Viewer3D.gui.ProgressBar”>
<image filename=“textures/progress-outer.png” imageMode=“resize:15,2,15,15,15,2,15,2,15,2,15,15” childLayout=“absolute”>
<image id=“progress” x=“0” y=“0” filename=“textures/progress-inner.png” width=“32px” height=“100%” imageMode=“resize:15,2,15,15,15,2,15,2,15,2,15,15” />
<text id=“progress-text” font=“verdana-small-regular.fnt” text="" textHAlign=“center” textVAlign=“center” width=“100%” height=“100%” x=“0” y=“0” color="#f00f" />
</image>
</controlDefinition>
<!-- a simple screen -->
<screen id=“start”>
<layer id=“layer” childLayout=“center”>
<control id=“my-progress” name=“progressbar” align=“center” valign=“center” width=“400px” height=“32px” />
</layer>
</screen>
</nifty>
[/xml]
[java]
public class ProgressBar implements Controller {
private Element progressBarElement;
private Element progressTextElement;
public void bind(
final Nifty nifty,
final Screen screenParam,
final Element element,
final Properties parameter,
final ControllerEventListener listener,
final Attributes controlDefinitionAttributes) {
progressBarElement = element.findElementByName(“progress”);
progressTextElement = element.findElementByName(“progress-text”);
}
public void onStartScreen() {
}
public void onFocus(final boolean getFocus) {
}
public boolean inputEvent(final NiftyInputEvent inputEvent) {
return false;
}
public void setProgress(final float progressValue) {
float progress = progressValue;
if (progress < 0.0f) {
progress = 0.0f;
} else if (progress > 1.0f) {
progress = 1.0f;
}
final int MIN_WIDTH = 32;
int pixelWidth = (int)(MIN_WIDTH + (progressBarElement.getParent().getWidth() - MIN_WIDTH) * progress);
progressBarElement.setConstraintWidth(new SizeValue(pixelWidth + “px”));
progressBarElement.getParent().layoutElements();
String progressText = String.format("%3.0f%%", progress * 100);
progressTextElement.getRenderer(TextRenderer.class).setText(progressText);
}
}
[/java]
[java]
…
private void updateGUI() {
Screen screen = nifty.getScreen(“start”);
// next we use the findControl() method of the screen to find our
// ProgressbarControl using the id “my-progress” as the reference
// and our ProgressbarControl class as the second parameter for the
// method so that we don’t need any casts.
ProgressBar progressbar = screen.findControl(“my-progress”, ProgressBar.class);
// use the setProgress() method to set the progress to 90%
progressbar.setProgress((float)(index/max));
}
…
[/java]
Its a bit complicated because when you initialize the application the gui is not updated – the update loop is not yet running :). So the solution would be to have a small initialization and then doing all loading etc. after the gui has been loaded without blocking the update loop. Models for example could be loaded on a separate thread (but have to be added to the scene on the OpenGL thread!!!) or you simply load a model and let a frame pass (load model in next update call).
I did it:
[java]
public void update(){
super.update();
if(!started && loading.isRunning()){
initGame();
started=true;
}
// do some animation
float tpf = timer.getTimePerFrame();
stateManager.update(tpf);
stateManager.render(renderManager);
// render the viewports
renderManager.render(tpf);
}
[/java]
I can see gui while loading, I can’t see updates on it.
On state with models to load I do:
[java]
…
app.enqueue(new LoadingTask(loading,
“Building model”));
app.update();
…
[/java]
where LoadingTask is a class:
[java]
public class LoadingTask implements Callable {
private final LoadingNodeState loading;
private String status;
private float progress=0;
public LoadingTask(LoadingNodeState loading,String status) {
this.loading = loading;
this.status=status;
}
public Void call() throws Exception {
//Thread.sleep(100);
progress=loading.setIndex(1+progress, status);
System.out.println(status+"="+progress);
if (progress>=100){
loading.setActive(false);
}
//if (loading.) {
//GameTaskQueueManager.getManager().update(new LoadingTask(loading, status));
//}
return null;
}
}
[/java]