diff --git a/Gruntfile.coffee b/Gruntfile.coffee
index 93e702b..dc45b51 100644
--- a/Gruntfile.coffee
+++ b/Gruntfile.coffee
@@ -31,6 +31,15 @@ module.exports = (grunt) ->
grunt.initConfig
pkg: grunt.file.readJSON("package.json")
+ watch:
+ options:
+ livereload: true
+ js:
+ files: ['main/**/*.coffee', 'main/**/*.html'],
+ tasks: ['default'],
+ options:
+ spawn: false
+
coffee:
main:
files: [{
diff --git a/extras/leap-plugins-0.1.4-extras.min.js b/extras/leap-plugins-0.1.4-extras.min.js
index 86af93d..418945f 100644
--- a/extras/leap-plugins-0.1.4-extras.min.js
+++ b/extras/leap-plugins-0.1.4-extras.min.js
@@ -1,5 +1,5 @@
/*
- * LeapJS-Plugins Extra - v0.1.4 - 2014-04-08
+ * LeapJS-Plugins Extra - v0.1.4 - 2014-04-27
* http://github.com/leapmotion/leapjs-plugins/
*
* Copyright 2014 LeapMotion, Inc
diff --git a/main/hand-splay/leap.hand-splay.coffee b/main/hand-splay/leap.hand-splay.coffee
new file mode 100644
index 0000000..a1d7e6f
--- /dev/null
+++ b/main/hand-splay/leap.hand-splay.coffee
@@ -0,0 +1,47 @@
+# measures how spread out and flat a hand is
+# fires 'handSplay' and 'handUnsplay' events from the controller
+#
+# Two items are made accessible through hand.data
+# hand.data('handSplay.splay') returns the fractional splay amount, 0 to 1
+# hand.data('handSplay.splayed') returns a boolean: whether the hand is considered splayed or not
+
+Leap.Controller.plugin 'handSplay', (scope = {})->
+ scope.splayThreshold ||= 0.65
+ scope.requiredFingers ||= 4
+
+ @use('handHold')
+
+ {
+ hand: (hand)->
+ palmDot = null
+ avgPalmDot = 0
+ straightenedFingerCount = 0
+
+ # set base data, find minimum
+ for finger in hand.fingers
+ palmDot = Leap.vec3.dot( hand.direction, finger.direction )
+ avgPalmDot += palmDot
+
+ if palmDot > scope.splayThreshold
+ straightenedFingerCount++
+
+ # v1 tracking backwards compatibility
+ # missing fingers treated as mid-curl
+ avgPalmDot += 0.5 * (5 - hand.fingers.length)
+
+ avgPalmDot /= 5
+
+ hand.data('handSplay.splay', avgPalmDot)
+ hand.data('handSplay.splayedFingers', straightenedFingerCount)
+
+ if avgPalmDot > scope.splayThreshold || straightenedFingerCount >= scope.requiredFingers
+ unless hand.data('handSplay.splayed')
+ hand.data('handSplay.splayed': true)
+ @emit('handSplay', hand)
+
+ else
+ if hand.data('handSplay.splayed')
+ @emit('handUnsplay', hand)
+ hand.data('handSplay.splayed': false)
+
+ }
\ No newline at end of file
diff --git a/main/hand-splay/leap.hand-splay.js b/main/hand-splay/leap.hand-splay.js
new file mode 100644
index 0000000..12828a3
--- /dev/null
+++ b/main/hand-splay/leap.hand-splay.js
@@ -0,0 +1,48 @@
+//CoffeeScript generated from main/hand-splay/leap.hand-splay.coffee
+(function() {
+ Leap.Controller.plugin('handSplay', function(scope) {
+ if (scope == null) {
+ scope = {};
+ }
+ scope.splayThreshold || (scope.splayThreshold = 0.65);
+ scope.requiredFingers || (scope.requiredFingers = 4);
+ this.use('handHold');
+ return {
+ hand: function(hand) {
+ var avgPalmDot, finger, palmDot, straightenedFingerCount, _i, _len, _ref;
+ palmDot = null;
+ avgPalmDot = 0;
+ straightenedFingerCount = 0;
+ _ref = hand.fingers;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ finger = _ref[_i];
+ palmDot = Leap.vec3.dot(hand.direction, finger.direction);
+ avgPalmDot += palmDot;
+ if (palmDot > scope.splayThreshold) {
+ straightenedFingerCount++;
+ }
+ }
+ avgPalmDot += 0.5 * (5 - hand.fingers.length);
+ avgPalmDot /= 5;
+ hand.data('handSplay.splay', avgPalmDot);
+ hand.data('handSplay.splayedFingers', straightenedFingerCount);
+ if (avgPalmDot > scope.splayThreshold || straightenedFingerCount >= scope.requiredFingers) {
+ if (!hand.data('handSplay.splayed')) {
+ hand.data({
+ 'handSplay.splayed': true
+ });
+ return this.emit('handSplay', hand);
+ }
+ } else {
+ if (hand.data('handSplay.splayed')) {
+ this.emit('handUnsplay', hand);
+ return hand.data({
+ 'handSplay.splayed': false
+ });
+ }
+ }
+ }
+ };
+ });
+
+}).call(this);
diff --git a/main/hand-splay/test.html b/main/hand-splay/test.html
new file mode 100644
index 0000000..7642bd9
--- /dev/null
+++ b/main/hand-splay/test.html
@@ -0,0 +1,40 @@
+
+
+ Hand Splay
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/main/leap-plugins-0.1.4.js b/main/leap-plugins-0.1.4.js
index 6d447d0..4e9b3d3 100644
--- a/main/leap-plugins-0.1.4.js
+++ b/main/leap-plugins-0.1.4.js
@@ -1,5 +1,5 @@
/*
- * LeapJS-Plugins - v0.1.4 - 2014-04-08
+ * LeapJS-Plugins - v0.1.4 - 2014-04-27
* http://github.com/leapmotion/leapjs-plugins/
*
* Copyright 2014 LeapMotion, Inc
@@ -157,10 +157,54 @@ Each event also includes the hand object, which will be invalid for the handLost
}).call(this);
+//CoffeeScript generated from main/hand-splay/leap.hand-splay.coffee
+(function() {
+ Leap.Controller.plugin('handSplay', function(scope) {
+ if (scope == null) {
+ scope = {};
+ }
+ scope.splayThreshold || (scope.splayThreshold = 0.65);
+ scope.requiredFingers || (scope.requiredFingers = 4);
+ this.use('handHold');
+ return {
+ hand: function(hand) {
+ var avgPalmDot, finger, palmDot, straightenedFingerCount, _i, _len, _ref;
+ palmDot = null;
+ avgPalmDot = 0;
+ straightenedFingerCount = 0;
+ _ref = hand.fingers;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ finger = _ref[_i];
+ palmDot = Leap.vec3.dot(hand.direction, finger.direction);
+ avgPalmDot += palmDot;
+ if (palmDot > scope.splayThreshold) {
+ straightenedFingerCount++;
+ }
+ }
+ avgPalmDot += 0.5 * (5 - hand.fingers.length);
+ avgPalmDot /= 5;
+ hand.data('handSplay.splay', avgPalmDot);
+ hand.data('handSplay.splayedFingers', straightenedFingerCount);
+ if (avgPalmDot > scope.splayThreshold || straightenedFingerCount >= scope.requiredFingers) {
+ if (!hand.data('handSplay.splayed')) {
+ hand.data({
+ 'handSplay.splayed': true
+ });
+ return this.emit('handSplay', hand);
+ }
+ } else {
+ if (hand.data('handSplay.splayed')) {
+ this.emit('handUnsplay', hand);
+ return hand.data({
+ 'handSplay.splayed': false
+ });
+ }
+ }
+ }
+ };
+ });
-
-
-
+}).call(this);
(function () {
diff --git a/main/leap-plugins-0.1.4.min.js b/main/leap-plugins-0.1.4.min.js
index 4142aa3..2fd79cd 100644
--- a/main/leap-plugins-0.1.4.min.js
+++ b/main/leap-plugins-0.1.4.min.js
@@ -1,5 +1,5 @@
/*
- * LeapJS-Plugins - v0.1.4 - 2014-04-08
+ * LeapJS-Plugins - v0.1.4 - 2014-04-27
* http://github.com/leapmotion/leapjs-plugins/
*
* Copyright 2014 LeapMotion, Inc
@@ -17,5 +17,5 @@
* limitations under the License.
*
*/
-(function(){var a;if(a=function(){var a;return a=[],this.on("deviceDisconnected",function(){for(var b=0,c=a.length;c>b;b++)id=a[b],a.splice(b,1),this.emit("handLost",this.lastConnectionFrame.hand(id)),b--,c--}),{frame:function(b){var c,d,e,f,g;d=b.hands.map(function(a){return a.id});for(var h=0,i=a.length;i>h;h++)c=a[h],-1==d.indexOf(c)&&(a.splice(h,1),this.emit("handLost",this.frame(1).hand(c)),h--,i--);for(g=[],e=0,f=d.length;f>e;e++)c=d[e],-1===a.indexOf(c)?(a.push(c),g.push(this.emit("handFound",b.hand(c)))):g.push(void 0);return g}}},"undefined"!=typeof Leap&&Leap.Controller)Leap.Controller.plugin("handEntry",a);else{if("undefined"==typeof module)throw"leap.js not included";module.exports.handEntry=a}}).call(this),function(){var a;if(a=function(){var a;return a={},{hand:{data:function(b,c){var d,e,f;if(a[e=this.id]||(a[e]=[]),c)return a[this.id][b]=c;if("[object String]"===toString.call(b))return a[this.id][b];f=[];for(d in b)c=b[d],f.push(void 0===c?delete a[this.id][d]:a[this.id][d]=c);return f},hold:function(a){return a?this.data({holding:a}):this.hold(this.hovering())},holding:function(){return this.data("holding")},release:function(){var a;return a=this.data("holding"),this.data({holding:void 0}),a},hoverFn:function(a){return this.data({getHover:a})},hovering:function(){var a;return(a=this.data("getHover"))?this._hovering||(this._hovering=a.call(this)):void 0}}}},"undefined"!=typeof Leap&&Leap.Controller)Leap.Controller.plugin("handHold",a);else{if("undefined"==typeof module)throw"leap.js not included";module.exports.handHold=a}}.call(this),function(){function a(a,b){var c=this;if(this.frameData=[],this.maxFrames=1e4,this.options=b,this.frameIndex=0,this.controller=a,this.scrollSections=this.options.scrollSections,this.loading=!1,this.setupLoops(),this.controller.connection.on("ready",function(){c.setupProtocols()}),b&&(isNaN(b)?b.maxFrames&&(this.maxFrames=b.maxFrames):this.maxFrames=b,b.onMaxFrames&&this.on("maxFrames",b.onMaxFrames.bind(this)),b.recording&&this.loadFrameData(b,function(){this.setFrames(b.recording),this.metadata=b.recording.metadata,b.onReady.call(this)}),b.scrollSections&&b.scrollSections.length>0)){for(var d=0;d
',c='
';a.prototype={setupLoops:function(){var a=this;this.stepFrameLoop=function(){"playing"==a.state&&(a.sendFrame(a.currentFrame()),!a.options.loop&&a.currentFrameIndex>a.frameIndex&&a.pause(),setTimeout(a.stepFrameLoop,a.timeToNextFrame()),a.advanceFrame())},this.stepAnimationLoop=function(){"playing"==a.state&&(a.sendCurrentSectionFrame(),requestAnimationFrame(a.stepAnimationLoop))}},setupProtocols:function(){var a=this;this.stopProtocol=this.controller.connection.protocol,this.playbackProtocol=function(b){var c=a.stopProtocol(b);return c instanceof Leap.Frame?(a.pauseOnHand&&(b.hands.length>0?(a.setGraphic(),a.idle()):0==b.hands.length&&a.setGraphic("wave")),{type:"playback"}):c},this.recordProtocol=function(b){var c=a.stopProtocol(b);return c instanceof Leap.Frame&&a.recordFrameHandler(b),c};for(var b in this.stopProtocol)this.stopProtocol.hasOwnProperty(b)&&(this.playbackProtocol[b]=this.stopProtocol[b],this.recordProtocol[b]=this.stopProtocol[b]);"playing"==this.state&&(this.controller.connection.protocol=this.playbackProtocol)},currentFrame:function(){return this.frameData[this.frameIndex]},nextFrame:function(){var a=this.frameIndex+1;return a%=this.rightCropPosition||1,aa&&(a=this.timeBetweenLoops),a},sendFrame:function(a){if(!a)throw"Frame data not provided";var b=new Leap.Frame(a);return this.controller.processFrame(b),this.currentFrameIndex=this.frameIndex,!0},sendCurrentSectionFrame:function(){if(!this.scrollSections)return!1;for(var a,b=0;b0&&a.completion<1)return this.setSectionPosition(a),!0;return!0},stop:function(){this.setFrames({frames:[]}),this.idle()},pause:function(){this.state="idle",this.overlay&&this.hideOverlay()},idle:function(){this.state="idle",this.controller.connection.protocol=this.stopProtocol},record:function(){this.stop(),this.frameData=[],this.frameIndex=0,this.state="recording",this.controller.connection.protocol=this.recordProtocol,this.setGraphic("connect")},recordPending:function(){return"recording"==this.state&&0==this.frameData.length},recording:function(){return"recording"==this.state&&0!=this.frameData.length},finishRecording:function(){this.play(),this.pause(),this.setFrames({frames:this.frameData}),this.controller.emit("playback.recordingFinished",this)},setFrames:function(a){a.frames&&(this.frameData=a.frames,this.frameIndex=0,this.maxFrames=a.frames.length,this.leftCropPosition=0,this.rightCropPosition=this.maxFrames)},loaded:function(){return this.frameData&&this.frameData.length},setSectionPosition:function(a){if(void 0!==a.recording.frames){var b=Math.round(a.completion*a.recording.frames.length);b!=a.currentPosition&&(a.currentPosition=b,this.sendFrame(a.recording.frames[b]))}},setFrameIndex:function(a){a!=this.frameIndex&&(this.frameIndex=a%this.maxFrames,this.sendFrame(this.currentFrame()))},leftCrop:function(){this.leftCropPosition=this.frameIndex},rightCrop:function(){this.rightCropPosition=this.frameIndex},play:function(a){if("playing"!=this.state&&1!=this.loading){this.state="playing",this.controller.connection.protocol=this.playbackProtocol,void 0===a&&(a=!0),(a===!0||a===!1)&&(a={loop:a}),void 0===a.loop&&(a.loop=!0),this.options=a,this.state="playing";var b=this;this.controller.connection.removeAllListeners("frame"),this.controller.connection.on("frame",function(a){b.autoPlay&&"idle"==b.state&&0==a.hands.length&&b.play(),b.controller.processFrame(a)}),this.scrollSections?this.stepAnimationLoop():this.stepFrameLoop()}},recordFrameHandler:function(a){this.setGraphic("wave"),a.hands.length>0?(this.frameData.push(a),this.hideOverlay()):this.frameData.length>0&&this.finishRecording()},loadFrameData:function(a,b){if("string"!=typeof a.recording)b&&b.call(this,a.recording);else{var c=new XMLHttpRequest,d=this,e=a.recording;c.onreadystatechange=function(){c.readyState===c.DONE&&(200===c.status||0===c.status?c.responseText?(a.recording=c.responseText,"lz"==e.split(".")[e.split(".").length-1]&&(a.recording=d.decompressJSON(a.recording)),a.recording=JSON.parse(a.recording),d.loading=!1,b&&b.call(d,a.recording),d.controller.emit("playback.ajax:complete",d)):console.error('Leap Playback: "'+e+'" seems to be unreachable or the file is empty.'):console.error("Leap Playback: Couldn't load \""+e+'" ('+c.status+")"))},d.loading=!0,d.controller.emit("playback.ajax:begin",d),c.open("GET",e,!0),c.send(null)}},hideOverlay:function(){this.overlay.style.display="none"},setGraphic:function(a){if(this.graphicName!=a)switch(this.graphicName=a,a){case"connect":this.overlay.style.display="block",this.overlay.innerHTML=b;break;case"wave":this.overlay.style.display="block",this.overlay.innerHTML=c;break;case void 0:this.overlay.innerHTML=""}},cullFrames:function(a){a||(a=1);for(var b=0;b>8,c=255&a.charCodeAt(j/2),d=j/2+1>8:0/0):(b=255&a.charCodeAt((j-1)/2),(j+1)/2>8,d=255&a.charCodeAt((j+1)/2)):c=d=0/0),j+=3,e=b>>2,f=(3&b)<<4|c>>4,g=(15&c)<<2|d>>6,h=63&d,isNaN(c)?g=h=64:isNaN(d)&&(h=64),i=i+this._keyStr.charAt(e)+this._keyStr.charAt(f)+this._keyStr.charAt(g)+this._keyStr.charAt(h);return i},decompressFromBase64:function(a){if(null==a)return"";var b,c,d,e,f,g,h,i,j="",k=0,l=0,m=this._f;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");l>4,d=(15&g)<<4|h>>2,e=(3&h)<<6|i,k%2==0?(b=c<<8,64!=h&&(j+=m(b|d)),64!=i&&(b=e<<8)):(j+=m(b|c),64!=h&&(b=d<<8),64!=i&&(j+=m(b|e))),k+=3;return this.decompress(j)},compress:function(a){if(null==a)return"";var b,c,d,e={},f={},g="",h="",i="",j=2,k=3,l=2,m="",n=0,o=0,p=this._f;for(d=0;db;b++)n<<=1,15==o?(o=0,m+=p(n),n=0):o++;for(c=i.charCodeAt(0),b=0;8>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1}else{for(c=1,b=0;l>b;b++)n=n<<1|c,15==o?(o=0,m+=p(n),n=0):o++,c=0;for(c=i.charCodeAt(0),b=0;16>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1}j--,0==j&&(j=Math.pow(2,l),l++),delete f[i]}else for(c=e[i],b=0;l>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1;j--,0==j&&(j=Math.pow(2,l),l++),e[h]=k++,i=String(g)}if(""!==i){if(Object.prototype.hasOwnProperty.call(f,i)){if(i.charCodeAt(0)<256){for(b=0;l>b;b++)n<<=1,15==o?(o=0,m+=p(n),n=0):o++;for(c=i.charCodeAt(0),b=0;8>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1}else{for(c=1,b=0;l>b;b++)n=n<<1|c,15==o?(o=0,m+=p(n),n=0):o++,c=0;for(c=i.charCodeAt(0),b=0;16>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1}j--,0==j&&(j=Math.pow(2,l),l++),delete f[i]}else for(c=e[i],b=0;l>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1;j--,0==j&&(j=Math.pow(2,l),l++)}for(c=2,b=0;l>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1;for(;;){if(n<<=1,15==o){m+=p(n);break}o++}return m},decompress:function(a){if(null==a)return"";if(""==a)return null;var b,c,d,e,f,g,h,i,j=[],k=4,l=4,m=3,n="",o="",p=this._f,q={string:a,val:a.charCodeAt(0),position:32768,index:1};for(c=0;3>c;c+=1)j[c]=c;for(e=0,g=Math.pow(2,2),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;switch(b=e){case 0:for(e=0,g=Math.pow(2,8),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;i=p(e);break;case 1:for(e=0,g=Math.pow(2,16),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;i=p(e);break;case 2:return""}for(j[3]=i,d=o=i;;){if(q.index>q.string.length)return"";for(e=0,g=Math.pow(2,m),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;switch(i=e){case 0:for(e=0,g=Math.pow(2,8),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;j[l++]=p(e),i=l-1,k--;break;case 1:for(e=0,g=Math.pow(2,16),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;j[l++]=p(e),i=l-1,k--;break;case 2:return o}if(0==k&&(k=Math.pow(2,m),m++),j[i])n=j[i];
-else{if(i!==l)return null;n=d+d.charAt(0)}o+=n,j[l++]=d+n.charAt(0),k--,d=n,0==k&&(k=Math.pow(2,m),m++)}}};var d=function(b){var c=this,d=b.autoPlay;void 0===d&&(d=!0);var e=b.pauseOnHand;void 0===e&&(e=!1);var f=b.timeBetweenLoops;void 0===f&&(f=50);var g=b.requiredProtocolVersion,h=b.overlay;void 0===h&&document.body&&(h=document.createElement("div"),document.body.appendChild(h),h.style.width="100%",h.style.position="absolute",h.style.top="0",h.style.left="-"+window.getComputedStyle(document.body).getPropertyValue("margin"),h.style.padding="10px",h.style.textAlign="center",h.style.fontSize="18px",h.style.opacity="0.8",h.style.display="none",h.style.zIndex="10"),b.player=new a(this,{recording:b.recording,scrollSections:b.scrollSections,onReady:function(){d&&!c.connection.connected&&(this.play(),this.pauseOnHand&&this.setGraphic("connect"))}}),b.player.overlay=h,b.player.pauseOnHand=e,b.player.requiredProtocolVersion=g,b.player.autoPlay=d,b.player.timeBetweenLoops=f;var i=function(){return c.connection.opts.requestProtocolVersionb?(c="Protocol Version too old. v"+d+" required, v"+b+" available.",a.disconnect&&(this.disconnect(),c+=" Disconnecting."),console.warn(c),a.alert&&alert("Your Leap Software version is out of date. Visit http://www.leapmotion.com/setup to update"),this.emit("versionCheck.outdated",{required:d,current:b,disconnect:a.disconnect})):void 0}),{}},"undefined"!=typeof Leap&&Leap.Controller)Leap.Controller.plugin("versionCheck",a);else{if("undefined"==typeof module)throw"leap.js not included";module.exports.versionCheck=a}}.call(this);
\ No newline at end of file
+(function(){var a;if(a=function(){var a;return a=[],this.on("deviceDisconnected",function(){for(var b=0,c=a.length;c>b;b++)id=a[b],a.splice(b,1),this.emit("handLost",this.lastConnectionFrame.hand(id)),b--,c--}),{frame:function(b){var c,d,e,f,g;d=b.hands.map(function(a){return a.id});for(var h=0,i=a.length;i>h;h++)c=a[h],-1==d.indexOf(c)&&(a.splice(h,1),this.emit("handLost",this.frame(1).hand(c)),h--,i--);for(g=[],e=0,f=d.length;f>e;e++)c=d[e],-1===a.indexOf(c)?(a.push(c),g.push(this.emit("handFound",b.hand(c)))):g.push(void 0);return g}}},"undefined"!=typeof Leap&&Leap.Controller)Leap.Controller.plugin("handEntry",a);else{if("undefined"==typeof module)throw"leap.js not included";module.exports.handEntry=a}}).call(this),function(){var a;if(a=function(){var a;return a={},{hand:{data:function(b,c){var d,e,f;if(a[e=this.id]||(a[e]=[]),c)return a[this.id][b]=c;if("[object String]"===toString.call(b))return a[this.id][b];f=[];for(d in b)c=b[d],f.push(void 0===c?delete a[this.id][d]:a[this.id][d]=c);return f},hold:function(a){return a?this.data({holding:a}):this.hold(this.hovering())},holding:function(){return this.data("holding")},release:function(){var a;return a=this.data("holding"),this.data({holding:void 0}),a},hoverFn:function(a){return this.data({getHover:a})},hovering:function(){var a;return(a=this.data("getHover"))?this._hovering||(this._hovering=a.call(this)):void 0}}}},"undefined"!=typeof Leap&&Leap.Controller)Leap.Controller.plugin("handHold",a);else{if("undefined"==typeof module)throw"leap.js not included";module.exports.handHold=a}}.call(this),function(){Leap.Controller.plugin("handSplay",function(a){return null==a&&(a={}),a.splayThreshold||(a.splayThreshold=.65),a.requiredFingers||(a.requiredFingers=4),this.use("handHold"),{hand:function(b){var c,d,e,f,g,h,i;for(e=null,c=0,f=0,i=b.fingers,g=0,h=i.length;h>g;g++)d=i[g],e=Leap.vec3.dot(b.direction,d.direction),c+=e,e>a.splayThreshold&&f++;if(c+=.5*(5-b.fingers.length),c/=5,b.data("handSplay.splay",c),b.data("handSplay.splayedFingers",f),c>a.splayThreshold||f>=a.requiredFingers){if(!b.data("handSplay.splayed"))return b.data({"handSplay.splayed":!0}),this.emit("handSplay",b)}else if(b.data("handSplay.splayed"))return this.emit("handUnsplay",b),b.data({"handSplay.splayed":!1})}}})}.call(this),function(){function a(a,b){var c=this;if(this.frameData=[],this.maxFrames=1e4,this.options=b,this.frameIndex=0,this.controller=a,this.scrollSections=this.options.scrollSections,this.loading=!1,this.setupLoops(),this.controller.connection.on("ready",function(){c.setupProtocols()}),b&&(isNaN(b)?b.maxFrames&&(this.maxFrames=b.maxFrames):this.maxFrames=b,b.onMaxFrames&&this.on("maxFrames",b.onMaxFrames.bind(this)),b.recording&&this.loadFrameData(b,function(){this.setFrames(b.recording),this.metadata=b.recording.metadata,b.onReady.call(this)}),b.scrollSections&&b.scrollSections.length>0)){for(var d=0;d
',c='
';a.prototype={setupLoops:function(){var a=this;this.stepFrameLoop=function(){"playing"==a.state&&(a.sendFrame(a.currentFrame()),!a.options.loop&&a.currentFrameIndex>a.frameIndex&&a.pause(),setTimeout(a.stepFrameLoop,a.timeToNextFrame()),a.advanceFrame())},this.stepAnimationLoop=function(){"playing"==a.state&&(a.sendCurrentSectionFrame(),requestAnimationFrame(a.stepAnimationLoop))}},setupProtocols:function(){var a=this;this.stopProtocol=this.controller.connection.protocol,this.playbackProtocol=function(b){var c=a.stopProtocol(b);return c instanceof Leap.Frame?(a.pauseOnHand&&(b.hands.length>0?(a.setGraphic(),a.idle()):0==b.hands.length&&a.setGraphic("wave")),{type:"playback"}):c},this.recordProtocol=function(b){var c=a.stopProtocol(b);return c instanceof Leap.Frame&&a.recordFrameHandler(b),c};for(var b in this.stopProtocol)this.stopProtocol.hasOwnProperty(b)&&(this.playbackProtocol[b]=this.stopProtocol[b],this.recordProtocol[b]=this.stopProtocol[b]);"playing"==this.state&&(this.controller.connection.protocol=this.playbackProtocol)},currentFrame:function(){return this.frameData[this.frameIndex]},nextFrame:function(){var a=this.frameIndex+1;return a%=this.rightCropPosition||1,aa&&(a=this.timeBetweenLoops),a},sendFrame:function(a){if(!a)throw"Frame data not provided";var b=new Leap.Frame(a);return this.controller.processFrame(b),this.currentFrameIndex=this.frameIndex,!0},sendCurrentSectionFrame:function(){if(!this.scrollSections)return!1;for(var a,b=0;b0&&a.completion<1)return this.setSectionPosition(a),!0;return!0},stop:function(){this.setFrames({frames:[]}),this.idle()},pause:function(){this.state="idle",this.overlay&&this.hideOverlay()},idle:function(){this.state="idle",this.controller.connection.protocol=this.stopProtocol},record:function(){this.stop(),this.frameData=[],this.frameIndex=0,this.state="recording",this.controller.connection.protocol=this.recordProtocol,this.setGraphic("connect")},recordPending:function(){return"recording"==this.state&&0==this.frameData.length},recording:function(){return"recording"==this.state&&0!=this.frameData.length},finishRecording:function(){this.play(),this.pause(),this.setFrames({frames:this.frameData}),this.controller.emit("playback.recordingFinished",this)},setFrames:function(a){a.frames&&(this.frameData=a.frames,this.frameIndex=0,this.maxFrames=a.frames.length,this.leftCropPosition=0,this.rightCropPosition=this.maxFrames)},loaded:function(){return this.frameData&&this.frameData.length},setSectionPosition:function(a){if(void 0!==a.recording.frames){var b=Math.round(a.completion*a.recording.frames.length);b!=a.currentPosition&&(a.currentPosition=b,this.sendFrame(a.recording.frames[b]))}},setFrameIndex:function(a){a!=this.frameIndex&&(this.frameIndex=a%this.maxFrames,this.sendFrame(this.currentFrame()))},leftCrop:function(){this.leftCropPosition=this.frameIndex},rightCrop:function(){this.rightCropPosition=this.frameIndex},play:function(a){if("playing"!=this.state&&1!=this.loading){this.state="playing",this.controller.connection.protocol=this.playbackProtocol,void 0===a&&(a=!0),(a===!0||a===!1)&&(a={loop:a}),void 0===a.loop&&(a.loop=!0),this.options=a,this.state="playing";var b=this;this.controller.connection.removeAllListeners("frame"),this.controller.connection.on("frame",function(a){b.autoPlay&&"idle"==b.state&&0==a.hands.length&&b.play(),b.controller.processFrame(a)}),this.scrollSections?this.stepAnimationLoop():this.stepFrameLoop()}},recordFrameHandler:function(a){this.setGraphic("wave"),a.hands.length>0?(this.frameData.push(a),this.hideOverlay()):this.frameData.length>0&&this.finishRecording()},loadFrameData:function(a,b){if("string"!=typeof a.recording)b&&b.call(this,a.recording);else{var c=new XMLHttpRequest,d=this,e=a.recording;c.onreadystatechange=function(){c.readyState===c.DONE&&(200===c.status||0===c.status?c.responseText?(a.recording=c.responseText,"lz"==e.split(".")[e.split(".").length-1]&&(a.recording=d.decompressJSON(a.recording)),a.recording=JSON.parse(a.recording),d.loading=!1,b&&b.call(d,a.recording),d.controller.emit("playback.ajax:complete",d)):console.error('Leap Playback: "'+e+'" seems to be unreachable or the file is empty.'):console.error("Leap Playback: Couldn't load \""+e+'" ('+c.status+")"))},d.loading=!0,d.controller.emit("playback.ajax:begin",d),c.open("GET",e,!0),c.send(null)}},hideOverlay:function(){this.overlay.style.display="none"},setGraphic:function(a){if(this.graphicName!=a)switch(this.graphicName=a,a){case"connect":this.overlay.style.display="block",this.overlay.innerHTML=b;break;case"wave":this.overlay.style.display="block",this.overlay.innerHTML=c;break;case void 0:this.overlay.innerHTML=""}},cullFrames:function(a){a||(a=1);for(var b=0;b>8,c=255&a.charCodeAt(j/2),d=j/2+1>8:0/0):(b=255&a.charCodeAt((j-1)/2),(j+1)/2>8,d=255&a.charCodeAt((j+1)/2)):c=d=0/0),j+=3,e=b>>2,f=(3&b)<<4|c>>4,g=(15&c)<<2|d>>6,h=63&d,isNaN(c)?g=h=64:isNaN(d)&&(h=64),i=i+this._keyStr.charAt(e)+this._keyStr.charAt(f)+this._keyStr.charAt(g)+this._keyStr.charAt(h);return i},decompressFromBase64:function(a){if(null==a)return"";var b,c,d,e,f,g,h,i,j="",k=0,l=0,m=this._f;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");l>4,d=(15&g)<<4|h>>2,e=(3&h)<<6|i,k%2==0?(b=c<<8,64!=h&&(j+=m(b|d)),64!=i&&(b=e<<8)):(j+=m(b|c),64!=h&&(b=d<<8),64!=i&&(j+=m(b|e))),k+=3;return this.decompress(j)},compress:function(a){if(null==a)return"";var b,c,d,e={},f={},g="",h="",i="",j=2,k=3,l=2,m="",n=0,o=0,p=this._f;for(d=0;db;b++)n<<=1,15==o?(o=0,m+=p(n),n=0):o++;for(c=i.charCodeAt(0),b=0;8>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1}else{for(c=1,b=0;l>b;b++)n=n<<1|c,15==o?(o=0,m+=p(n),n=0):o++,c=0;for(c=i.charCodeAt(0),b=0;16>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1}j--,0==j&&(j=Math.pow(2,l),l++),delete f[i]}else for(c=e[i],b=0;l>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1;j--,0==j&&(j=Math.pow(2,l),l++),e[h]=k++,i=String(g)}if(""!==i){if(Object.prototype.hasOwnProperty.call(f,i)){if(i.charCodeAt(0)<256){for(b=0;l>b;b++)n<<=1,15==o?(o=0,m+=p(n),n=0):o++;for(c=i.charCodeAt(0),b=0;8>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1}else{for(c=1,b=0;l>b;b++)n=n<<1|c,15==o?(o=0,m+=p(n),n=0):o++,c=0;for(c=i.charCodeAt(0),b=0;16>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1}j--,0==j&&(j=Math.pow(2,l),l++),delete f[i]}else for(c=e[i],b=0;l>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1;j--,0==j&&(j=Math.pow(2,l),l++)}for(c=2,b=0;l>b;b++)n=n<<1|1&c,15==o?(o=0,m+=p(n),n=0):o++,c>>=1;for(;;){if(n<<=1,15==o){m+=p(n);break}o++}return m},decompress:function(a){if(null==a)return"";if(""==a)return null;var b,c,d,e,f,g,h,i,j=[],k=4,l=4,m=3,n="",o="",p=this._f,q={string:a,val:a.charCodeAt(0),position:32768,index:1};for(c=0;3>c;c+=1)j[c]=c;for(e=0,g=Math.pow(2,2),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;switch(b=e){case 0:for(e=0,g=Math.pow(2,8),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;i=p(e);break;case 1:for(e=0,g=Math.pow(2,16),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;
+i=p(e);break;case 2:return""}for(j[3]=i,d=o=i;;){if(q.index>q.string.length)return"";for(e=0,g=Math.pow(2,m),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;switch(i=e){case 0:for(e=0,g=Math.pow(2,8),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;j[l++]=p(e),i=l-1,k--;break;case 1:for(e=0,g=Math.pow(2,16),h=1;h!=g;)f=q.val&q.position,q.position>>=1,0==q.position&&(q.position=32768,q.val=q.string.charCodeAt(q.index++)),e|=(f>0?1:0)*h,h<<=1;j[l++]=p(e),i=l-1,k--;break;case 2:return o}if(0==k&&(k=Math.pow(2,m),m++),j[i])n=j[i];else{if(i!==l)return null;n=d+d.charAt(0)}o+=n,j[l++]=d+n.charAt(0),k--,d=n,0==k&&(k=Math.pow(2,m),m++)}}};var d=function(b){var c=this,d=b.autoPlay;void 0===d&&(d=!0);var e=b.pauseOnHand;void 0===e&&(e=!1);var f=b.timeBetweenLoops;void 0===f&&(f=50);var g=b.requiredProtocolVersion,h=b.overlay;void 0===h&&document.body&&(h=document.createElement("div"),document.body.appendChild(h),h.style.width="100%",h.style.position="absolute",h.style.top="0",h.style.left="-"+window.getComputedStyle(document.body).getPropertyValue("margin"),h.style.padding="10px",h.style.textAlign="center",h.style.fontSize="18px",h.style.opacity="0.8",h.style.display="none",h.style.zIndex="10"),b.player=new a(this,{recording:b.recording,scrollSections:b.scrollSections,onReady:function(){d&&!c.connection.connected&&(this.play(),this.pauseOnHand&&this.setGraphic("connect"))}}),b.player.overlay=h,b.player.pauseOnHand=e,b.player.requiredProtocolVersion=g,b.player.autoPlay=d,b.player.timeBetweenLoops=f;var i=function(){return c.connection.opts.requestProtocolVersionb?(c="Protocol Version too old. v"+d+" required, v"+b+" available.",a.disconnect&&(this.disconnect(),c+=" Disconnecting."),console.warn(c),a.alert&&alert("Your Leap Software version is out of date. Visit http://www.leapmotion.com/setup to update"),this.emit("versionCheck.outdated",{required:d,current:b,disconnect:a.disconnect})):void 0}),{}},"undefined"!=typeof Leap&&Leap.Controller)Leap.Controller.plugin("versionCheck",a);else{if("undefined"==typeof module)throw"leap.js not included";module.exports.versionCheck=a}}.call(this);
\ No newline at end of file
diff --git a/main/playback/leap-playback-0.1.js b/main/playback/leap-playback-0.1.js
index ce4b2f2..4842fb7 100644
--- a/main/playback/leap-playback-0.1.js
+++ b/main/playback/leap-playback-0.1.js
@@ -1,3 +1,4 @@
+
(function () {
var CONNECT_LEAP_ICON = '
';
var MOVE_HAND_OVER_LEAP_ICON = '
';
diff --git a/package.json b/package.json
index cbad7fa..bc82d30 100644
--- a/package.json
+++ b/package.json
@@ -6,13 +6,14 @@
"dependencies": {},
"devDependencies": {
"coffee-script": ">=1.7.1",
- "grunt-contrib-concat": "~0.3.0",
- "grunt-contrib-uglify": "~0.3.2",
- "grunt-contrib-coffee": "~0.8.2",
- "grunt-banner": "git://github.com/pehrlich/grunt-banner.git",
- "grunt-contrib-clean": "~0.5.0",
"grunt": "~0.4.2",
+ "grunt-banner": "git://github.com/pehrlich/grunt-banner.git",
"grunt-bump": "0.0.13",
+ "grunt-contrib-clean": "~0.5.0",
+ "grunt-contrib-coffee": "~0.8.2",
+ "grunt-contrib-concat": "~0.3.0",
+ "grunt-contrib-uglify": "~0.3.2",
+ "grunt-contrib-watch": "^0.6.1",
"load-grunt-tasks": "~0.4.0"
},
"repository": {