diff --git a/.eslintrc.js b/.eslintrc.js index b4d88777f2..535abb807e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -54,7 +54,8 @@ module.exports = { "Window": false, "XMLHttpRequest": false, "location": false, - "print": false + "print": false, + "module": false }, "rules": { "brace-style": ["error", "1tbs", { "allowSingleLine": false }], diff --git a/interface/resources/icons/tablet-icons/clap-a.svg b/interface/resources/icons/tablet-icons/clap-a.svg new file mode 100644 index 0000000000..10a8e3ea98 --- /dev/null +++ b/interface/resources/icons/tablet-icons/clap-a.svg @@ -0,0 +1,104 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/interface/resources/icons/tablet-icons/clap-i.svg b/interface/resources/icons/tablet-icons/clap-i.svg new file mode 100644 index 0000000000..3e4ecb0b64 --- /dev/null +++ b/interface/resources/icons/tablet-icons/clap-i.svg @@ -0,0 +1,104 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/unpublishedScripts/marketplace/clap/animations/ClapAnimation.json b/unpublishedScripts/marketplace/clap/animations/ClapAnimation.json new file mode 100644 index 0000000000..2dca45a0de --- /dev/null +++ b/unpublishedScripts/marketplace/clap/animations/ClapAnimation.json @@ -0,0 +1,386 @@ +{ + "RightShoulder": { + "rotations": { + "x": 0.5578474402427673, + "y": -0.44214877486228943, + "z": 0.4979960322380066, + "w": 0.4952884614467621 + } + }, + "RightArm": { + "rotations": { + "x": 0.6266362071037292, + "y": -0.02882515825331211, + "z": -0.3233867585659027, + "w": 0.7084611654281616 + } + }, + "RightForeArm": { + "rotations": { + "x": 0.00004018074105260894, + "y": 0.06418406218290329, + "z": -0.5193823575973511, + "w": 0.8521281480789185 + } + }, + "RightHand": { + "rotations": { + "x": -0.21368850767612457, + "y": 0.02043931558728218, + "z": -0.02227853797376156, + "w": 0.9764339923858643 + } + }, + "RightHandPinky1": { + "rotations": { + "x": -0.003497191471979022, + "y": -0.01721140556037426, + "z": 0.19736060500144958, + "w": 0.980173647403717 + } + }, + "RightHandPinky2": { + "rotations": { + "x": 0.000005483317181642633, + "y": -0.00008023700502235442, + "z": -0.06867633014917374, + "w": 0.997639000415802 + } + }, + "RightHandPinky3": { + "rotations": { + "x": 7.18885644346301e-8, + "y": -2.7131383717460267e-7, + "z": 0.007620905060321093, + "w": 0.9999709725379944 + } + }, + "RightHandPinky4": { + "rotations": { + "x": -5.719068774112657e-9, + "y": 5.142213126418937e-7, + "z": -0.0075718737207353115, + "w": 0.999971330165863 + } + }, + "RightHandRing1": { + "rotations": { + "x": -0.0013452530838549137, + "y": -0.017564140260219574, + "z": 0.0761696845293045, + "w": 0.9969393610954285 + } + }, + "RightHandRing2": { + "rotations": { + "x": 0.0000010375651982030831, + "y": -0.00002211921673733741, + "z": -0.04599710553884506, + "w": 0.9989416003227234 + } + }, + "RightHandRing3": { + "rotations": { + "x": -2.7102969868408877e-10, + "y": 1.9202734335976857e-7, + "z": 0.0016911650309339166, + "w": 0.9999985694885254 + } + }, + "RightHandRing4": { + "rotations": { + "x": 2.3246689018208144e-9, + "y": -3.364403156069784e-8, + "z": 0.0004951066803187132, + "w": 0.9999998807907104 + } + }, + "RightHandMiddle1": { + "rotations": { + "x": 0.0012630893616005778, + "y": -0.017612185329198837, + "z": -0.07168931514024734, + "w": 0.9972707033157349 + } + }, + "RightHandMiddle2": { + "rotations": { + "x": 2.3561028683616314e-7, + "y": 0.000020313073036959395, + "z": 0.011195243336260319, + "w": 0.9999373555183411 + } + }, + "RightHandMiddle3": { + "rotations": { + "x": 6.375214667286855e-8, + "y": 4.750924631480302e-7, + "z": 0.00237679248675704, + "w": 0.9999971985816956 + } + }, + "RightHandMiddle4": { + "rotations": { + "x": 6.717256439969788e-8, + "y": 3.876683507542111e-8, + "z": -0.005236906465142965, + "w": 0.9999862909317017 + } + }, + "RightHandIndex1": { + "rotations": { + "x": 0.002164300065487623, + "y": -0.017346171662211418, + "z": -0.12158434838056564, + "w": 0.9924271702766418 + } + }, + "RightHandIndex2": { + "rotations": { + "x": -0.00000143755482895358, + "y": -0.0001614764187252149, + "z": 0.008941099047660828, + "w": 0.9999601244926453 + } + }, + "RightHandIndex3": { + "rotations": { + "x": 7.458467621290765e-8, + "y": 5.365728839024086e-7, + "z": 0.03373909369111061, + "w": 0.999430775642395 + } + }, + "RightHandIndex4": { + "rotations": { + "x": 4.511302997833866e-10, + "y": -2.259726272768603e-7, + "z": -0.009632252156734467, + "w": 0.9999536275863647 + } + }, + "RightHandThumb1": { + "rotations": { + "x": -0.0783928632736206, + "y": -0.3033908009529114, + "z": -0.26653754711151123, + "w": 0.9114638566970825 + } + }, + "RightHandThumb2": { + "rotations": { + "x": 0.0031029442325234413, + "y": 0.07382386922836304, + "z": 0.005253761075437069, + "w": 0.9972526431083679 + } + }, + "RightHandThumb3": { + "rotations": { + "x": 0.0040440745651721954, + "y": -0.04943573474884033, + "z": 0.007246015593409538, + "w": 0.9987428188323975 + } + }, + "RightHandThumb4": { + "rotations": { + "x": -0.00009280416270485148, + "y": -0.01658034883439541, + "z": -0.00014316302258521318, + "w": 0.999862551689148 + } + }, + "LeftShoulder": { + "rotations": { + "x": 0.5578474402427673, + "y": 0.44214877486228943, + "z": -0.4979960322380066, + "w": 0.4952884614467621 + } + }, + "LeftArm": { + "rotations": { + "x": 0.626636266708374, + "y": 0.028824958950281143, + "z": 0.3233867585659027, + "w": 0.7084611654281616 + } + }, + "LeftForeArm": { + "rotations": { + "x": 0.00004015670492663048, + "y": -0.06418408453464508, + "z": 0.5193824768066406, + "w": 0.8521282076835632 + } + }, + "LeftHand": { + "rotations": { + "x": -0.21368853747844696, + "y": -0.02043931558728218, + "z": 0.02227853797376156, + "w": 0.9764339923858643 + } + }, + "LeftHandPinky1": { + "rotations": { + "x": -0.003497188910841942, + "y": 0.01721140556037426, + "z": -0.19736060500144958, + "w": 0.980173647403717 + } + }, + "LeftHandPinky2": { + "rotations": { + "x": 0.000005479304491018411, + "y": 0.00008023556438274682, + "z": 0.06867631524801254, + "w": 0.997639000415802 + } + }, + "LeftHandPinky3": { + "rotations": { + "x": 7.229602516645173e-8, + "y": 2.709063835482084e-7, + "z": -0.007620909716933966, + "w": 0.9999709725379944 + } + }, + "LeftHandPinky4": { + "rotations": { + "x": -5.52988677071653e-9, + "y": -5.13755651354586e-7, + "z": 0.007571868598461151, + "w": 0.999971330165863 + } + }, + "LeftHandRing1": { + "rotations": { + "x": -0.001345252152532339, + "y": 0.017564138397574425, + "z": -0.0761696845293045, + "w": 0.9969393610954285 + } + }, + "LeftHandRing2": { + "rotations": { + "x": 0.000001034482806971937, + "y": 0.000022119218556326814, + "z": 0.04599710553884506, + "w": 0.9989416003227234 + } + }, + "LeftHandRing3": { + "rotations": { + "x": -2.8012464570181805e-10, + "y": -1.923183816643359e-7, + "z": -0.0016911652637645602, + "w": 0.9999985694885254 + } + }, + "LeftHandRing4": { + "rotations": { + "x": -1.1168596047994583e-9, + "y": 3.33529932561305e-8, + "z": -0.0004951058072037995, + "w": 0.9999998807907104 + } + }, + "LeftHandMiddle1": { + "rotations": { + "x": 0.0012630895944312215, + "y": 0.01761218160390854, + "z": 0.07168931514024734, + "w": 0.9972707033157349 + } + }, + "LeftHandMiddle2": { + "rotations": { + "x": 2.37378529277521e-7, + "y": -0.00002031277836067602, + "z": -0.011195233091711998, + "w": 0.9999373555183411 + } + }, + "LeftHandMiddle3": { + "rotations": { + "x": 7.146466884933034e-8, + "y": -4.7555812443533796e-7, + "z": -0.0023767934180796146, + "w": 0.9999971985816956 + } + }, + "LeftHandMiddle4": { + "rotations": { + "x": 6.549178976911207e-8, + "y": -3.865041975359418e-8, + "z": 0.005236904136836529, + "w": 0.9999862909317017 + } + }, + "LeftHandIndex1": { + "rotations": { + "x": 0.002164299599826336, + "y": 0.017346171662211418, + "z": 0.12158433347940445, + "w": 0.9924271702766418 + } + }, + "LeftHandIndex2": { + "rotations": { + "x": -0.000001437780269952782, + "y": 0.00016147761198226362, + "z": -0.008941099047660828, + "w": 0.9999601244926453 + } + }, + "LeftHandIndex3": { + "rotations": { + "x": 7.61426193207626e-8, + "y": -5.373883027459669e-7, + "z": -0.03373908996582031, + "w": 0.999430775642395 + } + }, + "LeftHandIndex4": { + "rotations": { + "x": -5.311697748311417e-10, + "y": 2.26380109324964e-7, + "z": 0.009632255882024765, + "w": 0.9999536275863647 + } + }, + "LeftHandThumb1": { + "rotations": { + "x": -0.07839284837245941, + "y": 0.3033908009529114, + "z": 0.26653754711151123, + "w": 0.9114638566970825 + } + }, + "LeftHandThumb2": { + "rotations": { + "x": 0.0031029372476041317, + "y": -0.07382386922836304, + "z": -0.005253763869404793, + "w": 0.9972526431083679 + } + }, + "LeftHandThumb3": { + "rotations": { + "x": 0.004044072702527046, + "y": 0.049435727298259735, + "z": -0.0072460174560546875, + "w": 0.9987428188323975 + } + }, + "LeftHandThumb4": { + "rotations": { + "x": -0.00009280881931772456, + "y": 0.016580356284976006, + "z": 0.00014314628788270056, + "w": 0.999862551689148 + } + } +} diff --git a/unpublishedScripts/marketplace/clap/animations/Clap_left.fbx b/unpublishedScripts/marketplace/clap/animations/Clap_left.fbx new file mode 100644 index 0000000000..a3830b9838 Binary files /dev/null and b/unpublishedScripts/marketplace/clap/animations/Clap_left.fbx differ diff --git a/unpublishedScripts/marketplace/clap/animations/Clap_right.fbx b/unpublishedScripts/marketplace/clap/animations/Clap_right.fbx new file mode 100644 index 0000000000..1877e963f9 Binary files /dev/null and b/unpublishedScripts/marketplace/clap/animations/Clap_right.fbx differ diff --git a/unpublishedScripts/marketplace/clap/clapApp.js b/unpublishedScripts/marketplace/clap/clapApp.js new file mode 100644 index 0000000000..a32937d6dd --- /dev/null +++ b/unpublishedScripts/marketplace/clap/clapApp.js @@ -0,0 +1,56 @@ +"use strict"; + +/* + clapApp.js + unpublishedScripts/marketplace/clap/clapApp.js + + Created by Matti 'Menithal' Lahtinen on 9/11/2017 + Copyright 2017 High Fidelity, Inc. + + Distributed under the Apache License, Version 2.0. + See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ + +// Entry Script for the clap app + +// Load up engine +var APP_NAME = "CLAP"; +var ClapEngine = Script.require(Script.resolvePath("scripts/ClapEngine.js?v6")); +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + +// Define Menu +var blackIcon = Script.resolvePath("icons/tablet-icons/clap-a.svg"); +var whiteIcon =Script.resolvePath("icons/tablet-icons/clap-i.svg"); +var isActive = true; + +var activeButton = tablet.addButton({ + icon: whiteIcon, + activeIcon: blackIcon, + text: APP_NAME, + isActive: isActive, + sortOrder: 11 +}); + +if (isActive) { + ClapEngine.connectEngine(); +} + +function onClick(enabled) { + + isActive = !isActive; + activeButton.editProperties({ + isActive: isActive + }); + if (isActive) { + ClapEngine.connectEngine(); + } else { + ClapEngine.disconnectEngine(); + } +} +activeButton.clicked.connect(onClick); + +Script.scriptEnding.connect(function () { + ClapEngine.disconnectEngine(); + activeButton.clicked.disconnect(onClick); + tablet.removeButton(activeButton); +}); diff --git a/unpublishedScripts/marketplace/clap/entities/ClapParticle.json b/unpublishedScripts/marketplace/clap/entities/ClapParticle.json new file mode 100644 index 0000000000..bf1b70665b --- /dev/null +++ b/unpublishedScripts/marketplace/clap/entities/ClapParticle.json @@ -0,0 +1,58 @@ +{ + "alpha": 0.01, + "alphaFinish": 0.0, + "alphaSpread": 1, + "alphaStart": 0.05, + "color": { + "blue": 200, + "green": 200, + "red": 200 + }, + "colorFinish": { + "blue": 200, + "green": 200, + "red": 200 + }, + "colorStart": { + "blue": 200, + "green": 200, + "red": 200 + }, + "created": "2017-09-09T16:01:38Z", + "dimensions": { + "x": 0.5, + "y": 0.5, + "z": 0.5 + }, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "emitDimensions": { + "x": 0.25, + "y": 0.25, + "z": 0.25 + }, + "emitOrientation": { + "w": 1, + "x": 0, + "y": 0, + "z": 0 + }, + "emitRate": 100, + "emitSpeed": 0.125, + "lifespan": 0.5, + "lifetime": 2, + "script": "(function(){return{preload:function(id){Script.setTimeout(function(){Entities.editEntity(id,{isEmitting:false});},200);}}})", + "maxParticles": 100, + "particleRadius": 0.05, + "polarFinish": 1.4311699867248535, + "polarStart": 1.3962633609771729, + "radiusFinish": 0.01, + "radiusSpread": 0.2, + "radiusStart": 0.05, + "speedSpread": 0, + "emitShouldTrail": true, + "type": "ParticleEffect" +} diff --git a/unpublishedScripts/marketplace/clap/icons/clap-black-icon.svg b/unpublishedScripts/marketplace/clap/icons/clap-black-icon.svg new file mode 100644 index 0000000000..10a8e3ea98 --- /dev/null +++ b/unpublishedScripts/marketplace/clap/icons/clap-black-icon.svg @@ -0,0 +1,104 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/unpublishedScripts/marketplace/clap/icons/clap-white-icon.svg b/unpublishedScripts/marketplace/clap/icons/clap-white-icon.svg new file mode 100644 index 0000000000..3e4ecb0b64 --- /dev/null +++ b/unpublishedScripts/marketplace/clap/icons/clap-white-icon.svg @@ -0,0 +1,104 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/unpublishedScripts/marketplace/clap/scripts/ClapDebugger.js b/unpublishedScripts/marketplace/clap/scripts/ClapDebugger.js new file mode 100644 index 0000000000..247664c157 --- /dev/null +++ b/unpublishedScripts/marketplace/clap/scripts/ClapDebugger.js @@ -0,0 +1,165 @@ +"use strict"; + +/* + clapApp.js + unpublishedScripts/marketplace/clap/scripts/clapDebugger.js + + Created by Matti 'Menithal' Lahtinen on 9/11/2017 + Copyright 2017 High Fidelity, Inc. + + Distributed under the Apache License, Version 2.0. + See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ + +var DEBUG_RIGHT_HAND; +var DEBUG_LEFT_HAND; +var DEBUG_CLAP_LEFT; +var DEBUG_CLAP_RIGHT; +var DEBUG_CLAP; +var DEBUG_CLAP_DIRECTION; + +// Debug Values: +var DEBUG_CORRECT = { + red: 0, + green: 255, + blue: 0 +}; +var DEBUG_WRONG = { + red: 255, + green: 0, + blue: 0 +}; + +var DEBUG_VOLUME = { + red: 255, + green: 255, + blue: 128 +}; + +module.exports = { + disableDebug: function () { + Overlays.deleteOverlay(DEBUG_RIGHT_HAND); + Overlays.deleteOverlay(DEBUG_LEFT_HAND); + Overlays.deleteOverlay(DEBUG_CLAP_LEFT); + Overlays.deleteOverlay(DEBUG_CLAP_RIGHT); + Overlays.deleteOverlay(DEBUG_CLAP); + Overlays.deleteOverlay(DEBUG_CLAP_DIRECTION); + }, + + debugPositions: function (leftAlignmentWorld, leftHandPositionOffset, leftHandDownWorld, rightAlignmentWorld, rightHandPositionOffset, rightHandDownWorld, tolerance) { + + Overlays.editOverlay(DEBUG_CLAP_LEFT, { + color: leftAlignmentWorld > tolerance ? DEBUG_CORRECT : DEBUG_WRONG, + position: leftHandPositionOffset + }); + + Overlays.editOverlay(DEBUG_CLAP_RIGHT, { + color: rightAlignmentWorld > tolerance ? DEBUG_CORRECT : DEBUG_WRONG, + position: rightHandPositionOffset + }); + + Overlays.editOverlay(DEBUG_LEFT_HAND, { + color: leftAlignmentWorld > tolerance ? DEBUG_CORRECT : DEBUG_WRONG, + start: leftHandPositionOffset, + end: Vec3.sum(leftHandPositionOffset, Vec3.multiply(leftHandDownWorld, 0.2)) + }); + + Overlays.editOverlay(DEBUG_RIGHT_HAND, { + color: rightAlignmentWorld > tolerance ? DEBUG_CORRECT : DEBUG_WRONG, + start: rightHandPositionOffset, + end: Vec3.sum(rightHandPositionOffset, Vec3.multiply(rightHandDownWorld, 0.2)) + }); + }, + + debugClapLine: function (start, end, visible) { + Overlays.editOverlay(DEBUG_CLAP_DIRECTION, { + start: start, + end: end, + visible: visible + }); + }, + + clapSphere: function (pos, vol) { + Overlays.editOverlay(DEBUG_CLAP, { + position: pos, + scale: { + x: vol, + y: vol, + z: vol + } + }); + }, + + enableDebug: function () { + DEBUG_RIGHT_HAND = Overlays.addOverlay("line3d", { + color: DEBUG_WRONG, + start: MyAvatar.position, + end: Vec3.sum(MyAvatar.position, { + x: 0, + y: 1, + z: 0 + }), + dimensions: { + x: 2, + y: 2, + z: 2 + } + }); + + DEBUG_LEFT_HAND = Overlays.addOverlay("line3d", { + color: DEBUG_WRONG, + start: MyAvatar.position, + end: Vec3.sum(MyAvatar.position, { + x: 0, + y: 1, + z: 0 + }), + dimensions: { + x: 2, + y: 2, + z: 2 + } + }); + + DEBUG_CLAP_LEFT = Overlays.addOverlay("sphere", { + position: MyAvatar.position, + color: DEBUG_WRONG, + scale: { + x: 0.05, + y: 0.05, + z: 0.05 + } + }); + + DEBUG_CLAP_RIGHT = Overlays.addOverlay("sphere", { + position: MyAvatar.position, + color: DEBUG_WRONG, + scale: { + x: 0.05, + y: 0.05, + z: 0.05 + } + }); + + DEBUG_CLAP = Overlays.addOverlay("sphere", { + position: MyAvatar.position, + color: DEBUG_VOLUME, + scale: { + x: 0.05, + y: 0.05, + z: 0.05 + } + }); + + DEBUG_CLAP_DIRECTION = Overlays.addOverlay("line3d", { + color: DEBUG_VOLUME, + start: MyAvatar.position, + end: MyAvatar.position, + dimensions: { + x: 2, + y: 2, + z: 2 + } + }); + } +}; diff --git a/unpublishedScripts/marketplace/clap/scripts/ClapEngine.js b/unpublishedScripts/marketplace/clap/scripts/ClapEngine.js new file mode 100644 index 0000000000..f36aa9716b --- /dev/null +++ b/unpublishedScripts/marketplace/clap/scripts/ClapEngine.js @@ -0,0 +1,318 @@ +"use strict"; + +/* + clapEngine.js + unpublishedScripts/marketplace/clap/clapApp.js + + Created by Matti 'Menithal' Lahtinen on 9/11/2017 + Copyright 2017 High Fidelity, Inc. + + Distributed under the Apache License, Version 2.0. + See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + + + Main Heart of the clap script> Does both keyboard binding and tracking of the gear.. + +*/ +var DEG_TO_RAD = Math.PI / 180; +// If angle is closer to 0 from 25 degrees, then "clap" can happen; +var COS_OF_TOLERANCE = Math.cos(25 * DEG_TO_RAD); + +var CONTROL_MAP_PACKAGE = "com.highfidelity.avatar.clap.active"; + +var CLAP_MENU = "Clap"; +var ENABLE_PARTICLE_MENU = "Enable Clap Particles"; +var ENABLE_DEBUG_MENU = "Enable Clap Debug"; + +var sounds = [ + "clap1.wav", + "clap2.wav", + "clap3.wav", + "clap4.wav", + "clap5.wav", + "clap6.wav" +]; + + +var ClapParticle = Script.require(Script.resolvePath("../entities/ClapParticle.json?V2")); +var ClapAnimation = Script.require(Script.resolvePath("../animations/ClapAnimation.json?V2")); +var ClapDebugger = Script.require(Script.resolvePath("ClapDebugger.js?V2")); + +var settingDebug = false; +var settingParticlesOn = true; + +function setJointRotation(map) { + Object.keys(map).forEach(function (key, index) { + MyAvatar.setJointRotation(MyAvatar.getJointIndex(key), map[key].rotations); + }); +} +// Load Sounds to Cache +var cache = []; +for (var index in sounds) { + cache.push(SoundCache.getSound(Script.resolvePath("../sounds/" + sounds[index]))); +} + + +var previousIndex; +var clapOn = false; +var animClap = false; +var animThrottle; + +function clap(volume, position, rotation) { + var index; + // Make sure one does not generate consequtive sounds + do { + index = Math.floor(Math.random() * cache.length); + } while (index === previousIndex); + + previousIndex = index; + + Audio.playSound(cache[index], { + position: position, + volume: volume / 4 + Math.random() * (volume / 3) + }); + + if (settingParticlesOn) { + ClapParticle.orientation = Quat.multiply(MyAvatar.orientation, rotation); + ClapParticle.position = position; + ClapParticle.emitSpeed = volume > 1 ? 1 : volume; + Entities.addEntity(ClapParticle, true); + } + + + if (settingDebug) { + ClapDebugger.clapSphere(position, volume); + } + +} +// Helper Functions +function getHandFingerAnim(side) { + return Script.resolvePath("../animations/Clap_" + side + '.fbx'); +} + +// Disable all role animations related to fingers for side +function overrideFingerRoleAnimation(side) { + var anim = getHandFingerAnim(side); + MyAvatar.overrideRoleAnimation(side + "HandGraspOpen", anim, 30, true, 0, 0); + MyAvatar.overrideRoleAnimation(side + "HandGraspClosed", anim, 30, true, 0, 0); + if (HMD.active) { + MyAvatar.overrideRoleAnimation(side + "HandPointIntro", anim, 30, true, 0, 0); + MyAvatar.overrideRoleAnimation(side + "HandPointHold", anim, 30, true, 0, 0); + MyAvatar.overrideRoleAnimation(side + "HandPointOutro", anim, 30, true, 0, 0); + + MyAvatar.overrideRoleAnimation(side + "IndexPointOpen", anim, 30, true, 0, 0); + MyAvatar.overrideRoleAnimation(side + "IndexPointClosed", anim, 30, true, 0, 0); + MyAvatar.overrideRoleAnimation(side + "IndexPointAndThumbRaiseOpen", anim, 30, true, 0, 0); + MyAvatar.overrideRoleAnimation(side + "IndexPointAndThumbRaiseClosed", anim, 30, true, 0, 0); + + MyAvatar.overrideRoleAnimation(side + "ThumbRaiseOpen", anim, 30, true, 0, 0); + MyAvatar.overrideRoleAnimation(side + "ThumbRaiseClosed", anim, 30, true, 0, 0); + } +} +// Re-enable all role animations for fingers +function restoreFingerRoleAnimation(side) { + MyAvatar.restoreRoleAnimation(side + "HandGraspOpen"); + MyAvatar.restoreRoleAnimation(side + "HandGraspClosed"); + if (HMD.active) { + MyAvatar.restoreRoleAnimation(side + "HandPointIntro"); + MyAvatar.restoreRoleAnimation(side + "HandPointHold"); + MyAvatar.restoreRoleAnimation(side + "HandPointOutro"); + MyAvatar.restoreRoleAnimation(side + "IndexPointOpen"); + + MyAvatar.restoreRoleAnimation(side + "IndexPointClosed"); + MyAvatar.restoreRoleAnimation(side + "IndexPointAndThumbRaiseOpen"); + MyAvatar.restoreRoleAnimation(side + "IndexPointAndThumbRaiseClosed"); + MyAvatar.restoreRoleAnimation(side + "ThumbRaiseOpen"); + MyAvatar.restoreRoleAnimation(side + "ThumbRaiseClosed"); + } +} + + +function menuListener(menuItem) { + if (menuItem === ENABLE_PARTICLE_MENU) { + settingParticlesOn = Menu.isOptionChecked(ENABLE_PARTICLE_MENU); + } else if (menuItem === ENABLE_DEBUG_MENU) { + var debugOn = Menu.isOptionChecked(ENABLE_DEBUG_MENU); + + if (debugOn) { + settingDebug = true; + ClapDebugger.enableDebug(); + } else { + settingDebug = false; + ClapDebugger.disableDebug(); + } + } +} + +function update(dt) { + + // NOTICE: Someof this stuff is unnessary for the actual: But they are done for Debug Purposes! + // Forexample, the controller doesnt really need to know where it is in the world, only its relation to the other controller! + + var leftHand = Controller.getPoseValue(Controller.Standard.LeftHand); + var rightHand = Controller.getPoseValue(Controller.Standard.RightHand); + + // Get Offset position for palms, not the controllers that are at the wrists (7.5 cm up) + + var leftWorldRotation = Quat.multiply(MyAvatar.orientation, leftHand.rotation); + var rightWorldRotation = Quat.multiply(MyAvatar.orientation, rightHand.rotation); + + var leftWorldUpNormal = Quat.getUp(leftWorldRotation); + var rightWorldUpNormal = Quat.getUp(rightWorldRotation); + + var leftHandDownWorld = Vec3.multiply(-1, Quat.getForward(leftWorldRotation)); + var rightHandDownWorld = Vec3.multiply(-1, Quat.getForward(rightWorldRotation)); + + // + var leftHandWorldPosition = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, leftHand.translation)); + var rightHandWorldPosition = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, rightHand.translation)); + + var rightHandPositionOffset = Vec3.sum(rightHandWorldPosition, Vec3.multiply(rightWorldUpNormal, 0.035)); + var leftHandPositionOffset = Vec3.sum(leftHandWorldPosition, Vec3.multiply(leftWorldUpNormal, 0.035)); + + var leftToRightWorld = Vec3.subtract(leftHandPositionOffset, rightHandPositionOffset); + var rightToLeftWorld = Vec3.subtract(rightHandPositionOffset, leftHandPositionOffset); + + var leftAlignmentWorld = -1 * Vec3.dot(Vec3.normalize(leftToRightWorld), leftHandDownWorld); + var rightAlignmentWorld = -1 * Vec3.dot(Vec3.normalize(rightToLeftWorld), rightHandDownWorld); + + var distance = Vec3.distance(rightHandPositionOffset, leftHandPositionOffset); + + var matchTolerance = leftAlignmentWorld > COS_OF_TOLERANCE && rightAlignmentWorld > COS_OF_TOLERANCE; + + if (settingDebug) { + ClapDebugger.debugPositions(leftAlignmentWorld, + leftHandPositionOffset, leftHandDownWorld, + rightAlignmentWorld, rightHandPositionOffset, + rightHandDownWorld, COS_OF_TOLERANCE); + } + // Using subtract, because these will be heading to opposite directions + var angularVelocity = Vec3.length(Vec3.subtract(leftHand.angularVelocity, rightHand.angularVelocity)); + var velocity = Vec3.length(Vec3.subtract(leftHand.velocity, rightHand.velocity)); + + if (matchTolerance && distance < 0.3 && !animClap) { + if (settingDebug) { + ClapDebugger.debugClapLine(leftHandPositionOffset, rightHandPositionOffset, true); + } + if (!animThrottle) { + overrideFingerRoleAnimation("left"); + overrideFingerRoleAnimation("right"); + animClap = true; + } else { + Script.clearTimeout(animThrottle); + animThrottle = false; + } + } else if (animClap && distance > 0.3) { + if (settingDebug) { + ClapDebugger.debugClapLine(leftHandPositionOffset, rightHandPositionOffset, false); + } + animThrottle = Script.setTimeout(function () { + restoreFingerRoleAnimation("left"); + restoreFingerRoleAnimation("right"); + animClap = false; + }, 500); + } + + if (distance < 0.22 && matchTolerance && !clapOn) { + clapOn = true; + + var midClap = Vec3.mix(rightHandPositionOffset, leftHandPositionOffset, 0.5); + var volume = velocity / 2 + angularVelocity / 5; + + clap(volume, midClap, Quat.lookAtSimple(rightHandPositionOffset, leftHandPositionOffset)); + } else if (distance > 0.22 && !matchTolerance) { + clapOn = false; + } +} + + +module.exports = { + connectEngine: function () { + if (!Menu.menuExists(CLAP_MENU)) { + Menu.addMenu(CLAP_MENU); + } + + if (!Menu.menuItemExists(CLAP_MENU, ENABLE_PARTICLE_MENU)) { + Menu.addMenuItem({ + menuName: CLAP_MENU, + menuItemName: ENABLE_PARTICLE_MENU, + isCheckable: true, + isChecked: settingParticlesOn + }); + } + if (!Menu.menuItemExists(CLAP_MENU, ENABLE_DEBUG_MENU)) { + Menu.addMenuItem({ + menuName: CLAP_MENU, + menuItemName: ENABLE_DEBUG_MENU, + isCheckable: true, + isChecked: settingDebug + }); + } + + + Menu.menuItemEvent.connect(menuListener); + + var controls = Controller.newMapping(CONTROL_MAP_PACKAGE); + var Keyboard = Controller.Hardware.Keyboard; + + controls.from(Keyboard.K).to(function (down) { + if (down) { + + setJointRotation(ClapAnimation); + Script.setTimeout(function () { + // As soon as an animation bug is fixed, this will kick and get fixed.s. + overrideFingerRoleAnimation("left"); + overrideFingerRoleAnimation("right"); + + var lh = MyAvatar.getJointPosition("LeftHand"); + var rh = MyAvatar.getJointPosition("RightHand"); + var midClap = Vec3.mix(rh, lh, 0.5); + var volume = 0.5 + Math.random() * 0.5; + var position = midClap; + + clap(volume, position, Quat.fromVec3Degrees(0, 0, 0)); + }, 50); // delay is present to allow for frames to catch up. + } else { + + restoreFingerRoleAnimation("left"); + + restoreFingerRoleAnimation("right"); + MyAvatar.clearJointsData(); + } + }); + Controller.enableMapping(CONTROL_MAP_PACKAGE); + + // settingDebug STUFF + if (settingDebug) { + ClapDebugger.enableDebug(); + } + + + Script.update.connect(update); + + Script.scriptEnding.connect(this.disconnectEngine); + }, + disconnectEngine: function () { + if (settingDebug) { + ClapDebugger.disableDebug(); + } + if (Menu.menuItemExists(CLAP_MENU, ENABLE_PARTICLE_MENU)) { + Menu.removeMenuItem(CLAP_MENU, ENABLE_PARTICLE_MENU); + } + if (Menu.menuItemExists(CLAP_MENU, ENABLE_DEBUG_MENU)) { + Menu.removeMenuItem(CLAP_MENU, ENABLE_DEBUG_MENU); + } + + if (Menu.menuExists(CLAP_MENU)) { + Menu.removeMenu(CLAP_MENU); + } + restoreFingerRoleAnimation('left'); + restoreFingerRoleAnimation('right'); + Controller.disableMapping(CONTROL_MAP_PACKAGE); + try { + Script.update.disconnect(update); + } catch (e) { + print("Script.update connection did not exist on disconnection. Skipping") + } + } +}; diff --git a/unpublishedScripts/marketplace/clap/sounds/clap1.wav b/unpublishedScripts/marketplace/clap/sounds/clap1.wav new file mode 100644 index 0000000000..679cb7e732 Binary files /dev/null and b/unpublishedScripts/marketplace/clap/sounds/clap1.wav differ diff --git a/unpublishedScripts/marketplace/clap/sounds/clap2.wav b/unpublishedScripts/marketplace/clap/sounds/clap2.wav new file mode 100644 index 0000000000..b43c745e52 Binary files /dev/null and b/unpublishedScripts/marketplace/clap/sounds/clap2.wav differ diff --git a/unpublishedScripts/marketplace/clap/sounds/clap3.wav b/unpublishedScripts/marketplace/clap/sounds/clap3.wav new file mode 100644 index 0000000000..47a4a8d48f Binary files /dev/null and b/unpublishedScripts/marketplace/clap/sounds/clap3.wav differ diff --git a/unpublishedScripts/marketplace/clap/sounds/clap4.wav b/unpublishedScripts/marketplace/clap/sounds/clap4.wav new file mode 100644 index 0000000000..4e8dfca1a0 Binary files /dev/null and b/unpublishedScripts/marketplace/clap/sounds/clap4.wav differ diff --git a/unpublishedScripts/marketplace/clap/sounds/clap5.wav b/unpublishedScripts/marketplace/clap/sounds/clap5.wav new file mode 100644 index 0000000000..1f38864db4 Binary files /dev/null and b/unpublishedScripts/marketplace/clap/sounds/clap5.wav differ diff --git a/unpublishedScripts/marketplace/clap/sounds/clap6.wav b/unpublishedScripts/marketplace/clap/sounds/clap6.wav new file mode 100644 index 0000000000..4591f79d9d Binary files /dev/null and b/unpublishedScripts/marketplace/clap/sounds/clap6.wav differ