1 /**
  2  * Copyright (C) 2009-2012 Klaus Reimer <k@ailis.de>
  3  * See LICENSE.txt for licensing information
  4  * 
  5  * @require threedee.js
  6  * @require threedee/updater/NodeUpdater.js
  7  */
  8 
  9 /**
 10  * Constructs a new keyboard updater connected to the specified HTML element.
 11  * 
 12  * @param {(Window|Element)=} element
 13  *            The element to which the keyboard event handlers are connected.
 14  *            This is optional and defaults to the browser window.
 15  *            
 16  * @constructor
 17  * @extends {threedee.NodeUpdater}
 18  * @class 
 19  * This updater can be bound to a HTML element (Window is default) where
 20  * it listens for key presses and releases to transform the connected node
 21  * according to the key pressed and velocity settings.
 22  */
 23 
 24 threedee.KeyboardUpdater = function(element)
 25 {
 26     var updater;
 27     
 28     threedee.NodeUpdater.call(this);
 29     if (!element) element = window;
 30     this.element = element;
 31     
 32     updater = this;
 33     
 34     element.addEventListener("keydown", this.handleKeyDown.bind(this), false);     
 35     element.addEventListener("keyup", this.handleKeyUp.bind(this), false);     
 36 };
 37 threedee.inherit(threedee.KeyboardUpdater, threedee.NodeUpdater);
 38 
 39 /**
 40  * The element to which the keyboard event handlers are connected.
 41  * @private
 42  * @type {!(Window|Element)}
 43  */
 44 threedee.KeyboardUpdater.prototype.element;
 45 
 46 /**
 47  * The movement speed in units per second.
 48  * @private
 49  * @type {number}
 50  */ 
 51 threedee.KeyboardUpdater.prototype.speed = 10;
 52 
 53 /** 
 54  * The rotation speed in clock-wise RAD per second. 
 55  * @private
 56  * @type {number}
 57  */
 58 threedee.KeyboardUpdater.prototype.rotSpeed = 45 * Math.PI / 180;
 59 
 60 /**
 61  * Flag indicating if the left key has been pressed.
 62  * @private
 63  * @type {boolean}
 64  */
 65 threedee.KeyboardUpdater.prototype.left = false;
 66 
 67 /**
 68  * Flag indicating if the right key has been pressed.
 69  * @private
 70  * @type {boolean}
 71  */
 72 threedee.KeyboardUpdater.prototype.right = false;
 73 
 74 /**
 75  * Flag indicating if the up key has been pressed.
 76  * @private
 77  * @type {boolean}
 78  */
 79 threedee.KeyboardUpdater.prototype.up = false;
 80 
 81 /**
 82  * Flag indicating if the down key has been pressed.
 83  * @private
 84  * @type {boolean}
 85  */
 86 threedee.KeyboardUpdater.prototype.down = false;
 87 
 88 /**
 89  * Flag indicating if the forward key has been pressed.
 90  * @private
 91  * @type {boolean}
 92  */
 93 threedee.KeyboardUpdater.prototype.forward = false;
 94 
 95 /**
 96  * Flag indicating if the backward key has been pressed.
 97  * @private
 98  * @type {boolean}
 99  */
100 threedee.KeyboardUpdater.prototype.backward = false;
101 
102 /**
103  * Flag indicating if the pitch up key has been pressed.
104  * @private
105  * @type {boolean}
106  */
107 threedee.KeyboardUpdater.prototype.pitchUp = false;
108 
109 /**
110  * Flag indicating if the pitch down key has been pressed.
111  * @private
112  * @type {boolean}
113  */
114 threedee.KeyboardUpdater.prototype.pitchDown = false;
115 
116 /**
117  * Flag indicating if the yaw left key has been pressed.
118  * @private
119  * @type {boolean}
120  */
121 threedee.KeyboardUpdater.prototype.yawLeft = false;
122 
123 /**
124  * Flag indicating if the yaw right key has been pressed.
125  * @private
126  * @type {boolean}
127  */
128 threedee.KeyboardUpdater.prototype.yawRight = false;
129 
130 /**
131  * Flag indicating if the roll left key has been pressed.
132  * @private
133  * @type {boolean}
134  */
135 threedee.KeyboardUpdater.prototype.rollLeft = false;
136 
137 /**
138  * Flag indicating if the roll right key has been pressed.
139  * @private
140  * @type {boolean}
141  */
142 threedee.KeyboardUpdater.prototype.rollRight = false;
143 
144 /**
145  * Handles the key-down event.
146  * 
147  * @param {!Event} e
148  *           The event.
149  * @private
150  */
151 threedee.KeyboardUpdater.prototype.handleKeyDown = function(e)
152 {
153     switch (e.keyCode)
154     {
155         case 87:
156             this.forward = true;
157             break;
158             
159         case 83:
160             this.backward = true;
161             break;
162                         
163         case 65:
164             this.left = true;
165             break;
166 
167         case 68:
168             this.right = true;
169             break;
170 
171         case 82:
172             this.down = true;
173             break;
174 
175         case 70:
176             this.up = true;
177             break;
178             
179         case 37:
180             this.yawLeft = true;
181             break;
182             
183         case 39:
184             this.yawRight = true;
185             break;
186 
187         case 38:
188             this.pitchUp = true;
189             break;
190             
191         case 40:
192             this.pitchDown = true;
193             break;
194 
195         case 81:
196             this.rollLeft = true;
197             break;
198             
199         case 69:
200             this.rollRight = true;
201             break;
202 
203         default:
204             return;
205     }
206     e.preventDefault();
207 };
208 
209 /**
210  * Handles the key-up event.
211  * 
212  * @param {!Event} e
213  *           The event.
214  * @private
215  */
216 threedee.KeyboardUpdater.prototype.handleKeyUp = function(e)
217 {
218     switch (e.keyCode)
219     {
220         case 87:
221             this.forward = false;
222             break;
223             
224         case 83:
225             this.backward = false;
226             break;
227             
228         case 65:
229             this.left = false;
230             break;
231 
232         case 68:
233             this.right = false;
234             break;
235 
236         case 82:
237             this.down = false;
238             break;
239 
240         case 70:
241             this.up = false;
242             break;
243 
244         case 37:
245             this.yawLeft = false;
246             break;
247             
248         case 39:
249             this.yawRight = false;
250             break;
251 
252         case 38:
253             this.pitchUp = false;
254             break;
255             
256         case 40:
257             this.pitchDown = false;
258             break;
259 
260         case 81:
261             this.rollLeft = false;
262             break;
263             
264         case 69:
265             this.rollRight = false;
266             break;
267 
268         default:
269     }
270     e.preventDefault();
271 };
272 
273 /**
274  * @inheritDoc
275  * 
276  * @param {!threedee.SceneNode} node
277  * @param {number} delta
278  */
279 threedee.KeyboardUpdater.prototype.update = function(node, delta)
280 {
281     var x, y, z, rx, ry, rz, transform;
282     
283     x = this.right ? 1 : (this.left ? -1 : 0);
284     y = this.down ? 1 : (this.up ? -1 : 0);
285     z = this.forward ? 1 : (this.backward ? -1 : 0);
286     rx = this.pitchUp ? 1 : (this.pitchDown ? -1 : 0);
287     ry = this.yawRight ? 1 : (this.yawLeft ? -1 : 0);
288     rz = this.rollLeft ? 1 : (this.rollRight ? -1 : 0);
289 
290     transform = node.getTransform();
291     
292     transform.translate(x * this.speed * delta / 1000, y * this.speed
293         * delta / 1000, z * this.speed * delta / 1000);
294     
295     transform.rotateX(rx * this.rotSpeed * delta / 1000);               
296     transform.rotateY(ry * this.rotSpeed * delta / 1000);               
297     transform.rotateZ(rz * this.rotSpeed * delta / 1000);
298 };
299