- 浏览: 49592 次
- 性别:
- 来自: 上海
文章分类
Touchlib源码注释-----TUIO.as
Touchlib源码注释-----TUIO.as 收藏
声明:欢迎任何人和组织转载本blog中文章,但必须标记文章原始链接和作者信息
TUIO.as文件详细注释
TUIOObject.as TUIOEvent.as TUIOCursor.as文件详细注释
研究了一段时间的multiTouch,根据自己的理解也对代码做了很多注释,今天整理了一下Touchlib这个库的Actionscript 3版本的源码注释,现在发布出来,希望和大家一起讨论修正。也欢迎大家指出其中的错误或者发表自己的意见。后续的as文件,会在我整理完成后慢慢发布出来。好了直接贴代码(本人很想办一个openframeworks的中文论坛,然后会发布一些ccv和openframeworks的个人心得,希望有这个兴趣的朋友一起来研究研究)
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/li_007/archive/2010/01/01/5118098.aspx
package com.touchlib {
import flash.events.DataEvent;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.geom.Point;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.XMLSocket;
//import flash.system.System;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
//import flash.events.MouseEvent;
import flash.display.*;
import app.core.element.Wrapper;
import flash.events.MouseEvent;
public class TUIO
{
static var FLOSCSocket:XMLSocket;
static var FLOSCSocketHost:String;
static var FLOSCSocketPort:Number;
static var thestage:Stage;
// 存储了所有可用TUIOObject实例
static var objectArray:Array;
// 存储了所有可用TUIOOject对象的ID号,但是在本源文件中并没有用到这个变量
static var idArray:Array;
public static var debugMode:Boolean;
static var debugText:TextField;
static var debugToggle:TextField;
static var recordedXML:XML;
static var bRecording:Boolean = false;
//static var xmlPlaybackURL:String = "www/xml/test.xml";
static var xmlPlaybackURL:String = "";
static var xmlPlaybackLoader:URLLoader;
static var playbackXML:XML;
static var bInitialized = false;
// s : 当然舞台,传递文档类的this即可
// host : 服务器IP地址
// port : 端口,CCV默认为3000
// debugXMLFile : 调试用xml文件路径
// debug : 一个Boolen值,表示当前是否为调试状态(不一定需要调试xml)
//
// 这个是TUIO AS 3 Library的初始化函数,在flash工程的文档类开始调用就可以。
//
public static function init (s:DisplayObjectContainer, host:String, port:Number, debugXMLFile:String, dbug:Boolean = true):void
{
if(bInitialized)
return;
debugMode = dbug;
FLOSCSocketHost=host;
FLOSCSocketPort=port;
bInitialized = true;
thestage = s.stage; // 获取当然文档类的舞台
thestage.align = StageAlign.TOP_LEFT;
thestage.displayState = StageDisplayState.FULL_SCREEN;
objectArray = new Array();
idArray = new Array();
try
{
// 与服务端建立xml socket连接,比如CCV。
// 关于flash的xmlsocket编程大家可以自己去查阅Actionscript 3的文档
FLOSCSocket = new XMLSocket();
FLOSCSocket.addEventListener(Event.CLOSE, closeHandler);
FLOSCSocket.addEventListener(Event.CONNECT, connectHandler);
FLOSCSocket.addEventListener(DataEvent.DATA, dataHandler);
FLOSCSocket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
FLOSCSocket.addEventListener(ProgressEvent.PROGRESS, progressHandler);
FLOSCSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
FLOSCSocket.connect(host, port);
} catch (e)
{
}
// 如果当前是调试状态,设置一些调试所需元件
if(debugMode)
{
var format:TextFormat = new TextFormat();
debugText = new TextField();
format.font = "Verdana";
format.color = 0xFFFFFF;
format.size = 10;
debugText.defaultTextFormat = format;
debugText.autoSize = TextFieldAutoSize.LEFT;
debugText.background = true;
debugText.backgroundColor = 0x000000;
debugText.border = true;
debugText.borderColor = 0x333333;
// 将一个动态文本对象加到显示列表,并且将它放在显示列表的最上层。
// 其实这个debugText对象是实时显示调试状态下,触摸点的ID号,x和y坐标
thestage.addChild( debugText );
thestage.setChildIndex(debugText, thestage.numChildren-1);
recordedXML = <OSCPackets></OSCPackets>;
// 创建一个Sprite对象,调试作用,稍后介绍
var buttonSprite = new Sprite();
buttonSprite.graphics.beginFill(0xFFFFFF,1.0);
buttonSprite.graphics.drawRoundRect(0, -10, 50, 60,10);
buttonSprite.addEventListener(MouseEvent.CLICK, toggleDebug);
// 创建一个Wrapper对象,Wrapper对象类在app.core.element包中
var WrapperObject:Wrapper = new Wrapper(buttonSprite);
thestage.addChild(WrapperObject);
thestage.setChildIndex(WrapperObject, thestage.numChildren-1);
//trace(thestage.numChildren);
// 调试xml文件处理
if(xmlPlaybackURL != "")
{
xmlPlaybackLoader = new URLLoader();
xmlPlaybackLoader.addEventListener("complete", xmlPlaybackLoaded);
xmlPlaybackLoader.load(new URLRequest(xmlPlaybackURL));
thestage.addEventListener(Event.ENTER_FRAME, frameUpdate);
}
} else {
recordedXML = <OSCPackets></OSCPackets>;
bRecording = false;
}
}
// 调试xml文件加载完成事件处理函数
private static function xmlPlaybackLoaded(evt:Event) {
trace("Loaded xml debug data");
playbackXML = new XML(xmlPlaybackLoader.data);
}
//
private static function frameUpdate(evt:Event)
{
if(playbackXML && playbackXML.OSCPACKET && playbackXML.OSCPACKET[0])
{
processMessage(playbackXML.OSCPACKET[0]);
delete playbackXML.OSCPACKET[0];
}
}
// 从名字就可以看出来函数功能。根据id来查找所有存储在objectArray数组中的TUIOObject实例
public static function getObjectById(id:Number): TUIOObject
{
for(var i=0; i<objectArray.length; i++)
{
if(objectArray[i].ID == id)
{
//trace("found " + id);
return objectArray[i];
}
}
//trace("Notfound");
return null;
}
// 这个函数要结合TUIOObject类来理解。
public static function listenForObject(id:Number, reciever:Object)
{
var tmpObj:TUIOObject = getObjectById(id);
if(tmpObj)
{
tmpObj.addListener(reciever);
}
}
// 这个是最重要的数据处理函数
public static function processMessage(msg:XML)
{
var fseq:String;
var node:XML;
// 处理fseq消息,格式如下:
//
// /tuio/[profileName] fseq int32
// profileName 代表定义好的常用可感知用户界面配置
// fseq 消息标示
// int32 一个类型为int32的fseq值
for each(node in msg.MESSAGE)
{
if(node.ARGUMENT[0] && node.ARGUMENT[0].@VALUE == "fseq")
fseq = node.ARGUMENT[1].@VALUE;
}
/// trace("fseq = " + fseq);
// 处理alive消息,格式如下:
//
// uio/[profileName] alive [list of active sessionIDs]
// profileName 代表定义好的常用可感知用户界面配置
// alive 消息标示
// [list of active sessionIDs] 一系列当前有用的目标对象的id号
for each(node in msg.MESSAGE)
{
if(node.ARGUMENT[0] && node.ARGUMENT[0].@VALUE == "alive")
{
// 重置objectArray数组中存储的所有TUIOOject实例的isAlive属性
for each (var obj1:TUIOObject in objectArray)
{
obj1.isAlive = false;
}
// 在这个地方重新定义了一个array,但是是无用的变量。
var newIdArray:Array = new Array();
// 循环获得alive消息所有id
//
// alive消息是配合set消息来确定哪些blobs点是有用,也就是哪些set消息中包含的数据是有效的
// 可以结合CCV中的源码来理解
for each(var aliveItem:XML in node.ARGUMENT.(@VALUE != "alive"))
{
// 根据alive消息中的id,相应的TUIOObject实例的isAlive属性设置为true,也即是当前点可用
if(getObjectById(aliveItem.@VALUE))
getObjectById(aliveItem.@VALUE).isAlive = true;
}
//trace(idArray);
idArray = newIdArray;
}
}
// 处理set消息
for each(node in msg.MESSAGE)
{
if(node.ARGUMENT[0])
{
var type:String;
// 在这里要注意区别2Dobj和2Dcur这两种profile的区别,结构如下,具体请阅读TUIO Protocol Specification
//
// /tuio/2Dobj set s i x y a X Y A m r
// /tuio/2Dcur set s x y X Y m
//
// 由于本人结合研究的CCV发送的是/tuio/2Dcur消息结构,所以我先注释/tuio/2Dcur结构消息处理
// 对于/tuio/2Dobj消息处理的注释在以后补上。
if(node.@NAME == "/tuio/2Dobj")
{
type = node.ARGUMENT[0].@VALUE;
if(type == "set")
{
var sID = node.ARGUMENT[1].@VALUE;
var id = node.ARGUMENT[2].@VALUE;
var x = Number(node.ARGUMENT[3].@VALUE) * thestage.stageWidth;
var y = Number(node.ARGUMENT[4].@VALUE) * thestage.stageHeight;
var a = Number(node.ARGUMENT[5].@VALUE);
var X = Number(node.ARGUMENT[6].@VALUE);
var Y = Number(node.ARGUMENT[7].@VALUE);
var A = Number(node.ARGUMENT[8].@VALUE);
var m = node.ARGUMENT[9].@VALUE;
var r = node.ARGUMENT[10].@VALUE;
// send object update event..
var objArray:Array = thestage.getObjectsUnderPoint(new Point(x, y));
var stagePoint:Point = new Point(x,y);
var displayObjArray:Array = thestage.getObjectsUnderPoint(stagePoint);
var dobj = null;
// if(displayObjArray.length > 0)
// dobj = displayObjArray[displayObjArray.length-1];
var tuioobj = getObjectById(id);
if(tuioobj == null)
{
tuioobj = new TUIOObject("2Dobj", id, x, y, X, Y, sID, a, dobj);
thestage.addChild(tuioobj.spr);
objectArray.push(tuioobj);
tuioobj.notifyCreated();
} else {
tuioobj.spr.x = x;
tuioobj.spr.y = y;
tuioobj.x = x;
tuioobj.y = y;
tuioobj.dX = X;
tuioobj.dY = Y;
tuioobj.setObjOver(dobj);
tuioobj.notifyMoved();
}
try
{
if(tuioobj.obj && tuioobj.obj.parent)
{
var localPoint:Point = tuioobj.obj.parent.globalToLocal(stagePoint);
tuioobj.obj.dispatchEvent(new TUIOEvent(TUIOEvent.TUIO_MOVE, true, false, x, y, localPoint.x, localPoint.y, tuioobj.oldX, tuioobj.oldY, tuioobj.obj, false,false,false, true, m, "2Dobj", id, sID, a));
}
} catch (e)
{
}
}
}
//
// /tuio/2Dcur set s x y X Y m
//
else if(node.@NAME == "/tuio/2Dcur")
{
// trace("2dcur");
type = node.ARGUMENT[0].@VALUE;
// 判断消息类型是否为set
if(type == "set")
{
// 当前点的id
var id = node.ARGUMENT[1].@VALUE;
// 将x,y分别乘以舞台宽度和高度转化为当前点全局舞台坐标中的水平和垂直坐标
// 注意在这里为什么是分别对应乘以舞台宽度和高度,需要认真理解
var x = Number(node.ARGUMENT[2].@VALUE) * thestage.stageWidth;
var y = Number(node.ARGUMENT[3].@VALUE) * thestage.stageHeight;
// 分别是当前点的位移量
var X = Number(node.ARGUMENT[4].@VALUE);
var Y = Number(node.ARGUMENT[5].@VALUE);
// 这个值根据TUIO Protocol Specification的解释和CCV中源码实现,我的理解产生了矛盾。
// 需要我后续的实验验证。故再次不做注释说明,也希望那位与我共同讨论(leezhm@126.com)
var m = node.ARGUMENT[6].@VALUE;
//var area = node.ARGUMENT[7].@VALUE;
var stagePoint:Point = new Point(x, y);
// 下面代码段是一个理解重点
// 根据当前点坐标得到舞台上该点下面所有显示对象。关于getObjectsUnderPoint函数
// 可以查阅Actionscript 3的Docs,它返回的包含所有对象的一个数组
var displayObjArray:Array = thestage.getObjectsUnderPoint(stagePoint);
var dobj = null;
// 根据返回的数组,得到最上层的显示对象
//
// 为什么要得到这个最上层的显示对象呢?怎么实现触摸响应的呢?
// 比如:舞台上有一个MovieClip,在这个MC上有一个Button。
// 当你的手触摸到这个button的时候,我们得到了当前点坐标(肯定是stageX和stageY),这样我们
// 用上面的方法获得这个点下面所有的显示对象,包括button,MovieClip等。这个时候我们就要获取
// 最上层这个button,然后让这个button发送一个TUIOEvent.TUIO_DOWN等这样的事件。然后我们只需
// 要在我们的flash中的button上监听这个TUIO_DOWN事件就可以了。
//
// 理解了么?这就是由屏幕上一个点,到flash舞台上元素响应事件的原理。好好学习下Actionscript 3
// 的事件机制后理解这些吧。因为这个让我也想起了Box2D这个库中实现鼠标事件的原理。
if(displayObjArray.length > 0)
dobj = displayObjArray[displayObjArray.length-1];
var sztmp:String="";
// for(var i=0; i<displayObjArray.length; i++)
// sztmp += (displayObjArray[i] is InteractiveObject) + ",";
// trace(sztmp);
// 根据当前id号在objectArray数组中查找是否存在对于的TUIOOjbect实例
var tuioobj = getObjectById(id);
if(tuioobj == null)
{
// 不存在,则创建响应TUIOObject对象,并加入到舞台和数组中(个人觉得没必要加载到舞台,
// 况且为了加载还重新定义了一个Sprite,真是有点多此一举)
//
// 注意这里创建TUIOObject实例所传递的参数中最后一个参数。当然这也要结合TUIOObject类
// 来理解。具体的将会在TUIOObject类中注释。
tuioobj = new TUIOObject("2Dcur", id, x, y, X, Y, -1, 0, dobj);
//tuioobj.area = area;
thestage.addChild(tuioobj.spr);
objectArray.push(tuioobj);
// 发送TUIO_OVER和TUIO_DOWN消息(请结合TUIOObject代码来理解)
tuioobj.notifyCreated();
}
else
{
// 存在,则更新当前点的信息
tuioobj.spr.x = x;
tuioobj.spr.y = y;
tuioobj.x = x;
tuioobj.y = y;
//tuioobj.area = area;
tuioobj.dX = X;
tuioobj.dY = Y;
tuioobj.setObjOver(dobj);
tuioobj.notifyMoved();
}
try
{
// 发送TUIO_MOVE消息
if(tuioobj.obj && tuioobj.obj.parent)
{
var localPoint:Point = tuioobj.obj.parent.globalToLocal(stagePoint);
tuioobj.obj.dispatchEvent(new TUIOEvent(TUIOEvent.TUIO_MOVE, true, false, x, y, localPoint.x, localPoint.y, tuioobj.oldX, tuioobj.oldY, tuioobj.obj, false,false,false, true, m, "2Dobj", id, sID, a));
}
} catch (e)
{
trace("Dispatch event failed " + tuioobj.name);
}
}
}
}
}
// 设置调试显示文本
if(debugMode)
{
debugText.text = "";
debugText.y = -2000;
debugText.x = -2000;
}
for (var i=0; i<objectArray.length; i++ )
{
// 如果当前点非alive,则总objectArray数组中去掉,并且清楚当前点。
if(objectArray[i].isAlive == false)
{
objectArray[i].kill();
thestage.removeChild(objectArray[i].spr);
objectArray.splice(i, 1);
i--;
}
else
{
// 调试状态下显示当前点的坐标(stageX和stageY)
if(debugMode)
{
debugText.appendText(" " + (i + 1) +" - " +objectArray[i].ID + " X:" + int(objectArray[i].x) + " Y:" + int(objectArray[i].y) + " \n");
debugText.x = thestage.stageWidth-160;
debugText.y = 40;
}
}
}
}
private static function toggleDebug(e:Event)
{
if(!debugMode){
debugMode=true;
FLOSCSocket.connect(FLOSCSocketHost, FLOSCSocketPort);
e.target.x=20;
}
else{
debugMode=false;
FLOSCSocket.connect(FLOSCSocketHost, FLOSCSocketPort);
e.target.x=0;
}
// show XML
//bRecording = false;
//debugMode = false;
//debugText.text = recordedXML.toString();
//debugText.x = 0;
//debugText.y = 0;
}
private static function closeHandler(event:Event):void {
//trace("closeHandler: " + event);
}
private static function connectHandler(event:Event):void {
// trace("connectHandler: " + event);
}
private static function dataHandler(event:DataEvent):void {
//trace("dataHandler: " + event);
if(bRecording)
recordedXML.appendChild( XML(event.data) );
processMessage(XML(event.data));
}
private static function ioErrorHandler(event:IOErrorEvent):void {
// thestage.tfDebug.appendText("ioError: " + event + "\n");
trace("ioErrorHandler: " + event);
}
private static function progressHandler(event:ProgressEvent):void {
//trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
}
private static function securityErrorHandler(event:SecurityErrorEvent):void {
trace("securityErrorHandler: " + event);
// thestage.tfDebug.appendText("securityError: " + event + "\n");
}
}
}
Touchlib源码注释-----TUIO.as 收藏
声明:欢迎任何人和组织转载本blog中文章,但必须标记文章原始链接和作者信息
TUIO.as文件详细注释
TUIOObject.as TUIOEvent.as TUIOCursor.as文件详细注释
研究了一段时间的multiTouch,根据自己的理解也对代码做了很多注释,今天整理了一下Touchlib这个库的Actionscript 3版本的源码注释,现在发布出来,希望和大家一起讨论修正。也欢迎大家指出其中的错误或者发表自己的意见。后续的as文件,会在我整理完成后慢慢发布出来。好了直接贴代码(本人很想办一个openframeworks的中文论坛,然后会发布一些ccv和openframeworks的个人心得,希望有这个兴趣的朋友一起来研究研究)
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/li_007/archive/2010/01/01/5118098.aspx
package com.touchlib {
import flash.events.DataEvent;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.geom.Point;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.XMLSocket;
//import flash.system.System;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
//import flash.events.MouseEvent;
import flash.display.*;
import app.core.element.Wrapper;
import flash.events.MouseEvent;
public class TUIO
{
static var FLOSCSocket:XMLSocket;
static var FLOSCSocketHost:String;
static var FLOSCSocketPort:Number;
static var thestage:Stage;
// 存储了所有可用TUIOObject实例
static var objectArray:Array;
// 存储了所有可用TUIOOject对象的ID号,但是在本源文件中并没有用到这个变量
static var idArray:Array;
public static var debugMode:Boolean;
static var debugText:TextField;
static var debugToggle:TextField;
static var recordedXML:XML;
static var bRecording:Boolean = false;
//static var xmlPlaybackURL:String = "www/xml/test.xml";
static var xmlPlaybackURL:String = "";
static var xmlPlaybackLoader:URLLoader;
static var playbackXML:XML;
static var bInitialized = false;
// s : 当然舞台,传递文档类的this即可
// host : 服务器IP地址
// port : 端口,CCV默认为3000
// debugXMLFile : 调试用xml文件路径
// debug : 一个Boolen值,表示当前是否为调试状态(不一定需要调试xml)
//
// 这个是TUIO AS 3 Library的初始化函数,在flash工程的文档类开始调用就可以。
//
public static function init (s:DisplayObjectContainer, host:String, port:Number, debugXMLFile:String, dbug:Boolean = true):void
{
if(bInitialized)
return;
debugMode = dbug;
FLOSCSocketHost=host;
FLOSCSocketPort=port;
bInitialized = true;
thestage = s.stage; // 获取当然文档类的舞台
thestage.align = StageAlign.TOP_LEFT;
thestage.displayState = StageDisplayState.FULL_SCREEN;
objectArray = new Array();
idArray = new Array();
try
{
// 与服务端建立xml socket连接,比如CCV。
// 关于flash的xmlsocket编程大家可以自己去查阅Actionscript 3的文档
FLOSCSocket = new XMLSocket();
FLOSCSocket.addEventListener(Event.CLOSE, closeHandler);
FLOSCSocket.addEventListener(Event.CONNECT, connectHandler);
FLOSCSocket.addEventListener(DataEvent.DATA, dataHandler);
FLOSCSocket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
FLOSCSocket.addEventListener(ProgressEvent.PROGRESS, progressHandler);
FLOSCSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
FLOSCSocket.connect(host, port);
} catch (e)
{
}
// 如果当前是调试状态,设置一些调试所需元件
if(debugMode)
{
var format:TextFormat = new TextFormat();
debugText = new TextField();
format.font = "Verdana";
format.color = 0xFFFFFF;
format.size = 10;
debugText.defaultTextFormat = format;
debugText.autoSize = TextFieldAutoSize.LEFT;
debugText.background = true;
debugText.backgroundColor = 0x000000;
debugText.border = true;
debugText.borderColor = 0x333333;
// 将一个动态文本对象加到显示列表,并且将它放在显示列表的最上层。
// 其实这个debugText对象是实时显示调试状态下,触摸点的ID号,x和y坐标
thestage.addChild( debugText );
thestage.setChildIndex(debugText, thestage.numChildren-1);
recordedXML = <OSCPackets></OSCPackets>;
// 创建一个Sprite对象,调试作用,稍后介绍
var buttonSprite = new Sprite();
buttonSprite.graphics.beginFill(0xFFFFFF,1.0);
buttonSprite.graphics.drawRoundRect(0, -10, 50, 60,10);
buttonSprite.addEventListener(MouseEvent.CLICK, toggleDebug);
// 创建一个Wrapper对象,Wrapper对象类在app.core.element包中
var WrapperObject:Wrapper = new Wrapper(buttonSprite);
thestage.addChild(WrapperObject);
thestage.setChildIndex(WrapperObject, thestage.numChildren-1);
//trace(thestage.numChildren);
// 调试xml文件处理
if(xmlPlaybackURL != "")
{
xmlPlaybackLoader = new URLLoader();
xmlPlaybackLoader.addEventListener("complete", xmlPlaybackLoaded);
xmlPlaybackLoader.load(new URLRequest(xmlPlaybackURL));
thestage.addEventListener(Event.ENTER_FRAME, frameUpdate);
}
} else {
recordedXML = <OSCPackets></OSCPackets>;
bRecording = false;
}
}
// 调试xml文件加载完成事件处理函数
private static function xmlPlaybackLoaded(evt:Event) {
trace("Loaded xml debug data");
playbackXML = new XML(xmlPlaybackLoader.data);
}
//
private static function frameUpdate(evt:Event)
{
if(playbackXML && playbackXML.OSCPACKET && playbackXML.OSCPACKET[0])
{
processMessage(playbackXML.OSCPACKET[0]);
delete playbackXML.OSCPACKET[0];
}
}
// 从名字就可以看出来函数功能。根据id来查找所有存储在objectArray数组中的TUIOObject实例
public static function getObjectById(id:Number): TUIOObject
{
for(var i=0; i<objectArray.length; i++)
{
if(objectArray[i].ID == id)
{
//trace("found " + id);
return objectArray[i];
}
}
//trace("Notfound");
return null;
}
// 这个函数要结合TUIOObject类来理解。
public static function listenForObject(id:Number, reciever:Object)
{
var tmpObj:TUIOObject = getObjectById(id);
if(tmpObj)
{
tmpObj.addListener(reciever);
}
}
// 这个是最重要的数据处理函数
public static function processMessage(msg:XML)
{
var fseq:String;
var node:XML;
// 处理fseq消息,格式如下:
//
// /tuio/[profileName] fseq int32
// profileName 代表定义好的常用可感知用户界面配置
// fseq 消息标示
// int32 一个类型为int32的fseq值
for each(node in msg.MESSAGE)
{
if(node.ARGUMENT[0] && node.ARGUMENT[0].@VALUE == "fseq")
fseq = node.ARGUMENT[1].@VALUE;
}
/// trace("fseq = " + fseq);
// 处理alive消息,格式如下:
//
// uio/[profileName] alive [list of active sessionIDs]
// profileName 代表定义好的常用可感知用户界面配置
// alive 消息标示
// [list of active sessionIDs] 一系列当前有用的目标对象的id号
for each(node in msg.MESSAGE)
{
if(node.ARGUMENT[0] && node.ARGUMENT[0].@VALUE == "alive")
{
// 重置objectArray数组中存储的所有TUIOOject实例的isAlive属性
for each (var obj1:TUIOObject in objectArray)
{
obj1.isAlive = false;
}
// 在这个地方重新定义了一个array,但是是无用的变量。
var newIdArray:Array = new Array();
// 循环获得alive消息所有id
//
// alive消息是配合set消息来确定哪些blobs点是有用,也就是哪些set消息中包含的数据是有效的
// 可以结合CCV中的源码来理解
for each(var aliveItem:XML in node.ARGUMENT.(@VALUE != "alive"))
{
// 根据alive消息中的id,相应的TUIOObject实例的isAlive属性设置为true,也即是当前点可用
if(getObjectById(aliveItem.@VALUE))
getObjectById(aliveItem.@VALUE).isAlive = true;
}
//trace(idArray);
idArray = newIdArray;
}
}
// 处理set消息
for each(node in msg.MESSAGE)
{
if(node.ARGUMENT[0])
{
var type:String;
// 在这里要注意区别2Dobj和2Dcur这两种profile的区别,结构如下,具体请阅读TUIO Protocol Specification
//
// /tuio/2Dobj set s i x y a X Y A m r
// /tuio/2Dcur set s x y X Y m
//
// 由于本人结合研究的CCV发送的是/tuio/2Dcur消息结构,所以我先注释/tuio/2Dcur结构消息处理
// 对于/tuio/2Dobj消息处理的注释在以后补上。
if(node.@NAME == "/tuio/2Dobj")
{
type = node.ARGUMENT[0].@VALUE;
if(type == "set")
{
var sID = node.ARGUMENT[1].@VALUE;
var id = node.ARGUMENT[2].@VALUE;
var x = Number(node.ARGUMENT[3].@VALUE) * thestage.stageWidth;
var y = Number(node.ARGUMENT[4].@VALUE) * thestage.stageHeight;
var a = Number(node.ARGUMENT[5].@VALUE);
var X = Number(node.ARGUMENT[6].@VALUE);
var Y = Number(node.ARGUMENT[7].@VALUE);
var A = Number(node.ARGUMENT[8].@VALUE);
var m = node.ARGUMENT[9].@VALUE;
var r = node.ARGUMENT[10].@VALUE;
// send object update event..
var objArray:Array = thestage.getObjectsUnderPoint(new Point(x, y));
var stagePoint:Point = new Point(x,y);
var displayObjArray:Array = thestage.getObjectsUnderPoint(stagePoint);
var dobj = null;
// if(displayObjArray.length > 0)
// dobj = displayObjArray[displayObjArray.length-1];
var tuioobj = getObjectById(id);
if(tuioobj == null)
{
tuioobj = new TUIOObject("2Dobj", id, x, y, X, Y, sID, a, dobj);
thestage.addChild(tuioobj.spr);
objectArray.push(tuioobj);
tuioobj.notifyCreated();
} else {
tuioobj.spr.x = x;
tuioobj.spr.y = y;
tuioobj.x = x;
tuioobj.y = y;
tuioobj.dX = X;
tuioobj.dY = Y;
tuioobj.setObjOver(dobj);
tuioobj.notifyMoved();
}
try
{
if(tuioobj.obj && tuioobj.obj.parent)
{
var localPoint:Point = tuioobj.obj.parent.globalToLocal(stagePoint);
tuioobj.obj.dispatchEvent(new TUIOEvent(TUIOEvent.TUIO_MOVE, true, false, x, y, localPoint.x, localPoint.y, tuioobj.oldX, tuioobj.oldY, tuioobj.obj, false,false,false, true, m, "2Dobj", id, sID, a));
}
} catch (e)
{
}
}
}
//
// /tuio/2Dcur set s x y X Y m
//
else if(node.@NAME == "/tuio/2Dcur")
{
// trace("2dcur");
type = node.ARGUMENT[0].@VALUE;
// 判断消息类型是否为set
if(type == "set")
{
// 当前点的id
var id = node.ARGUMENT[1].@VALUE;
// 将x,y分别乘以舞台宽度和高度转化为当前点全局舞台坐标中的水平和垂直坐标
// 注意在这里为什么是分别对应乘以舞台宽度和高度,需要认真理解
var x = Number(node.ARGUMENT[2].@VALUE) * thestage.stageWidth;
var y = Number(node.ARGUMENT[3].@VALUE) * thestage.stageHeight;
// 分别是当前点的位移量
var X = Number(node.ARGUMENT[4].@VALUE);
var Y = Number(node.ARGUMENT[5].@VALUE);
// 这个值根据TUIO Protocol Specification的解释和CCV中源码实现,我的理解产生了矛盾。
// 需要我后续的实验验证。故再次不做注释说明,也希望那位与我共同讨论(leezhm@126.com)
var m = node.ARGUMENT[6].@VALUE;
//var area = node.ARGUMENT[7].@VALUE;
var stagePoint:Point = new Point(x, y);
// 下面代码段是一个理解重点
// 根据当前点坐标得到舞台上该点下面所有显示对象。关于getObjectsUnderPoint函数
// 可以查阅Actionscript 3的Docs,它返回的包含所有对象的一个数组
var displayObjArray:Array = thestage.getObjectsUnderPoint(stagePoint);
var dobj = null;
// 根据返回的数组,得到最上层的显示对象
//
// 为什么要得到这个最上层的显示对象呢?怎么实现触摸响应的呢?
// 比如:舞台上有一个MovieClip,在这个MC上有一个Button。
// 当你的手触摸到这个button的时候,我们得到了当前点坐标(肯定是stageX和stageY),这样我们
// 用上面的方法获得这个点下面所有的显示对象,包括button,MovieClip等。这个时候我们就要获取
// 最上层这个button,然后让这个button发送一个TUIOEvent.TUIO_DOWN等这样的事件。然后我们只需
// 要在我们的flash中的button上监听这个TUIO_DOWN事件就可以了。
//
// 理解了么?这就是由屏幕上一个点,到flash舞台上元素响应事件的原理。好好学习下Actionscript 3
// 的事件机制后理解这些吧。因为这个让我也想起了Box2D这个库中实现鼠标事件的原理。
if(displayObjArray.length > 0)
dobj = displayObjArray[displayObjArray.length-1];
var sztmp:String="";
// for(var i=0; i<displayObjArray.length; i++)
// sztmp += (displayObjArray[i] is InteractiveObject) + ",";
// trace(sztmp);
// 根据当前id号在objectArray数组中查找是否存在对于的TUIOOjbect实例
var tuioobj = getObjectById(id);
if(tuioobj == null)
{
// 不存在,则创建响应TUIOObject对象,并加入到舞台和数组中(个人觉得没必要加载到舞台,
// 况且为了加载还重新定义了一个Sprite,真是有点多此一举)
//
// 注意这里创建TUIOObject实例所传递的参数中最后一个参数。当然这也要结合TUIOObject类
// 来理解。具体的将会在TUIOObject类中注释。
tuioobj = new TUIOObject("2Dcur", id, x, y, X, Y, -1, 0, dobj);
//tuioobj.area = area;
thestage.addChild(tuioobj.spr);
objectArray.push(tuioobj);
// 发送TUIO_OVER和TUIO_DOWN消息(请结合TUIOObject代码来理解)
tuioobj.notifyCreated();
}
else
{
// 存在,则更新当前点的信息
tuioobj.spr.x = x;
tuioobj.spr.y = y;
tuioobj.x = x;
tuioobj.y = y;
//tuioobj.area = area;
tuioobj.dX = X;
tuioobj.dY = Y;
tuioobj.setObjOver(dobj);
tuioobj.notifyMoved();
}
try
{
// 发送TUIO_MOVE消息
if(tuioobj.obj && tuioobj.obj.parent)
{
var localPoint:Point = tuioobj.obj.parent.globalToLocal(stagePoint);
tuioobj.obj.dispatchEvent(new TUIOEvent(TUIOEvent.TUIO_MOVE, true, false, x, y, localPoint.x, localPoint.y, tuioobj.oldX, tuioobj.oldY, tuioobj.obj, false,false,false, true, m, "2Dobj", id, sID, a));
}
} catch (e)
{
trace("Dispatch event failed " + tuioobj.name);
}
}
}
}
}
// 设置调试显示文本
if(debugMode)
{
debugText.text = "";
debugText.y = -2000;
debugText.x = -2000;
}
for (var i=0; i<objectArray.length; i++ )
{
// 如果当前点非alive,则总objectArray数组中去掉,并且清楚当前点。
if(objectArray[i].isAlive == false)
{
objectArray[i].kill();
thestage.removeChild(objectArray[i].spr);
objectArray.splice(i, 1);
i--;
}
else
{
// 调试状态下显示当前点的坐标(stageX和stageY)
if(debugMode)
{
debugText.appendText(" " + (i + 1) +" - " +objectArray[i].ID + " X:" + int(objectArray[i].x) + " Y:" + int(objectArray[i].y) + " \n");
debugText.x = thestage.stageWidth-160;
debugText.y = 40;
}
}
}
}
private static function toggleDebug(e:Event)
{
if(!debugMode){
debugMode=true;
FLOSCSocket.connect(FLOSCSocketHost, FLOSCSocketPort);
e.target.x=20;
}
else{
debugMode=false;
FLOSCSocket.connect(FLOSCSocketHost, FLOSCSocketPort);
e.target.x=0;
}
// show XML
//bRecording = false;
//debugMode = false;
//debugText.text = recordedXML.toString();
//debugText.x = 0;
//debugText.y = 0;
}
private static function closeHandler(event:Event):void {
//trace("closeHandler: " + event);
}
private static function connectHandler(event:Event):void {
// trace("connectHandler: " + event);
}
private static function dataHandler(event:DataEvent):void {
//trace("dataHandler: " + event);
if(bRecording)
recordedXML.appendChild( XML(event.data) );
processMessage(XML(event.data));
}
private static function ioErrorHandler(event:IOErrorEvent):void {
// thestage.tfDebug.appendText("ioError: " + event + "\n");
trace("ioErrorHandler: " + event);
}
private static function progressHandler(event:ProgressEvent):void {
//trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
}
private static function securityErrorHandler(event:SecurityErrorEvent):void {
trace("securityErrorHandler: " + event);
// thestage.tfDebug.appendText("securityError: " + event + "\n");
}
}
}
相关推荐
标题“TuioListener_tuio监听_雷达串口转tuio_TUIO协议_互动雷达”涉及到的关键知识点主要包括TUIO监听、雷达串口通信以及TUIO协议在互动雷达中的应用。 首先,TUIO监听是程序设计中一个重要的环节,主要用于接收和...
**TUIO模拟器简介** TUIO(Tabletop User Interface Objects)是一种基于UDP的协议,主要用于多点触摸和手势识别设备与应用之间的通信。它允许用户与触摸表面交互,如交互式白板、触控桌等。TUIO模拟器,即...
**TUIO多点触摸调试工具详解** TUIO(Tangible User Interface Object)是一种用于在多点触摸设备上实现远程交互的开放协议。它基于UDP(User Datagram Protocol)网络协议,为各种输入设备,如触摸屏、触摸桌或...
### 关于TUIO 1.1中文简介 #### TUIO 1.1协议概述 TUIO(Tangible User Interface Object)1.1协议是TUIO规范的一个增量和向后兼容的更新版本,它在保持原有TUIO 1.0规范的核心结构的基础上,增加了一些新的特性,...
**TUIO模拟器及其在Unity3D中的应用** TUIO(Tabletop User Interface Ontology)是一种协议,用于在多点触摸设备和平板界面之间建立通信。它为交互式表面提供了一种标准的方式来发送和接收多点触摸事件,如触摸点...
TUIOSimulator是一款强大的工具,专为测试和开发TUIO(Touch UI Object)协议的应用程序而设计。TUIO是一种开放标准,它允许多点触控设备,如触摸屏、投影表面等,与计算机应用程序进行通信。TUIOSimulator提供了两...
TUIO(Touch User Interface Object)是一种开源的网络协议,主要设计用于支持多点触摸设备与应用程序之间的通信。它提供了一种标准化的方式来传输多点触摸事件、手势以及其他交互数据,使得开发者可以创建支持多点...
**TUIO CPP:C# 实现与OSC通信详解** TUIO(Transmission of UI Events Over OSC)是一种基于OSC(Open Sound Control)的协议,专为多触点用户界面(如触摸屏、交互式白板等)设计,用于传输用户交互事件。TUIO将...
此示例"FLASH AS3 雷达tuio+UDP协议"是一个结合了多种技术的项目,主要涉及了AS3编程、雷达系统模拟以及网络通信协议。以下是关于这些知识点的详细解释: 1. **Flash AS3**: Adobe Flash Player的ActionScript 3是...
**Unity与TUIO结合应用详解** Unity是一个强大的跨平台游戏引擎,被广泛应用于游戏开发、虚拟现实(VR)、增强现实(AR)以及交互式体验的设计。TUIO(Touch User Interface Object)则是一种用于多点触控和手势...
【标题】"TUIO官方案例C++源码(互动投影技术官方案例C++源码)"涉及的核心知识点是TUIO协议在互动投影技术中的应用,以及使用C++编程语言实现的相关源码。TUIO(Touch User Interface Object)是一种用于多点触控和...
而Tuio(Tangible User Interface Object)是一种开放源代码的交互协议,它使得物体、手势和其他形式的输入能够与计算机进行实时互动,特别适用于多点触控和体感交互应用。 "unity+tuio实现触屏demo"这个项目是将...
**TUIO(Tabletop User Interface Ontology)**是一种开放标准的通信协议,主要用于支持多点触控设备,如交互式桌子、触摸屏等与软件应用程序之间的交互。在Flash AS3(ActionScript 3)中,TUIO的运用允许开发者...
【TUIO(Touch User Interface Object)简介】 TUIO是一种开放的、基于OSC(Open Sound Control)的网络协议,主要用于多点触控设备与应用程序之间的通信。它允许实时地传输多点触摸事件和对象识别信息,为游戏开发...
**Tuio信号仿真输出软件详解** Tuio(Tabletop Ubiquitous Object)是一种用于多点触控设备和交互式表面的开放源代码协议。它允许软件应用接收来自各种输入设备(如触摸屏、手指、鼠标或特殊跟踪设备)的实时位置和...
Unity TUIO模拟器是一种专为Unity开发设计的工具,用于在没有真实硬件设备的情况下测试和调试互动大屏项目。TUIO(Touch User Interface Object)是一种基于OSC(Open Sound Control)协议的交互式界面标准,它允许...
标题中的“tuio的unity实现 UDP For Unity Demo”是指在Unity引擎中实现TUIO(Tabletop User Interface Objects)协议的UDP通信示例。TUIO是一种通用的、基于UDP的传输协议,常用于多点触摸设备和虚拟现实交互。...
在投影激光雷达互动项目中,使用Window模拟器是不可或缺的一环。Window模拟器是一款功能强大的软件工具,专为在计算机上...unity 现成的tuio雷达模拟器,可以用来对接unity项目的互动大屏开发,这个是非常好用的模拟器
**Python-TUIO库详解** Python-TUIO库是一个用于Python的开源库,它使得开发者能够处理TUIO(Touchable User Interface Objects)流。TUIO是一种通用的传输协议,常用于多点触摸和运动追踪设备,如触摸屏、投影交互...
TUIO(Touch User Interface Object)是一种用于多点触控和手势识别的开放源代码协议。这个名为"TUIO_Simulator-调试工具.zip"的压缩包文件,显然包含了一个用于测试和调试TUIO相关应用的模拟器。通过这个工具,...