OSDN Git Service

c63a93b661addf1e4d36572625607cccb772c77f
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / input / KeyBindingManager.java
1 /*
2  * Copyright (c) 2003-2009 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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.
31  */
32
33 package com.jme.input;
34
35 import java.util.ArrayList;
36 import java.util.HashMap;
37
38 /**
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.
45  *
46  * @see com.jme.input.KeyInput
47  * @author Mark Powell
48  * @version $Id: KeyBindingManager.java,v 1.17 2006/05/12 21:16:17 nca Exp $
49  */
50 public class KeyBindingManager {
51         //singleton instance
52         private static KeyBindingManager instance = null;
53
54         //key mappings
55         private HashMap<String, ArrayList<KeyCodes>> keyMap;
56
57         private boolean[] restrictKey = new boolean[256];
58
59         /**
60          * Private constructor is called by the getInstance method.
61          * It initializes the keyMap.
62          */
63         private KeyBindingManager() {
64                 keyMap = new HashMap<String, ArrayList<KeyCodes>>();
65     }
66         
67         /**
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.
72          */
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;
78         keyList.add(key);
79         keyMap.put(command, keyList);
80         }
81
82     /**
83      * <code>set</code> sets the command to the given list of keycodes
84      * overriding any previous keycodes previously set for the same command.
85      *
86      * @param command the command to set.
87      * @param keyCode the list of keys to set to the command.
88      */
89     public void set(String command, int[] keyCode) {
90         ArrayList<KeyCodes> keyList = new ArrayList<KeyCodes>();
91         KeyCodes key = new KeyCodes();
92         key.keys = keyCode;
93         keyList.add(key);
94         keyMap.put(command, keyList);
95     }
96
97     /**
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.
103      */
104     public void add(String command, int keyCode) {
105         ArrayList<KeyCodes> list = keyMap.get(command);
106         if(null == list) {
107             set( command, keyCode );
108             return;
109         }
110
111         KeyCodes key = new KeyCodes();
112         key.keys = new int[1];
113         key.keys[0] = keyCode;
114         list.add(key);
115     }
116
117     /**
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.
123      */
124     public void add(String command, int[] keyCode) {
125         ArrayList<KeyCodes> list = keyMap.get(command);
126         if(null == list) {
127             set( command, keyCode );
128             return;
129         }
130
131         KeyCodes key = new KeyCodes();
132         key.keys = keyCode;
133         list.add(key);
134     }
135
136     /**
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.
143      */
144         public int[] get(String command, int index) {
145         return keyMap.get(command).get(index).keys;
146    }
147
148    /**
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.
154     */
155    public boolean isValidCommand(String command) {
156      return isValidCommand(command, true);
157    }
158
159     /**
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.
166      */
167     public boolean isValidCommand(String command, boolean allowRepeats) {
168         ArrayList<KeyCodes> keyList = keyMap.get(command);
169         if(null == keyList) {
170             return false;
171         }
172         if ( keyList.isEmpty() )
173         {
174             return true; //is this desired? (it was the previous behaviour)
175         }
176
177         for(int i = 0, max = keyList.size(); i < max; i++) {
178             int[] keycodes = keyList.get(i).keys;
179             boolean value = true;
180
181             for(int j = 0; value && j < keycodes.length; j++) {
182               if (allowRepeats)
183                 value = KeyInput.get().isKeyDown(keycodes[j]);
184               else
185                 value = getStickyKey(keycodes[j]);
186             }
187
188             if (value) {
189                 return true;
190             }
191         }
192         
193         return false;
194     }
195
196     /**
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.
203      */
204     private boolean getStickyKey(int key) {
205         if (!restrictKey[key] && KeyInput.get().isKeyDown(key)) {
206             restrictKey[key] = true;
207             return true;
208         } else if (!KeyInput.get().isKeyDown(key) && restrictKey[key])
209             restrictKey[key] = false;
210         return false;
211     }
212
213     /**
214      * <code>remove</code> deletes a key map from the list.
215      * @param command the key map to delete.
216      */
217         public void remove(String command) {
218                 keyMap.remove(command);
219         }
220         
221         /**
222      * <code>removeAll</code> deletes all key mappings from the list.
223      */
224     public void removeAll() {
225         keyMap.clear();
226     }
227
228     /**
229      * <code>getInstance</code> gets the static singleton instance of
230      * the manager.
231      * @return the instance of the key binding manager.
232      */
233         public static KeyBindingManager getKeyBindingManager() {
234                 if(null == instance) {
235                         instance = new KeyBindingManager();
236                 }
237
238                 return instance;
239         }
240
241     /**
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
245      * this uses.
246      */
247     public class KeyCodes {
248         public int[] keys;
249     }
250 }