I use for my flash application external touch-input. Signals from touch panel I receive via TUIO library for as3 ( https://code.google.com/p/tuio-as3/ )
I have sometimes problem then TuioManager wrong detects object which must receive touch input.
private function getTopDisplayObjectUnderPoint(point:Point):DisplayObject {
var targets:Array = stage.getObjectsUnderPoint(point);
var item:DisplayObject = (targets.length > 0) ? targets[targets.length - 1] : stage;
if (this.touchTargetDiscoveryMode == TOUCH_TARGET_DISCOVERY_MOUSE_ENABLED) {
while (targets.length > 0) {
item = targets.pop() as DisplayObject;
//ignore debug cursor/object/blob and send object under debug cursor/object/blob
if ((item is ITuioDebugCursor || item is ITuioDebugBlob || item is ITuioDebugObject || item is ITuioDebugTextSprite) && targets.length > 0) {
continue;
}
if (item.parent != null && !(item is InteractiveObject)) item = item.parent;
if (item is InteractiveObject) {
if ((item as InteractiveObject).mouseEnabled) return item;
}
}
item = stage;
}
else if (this.touchTargetDiscoveryMode == TOUCH_TARGET_DISCOVERY_IGNORELIST) {
while (targets.length > 0) {
item = targets.pop();
//ignore debug cursor/object/blob and send object under debug cursor/object/blob
if ((item is ITuioDebugCursor || item is ITuioDebugBlob || item is ITuioDebugObject || item is ITuioDebugTextSprite) && targets.length > 0) {
continue;
}
if (!bubbleListCheck(item)) return item;
}
item = stage;
}
return item;
}
I used this.touchTargetDiscoveryMode == TOUCH_TARGET_DISCOVERY_MOUSE_ENABLED.
This function does not use mouseChildren property.
For example, I use world map in fxg graphic and I want disable all its children: worldMap.mouseChildren = false;
But it works if I use system mouse input, but not for TUIO. Result of function getTopDisplayObjectUnderPoint will be one of child MovieClip. In trace I see hierarchy like as:
worldMap
MovieClip
....
MovieClip
Yes, I can set recursively all property mouseEnabled = false for children of worldMap. It can fix for only this problem, but not problem with wrong object selection in more global case.
I tried to modify this function and wrote two helper function:
private function isMouseChildrenEnabled(obj:DisplayObject):Boolean {
if (obj.parent == null) {
return true;
}
return obj.parent.mouseChildren && isMouseChildrenEnabled(obj.parent);
}
private function findMouseEnabledObject(obj:InteractiveObject):InteractiveObject
{
if (obj.mouseEnabled && isMouseChildrenEnabled(obj))
return obj;
return obj.parent ? findMouseEnabledObject(obj.parent) : null;
}
private function getTopDisplayObjectUnderPoint(point:Point):DisplayObject {
var targets:Array = stage.getObjectsUnderPoint(point);
var item:DisplayObject = (targets.length > 0) ? targets[targets.length - 1] : stage;
if(this.touchTargetDiscoveryMode == TOUCH_TARGET_DISCOVERY_MOUSE_ENABLED){
while(targets.length > 0) {
item = targets.pop() as DisplayObject;
//ignore debug cursor/object/blob and send object under debug cursor/object/blob
if((item is ITuioDebugCursor || item is ITuioDebugBlob || item is ITuioDebugObject || item is ITuioDebugTextSprite) && targets.length > 0){
continue;
}
if (item.parent != null && !(item is InteractiveObject)) item = item.parent;
if (item is InteractiveObject) {
var io:InteractiveObject = findMouseEnabledObject(item as InteractiveObject);
if (io) return io;
}
}
item = stage;
} else if (this.touchTargetDiscoveryMode == TOUCH_TARGET_DISCOVERY_IGNORELIST) {
while(targets.length > 0) {
item = targets.pop();
//ignore debug cursor/object/blob and send object under debug cursor/object/blob
if((item is ITuioDebugCursor || item is ITuioDebugBlob || item is ITuioDebugObject || item is ITuioDebugTextSprite) && targets.length > 0){
continue;
}
if (!bubbleListCheck(item)) return item;
}
item = stage;
}
return item;
}
But after new fixes we have new bugs :( I see bug if I use flex drag drop. During drag drop flex shows dragged image and tuio detects wrong drop target. In trace stage.getObjectsUnderPoint() I see something like as:
[n] - image (mouseEnabled=true, mouseChildren=true)
parent: embed_swf_drag_cursor... (mouseEnabled=false, mouseChildren=false)
parent: application_systemManager... (mouseEnabled=true, mouseChildren=true)
parent: stage
[n-1] - borderContainer (mouseEnabled=true, mouseChildren=true) - it is my drop target
In result I have systemManager as target, but I need BorderContainer.
How correct find enabled object for user input?
P.S. Tested on Linux and Windows flash players.
Update 13.11
I tried to write function which get enabled object under point:
private function getTopEnabledObject(object:DisplayObjectContainer, hitPoint:Point):InteractiveObject
{
if (!object.mouseChildren)
return null;
var child:DisplayObject;
for (var i:int = object.numChildren - 1; i >= 0; i--)
{
child = object.getChildAt(i);
if (child.visible && child is InteractiveObject && child.hitTestPoint(hitPoint.x, hitPoint.y, true))
{
if (child is DisplayObjectContainer)
{
var target:InteractiveObject = getTopEnabledObject(child as DisplayObjectContainer, hitPoint);
if (target)
return target;
}
if ((child as InteractiveObject).mouseEnabled)
return child as InteractiveObject;
}
}
return null;
}
It works slowly in 5-10 times. And I had crashes after many-many touches in short time.