Author Topic: KeyMapper isn't working with the software renderer...  (Read 2383 times)

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
KeyMapper isn't working with the software renderer...
« on: November 01, 2011, 09:09:57 pm »
...even after I added the premusably redundant line this.addKeyListener(keyMapper). My game loop prints "polling" just before I poll the KeyMapper, but then the state is always RELEASED (with key code 0). Very bizarre. It's worth noting that the pre-game parts of my game are handled on a canvas that I remove from the frame when the game starts. But this.addKeyListener(keyMapper) is being called AFTER the call to remove the canvas.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: KeyMapper isn't working with the software renderer...
« Reply #1 on: November 01, 2011, 09:24:33 pm »
...and you are using the constructor that takes the Component?

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
Re: KeyMapper isn't working with the software renderer...
« Reply #2 on: November 01, 2011, 09:37:35 pm »
Yes.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: KeyMapper isn't working with the software renderer...
« Reply #3 on: November 01, 2011, 09:45:32 pm »
No idea. It works fine for me...here's the code for the KeyMapper. Maybe this helps to find the problem:

Code: [Select]
package com.threed.jpct.util;

import java.awt.event.*;
import java.awt.*;
import org.lwjgl.input.*;
import org.lwjgl.opengl.*;
import com.threed.jpct.FrameBuffer;

/**
 * KeyMapper is convenience class to ease the different handling of the keyboard
 * when using hard- or software rendering. It provides a uniform way to access
 * the keyboard.
 */
public class KeyMapper implements KeyListener {

private int bufferSize = 10;

private KeyState[] keys;

private int[] awtKeyState;

private int keyCnt;

private int pollCnt;

private boolean lwjgl;

private Component comp = null;

private boolean created = false;

private int[] mapping = new int[] { Keyboard.KEY_NONE, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_ESCAPE, KeyEvent.VK_ESCAPE, 0, Keyboard.KEY_1, KeyEvent.VK_1, 0, Keyboard.KEY_2, KeyEvent.VK_2, 0,
Keyboard.KEY_3, KeyEvent.VK_3, 0, Keyboard.KEY_4, KeyEvent.VK_4, 0, Keyboard.KEY_5, KeyEvent.VK_5, 0, Keyboard.KEY_6, KeyEvent.VK_6, 0, Keyboard.KEY_7, KeyEvent.VK_7, 0, Keyboard.KEY_8,
KeyEvent.VK_8, 0, Keyboard.KEY_9, KeyEvent.VK_9, 0, Keyboard.KEY_0, KeyEvent.VK_0, 0, Keyboard.KEY_MINUS, KeyEvent.VK_MINUS, 0, Keyboard.KEY_EQUALS, KeyEvent.VK_EQUALS, 0,
Keyboard.KEY_BACK, KeyEvent.VK_BACK_SPACE, 0, Keyboard.KEY_TAB, KeyEvent.VK_TAB, 0, Keyboard.KEY_Q, KeyEvent.VK_Q, 0, Keyboard.KEY_W, KeyEvent.VK_W, 0, Keyboard.KEY_E, KeyEvent.VK_E, 0,
Keyboard.KEY_R, KeyEvent.VK_R, 0, Keyboard.KEY_T, KeyEvent.VK_T, 0, Keyboard.KEY_Y, KeyEvent.VK_Y, 0, Keyboard.KEY_U, KeyEvent.VK_U, 0, Keyboard.KEY_I, KeyEvent.VK_I, 0, Keyboard.KEY_O,
KeyEvent.VK_O, 0, Keyboard.KEY_P, KeyEvent.VK_P, 0, Keyboard.KEY_LBRACKET, KeyEvent.VK_LEFT_PARENTHESIS, 0, Keyboard.KEY_RBRACKET, KeyEvent.VK_RIGHT_PARENTHESIS, 0, Keyboard.KEY_RETURN,
KeyEvent.VK_ENTER, 0, Keyboard.KEY_LCONTROL, KeyEvent.VK_CONTROL, 0, Keyboard.KEY_A, KeyEvent.VK_A, 0, Keyboard.KEY_S, KeyEvent.VK_S, 0, Keyboard.KEY_D, KeyEvent.VK_D, 0, Keyboard.KEY_F,
KeyEvent.VK_F, 0, Keyboard.KEY_G, KeyEvent.VK_G, 0, Keyboard.KEY_H, KeyEvent.VK_H, 0, Keyboard.KEY_J, KeyEvent.VK_J, 0, Keyboard.KEY_K, KeyEvent.VK_K, 0, Keyboard.KEY_L, KeyEvent.VK_L, 0,
Keyboard.KEY_SEMICOLON, KeyEvent.VK_SEMICOLON, 0, Keyboard.KEY_APOSTROPHE, KeyEvent.VK_COLON, 0, Keyboard.KEY_GRAVE, KeyEvent.VK_DEAD_GRAVE, 0, Keyboard.KEY_LSHIFT, KeyEvent.VK_SHIFT, 0,
Keyboard.KEY_BACKSLASH, KeyEvent.VK_BACK_SLASH, 0, Keyboard.KEY_Z, KeyEvent.VK_Z, 0, Keyboard.KEY_X, KeyEvent.VK_X, 0, Keyboard.KEY_C, KeyEvent.VK_C, 0, Keyboard.KEY_V, KeyEvent.VK_V, 0,
Keyboard.KEY_B, KeyEvent.VK_B, 0, Keyboard.KEY_N, KeyEvent.VK_N, 0, Keyboard.KEY_M, KeyEvent.VK_M, 0, Keyboard.KEY_COMMA, KeyEvent.VK_COMMA, 0, Keyboard.KEY_PERIOD, KeyEvent.VK_PERIOD,
0,
Keyboard.KEY_SLASH,
KeyEvent.VK_SLASH,
0,
Keyboard.KEY_RSHIFT,
KeyEvent.VK_SHIFT,
0,
Keyboard.KEY_MULTIPLY,
KeyEvent.VK_MULTIPLY,
0,
Keyboard.KEY_LMENU,
KeyEvent.VK_UNDEFINED,
0, // Ändern...
Keyboard.KEY_SPACE, KeyEvent.VK_SPACE, 0, Keyboard.KEY_CAPITAL, KeyEvent.VK_CAPS_LOCK, 0, Keyboard.KEY_F1, KeyEvent.VK_F1, 0, Keyboard.KEY_F2, KeyEvent.VK_F2, 0, Keyboard.KEY_F3,
KeyEvent.VK_F3, 0, Keyboard.KEY_F4, KeyEvent.VK_F4, 0, Keyboard.KEY_F5, KeyEvent.VK_F5, 0, Keyboard.KEY_F6, KeyEvent.VK_F6, 0, Keyboard.KEY_F7, KeyEvent.VK_F7, 0, Keyboard.KEY_F8,
KeyEvent.VK_F8, 0, Keyboard.KEY_F9, KeyEvent.VK_F9, 0, Keyboard.KEY_F10, KeyEvent.VK_F10, 0, Keyboard.KEY_NUMLOCK, KeyEvent.VK_NUM_LOCK, 0, Keyboard.KEY_SCROLL, KeyEvent.VK_SCROLL_LOCK,
0, Keyboard.KEY_NUMPAD7, KeyEvent.VK_NUMPAD7, 0, Keyboard.KEY_NUMPAD8, KeyEvent.VK_NUMPAD8, 0, Keyboard.KEY_NUMPAD9, KeyEvent.VK_NUMPAD9, 0, Keyboard.KEY_SUBTRACT, KeyEvent.VK_SUBTRACT,
0, Keyboard.KEY_NUMPAD4, KeyEvent.VK_NUMPAD4, 0, Keyboard.KEY_NUMPAD5, KeyEvent.VK_NUMPAD5, 0, Keyboard.KEY_NUMPAD6, KeyEvent.VK_NUMPAD6, 0, Keyboard.KEY_ADD, KeyEvent.VK_ADD, 0,
Keyboard.KEY_NUMPAD1, KeyEvent.VK_NUMPAD1, 0, Keyboard.KEY_NUMPAD2, KeyEvent.VK_NUMPAD2, 0, Keyboard.KEY_NUMPAD3, KeyEvent.VK_NUMPAD3, 0, Keyboard.KEY_NUMPAD0, KeyEvent.VK_NUMPAD0, 0,
Keyboard.KEY_DECIMAL, KeyEvent.VK_DECIMAL, 0, Keyboard.KEY_F11, KeyEvent.VK_F11, 0, Keyboard.KEY_F12, KeyEvent.VK_F12, 0, Keyboard.KEY_F13, KeyEvent.VK_F13, 0, Keyboard.KEY_F14,
KeyEvent.VK_F14, 0, Keyboard.KEY_F15, KeyEvent.VK_F15, 0, Keyboard.KEY_KANA, KeyEvent.VK_KANA, 0, Keyboard.KEY_CONVERT, KeyEvent.VK_CONVERT, 0, Keyboard.KEY_NOCONVERT,
KeyEvent.VK_NONCONVERT,
0,
Keyboard.KEY_YEN,
KeyEvent.VK_UNDEFINED,
0,// Ändern...
Keyboard.KEY_NUMPADEQUALS, KeyEvent.VK_EQUALS, 0, Keyboard.KEY_CIRCUMFLEX, KeyEvent.VK_CIRCUMFLEX, 0, Keyboard.KEY_AT, KeyEvent.VK_AT, 0, Keyboard.KEY_COLON, KeyEvent.VK_COLON, 0,
Keyboard.KEY_UNDERLINE, KeyEvent.VK_UNDERSCORE, 0, Keyboard.KEY_KANJI, KeyEvent.VK_KANJI, 0, Keyboard.KEY_STOP, KeyEvent.VK_STOP, 0,
Keyboard.KEY_AX,
KeyEvent.VK_UNDEFINED,
0, // Ändern...
Keyboard.KEY_UNLABELED,
KeyEvent.VK_UNDEFINED,
0, // Ändern...
Keyboard.KEY_NUMPADENTER, KeyEvent.VK_ENTER, 0, Keyboard.KEY_RCONTROL, KeyEvent.VK_CONTROL, 0, Keyboard.KEY_NUMPADCOMMA, KeyEvent.VK_COMMA, 0, Keyboard.KEY_DIVIDE, KeyEvent.VK_DIVIDE, 0,
Keyboard.KEY_SYSRQ,
KeyEvent.VK_UNDEFINED,
0, // Ändern...
Keyboard.KEY_RMENU, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_PAUSE, KeyEvent.VK_PAUSE, 0, Keyboard.KEY_HOME, KeyEvent.VK_HOME, 0, Keyboard.KEY_UP, KeyEvent.VK_UP, 0, Keyboard.KEY_PRIOR,
KeyEvent.VK_PAGE_UP, 0, Keyboard.KEY_LEFT, KeyEvent.VK_LEFT, 0, Keyboard.KEY_RIGHT, KeyEvent.VK_RIGHT, 0, Keyboard.KEY_END, KeyEvent.VK_END, 0, Keyboard.KEY_DOWN, KeyEvent.VK_DOWN, 0,
Keyboard.KEY_NEXT, KeyEvent.VK_PAGE_DOWN, 0, Keyboard.KEY_INSERT, KeyEvent.VK_INSERT, 0, Keyboard.KEY_DELETE, KeyEvent.VK_DELETE, 0, Keyboard.KEY_LWIN, KeyEvent.VK_UNDEFINED, 0, // Ändern...
Keyboard.KEY_RWIN, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_APPS, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_POWER, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_SLEEP, KeyEvent.VK_UNDEFINED, 0 };

/**
* Use this constructor to create a KeyMapper that works in combination with
* hardware rendering (i.e. that is using LWJGL's methods to access the
* keyboard).
*/
public KeyMapper() {
init(null);
}

/**
* Use this construtor to create a KeyMapper that works on an AWT/Swing
* component, which is usually your frame (or whatever) where the rendered
* output will be displayed onto. The KeyMapper will automatically register
* itself as a KeyListener of the component. To deregister, call destroy on
* this KeyMapper.
*
* @param comp
*            the component
*/
public KeyMapper(Component comp) {
init(comp);
}

/**
* Destroys the KeyMapper. This will free up used resources and will
* deregister the KeyMapper if required. It's mandatory to call this method
* before exiting your application or instantiating another KeyMapper.
*/
public void destroy() {
if (comp != null) {
comp.removeKeyListener(this);
awtKeyState = null;
} else {
synchronized (FrameBuffer.SYNCHRONIZER) {
if (Keyboard.isCreated()) {
Keyboard.destroy();
}
}
}
}

/**
* Poll the keyboard until no further KeyStates are available. In that case,
* KeyState.NONE will be returned.
*
* @return the KeyState (i.e. which key has been pressed/released)
*/
public synchronized KeyState poll() {
if (created) {
if (lwjgl) {
pollLWJGLKeys();
}

if (pollCnt != keyCnt && pollCnt < bufferSize) {
KeyState state = keys[pollCnt];
keys[pollCnt] = null;
pollCnt++;
return state;
} else {
pollCnt = 0;
keyCnt = 0;
return KeyState.NONE;
}
} else {
init(null);
return KeyState.NONE;
}
}

/**
* Has to be public, because KeyMapper implements KeyListener. No need to
* call this method directly.
*
* @param e
*            the KeyEvent
*/
public void keyTyped(KeyEvent e) {
}

/**
* Has to be public, because KeyMapper implements KeyListener. No need to
* call this method directly.
*
* @param e
*            the KeyEvent
*/
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code < awtKeyState.length) {
if (awtKeyState[code] != 1) {
awtKeyState[code] = 1;
processKey(e.getKeyCode(), e.getKeyChar(), true);
}
} else {
// Just do it in this case...if it ever happens!
processKey(e.getKeyCode(), e.getKeyChar(), true);
}
}

/**
* Has to be public, because KeyMapper implements KeyListener. No need to
* call this method directly.
*
* @param e
*            the KeyEvent
*/
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if (code < awtKeyState.length) {
if (awtKeyState[code] != 0) {
// Releasing a key that has never been pressed is impossible,
// but we are
// doing this check anyway...it won't hurt though.
awtKeyState[code] = 0;
processKey(e.getKeyCode(), e.getKeyChar(), false);
}
} else {
// Just do it in this case...if it ever happens!
processKey(e.getKeyCode(), e.getKeyChar(), false);
}

}

private void pollLWJGLKeys() {
synchronized (FrameBuffer.SYNCHRONIZER) {
if (Keyboard.isCreated()) {
// Keyboard.poll();
while (Keyboard.next()) {
int key = Keyboard.getEventKey();
char chr = Keyboard.getEventCharacter();
boolean state = Keyboard.getEventKeyState();
for (int i = 0; i < mapping.length; i = i + 3) {
if (mapping[i] == key) {
if (state && mapping[i + 2] != 1) {
processKey(mapping[i + 1], chr, true);
mapping[i + 2] = 1;
} else {
if (!state && mapping[i + 2] == 1) {
processKey(mapping[i + 1], chr, false);
mapping[i + 2] = 0;
}
}
}
}
}
}
}
}

private void init(Component comp) {
keys = new KeyState[bufferSize];
keyCnt = 0;
created = true;
if (comp != null) {
this.comp = comp;
awtKeyState = new int[0xFFFF];
comp.addKeyListener(this);
lwjgl = false;
} else {
lwjgl = true;
try {
synchronized (FrameBuffer.SYNCHRONIZER) {
if (!Keyboard.isCreated()) {
if (Display.isCreated()) {
Keyboard.create();
} else {
created = false;
}
}
}
} catch (Exception e) {
created = false;
}
}
}

private synchronized void processKey(int code, char chr, boolean pressed) {
while (keyCnt >= bufferSize) {
resizeBuffer();
}
keys[keyCnt] = new KeyState(code, chr, pressed);
keyCnt++;
}

private void resizeBuffer() {
KeyState[] newBuffer = new KeyState[bufferSize + 10];
System.arraycopy(keys, 0, newBuffer, 0, bufferSize);
bufferSize += 10;
keys = newBuffer;
}
}

Offline AGP

  • quad
  • ******
  • Posts: 1726
    • View Profile
Re: KeyMapper isn't working with the software renderer...
« Reply #4 on: November 21, 2011, 05:57:39 pm »
It was, as I had suspected, a Java 7 issue. Adding frame.requestFocus() at the end of the constructor solved it for me. It was not a KeyMapper-specific issue, but rather a KeyListener one.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: KeyMapper isn't working with the software renderer...
« Reply #5 on: November 21, 2011, 06:01:09 pm »
Makes sense to add it then to the KeyMapper, i guess... ???