2 * Copyright (c) 2003-2009 jMonkeyEngine
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 package com.jme.input;
35 import java.util.ArrayList;
36 import java.util.HashMap;
39 * <code>KeyBindingManager</code> maintains a list of command and
40 * key pairs. A key is denoted as an int and corresponds to <code>KeyInput</code>'s
41 * constants. A call to <code>isValidCommand</code> with an associated command will return
42 * true if they key associated with the command is pressed. This allows for pairings with
43 * <code>InputAction</code> how is also associated with a command, to be paired allowing
44 * for actions to be performed within the game based on user input.
46 * @see com.jme.input.KeyInput
48 * @version $Id: KeyBindingManager.java,v 1.17 2006/05/12 21:16:17 nca Exp $
50 public class KeyBindingManager {
52 private static KeyBindingManager instance = null;
55 private HashMap<String, ArrayList<KeyCodes>> keyMap;
57 private boolean[] restrictKey = new boolean[256];
60 * Private constructor is called by the getInstance method.
61 * It initializes the keyMap.
63 private KeyBindingManager() {
64 keyMap = new HashMap<String, ArrayList<KeyCodes>>();
68 * <code>set</code> sets the command to the given keycode overriding
69 * any previous keycodes previously set for the same command.
70 * @param command the command to set.
71 * @param keyCode the key to set to the command.
73 public void set(String command, int keyCode) {
74 ArrayList<KeyCodes> keyList = new ArrayList<KeyCodes>();
75 KeyCodes key = new KeyCodes();
76 key.keys = new int[1];
77 key.keys[0] = keyCode;
79 keyMap.put(command, keyList);
83 * <code>set</code> sets the command to the given list of keycodes
84 * overriding any previous keycodes previously set for the same command.
86 * @param command the command to set.
87 * @param keyCode the list of keys to set to the command.
89 public void set(String command, int[] keyCode) {
90 ArrayList<KeyCodes> keyList = new ArrayList<KeyCodes>();
91 KeyCodes key = new KeyCodes();
94 keyMap.put(command, keyList);
98 * <code>add</code> adds a keycode to a command that already exists. This
99 * will not override the previous keycode, but add to it. Allowing the
100 * two keys to perform the same command.
101 * @param command the command to add to.
102 * @param keyCode the key to add to the command.
104 public void add(String command, int keyCode) {
105 ArrayList<KeyCodes> list = keyMap.get(command);
107 set( command, keyCode );
111 KeyCodes key = new KeyCodes();
112 key.keys = new int[1];
113 key.keys[0] = keyCode;
118 * <code>add</code> adds a list of keycodes corresponding to a
119 * command. All the keys defined in the array must be pressed for
120 * the command to be valid.
121 * @param command the command to assign to the keys.
122 * @param keyCode the array of keys that must be pressed.
124 public void add(String command, int[] keyCode) {
125 ArrayList<KeyCodes> list = keyMap.get(command);
127 set( command, keyCode );
131 KeyCodes key = new KeyCodes();
137 * <code>get</code> retrieves the key(s) for a given command. An array
138 * of ints are returned, where all ints would be required for the command
139 * to be executed. For example: int[] = {KEY_1, KEY_2} would require
140 * both 1 and 2 pressed at the same time.
141 * @param command the requested key map
142 * @return the key map for the command.
144 public int[] get(String command, int index) {
145 return keyMap.get(command).get(index).keys;
149 * <code>isValidCommand</code> determines if a command is executable in
150 * the current state of the keyboard. That is, is a valid key pressed to
151 * execute the requested command.
152 * @param command the command to check.
153 * @return true if the command should be executed, false otherwise.
155 public boolean isValidCommand(String command) {
156 return isValidCommand(command, true);
160 * <code>isValidCommand</code> determines if a command is executable in
161 * the current state of the keyboard. That is, is a valid key pressed to
162 * execute the requested command.
163 * @param command the command to check.
164 * @param allowRepeats allow repetitious key presses.
165 * @return true if the command should be executed, false otherwise.
167 public boolean isValidCommand(String command, boolean allowRepeats) {
168 ArrayList<KeyCodes> keyList = keyMap.get(command);
169 if(null == keyList) {
172 if ( keyList.isEmpty() )
174 return true; //is this desired? (it was the previous behaviour)
177 for(int i = 0, max = keyList.size(); i < max; i++) {
178 int[] keycodes = keyList.get(i).keys;
179 boolean value = true;
181 for(int j = 0; value && j < keycodes.length; j++) {
183 value = KeyInput.get().isKeyDown(keycodes[j]);
185 value = getStickyKey(keycodes[j]);
197 * Returns true if a key is down and wasn't down last call.
198 * If a key is down and not restricted, the key is set as restricted and true is returned.
199 * If a key is down and restricted, false is returned.
200 * If a key is not down and is restricted, the restriction is cleared.
201 * @param key The key to test
202 * @return True if the key is a fresh key input.
204 private boolean getStickyKey(int key) {
205 if (!restrictKey[key] && KeyInput.get().isKeyDown(key)) {
206 restrictKey[key] = true;
208 } else if (!KeyInput.get().isKeyDown(key) && restrictKey[key])
209 restrictKey[key] = false;
214 * <code>remove</code> deletes a key map from the list.
215 * @param command the key map to delete.
217 public void remove(String command) {
218 keyMap.remove(command);
222 * <code>removeAll</code> deletes all key mappings from the list.
224 public void removeAll() {
229 * <code>getInstance</code> gets the static singleton instance of
231 * @return the instance of the key binding manager.
233 public static KeyBindingManager getKeyBindingManager() {
234 if(null == instance) {
235 instance = new KeyBindingManager();
242 * <code>KeyCodes</code> defines a list of one or more keys for
243 * a given key command. During key press comparisons, a logical and
244 * will be used to insure all keys are pressed for which ever command
247 public class KeyCodes {