| 1 |
/** |
|---|
| 2 |
* @author Trevor McCauley |
|---|
| 3 |
* @link www.senocular.com |
|---|
| 4 |
*/ |
|---|
| 5 |
|
|---|
| 6 |
package org.papervision3d.core.utils.virtualmouse |
|---|
| 7 |
{ |
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
import flash.display.DisplayObject; |
|---|
| 11 |
import flash.display.DisplayObjectContainer; |
|---|
| 12 |
import flash.display.InteractiveObject; |
|---|
| 13 |
import flash.display.SimpleButton; |
|---|
| 14 |
import flash.display.Sprite; |
|---|
| 15 |
import flash.display.Stage; |
|---|
| 16 |
import flash.events.Event; |
|---|
| 17 |
import flash.events.EventDispatcher; |
|---|
| 18 |
import flash.events.KeyboardEvent; |
|---|
| 19 |
import flash.events.MouseEvent; |
|---|
| 20 |
import flash.geom.Point; |
|---|
| 21 |
import flash.utils.Dictionary; |
|---|
| 22 |
|
|---|
| 23 |
import org.papervision3d.core.log.PaperLogger; |
|---|
| 24 |
|
|---|
| 25 |
/** |
|---|
| 26 |
* Dispatched when the virtual mouse state is updated. |
|---|
| 27 |
* @eventType flash.events.Event |
|---|
| 28 |
*/ |
|---|
| 29 |
[Event(name="update", type="flash.events.Event")] |
|---|
| 30 |
|
|---|
| 31 |
/** |
|---|
| 32 |
* Dispatched when the virtual mouse fires an |
|---|
| 33 |
* Event.MOUSE_LEAVE event. |
|---|
| 34 |
* @eventType flash.events.Event |
|---|
| 35 |
*/ |
|---|
| 36 |
[Event(name="mouseLeave", type="flash.events.Event")] |
|---|
| 37 |
|
|---|
| 38 |
/** |
|---|
| 39 |
* Dispatched when the virtual mouse fires an |
|---|
| 40 |
* MouseEvent.MOUSE_MOVE event. |
|---|
| 41 |
* @eventType flash.events.MouseEvent |
|---|
| 42 |
*/ |
|---|
| 43 |
[Event(name="mouseMove", type="flash.events.MouseEvent")] |
|---|
| 44 |
|
|---|
| 45 |
/** |
|---|
| 46 |
* Dispatched when the virtual mouse fires an |
|---|
| 47 |
* MouseEvent.MOUSE_OUT event. |
|---|
| 48 |
* @eventType flash.events.MouseEvent |
|---|
| 49 |
*/ |
|---|
| 50 |
[Event(name="mouseOut", type="flash.events.MouseEvent")] |
|---|
| 51 |
/** |
|---|
| 52 |
* Dispatched when the virtual mouse fires an |
|---|
| 53 |
* MouseEvent.ROLL_OUT event. |
|---|
| 54 |
* @eventType flash.events.MouseEvent |
|---|
| 55 |
*/ |
|---|
| 56 |
[Event(name="rollOut", type="flash.events.MouseEvent")] |
|---|
| 57 |
|
|---|
| 58 |
/** |
|---|
| 59 |
* Dispatched when the virtual mouse fires an |
|---|
| 60 |
* MouseEvent.MOUSE_OVER event. |
|---|
| 61 |
* @eventType flash.events.MouseEvent |
|---|
| 62 |
*/ |
|---|
| 63 |
[Event(name="mouseOver", type="flash.events.MouseEvent")] |
|---|
| 64 |
|
|---|
| 65 |
/** |
|---|
| 66 |
* Dispatched when the virtual mouse fires an |
|---|
| 67 |
* MouseEvent.ROLL_OVER event. |
|---|
| 68 |
* @eventType flash.events.MouseEvent |
|---|
| 69 |
*/ |
|---|
| 70 |
[Event(name="rollOver", type="flash.events.MouseEvent")] |
|---|
| 71 |
|
|---|
| 72 |
/** |
|---|
| 73 |
* Dispatched when the virtual mouse fires an |
|---|
| 74 |
* MouseEvent.MOUSE_DOWN event. |
|---|
| 75 |
* @eventType flash.events.MouseEvent |
|---|
| 76 |
*/ |
|---|
| 77 |
[Event(name="mouseDown", type="flash.events.MouseEvent")] |
|---|
| 78 |
|
|---|
| 79 |
/** |
|---|
| 80 |
* Dispatched when the virtual mouse fires an |
|---|
| 81 |
* MouseEvent.MOUSE_UP event. |
|---|
| 82 |
* @eventType flash.events.MouseEvent |
|---|
| 83 |
*/ |
|---|
| 84 |
[Event(name="mouseUp", type="flash.events.MouseEvent")] |
|---|
| 85 |
|
|---|
| 86 |
/** |
|---|
| 87 |
* Dispatched when the virtual mouse fires an |
|---|
| 88 |
* MouseEvent.CLICK event. |
|---|
| 89 |
* @eventType flash.events.MouseEvent |
|---|
| 90 |
*/ |
|---|
| 91 |
[Event(name="click", type="flash.events.MouseEvent")] |
|---|
| 92 |
|
|---|
| 93 |
/** |
|---|
| 94 |
* Dispatched when the virtual mouse fires an |
|---|
| 95 |
* MouseEvent.DOUBLE_CLICK event. |
|---|
| 96 |
* @eventType flash.events.MouseEvent |
|---|
| 97 |
*/ |
|---|
| 98 |
[Event(name="doubleClick", type="flash.events.MouseEvent")] |
|---|
| 99 |
|
|---|
| 100 |
/** |
|---|
| 101 |
* The VirtualMouse class is used to create a programmatic |
|---|
| 102 |
* version of the users mouse that can be moved about the |
|---|
| 103 |
* Flash player stage firing off mouse events of the display |
|---|
| 104 |
* objects it interacts with. This can allow you to simulate |
|---|
| 105 |
* interaction with buttons and movie clips through ActionScript. |
|---|
| 106 |
* <br /> |
|---|
| 107 |
* Handled events include: |
|---|
| 108 |
* Event.MOUSE_LEAVE, |
|---|
| 109 |
* MouseEvent.MOUSE_MOVE, |
|---|
| 110 |
* MouseEvent.MOUSE_OUT, |
|---|
| 111 |
* MouseEvent.ROLL_OUT, |
|---|
| 112 |
* MouseEvent.MOUSE_OVER, |
|---|
| 113 |
* MouseEvent.ROLL_OVER, |
|---|
| 114 |
* MouseEvent.MOUSE_DOWN, |
|---|
| 115 |
* MouseEvent.MOUSE_UP. |
|---|
| 116 |
* MouseEvent.CLICK, and, |
|---|
| 117 |
* MouseEvent.DOUBLE_CLICK. |
|---|
| 118 |
* Along with dispatching those events for their respective |
|---|
| 119 |
* targets, the VirtualMouse instance will also dispatch the |
|---|
| 120 |
* event on itself allowing to capture which events are being |
|---|
| 121 |
* fired by the virtual mouse. The last event fired can also |
|---|
| 122 |
* be referenced in the lastEvent property. |
|---|
| 123 |
* <br /> |
|---|
| 124 |
* VirtualMouse mouse cannot: |
|---|
| 125 |
* activate states of SimpleButton instances, |
|---|
| 126 |
* change object focus, |
|---|
| 127 |
* handle mouseWheel related events, |
|---|
| 128 |
* change the system's cursor location, or |
|---|
| 129 |
* spoof the location of the mouseX and mouseY properties |
|---|
| 130 |
* (which some components rely on). |
|---|
| 131 |
*/ |
|---|
| 132 |
public class VirtualMouse extends EventDispatcher { |
|---|
| 133 |
|
|---|
| 134 |
public static const UPDATE:String = "update"; |
|---|
| 135 |
|
|---|
| 136 |
private var altKey:Boolean = false; |
|---|
| 137 |
private var ctrlKey:Boolean = false; |
|---|
| 138 |
private var shiftKey:Boolean = false; |
|---|
| 139 |
private var delta:int = 0; // mouseWheel unsupported |
|---|
| 140 |
|
|---|
| 141 |
private var _stage:Stage; |
|---|
| 142 |
private var _container:Sprite; |
|---|
| 143 |
private var target:InteractiveObject; |
|---|
| 144 |
|
|---|
| 145 |
private var location:Point; |
|---|
| 146 |
|
|---|
| 147 |
private var isLocked:Boolean = false; |
|---|
| 148 |
private var isDoubleClickEvent:Boolean = false; |
|---|
| 149 |
private static var _mouseIsDown:Boolean = false; |
|---|
| 150 |
|
|---|
| 151 |
private var disabledEvents:Object = new Object(); |
|---|
| 152 |
private var ignoredInstances:Dictionary = new Dictionary(true); |
|---|
| 153 |
|
|---|
| 154 |
private var _lastEvent:Event; |
|---|
| 155 |
private var lastMouseDown:Boolean = false; |
|---|
| 156 |
private var updateMouseDown:Boolean = false; |
|---|
| 157 |
private var lastLocation:Point; |
|---|
| 158 |
private var lastDownTarget:DisplayObject; |
|---|
| 159 |
private var lastWithinStage:Boolean = true; |
|---|
| 160 |
|
|---|
| 161 |
private var _useNativeEvents:Boolean = false; |
|---|
| 162 |
private var eventEvent:Class = VirtualMouseEvent; |
|---|
| 163 |
private var mouseEventEvent:Class = VirtualMouseMouseEvent; |
|---|
| 164 |
|
|---|
| 165 |
|
|---|
| 166 |
|
|---|
| 167 |
/** |
|---|
| 168 |
* A reference to the Stage instance. This |
|---|
| 169 |
* reference needs to be passed to the |
|---|
| 170 |
* VirtualMouse instance either in its constructor |
|---|
| 171 |
* or through assigning it's stage property. |
|---|
| 172 |
* Without a valid reference to the stage, the |
|---|
| 173 |
* virtual mouse will not function. |
|---|
| 174 |
* @see VirtualMouse() |
|---|
| 175 |
*/ |
|---|
| 176 |
public function get stage():Stage { |
|---|
| 177 |
return _stage; |
|---|
| 178 |
} |
|---|
| 179 |
public function set stage(s:Stage):void { |
|---|
| 180 |
var hadStage:Boolean; |
|---|
| 181 |
if (_stage){ |
|---|
| 182 |
hadStage = true; |
|---|
| 183 |
_stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyHandler); |
|---|
| 184 |
_stage.removeEventListener(KeyboardEvent.KEY_UP, keyHandler); |
|---|
| 185 |
}else{ |
|---|
| 186 |
hadStage = false; |
|---|
| 187 |
} |
|---|
| 188 |
_stage = s; |
|---|
| 189 |
if (_stage) { |
|---|
| 190 |
_stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHandler); |
|---|
| 191 |
_stage.addEventListener(KeyboardEvent.KEY_UP, keyHandler); |
|---|
| 192 |
target = _stage; |
|---|
| 193 |
if (!hadStage) update(); |
|---|
| 194 |
} |
|---|
| 195 |
} |
|---|
| 196 |
|
|---|
| 197 |
/** |
|---|
| 198 |
* |
|---|
| 199 |
* @param value Sprite container you want VirtualMouse to use with its testing of sub containers |
|---|
| 200 |
* @return |
|---|
| 201 |
*/ |
|---|
| 202 |
public function set container(value:Sprite):void |
|---|
| 203 |
{ |
|---|
| 204 |
_container = value; |
|---|
| 205 |
} |
|---|
| 206 |
public function get container():Sprite { return _container; } |
|---|
| 207 |
|
|---|
| 208 |
/** |
|---|
| 209 |
* The last event dispatched by the VirtualMouse |
|---|
| 210 |
* instance. This can be useful for preventing |
|---|
| 211 |
* event recursion if performing VirtualMouse |
|---|
| 212 |
* operations within MouseEvent handlers. |
|---|
| 213 |
*/ |
|---|
| 214 |
public function get lastEvent():Event { |
|---|
| 215 |
return _lastEvent; |
|---|
| 216 |
} |
|---|
| 217 |
|
|---|
| 218 |
/** |
|---|
| 219 |
* True if the virtual mouse is being |
|---|
| 220 |
* pressed, false if not. The mouse is |
|---|
| 221 |
* down for the virtual mouse if press() |
|---|
| 222 |
* was called. |
|---|
| 223 |
* @see press() |
|---|
| 224 |
* @see release() |
|---|
| 225 |
*/ |
|---|
| 226 |
public function get mouseIsDown():Boolean { |
|---|
| 227 |
return _mouseIsDown; |
|---|
| 228 |
} |
|---|
| 229 |
|
|---|
| 230 |
/** |
|---|
| 231 |
* The x location of the virtual mouse. If you are |
|---|
| 232 |
* setting both the x and y properties of the |
|---|
| 233 |
* virtual mouse at the same time, you would probably |
|---|
| 234 |
* want to lock the VirtualMouse instance to prevent |
|---|
| 235 |
* additional events from firing. |
|---|
| 236 |
* @see lock |
|---|
| 237 |
* @see unlock |
|---|
| 238 |
* @see y |
|---|
| 239 |
* @see setLocation() |
|---|
| 240 |
* @see getLocation() |
|---|
| 241 |
*/ |
|---|
| 242 |
public function get x():Number { |
|---|
| 243 |
return location.x; |
|---|
| 244 |
} |
|---|
| 245 |
public function set x(n:Number):void { |
|---|
| 246 |
location.x = n; |
|---|
| 247 |
if (!isLocked) update(); |
|---|
| 248 |
} |
|---|
| 249 |
|
|---|
| 250 |
/** |
|---|
| 251 |
* The y location of the virtual mouse. If you are |
|---|
| 252 |
* setting both the x and y properties of the |
|---|
| 253 |
* virtual mouse at the same time, you would probably |
|---|
| 254 |
* want to lock the VirtualMouse instance to prevent |
|---|
| 255 |
* additional events from firing. |
|---|
| 256 |
* @see lock |
|---|
| 257 |
* @see unlock |
|---|
| 258 |
* @see x |
|---|
| 259 |
* @see setLocation() |
|---|
| 260 |
* @see getLocation() |
|---|
| 261 |
*/ |
|---|
| 262 |
public function get y():Number { |
|---|
| 263 |
return location.y; |
|---|
| 264 |
} |
|---|
| 265 |
public function set y(n:Number):void { |
|---|
| 266 |
location.y = n; |
|---|
| 267 |
if (!isLocked) update(); |
|---|
| 268 |
} |
|---|
| 269 |
|
|---|
| 270 |
/** |
|---|
| 271 |
* Determines if the events dispatched by the |
|---|
| 272 |
* VirtualMouse instance are IVirualMouseEvent |
|---|
| 273 |
* Events (wrapping Event and MouseEvent) or events |
|---|
| 274 |
* of the native Event and MouseEvent type. When using |
|---|
| 275 |
* non-native events, you can check to see if the |
|---|
| 276 |
* events originated from VirtualMouse by seeing if |
|---|
| 277 |
* the events are of the type IVirualMouseEvent. |
|---|
| 278 |
* @see lastEvent |
|---|
| 279 |
*/ |
|---|
| 280 |
public function get useNativeEvents():Boolean { |
|---|
| 281 |
return _useNativeEvents; |
|---|
| 282 |
} |
|---|
| 283 |
public function set useNativeEvents(b:Boolean):void { |
|---|
| 284 |
if (b == _useNativeEvents) return; |
|---|
| 285 |
_useNativeEvents = b; |
|---|
| 286 |
if (_useNativeEvents){ |
|---|
| 287 |
eventEvent = VirtualMouseEvent; |
|---|
| 288 |
mouseEventEvent = VirtualMouseMouseEvent; |
|---|
| 289 |
}else{ |
|---|
| 290 |
eventEvent = Event; |
|---|
| 291 |
mouseEventEvent = MouseEvent; |
|---|
| 292 |
} |
|---|
| 293 |
} |
|---|
| 294 |
|
|---|
| 295 |
/** |
|---|
| 296 |
* Initializes a new VirtualMouse instance. |
|---|
| 297 |
* @param stage A reference to the stage instance. |
|---|
| 298 |
* @param startX The initial x location of |
|---|
| 299 |
* the virtual mouse. |
|---|
| 300 |
* @param startY The initial y location of |
|---|
| 301 |
* the virtual mouse. |
|---|
| 302 |
*/ |
|---|
| 303 |
public function VirtualMouse(stage:Stage = null, container:Sprite = null, startX:Number = 0, startY:Number = 0) { |
|---|
| 304 |
this.stage = stage; |
|---|
| 305 |
this.container = container; |
|---|
| 306 |
location = new Point(startX, startY); |
|---|
| 307 |
lastLocation = location.clone(); |
|---|
| 308 |
addEventListener(UPDATE, handleUpdate); |
|---|
| 309 |
update(); |
|---|
| 310 |
} |
|---|
| 311 |
|
|---|
| 312 |
/** |
|---|
| 313 |
* Returns the location (x and y) of the current |
|---|
| 314 |
* VirtualMouse instance. The location of the |
|---|
| 315 |
* virtual mouse is based in the global |
|---|
| 316 |
* coordinate space. |
|---|
| 317 |
* @return A Point instance representing the |
|---|
| 318 |
* location of the virtual mouse in |
|---|
| 319 |
* global coordinate space. |
|---|
| 320 |
* @see x |
|---|
| 321 |
* @see y |
|---|
| 322 |
* @see setLocation() |
|---|
| 323 |
*/ |
|---|
| 324 |
public function getLocation():Point { |
|---|
| 325 |
return location.clone(); |
|---|
| 326 |
} |
|---|
| 327 |
|
|---|
| 328 |
/** |
|---|
| 329 |
* Sets the location (x and y) of the current |
|---|
| 330 |
* VirtualMouse instance. There are two ways to |
|---|
| 331 |
* call setLocation, either passing in a single |
|---|
| 332 |
* Point instance, or by passing in two Number |
|---|
| 333 |
* instances representing x and y coordinates. |
|---|
| 334 |
* The location of the virtual mouse is based in |
|---|
| 335 |
* the global coordinate space. |
|---|
| 336 |
* @param a A Point instance or x Number value. |
|---|
| 337 |
* @param b A y Number value if a is a Number. |
|---|
| 338 |
* @see x |
|---|
| 339 |
* @see y |
|---|
| 340 |
* @see getLocation() |
|---|
| 341 |
*/ |
|---|
| 342 |
public function setLocation(a:*, b:* = null):void |
|---|
| 343 |
{ |
|---|
| 344 |
//log.debug("VM setLocation", a, b); |
|---|
| 345 |
if (a is Point) { |
|---|
| 346 |
var loc:Point = a as Point; |
|---|
| 347 |
location.x = loc.x; |
|---|
| 348 |
location.y = loc.y; |
|---|
| 349 |
}else{ |
|---|
| 350 |
location.x = Number(a); |
|---|
| 351 |
location.y = Number(b); |
|---|
| 352 |
} |
|---|
| 353 |
|
|---|
| 354 |
if (!isLocked) update(); |
|---|
| 355 |
} |
|---|
| 356 |
|
|---|
| 357 |
/** |
|---|
| 358 |
* Locks the current VirtualMouse instance |
|---|
| 359 |
* preventing updates from being made as |
|---|
| 360 |
* properties change within the instance. |
|---|
| 361 |
* To release and allow an update, call unlock(). |
|---|
| 362 |
* @see lock() |
|---|
| 363 |
* @see update() |
|---|
| 364 |
*/ |
|---|
| 365 |
public function lock():void { |
|---|
| 366 |
isLocked = true; |
|---|
| 367 |
} |
|---|
| 368 |
|
|---|
| 369 |
/** |
|---|
| 370 |
* Unlocks the current VirtualMouse instance |
|---|
| 371 |
* allowing updates to be made for the |
|---|
| 372 |
* dispatching of virtual mouse events. After |
|---|
| 373 |
* unlocking the instance, it will update and |
|---|
| 374 |
* additional calls to press(), release(), or |
|---|
| 375 |
* changing the location of the virtual mouse |
|---|
| 376 |
* will also invoke updates. |
|---|
| 377 |
* @see lock() |
|---|
| 378 |
* @see update() |
|---|
| 379 |
*/ |
|---|
| 380 |
public function unlock():void { |
|---|
| 381 |
isLocked = false; |
|---|
| 382 |
update(); |
|---|
| 383 |
} |
|---|
| 384 |
|
|---|
| 385 |
/** |
|---|
| 386 |
* Allows you to disable an event by type |
|---|
| 387 |
* preventing the virtual mouse from |
|---|
| 388 |
* dispatching that event during an update. |
|---|
| 389 |
* @param type The type for the event to |
|---|
| 390 |
* disable, e.g. MouseEvent.CLICK |
|---|
| 391 |
* @see enableEvent() |
|---|
| 392 |
*/ |
|---|
| 393 |
public function disableEvent(type:String):void { |
|---|
| 394 |
disabledEvents[type] = true; |
|---|
| 395 |
} |
|---|
| 396 |
|
|---|
| 397 |
/** |
|---|
| 398 |
* Re-enables an event disabled with |
|---|
| 399 |
* disableEvent. |
|---|
| 400 |
* @param type The type for the event to |
|---|
| 401 |
* enable, e.g. MouseEvent.CLICK |
|---|
| 402 |
* @see disableEvent() |
|---|
| 403 |
*/ |
|---|
| 404 |
public function enableEvent(type:String):void { |
|---|
| 405 |
if (type in disabledEvents) { |
|---|
| 406 |
delete disabledEvents[type]; |
|---|
| 407 |
} |
|---|
| 408 |
} |
|---|
| 409 |
|
|---|
| 410 |
/** |
|---|
| 411 |
* Ignores a display object preventing that |
|---|
| 412 |
* object from recieving events from the |
|---|
| 413 |
* virtual mouse. This is useful for instances |
|---|
| 414 |
* used for cursors which may always be under |
|---|
| 415 |
* the virtual mouse's location. |
|---|
| 416 |
* @param instance A reference to the |
|---|
| 417 |
* DisplayObject instance to ignore. |
|---|
| 418 |
* @see unignore() |
|---|
| 419 |
*/ |
|---|
| 420 |
public function ignore(instance:DisplayObject):void { |
|---|
| 421 |
ignoredInstances[instance] = true; |
|---|
| 422 |
} |
|---|
| 423 |
|
|---|
| 424 |
/** |
|---|
| 425 |
* Removes an instance from the ignore list |
|---|
| 426 |
* defined by ignore(). When an ingored |
|---|
| 427 |
* object is passed into unignore(), it will |
|---|
| 428 |
* be able to receive events from the virtual |
|---|
| 429 |
* mouse. |
|---|
| 430 |
* @param instance A reference to the |
|---|
| 431 |
* DisplayObject instance to unignore. |
|---|
| 432 |
* @see ignore() |
|---|
| 433 |
*/ |
|---|
| 434 |
public function unignore(instance:DisplayObject):void { |
|---|
| 435 |
if (instance in ignoredInstances){ |
|---|
| 436 |
delete ignoredInstances[instance]; |
|---|
| 437 |
} |
|---|
| 438 |
} |
|---|
| 439 |
|
|---|
| 440 |
/** |
|---|
| 441 |
* Simulates the pressing of the left |
|---|
| 442 |
* mouse button. To release the mouse |
|---|
| 443 |
* button, use release(). |
|---|
| 444 |
* @see release() |
|---|
| 445 |
* @see click() |
|---|
| 446 |
*/ |
|---|
| 447 |
public function press():void { |
|---|
| 448 |
//if (_mouseIsDown) return; |
|---|
| 449 |
updateMouseDown = true; |
|---|
| 450 |
_mouseIsDown = true; |
|---|
| 451 |
if (!isLocked) update(); |
|---|
| 452 |
} |
|---|
| 453 |
|
|---|
| 454 |
/** |
|---|
| 455 |
* Simulates the release of the left |
|---|
| 456 |
* mouse button. This method has no |
|---|
| 457 |
* effect unless press() was called first. |
|---|
| 458 |
* @see press() |
|---|
| 459 |
* @see click() |
|---|
| 460 |
*/ |
|---|
| 461 |
public function release():void { |
|---|
| 462 |
//if (!_mouseIsDown) return; |
|---|
| 463 |
updateMouseDown = true; |
|---|
| 464 |
_mouseIsDown = false; |
|---|
| 465 |
if (!isLocked) update(); |
|---|
| 466 |
} |
|---|
| 467 |
|
|---|
| 468 |
/** |
|---|
| 469 |
* Simulates a click of the left |
|---|
| 470 |
* mouse button (press and release) |
|---|
| 471 |
* @see press() |
|---|
| 472 |
* @see release() |
|---|
| 473 |
* @see click() |
|---|
| 474 |
* @see doubleClick() |
|---|
| 475 |
*/ |
|---|
| 476 |
public function click():void { |
|---|
| 477 |
press(); |
|---|
| 478 |
release(); |
|---|
| 479 |
} |
|---|
| 480 |
|
|---|
| 481 |
/** |
|---|
| 482 |
* Simulates a double-click of the left |
|---|
| 483 |
* mouse button (press and release twice). |
|---|
| 484 |
* Calling this command is the only way to |
|---|
| 485 |
* simulate a double-click for the virtual |
|---|
| 486 |
* mouse. Calling press() and release() or |
|---|
| 487 |
* click() is rapid succession will not |
|---|
| 488 |
* invoke a double-click event. The double-click |
|---|
| 489 |
* event will also only fire for an instance |
|---|
| 490 |
* if it's doubleClickEnabled property is |
|---|
| 491 |
* set to true. |
|---|
| 492 |
* @see click() |
|---|
| 493 |
*/ |
|---|
| 494 |
public function doubleClick():void { |
|---|
| 495 |
// if locked, doubleClick will |
|---|
| 496 |
// not fire but the mouse will |
|---|
| 497 |
// be released if not already |
|---|
| 498 |
if (isLocked) { |
|---|
| 499 |
release(); |
|---|
| 500 |
}else{ |
|---|
| 501 |
|
|---|
| 502 |
// call update with a click, press, then release |
|---|
| 503 |
// and double-click notification for release |
|---|
| 504 |
click(); |
|---|
| 505 |
press(); |
|---|
| 506 |
isDoubleClickEvent = true; |
|---|
| 507 |
release(); |
|---|
| 508 |
isDoubleClickEvent = false; |
|---|
| 509 |
} |
|---|
| 510 |
} |
|---|
| 511 |
|
|---|
| 512 |
/*Added by Jim Kremens kremens@gmail.com 08/16/07 */ |
|---|
| 513 |
public function exitContainer():void { |
|---|
| 514 |
if( !container ) return; |
|---|
| 515 |
var targetLocal:Point = target.globalToLocal(location); |
|---|
| 516 |
//log.debug("Targetlocal", target != container); |
|---|
| 517 |
if (!disabledEvents[MouseEvent.MOUSE_OUT]) { |
|---|
| 518 |
_lastEvent = new mouseEventEvent(MouseEvent.MOUSE_OUT, true, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 519 |
container.dispatchEvent(new mouseEventEvent(MouseEvent.MOUSE_OUT, true, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta)); |
|---|
| 520 |
dispatchEvent(new mouseEventEvent(MouseEvent.MOUSE_OUT, true, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta)); |
|---|
| 521 |
} |
|---|
| 522 |
if (!disabledEvents[MouseEvent.ROLL_OUT]) { // rolls do not propagate |
|---|
| 523 |
_lastEvent = new mouseEventEvent(MouseEvent.ROLL_OUT, false, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 524 |
container.dispatchEvent(new mouseEventEvent(MouseEvent.ROLL_OUT, false, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta)); |
|---|
| 525 |
dispatchEvent(new mouseEventEvent(MouseEvent.ROLL_OUT, false, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta)); |
|---|
| 526 |
} |
|---|
| 527 |
if (target != container) { |
|---|
| 528 |
if (!disabledEvents[MouseEvent.MOUSE_OUT]) { |
|---|
| 529 |
_lastEvent = new mouseEventEvent(MouseEvent.MOUSE_OUT, true, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 530 |
target.dispatchEvent(new mouseEventEvent(MouseEvent.MOUSE_OUT, true, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta)); |
|---|
| 531 |
dispatchEvent(new mouseEventEvent(MouseEvent.MOUSE_OUT, true, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta)); |
|---|
| 532 |
} |
|---|
| 533 |
if (!disabledEvents[MouseEvent.ROLL_OUT]) { // rolls do not propagate |
|---|
| 534 |
_lastEvent = new mouseEventEvent(MouseEvent.ROLL_OUT, false, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 535 |
target.dispatchEvent(new mouseEventEvent(MouseEvent.ROLL_OUT, false, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta)); |
|---|
| 536 |
dispatchEvent(new mouseEventEvent(MouseEvent.ROLL_OUT, false, false, targetLocal.x, targetLocal.y, container, ctrlKey, altKey, shiftKey, _mouseIsDown, delta)); |
|---|
| 537 |
} |
|---|
| 538 |
} |
|---|
| 539 |
//reset the target to the stage, which is the value it starts at. |
|---|
| 540 |
target = _stage; |
|---|
| 541 |
} |
|---|
| 542 |
|
|---|
| 543 |
/** |
|---|
| 544 |
* Updates the VirtualMouse instance's state |
|---|
| 545 |
* to reflect a change in the virtual mouse. |
|---|
| 546 |
* Within this method all events will be dispatched. |
|---|
| 547 |
* update() is called any time a VirtualMouse |
|---|
| 548 |
* property is changed unless lock() was used to |
|---|
| 549 |
* lock the instance. update() will then not be |
|---|
| 550 |
* called until unlock() is used to unlock |
|---|
| 551 |
* the instance. Typically you would never call |
|---|
| 552 |
* update() directly; it is called automatically |
|---|
| 553 |
* by the VirtualMouse class. Calling update() |
|---|
| 554 |
* manually will override lock(). Whenever update() |
|---|
| 555 |
* is called, the UPDATE event is dispatched. |
|---|
| 556 |
* @see lock() |
|---|
| 557 |
* @see unlock() |
|---|
| 558 |
*/ |
|---|
| 559 |
public function update():void { |
|---|
| 560 |
// dispatch an update event indicating that |
|---|
| 561 |
// an update has occured |
|---|
| 562 |
dispatchEvent(new Event(UPDATE, false, false)); |
|---|
| 563 |
} |
|---|
| 564 |
|
|---|
| 565 |
private function handleUpdate(event:Event):void |
|---|
| 566 |
{ |
|---|
| 567 |
if (!container) return; |
|---|
| 568 |
|
|---|
| 569 |
// go through each objectsUnderPoint checking: |
|---|
| 570 |
// 1) is not ignored |
|---|
| 571 |
// 2) is InteractiveObject |
|---|
| 572 |
// 3) mouseEnabled |
|---|
| 573 |
// 4) all parents have mouseChildren |
|---|
| 574 |
// if not interactive object, defer interaction to next object in list |
|---|
| 575 |
// if is interactive and enabled, give interaction and ignore rest |
|---|
| 576 |
|
|---|
| 577 |
// var p:Point = CoordinateTools.localToLocal(container, stage, location); |
|---|
| 578 |
//var objectsUnderPoint:Array = container.getObjectsUnderPoint(p); |
|---|
| 579 |
|
|---|
| 580 |
if( container.scrollRect ){ |
|---|
| 581 |
PaperLogger.warning("The container that virtualMouse is trying to test against has a scrollRect defined, and may cause an issue with finding objects under a defined point. Use MovieMaterial.rect to set a rectangle area instead"); |
|---|
| 582 |
} |
|---|
| 583 |
var originalPoint:Point = new Point(); |
|---|
| 584 |
originalPoint.x = container.x; |
|---|
| 585 |
originalPoint.y = container.y; |
|---|
| 586 |
container.x = container.y = 0; |
|---|
| 587 |
|
|---|
| 588 |
var objectsUnderPoint:Array = container.getObjectsUnderPoint(location); |
|---|
| 589 |
|
|---|
| 590 |
container.x = originalPoint.x; |
|---|
| 591 |
container.y = originalPoint.y; |
|---|
| 592 |
|
|---|
| 593 |
var currentTarget:InteractiveObject; |
|---|
| 594 |
var currentParent:DisplayObject; |
|---|
| 595 |
|
|---|
| 596 |
var i:int = objectsUnderPoint.length; |
|---|
| 597 |
|
|---|
| 598 |
while (i--) { |
|---|
| 599 |
currentParent = objectsUnderPoint[i]; |
|---|
| 600 |
|
|---|
| 601 |
// go through parent hierarchy |
|---|
| 602 |
while (currentParent) { |
|---|
| 603 |
|
|---|
| 604 |
// don't use ignored instances as the target |
|---|
| 605 |
if (ignoredInstances[currentParent] |
|---|
| 606 |
) { |
|---|
| 607 |
currentTarget = null; |
|---|
| 608 |
break; |
|---|
| 609 |
} |
|---|
| 610 |
|
|---|
| 611 |
// invalid target if in a SimpleButton |
|---|
| 612 |
if (currentTarget && currentParent is SimpleButton) |
|---|
| 613 |
{ |
|---|
| 614 |
//log.debug("found SimpleButton - setting currentTarget to null"); |
|---|
| 615 |
currentTarget = null; |
|---|
| 616 |
|
|---|
| 617 |
// invalid target if a parent has a |
|---|
| 618 |
// false mouseChildren |
|---|
| 619 |
} else if (currentTarget && !DisplayObjectContainer(currentParent).mouseChildren) |
|---|
| 620 |
{ |
|---|
| 621 |
//log.debug("parent false mouseChildren - setting currentTarget to null"); |
|---|
| 622 |
currentTarget = null; |
|---|
| 623 |
} |
|---|
| 624 |
|
|---|
| 625 |
// define target if an InteractiveObject |
|---|
| 626 |
// and mouseEnabled is true |
|---|
| 627 |
if (!currentTarget && currentParent is InteractiveObject && InteractiveObject(currentParent).mouseEnabled) |
|---|
| 628 |
{ |
|---|
| 629 |
//log.debug("found InteractiveObject && mouseEnabled = true - setting currentTarget"); |
|---|
| 630 |
currentTarget = InteractiveObject(currentParent); |
|---|
| 631 |
} |
|---|
| 632 |
|
|---|
| 633 |
// next parent in hierarchy |
|---|
| 634 |
currentParent = currentParent.parent; |
|---|
| 635 |
} |
|---|
| 636 |
|
|---|
| 637 |
// if a currentTarget was found |
|---|
| 638 |
// ignore all other objectsUnderPoint |
|---|
| 639 |
if (currentTarget){ |
|---|
| 640 |
break; |
|---|
| 641 |
} |
|---|
| 642 |
} |
|---|
| 643 |
|
|---|
| 644 |
|
|---|
| 645 |
|
|---|
| 646 |
// if a currentTarget was not found |
|---|
| 647 |
// the currentTarget is the stage |
|---|
| 648 |
if (!currentTarget) |
|---|
| 649 |
{ |
|---|
| 650 |
//trace("no CurrentTarget", container.hitTestPoint(location.x, location.y)); |
|---|
| 651 |
currentTarget = container; |
|---|
| 652 |
//currentTarget = _stage; |
|---|
| 653 |
//log.debug("no new target found, using stage"); |
|---|
| 654 |
} |
|---|
| 655 |
|
|---|
| 656 |
// get local coordinate locations |
|---|
| 657 |
var targetLocal:Point = target.globalToLocal(location); |
|---|
| 658 |
var currentTargetLocal:Point = currentTarget.globalToLocal(location); |
|---|
| 659 |
|
|---|
| 660 |
|
|---|
| 661 |
// move event |
|---|
| 662 |
if (lastLocation.x != location.x || lastLocation.y != location.y) |
|---|
| 663 |
{ |
|---|
| 664 |
var withinStage:Boolean = false; |
|---|
| 665 |
if(stage) withinStage = (location.x >= 0 && location.y >= 0 && location.x <= stage.stageWidth && location.y <= stage.stageHeight); |
|---|
| 666 |
|
|---|
| 667 |
// mouse leave if left stage |
|---|
| 668 |
if (!withinStage && lastWithinStage && !disabledEvents[Event.MOUSE_LEAVE]){ |
|---|
| 669 |
_lastEvent = new eventEvent(Event.MOUSE_LEAVE, false, false); |
|---|
| 670 |
stage.dispatchEvent(_lastEvent); |
|---|
| 671 |
dispatchEvent(_lastEvent); |
|---|
| 672 |
} |
|---|
| 673 |
|
|---|
| 674 |
// only mouse move if within stage |
|---|
| 675 |
if (withinStage && !disabledEvents[MouseEvent.MOUSE_MOVE]){ |
|---|
| 676 |
_lastEvent = new mouseEventEvent(MouseEvent.MOUSE_MOVE, true, false, currentTargetLocal.x, currentTargetLocal.y, currentTarget, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 677 |
currentTarget.dispatchEvent(_lastEvent); |
|---|
| 678 |
dispatchEvent(_lastEvent); |
|---|
| 679 |
} |
|---|
| 680 |
|
|---|
| 681 |
// remember if within stage |
|---|
| 682 |
lastWithinStage = withinStage; |
|---|
| 683 |
} |
|---|
| 684 |
|
|---|
| 685 |
// roll/mouse (out and over) events |
|---|
| 686 |
|
|---|
| 687 |
if (currentTarget != target) |
|---|
| 688 |
{ |
|---|
| 689 |
// off of last target |
|---|
| 690 |
if (!disabledEvents[MouseEvent.MOUSE_OUT]){ |
|---|
| 691 |
_lastEvent = new mouseEventEvent(MouseEvent.MOUSE_OUT, true, false, targetLocal.x, targetLocal.y, currentTarget, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 692 |
target.dispatchEvent(_lastEvent); |
|---|
| 693 |
dispatchEvent(_lastEvent); |
|---|
| 694 |
} |
|---|
| 695 |
if (!disabledEvents[MouseEvent.ROLL_OUT]){ // rolls do not propagate |
|---|
| 696 |
_lastEvent = new mouseEventEvent(MouseEvent.ROLL_OUT, false, false, targetLocal.x, targetLocal.y, currentTarget, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 697 |
target.dispatchEvent(_lastEvent); |
|---|
| 698 |
dispatchEvent(_lastEvent); |
|---|
| 699 |
} |
|---|
| 700 |
|
|---|
| 701 |
// on to current target |
|---|
| 702 |
if (!disabledEvents[MouseEvent.MOUSE_OVER]){ |
|---|
| 703 |
//log.debug("*** MOUSEOVER****"); |
|---|
| 704 |
_lastEvent = new mouseEventEvent(MouseEvent.MOUSE_OVER, true, false, currentTargetLocal.x, currentTargetLocal.y, target, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 705 |
currentTarget.dispatchEvent(_lastEvent); |
|---|
| 706 |
dispatchEvent(_lastEvent); |
|---|
| 707 |
} |
|---|
| 708 |
if (!disabledEvents[MouseEvent.ROLL_OVER]){ // rolls do not propagate |
|---|
| 709 |
//log.debug("*** ROLLOVER****"); |
|---|
| 710 |
_lastEvent = new mouseEventEvent(MouseEvent.ROLL_OVER, false, false, currentTargetLocal.x, currentTargetLocal.y, target, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 711 |
currentTarget.dispatchEvent(_lastEvent); |
|---|
| 712 |
dispatchEvent(_lastEvent); |
|---|
| 713 |
} |
|---|
| 714 |
|
|---|
| 715 |
|
|---|
| 716 |
} |
|---|
| 717 |
|
|---|
| 718 |
// click/up/down events |
|---|
| 719 |
if (updateMouseDown) { |
|---|
| 720 |
if (_mouseIsDown) { |
|---|
| 721 |
|
|---|
| 722 |
if (!disabledEvents[MouseEvent.MOUSE_DOWN]){ |
|---|
| 723 |
_lastEvent = new mouseEventEvent(MouseEvent.MOUSE_DOWN, true, false, currentTargetLocal.x, currentTargetLocal.y, currentTarget, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 724 |
currentTarget.dispatchEvent(_lastEvent); |
|---|
| 725 |
dispatchEvent(_lastEvent); |
|---|
| 726 |
} |
|---|
| 727 |
|
|---|
| 728 |
// remember last down |
|---|
| 729 |
lastDownTarget = currentTarget; |
|---|
| 730 |
updateMouseDown = false; |
|---|
| 731 |
// mouse is up |
|---|
| 732 |
}else{ |
|---|
| 733 |
if (!disabledEvents[MouseEvent.MOUSE_UP]){ |
|---|
| 734 |
_lastEvent = new mouseEventEvent(MouseEvent.MOUSE_UP, true, false, currentTargetLocal.x, currentTargetLocal.y, currentTarget, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 735 |
currentTarget.dispatchEvent(_lastEvent); |
|---|
| 736 |
dispatchEvent(_lastEvent); |
|---|
| 737 |
} |
|---|
| 738 |
|
|---|
| 739 |
if (!disabledEvents[MouseEvent.CLICK] && currentTarget == lastDownTarget) { |
|---|
| 740 |
_lastEvent = new mouseEventEvent(MouseEvent.CLICK, true, false, currentTargetLocal.x, currentTargetLocal.y, currentTarget, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 741 |
currentTarget.dispatchEvent(_lastEvent); |
|---|
| 742 |
dispatchEvent(_lastEvent); |
|---|
| 743 |
} |
|---|
| 744 |
|
|---|
| 745 |
// clear last down |
|---|
| 746 |
lastDownTarget = null; |
|---|
| 747 |
updateMouseDown = false; |
|---|
| 748 |
} |
|---|
| 749 |
} |
|---|
| 750 |
|
|---|
| 751 |
// explicit call to doubleClick() |
|---|
| 752 |
if (isDoubleClickEvent && !disabledEvents[MouseEvent.DOUBLE_CLICK] && currentTarget.doubleClickEnabled) { |
|---|
| 753 |
_lastEvent = new mouseEventEvent(MouseEvent.DOUBLE_CLICK, true, false, currentTargetLocal.x, currentTargetLocal.y, currentTarget, ctrlKey, altKey, shiftKey, _mouseIsDown, delta); |
|---|
| 754 |
currentTarget.dispatchEvent(_lastEvent); |
|---|
| 755 |
dispatchEvent(_lastEvent); |
|---|
| 756 |
} |
|---|
| 757 |
|
|---|
| 758 |
// remember last values |
|---|
| 759 |
lastLocation = location.clone(); |
|---|
| 760 |
lastMouseDown = _mouseIsDown; |
|---|
| 761 |
target = currentTarget; |
|---|
| 762 |
} |
|---|
| 763 |
|
|---|
| 764 |
private function keyHandler(event:KeyboardEvent):void { |
|---|
| 765 |
// update properties used in MouseEvents |
|---|
| 766 |
altKey = event.altKey; |
|---|
| 767 |
ctrlKey = event.ctrlKey; |
|---|
| 768 |
shiftKey = event.shiftKey; |
|---|
| 769 |
} |
|---|
| 770 |
} |
|---|
| 771 |
} |
|---|