Using the TuioManager
The TuioManager is the way to go if you want to create a Tuio tracker input based flash application without the need to tinker with the Tuio tracking data itself.
The TuioManager is an implementation of the ITuioListener interface and processes the data received by the TuioClient and turns it into events you can handle by using event listeners. The TuioManager uses two custom event classes but is also able to dispatch MouseEvents.
The two custom event classes are:
- TuioTouchEvent: Works like the MouseEvent just for touches tracked by the Tuio tracker. Will probably be the event used in most cases. Is dispatched onto the stage's children.
- TuioEvent: Is an event equivalent of the callback functions defined in the ITuioListener interface. Gives you more control on what to do with the actual tracking data. Is dispatched onto the TuioManager itself.
Initializing the TuioManager
Since the TuioManager needs a TuioClient to receive tracking data you first have to create a new TuioClient with the IOSCConnector for the connection method you want to use. With this TuioClient you then can create a new TuioManager.
-
var tuioClient:TuioClient = new TuioClient(new UDPConnector());
-
var tuioManager:TuioManager = TuioManager.init(stage);
-
tuioClient.addListener(tuioManager);
The TuioManager will automatically start to dispatch TuioEvent and TouchEvents as soon as tracking data is received. Since the TuioManager searches the whole child tree of the stage to find the topmost object under a certain touch point to dispatch a TouchEvent it might happen that you want to exclude objects from this touchtarget discovery.
Touchtarget discovery
The Touchtarget discovery can be configured by setting the TuioManager.touchTargetDiscoveryMode.
There are the following possibilities:
- TuioManager.TOUCH_TARGET_DISCOVERY_MOUSE_ENABLED
Is the default setting and simply checks if the mouseEnabled property is set true before dispatching a TouchEvent. The mouseChildren property currently isn't checked but may be added later depending on feedback. - TuioManager.TOUCH_TARGET_DISCOVERY_NONE
Nomen est omen -> nothing is excluded. - TuioManager.TOUCH_TARGET_DISCOVERY_IGNORELIST
An ignore list is used to exclude DisplayObjects. They can be added to the list via TuioManager.addToIgnoreList or removed again via TuioManager.removeFromIgnoreList. If a DisplayObjectContainer is added to the list all of its children won't receive TouchEvents
MouseEvents
The TuioManager can also dispatch MouseEvents in addition to TouchEvents and TuioEvents. To enable this you have to set TuioManager.dispatchMouseEvents = true. Note that this will also set the touchTargetDiscoveryMode back to TuioManager.TOUCH_TARGET_DISCOVERY_MOUSE_ENABLED in case you have changed that.
Blobs and Objects
TUIO distinguishes between three types of tracked objects. Your fingers are basically "cursor" messages which the TuioManager automatically reacts to. Fiducials are called "objects" and everything else is a "blob". Depending on your setup you might need the TuioManager to react to blobs and objects. You can achieve this by setting the TuioManager's properties triggerTouchOnBlob and/or triggerTouchOnObject true.
Touch behaviour
You can directly change the behaviour of the doubleTap and hold TouchEvents by setting properties of the TuioManager.
- doubleTapTimeout: With this property you can set the minimum time that may pass between two taps so that they are still considered a double tap.
- doubleTapDistance: By setting this you can control the maximum allowed distance between the two taps. You'll maybe need to configure this depending on the sensibility and display/toucharea ratio of you setup.
- holdTimeout: Controls the time that has to pass until a still touch triggers a hold TouchEvent.
Example project
You can find a similar project within the latest downloadable package in the TuioManagerExample so I won't write fully working code in order to focus on the important stuff.
In this project for each touch a circle is drawn but also an additional circle if a touch is released. This circle can then be removed by again tapping it.
At first the TuioManager is initialized and the eventlisteners are added.
-
this.tuio = new TuioClient(new UDPConnector());
-
this.tuioManager = TuioManager.init(stage);
-
this.tuio.addListener(this.tuioManager );
-
-
this.tuioManager.addEventListener(TuioEvent.ADD, addHandler);
-
this.tuioManager.addEventListener(TuioEvent.UPDATE, updateHandler);
-
this.tuioManager.addEventListener(TuioEvent.REMOVE, removeHandler);
-
-
stage.addEventListener(TouchEvent.TOUCH_UP, tapHandler);
As you can see there are both TuioEvent and TouchEvents used here. The TuioEvent used for drawing a circle for each touch to give a visual feedback to the user. The TouchEvent is used to draw a circle after a touch. A TuioEvent.REMOVE listener would have done the same job but I used it here for example purposes.
Next I'll explain the the TuioEvent listeners attached to the TuioManager above. The following function creates a new circle if there is a new object tracked by the tracker. Notice that the circle is set mouseEnabled = false in order to keep it from receiving TouchEvents since it would be on top now and would normally receive those.
-
public function addHandler(e:TuioEvent):void {
-
var circle:Circle = new Circle(e.tuioContainer.sessionID.toString(), stage, e.tuioContainer.x*stage.stageWidth, e.tuioContainer.y * stage.stageHeight, this.circleSize, 0xee3333);
-
circle.mouseEnabled = false;
-
}
Next up is the updatehandler which updates the circles created in the addHandler according to the new tracking position.
-
public function updateHandler(e:TuioEvent):void {
-
currentCircle = stage.getChildByName(e.tuioContainer.sessionID.toString()) as Circle;
-
currentCircle.x = e.tuioContainer.x*stage.stageWidth;
-
currentCircle.y = e.tuioContainer.y*stage.stageHeight;
-
}
Last but not least the removeHandler removes the circles if the corresponding tracked object was removed from the tracking area.
-
public function removeHandler(e:TuioEvent):void {
-
currentCircle = stage.getChildByName(e.tuioContainer.sessionID.toString()) as Circle;
-
stage.removeChild(currentCircle);
-
}
The following tapHandler creates a circle if a touch is released. There is also an eventlistener added to the circle to remove it when it is tapped. Please note that since the event listenere is attached to the stage and TOUCH_UP is a bubbling event there has to be a check whether the stage is the actual target of the TouchEvent.
-
public function tapHandler(e:TouchEvent):void {
-
if(e.relatedObject == stage){
-
var circle:Circle = new Circle("tabring", stage, e.tuioContainer.x*stage.stageWidth, e.tuioContainer.y * stage.stageHeight, this.circleSize+5, 0xcc6600);
-
circle.addEventListener(TouchEvent.TAP, circleTapHandler);
-
}
-
}
The circleTapHandler is added to every circle created in the tapHandler and removes the target from the stage.
-
public function circleTapHandler(e:TouchEvent):void {
-
stage.removeChild(e.relatedObject);
-
}
If you find errors or have any additional questions please use the comments to this article to let us know how we can improve it
February 12th, 2010 - 21:37
Awesome work, keep it up. This is amazing stuff!
July 5th, 2010 - 17:26
im trying to run this code but i dont get any response
do i need to run the cammera and use markers
December 10th, 2010 - 18:23
Thanks for your work on this. Makes life MUCH easier.
I have everything working with ReacTIVision, the upd-flashlc-bridge and a Flash app firing ADD_OBJECT and REMOVE_OBJECT events. I’m unclear, though, on how to read information about the object that has been detected. Is there a way to identify the fiducial ID detected?
Thanks for your help.
December 10th, 2010 - 22:01
What you are looking for is the classID property of the TuioContainer attached to the TuioEvent -> cast it to TuioObject in order to get that value. You can also try using the fiducial subpackage which has some additional functionality that might be helpful for working with fiducials.
March 29th, 2011 - 21:40
Hi, i’m looking for a method that would list the current cursors that are over a same displayObject… is there something like this in the lib ?
thanks
March 29th, 2011 - 21:57
Hi, no there currently isn’t such a method but I may add it in the future. For now you can either get this behaviour by modifying the TuioManager (have a look at the lastTarget array) or by using the TouchEvents
March 30th, 2011 - 16:07
Hi, thanks for the quick answer.
I put some suggestions in the comments of this page :
http://bubblebird.at/tuioflash/tuio-as3-library/
April 28th, 2011 - 22:21
this is great. Good job
May 26th, 2011 - 19:52
Hi gimmix, been using your lib a lot lately and came up with quick improvements that i needed to make real production setups fit in customer constraints :
– Needed to use the screen in vertical position, but calibration software from our touch overlay provider didn’t accept driver’s screen rotation handling and wouldn’t calibrate correctly when in portrait mode.
—> I added a “verticalScreen” property that basically invert X and Y in TuioContainer, which makes coordinates match the actual screen orientation. Could be even better with a “screenOrientation” or “screenRotation” property that would really compensate any position or rotation of screens (with complex setups for exemple).
– Needed the RotateGesture to be trigger even if only one finger is moving (i. e. when a finger turn around the other one).
—> I changed in the TuioManager the way the TOUCH_MOVE event is dispatched to always dispatch it when finger is over. Could be set by a property because selective Move event dispatching could be interesting in some (fewer i believe) situations.
– Needed a real TAP filtering, because the lib currently dispatch it always with touch up. So no comfortable feeling for touch with distance and timing filtering.
—> I added in the TuioManager some code to be able to configure minimum tap distance and minimum tap timing, so TouchEvent.TAP are only dispatched when it occurs in a certain amount of time and inside a certain perimeter. Good click alternative and makes interface coding much clearer (when not using MouseEvent).
– Changed few lines in TuioDebug to get it fully working on black screens (text color was not changeable).
I think that’s all for the time being, this lib is really powerful and extensible, easy to understand and comfortable to digg into the code and i would be happy to give you the sources of my modifications if you’re interested.
Have a nice day (or is it night already ?),
Ben
May 27th, 2011 - 19:10
Thanks for the suggestions I’ll definitely keep them in mind for future revisions. If it isn’t too much trouble I’d be glad if you could send me your modified code so I can have a look at it and maybe copy some stuff
The RotateGesture maybe could have been done by simply modifying the RotateGesture class although depending on the revision you work with this could turn out pretty tricky.
June 9th, 2011 - 20:42
Hey, I am trying to figure out your library and for whatever reason I cannot for the life of me get any objects to be detected. I can get TOUCH_DOWN detected easy enough but ADD_OBJECT does not seem to be firing. Is there an example anywhere that I could look at to see an object detected reliably?
July 18th, 2011 - 20:05
Hi there,
my trying to figure out how to detect objects.
I’m running TuioKinect 0.1, udp-flashlc bridge and a simple TuioClient AIR 2.0 app on MacOS… At the moment, it works great for cursor detection.
When I start reacTIVision (with TuioKinect already running), I got the message “camera disconnected”. No TuioObject events firing obviously…
What is the correct way to track fiducials ?
Did I made something wrong with the couple TuioKinect/reacTIVision ? Any help very appreciated
thanks for this huge work
July 18th, 2011 - 21:38
well my gues would be that both rackers can’t use the same webcam at the same time, so you will need either two webcams, one for each tracker, or a webcam multiplexer which basically is a software that ceates multiple virtual webcams with the same video feed. On which platform are you working on?
July 19th, 2011 - 10:00
Thanks for the quick reply, I’m currently running my tests on a Mac OS 10.6.
I thought I could use the same camera source (in fact, Kinect), with two different trackers at the same time… I’m going to try to find a multiplexer software, but it seems not , if you know any other solution, please let me know.
July 20th, 2011 - 00:21
maybe try manycam, that worked for me once.
November 10th, 2011 - 13:02
Hi. there
thank for your blog.
I’ve got a problem. but I don’ know.
I’ve worked my application with Flash CS5.5, AIR 2.5.
please let me know
My error message : 1172: Definition mx.controls:Button could not be found.
my code :
private var tc:TuioClient = new TuioClient(new UDPConnector(“127.0.0.1″, 3333)); // This connector can only be used within Air2.0 or newer Air projects.
private var tuioManager:TuioManager = TuioManager.init(stage); // what’s problem
.
.
.
November 11th, 2011 - 04:31
Hi. all.
I’ve got a problem. but I don’t know what ‘s wrong.
please let me take
*error
1172: Definition mx.controls:Button could not be found. (what’s this?)
* my code
import org.tuio.*;
import org.tuio.osc.*;
import org.tuio.connectors.*;
import org.tuio.debug.*;
import flash.display.*;
import flash.text.*;
import flash.ui.*;
import flash.events.Event;
public class Main extends MovieClip
{
private var tuioClient:TuioClient = new TuioClient(new UDPConnector());
private var tuioManager:TuioManager = TuioManager.init(stage);
private var myRectangle:MovieClip = new MovieClip();
public function Main()
{
tuioClient.addListener(TuioDebug.init(stage));
tuioClient.addListener(tuioManager);
myRectangle.graphics.beginFill(0x6633cc);
myRectangle.graphics.drawRect(300, 300, 200, 200);
addChild(myRectangle);
addEventListener(TuioTouchEvent.TOUCH_DOWN, handler_touchDown);
}
.
.
.
.
November 11th, 2011 - 12:54
That is an error due to an unnecessary import statement in the TuioFiducialEvent on line 6. Just remove it or comment it.
This throws an error because the mx.controls package is only available in FlashBuilder and the flexsdk but not in Flash.
December 15th, 2011 - 09:55
hi, so theres no guide for the latest version of the lib? TuioManager now doesnt have the init function, and i think due to that, my TuioTouchEvents arent dispatching. an updated guide would be really helpful.
December 15th, 2011 - 10:03
sry bout that, jus noticed there were two different classes TUIOManager and TuioManager ;P