FengGUI in-game settings

Hi guys,



is there an example on how to use FengGUI in a game menu to specify the settings of a game: resolution, depth, fullscreen, etc?

It doesn't seem (to me) very straight forward to accomplish.



Core-dump, do you plan on adding this feature to Stardust so I can leech off your work once again  :smiley:



thanks


no I'm currently not working on it, but i gladly accept contributions :wink:



I guess you just create dropdown lists and checkbuttons etc, you can look in the default settings panel on how to get the valid values.

The apply button would reinit or reset the display.

I never tried to recreate the display while the application is running, so i don't know what problems there could be.

FengGui itself is not very trivial, imo. But once you get it running and sorta figured out its really great. Just use combo boxes and check boxes, as core dump suggested. You can pull apart the settings dialog of the tests to get all your values.

Thanks guys.

I think I should be able more or less to get the gui items like you suggested. I am more worried about saving the settings in a properties file and applying them while the application is running. I will look at LWJGLPropertiesDialog and PropertiesIO on how to do the saving, but I have no idea how to recreate the display.

There is a class TestSwingSettingsEditor using GameSettingPanel but doesn't seem to do much. You can select the settings but you can't apply them? I looked at the code and I can't see where the settings would be applied to the display… Maybe I am missing something? (this is in jme 1 by the way)

I can't comment on FengGUI cos I have never used it.

Changing graphics settings in game is something I found surprisingly painless, though.

I too trawled through LWJGL code looking at how the properties box worked, before deciding that was a complete waste of time (might not even be using LWJGL!).



I just invoke reinit() when apply is pressed.



reinit does something like this:



display.recreateWindow(width, height, BitsPerPixel, Refresh, fullscreen);

cam.setFrustumPerspective(45.0f,  width / height(), 1, 1000);

cam.update();



And that's it.

Hmm, indeed. It does work just like you said. Thanks a lot!

Spoke too fast I guess. It hangs when I try to resize the window when I use jmedesktop.

Alric, if you don't use FengGUI, what do you use? JMEDesktop?

I modified the TestJMEDesktop class to illustrate.

Any insight on this?



thanks a lot



package jmetest.awt.swingui;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.SwingUtilities;
import com.jme.app.AbstractGame;
import com.jme.app.SimpleGame;
import com.jme.input.InputHandler;
import com.jme.input.KeyboardLookHandler;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.SceneElement;
import com.jme.scene.state.LightState;
import com.jme.system.DisplaySystem;
import com.jmex.awt.swingui.JMEDesktop;
import com.jme.input.MouseInput;
/**
 * Example for using Swing within a jME game: Some frames, buttons and textfields are shown above
 * and on a spinning box. See {@link HelloJMEDesktop} for a shorter example.
 *
 * @see com.jmex.awt.swingui.JMEDesktop
 */
public class TestJMEDesktop extends SimpleGame {
    private static final Logger logger = Logger.getLogger(TestJMEDesktop.class
            .getName());
   
    private JMEDesktop jmeDesktop;
    private Node desktopNode;
    private KeyboardLookHandler lookHandler;

    public TestJMEDesktop() {
    }

    protected void simpleUpdate() {
        if ( jmeDesktop.getFocusOwner() == null ) {
            lookHandler.setEnabled( true );
        } else {
            lookHandler.setEnabled( false );
        }
    }

    public static void main( String[] args ) throws Exception {
        TestJMEDesktop testJMEDesktop = new TestJMEDesktop();
        testJMEDesktop.setDialogBehaviour( AbstractGame.ALWAYS_SHOW_PROPS_DIALOG );
        testJMEDesktop.start();
    }

    /**
     * Called near end of initGame(). Must be defined by derived classes.
     */
    protected void simpleInitGame() {
        display.setTitle( "jME-Desktop test" );
        display.getRenderer().setBackgroundColor( ColorRGBA.blue.clone() );

        // move the 'default' keys (debug normals, toggle lighting, etc.) to a separated input handler
        InputHandler handlerForDefaultKeyActions = input;
        // remove the first person nested handlers
        handlerForDefaultKeyActions.removeAllFromAttachedHandlers();
        // create a new handler for our input
        input = new InputHandler();
        // add the default handler as a child
        input.addToAttachedHandlers( handlerForDefaultKeyActions );
        // create another look handler
        lookHandler = new KeyboardLookHandler( cam, 50, 1 );
        // and nest it
        input.addToAttachedHandlers( lookHandler );

        jmeDesktop = new JMEDesktop( "test internalFrame" );
        jmeDesktop.setup( display.getWidth(), display.getHeight(), false, input );
        jmeDesktop.setLightCombineMode( LightState.OFF );
        desktopNode = new Node( "desktop node" );
        desktopNode.attachChild( jmeDesktop );
        rootNode.attachChild( desktopNode );
        rootNode.setCullMode( SceneElement.CULL_NEVER );
 

        fullScreen();

        jmeDesktop.getJDesktop().setBackground( new Color( 1, 1, 1, 0.2f ) );

        try {
            SwingUtilities.invokeAndWait( new Runnable() {
                public void run() {
                    // Only access the Swing UI from the Swing event dispatch thread!
                    // See SwingUtilities.invokeLater()
                    // and http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html for details.
                    createSwingStuff();
                }
            } );
        } catch ( InterruptedException e ) {
            // ok - just leave
            return;
        } catch ( InvocationTargetException e ) {
            throw new RuntimeException( e );
        }
        MouseInput.get().setCursorVisible( true );
    }
   
    private void fullScreen() {
        final DisplaySystem display = DisplaySystem.getDisplaySystem();

        desktopNode.getLocalRotation().set( 0, 0, 0, 1 );
        desktopNode.getLocalTranslation().set( display.getWidth() / 2, display.getHeight() / 2, 0 );
        desktopNode.getLocalScale().set( 1, 1, 1 );
        desktopNode.setRenderQueueMode( Renderer.QUEUE_ORTHO );
        desktopNode.setCullMode( SceneElement.CULL_NEVER );
    }

    protected void createSwingStuff() {
        final JDesktopPane desktopPane = jmeDesktop.getJDesktop();
        desktopPane.removeAll();

        final JButton resize = new JButton( "resize" );
        resize.setLocation( 300, 100 );
        resize.setSize( resize.getPreferredSize() );
        desktopPane.add( resize );
        resize.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
               display.recreateWindow(800,600,24,60,false);
            }
        } );

        desktopPane.repaint();
        desktopPane.revalidate();
    }

    protected void cleanup() {
        if ( jmeDesktop != null ) {
            jmeDesktop.dispose();
        }
        super.cleanup();
    }
}

Well I don't use JMEDesktop either so I'm no expert there (I wrote a very simple UI system from scratch using ortho quads). But I think your problem is that you're trying to call recreate windo from an actionListener.



I tinkered with your code, and just setting a flag from the actionListener then doing the recreateWindow in the main game loop seems to solve the problem.  Not saying it's the best way to do it just demonstrates that moving the recreateWindow back into your main code fixes the lockup:



public class TestJMEDesktop extends SimpleGame {
    private static final Logger logger = Logger.getLogger(TestJMEDesktop.class
            .getName());
   
    private JMEDesktop jmeDesktop;
    private Node desktopNode;
    private KeyboardLookHandler lookHandler;
    private boolean flag_resize = false;

    public TestJMEDesktop() {
    }

    protected void simpleUpdate() {
        if ( jmeDesktop.getFocusOwner() == null ) {
            lookHandler.setEnabled( true );
        } else {
            lookHandler.setEnabled( false );
        }
        if(flag_resize) {
           flag_resize = false;
           try{
               display.recreateWindow(800,600,24,60,false);
            } catch (JmeException err) {
               err.printStackTrace();
               System.exit(1);
            }
        }
    }

    public static void main( String[] args ) throws Exception {
        TestJMEDesktop testJMEDesktop = new TestJMEDesktop();
        testJMEDesktop.setDialogBehaviour( AbstractGame.ALWAYS_SHOW_PROPS_DIALOG );
        testJMEDesktop.start();
    }

    /**
     * Called near end of initGame(). Must be defined by derived classes.
     */
    protected void simpleInitGame() {
        display.setTitle( "jME-Desktop test" );
        display.getRenderer().setBackgroundColor( ColorRGBA.blue.clone() );

        // move the 'default' keys (debug normals, toggle lighting, etc.) to a separated input handler
        InputHandler handlerForDefaultKeyActions = input;
        // remove the first person nested handlers
        handlerForDefaultKeyActions.removeAllFromAttachedHandlers();
        // create a new handler for our input
        input = new InputHandler();
        // add the default handler as a child
        input.addToAttachedHandlers( handlerForDefaultKeyActions );
        // create another look handler
        lookHandler = new KeyboardLookHandler( cam, 50, 1 );
        // and nest it
        input.addToAttachedHandlers( lookHandler );

        jmeDesktop = new JMEDesktop( "test internalFrame" );
        jmeDesktop.setup( display.getWidth(), display.getHeight(), false, input );
        jmeDesktop.setLightCombineMode( LightState.OFF );
        desktopNode = new Node( "desktop node" );
        desktopNode.attachChild( jmeDesktop );
        rootNode.attachChild( desktopNode );
        rootNode.setCullMode( SceneElement.CULL_NEVER );
 

        fullScreen();

        jmeDesktop.getJDesktop().setBackground( new Color( 1, 1, 1, 0.2f ) );

        try {
            SwingUtilities.invokeAndWait( new Runnable() {
                public void run() {
                    // Only access the Swing UI from the Swing event dispatch thread!
                    // See SwingUtilities.invokeLater()
                    // and http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html for details.
                    createSwingStuff();
                }
            } );
        } catch ( InterruptedException e ) {
            // ok - just leave
            return;
        } catch ( InvocationTargetException e ) {
            throw new RuntimeException( e );
        }
        MouseInput.get().setCursorVisible( true );
    }
   
    private void fullScreen() {
        final DisplaySystem display = DisplaySystem.getDisplaySystem();

        desktopNode.getLocalRotation().set( 0, 0, 0, 1 );
        desktopNode.getLocalTranslation().set( display.getWidth() / 2, display.getHeight() / 2, 0 );
        desktopNode.getLocalScale().set( 1, 1, 1 );
        desktopNode.setRenderQueueMode( Renderer.QUEUE_ORTHO );
        desktopNode.setCullMode( SceneElement.CULL_NEVER );
    }

    protected void createSwingStuff() {
        final JDesktopPane desktopPane = jmeDesktop.getJDesktop();
        desktopPane.removeAll();

        final JButton resize = new JButton( "resize" );
        resize.setLocation( 300, 100 );
        resize.setSize( resize.getPreferredSize() );
        desktopPane.add( resize );
        resize.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
               flag_resize = true;
            }
        } );

        desktopPane.repaint();
        desktopPane.revalidate();
    }

    protected void cleanup() {
        if ( jmeDesktop != null ) {
            jmeDesktop.dispose();
        }
        super.cleanup();
    }
}

You may want to move to jME 2.0, there's a chance this problem (and others) will disappear :wink:

Will do. Thanks a million guys. Alric's suggestion works fine.