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 * 010 * It does not perform the blocking functionality of the non-GDX SquidKey implementation, because this is meant to run 011 * in an event-driven libGDX game and should not step on the toes of libGDX's input handling. To block game logic 012 * 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 static private final int KEY_DOWN = 0; 021 static private final int KEY_UP = 1; 022 static private 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 = false; 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 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 synchronized (this) { 095 if (processor == null) { 096 queue.clear(); 097 return; 098 } 099 q.addAll(queue); 100 queue.clear(); 101 } 102 for (int i = 0, n = q.size; i < n;) { 103 switch (q.get(i++)) { 104 case KEY_DOWN: 105 processor.keyDown(q.get(i++)); 106 break; 107 case KEY_UP: 108 processor.keyUp(q.get(i++)); 109 break; 110 case KEY_TYPED: 111 processor.keyTyped((char)q.get(i++)); 112 break; 113 } 114 } 115 q.clear(); 116 } 117 118 /** 119 * Returns true if at least one event is queued. 120 * @return true if there is an event queued, false otherwise. 121 */ 122 public boolean hasNext() 123 { 124 return queue.size >= 2; 125 } 126 127 /** 128 * Processes the first event queued up, passing it to this object's InputProcessor. 129 */ 130 public void next() 131 { 132 IntArray q = processingQueue; 133 synchronized (this) { 134 if (processor == null || queue.size < 2) { 135 queue.clear(); 136 return; 137 } 138 q.addAll(queue, 0, 2); 139 queue.removeRange(0, 1); 140 } 141 if(q.size >= 2) 142 { 143 int e = q.get(0), n = q.get(1); 144 switch (e) { 145 case KEY_DOWN: 146 processor.keyDown(n); 147 break; 148 case KEY_UP: 149 processor.keyUp(n); 150 break; 151 case KEY_TYPED: 152 processor.keyTyped((char)n); 153 break; 154 } 155 } 156 q.clear(); 157 } 158 159 /** 160 * Empties the backing queue of data. 161 */ 162 public void flush() 163 { 164 queue.clear(); 165 } 166 167 @Override 168 public synchronized boolean keyDown (int keycode) { 169 if(ignoreInput) return false; 170 queue.add(KEY_DOWN); 171 queue.add(keycode); 172 return false; 173 } 174 175 @Override 176 public synchronized boolean keyUp (int keycode) { 177 if(ignoreInput) return false; 178 queue.add(KEY_UP); 179 queue.add(keycode); 180 return false; 181 } 182 183 @Override 184 public synchronized boolean keyTyped (char character) { 185 if(ignoreInput) return false; 186 queue.add(KEY_TYPED); 187 queue.add(character); 188 return false; 189 } 190 191 @Override 192 public synchronized boolean touchDown (int screenX, int screenY, int pointer, int button) { 193 return false; 194 } 195 196 @Override 197 public synchronized boolean touchUp (int screenX, int screenY, int pointer, int button) { 198 return false; 199 } 200 201 @Override 202 public synchronized boolean touchDragged (int screenX, int screenY, int pointer) { 203 return false; 204 } 205 206 @Override 207 public synchronized boolean mouseMoved (int screenX, int screenY) { 208 return false; 209 } 210 211 @Override 212 public synchronized boolean scrolled (int amount) { 213 return false; 214 } 215 216}