tuio.js 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145
  1. /*! Tuio.js - v0.0.1 - 2012-10-14
  2. * http://fe9lix.github.com/Tuio.js/
  3. * Copyright (c) 2012 Felix Raab; Licensed GPL */
  4. (function(root) {
  5. // Initial Setup, events mixin and extend/inherits taken from Backbone.js
  6. // See Backbone.js source for original version and comments.
  7. var previousTuio = root.Tuio;
  8. var slice = Array.prototype.slice;
  9. var splice = Array.prototype.splice;
  10. var Tuio;
  11. if (typeof exports !== "undefined") {
  12. Tuio = exports;
  13. } else {
  14. Tuio = root.Tuio = {};
  15. }
  16. Tuio.VERSION = "0.0.1";
  17. var _ = root._;
  18. if (!_ && (typeof require !== "undefined")) {
  19. _ = require("lodash");
  20. }
  21. Tuio.noConflict = function() {
  22. root.Tuio = previousTuio;
  23. return this;
  24. };
  25. var eventSplitter = /\s+/;
  26. var Events = Tuio.Events = {
  27. on: function(events, callback, context) {
  28. var calls, event, node, tail, list;
  29. if (!callback) {
  30. return this;
  31. }
  32. events = events.split(eventSplitter);
  33. calls = this._callbacks || (this._callbacks = {});
  34. while (event = events.shift()) {
  35. list = calls[event];
  36. node = list ? list.tail : {};
  37. node.next = tail = {};
  38. node.context = context;
  39. node.callback = callback;
  40. calls[event] = {tail: tail, next: list ? list.next : node};
  41. }
  42. return this;
  43. },
  44. off: function(events, callback, context) {
  45. var event, calls, node, tail, cb, ctx;
  46. if (!(calls = this._callbacks)) {
  47. return;
  48. }
  49. if (!(events || callback || context)) {
  50. delete this._callbacks;
  51. return this;
  52. }
  53. events = events ? events.split(eventSplitter) : _.keys(calls);
  54. while (event = events.shift()) {
  55. node = calls[event];
  56. delete calls[event];
  57. if (!node || !(callback || context)) {
  58. continue;
  59. }
  60. tail = node.tail;
  61. while ((node = node.next) !== tail) {
  62. cb = node.callback;
  63. ctx = node.context;
  64. if ((callback && cb !== callback) || (context && ctx !== context)) {
  65. this.on(event, cb, ctx);
  66. }
  67. }
  68. }
  69. return this;
  70. },
  71. trigger: function(events) {
  72. var event, node, calls, tail, args, all, rest;
  73. if (!(calls = this._callbacks)) {
  74. return this;
  75. }
  76. all = calls.all;
  77. events = events.split(eventSplitter);
  78. rest = slice.call(arguments, 1);
  79. while (event = events.shift()) {
  80. if (node = calls[event]) {
  81. tail = node.tail;
  82. while ((node = node.next) !== tail) {
  83. node.callback.apply(node.context || this, rest);
  84. }
  85. }
  86. if (node = all) {
  87. tail = node.tail;
  88. args = [event].concat(rest);
  89. while ((node = node.next) !== tail) {
  90. node.callback.apply(node.context || this, args);
  91. }
  92. }
  93. }
  94. return this;
  95. }
  96. };
  97. var Model = Tuio.Model = function() {
  98. this.initialize.apply(this, arguments);
  99. };
  100. _.extend(Model.prototype, Events);
  101. var extend = function (protoProps, classProps) {
  102. var child = inherits(this, protoProps, classProps);
  103. child.extend = this.extend;
  104. return child;
  105. };
  106. Tuio.Model.extend = extend;
  107. var Ctor = function() {
  108. };
  109. var inherits = function(parent, protoProps, staticProps) {
  110. var child;
  111. if (protoProps && protoProps.hasOwnProperty("constructor")) {
  112. child = protoProps.constructor;
  113. } else {
  114. child = function() {
  115. parent.apply(this, arguments);
  116. };
  117. }
  118. _.extend(child, parent);
  119. Ctor.prototype = parent.prototype;
  120. child.prototype = new Ctor();
  121. if (protoProps) {
  122. _.extend(child.prototype, protoProps);
  123. }
  124. if (staticProps) {
  125. _.extend(child, staticProps);
  126. }
  127. child.prototype.constructor = child;
  128. child.__super__ = parent.prototype;
  129. return child;
  130. };
  131. }(this));
  132. Tuio.Time = Tuio.Model.extend({
  133. seconds: 0,
  134. microSeconds: 0,
  135. initialize: function(sec, usec) {
  136. this.seconds = sec || 0;
  137. this.microSeconds = usec || 0;
  138. },
  139. add: function(us) {
  140. return new Tuio.Time(
  141. this.seconds + Math.floor(us / 1000000),
  142. this.microSeconds + us % 1000000
  143. );
  144. },
  145. addTime: function(ttime) {
  146. var sec = this.seconds + ttime.getSeconds(),
  147. usec = this.microSeconds + ttime.getMicroseconds();
  148. sec += Math.floor(usec / 1000000);
  149. usec = usec % 1000000;
  150. return new Tuio.Time(sec, usec);
  151. },
  152. subtract: function(us) {
  153. var sec = this.seconds - Math.floor(us / 1000000),
  154. usec = this.microSeconds - us % 1000000;
  155. if (usec < 0) {
  156. usec += 1000000;
  157. sec = sec - 1;
  158. }
  159. return new Tuio.Time(sec, usec);
  160. },
  161. subtractTime: function(ttime) {
  162. var sec = this.seconds - ttime.getSeconds(),
  163. usec = this.microSeconds - ttime.getMicroseconds();
  164. if (usec < 0) {
  165. usec += 1000000;
  166. sec = sec - 1;
  167. }
  168. return new Tuio.Time(sec, usec);
  169. },
  170. equals: function(ttime) {
  171. return (
  172. (this.seconds === ttime.getSeconds()) &&
  173. (this.microSeconds === ttime.getMicroseconds())
  174. );
  175. },
  176. reset: function() {
  177. this.seconds = 0;
  178. this.microSeconds = 0;
  179. },
  180. getSeconds: function() {
  181. return this.seconds;
  182. },
  183. getMicroseconds: function() {
  184. return this.microSeconds;
  185. },
  186. getTotalMilliseconds: function() {
  187. return this.seconds * 1000 + Math.floor(this.microSeconds / 1000);
  188. }
  189. }, {
  190. startSeconds: 0,
  191. startMicroSeconds: 0,
  192. fromMilliseconds: function(msec) {
  193. return new Tuio.Time(
  194. Math.floor(msec / 1000),
  195. 1000 * (msec % 1000)
  196. );
  197. },
  198. fromTime: function(ttime) {
  199. return new Tuio.Time(
  200. ttime.getSeconds(),
  201. ttime.getMicroseconds()
  202. );
  203. },
  204. initSession: function() {
  205. var startTime = Tuio.Time.getSystemTime();
  206. Tuio.Time.startSeconds = startTime.getSeconds();
  207. Tuio.Time.startMicroSeconds = startTime.getMicroseconds();
  208. },
  209. getSessionTime: function() {
  210. return Tuio.Time.getSystemTime().subtractTime(Tuio.Time.getStartTime());
  211. },
  212. getStartTime: function() {
  213. return new Tuio.Time(
  214. Tuio.Time.startSeconds,
  215. Tuio.Time.startMicroSeconds
  216. );
  217. },
  218. getSystemTime: function() {
  219. var usec = new Date().getTime() * 1000;
  220. return new Tuio.Time(
  221. Math.floor(usec / 1000000),
  222. usec % 1000000
  223. );
  224. }
  225. });
  226. Tuio.Point = Tuio.Model.extend({
  227. xPos: null,
  228. yPos: null,
  229. currentTime: null,
  230. startTime: null,
  231. initialize: function(params) {
  232. this.xPos = params.xp || 0;
  233. this.yPos = params.yp || 0;
  234. this.currentTime = Tuio.Time.fromTime(params.ttime || Tuio.Time.getSessionTime());
  235. this.startTime = Tuio.Time.fromTime(this.currentTime);
  236. },
  237. update: function(params) {
  238. this.xPos = params.xp;
  239. this.yPos = params.yp;
  240. if (params.hasOwnProperty("ttime")) {
  241. this.currentTime = Tuio.Time.fromTime(params.ttime);
  242. }
  243. },
  244. updateToPoint: function(tpoint) {
  245. this.xPos = tpoint.getX();
  246. this.yPos = tpoint.getY();
  247. },
  248. getX: function() {
  249. return this.xPos;
  250. },
  251. getY: function() {
  252. return this.yPos;
  253. },
  254. getDistance: function(xp, yp) {
  255. var dx = this.xPos - xp,
  256. dy = this.yPos - yp;
  257. return Math.sqrt(dx * dx + dy * dy);
  258. },
  259. getDistanceToPoint: function(tpoint) {
  260. return this.getDistance(tpoint.getX(), tpoint.getY());
  261. },
  262. getAngle: function(xp, yp) {
  263. var side = this.xPos - xp,
  264. height = this.yPos - yp,
  265. distance = this.getDistance(xp, yp),
  266. angle = Math.asin(side / distance) + Math.PI / 2;
  267. if (height < 0) {
  268. angle = 2 * Math.PI - angle;
  269. }
  270. return angle;
  271. },
  272. getAngleToPoint: function(tpoint) {
  273. return this.getAngle(tpoint.getX(), tpoint.getY());
  274. },
  275. getAngleDegrees: function(xp, yp) {
  276. return (this.getAngle(xp, yp) / Math.PI) * 180;
  277. },
  278. getAngleDegreesToPoint: function(tpoint) {
  279. return (this.getAngleToPoint(tpoint) / Math.PI) * 180;
  280. },
  281. getScreenX: function(width) {
  282. return Math.round(this.xPos * width);
  283. },
  284. getScreenY: function(height) {
  285. return Math.round(this.yPos * height);
  286. },
  287. getTuioTime: function() {
  288. return Tuio.Time.fromTime(this.currentTime);
  289. },
  290. getStartTime: function() {
  291. return Tuio.Time.fromTime(this.startTime);
  292. }
  293. }, {
  294. fromPoint: function(tpoint) {
  295. return new Tuio.Point({
  296. xp: tpoint.getX(),
  297. yp: tpoint.getY()
  298. });
  299. }
  300. });
  301. Tuio.Container = Tuio.Point.extend({
  302. sessionId: null,
  303. xSpeed: null,
  304. ySpeed: null,
  305. motionSpeed: null,
  306. motionAccel: null,
  307. path: null,
  308. state: null,
  309. initialize: function(params) {
  310. Tuio.Point.prototype.initialize.call(this, params);
  311. this.sessionId = params.si;
  312. this.xSpeed = 0;
  313. this.ySpeed = 0;
  314. this.motionSpeed = 0;
  315. this.motionAccel = 0;
  316. this.path = [new Tuio.Point({
  317. ttime: this.currentTime,
  318. xp: this.xPos,
  319. yp: this.yPos
  320. })];
  321. this.state = Tuio.Container.TUIO_ADDED;
  322. },
  323. update: function(params) {
  324. var lastPoint = this.path[this.path.length - 1];
  325. Tuio.Point.prototype.update.call(this, params);
  326. if (
  327. params.hasOwnProperty("xs") &&
  328. params.hasOwnProperty("ys") &&
  329. params.hasOwnProperty("ma")) {
  330. this.xSpeed = params.xs;
  331. this.ySpeed = params.ys;
  332. this.motionSpeed = Math.sqrt(this.xSpeed * this.xSpeed + this.ySpeed * this.ySpeed);
  333. this.motionAccel = params.ma;
  334. } else {
  335. var diffTime = this.currentTime.subtractTime(lastPoint.getTuioTime()),
  336. dt = diffTime.getTotalMilliseconds() / 1000,
  337. dx = this.xPos - lastPoint.getX(),
  338. dy = this.yPos - lastPoint.getY(),
  339. dist = Math.sqrt(dx * dx + dy * dy),
  340. lastMotionSpeed = this.motionSpeed;
  341. this.xSpeed = dx / dt;
  342. this.ySpeed = dy / dt;
  343. this.motionSpeed = dist / dt;
  344. this.motionAccel = (this.motionSpeed - lastMotionSpeed) / dt;
  345. }
  346. this.updatePathAndState();
  347. },
  348. updateContainer: function(tcon) {
  349. Tuio.Point.prototype.updateToPoint.call(this, tcon);
  350. this.xSpeed = tcon.getXSpeed();
  351. this.ySpeed = tcon.getYSpeed();
  352. this.motionSpeed = tcon.getMotionSpeed();
  353. this.motionAccel = tcon.getMotionAccel();
  354. this.updatePathAndState();
  355. },
  356. updatePathAndState: function() {
  357. this.path.push(new Tuio.Point({
  358. ttime: this.currentTime,
  359. xp: this.xPos,
  360. yp: this.yPos
  361. }));
  362. if (this.motionAccel > 0) {
  363. this.state = Tuio.Container.TUIO_ACCELERATING;
  364. } else if (this.motionAccel < 0) {
  365. this.state = Tuio.Container.TUIO_DECELERATING;
  366. } else {
  367. this.state = Tuio.Container.TUIO_STOPPED;
  368. }
  369. },
  370. stop: function(ttime) {
  371. this.update({
  372. ttime: ttime,
  373. xp: this.xPos,
  374. yp: this.yPos
  375. });
  376. },
  377. remove: function(ttime) {
  378. this.currentTime = Tuio.Time.fromTime(ttime);
  379. this.state = Tuio.Container.TUIO_REMOVED;
  380. },
  381. getSessionId: function() {
  382. return this.sessionId;
  383. },
  384. getXSpeed: function() {
  385. return this.xSpeed;
  386. },
  387. getYSpeed: function() {
  388. return this.ySpeed;
  389. },
  390. getPosition: function() {
  391. return new Tuio.Point(this.xPos, this.yPos);
  392. },
  393. getPath: function() {
  394. return this.path;
  395. },
  396. getMotionSpeed: function() {
  397. return this.motionSpeed;
  398. },
  399. getMotionAccel: function() {
  400. return this.motionAccel;
  401. },
  402. getTuioState: function() {
  403. return this.state;
  404. },
  405. isMoving: function() {
  406. return (
  407. (this.state === Tuio.Container.TUIO_ACCELERATING) ||
  408. (this.state === Tuio.Container.TUIO_DECELERATING)
  409. );
  410. }
  411. }, {
  412. TUIO_ADDED: 0,
  413. TUIO_ACCELERATING: 1,
  414. TUIO_DECELERATING: 2,
  415. TUIO_STOPPED: 3,
  416. TUIO_REMOVED: 4,
  417. fromContainer: function(tcon) {
  418. return new Tuio.Container({
  419. xp: tcon.getX(),
  420. yp: tcon.getY(),
  421. si: tcon.getSessionID()
  422. });
  423. }
  424. });
  425. Tuio.Cursor = Tuio.Container.extend({
  426. cursorId: null,
  427. initialize: function(params) {
  428. Tuio.Container.prototype.initialize.call(this, params);
  429. this.cursorId = params.ci;
  430. },
  431. getCursorId: function() {
  432. return this.cursorId;
  433. }
  434. }, {
  435. fromCursor: function(tcur) {
  436. return new Tuio.Cursor({
  437. si: tcur.getSessionId(),
  438. ci: tcur.getCursorId(),
  439. xp: tcur.getX(),
  440. yp: tcur.getY()
  441. });
  442. }
  443. });
  444. Tuio.Object = Tuio.Container.extend({
  445. symbolId: null,
  446. angle: null,
  447. rotationSpeed: null,
  448. rotationAccel: null,
  449. initialize: function(params) {
  450. Tuio.Container.prototype.initialize.call(this, params);
  451. this.symbolId = params.sym;
  452. this.angle = params.a;
  453. this.rotationSpeed = 0;
  454. this.rotationAccel = 0;
  455. },
  456. update: function(params) {
  457. var lastPoint = this.path[this.path.length - 1];
  458. Tuio.Container.prototype.update.call(this, params);
  459. if (
  460. params.hasOwnProperty("rs") &&
  461. params.hasOwnProperty("ra")) {
  462. this.angle = params.a;
  463. this.rotationSpeed = params.rs;
  464. this.rotationAccel = params.ra;
  465. } else {
  466. var diffTime = this.currentTime.subtractTime(lastPoint.getTuioTime()),
  467. dt = diffTime.getTotalMilliseconds() / 1000,
  468. lastAngle = this.angle,
  469. lastRotationSpeed = this.rotationSpeed;
  470. this.angle = params.a;
  471. var da = (this.angle - lastAngle) / (2 * Math.PI);
  472. if (da > 0.75) {
  473. da -= 1;
  474. } else if (da < -0.75) {
  475. da += 1;
  476. }
  477. this.rotationSpeed = da / dt;
  478. this.rotationAccel = (this.rotationSpeed - lastRotationSpeed) / dt;
  479. }
  480. this.updateObjectState();
  481. },
  482. updateObject: function(tobj) {
  483. Tuio.Container.prototype.updateContainer.call(this, tobj);
  484. this.angle = tobj.getAngle();
  485. this.rotationSpeed = tobj.getRotationSpeed();
  486. this.rotationAccel = tobj.getRotationAccel();
  487. this.updateObjectState();
  488. },
  489. updateObjectState: function() {
  490. if ((this.rotationAccel !== 0) && (this.state !== Tuio.Object.TUIO_STOPPED)) {
  491. this.state = Tuio.Object.TUIO_ROTATING;
  492. }
  493. },
  494. stop: function(ttime) {
  495. this.update({
  496. ttime: ttime,
  497. xp: this.xPos,
  498. yp: this.yPos,
  499. a: this.angle
  500. });
  501. },
  502. getSymbolId: function() {
  503. return this.symbolId;
  504. },
  505. getAngle: function() {
  506. return this.angle;
  507. },
  508. getAngleDegrees: function() {
  509. return this.angle / Math.PI * 180;
  510. },
  511. getRotationSpeed: function() {
  512. return this.rotationSpeed;
  513. },
  514. getRotationAccel: function() {
  515. return this.rotationAccel;
  516. },
  517. isMoving: function() {
  518. return (
  519. (this.state === Tuio.Object.TUIO_ACCELERATING) ||
  520. (this.state === Tuio.Object.TUIO_DECELERATING) ||
  521. (this.state === Tuio.Object.TUIO_ROTATING)
  522. );
  523. }
  524. }, {
  525. TUIO_ROTATING: 5,
  526. fromObject: function(tobj) {
  527. return new Tuio.Object({
  528. xp: tobj.getX(),
  529. yp: tobj.getY(),
  530. si: tobj.getSessionID(),
  531. sym: tobj.getSymbolId(),
  532. a: tobj.getAngle()
  533. });
  534. }
  535. });
  536. Tuio.Client = Tuio.Model.extend({
  537. host: null,
  538. socket: null,
  539. connected: null,
  540. objectList: null,
  541. aliveObjectList: null,
  542. newObjectList: null,
  543. cursorList: null,
  544. aliveCursorList: null,
  545. newCursorList: null,
  546. frameObjects: null,
  547. frameCursors: null,
  548. freeCursorList: null,
  549. maxCursorId: null,
  550. currentFrame: null,
  551. currentTime: null,
  552. initialize: function(params) {
  553. this.host = params.host;
  554. this.connected = false;
  555. this.objectList = {};
  556. this.aliveObjectList = [];
  557. this.newObjectList = [];
  558. this.cursorList = {};
  559. this.aliveCursorList = [];
  560. this.newCursorList = [];
  561. this.frameObjects = [];
  562. this.frameCursors = [];
  563. this.freeCursorList = [];
  564. this.maxCursorId = -1;
  565. this.currentFrame = 0;
  566. this.currentTime = null;
  567. _.bindAll(this, "onConnect", "acceptBundle", "onDisconnect");
  568. },
  569. connect: function() {
  570. Tuio.Time.initSession();
  571. this.currentTime = new Tuio.Time();
  572. this.currentTime.reset();
  573. console.log(this.host);
  574. this.socket = io(this.host, {transports: ['websocket']});
  575. this.socket.on("connect", this.onConnect);
  576. this.socket.on("disconnect", this.onDisconnect);
  577. },
  578. onConnect: function() {
  579. this.socket.on("osc", this.acceptBundle);
  580. this.connected = true;
  581. this.trigger("connect");
  582. },
  583. onDisconnect: function() {
  584. this.connected = false;
  585. this.trigger("disconnect");
  586. },
  587. isConnected: function() {
  588. return this.connected;
  589. },
  590. getTuioObjects: function() {
  591. return _.clone(this.objectList);
  592. },
  593. getTuioCursors: function() {
  594. return _.clone(this.cursorList);
  595. },
  596. getTuioObject: function(sid) {
  597. return this.objectList[sid];
  598. },
  599. getTuioCursor: function(sid) {
  600. return this.cursorList[sid];
  601. },
  602. acceptBundle: function(oscBundle) {
  603. var msg = null;
  604. for (var i = 0, max = oscBundle.length; i < max; i++) {
  605. msg = oscBundle[i];
  606. switch (msg[0]) {
  607. case "/tuio/2Dobj":
  608. case "/tuio/2Dcur":
  609. this.acceptMessage(msg);
  610. break;
  611. }
  612. }
  613. },
  614. acceptMessage: function(oscMessage) {
  615. var address = oscMessage[0],
  616. command = oscMessage[1],
  617. args = oscMessage.slice(2, oscMessage.length);
  618. switch (address) {
  619. case "/tuio/2Dobj":
  620. this.handleObjectMessage(command, args);
  621. break;
  622. case "/tuio/2Dcur":
  623. this.handleCursorMessage(command, args);
  624. break;
  625. }
  626. },
  627. handleObjectMessage: function(command, args) {
  628. switch (command) {
  629. case "set":
  630. this.objectSet(args);
  631. break;
  632. case "alive":
  633. this.objectAlive(args);
  634. break;
  635. case "fseq":
  636. this.objectFseq(args);
  637. break;
  638. }
  639. },
  640. handleCursorMessage: function(command, args) {
  641. switch (command) {
  642. case "set":
  643. this.cursorSet(args);
  644. break;
  645. case "alive":
  646. this.cursorAlive(args);
  647. break;
  648. case "fseq":
  649. this.cursorFseq(args);
  650. break;
  651. }
  652. },
  653. objectSet: function(args) {
  654. var sid = args[0],
  655. cid = args[1],
  656. xPos = args[2],
  657. yPos = args[3],
  658. angle = args[4],
  659. xSpeed = args[5],
  660. ySpeed = args[6],
  661. rSpeed = args[7],
  662. mAccel = args[8],
  663. rAccel = args[9];
  664. if (!_.has(this.objectList, sid)) {
  665. var addObject = new Tuio.Object({
  666. si: sid,
  667. sym: cid,
  668. xp: xPos,
  669. yp: yPos,
  670. a: angle
  671. });
  672. this.frameObjects.push(addObject);
  673. } else {
  674. var tobj = this.objectList[sid];
  675. if (!tobj) {
  676. return;
  677. }
  678. if (
  679. (tobj.xPos !== xPos) ||
  680. (tobj.yPos !== yPos) ||
  681. (tobj.angle !== angle) ||
  682. (tobj.xSpeed !== xSpeed) ||
  683. (tobj.ySpeed !== ySpeed) ||
  684. (tobj.rotationSpeed !== rSpeed) ||
  685. (tobj.motionAccel !== mAccel) ||
  686. (tobj.rotationAccel !== rAccel)) {
  687. var updateObject = new Tuio.Object({
  688. si: sid,
  689. sym: cid,
  690. xp: xPos,
  691. yp: yPos,
  692. a: angle
  693. });
  694. updateObject.update({
  695. xp: xPos,
  696. yp: yPos,
  697. a: angle,
  698. xs: xSpeed,
  699. ys: ySpeed,
  700. rs: rSpeed,
  701. ma: mAccel,
  702. ra: rAccel
  703. });
  704. this.frameObjects.push(updateObject);
  705. }
  706. }
  707. },
  708. objectAlive: function(args) {
  709. var removeObject = null;
  710. this.newObjectList = args;
  711. this.aliveObjectList = _.difference(this.aliveObjectList, this.newObjectList);
  712. for (var i = 0, max = this.aliveObjectList.length; i < max; i++) {
  713. removeObject = this.objectList[this.aliveObjectList[i]];
  714. if (removeObject) {
  715. removeObject.remove(this.currentTime);
  716. this.frameObjects.push(removeObject);
  717. }
  718. }
  719. },
  720. objectFseq: function(args) {
  721. var fseq = args[0],
  722. lateFrame = false,
  723. tobj = null;
  724. if (fseq > 0) {
  725. if (fseq > this.currentFrame) {
  726. this.currentTime = Tuio.Time.getSessionTime();
  727. }
  728. if ((fseq >= this.currentFrame) || ((this.currentFrame - fseq) > 100)) {
  729. this.currentFrame = fseq;
  730. } else {
  731. lateFrame = true;
  732. }
  733. } else if (Tuio.Time.getSessionTime().subtractTime(this.currentTime).getTotalMilliseconds() > 100) {
  734. this.currentTime = Tuio.Time.getSessionTime();
  735. }
  736. if (!lateFrame) {
  737. for (var i = 0, max = this.frameObjects.length; i < max; i++) {
  738. tobj = this.frameObjects[i];
  739. switch (tobj.getTuioState()) {
  740. case Tuio.Object.TUIO_REMOVED:
  741. this.objectRemoved(tobj);
  742. break;
  743. case Tuio.Object.TUIO_ADDED:
  744. this.objectAdded(tobj);
  745. break;
  746. default:
  747. this.objectDefault(tobj);
  748. break;
  749. }
  750. }
  751. this.trigger("refresh", Tuio.Time.fromTime(this.currentTime));
  752. var buffer = this.aliveObjectList;
  753. this.aliveObjectList = this.newObjectList;
  754. this.newObjectList = buffer;
  755. }
  756. this.frameObjects = [];
  757. },
  758. objectRemoved: function(tobj) {
  759. var removeObject = tobj;
  760. removeObject.remove(this.currentTime);
  761. this.trigger("removeTuioObject", removeObject);
  762. delete this.objectList[removeObject.getSessionId()];
  763. },
  764. objectAdded: function(tobj) {
  765. var addObject = new Tuio.Object({
  766. ttime: this.currentTime,
  767. si: tobj.getSessionId(),
  768. sym: tobj.getSymbolId(),
  769. xp: tobj.getX(),
  770. yp: tobj.getY(),
  771. a: tobj.getAngle()
  772. });
  773. this.objectList[addObject.getSessionId()] = addObject;
  774. this.trigger("addTuioObject", addObject);
  775. },
  776. objectDefault: function(tobj) {
  777. var updateObject = this.objectList[tobj.getSessionId()];
  778. if (
  779. (tobj.getX() !== updateObject.getX() && tobj.getXSpeed() === 0) ||
  780. (tobj.getY() !== updateObject.getY() && tobj.getYSpeed() === 0)) {
  781. updateObject.update({
  782. ttime: this.currentTime,
  783. xp: tobj.getX(),
  784. yp: tobj.getY(),
  785. a: tobj.getAngle()
  786. });
  787. } else {
  788. updateObject.update({
  789. ttime: this.currentTime,
  790. xp: tobj.getX(),
  791. yp: tobj.getY(),
  792. a: tobj.getAngle(),
  793. xs: tobj.getXSpeed(),
  794. ys: tobj.getYSpeed(),
  795. rs: tobj.getRotationSpeed(),
  796. ma: tobj.getMotionAccel(),
  797. ra: tobj.getRotationAccel()
  798. });
  799. }
  800. this.trigger("updateTuioObject", updateObject);
  801. },
  802. cursorSet: function(args) {
  803. var sid = args[0],
  804. xPos = args[1],
  805. yPos = args[2],
  806. xSpeed = args[3],
  807. ySpeed = args[4],
  808. mAccel = args[5];
  809. if (!_.has(this.cursorList, sid)) {
  810. var addCursor = new Tuio.Cursor({
  811. si: sid,
  812. ci: -1,
  813. xp: xPos,
  814. yp: yPos
  815. });
  816. this.frameCursors.push(addCursor);
  817. } else {
  818. var tcur = this.cursorList[sid];
  819. if (!tcur) {
  820. return;
  821. }
  822. if (
  823. (tcur.xPos !== xPos) ||
  824. (tcur.yPos !== yPos) ||
  825. (tcur.xSpeed !== xSpeed) ||
  826. (tcur.ySpeed !== ySpeed) ||
  827. (tcur.motionAccel !== mAccel)) {
  828. var updateCursor = new Tuio.Cursor({
  829. si: sid,
  830. ci: tcur.getCursorId(),
  831. xp: xPos,
  832. yp: yPos
  833. });
  834. updateCursor.update({
  835. xp: xPos,
  836. yp: yPos,
  837. xs: xSpeed,
  838. ys: ySpeed,
  839. ma: mAccel
  840. });
  841. this.frameCursors.push(updateCursor);
  842. }
  843. }
  844. },
  845. cursorAlive: function(args) {
  846. var removeCursor = null;
  847. this.newCursorList = args;
  848. this.aliveCursorList = _.difference(this.aliveCursorList, this.newCursorList);
  849. for (var i = 0, max = this.aliveCursorList.length; i < max; i++) {
  850. removeCursor = this.cursorList[this.aliveCursorList[i]];
  851. if (removeCursor) {
  852. removeCursor.remove(this.currentTime);
  853. this.frameCursors.push(removeCursor);
  854. }
  855. }
  856. },
  857. cursorFseq: function(args) {
  858. var fseq = args[0],
  859. lateFrame = false,
  860. tcur = null;
  861. if (fseq > 0) {
  862. if (fseq > this.currentFrame) {
  863. this.currentTime = Tuio.Time.getSessionTime();
  864. }
  865. if ((fseq >= this.currentFrame) || ((this.currentFrame - fseq) > 100)) {
  866. this.currentFrame = fseq;
  867. } else {
  868. lateFrame = true;
  869. }
  870. } else if (Tuio.Time.getSessionTime().subtractTime(this.currentTime).getTotalMilliseconds() > 100) {
  871. this.currentTime = Tuio.Time.getSessionTime();
  872. }
  873. if (!lateFrame) {
  874. for (var i = 0, max = this.frameCursors.length; i < max; i++) {
  875. tcur = this.frameCursors[i];
  876. switch (tcur.getTuioState()) {
  877. case Tuio.Cursor.TUIO_REMOVED:
  878. this.cursorRemoved(tcur);
  879. break;
  880. case Tuio.Cursor.TUIO_ADDED:
  881. this.cursorAdded(tcur);
  882. break;
  883. default:
  884. this.cursorDefault(tcur);
  885. break;
  886. }
  887. }
  888. this.trigger("refresh", Tuio.Time.fromTime(this.currentTime));
  889. var buffer = this.aliveCursorList;
  890. this.aliveCursorList = this.newCursorList;
  891. this.newCursorList = buffer;
  892. }
  893. this.frameCursors = [];
  894. },
  895. cursorRemoved: function(tcur) {
  896. var removeCursor = tcur;
  897. removeCursor.remove(this.currentTime);
  898. this.trigger("removeTuioCursor", removeCursor);
  899. delete this.cursorList[removeCursor.getSessionId()];
  900. if (removeCursor.getCursorId() === this.maxCursorId) {
  901. this.maxCursorId = -1;
  902. if (_.size(this.cursorList) > 0) {
  903. var maxCursor = _.max(this.cursorList, function(cur) {
  904. return cur.getCursorId();
  905. });
  906. if (maxCursor.getCursorId() > this.maxCursorId) {
  907. this.maxCursorId = maxCursor.getCursorId();
  908. }
  909. this.freeCursorList = _.without(this.freeCursorList, function(cur) {
  910. return cur.getCursorId() >= this.maxCursorId;
  911. });
  912. } else {
  913. this.freeCursorList = [];
  914. }
  915. } else if (removeCursor.getCursorId() < this.maxCursorId) {
  916. this.freeCursorList.push(removeCursor);
  917. }
  918. },
  919. cursorAdded: function(tcur) {
  920. var cid = _.size(this.cursorList),
  921. testCursor = null;
  922. if ((cid <= this.maxCursorId) && (this.freeCursorList.length > 0)) {
  923. var closestCursor = this.freeCursorList[0];
  924. for (var i = 0, max = this.freeCursorList.length; i < max; i++) {
  925. testCursor = this.freeCursorList[i];
  926. if (testCursor.getDistanceToPoint(tcur) < closestCursor.getDistanceToPoint(tcur)) {
  927. closestCursor = testCursor;
  928. }
  929. }
  930. cid = closestCursor.getCursorId();
  931. this.freeCursorList = _.without(this.freeCursorList, function(cur) {
  932. return cur.getCursorId() === cid;
  933. });
  934. } else {
  935. this.maxCursorId = cid;
  936. }
  937. var addCursor = new Tuio.Cursor({
  938. ttime: this.currentTime,
  939. si: tcur.getSessionId(),
  940. ci: cid,
  941. xp: tcur.getX(),
  942. yp: tcur.getY()
  943. });
  944. this.cursorList[addCursor.getSessionId()] = addCursor;
  945. this.trigger("addTuioCursor", addCursor);
  946. },
  947. cursorDefault: function(tcur) {
  948. var updateCursor = this.cursorList[tcur.getSessionId()];
  949. if (
  950. (tcur.getX() !== updateCursor.getX() && tcur.getXSpeed() === 0) ||
  951. (tcur.getY() !== updateCursor.getY() && tcur.getYSpeed() === 0)) {
  952. updateCursor.update({
  953. ttime: this.currentTime,
  954. xp: tcur.getX(),
  955. yp: tcur.getY()
  956. });
  957. } else {
  958. updateCursor.update({
  959. ttime: this.currentTime,
  960. xp: tcur.getX(),
  961. yp: tcur.getY(),
  962. xs: tcur.getXSpeed(),
  963. ys: tcur.getYSpeed(),
  964. ma: tcur.getMotionAccel()
  965. });
  966. }
  967. this.trigger("updateTuioCursor", updateCursor);
  968. }
  969. });