KeyBindingManager Problem

Basically, everything is normally set up, with no problems. When I set the isValidCommand true, it does a command multiple times, and when I set it false it does it 0 times. Can anyone please pinpoint the problem? Since, its my understanding if you set it false, its supposed to do it only once.

All the demos work fine, and I dont have this bug, and if I do commands through editing the ui edit box, it works fine ( even though it uses a diffrent method ).


 
protected void simpleInitGame() {

if (KeyBindingManager
            .getKeyBindingManager()
            .isValidCommand("Enter", false))   
      doCommand(); }
....


...

 

protected void simpleInitGame()
{


      
        KeyBindingManager.getKeyBindingManager().set(
                "Enter",
                KeyInput.KEY_RETURN);
...

}

it looks fine to me. Have you tried putting a System.out.println("") in there to double check when it’s firing off?

The diffrent amount of actions when its true, to my understanding, is ok, since its based on frame rate. What I dont get, is why false wont output anything.



When True:



Firing

Firing

Firing

Firing

Firing

Firing

Firing



Second Time True Try:

Firing

Firing

Firing

Firing

Firing

Firing

Firing

Firing

Firing

Firing

Firing





When False:



Nothing

Can you post your entire program assuming it’s not too long of course.

I have an edited UiEditBox and MainSimpleGame code, but its way to much to post here, and I checked them both, and neither do nothing to create such an error.





public class RenderT
   extends MainSimpleGame
{
    RenderT app;
    private KeyInput key;
protected void simpleUpdate()
    {
    tpf = timer.getTimePerFrame();

    if (KeyBindingManager
            .getKeyBindingManager()
            .isValidCommand("Enter", true))   
    {
       System.out.println("Firing");
    }
       
    if (KeyBindingManager
            .getKeyBindingManager()
            .isValidCommand("Escape", true))
         connection.closeLink();
    }
//


   public static void main(String[] args)
   {
      RenderT app = new RenderT();

app.setDialogBehaviour(SimpleGame.ALWAYS_SHOW_PROPS_DIALOG);
      
app.start();
   }
   //
protected void simpleInitGame()
{
   try {
//
       
      

      
        KeyBindingManager.getKeyBindingManager().set(
                "Enter",
                KeyInput.KEY_RETURN);
        KeyBindingManager.getKeyBindingManager().set(
                "Escape",
                KeyInput.KEY_ESCAPE);
//      snow();
   } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   }
}

Hmm, works just fine here as a sub of SimpleGame. Each press of Enter creates 1 printout of "Firing":


import com.jme.app.SimpleGame;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;

public class RenderT extends SimpleGame {

    protected void simpleUpdate() {
        tpf = timer.getTimePerFrame();

        if (KeyBindingManager.getKeyBindingManager().isValidCommand("Enter",
                false)) {
            System.out.println("Firing");
        }
    }

    public static void main(String[] args) {
        RenderT app = new RenderT();

        app.setDialogBehaviour(SimpleGame.ALWAYS_SHOW_PROPS_DIALOG);

        app.start();
    }

    protected void simpleInitGame() {
        try {

            KeyBindingManager.getKeyBindingManager().set("Enter",
                    KeyInput.KEY_RETURN);
            KeyBindingManager.getKeyBindingManager().set("Escape",
                    KeyInput.KEY_ESCAPE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

If I do it with the normal one, it works. Looks like I have a little work to do on my version, eh? Anyway, I feel pretty stupid for not testing this out before. :frowning:

After some optimizing, I have still failed to pinpoint the problem : Here is my MainSimpleGame (Warning: Long)


public abstract class MainSimpleGame
   extends BaseGame
{
  /** The camera that we see through. */
  protected Camera cam;
  public static String toAdd;
    /** The root of our normal scene graph. */
  protected Node rootNode;
    /** Handles our mouse/keyboard input. */
//  protected InputHandler input;
    /** High resolution timer for jME. */
  protected Timer timer;
    /** The root node of our text. */
  protected Node fpsNode;
    /** Displays all the lovely information at the bottom. */
  protected Text fps;
    /** Simply an easy way to get at timer.getTimePerFrame().  Also saves time so you don't call it more than once per frame. */
  protected float tpf;
  protected Node mouseNode;
  protected InputHandler input;
  protected Node uiNode;
  protected InputHandler bufferedInput;
  protected AbsoluteMouse mouse;
  public MyTextBox myBox;
 
  MainUIEditBox _edit = null;
 
  UIColorScheme _scheme = new UIColorScheme();
    /** True if the renderer should display bounds. */
  protected boolean showBounds = false;
 
  private ArrayList targets;

    /** A wirestate to turn on and off for the rootNode */
  protected WireframeState wireState;
    /** A lightstate to turn on and off for the rootNode */
  protected LightState lightState;

    /** Location of the font for jME's text at the bottom */
  public static String fontLocation = "com/jme/app/defaultfont.tga";

  /** This is used to display print text. */
  protected StringBuffer updateBuffer=new StringBuffer(30);
  /** This is used to recieve getStatistics calls.*/
  protected StringBuffer tempBuffer=new StringBuffer();
   protected boolean pause;

   /**
   * This is called every frame in BaseGame.start()
   * @param interpolation unused in this implementation
   * @see AbstractGame#update(float interpolation)
   */
  protected final void update(float interpolation) {
      /** Recalculate the framerate. */
    timer.update();
      /** Update tpf to time per frame according to the Timer. */
    tpf = timer.getTimePerFrame();
      /** Check for key/mouse updates. */
    input.update(tpf);
    mouse.update();
 //   input2.update(tpf);
    bufferedInput.update(tpf);
    updateBuffer.setLength(0);
   
      if (pause) return;
      /** Call simpleUpdate in any derived classes of SimpleGame. */
   simpleUpdate();

   /** Update controllers/render states/transforms/bounds for rootNode. */
rootNode.updateGeometricState(tpf, true);

  }

  /**
   * This is called every frame in BaseGame.start(), after update()
   * @param interpolation unused in this implementation
   * @see AbstractGame#render(float interpolation)
   */
  protected final void render(float interpolation) {
      /** Reset display's tracking information for number of triangles/vertexes */
    display.getRenderer().clearStatistics();
      /** Clears the previously rendered information. */
    display.getRenderer().clearBuffers();
      /** Draw the rootNode and all its children. */
    display.getRenderer().draw(rootNode);
      /** If showing bounds, draw rootNode's bounds, and the bounds of all its children. */
    if (showBounds)
      display.getRenderer().drawBounds(rootNode);
      /** Draw the fps node to show the fancy information at the bottom. */
//    display.getRenderer().draw(fpsNode);
      /** Call simpleRender() in any derived classes. */
    simpleRender();
  }

  /**
   * Creates display, sets up camera, and binds keys.  Called in BaseGame.start() directly after
   * the dialog box.
   * @see AbstractGame#initSystem()
   */
  protected final void initSystem() {
     LoggingSystem.getLogger().setLevel(Level.SEVERE);
     try {
        /** Get a DisplaySystem acording to the renderer selected in the startup box. */
      display = DisplaySystem.getDisplaySystem(properties.getRenderer());
       /** Create a window with the startup box's information. */
      display.createWindow(
          properties.getWidth(),
          properties.getHeight(),
          properties.getDepth(),
          properties.getFreq(),
          properties.getFullscreen());
         /** Create a camera specific to the DisplaySystem that works with
          * the display's width and height*/
      cam =
          display.getRenderer().createCamera(
          display.getWidth(),
          display.getHeight());

    }
    catch (JmeException e) {
        /** If the displaysystem can't be initialized correctly, exit instantly. */
      e.printStackTrace();
      System.exit(1);
    }

      /** Set a black background.*/
    display.getRenderer().setBackgroundColor(ColorRGBA.black);

    /** Set up how our camera sees. */
    cam.setFrustumPerspective(45.0f,
                              (float) display.getWidth() /
                              (float) display.getHeight(), 1, 1000);
    Vector3f loc = new Vector3f(0.0f, 0.0f, 25.0f);
    Vector3f left = new Vector3f( -1.0f, 0.0f, 0.0f);
    Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
    Vector3f dir = new Vector3f(0.0f, 0f, -1.0f);
      /** Move our camera to a correct place and orientation. */
    cam.setFrame(loc, left, up, dir);
      /** Signal that we've changed our camera's location/frustum. */
    cam.update();
      /** Assign the camera to this renderer.*/
    display.getRenderer().setCamera(cam);
    InputSystem.createInputSystem(properties.getRenderer());
    /** Create a basic input controller. */
    input = new InputHandler();
    bufferedInput = new InputHandler();
    input.setKeySpeed(10f);
    input.setMouseSpeed(1f);
      /** Get a high resolution timer for FPS updates. */
    timer = Timer.getTimer(properties.getRenderer());

      /** Sets the title of our display. */
      display.setTitle("SimpleGame");
      /** Signal to the renderer that it should keep track of rendering information. */
    display.getRenderer().enableStatistics(true);

      /** Assign key P to action "toggle_pause". */
      KeyBindingManager.getKeyBindingManager().set(
            "toggle_pause",
            KeyInput.KEY_P);
      /** Assign key T to action "toggle_wire". */
    KeyBindingManager.getKeyBindingManager().set(
        "toggle_wire",
        KeyInput.KEY_T);
      /** Assign key L to action "toggle_lights". */
    KeyBindingManager.getKeyBindingManager().set(
        "toggle_lights",
        KeyInput.KEY_L);
      /** Assign key B to action "toggle_bounds". */
    KeyBindingManager.getKeyBindingManager().set(
        "toggle_bounds",
        KeyInput.KEY_B);
      /** Assign key C to action "camera_out". */
    KeyBindingManager.getKeyBindingManager().set(
        "camera_out",
        KeyInput.KEY_C);
    KeyBindingManager.getKeyBindingManager().set(
            "Exit",
            KeyInput.KEY_ESCAPE);
    KeyBindingManager.getKeyBindingManager().set(
            "Send",
            KeyInput.KEY_RETURN);
  }

  /**
   * Creates rootNode, lighting, statistic text, and other basic render states.
   * Called in BaseGame.start() after initSystem().
   * @see AbstractGame#initGame()
   */
  protected final void initGame() {
      /** Create rootNode */
    rootNode = new Node("rootNode");
    mouseNode = new Node("mouseNode");
    uiNode = new Node ("uiNode");

String[] names = { "main", "nice" };
String[] locs = { fontLocation, "conc_font.png" };

UIFonts _fonts = new UIFonts(names, locs);
   
    /** Create a wirestate to toggle on and off.  Starts disabled with
     * default width of 1 pixel. */
    wireState = display.getRenderer().createWireframeState();
    wireState.setEnabled(false);
    rootNode.setRenderState(wireState);

    /** Create a ZBuffer to display pixels closest to the camera above farther ones.  */
    ZBufferState buf = display.getRenderer().createZBufferState();
    buf.setEnabled(true);
    buf.setFunction(ZBufferState.CF_LEQUAL);
    rootNode.setRenderState(buf);

    // -- FPS DISPLAY
    // First setup alpha state
      /** This allows correct blending of text and what is already rendered below it*/
    AlphaState as1 = display.getRenderer().createAlphaState();
    as1.setBlendEnabled(true);
    as1.setSrcFunction(AlphaState.SB_SRC_ALPHA);
    as1.setDstFunction(AlphaState.DB_ONE);
    as1.setTestEnabled(true);
    as1.setTestFunction(AlphaState.TF_GREATER);
    as1.setEnabled(true);

    // Now setup font texture
    TextureState font = display.getRenderer().createTextureState();
      /** The texture is loaded from fontLocation */
    font.setTexture(
        TextureManager.loadTexture(
        MainSimpleGame.class.getClassLoader().getResource(
        fontLocation),
        Texture.MM_LINEAR,
        Texture.FM_LINEAR));
    font.setEnabled(true);

    // Then our font Text object.
      /** This is what will actually have the text at the bottom. */
    fps = new Text("FPS label", "");
    fps.setForceView(true);
    fps.setTextureCombineMode(TextureState.REPLACE);

    // Finally, a stand alone node (not attached to root on purpose)
    fpsNode = new Node("FPS node");
    fpsNode.attachChild(fps);
    fpsNode.setRenderState(font);
    fpsNode.setRenderState(as1);
    fpsNode.setForceView(true);

    // ---- LIGHTS
      /** Set up a basic, default light. */
    PointLight light = new PointLight();
    light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
    light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
    light.setLocation(new Vector3f(100, 100, 100));
    light.setEnabled(true);

      /** Attach the light to a lightState and the lightState to rootNode. */
    lightState = display.getRenderer().createLightState();
    lightState.setEnabled(true);
    lightState.attach(light);
    rootNode.setRenderState(lightState);

    //


   
   
   
    AlphaState as2 = display.getRenderer().createAlphaState();
    as2.setBlendEnabled(true);
    as2.setSrcFunction(AlphaState.SB_SRC_ALPHA);
    as2.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
    as2.setTestEnabled(true);
    as2.setTestFunction(AlphaState.TF_GREATER);
    AlphaState alpha = display.getRenderer().createAlphaState();
    alpha.setBlendEnabled(true);
    alpha.setSrcFunction(4);
    alpha.setDstFunction(1);
    alpha.setTestEnabled(true);
    alpha.setTestFunction(4);
   
    mouse = new AbsoluteMouse("Mouse Input", display.getWidth(), display
            .getHeight());
    TextureState cursor = display.getRenderer().createTextureState();
    cursor.setEnabled(true);
    cursor.setTexture(TextureManager.loadTexture(TestAbsoluteMouse.class
            .getClassLoader()
            .getResource("jmetest/data/cursor/cursor1.png"),
            Texture.MM_LINEAR, Texture.FM_LINEAR));
   
    mouse.setRenderState(cursor);
    mouse.setRenderState(as2);
    mouse.setMouseInput(InputSystem.getMouseInput());

    /*
     * Set the speed of the mouse
     */
    input.setMouse(mouse);
    _edit = new MainUIEditBox("edit", 5 , 4, 400, 15, input, bufferedInput, _scheme,
      _fonts, "nice", "", 60f, 0f, UIObject.TEXTURE, display);
      /** Let derived classes initialize. */
myBox = new MyTextBox(display, input); 
    simpleInitGame();
    rootNode.attachChild(myBox);
    rootNode.attachChild(_edit);
    rootNode.attachChild(mouse);
      /** Update geometric and rendering information for both the rootNode and fpsNode. */
    rootNode.updateGeometricState(0.0f, true);
    rootNode.updateRenderState();
    fpsNode.updateGeometricState(0.0f, true);
    fpsNode.updateRenderState();
  }

  /**
   * Called near end of initGame(). Must be defined by derived classes.
   */
  protected abstract void simpleInitGame();

    /**
     * Can be defined in derived classes for custom updating.
     * Called every frame in update.
     */
  protected void simpleUpdate() {}

    /**
     * Can be defined in derived classes for custom rendering.
     * Called every frame in render.
     */
  protected void simpleRender() {}

  /**
   * unused
   * @see AbstractGame#reinit()
   */
  protected void reinit() {
  }

  /**
   * Cleans up the keyboard.
   * @see AbstractGame#cleanup()
   */
  protected void cleanup() {
    LoggingSystem.getLogger().log(Level.INFO, "Cleaning up resources.");

    if (InputSystem.getKeyInput() != null)
      InputSystem.getKeyInput().destroy();
    if (InputSystem.getMouseInput() != null)
      InputSystem.getMouseInput().destroy();
  }
}

why do you set up another input handler (bufferedInput?) Try cleaning up that (only use 1) and removing all UI components. If that fixes it, add what you need back in one at a time until the problem resurfaces.

Thanks! I did that, started it from scratch and pinpointed the problem: Its this



Original:

input = new FirstPersonHandler(this, cam, properties.getRenderer());



What I do:

input = new InputHandler();



I have no idea why it wont work on false with the latter input. :frowning:

(Tested this on the original SimpleGame)

Fixed: I just redid the FirstPersonHandler code to suit my needs :slight_smile:



But, the problem is the Edit Box only works with a buffered input, and if you put in the old input -> the key bindings in the edit box code dont work. And if you use buffered input all the other input is messed up.

hmm, well I have to point to UI being only “barely implemented” at this time. Lots of irregularities are likely. This sounds like a question for Guurk if he’s still working on GUI.

The problem seems to be in the Edit Box code :


  public abstract class EditBoxKeyInputAction extends KeyInputAction {
        public EditBoxKeyInputAction() {
            this.allowsRepeats = false;
        }
    }; 



So if you set it true here, and false on the simplegame class, the false will work for the higher level key bindings, but the true will effect this and multi presses.

False their, and false here makes 0 key readings since its 2 falses.
2 true's work as one true, and just read do commands.

EDIT: Another thing I found out that special keys (,./) and spaces are effected by the true/false option. And normal letters are not effected, and if you comment out that code only special keys are effected.