AZERTY keyboard support? (and QWERTZ)

Hello,

i was wondering if there was any support for AZERTY (and eventually QWERTZ) keyboard with jME?

(beside rebinding every key everytime 'by hand' in jme' sources or in our main)



:?



Thanx in advance


Nothing that I know of, but this is an interesting thing to look at since I had a co-worker using french keyboards who used to get quite frustrated with the keybindings.



Using Locale.getDefault() you can find the OS' set country and automatically re-bind from there.  I'll have a look at integrating this into the jME2 sources as this is a great usability thing, but it would only be for the built in control handlers such as FirstPersonHandler.  Are you using jME2 or 3?



P.S: nice name :wink:

Yeah WSAD binding is hell for AZERTY keyboards!!!



I think Kirill is planning to add a "save/load key mapping to a config file" feature to JME3, so you could easily load the correct binding for your keyboard.




1 Like

If you're using KeyboardLookHandler with jME2, then you can use this function to detect and change the assignment of keys :slight_smile:



private void adjustPerLocale(){
      KeyBindingManager keyBindingManager = KeyBindingManager.getKeyBindingManager();
      Locale locale = Locale.getDefault();
      if(locale.equals(Locale.FRANCE) || locale.equals(Locale.FRENCH)){
         keyBindingManager.set("forward", KeyInput.KEY_Z);
         keyBindingManager.set("backward", KeyInput.KEY_S);
         keyBindingManager.set("strafeLeft", KeyInput.KEY_Q);
         keyBindingManager.set("strafeRight", KeyInput.KEY_D);
         keyBindingManager.set( "elevateUp", KeyInput.KEY_A);
         keyBindingManager.set( "elevateDown", KeyInput.KEY_W);
      }
      else if(locale.equals(Locale.GERMANY) || locale.equals(Locale.GERMAN)){
         keyBindingManager.set("forward", KeyInput.KEY_Z);
         keyBindingManager.set("backward", KeyInput.KEY_S);
         keyBindingManager.set("strafeLeft", KeyInput.KEY_A);
         keyBindingManager.set("strafeRight", KeyInput.KEY_D);
         keyBindingManager.set( "elevateUp", KeyInput.KEY_Q);
         keyBindingManager.set( "elevateDown", KeyInput.KEY_Y);
      }
   }

1 Like

Thanx sbook,

that was what i was doing in jme2.

But i hoped jme3 might change the keyboard handling or that u could still do that in the jmonleyplatform^^



Honestly, i starting to get sick already of that localization/keyboard setting (i'll try eclispe with sources, might be better than the jmonkeyplatform)^^



Ill keep u informed

I created a new java project with jme3 sources, it works fine and i can change keymapping like in jme2.



Too bad i can't use the jmonkeyplatform :confused:

fckregistration said:

I created a new java project with jme3 sources, it works fine and i can change keymapping like in jme2.

Too bad i can't use the jmonkeyplatform :/

I dont understand? Whats your problem with jMP? How is setting the keybindings for a jme3 game different in eclipse than in jMP?
normen said:

fckregistration said:

I created a new java project with jme3 sources, it works fine and i can change keymapping like in jme2.

Too bad i can't use the jmonkeyplatform :/

I dont understand? Whats your problem with jMP? How is setting the keybindings for a jme3 game different in eclipse than in jMP?

Because i downloaded the win32 exe installer for jmp.
It offers with some demo codes that i wanted to run+edit.
But since the sources/classes (for input handlers) in the package jm3 are in an jar, u can't modify them.

That's no big deal because i don't really need another IDE for java^^
(i will not/never use netbean IDE)


fckregistration said:

Because i downloaded the win32 exe installer for jmp.
It offers with some demo codes that i wanted to run+edit.
But since the sources/classes (for input handlers) in the package jm3 are in an jar, u can't modify them.
That's no big deal because i don't really need another IDE for java^^
(i will not/never use netbean IDE)

Lol. For eclipse fanboys there will be asset-only projects in jMP at some point, so you can code in your beloved IDE and use jMP for handling assets etc.
normen said:

fckregistration said:

Because i downloaded the win32 exe installer for jmp.
It offers with some demo codes that i wanted to run+edit.
But since the sources/classes (for input handlers) in the package jm3 are in an jar, u can't modify them.
That's no big deal because i don't really need another IDE for java^^
(i will not/never use netbean IDE)

Lol. For eclipse fanboys there will be asset-only projects in jMP at some point, so you can code in your beloved IDE and use jMP for handling assets etc.



i ain't an eclipse fanboys (if u could ask my friends, u'd know that i said many bad things about eclipse^^)...
it is just i have already an IDE and i don't want another one (even if it is only for handling some part i can't in my regular IDE).
fckregistration said:

i ain't an eclipse fanboys (if u could ask my friends, u'd know that i said many bad things about eclipse^^)...
it is just i have already an IDE and i don't want another one (even if it is only for handling some part i can't in my regular IDE).

Hm, ok. I rather use an IDE that is made for the environment I am working in. For javacard software I use an Eclipse IDE that is adapted for that purpose, for coding on MacOSX I use XCode, for Java software I use NetBeans and for PHP software I use another (older) install of NetBeans. Writing all config files etc. by hand just to stick to a certain IDE just does not make much sense to me :)
Cheers,
Normen
1 Like
normen said:

fckregistration said:

i ain't an eclipse fanboys (if u could ask my friends, u'd know that i said many bad things about eclipse^^)...
it is just i have already an IDE and i don't want another one (even if it is only for handling some part i can't in my regular IDE).

Hm, ok. I rather use an IDE that is made for the environment I am working in. For javacard software I use an Eclipse IDE that is adapted for that purpose, for coding on MacOSX I use XCode, for Java software I use NetBeans and for PHP software I use another (older) install of NetBeans. Writing all config files etc. by hand just to stick to a certain IDE just does not make much sense to me :)
Cheers,
Normen


Well, i think it is less messy and easier to have a single IDE for everything.
Thanx for the answers
fckregistration said:
Well, i think it is less messy and easier to have a single IDE for everything.
Thanx for the answers


As a self-proclaimed Eclipse fanboy (its unhealthy, Normen hates me for it, etc), NetBeans' PHP support makes Eclipse feel like a joke :)

fckregistration said:

Thanx sbook,
that was what i was doing in jme2.


Perhaps its time that this made it into the constructor up there in the codebase.. I'll set up a contribution
2 Likes

I had the same problem for classes extending com.jme3.app.SimpleApplication, it can be solved easily by:

  1. implementing an azerty FlyByCamera based on the qwerty implementation from jme3

  2. adding a couple of lines at the begin of simpleInitApp() method (to detach the FlyCamAppState and register the azerty FlyByCamera)

  3. mygame.AZERTYFlyByCamera:

[java]
/*

  • Copyright © 2009-2010 jMonkeyEngine
  • All rights reserved.
  • Redistribution and use in source and binary forms, with or without
  • modification, are permitted provided that the following conditions are
  • met:
    • Redistributions of source code must retain the above copyright
  • notice, this list of conditions and the following disclaimer.
    • Redistributions in binary form must reproduce the above copyright
  • notice, this list of conditions and the following disclaimer in the
  • documentation and/or other materials provided with the distribution.
    • Neither the name of ‘jMonkeyEngine’ nor the names of its contributors
  • may be used to endorse or promote products derived from this software
  • without specific prior written permission.
  • THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  • “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  • TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  • PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  • CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  • EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  • PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  • PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  • LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  • NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  • SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
    package mygame;

import com.jme3.collision.MotionAllowedListener;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;

/**

  • A first person view camera controller.

  • After creation, you must register the camera controller with the

  • dispatcher using #registerWithDispatcher().

  • Controls:

    • Move the mouse to rotate the camera
    • Mouse wheel for zooming in or out
    • WASD keys for moving forward/backward and strafing
    • QZ keys raise or lower the camera
      */
      public class AZERTYFlyByCamera implements AnalogListener, ActionListener {

    private Camera cam;
    private Vector3f initialUpVec;
    private float rotationSpeed = 1f;
    private float moveSpeed = 3f;
    private MotionAllowedListener motionAllowed = null;
    private boolean enabled = true;
    private boolean dragToRotate = false;
    private boolean canRotate = false;
    private InputManager inputManager;

    /**

    • Creates a new FlyByCamera to control the given Camera object.
    • @param cam
      */
      public AZERTYFlyByCamera(Camera cam){
      this.cam = cam;
      initialUpVec = cam.getUp().clone();
      }

    public void setMotionAllowedListener(MotionAllowedListener listener){
    this.motionAllowed = listener;
    }

    /**

    • Sets the move speed. The speed is given in world units per second.
    • @param moveSpeed
      */
      public void setMoveSpeed(float moveSpeed){
      this.moveSpeed = moveSpeed;
      }

    /**

    • Sets the rotation speed.
    • @param rotationSpeed
      */
      public void setRotationSpeed(float rotationSpeed){
      this.rotationSpeed = rotationSpeed;
      }

    /**

    • @param enable If false, the camera will ignore input.
      */
      public void setEnabled(boolean enable){
      enabled = enable;
      }

    /**

    • @return If enabled
    • @see FlyByCamera#setEnabled(boolean)
      */
      public boolean isEnabled(){
      return enabled;
      }

    /**

    • @return If drag to rotate feature is enabled.
    • @see FlyByCamera#setDragToRotate(boolean)
      */
      public boolean isDragToRotate() {
      return dragToRotate;
      }

    /**

    • @param dragToRotate When true, the user must hold the mouse button
    • and drag over the screen to rotate the camera, and the cursor is
    • visible until dragged. Otherwise, the cursor is invisible at all times
    • and holding the mouse button is not needed to rotate the camera.
    • This feature is disabled by default.
      */
      public void setDragToRotate(boolean dragToRotate) {
      this.dragToRotate = dragToRotate;
      inputManager.setCursorVisible(dragToRotate);
      }

    /**

    • Registers the FlyByCamera to recieve input events from the provided
    • Dispatcher.
    • @param dispacher
      */
      public void registerWithInput(InputManager inputManager){
      this.inputManager = inputManager;

// inputManager.registerJoystickAxisBinding(“FLYCAM_Left”, 2, JoyInput.AXIS_X, true);
// inputManager.registerJoystickAxisBinding(“FLYCAM_Right”, 2, JoyInput.AXIS_X, false);
// inputManager.registerJoystickAxisBinding(“FLYCAM_Up”, 2, JoyInput.AXIS_Y, true);
// inputManager.registerJoystickAxisBinding(“FLYCAM_Down”, 2, JoyInput.AXIS_Y, false);
//
// inputManager.registerJoystickAxisBinding(“FLYCAM_StrafeLeft”, 2, JoyInput.POV_X, true);
// inputManager.registerJoystickAxisBinding(“FLYCAM_StrafeRight”, 2, JoyInput.POV_X, false);
// inputManager.registerJoystickAxisBinding(“FLYCAM_Forward”, 2, JoyInput.POV_Y, true);
// inputManager.registerJoystickAxisBinding(“FLYCAM_Backward”, 2, JoyInput.POV_Y, false);

    String[] mappings = new String[]{
        "FLYCAM_Left",
        "FLYCAM_Right",
        "FLYCAM_Up",
        "FLYCAM_Down",

        "FLYCAM_StrafeLeft",
        "FLYCAM_StrafeRight",
        "FLYCAM_Forward",
        "FLYCAM_Backward",

        "FLYCAM_ZoomIn",
        "FLYCAM_ZoomOut",
        "FLYCAM_RotateDrag",

        "FLYCAM_Rise",
        "FLYCAM_Lower"
    };

    // both mouse and button - rotation of cam
    inputManager.addMapping("FLYCAM_Left", new MouseAxisTrigger(0, true),
                                           new KeyTrigger(KeyInput.KEY_LEFT));

    inputManager.addMapping("FLYCAM_Right", new MouseAxisTrigger(0, false),
                                            new KeyTrigger(KeyInput.KEY_RIGHT));

    inputManager.addMapping("FLYCAM_Up", new MouseAxisTrigger(1, false),
                                         new KeyTrigger(KeyInput.KEY_UP));

    inputManager.addMapping("FLYCAM_Down", new MouseAxisTrigger(1, true),
                                           new KeyTrigger(KeyInput.KEY_DOWN));

    // mouse only - zoom in/out with wheel, and rotate drag
    inputManager.addMapping("FLYCAM_ZoomIn", new MouseAxisTrigger(2, false));
    inputManager.addMapping("FLYCAM_ZoomOut", new MouseAxisTrigger(2, true));
    inputManager.addMapping("FLYCAM_RotateDrag", new MouseButtonTrigger(0));

    // keyboard only ZQSD for movement and WZ for rise/lower height
    inputManager.addMapping("FLYCAM_StrafeLeft", new KeyTrigger(KeyInput.KEY_Q));
    inputManager.addMapping("FLYCAM_StrafeRight", new KeyTrigger(KeyInput.KEY_D));
    inputManager.addMapping("FLYCAM_Forward", new KeyTrigger(KeyInput.KEY_Z));
    inputManager.addMapping("FLYCAM_Backward", new KeyTrigger(KeyInput.KEY_S));
    inputManager.addMapping("FLYCAM_Rise", new KeyTrigger(KeyInput.KEY_A));
    inputManager.addMapping("FLYCAM_Lower", new KeyTrigger(KeyInput.KEY_W));

    inputManager.addListener(this, mappings);
    inputManager.setCursorVisible(dragToRotate);
}

private void rotateCamera(float value, Vector3f axis){
    if (dragToRotate){
        if (canRotate){

// value = -value;
}else{
return;
}
}

    Matrix3f mat = new Matrix3f();
    mat.fromAngleNormalAxis(rotationSpeed * value, axis);

    Vector3f up = cam.getUp();
    Vector3f left = cam.getLeft();
    Vector3f dir = cam.getDirection();

    mat.mult(up, up);
    mat.mult(left, left);
    mat.mult(dir, dir);

    Quaternion q = new Quaternion();
    q.fromAxes(left, up, dir);
    //q.normalize();
    q.normalizeLocal();
    cam.setAxes(q);
}

private void zoomCamera(float value){
    // derive fovY value
    float h = cam.getFrustumTop();
    float w = cam.getFrustumRight();
    float aspect = w / h;

    float near = cam.getFrustumNear();

    float fovY = FastMath.atan(h / near)
              / (FastMath.DEG_TO_RAD * .5f);
    fovY += value * 0.1f;

    h = FastMath.tan( fovY * FastMath.DEG_TO_RAD * .5f) * near;
    w = h * aspect;

    cam.setFrustumTop(h);
    cam.setFrustumBottom(-h);
    cam.setFrustumLeft(-w);
    cam.setFrustumRight(w);
}

private void riseCamera(float value){
    Vector3f vel = new Vector3f(0, value * moveSpeed, 0);
    Vector3f pos = cam.getLocation().clone();

    if (motionAllowed != null)
        motionAllowed.checkMotionAllowed(pos, vel);
    else
        pos.addLocal(vel);

    cam.setLocation(pos);
}

private void moveCamera(float value, boolean sideways){
    Vector3f vel = new Vector3f();
    Vector3f pos = cam.getLocation().clone();

    if (sideways){
        cam.getLeft(vel);
    }else{
        cam.getDirection(vel);
    }
    vel.multLocal(value * moveSpeed);

    if (motionAllowed != null)
        motionAllowed.checkMotionAllowed(pos, vel);
    else
        pos.addLocal(vel);

    cam.setLocation(pos);
}

public void onAnalog(String name, float value, float tpf) {
    if (!enabled)
        return;

    if (name.equals("FLYCAM_Left")){
        rotateCamera(value, initialUpVec);
    }else if (name.equals("FLYCAM_Right")){
        rotateCamera(-value, initialUpVec);
    }else if (name.equals("FLYCAM_Up")){
        rotateCamera(-value, cam.getLeft());
    }else if (name.equals("FLYCAM_Down")){
        rotateCamera(value, cam.getLeft());
    }else if (name.equals("FLYCAM_Forward")){
        moveCamera(value, false);
    }else if (name.equals("FLYCAM_Backward")){
        moveCamera(-value, false);
    }else if (name.equals("FLYCAM_StrafeLeft")){
        moveCamera(value, true);
    }else if (name.equals("FLYCAM_StrafeRight")){
        moveCamera(-value, true);
    }else if (name.equals("FLYCAM_Rise")){
        riseCamera(value);
    }else if (name.equals("FLYCAM_Lower")){
        riseCamera(-value);
    }else if (name.equals("FLYCAM_ZoomIn")){
        zoomCamera(value);
    }else if (name.equals("FLYCAM_ZoomOut")){
        zoomCamera(-value);
    }
}

public void onAction(String name, boolean value, float tpf) {
    if (!enabled)
        return;

    if (name.equals("FLYCAM_RotateDrag") && dragToRotate){
        canRotate = value;
        inputManager.setCursorVisible(!value);
    }
}

}
[/java]

  1. mygame.Main:

[java]
/*

  • Copyright © 2009-2010 jMonkeyEngine
  • All rights reserved.
  • Redistribution and use in source and binary forms, with or without
  • modification, are permitted provided that the following conditions are
  • met:
    • Redistributions of source code must retain the above copyright
  • notice, this list of conditions and the following disclaimer.
    • Redistributions in binary form must reproduce the above copyright
  • notice, this list of conditions and the following disclaimer in the
  • documentation and/or other materials provided with the distribution.
    • Neither the name of ‘jMonkeyEngine’ nor the names of its contributors
  • may be used to endorse or promote products derived from this software
  • without specific prior written permission.
  • THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  • “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  • TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  • PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  • CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  • EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  • PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  • PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  • LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  • NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  • SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
    package mygame;

import com.jme3.app.FlyCamAppState;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;

/**

  • test

  • @author normenhansen
    */
    public class Main extends SimpleApplication {

    public static void main(String[] args) {
    Main app = new Main();
    app.start();

    }

    @Override
    public void simpleInitApp() {

    //Here are the couple of lines!
    stateManager.detach( stateManager.getState( FlyCamAppState.class ) );
    new AZERTYFlyByCamera(cam).registerWithInput(inputManager);
    //

     Box b = new Box(1, 1, 1);
     Geometry geom = new Geometry("Box", b);
    
     Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
     mat.setColor("Color", ColorRGBA.Blue);
     geom.setMaterial(mat);
    
     rootNode.attachChild(geom);
    

    }

    @Override
    public void simpleUpdate(float tpf) {
    //TODO: add update code
    }

    @Override
    public void simpleRender(RenderManager rm) {
    //TODO: add render code
    }

}
[/java]

1 Like

Lol i wasn’t sure till now but it seems i was the one posting the problem^.^
And i changed my mind… separate IDE’s is a good idea^.^