001package squidpony.squidgrid.gui.gdx; 002 003import com.badlogic.gdx.InputProcessor; 004import com.badlogic.gdx.utils.IntArray; 005 006/** 007 * This wraps an InputProcessor, storing all key events and allowing them to be processed one at a time using next() or 008 * all at once using drain(). To have an effect, it needs to be registered by calling Input.setInputProcessor(SquidKey). 009 * <br> 010 * It does not perform the blocking functionality of the now-removed Swing SquidKey implementation, because this is 011 * meant to run in an event-driven libGDX game and should not step on the toes of libGDX's input handling. To block game 012 * logic until an event has been received, check hasNext() in the game's render() method and effectively "block" by not 013 * running game logic if hasNext() returns false. You can get an event if hasNext() returns true by calling next(). 014 * 015 * @author Eben Howard - http://squidpony.com - howard@squidpony.com 016 * @author Nathan Sweet 017 * @author Tommy Ettinger 018 * */ 019public class SquidKey implements InputProcessor { 020 private static final int KEY_DOWN = 0; 021 private static final int KEY_UP = 1; 022 private static final int KEY_TYPED = 2; 023 024 private InputProcessor processor; 025 private final IntArray queue = new IntArray(); 026 private final IntArray processingQueue = new IntArray(); 027 private boolean ignoreInput; 028 029 /** 030 * Constructs a SquidKey with no InputProcessor; for this to do anything, setProcessor() must be called. 031 */ 032 public SquidKey () { 033 } 034 035 /** 036 * Constructs a SquidKey with the given InputProcessor. 037 * @param processor An InputProcessor that will handle keyDown(), keyUp(), and keyTyped() events 038 */ 039 public SquidKey (InputProcessor processor) { 040 this.processor = processor; 041 } 042 043 /** 044 * Constructs a SquidKey with the given InputProcessor. 045 * @param processor An InputProcessor that will handle keyDown(), keyUp(), and keyTyped() events 046 * @param ignoreInput the starting value for the ignore status; true to ignore input, false to process it. 047 */ 048 public SquidKey (InputProcessor processor, boolean ignoreInput) { 049 this.processor = processor; 050 this.ignoreInput = ignoreInput; 051 } 052 053 /** 054 * Sets the InputProcessor that this object will use to make sense of Key events. 055 * @param processor An InputProcessor that will handle keyDown(), keyUp(), and keyTyped() events 056 */ 057 public void setProcessor (InputProcessor processor) { 058 this.processor = processor; 059 } 060 061 /** 062 * Gets this object's InputProcessor. 063 * @return this object's InputProcessor 064 */ 065 public InputProcessor getProcessor () { 066 return processor; 067 } 068 069 /** 070 * Get the status for whether this should ignore input right now or not. True means this object will ignore and not 071 * queue keypresses, false means it should process them normally. Useful to pause processing or delegate it to 072 * another object temporarily. 073 * @return true if this object currently ignores input, false otherwise. 074 */ 075 public boolean getIgnoreInput() { 076 return ignoreInput; 077 } 078 079 /** 080 * Set the status for whether this should ignore input right now or not. True means this object will ignore and not 081 * queue keypresses, false means it should process them normally. Useful to pause processing or delegate it to 082 * another object temporarily. 083 * @param ignoreInput true if this should object should ignore and not queue input, false otherwise. 084 */ 085 public void setIgnoreInput(boolean ignoreInput) { 086 this.ignoreInput = ignoreInput; 087 } 088 089 /** 090 * Processes all events queued up, passing them to this object's InputProcessor. 091 */ 092 public void drain () { 093 IntArray q = processingQueue; 094 if (processor == null) { 095 queue.clear(); 096 return; 097 } 098 q.addAll(queue); 099 queue.clear(); 100 101 for (int i = 0, n = q.size; i < n; ) { 102 switch (q.get(i++)) { 103 case KEY_DOWN: 104 processor.keyDown(q.get(i++)); 105 break; 106 case KEY_UP: 107 processor.keyUp(q.get(i++)); 108 break; 109 case KEY_TYPED: 110 processor.keyTyped((char) q.get(i++)); 111 break; 112 } 113 } 114 q.clear(); 115 } 116 117 /** 118 * Returns true if at least one event is queued. 119 * @return true if there is an event queued, false otherwise. 120 */ 121 public boolean hasNext() 122 { 123 return queue.size >= 2; 124 } 125 126 /** 127 * Processes the first event queued up, passing it to this object's InputProcessor. 128 */ 129 public void next() { 130 IntArray q = processingQueue; 131 if (processor == null || queue.size < 2) { 132 queue.clear(); 133 return; 134 } 135 q.addAll(queue, 0, 2); 136 queue.removeRange(0, 1); 137 138 if (q.size >= 2) { 139 int e = q.get(0), n = q.get(1); 140 switch (e) { 141 case KEY_DOWN: 142 processor.keyDown(n); 143 break; 144 case KEY_UP: 145 processor.keyUp(n); 146 break; 147 case KEY_TYPED: 148 processor.keyTyped((char) n); 149 break; 150 } 151 } 152 q.clear(); 153 } 154 155 /** 156 * Empties the backing queue of data. 157 */ 158 public void flush() 159 { 160 queue.clear(); 161 } 162 163 @Override 164 public boolean keyDown (int keycode) { 165 if(ignoreInput) return false; 166 queue.add(KEY_DOWN); 167 queue.add(keycode); 168 return false; 169 } 170 171 @Override 172 public boolean keyUp (int keycode) { 173 if(ignoreInput) return false; 174 queue.add(KEY_UP); 175 queue.add(keycode); 176 return false; 177 } 178 179 @Override 180 public boolean keyTyped (char character) { 181 if(ignoreInput) return false; 182 queue.add(KEY_TYPED); 183 queue.add(character); 184 return false; 185 } 186 187 @Override 188 public boolean touchDown (int screenX, int screenY, int pointer, int button) { 189 return false; 190 } 191 192 @Override 193 public boolean touchUp (int screenX, int screenY, int pointer, int button) { 194 return false; 195 } 196 197 @Override 198 public boolean touchDragged (int screenX, int screenY, int pointer) { 199 return false; 200 } 201 202 @Override 203 public boolean mouseMoved (int screenX, int screenY) { 204 return false; 205 } 206 207 @Override 208 public boolean scrolled (int amount) { 209 return false; 210 } 211 212}