1/**
2 * Key polling class
3 *
4 * To create:
5 * var key:KeyPoll = new KeyPoll( displayObject );
6 *
7 * the display object will usually be the stage.
8 *
9 * Full example:
10 * package
11 *  {
12 *  	import flash.display.Sprite;
13 *  	import flash.events.Event;
14 *  	import flash.ui.Keyboard;
15 *  	import fgc.input.KeyPoll;
16 *
17 *  	public class Test
18 *  	{
19 *  		var key:KeyPoll;
20 *
21 *  		public function Test()
22 *  		{
23 *  			key = new KeyPoll( this.stage );
24 *  			addEventListener( Event.ENTER_FRAME, enterFrame );
25 *  		}
26 *
27 *  		public function enterFrame( ev:Event ):void
28 *  		{
29 *  			if( key.isDown( Keyboard.LEFT ) )
30 *  			{
31 *  				trace( "left key is down" );
32 *  			}
33 *  			if( key.isDown( Keyboard.RIGHT ) )
34 *  			{
35 *  				trace( "right key is down" );
36 *  			}
37 *  		}
38 *  	}
39 *  }
40 *
41 * Author: Richard Lord
42 * Copyright (c) FlashGameCode.net 2007
43 * Version 1.0.2
44 *
45 * Permission is hereby granted, free of charge, to any person obtaining a copy
46 * of this software and associated documentation files (the "Software"), to deal
47 * in the Software without restriction, including without limitation the rights
48 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
49 * copies of the Software, and to permit persons to whom the Software is
50 * furnished to do so, subject to the following conditions:
51 *
52 * The above copyright notice and this permission notice shall be included in
53 * all copies or substantial portions of the Software.
54 *
55 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
61 * THE SOFTWARE.
62 */
63
64package bigroom.input
65{
66	import flash.events.KeyboardEvent;
67	import flash.events.Event;
68	import flash.display.DisplayObject;
69	import flash.utils.ByteArray;
70  import flash.events.TouchEvent;
71  import flash.ui.Multitouch;
72  import flash.ui.MultitouchInputMode;
73
74	import flash.ui.*;
75	import flash.events.MouseEvent;
76
77	import flash.net.*;
78
79	public class KeyPoll
80	{
81		private var states:ByteArray;
82		private var dispObj:DisplayObject;
83		public var click:Boolean = false;
84		public var clickheld:Boolean = false;
85		public var hasclicked:Boolean = false;
86		public var press:Boolean = false;
87		public var onscreen:Boolean=true;
88		public var gotosite:String = "";
89		public var touchx:Vector.<int> = new Vector.<int>;
90		public var touchy:Vector.<int> = new Vector.<int>;
91		public var touchid:Vector.<int> = new Vector.<int>;
92		public var temptouchid:int = 0;
93
94		public var controlstick:int = -1;
95		public var controlstick_x:int = 0;
96		public var controlstick_y:int = 0;
97		public var pushleft:Boolean = false;
98		public var pushright:Boolean = false;
99		public var controlstick_xrange:int = 0;
100		public var controlstick_yrange:int = 0;
101		public var deadzone:int = 0, deadzone_inner:int = 0;
102		public var firstmove:Boolean = false;
103
104		public var touchPoints : uint;
105
106
107		public function KeyPoll( obj:DisplayObject )
108		{
109			states = new ByteArray();
110			states.writeUnsignedInt( 0 );
111			states.writeUnsignedInt( 0 );
112			states.writeUnsignedInt( 0 );
113			states.writeUnsignedInt( 0 );
114			states.writeUnsignedInt( 0 );
115			states.writeUnsignedInt( 0 );
116			states.writeUnsignedInt( 0 );
117			states.writeUnsignedInt( 0 );
118
119			touchPoints = 0;
120			for (var i:int = 0; i < 20; i++) {
121				touchx.push(0);
122				touchy.push(0);
123				touchid.push(-1);
124			}
125
126			Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
127			dispObj = obj;
128			dispObj.addEventListener( KeyboardEvent.KEY_DOWN, keyDownListener, false, 0, true );
129			dispObj.addEventListener( KeyboardEvent.KEY_UP, keyUpListener, false, 0, true );
130			dispObj.addEventListener( Event.ACTIVATE, activateListener, false, 0, true );
131			dispObj.addEventListener( Event.DEACTIVATE, deactivateListener, false, 0, true );
132
133			/*
134			dispObj.addEventListener( MouseEvent.MOUSE_DOWN, mouseDownListener);
135			dispObj.addEventListener( MouseEvent.MOUSE_UP, mouseUpListener );
136			*/
137
138
139			dispObj.addEventListener( TouchEvent.TOUCH_BEGIN, touchbeginlistener);
140      dispObj.addEventListener( TouchEvent.TOUCH_MOVE, touchmovelistener);
141			dispObj.addEventListener( TouchEvent.TOUCH_END, touchendlistener );
142
143
144			//dispObj.addEventListener( TouchEvent.TOUCH_TAP, mouseclicker);
145		}
146
147		public function definestickrange(x:int, y:int, d:int):void {
148			/*
149			if (device.deviceresolution == device.ANDROID) {
150				//Turn d into a sensible value
151				d = 6;
152			}else {
153				//Ignore it and just use 6
154				d = 6;
155			}
156			*/
157			controlstick_xrange = x;
158			controlstick_yrange = y;
159			deadzone = d;
160			deadzone_inner = Math.min(int(d * 0.5), 1);
161		}
162
163		public function gettouchx():int {
164			if (touchPoints == 0) {
165				return touchx[0];
166			}else {
167				return touchx[touchPoints - 1];
168			}
169		}
170
171		public function gettouchy():int {
172			if (touchPoints == 0) {
173				return touchy[0];
174			}else {
175				return touchy[touchPoints - 1];
176			}
177		}
178
179		/*
180		public function mouseUpListener( e:MouseEvent ):void {
181			//Identify the point that's been removed, and take it away from the array
182			touchPoints = 0;
183
184			if (touchPoints == 0){
185				press = false;
186
187				click = false;
188				clickheld = false;
189				hasclicked = false;
190			}
191		}
192
193		public function mouseDownListener( e:MouseEvent ):void {
194			touchx[0] = e.stageX;
195			touchy[0] = e.stageY;
196			touchid[0] = 1;
197
198			touchPoints=1;
199			press = true;
200
201			click = true;
202			clickheld = true;
203			hasclicked = true;
204		}
205		*/
206
207		public function touchbeginlistener( e:TouchEvent ):void {
208			touchx[touchPoints] = e.stageX;
209			touchy[touchPoints] = e.stageY;
210			touchid[touchPoints] = e.touchPointID;
211
212			if (controlstick == -1) {
213				//Consider this for the controlstick point
214				if (touchx[touchPoints] < controlstick_xrange) {
215					if (touchy[touchPoints] > controlstick_yrange) {
216						controlstick = touchid[touchPoints];
217						controlstick_x = touchx[touchPoints];
218						controlstick_y = touchy[touchPoints];
219						pushleft = false;
220						pushright = false;
221						firstmove = true;
222				  }
223				}
224			}
225
226			touchPoints++;
227			press = true;
228
229			click = true;
230			clickheld = true;
231			hasclicked = true;
232		}
233
234		public function touchendlistener( e:TouchEvent ):void {
235			//Identify the point that's been removed, and take it away from the array
236			temptouchid = e.touchPointID;
237
238			if (temptouchid == controlstick) {
239				controlstick = -1;
240				pushleft = false;
241				pushright = false;
242				firstmove = false;
243				controlstick_x = -1;
244				controlstick_y = -1;
245			}
246
247			for (var i:int = 0; i < touchPoints; i++) {
248				if (touchid[i] == temptouchid) {
249					for (var j:int = i; j < touchPoints; j++) {
250						touchx[j] = touchx[j + 1];
251						touchy[j] = touchy[j + 1];
252						touchid[j] = touchid[j + 1];
253					}
254					i = touchPoints + 1;
255					touchPoints--;
256				}
257			}
258
259			if (touchPoints == 0){
260				press = false;
261
262				click = false;
263				clickheld = false;
264				hasclicked = false;
265			}
266		}
267
268		public function touchmovelistener(e:TouchEvent):void {
269			//Identify the touch point that's moving, and update it's coordinates
270			temptouchid = e.touchPointID;
271			for (var i:int = 0; i < touchPoints; i++) {
272				if (touchid[i] == temptouchid) {
273					touchx[i] = e.stageX;
274					touchy[i] = e.stageY;
275
276					if (touchid[i] == controlstick) {
277						if (firstmove) {
278							if (touchx[i] < controlstick_x) {
279								pushleft = true; pushright = false;
280								firstmove = false;
281								controlstick_x = touchx[i] + deadzone;
282								controlstick_y = touchy[i];
283							}else if (touchx[i] > controlstick_x) {
284								pushleft = false; pushright = true;
285								firstmove = false;
286								controlstick_x = touchx[i] - deadzone;
287								controlstick_y = touchy[i];
288							}
289						}else{
290							if (touchx[i] < controlstick_x - deadzone) {
291								pushleft = true; pushright = false;
292								controlstick_x = touchx[i] + deadzone;
293								controlstick_y = touchy[i];
294							}else if (touchx[i] > controlstick_x + deadzone) {
295								pushleft = false; pushright = true;
296								controlstick_x = touchx[i] - deadzone;
297								controlstick_y = touchy[i];
298							}else if (touchx[i] >= controlstick_x - deadzone_inner &&
299												touchx[i] <= controlstick_x + deadzone_inner) {
300								pushleft = false; pushright = false;
301							}
302						}
303					}
304				}
305			}
306		}
307
308		public function visitsite(t:String):void {
309			gotosite = t;
310		}
311
312		/*
313		public function mouseclicker(e:TouchEvent):void {
314			touchx = e.stageX;
315			touchy = e.stageY;
316			if (gotosite == "NG") {
317				//API.loadNewgrounds();
318				gotosite = "";
319			}else	if (gotosite != "") {
320				var link:URLRequest = new URLRequest(gotosite);
321        navigateToURL(link, "_blank");
322				gotosite = "";
323			}
324		}
325		*/
326
327		private function keyDownListener( ev:KeyboardEvent ):void
328		{
329			states[ ev.keyCode >>> 3 ] |= 1 << (ev.keyCode & 7);
330
331			if (ev.keyCode == 27){
332				ev.preventDefault();
333			}else if (ev.keyCode == Keyboard.BACK) {
334				// user hit the back button on Android device
335				ev.preventDefault();
336				ev.stopImmediatePropagation();
337      }
338		}
339
340		private function keyUpListener( ev:KeyboardEvent ):void
341		{
342			states[ ev.keyCode >>> 3 ] &= ~(1 << (ev.keyCode & 7));
343		}
344
345		private function activateListener( ev:Event ):void
346		{
347			for( var i:int = 0; i < 8; ++i )
348			{
349				states[ i ] = 0;
350			}
351		}
352
353		private function deactivateListener( ev:Event ):void
354		{
355			for( var i:int = 0; i < 8; ++i )
356			{
357				states[ i ] = 0;
358			}
359		}
360
361		public function isDown( keyCode:uint ):Boolean
362		{
363			return ( states[ keyCode >>> 3 ] & (1 << (keyCode & 7)) ) != 0;
364		}
365
366		public function isUp( keyCode:uint ):Boolean
367		{
368			return ( states[ keyCode >>> 3 ] & (1 << (keyCode & 7)) ) == 0;
369		}
370	}
371}