@bolo said:
Wow. With this GUI, it's very quick and easy to create new stuff. I didn't see anything about tabbed menus (a la Nifty: http://sourceforge.net/apps/mediawiki/nifty-gui/index.php?title=Standard_Controls_Tabs), so I constructed an example tabbed menu system using just a few buttons and panels:
Can’t begin to thank you enough for sharing this! Sooo cool to hear “very quick and easy to create new stuff”! This makes me ultra-happy! Even better with the posted code for others =)
Ya know, I also wanted to mention something that is possible with this library that has been asked about Nifty a few times.
You can move your controls from one screen to the next by grabbing a pointer, unloading the current screen, creating a new screen and using screen.addElement(pointer);
Useful when you don’t want to lose current displayed data… like with chat boxes or consoles, etc
Since my last post, I managed to put this together… Still just a framework/rough draft of my game’s option menu selections. Next step is to hook this into the rest of JME and use the values that are selected. Note that the audio is not mine, just played for something to listen to.
All told, I started looking into this GUI and playing with bits of it last night, created that basic tab menu during my lunch break during the day today, and then took about two or three hours this evening to refactor my game’s code and insert what’s in this video–and frankly I think my coding skills are kind of “meh,” so I bet a lot of people could do better :). Definitely has speed and ease of use going for it!
I’m having trouble removing a Screen from the guiNode. Using guiNode.removeControl(screen) throws a null pointer exception. This appears to be because JME spatials remove controls by calling setSpatial(null), and the way you implemented setSpatial() in your Screen class tries to cast any input to a Node–which throws a NullPointerException.
Here’s the error:
[java]
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
at tonegod.gui.core.Screen.setSpatial(Screen.java:688)
at com.jme3.scene.Spatial.removeControl(Spatial.java:620)
at test.RemoveScreenTest.simpleInitApp(RemoveScreenTest.java:24)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:225)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:207)
at java.lang.Thread.run(Unknown Source)
[/java]
Yes… I’ve been changing all of these to Object incase you wanted to store a reference to… well… whatever! A String is just fine.
I noticed this yesterday (or madjack mentioned it actually). I’ll add this… for now, you can…um… one sec. You can override any of the following methods:
[java]
public void onButtonMouseLeftDown(MouseButtonEvent evt, boolean toggled);
public void onButtonMouseRightDown(MouseButtonEvent evt, boolean toggled);
public void onButtonMouseLeftUp(MouseButtonEvent evt, boolean toggled);
public void onButtonMouseRightUp(MouseButtonEvent evt, boolean toggled);
public void onButtonFocus(MouseMotionEvent evt);
public void onButtonLostFocus(MouseMotionEvent evt);
[/java]
The checkbox is an ButtonAdapter set to toggle-able, with replaced images.
Just updated to latest version and found another error related to adding/removing Screens. This one occurs when you add a screen, remove it, then try to add another one. Something to do with calling app.getAssetManager().unregisterLoader(BitmapFontLoader.class) when building that second screen.
Error:
[java]
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
at com.jme3.asset.ImplHandler.removeLoader(ImplHandler.java:283)
at com.jme3.asset.DesktopAssetManager.unregisterLoader(DesktopAssetManager.java:159)
at tonegod.gui.core.Screen.(Screen.java:171)
at tonegod.gui.core.Screen.(Screen.java:159)
at test.RemoveScreenTest.simpleInitApp(RemoveScreenTest.java:23)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:225)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:207)
at java.lang.Thread.run(Unknown Source)[/java]
@Dardzull
For the time being (and this is temporary while I get some other stuff summed up), Using a single screen is recommended. But! The good news is, hide/show actually manage the rendered elements in your scene. So, when an object is hidden… it is no longer part of the rendered GUI.
I’ll be adding in support for multiple screen soon… I have a couple more things I am squaring away and then this will be top priority.
@haze
I’m converting something that uses an AppState to swap between NiftyGui screens. So in order to minimize reworking what I have, dumping a screen to a node for the moment is the easiest way to go.
@Dardzull said:
Ok, then I will just fall back to using a Node to attach a screen to then (attach/detach) that from the guiNode. That way I can swap as needed. XD
You can do this… however it may create potential problems.
Since hide/show of the base element has the exact same effect as switch out screens in Nifty (except that you still have a pointer to the Element, just no Node attached to the rendered scene), you may want to consider this approach instead.
A couple fundamental differences between this library and Nifty are:
Nesting is not required to position elements… this can throw people at first, due to being used to control inside of panel inside of panel inside of panel to have it show up where you expect it. In this library… you simple create a control and add it to the screen. If you want… you have the choice to either hide it (remove it from the scene), or destroy it (remove it from the scene and remove the child reference.
The next is sort explained in the last example. There is no actual need for multiple screens, as elements are not left if the scene once hidden or removed. This doesn’t stop you from organizing your code in a way that uses… say… AppStates to either hide/show… or create/destroy controls.
Hopefully this will be helpful in picking a way of handling this.
hi, very nice gui lib (Y)
got one problem
created window, when i put Element to it, el isnt dragable, even if i set setIsMovable(true);
code example:
[java]public class Test1 extends SimpleApplication {
public static void main(String[] args) {
Test1 app = new Test1();
app.start();
}
Screen screen;
Window inventory,controls;
boolean inv_visible = true;
static int id = 1;
@Override
public void simpleInitApp() {
assetManager.registerLocator("assets/", FileLocator.class);
getFlyByCamera().setEnabled(false);
mouseInput.setCursorVisible(true);
screen = new Screen(this);
guiNode.addControl(screen);
(inventory = createNewWindow("Inventory")).setIsResizable(false);
controls = createNewWindow("Controls");
ButtonAdapter makeWindow = new ButtonAdapter( screen, "inv_sh", new Vector2f(15, 55) ) {
@Override
public void onButtonMouseLeftUp(MouseButtonEvent evt, boolean toggled) {
if (inv_visible) inventory.hide();
else inventory.show();
inv_visible = !inv_visible;
}
};
makeWindow.setText("Inventory");
controls.addChild(makeWindow);
ButtonAdapter additem = new ButtonAdapter( screen, "add_itm", new Vector2f(15, 105) ) {
@Override
public void onButtonMouseLeftUp(MouseButtonEvent evt, boolean toggled) {
Element el = new Element(
screen,
"item"+id,
new Vector2f(5,5),
new Vector2f(100,100),
new Vector4f(5,5,5,5),
"coin.png"
);
el.setIsMovable(true);
el.setlockToParentBounds(true);
el.setText("item "+id);
inventory.addChild(el);
id++;
}
};
additem.setText("add item");
controls.addChild(additem);
screen.addElement(controls);
screen.addElement(inventory);
}
public final Window createNewWindow(String someWindowTitle) {
Window nWin = new Window(
screen,
new Vector2f( (screen.getWidth()/2)-175, (screen.getHeight()/2)-100 )
);
nWin.setWindowTitle(someWindowTitle);
return nWin;
}
Um… I believe this is related to the ray casting issue not sorting thing properly when the scene graph is updated. To test this (and until I find a proper solution for this would you do me a favor and try adding this to the code where you create the new coin element:
[java]
// right after this line
inventory.addChild(el);
screen.removeElement(inventory);
screen.addElement(inventory);
[/java]
And let me know if this is the issue, if so, I’ll be working on a patch for this problem (though I think it is a JME issue, honestly) that will account for this.