GBUI checkin for upcoming release


SVN is updated with the latest changes on the trunk tip.

Updating to include status of things on this list:

DONE – 1) UserResponse Enum type change to be an Enum only – code changes as well in other places

DONE - still needs fixed test case – 2) Drag N Drop – checked in from the external donations.  Tests to come, currently those tests are broken because of some path changes that need to be made.

DONE – 3) BGeomView – camera.update() this has been uncommented and the test is fixed as well

DONE - still need to fix test – 4) Border style (BSS) additions -  A patch was submitted to add four new styles to BSS (border-left, border-right, border-top, border-bottom)

This will be in the next release – 5) I also want to add to this list one more thing I’m working on for the next release if I can get it done.  I’ve been asked by many about CSS adherence.  While BSS is it’s own language and a slimmed down version of CSS, I’m working on a CSS parser that will take CSS 1, 2 or 2.1 and give back the existing GBUI object representation.  The work is coming along nicely.  BSS will be supported as long as it’s there, I would say, but I’m going to add that you would now be able to write BSS in CSS annotation and get correct GBUI objects.  And not necessarily the slimmed down BSS versions.  Obviously CSS2 and 2.1 have some things that won’t be immediately supported, but I can’t see many that wouldn’t be.  I think this step would narrow the gap between thinking CSS styles will work or the syntax would work and finding out that everything blows up and then getting frustrated when you (as a Swing Developer) get annoyed that you have to deal with some crummy html construct :)  In any case, I think I’ll have the first phase of this supporting existing GBUI objects in for the next release.

Still working on it – 6) BEditorPane – multiline editor pane for text from

Still todo – 7) add benchmarks provided by theprism for fengGUI and those matching with BUI

All four of these are checked in to the SVN trunk.

DONE – 8 ) JME 2.0 upgrade completed –

Still working on – 9) Rotation of the Windows and objects in the windows

DONE – I also added Groovy support.  The lib and build.xml files have already been updated to accommodate this change.

The next GBUI release will include all of these changes, the tests and some unit tests.

Is there anything else that isn’t in GBUI that I could try to sneak into the next release?

I’m going to be publishing the BSS stylesheet info after I read mj’s tutorials.

Don’t forget there are wiki’s out there on



? cant get the link to work ?

Good job btw, jme needs its own user controls

Also - have you considered benchmarking it and comparing it to fenggui and jmedesktop

I changed the link… had Groovy on the brain it's hosted at google.

No, I've not considered benchmarking.  Since I didn't create the code, I'm just adding to a new "branch" with the help of those on this list (and lately a lot of help of those on this list) and managing it with Sfera, I'm not doing any benchmarking yet.

This is probably the wrong approach to it, but BUI does what I need, if it doesn't I add to it; thus sprung GBUI.  Others have added to it and now it has more functionality than the samskivert svn version does.  Would I like to do a lot more with it?  Yes.  But, right now, I am barely able to keep up with the code submissions and testing. :smiley:

In addition, before I get "distracted" with benchmarking, I owe several tutorials on BSS and GBUI in addition to that which mjsimpson has done.

One other thing that the code is lacking is unit testing.  I want to get that up to par as well as the code coverage to see what's lacking in the code.  There's a lot of work that could be done there, and I don't want that to be the primary focus, but I do want to ensure it's locked in so that we can at least see some of the bottlenecks through the coverage before running benchmarks.

If you can think of any benchmark tests that would be prime and quick to inject I'd be more than happy to implement them and push them out to the trunk tip.  I just don't want to make the time I guess.

I still feel wierd submitting this code since it's not mine to begin with, but Sfera and I have done a lot of work to it and there have been some major additions by some users lately that are, well, superb.  Those I suppose make it it's own project, but I don't want to lose sight of the fact that it wouldn't exist if it weren't for Three Rings and their work.

What would you test in the benchmarks to begin with?


The benchmark really needs to be simple.

How about one main container with a child container that holds a textfield and a button.

The benchmark will catch the rendering cycle times within the update of jme. Will also need something in 3d in view behind that needs some cpu power - perhaps the water demo ??

Ill do the fenggui and jme desktop if you can do the gbui.

The fenggui is below - decided against jmedesktop as its will be slower

import org.fenggui.Button;
import org.fenggui.Container;
import org.fenggui.Display;
import org.fenggui.Label;
import org.fenggui.TextEditor;
import org.fenggui.border.PlainBorder;
import org.fenggui.layout.GridLayout;

import com.jme.input.InputHandler;
import com.jme.scene.Spatial;
import com.jme.system.DisplaySystem;

public class GuiManager {
   public Display fengDis;
   InputHandler fenInput;
   FenGuiSpatial fenSpatial;
   final int centreOfScreenX;
   final int centreOfScreenY;   
   Container centre;
   public static GuiManager getGuiManager() {
      if(instance == null) instance = new GuiManager();
      return instance;
   private static GuiManager instance;
   private GuiManager() {
      fengDis = new Display(new org.fenggui.render.lwjgl.LWJGLBinding());
      fenInput = new FengJMEInputHandler(fengDis);
      fenSpatial = new FenGuiSpatial(fengDis);
      centreOfScreenX = DisplaySystem.getDisplaySystem().getWidth() / 2;
      centreOfScreenY = DisplaySystem.getDisplaySystem().getHeight() / 2;
      centre = new Container(new GridLayout(1,1));
   public void bindInInputHandler(InputHandler input) {
   public Spatial getFenSpatial() {      
      return fenSpatial;
   public Display getDisplay() {
      return fengDis;
   public void setup() {      
      Container child = new Container(new GridLayout(1, 3));
      Label l = new Label("Benchmark");
      PlainBorder b = new PlainBorder(2,2,2,2);
      l.setSize(50, 50);
      Button dummyButton = new Button("Button");
      TextEditor te = new TextEditor();
      te.setText("Im an editor");
   public void centreOnScreen(Container window) {
      window.setX(centreOfScreenX - (window.getWidth()/2));
      window.setY(centreOfScreenY - (window.getHeight()/2));      
   public int getCentreOfScreenX() {
      return centreOfScreenX;      
   public int getCentreOfScreenY() {
      return centreOfScreenY;      
   public InputHandler getFenInput() {
      return fenInput;
   public void removeAndClean(Container c) {
      if(c != null) {


and the test class

import java.util.logging.Level;
import java.util.logging.Logger;

import jmetest.effects.TestProjectedTexture;

import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.renderer.pass.RenderPass;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.state.CullState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jme.util.export.binary.BinaryImporter;
import com.jme.util.resource.ResourceLocatorTool;
import com.jme.util.resource.SimpleResourceLocator;
import com.jmex.effects.ProjectedTextureUtil;
import com.jmex.model.converters.MilkToJme;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.ImageBasedHeightMap;
import com.jmex.terrain.util.ProceduralSplatTextureGenerator;

public class BenchmarkFenggui extends SimpleGame{
       private static final Logger logger = Logger
   private TerrainPage terrain;
   protected BasicPassManager pManager;
   private Texture projectedTexture1;
   private Node projectorModel1;
   private Vector3f projectorAim1 = new Vector3f();
   //private Texture projectedTexture2;
   //private Box projectorModel2;
   //private Vector3f projectorAim2 = new Vector3f();
   public static void main( String[] args ) {
      BenchmarkFenggui app = new BenchmarkFenggui();
      app.setDialogBehaviour( ALWAYS_SHOW_PROPS_DIALOG );
    protected void simpleRender() {
   protected void simpleUpdate() {
      //make a funny projector animation
      projectorModel1.getLocalTranslation().set( FastMath.sin( timer.getTimeInSeconds() ) * (FastMath.sin( timer.getTimeInSeconds() * 0.7f ) * 15.0f + 20.0f),
                                      FastMath.sin( timer.getTimeInSeconds() * 0.5f ) * 10.0f + 20.0f,
                                      FastMath.cos( timer.getTimeInSeconds() * 1.2f ) * (FastMath.sin( timer.getTimeInSeconds() ) * 15.0f + 20.0f) );
      projectorAim1.set( FastMath.sin( timer.getTimeInSeconds() * 0.8f - FastMath.PI ) * (FastMath.sin( timer.getTimeInSeconds() * 0.5f - FastMath.PI ) * 10.0f + 10.0f),
                    FastMath.cos( timer.getTimeInSeconds() * 0.6f - FastMath.PI ) * (FastMath.sin( timer.getTimeInSeconds() * 0.3f - FastMath.PI ) * 10.0f + 10.0f) );
      projectorModel1.lookAt( projectorAim1, Vector3f.UNIT_Y );
      projectorModel1.updateGeometricState( 0.0f, true );
      //update texture matrix
      ProjectedTextureUtil.updateProjectedTexture( projectedTexture1, 30.0f, 1.5f, 1.0f, 1000.0f, projectorModel1.getLocalTranslation(), projectorAim1, Vector3f.UNIT_Y );
      //make a second funny projector animation
      //projectorModel2.getLocalTranslation().set( FastMath.sin( timer.getTimeInSeconds() - FastMath.PI ) * (FastMath.sin( timer.getTimeInSeconds() * 1.1f ) * 15.0f + 20.0f),
      //                                FastMath.sin( timer.getTimeInSeconds() * 0.7f - FastMath.PI ) * 10.0f + 30.0f,
      //                                FastMath.cos( timer.getTimeInSeconds() * 0.4f - FastMath.PI ) * (FastMath.sin( timer.getTimeInSeconds() ) * 15.0f + 20.0f) );
      //projectorAim2.set( FastMath.sin( timer.getTimeInSeconds() * 0.4f ) * (FastMath.sin( timer.getTimeInSeconds() * 0.7f ) * 10.0f + 10.0f),
      //              0.0f,
      //              FastMath.cos( timer.getTimeInSeconds() * 0.3f ) * (FastMath.sin( timer.getTimeInSeconds() * 0.8f ) * 10.0f + 10.0f) );
      //projectorModel2.lookAt( projectorAim2, Vector3f.UNIT_Y );
      //projectorModel2.updateGeometricState( 0.0f, true );
      //update texture matrix
      //ProjectedTextureUtil.updateProjectedTexture( projectedTexture2, 20.0f, 1.0f, 1.0f, 1000.0f, projectorModel2.getLocalTranslation(), projectorAim2, Vector3f.UNIT_Y );
   protected void simpleInitGame() {
      try {
        try {
                    new SimpleResourceLocator(TestProjectedTexture.class
        } catch (URISyntaxException e1) {
            logger.log(Level.WARNING, "unable to setup texture directory.", e1);
        pManager = new BasicPassManager();
        display.setTitle( "Projected Texture Test" );
         cam.getLocation().set( new Vector3f( 50, 50, 0 ) );
         cam.lookAt( new Vector3f(), Vector3f.UNIT_Y );
         CullState cs = display.getRenderer().createCullState();
         cs.setCullMode( CullState.CS_BACK );
         cs.setEnabled( true );
         //load projector model
         MilkToJme converter2 = new MilkToJme();
         URL MSFile2 = TestProjectedTexture.class.getClassLoader().getResource(
               "jmetest/data/model/msascii/camera.ms3d" );
         ByteArrayOutputStream BO2 = new ByteArrayOutputStream();
         try {
            converter2.convert( MSFile2.openStream(), BO2 );
         } catch( IOException e ) {
   "IO problem writting the file!!!" );
   e.getMessage() );
            System.exit( 0 );
         projectorModel1 = null;
         try {
            projectorModel1 = (Node) BinaryImporter.getInstance().load( new ByteArrayInputStream( BO2.toByteArray() ) );
         } catch( IOException e ) {
   "darn exceptions:" + e.getMessage() );
         rootNode.attachChild( projectorModel1 );
         //projectorModel2 = new Box( "Projector2", new Vector3f(), 1, 1, 2 );
         //projectorModel2.setModelBound( new BoundingBox() );
         TextureState ts = display.getRenderer().createTextureState();
         Texture t0 = TextureManager.loadTexture(
                     "jmetest/data/texture/Detail.jpg" ),
               Texture.FM_LINEAR );
         t0.setWrap( Texture.WM_WRAP_S_WRAP_T );
         ts.setTexture( t0, 0 );
      //   projectorModel2.setRenderState( ts );
         //rootNode.attachChild( projectorModel2 );
         //create terrain
         URL grayScale = TestProjectedTexture.class.getClassLoader().getResource( "jmetest/data/texture/terrain.png" );
         ImageBasedHeightMap heightMap = new ImageBasedHeightMap( new javax.swing.ImageIcon( grayScale ).getImage() );
         Vector3f terrainScale = new Vector3f( .5f, .05f, .5f );
         terrain = new TerrainPage( "image icon", 33, (heightMap.getSize()) + 1, terrainScale, heightMap.getHeightMap(), false );
         terrain.setDetailTexture( 1, 16 );
         terrain.setModelBound( new BoundingBox() );
         terrain.setLocalTranslation( new Vector3f( 0, 0, 0 ) );
         rootNode.attachChild( terrain );
         rootNode.setRenderState( cs );
         ProceduralSplatTextureGenerator pst = new ProceduralSplatTextureGenerator( heightMap );
         pst.addTexture( new javax.swing.ImageIcon( TestProjectedTexture.class.getClassLoader().getResource(
               "jmetest/data/texture/grassb.png" ) ), -128, 0, 128 );
         pst.addTexture( new javax.swing.ImageIcon( TestProjectedTexture.class.getClassLoader().getResource(
               "jmetest/data/texture/dirt.jpg" ) ), 0, 128, 255 );
         pst.addTexture( new javax.swing.ImageIcon( TestProjectedTexture.class.getClassLoader().getResource(
               "jmetest/data/texture/highest.jpg" ) ), 128, 255, 384 );
         pst.addSplatTexture( new javax.swing.ImageIcon( TestProjectedTexture.class.getClassLoader().getResource(
               "jmetest/data/texture/terrainTex.png" ) ), new javax.swing.ImageIcon( TestProjectedTexture.class.getClassLoader().getResource(
               "jmetest/data/texture/water.png" ) ) );
         pst.createTexture( 512 );
         //ts = display.getRenderer().createTextureState();
         //ts.setEnabled( true );
         Texture t1 = TextureManager.loadTexture( pst.getImageIcon().getImage(), Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR, true );
         ts.setTexture( t1, 0 );
         t1.setApply( Texture.AM_COMBINE );
         t1.setCombineFuncRGB( Texture.ACF_MODULATE );
         t1.setCombineSrc0RGB( Texture.ACS_TEXTURE );
         t1.setCombineOp0RGB( Texture.ACO_SRC_COLOR );
         t1.setCombineSrc1RGB( Texture.ACS_PRIMARY_COLOR );
         t1.setCombineOp1RGB( Texture.ACO_SRC_COLOR );
         t1.setCombineScaleRGB( 1.0f );
         //create a texture to use for projection
         projectedTexture1 = TextureManager.loadTexture( TestProjectedTexture.class.getClassLoader().getResource(
               "jmetest/data/images/Monkey.png" ), Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR );
         ts.setTexture( projectedTexture1, 1 );
         //this is were we set the texture up for projection
         ProjectedTextureUtil.setupProjectedTexture( projectedTexture1, Texture.WM_BCLAMP_S_BCLAMP_T, Texture.ACF_ADD );
         //create another texture to use for projection
         //projectedTexture2 = TextureManager.loadTexture( TestProjectedTexture.class.getClassLoader().getResource(
         //      "jmetest/data/texture/halo.jpg" ), Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR );
      //   ts.setTexture( projectedTexture2, 2 );
         //this is were we set the texture up for projection
      //   ProjectedTextureUtil.setupProjectedTexture( projectedTexture2, Texture.WM_BCLAMP_S_BCLAMP_T, Texture.ACF_ADD );
         terrain.setRenderState( ts );
         Box dummyBox = new Box( "Dummybox", new Vector3f(), 2, 12, 3 );
         dummyBox.setModelBound( new BoundingBox() );
         ts = display.getRenderer().createTextureState();
         t0 = TextureManager.loadTexture(
                     "jmetest/data/texture/wall.jpg" ),
               Texture.FM_LINEAR );
         t0.setWrap( Texture.WM_WRAP_S_WRAP_T );
         ts.setTexture( t0, 0 );
         //ts.setTexture( projectedTexture1, 1 );
         //ts.setTexture( projectedTexture2, 2 );
         dummyBox.setRenderState( ts );
         rootNode.attachChild( dummyBox );
         rootNode.setRenderQueueMode( com.jme.renderer.Renderer.QUEUE_OPAQUE );
         fpsNode.setRenderQueueMode( com.jme.renderer.Renderer.QUEUE_OPAQUE );
         GuiManager fend = GuiManager.getGuiManager();
      } catch( Exception e ) {
         logger.logp(Level.SEVERE, this.getClass().toString(),
                "simpleInitGame()", "Exception", e);
    private void setupUserDisplay() {
       FenGuiSpatial fenDisplay = (FenGuiSpatial)GuiManager.getGuiManager().getFenSpatial();
          RenderPass fenPass = new RenderPass();
         fenPass.add( fenDisplay);
         pManager.add( fenPass );

Awesome!  I'll plug that in for BUI as well.  Thx theprism!

I'm actually trying to figure out which to use for a UI for ProxyWars at the moment.  Swing, FenGUI, or gBUI - but I am concerned about how easy/difficult it will be overall.  I'd really like to see a test with jMEDesktop since I am used to using swing, but I've heard its horribly slow - I guess I'd really like to know just how bad it is before I decide to dump it.  It seems like jmedesktop would be much easier to use than FenGUI - so many threads on how to use that it's frightening to a newbie.

Though now that I see gBUI will have Drag n' Drop, and use CSS… I am quite interested in checking it out.  Still would like to see what's fastest though, or at least how comparable they all are.

I haven't seen any metrics comparing any of them together.  I have a set of metrics to compare fenggui to gbui, however, they have not been implemented in GBUI to get a feel for the run.

I can't speak to JMEDesktop, but the last time I ran fenggui it was comparable to gbui.  I don't know that I've ever had any of them run slow.

Mostly it comes down to preference of the programming interface.  If you have any problems with any of the gui choices you can certainly ask questions on these forums.  I try to answer questions for GBUI fairly quickly.  As well, if there's something you need I try to work on it as soon as I can.

I would say that the best way to get started is to check out the tests that are in the GBUI trunk.  They should be called examples or functional or integration tests… in any case, as well check out some fenggui and jmedesktop examples and see which one fits your style of programming a little better.


I tried to follow the guide to setup gBUI in eclipse, but I can't seem to get it going right.

I can't seem to get it to build right. :/    I've linked it to my properly building jME2 project and to the lwjgl jar/native libs as mentioned in the guide.  (The linux natives, since I am running Ubuntu.)  But I still see lots of red X's in the package explorer.

The only big difference I did was that I used Eclipe's built in subversion to download the trunk into a new java project- using the Java Project Wizard.  It doesn't seem to make sense that it wouldn't work though.

Sorry for the delay; been off the net changing continents and just getting back online.

I  don't feel like I've totally gotten Eclipse figured out (and I'm not using Linux), but I have seen it react negatively to what I consider minor differences in project setup.  If you can provide a few of the error messages, maybe they'll be something I recognize.

Description   Resource   Path   Location   Type
BStyleSheet cannot be resolved   gbui/src/java/com/jmex/bui/provider   line 41   Java Problem
BStyleSheet cannot be resolved   gbui/src/java/com/jmex/bui/provider   line 43   Java Problem
BStyleSheet cannot be resolved to a type   gbui/src/java/com/jmex/bui   line 41   Java Problem
BStyleSheet cannot be resolved to a type   gbui/src/java/com/jmex/bui   line 217   Java Problem
The import com.jmex.bui.BStyleSheet cannot be resolved   gbui/src/java/com/jmex/bui/headlessWindows   line 23   Java Problem
The import com.jmex.bui.BStyleSheet cannot be resolved   gbui/src/java/com/jmex/bui/bss   line 23   Java Problem
The method configureStyle(BStyleSheet) of type BButton must override or implement a supertype method   gbui/src/java/com/jmex/bui   line 217   Java Problem
The method configureStyle(BStyleSheet) of type BCheckBox must override or implement a supertype method   gbui/src/java/com/jmex/bui   line 41   Java Problem

There are a couple other error types as well, but that should be a enough I'd think/hope. The elipses are just a spacer since there were usually several more of the same error types.  On a side note, I also did try the guide on the actual google code page which is a little more detailed, but still ended up with the same result.

This looks like the BStyleSheet.groovy is missing from the src path.

Are you fully checked out from the trunk tip and using JME 2?


yes on jme2.

I assume yes on the trunk.

My resource URL under project> properties> SVN info is:

ok, and have you compiled using Ant, or are you compiling via the IDE?

If it's any help, I went through the eclipse setup 2 days ago. I had the same problem, even after trying all the suggestions. What finally did it was locating the *.groovy files (only in 2 folders) - right click and select 'Compile Groovy File'. Do this for the 5 groovy files and it should rebuild the project nicely. I had to do this by hand several times until this morning. When I started eclipse it announced that it was rebuilding groovy projects all by itself!

Kropotkin said:

If it's any help, I went through the eclipse setup 2 days ago. I had the same problem, even after trying all the suggestions. What finally did it was locating the *.groovy files (only in 2 folders) - right click and select 'Compile Groovy File'. Do this for the 5 groovy files and it should rebuild the project nicely. I had to do this by hand several times until this morning. When I started eclipse it announced that it was rebuilding groovy projects all by itself!

Fascinating!  I'll add that to the wiki.  I don't build via my IDE (even though it's IntelliJ,) I build with ant through IntelliJ or ant on the command line.  I recommend compiling via ant if at all possible.  For IntelliJ users that have multiple modules set up like I do and each has a different compilation path, it saves me a lot of headaches.