Please advise me with GUI

I have gone through the GUI tutorials in the Wiki, which was very informative but seemed a bit old and maybe too simple. Also checked out the sourcecode of Stardust (nice space-shooter, do not remember who's code it is) and that was similarly interesting, but I think I remember from somewhere that it was just a test project for the author. Other src-s that I have got my hands on have seemed more hectic and I have not dared use them as guide for my own GUI. There are some particular things that I am wondering about…



Where should I build and update the GUI? It seems reasonable for me to create a separate gamestate or similar for it. However in the Stardust project the author had just created a class with a rootNode and built the Hud there, not extending anything. Is there any benefits to doing it this way or would a gamestate be a better idea?



Also can you confirm that the best way of going about with the gui is drawing it all on a texture and then displaying it on a quad in ORTHO mode? Would this cause me any problems if I wanted to include some pre-made widgets from fengGUI or the built in Swing? What would be the best structure in that case? I have some related guides, but many points still elude me. Perhaps there is a better method?



In any case… any and all advice on GUI 'Best Practice' would be VERY welcome from you pro-s who have tried these things out already. I realize that the answer may depend on the type of game that is developed, so I'll say it is a turn based strategy game - several screens and overlays. There is also a real-time combat part that would be more resource intensive.



Thank you and all the best to you

I am wondering now why I put this thread in the Graphics section when we have a GUI one :slight_smile: Move it please if you do not mind.



Also I have seen suggestions that if one wants FengGUI to behave as expected (especialy in relation to transparency and whatnot), one should not use StandardGame but make a custom game using SimplePassGame. Last I heard about it was from February, so I am also wondering if that holds still true, or FengGUI and jME somehow integrated further now?

Here are my beliefs about GUIs and jME.

(There might be severe misunderstandings in there, and I don't have prove for any of this, hence I thought "beliefs" would be the more appropriate term than "knowledge" for this…)


  • JMEDesktop works great for almost all NVidia cards on Win and Linux, anything else can give performance trouble or even not run at all

  • JMEDesktop is maintained by irrisor, who doesn't have tons of spare time to fix every bug right now, but tends to at least advise on how you could go about fixing a specific problem yourself.

  • JMEDesktop uses swing for rendering, which is just awesome!

  • FengGUI works with a wider range of system configurations

  • Making your own custom UI look is way easier with FengGUI than with swing

  • FengGUI uses it's own interface to the underlying OpenGL bindings (aka lwjgl) - that confuses jME's state records and requires a few workarounds to get everything right

  • FengGUI renders directly to OpenGL, which is faster than JMEDesktop if you need to update your GUI often

This topic keeps appearing every once in a while.



I am no way a pro, but here are my two cents. Also I love the way you presented the topic.



Performance wise, JMEDesktop might not be the best option. FengGUI in the other hand is probably the fastest way to go.



Also, rendering everything in a texture and rendering it in ortho mode is not really fast and may also give you problems with resolution.



I read somewhere that JME 2 would provide some basic GUI support. Even if it is basic, for non GUI based games that would be great, as it would probably be the easiest way to go and would probably avoid problems with specific hardware and integration problems.



By the way, I use a different gamestate for GUI and Console. Their render method is called after the "main scene gamestate"  render method, and there I render my "GUI rootNode" (example below).



I am also facing this, and have tried BUI and FengGUI. I will probably go for FengGUI, but I would like to have that JME GUI support now. I don't have time to design but I would collaborate writing some code if someone wants to tackle this now (just drop me a message in that case).



My Console state looks like this. Look at the last method to see how this renders GUI separately (on top of the scene). I don't know if this is good performance wise:



/**
 * This represents the client console game state. It processes
 * input and draws the console.
 */
public class ConsoleState extends GameStateNode {
   
   private final static Logger logger = Logger.getLogger(ConsoleState.class.toString());
   
   /**
    * The root node which contains the user interface.
    */
   protected Node rootNode;
   
   /**
    * InputText text
    */
   protected Text inputText;
      
   /**
    * BufferText text lines
    */
   protected Text[] bufferText;
   
   /**
    * Constructor
    */
   public ConsoleState() {

      super("ConsoleState");
      initConsole();
      
   }
   
   /**
    * Initializes the console
    */
   public void initConsole() {
      rootNode = new Node();
      rootNode.setRenderQueueMode(Renderer.QUEUE_ORTHO);
      
      DisplaySystem display = DisplaySystem.getDisplaySystem();
      
      AlphaState as = display.getRenderer().createAlphaState();
      as.setBlendEnabled(true);
      as.setSrcFunction(AlphaState.SB_SRC_ALPHA);
      as.setDstFunction(AlphaState.DB_ONE);
      as.setTestEnabled(true);
      as.setTestFunction(AlphaState.TF_GREATER);
      as.setEnabled(true);
      TextureState font = display.getRenderer().createTextureState();
      try {
         font.setTexture(TextureManager.loadTexture(new File("data/font/defaultfont.tga").toURL(),   Texture.MM_LINEAR, Texture.FM_LINEAR));
      } catch (MalformedURLException e) {
         logger.warning ("Could not load font " + e);
      }
      font.setEnabled(true);
      
      float margin = 2;
      
      inputText = new Text("InputText", "");
      float height = (inputText.getHeight() * (System.getSettings().getClient().getConsoleLines() + 1)) + 2;      
      
      inputText.setTextureCombineMode(TextureState.REPLACE);
      Node inputNode = new Node("InputNode");
      inputNode.attachChild(inputText);
      inputNode.setRenderState(font);
      inputNode.setRenderState(as);
      inputNode.updateGeometricState(0.0f, true);
      inputNode.setLocalTranslation(new Vector3f(margin, display.getHeight() - (height) - 1, 0));
      
      // Create the console
      Quad console = new Quad("Console", display.getWidth() - margin * 2, height);
      console.setLocalTranslation(new Vector3f(display.getWidth() / 2, display.getHeight() - (height / 2) - margin, 0));
      console.setDefaultColor(new ColorRGBA(0.1f, 0.5f, 0.3f, 0.7f));
      AlphaState consoleAlphaState = display.getRenderer().createAlphaState();
      consoleAlphaState.setBlendEnabled(true);
      consoleAlphaState.setEnabled(true);
      console.setRenderState(consoleAlphaState);
      console.setLightCombineMode(LightState.OFF);
      console.updateRenderState();
      
    rootNode.attachChild(console);
    rootNode.attachChild(inputNode);
      
   
   
      bufferText = new Text[System.getSettings().getClient().getConsoleLines()];
      for (int i = 0; i < System.getSettings().getClient().getConsoleLines(); i++) {
         bufferText[i] = new Text("BufferText" + i, "");
         bufferText[i].setTextureCombineMode(TextureState.REPLACE);
         bufferText[i].setRandomColors();
         Node bufferNode = new Node("BufferNode" + i);
         bufferNode.attachChild(bufferText[i]);
         bufferNode.setRenderState(font);
         bufferNode.setRenderState(as);
         bufferNode.updateGeometricState(0.0f, true);
         bufferNode.setLocalTranslation(new Vector3f(margin, display.getHeight() - (height) - 1 + (inputText.getHeight() * ( i + 1)), 0));
         rootNode.attachChild(bufferNode);
      }
   
    rootNode.updateRenderState();
    updateBuffer();
   }
   
   /**
    * Redraws the text on the buffer
    */
   public void updateBuffer() {
      int consoleLines = System.getSettings().getClient().getConsoleLines();
      List<String> lines = System.getConsole().getLastLines(consoleLines);
      
      int i = 0;
      for (; ((i < consoleLines) && (i <lines.size())); i++) {
         bufferText[i].print(lines.get(lines.size() - 1 - i));
      }
      for (; i < consoleLines; i++) {
         bufferText[i].print ("");
      }
   }
   
   /**
    * Processes input for the console.
    */
   public void update(float tpf) {      
      inputText.print("> " + System.getConsole().getPrompt());
      rootNode.updateGeometricState(tpf, true);
      // Update child gamestates
      super.update(tpf);
   }

   /**
    * Draws the console.
    */
   public void render(float tpf) {
      DisplaySystem.getDisplaySystem().getRenderer().draw(rootNode);
      super.render (tpf);
   }
   
   
         
}


Thank you for replying. I agree, this topic seems to crop up every now and again and there are several threads one can search for on the forums but as people's methods seem to improve all the time and jME, FengGUI, BUI etc get developed, I believe it is a good idea to go over the best methods every now and again.



Seems like rendering to texture in Ortho mode as suggested in the tutorial in Wiki, is not advised. It did not seem very appealing from the start, considering that it would have to be combined with FengGUI/Swing whatever anyways if one wanted to make use of widgets and not write them himself.



From Hevee's post it seems clear than in order to maximise speed and compatibility, it would be best to use FengGUI. However I am still at a loss as to what would be the best method. As much as I have read and understood, it would be best if the game itself would be a custom game (not StandardGame out of the box) using SimplePassGame and making sure that the GUI components are rendered last in a separate pass. Any further explanations about the tricky parts in this would be very welcome… or quite possible it is clear as water from there on to everyone else :slight_smile:



The part about JME 2 including GUI components is most interesting… especially since according to rumors it should come out somewhere in the beginning of February. Perhaps I should just sit on the GUI part and do some modeling for 2 weeks? Then again, I would not expect it to include something as advanced as FengGUI fully included… so some trickery would still be needed. :slight_smile: Any comments from the devs would be so welcome.

Quick question



When using JME and Fengui, are there any duplicated and expensive opengl calls ( eg gl.loadIndentity() ) made between the two systems in one frame, something which would be defunct if a GUI was built specifically for JME.



If so, I would be happy to do small bits of work to create a JME GUI system. ? Is this going to be included ( in what ever limited form ) as part of the next release…

I am not sure about loadIdentity. In FengGUI code, loadIdentity() is called before displaying components. In the jME/FengGUI example in the Wiki (http://www.jmonkeyengine.com/wiki/doku.php?id=simple_fenggui_jme_app), it is not. I guess it is.



I don't think the incoming release of 2.0 will include this functionality. As far as I know, what is going to be released is the baseline on which 2.0 is going to be built, which probably means some refactoring and maybe few new core functionality… but as you said, developers comments on this would be very welcome.



Wouldn't it be nice:


GuiNode guiNode = new GuiNode();
rootNode().attachChild (guiNode);

GuiButton button = new GuiButton("Press me");
button.setAction ("pressButton");



Something like that. A minimally decent GUI engine involves a lot of work, though.

It is alot of work indeed, but with BUI as a base it shouldnt be so much more work…



One of the main factors would be deciding on the

a) event model

b) layout mechanisms

c) decorators

d) Drag and Drop

e) Text editing ( Document model / StringBuffer )



I think when these factors have been agreed alot of code will quickly be donated by many as and when.


Personally I would encourage UI as an addon much like physics or jgn.  I've spent about 6 of the last 12 months working on our custom UI system at work, so I know writing a complete and powerful UI system is not a quick task.  It would be best served by a dedicated group of people.



And before you ask, I very much doubt our UI code will be donated back to jME because of how tightly it is coupled to several other internal systems.  :confused:

Would you care to join in a wider JME UI project renanse, maybe in a position technical director whereby you dont necesarily code, but give pointers on the architecture of it

I'm always available for my 2 cents as you've no doubt noticed. :slight_smile:

theprism said:

a) event model
b) layout mechanisms
c) decorators
d) Drag and Drop
e) Text editing ( Document model / StringBuffer )

I think when these factors have been agreed alot of code will quickly be donated by many as and when.


Well, some structure needs to be donated first, for others to add. I also agree with renanse that keeping this "out" of jME is probably better and easier to manage.

About the points above, I shouldn't even comment on A and B.

For point C, I truly think that decorating should be almost entirely delegated to user code. No need to fancy xml decoration definition. After all the kind of jME applications that need GUI are usually the only users of their theme. A more complex/versatile decoration scheme could probably be built on top of that. I would, anyway, like to have a couple of out-of-the-box decorations (rounded corners, square corners :D).

I wouldn't even support point D in a basic "GUI for 3D engines" engine. And I didn't understand point E (sorry).

Just my two cents. As I said, I am up to write some components or something given the case.

Good to have you on board Jjmontes



We should maybe start a new thread for this…  also, if anyone is also interested in taking part please say so.



I havent used BUI or SWT, maybe if anyone has any views on either it would be good to hear. Also, if it is possible in adapting/enhancing what has been done on BUI maybe an option. Fear is that Sam Skivert ( three rings ) may have entirely abandoned BUI, but would be nice to find out if we can enhance BUI rather than start from scratch, or at least take BUI as a starting point…



The event model from swing creates quite alot of garbage, but the garbage can be managed with cached events as opposed to creating a new event each time one is needed.



Layouts are a bitch, but are necesary - think gridbaglayout is a bad idea as it really is unexpected on resize. Also, you can get most of what you need with a borderlayout, flow layout and gridlayout. we could probably drop component weighting.



Decorators, a border, insets, padding, ???



Drag and drop - ? enhanced event handling plus cursor interaction ??



Text editing, swing uses a document interface, which is quite good in that you can define your document model to just accept numbers or certain characters - not sure on the garbage of this though.



Im close to wrapping up on the Llama continous terrain, and when that is complete can devote a fair bit of time to this GUI project.

I think BUI is a good library, from what i saw in Bang! Howdy, the GUI is just nice, more than enough to make a good looking game, i havent seen any examples of game using FengGUI, is there any performance issues of using BUI?



I wonder if the Bang! Howdy developer would like to share their knowledge about building GUI in JME…

Im still trying out GBUI for my current game though…

@gr33nl1nk: If you have any questions or run into an issue or something you want isn't there, just let me know and I'll look at it.

@gerbilldrop: can i take a look on how you make the GUI for Dradis? if you dont mind of course :stuck_out_tongue: i want to learn about styling the GUI, looks cool,



and in my game, i want to put something like conversation Dialog as in Zelda game or other adventure RPG, when the player talks to NPC, how to customize the dialogBox so that i can use it for thing like this?

sure thing… PM sent

timo rocks! :smiley: