From 47471e837ff72a9c30812aa972d848bc85afea15 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 12 Oct 2015 16:31:36 -0700 Subject: [PATCH 01/16] reset targets once they have stopped moving --- examples/toys/ping_pong_gun/createTargets.js | 15 ++++++++++++--- unpublishedScripts/hiddenEntityReset.js | 19 ++++++++++--------- unpublishedScripts/masterReset.js | 18 +++++++++--------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/examples/toys/ping_pong_gun/createTargets.js b/examples/toys/ping_pong_gun/createTargets.js index 22329f90f0..013150b241 100644 --- a/examples/toys/ping_pong_gun/createTargets.js +++ b/examples/toys/ping_pong_gun/createTargets.js @@ -16,8 +16,9 @@ var scriptURL = Script.resolvePath('wallTarget.js'); var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx'; var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target_collision_hull.obj'; +var MINIMUM_MOVE_LENGTH = 0.05; +var RESET_DISTANCE = 0.5; -var RESET_DISTANCE = 1; var TARGET_USER_DATA_KEY = 'hifi-ping_pong_target'; var NUMBER_OF_TARGETS = 6; var TARGETS_PER_ROW = 3; @@ -60,6 +61,8 @@ var targets = []; var originalPositions = []; +var lastPositions = []; + function addTargets() { var i; var row = -1; @@ -77,6 +80,7 @@ function addTargets() { position.y = startPosition.y - (row * VERTICAL_SPACING); originalPositions.push(position); + lastPositions.push(position); var targetProperties = { name: 'Target', @@ -103,7 +107,11 @@ function testTargetDistanceFromStart() { var distance = Vec3.subtract(originalPosition, currentPosition); var length = Vec3.length(distance); - if (length > RESET_DISTANCE) { + var moving = Vec3.length(Vec3.subtract(currentPosition, lastPositions[index])); + + lastPositions[index] = currentPosition; + + if (length > RESET_DISTANCE && moving RESET_DISTANCE) { + var moving = Vec3.length(Vec3.subtract(currentPosition, lastPositions[index])); + + lastPositions[index] = currentPosition; + + if (length > RESET_DISTANCE && moving < MINIMUM_MOVE_LENGTH) { Entities.deleteEntity(target); @@ -482,15 +488,10 @@ compoundShapeURL: COLLISION_HULL_URL, position: originalPositions[index], rotation: rotation, - script: targetsScriptURL, - userData: JSON.stringify({ - resetMe: { - resetMe: true - } - }) + script: scriptURL }; - var target = Entities.addEntity(targetProperties); - targets[index] = target; + + targets[index] = Entities.addEntity(targetProperties); } }); diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index d9199a124d..e4db5fbf55 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -393,6 +393,7 @@ MasterReset = function() { var targets = []; var originalPositions = []; + var lastPositions = []; function addTargets() { var i; @@ -441,7 +442,11 @@ MasterReset = function() { var distance = Vec3.subtract(originalPosition, currentPosition); var length = Vec3.length(distance); - if (length > RESET_DISTANCE) { + var moving = Vec3.length(Vec3.subtract(currentPosition, lastPositions[index])); + + lastPositions[index] = currentPosition; + + if (length > RESET_DISTANCE && moving < MINIMUM_MOVE_LENGTH) { Entities.deleteEntity(target); @@ -455,15 +460,10 @@ MasterReset = function() { compoundShapeURL: COLLISION_HULL_URL, position: originalPositions[index], rotation: rotation, - script: targetsScriptURL, - userData: JSON.stringify({ - resetMe: { - resetMe: true - } - }) + script: scriptURL }; - var target = Entities.addEntity(targetProperties); - targets[index] = target; + + targets[index] = Entities.addEntity(targetProperties); } }); From bc4200d8d7b42eac3a5ebb422f394d66077093ea Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 12 Oct 2015 16:35:06 -0700 Subject: [PATCH 02/16] push last positions to array --- unpublishedScripts/hiddenEntityReset.js | 5 +++-- unpublishedScripts/masterReset.js | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 5eff989701..bc9ecbcf22 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -438,8 +438,9 @@ var position = Vec3.sum(startPosition, multiplier); position.y = startPosition.y - (row * VERTICAL_SPACING); - originalPositions.push(position); - + originalPositions.push(position); + lastPositions.push(position); + var targetProperties = { name: 'Target', type: 'Model', diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index e4db5fbf55..1644688e5d 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -411,7 +411,8 @@ MasterReset = function() { position.y = startPosition.y - (row * VERTICAL_SPACING); originalPositions.push(position); - + lastPositions.push(position); + var targetProperties = { name: 'Target', type: 'Model', @@ -429,8 +430,10 @@ MasterReset = function() { } }) }; + var target = Entities.addEntity(targetProperties); targets.push(target); + } } From 02620c4b0dced96e067ffcedc39ebe51b0fe7f3f Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 12 Oct 2015 16:59:42 -0700 Subject: [PATCH 03/16] make targets ungrabbable --- examples/toys/ping_pong_gun/createTargets.js | 9 +- unpublishedScripts/hiddenEntityReset.js | 11 +- unpublishedScripts/masterReset.js | 2435 +++++++++--------- 3 files changed, 1233 insertions(+), 1222 deletions(-) diff --git a/examples/toys/ping_pong_gun/createTargets.js b/examples/toys/ping_pong_gun/createTargets.js index 013150b241..fb286b1928 100644 --- a/examples/toys/ping_pong_gun/createTargets.js +++ b/examples/toys/ping_pong_gun/createTargets.js @@ -111,7 +111,7 @@ function testTargetDistanceFromStart() { lastPositions[index] = currentPosition; - if (length > RESET_DISTANCE && moving RESET_DISTANCE && moving < MINIMUM_MOVE_LENGTH) { Entities.deleteEntity(target); @@ -125,7 +125,12 @@ function testTargetDistanceFromStart() { compoundShapeURL: COLLISION_HULL_URL, position: originalPositions[index], rotation: rotation, - script: scriptURL + script: scriptURL, + userData: JSON.stringify({ + grabbableKey: { + grabbable: false + } + }) }; targets[index] = Entities.addEntity(targetProperties); diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index bc9ecbcf22..f959923ad3 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -413,6 +413,9 @@ userData: JSON.stringify({ resetMe: { resetMe: true + }, + grabbableKey: { + grabbable: false } }) }); @@ -438,9 +441,9 @@ var position = Vec3.sum(startPosition, multiplier); position.y = startPosition.y - (row * VERTICAL_SPACING); - originalPositions.push(position); - lastPositions.push(position); - + originalPositions.push(position); + lastPositions.push(position); + var targetProperties = { name: 'Target', type: 'Model', @@ -455,7 +458,7 @@ userData: JSON.stringify({ resetMe: { resetMe: true - } + }, }) }; var target = Entities.addEntity(targetProperties); diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 1644688e5d..fdedac3ec3 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -26,1256 +26,1259 @@ var targetsScriptURL = Script.resolvePath('../examples/toys/ping_pong_gun/wallTa MasterReset = function() { - var resetKey = "resetMe"; - var GRABBABLE_DATA_KEY = "grabbableKey"; + var resetKey = "resetMe"; + var GRABBABLE_DATA_KEY = "grabbableKey"; - var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; - var shouldDeleteOnEndScript = false; + var shouldDeleteOnEndScript = false; - //Before creating anything, first search a radius and delete all the things that should be deleted - deleteAllToys(); - createAllToys(); + //Before creating anything, first search a radius and delete all the things that should be deleted + deleteAllToys(); + createAllToys(); - function createAllToys() { - createBlocks({ - x: 548.3, - y: 495.55, - z: 504.4 - }); - - createBasketBall({ - x: 547.73, - y: 495.5, - z: 505.47 - }); - - createDoll({ - x: 546.67, - y: 495.41, - z: 505.09 - }); - - createWand({ - x: 546.71, - y: 495.55, - z: 506.15 - }); - - createDice(); - - createFlashlight({ - x: 545.72, - y: 495.41, - z: 505.78 - }); - - - - createCombinedArmChair({ - x: 549.29, - y: 494.9, - z: 508.22 - }); - - createPottedPlant({ - x: 554.26, - y: 495.2, - z: 504.53 - }); - - createPingPongBallGun(); - - createBasketballHoop(); - createBasketballRack(); - - createGates(); - - createFire(); - // Handles toggling of all sconce lights - createLights(); - - - - createCat({ - x: 551.09, - y: 494.98, - z: 503.49 - }); - - - createSprayCan({ - x: 549.7, - y: 495.6, - z: 503.91 - }); - - createTargets(); - - } - - function deleteAllToys() { - var entities = Entities.findEntities(MyAvatar.position, 100); - - entities.forEach(function(entity) { - //params: customKey, id, defaultValue - var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe; - if (shouldReset === true) { - Entities.deleteEntity(entity); - } - }); - } - - function createFire() { - - - var myOrientation = Quat.fromPitchYawRollDegrees(-90, 0, 0.0); - - var animationSettings = JSON.stringify({ - fps: 30, - running: true, - loop: true, - firstFrame: 1, - lastFrame: 10000 - }); - - - var fire = Entities.addEntity({ - type: "ParticleEffect", - name: "fire", - animationSettings: animationSettings, - textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - position: { - x: 551.45, - y: 494.82, - z: 502.05 - }, - emitRate: 100, - colorStart: { - red: 70, - green: 70, - blue: 137 - }, - color: { - red: 200, - green: 99, - blue: 42 - }, - colorFinish: { - red: 255, - green: 99, - blue: 32 - }, - radiusSpread: 0.01, - radiusStart: 0.02, - radiusEnd: 0.001, - particleRadius: 0.05, - radiusFinish: 0.0, - emitOrientation: myOrientation, - emitSpeed: 0.3, - speedSpread: 0.1, - alphaStart: 0.05, - alpha: 0.1, - alphaFinish: 0.05, - emitDimensions: { - x: 1, - y: 1, - z: 0.1 - }, - polarFinish: 0.1, - emitAcceleration: { - x: 0.0, - y: 0.0, - z: 0.0 - }, - accelerationSpread: { - x: 0.1, - y: 0.01, - z: 0.1 - }, - lifespan: 1, - userData: JSON.stringify({ - resetMe: { - resetMe: true - } - }) - }); - } - - function createBasketballRack() { - var NUMBER_OF_BALLS = 4; - var DIAMETER = 0.30; - var RESET_DISTANCE = 1; - var MINIMUM_MOVE_LENGTH = 0.05; - var basketballURL = HIFI_PUBLIC_BUCKET + "models/content/basketball2.fbx"; - var basketballCollisionSoundURL = HIFI_PUBLIC_BUCKET + "sounds/basketball/basketball.wav"; - var rackURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/basketball_rack.fbx"; - var rackCollisionHullURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/rack_collision_hull.obj"; - - var rackRotation = Quat.fromPitchYawRollDegrees(0, -90, 0); - - var rackStartPosition = { - x: 542.86, - y: 494.84, - z: 475.06 - }; - var rack = Entities.addEntity({ - name: 'Basketball Rack', - type: "Model", - modelURL: rackURL, - position: rackStartPosition, - rotation: rackRotation, - shapeType: 'compound', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - linearDamping: 1, - dimensions: { - x: 0.4, - y: 1.37, - z: 1.73 - }, - collisionsWillMove: true, - ignoreForCollisions: false, - compoundShapeURL: rackCollisionHullURL, - userData: JSON.stringify({ - resetMe: { - resetMe: true - }, - grabbableKey: { - grabbable: false - } - - }) - }); - - var collidingBalls = []; - var originalBallPositions = []; - - function createCollidingBalls() { - var position = rackStartPosition; - - var i; - for (i = 0; i < NUMBER_OF_BALLS; i++) { - var ballPosition = { - x: position.x, - y: position.y + DIAMETER * 2, - z: position.z + (DIAMETER) - (DIAMETER * i) - }; - - var collidingBall = Entities.addEntity({ - type: "Model", - name: 'Colliding Basketball', - shapeType: 'Sphere', - position: { - x: position.x + (DIAMETER * 2) - (DIAMETER * i), - y: position.y + DIAMETER * 2, - z: position.z - }, - dimensions: { - x: DIAMETER, - y: DIAMETER, - z: DIAMETER - }, - restitution: 1.0, - linearDamping: 0.00001, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - collisionsWillMove: true, - ignoreForCollisions: false, - modelURL: basketballURL, - userData: JSON.stringify({ - resetMe: { - resetMe: true - } - }) + function createAllToys() { + createBlocks({ + x: 548.3, + y: 495.55, + z: 504.4 }); - collidingBalls.push(collidingBall); - originalBallPositions.push(position); - } + createBasketBall({ + x: 547.73, + y: 495.5, + z: 505.47 + }); + + createDoll({ + x: 546.67, + y: 495.41, + z: 505.09 + }); + + createWand({ + x: 546.71, + y: 495.55, + z: 506.15 + }); + + createDice(); + + createFlashlight({ + x: 545.72, + y: 495.41, + z: 505.78 + }); + + + + createCombinedArmChair({ + x: 549.29, + y: 494.9, + z: 508.22 + }); + + createPottedPlant({ + x: 554.26, + y: 495.2, + z: 504.53 + }); + + createPingPongBallGun(); + + createBasketballHoop(); + createBasketballRack(); + + createGates(); + + createFire(); + // Handles toggling of all sconce lights + createLights(); + + + + createCat({ + x: 551.09, + y: 494.98, + z: 503.49 + }); + + + createSprayCan({ + x: 549.7, + y: 495.6, + z: 503.91 + }); + + createTargets(); + } - function testBallDistanceFromStart() { - var resetCount = 0; + function deleteAllToys() { + var entities = Entities.findEntities(MyAvatar.position, 100); - collidingBalls.forEach(function(ball, index) { - var currentPosition = Entities.getEntityProperties(ball, "position").position; - var originalPosition = originalBallPositions[index]; - var distance = Vec3.subtract(originalPosition, currentPosition); - var length = Vec3.length(distance); + entities.forEach(function(entity) { + //params: customKey, id, defaultValue + var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe; + if (shouldReset === true) { + Entities.deleteEntity(entity); + } + }); + } - if (length > RESET_DISTANCE) { - Script.setTimeout(function() { - var newPosition = Entities.getEntityProperties(ball, "position").position; - var moving = Vec3.length(Vec3.subtract(currentPosition, newPosition)); - if (moving < MINIMUM_MOVE_LENGTH) { - resetCount++; - if (resetCount === NUMBER_OF_BALLS) { + function createFire() { + + + var myOrientation = Quat.fromPitchYawRollDegrees(-90, 0, 0.0); + + var animationSettings = JSON.stringify({ + fps: 30, + running: true, + loop: true, + firstFrame: 1, + lastFrame: 10000 + }); + + + var fire = Entities.addEntity({ + type: "ParticleEffect", + name: "fire", + animationSettings: animationSettings, + textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + position: { + x: 551.45, + y: 494.82, + z: 502.05 + }, + emitRate: 100, + colorStart: { + red: 70, + green: 70, + blue: 137 + }, + color: { + red: 200, + green: 99, + blue: 42 + }, + colorFinish: { + red: 255, + green: 99, + blue: 32 + }, + radiusSpread: 0.01, + radiusStart: 0.02, + radiusEnd: 0.001, + particleRadius: 0.05, + radiusFinish: 0.0, + emitOrientation: myOrientation, + emitSpeed: 0.3, + speedSpread: 0.1, + alphaStart: 0.05, + alpha: 0.1, + alphaFinish: 0.05, + emitDimensions: { + x: 1, + y: 1, + z: 0.1 + }, + polarFinish: 0.1, + emitAcceleration: { + x: 0.0, + y: 0.0, + z: 0.0 + }, + accelerationSpread: { + x: 0.1, + y: 0.01, + z: 0.1 + }, + lifespan: 1, + userData: JSON.stringify({ + resetMe: { + resetMe: true + } + }) + }); + } + + function createBasketballRack() { + var NUMBER_OF_BALLS = 4; + var DIAMETER = 0.30; + var RESET_DISTANCE = 1; + var MINIMUM_MOVE_LENGTH = 0.05; + var basketballURL = HIFI_PUBLIC_BUCKET + "models/content/basketball2.fbx"; + var basketballCollisionSoundURL = HIFI_PUBLIC_BUCKET + "sounds/basketball/basketball.wav"; + var rackURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/basketball_rack.fbx"; + var rackCollisionHullURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/rack_collision_hull.obj"; + + var rackRotation = Quat.fromPitchYawRollDegrees(0, -90, 0); + + var rackStartPosition = { + x: 542.86, + y: 494.84, + z: 475.06 + }; + var rack = Entities.addEntity({ + name: 'Basketball Rack', + type: "Model", + modelURL: rackURL, + position: rackStartPosition, + rotation: rackRotation, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + linearDamping: 1, + dimensions: { + x: 0.4, + y: 1.37, + z: 1.73 + }, + collisionsWillMove: true, + ignoreForCollisions: false, + compoundShapeURL: rackCollisionHullURL, + userData: JSON.stringify({ + resetMe: { + resetMe: true + }, + grabbableKey: { + grabbable: false + } + + }) + }); + + var collidingBalls = []; + var originalBallPositions = []; + + function createCollidingBalls() { + var position = rackStartPosition; + + var i; + for (i = 0; i < NUMBER_OF_BALLS; i++) { + var ballPosition = { + x: position.x, + y: position.y + DIAMETER * 2, + z: position.z + (DIAMETER) - (DIAMETER * i) + }; + + var collidingBall = Entities.addEntity({ + type: "Model", + name: 'Colliding Basketball', + shapeType: 'Sphere', + position: { + x: position.x + (DIAMETER * 2) - (DIAMETER * i), + y: position.y + DIAMETER * 2, + z: position.z + }, + dimensions: { + x: DIAMETER, + y: DIAMETER, + z: DIAMETER + }, + restitution: 1.0, + linearDamping: 0.00001, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + collisionsWillMove: true, + ignoreForCollisions: false, + modelURL: basketballURL, + userData: JSON.stringify({ + resetMe: { + resetMe: true + } + }) + }); + + collidingBalls.push(collidingBall); + originalBallPositions.push(position); + } + } + + function testBallDistanceFromStart() { + var resetCount = 0; + + collidingBalls.forEach(function(ball, index) { + var currentPosition = Entities.getEntityProperties(ball, "position").position; + var originalPosition = originalBallPositions[index]; + var distance = Vec3.subtract(originalPosition, currentPosition); + var length = Vec3.length(distance); + + if (length > RESET_DISTANCE) { + Script.setTimeout(function() { + var newPosition = Entities.getEntityProperties(ball, "position").position; + var moving = Vec3.length(Vec3.subtract(currentPosition, newPosition)); + if (moving < MINIMUM_MOVE_LENGTH) { + resetCount++; + if (resetCount === NUMBER_OF_BALLS) { + deleteCollidingBalls(); + createCollidingBalls(); + } + } + }, 200); + } + }); + } + + function deleteEntity(entityID) { + if (entityID === rack) { deleteCollidingBalls(); - createCollidingBalls(); - } + Script.clearInterval(distanceCheckInterval); + Entities.deletingEntity.disconnect(deleteEntity); } - }, 200); - } - }); - } - - function deleteEntity(entityID) { - if (entityID === rack) { - deleteCollidingBalls(); - Script.clearInterval(distanceCheckInterval); - Entities.deletingEntity.disconnect(deleteEntity); - } - } - - function deleteCollidingBalls() { - while (collidingBalls.length > 0) { - Entities.deleteEntity(collidingBalls.pop()); - } - } - - createCollidingBalls(); - Entities.deletingEntity.connect(deleteEntity); - - var distanceCheckInterval = Script.setInterval(testBallDistanceFromStart, 1000); - } - - function createTargets() { - - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx'; - var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target_collision_hull.obj'; - - var RESET_DISTANCE = 1; - var TARGET_USER_DATA_KEY = 'hifi-ping_pong_target'; - var NUMBER_OF_TARGETS = 6; - var TARGETS_PER_ROW = 3; - - var TARGET_DIMENSIONS = { - x: 0.06, - y: 0.42, - z: 0.42 - }; - - var VERTICAL_SPACING = TARGET_DIMENSIONS.y + 0.5; - var HORIZONTAL_SPACING = TARGET_DIMENSIONS.z + 0.5; - - - var startPosition = { - x: 548.68, - y: 497.30, - z: 509.74 - }; - - var rotation = Quat.fromPitchYawRollDegrees(0, -55.25, 0); - - var targetIntervalClearer = Entities.addEntity({ - name: 'Target Interval Clearer - delete me to clear', - type: 'Box', - position: startPosition, - dimensions: TARGET_DIMENSIONS, - rotation: rotation, - visible: false, - collisionsWillMove: false, - ignoreForCollisions: true, - userData: JSON.stringify({ - resetMe: { - resetMe: true - } - }) - }); - - var targets = []; - - var originalPositions = []; - var lastPositions = []; - - function addTargets() { - var i; - var row = -1; - for (i = 0; i < NUMBER_OF_TARGETS; i++) { - - if (i % TARGETS_PER_ROW === 0) { - row++; } - var vHat = Quat.getFront(rotation); - var spacer = HORIZONTAL_SPACING * (i % TARGETS_PER_ROW) + (row * HORIZONTAL_SPACING / 2); - var multiplier = Vec3.multiply(spacer, vHat); - var position = Vec3.sum(startPosition, multiplier); - position.y = startPosition.y - (row * VERTICAL_SPACING); - - originalPositions.push(position); - lastPositions.push(position); - - var targetProperties = { - name: 'Target', - type: 'Model', - modelURL: MODEL_URL, - shapeType: 'compound', - collisionsWillMove: true, - dimensions: TARGET_DIMENSIONS, - compoundShapeURL: COLLISION_HULL_URL, - position: position, - rotation: rotation, - script: targetsScriptURL, - userData: JSON.stringify({ - resetMe: { - resetMe: true + function deleteCollidingBalls() { + while (collidingBalls.length > 0) { + Entities.deleteEntity(collidingBalls.pop()); } - }) + } + + createCollidingBalls(); + Entities.deletingEntity.connect(deleteEntity); + + var distanceCheckInterval = Script.setInterval(testBallDistanceFromStart, 1000); + } + + function createTargets() { + + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx'; + var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target_collision_hull.obj'; + + var RESET_DISTANCE = 1; + var TARGET_USER_DATA_KEY = 'hifi-ping_pong_target'; + var NUMBER_OF_TARGETS = 6; + var TARGETS_PER_ROW = 3; + + var TARGET_DIMENSIONS = { + x: 0.06, + y: 0.42, + z: 0.42 }; - var target = Entities.addEntity(targetProperties); - targets.push(target); + var VERTICAL_SPACING = TARGET_DIMENSIONS.y + 0.5; + var HORIZONTAL_SPACING = TARGET_DIMENSIONS.z + 0.5; + + + var startPosition = { + x: 548.68, + y: 497.30, + z: 509.74 + }; + + var rotation = Quat.fromPitchYawRollDegrees(0, -55.25, 0); + + var targetIntervalClearer = Entities.addEntity({ + name: 'Target Interval Clearer - delete me to clear', + type: 'Box', + position: startPosition, + dimensions: TARGET_DIMENSIONS, + rotation: rotation, + visible: false, + collisionsWillMove: false, + ignoreForCollisions: true, + userData: JSON.stringify({ + resetMe: { + resetMe: true + } + }) + }); + + var targets = []; + + var originalPositions = []; + var lastPositions = []; + + function addTargets() { + var i; + var row = -1; + for (i = 0; i < NUMBER_OF_TARGETS; i++) { + + if (i % TARGETS_PER_ROW === 0) { + row++; + } + + var vHat = Quat.getFront(rotation); + var spacer = HORIZONTAL_SPACING * (i % TARGETS_PER_ROW) + (row * HORIZONTAL_SPACING / 2); + var multiplier = Vec3.multiply(spacer, vHat); + var position = Vec3.sum(startPosition, multiplier); + position.y = startPosition.y - (row * VERTICAL_SPACING); + + originalPositions.push(position); + lastPositions.push(position); + + var targetProperties = { + name: 'Target', + type: 'Model', + modelURL: MODEL_URL, + shapeType: 'compound', + collisionsWillMove: true, + dimensions: TARGET_DIMENSIONS, + compoundShapeURL: COLLISION_HULL_URL, + position: position, + rotation: rotation, + script: targetsScriptURL, + userData: JSON.stringify({ + resetMe: { + resetMe: true + }, + grabbableKey: { + grabbable: false + } + }) + }; + + var target = Entities.addEntity(targetProperties); + targets.push(target); + + } + } + + function testTargetDistanceFromStart() { + targets.forEach(function(target, index) { + + var currentPosition = Entities.getEntityProperties(target, "position").position; + var originalPosition = originalPositions[index]; + var distance = Vec3.subtract(originalPosition, currentPosition); + var length = Vec3.length(distance); + + var moving = Vec3.length(Vec3.subtract(currentPosition, lastPositions[index])); + + lastPositions[index] = currentPosition; + + if (length > RESET_DISTANCE && moving < MINIMUM_MOVE_LENGTH) { + + Entities.deleteEntity(target); + + var targetProperties = { + name: 'Target', + type: 'Model', + modelURL: MODEL_URL, + shapeType: 'compound', + collisionsWillMove: true, + dimensions: TARGET_DIMENSIONS, + compoundShapeURL: COLLISION_HULL_URL, + position: originalPositions[index], + rotation: rotation, + script: scriptURL + }; + + targets[index] = Entities.addEntity(targetProperties); + + } + }); + } + + + function deleteEntity(entityID) { + if (entityID === targetIntervalClearer) { + deleteTargets(); + Script.clearInterval(distanceCheckInterval); + Entities.deletingEntity.disconnect(deleteEntity); + } + } + + function deleteTargets() { + while (targets.length > 0) { + Entities.deleteEntity(targets.pop()); + } + Entities.deleteEntity(targetIntervalClearer); + } + + Entities.deletingEntity.connect(deleteEntity); + var distanceCheckInterval = Script.setInterval(testTargetDistanceFromStart, 1000); + + addTargets(); - } } - function testTargetDistanceFromStart() { - targets.forEach(function(target, index) { + function createCat(position) { - var currentPosition = Entities.getEntityProperties(target, "position").position; - var originalPosition = originalPositions[index]; - var distance = Vec3.subtract(originalPosition, currentPosition); - var length = Vec3.length(distance); + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx"; + var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx"; + var animationSettings = JSON.stringify({ + running: true, + }); + var cat = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "cat", + script: catScriptURL, + animationURL: animationURL, + animationSettings: animationSettings, + position: position, + rotation: { + w: 0.35020983219146729, + x: -4.57763671875e-05, + y: 0.93664455413818359, + z: -1.52587890625e-05 + }, + dimensions: { + x: 0.15723302960395813, + y: 0.50762706995010376, + z: 0.90716040134429932 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true + } + }) + }); - var moving = Vec3.length(Vec3.subtract(currentPosition, lastPositions[index])); + } - lastPositions[index] = currentPosition; + function createFlashlight(position) { + var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx"; - if (length > RESET_DISTANCE && moving < MINIMUM_MOVE_LENGTH) { + var flashlight = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "flashlight", + script: flashlightScriptURL, + position: position, + dimensions: { + x: 0.08, + y: 0.30, + z: 0.08 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -3.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + shapeType: 'box', + userData: JSON.stringify({ + resetMe: { + resetMe: true + } + }) + }); - Entities.deleteEntity(target); - var targetProperties = { - name: 'Target', + } + + function createLights() { + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx"; + + + var rotation = { + w: 0.63280689716339111, + x: 0.63280689716339111, + y: -0.31551080942153931, + z: 0.31548023223876953 + }; + var axis = { + x: 0, + y: 1, + z: 0 + }; + var dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); + + var lightSwitchHall = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Hall", + script: lightsScriptURL, + position: { + x: 543.27764892578125, + y: 495.67999267578125, + z: 511.00564575195312 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + on: true, + type: "Hall Light" + } + }) + }); + + var sconceLight1 = Entities.addEntity({ + type: "Light", + position: { + x: 543.75, + y: 496.24, + z: 511.13 + }, + name: "Sconce 1 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Hall Light" + } + }) + }); + + var sconceLight2 = Entities.addEntity({ + type: "Light", + position: { + x: 540.1, + y: 496.24, + z: 505.57 + }, + name: "Sconce 2 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Hall Light" + } + }) + }); + + rotation = { + w: 0.20082402229309082, + x: 0.20082402229309082, + y: -0.67800414562225342, + z: 0.67797362804412842 + }; + axis = { + x: 0, + y: 1, + z: 0 + }; + dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); + + var lightSwitchGarage = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Garage", + script: lightsScriptURL, + position: { + x: 545.62, + y: 495.68, + z: 500.21 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + on: true, + type: "Garage Light" + } + }) + }); + + + + var sconceLight3 = Entities.addEntity({ + type: "Light", + position: { + x: 545.49468994140625, + y: 496.24026489257812, + z: 500.63516235351562 + }, + + name: "Sconce 3 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Garage Light" + } + }) + }); + + + var sconceLight4 = Entities.addEntity({ + type: "Light", + position: { + x: 550.90399169921875, + y: 496.24026489257812, + z: 507.90237426757812 + }, + name: "Sconce 4 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Garage Light" + } + }) + }); + + var sconceLight5 = Entities.addEntity({ + type: "Light", + position: { + x: 548.407958984375, + y: 496.24026489257812, + z: 509.5504150390625 + }, + name: "Sconce 5 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Garage Light" + } + }) + }); + + } + + + + function createDice() { + var diceProps = { + type: "Model", + modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx", + collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", + name: "dice", + position: { + x: 541, + y: 494.96, + z: 509.1 + }, + dimensions: { + x: 0.09, + y: 0.09, + z: 0.09 + }, + gravity: { + x: 0, + y: -3.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + shapeType: "box", + collisionsWillMove: true, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + } + }) + }; + var dice1 = Entities.addEntity(diceProps); + + diceProps.position = { + x: 541.05, + y: 494.96, + z: 509.0 + }; + + var dice2 = Entities.addEntity(diceProps); + + } + + + function createGates() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; + + var rotation = Quat.fromPitchYawRollDegrees(0, -16, 0); + var gate = Entities.addEntity({ + name: 'Front Door Fence', type: 'Model', modelURL: MODEL_URL, + shapeType: 'box', + position: { + x: 531.15, + y: 495.11, + z: 520.20 + }, + dimensions: { + x: 1.42, + y: 1.13, + z: 0.2 + }, + rotation: rotation, + collisionsWillMove: true, + gravity: { + x: 0, + y: -100, + z: 0 + }, + linearDamping: 1, + angularDamping: 10, + mass: 10, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + }, + grabbableKey: { + grabbable: false + } + }) + }); + } + + function createPingPongBallGun() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'; + var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; + + var position = { + x: 548.6, + y: 495.4, + z: 503.39 + }; + + var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); + + var pingPongGun = Entities.addEntity({ + type: "Model", + modelURL: MODEL_URL, + shapeType: 'box', + script: pingPongScriptURL, + position: position, + rotation: rotation, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 0.08, + y: 0.21, + z: 0.47 + }, + collisionsWillMove: true, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + } + }) + }); + } + + function createBasketballHoop() { + var position = { + x: 539.23, + y: 496.13, + z: 475.89 + }; + var rotation = Quat.fromPitchYawRollDegrees(0, 58.49, 0); + + var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; + var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; + + var hoop = Entities.addEntity({ + type: "Model", + modelURL: hoopURL, + position: position, + rotation: rotation, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 1.89, + y: 3.99, + z: 3.79 + }, + compoundShapeURL: hoopCollisionHullURL, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + }, + grabbableKey: { + grabbable: false + } + }) + }); + } + + function createWand(position) { + var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; + var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/actual_no_top_collision_hull.obj'; + + var entity = Entities.addEntity({ + name: 'Bubble Wand', + type: "Model", + modelURL: WAND_MODEL, + position: position, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 0.05, + y: 0.25, + z: 0.05 + }, + //must be enabled to be grabbable in the physics engine shapeType: 'compound', collisionsWillMove: true, - dimensions: TARGET_DIMENSIONS, - compoundShapeURL: COLLISION_HULL_URL, - position: originalPositions[index], - rotation: rotation, - script: scriptURL - }; - - targets[index] = Entities.addEntity(targetProperties); - - } - }); - } - - - function deleteEntity(entityID) { - if (entityID === targetIntervalClearer) { - deleteTargets(); - Script.clearInterval(distanceCheckInterval); - Entities.deletingEntity.disconnect(deleteEntity); - } - } - - function deleteTargets() { - while (targets.length > 0) { - Entities.deleteEntity(targets.pop()); - } - Entities.deleteEntity(targetIntervalClearer); - } - - Entities.deletingEntity.connect(deleteEntity); - var distanceCheckInterval = Script.setInterval(testTargetDistanceFromStart, 1000); - - addTargets(); - - } - - function createCat(position) { - - var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx"; - var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx"; - var animationSettings = JSON.stringify({ - running: true, - }); - var cat = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "cat", - script: catScriptURL, - animationURL: animationURL, - animationSettings: animationSettings, - position: position, - rotation: { - w: 0.35020983219146729, - x: -4.57763671875e-05, - y: 0.93664455413818359, - z: -1.52587890625e-05 - }, - dimensions: { - x: 0.15723302960395813, - y: 0.50762706995010376, - z: 0.90716040134429932 - }, - userData: JSON.stringify({ - resetMe: { - resetMe: true - } - }) - }); - - } - - function createFlashlight(position) { - var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx"; - - var flashlight = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "flashlight", - script: flashlightScriptURL, - position: position, - dimensions: { - x: 0.08, - y: 0.30, - z: 0.08 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -3.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - shapeType: 'box', - userData: JSON.stringify({ - resetMe: { - resetMe: true - } - }) - }); - - - } - - function createLights() { - var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx"; - - - var rotation = { - w: 0.63280689716339111, - x: 0.63280689716339111, - y: -0.31551080942153931, - z: 0.31548023223876953 - }; - var axis = { - x: 0, - y: 1, - z: 0 - }; - var dQ = Quat.angleAxis(180, axis); - rotation = Quat.multiply(rotation, dQ); - - var lightSwitchHall = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "Light Switch Hall", - script: lightsScriptURL, - position: { - x: 543.27764892578125, - y: 495.67999267578125, - z: 511.00564575195312 - }, - rotation: rotation, - dimensions: { - x: 0.10546875, - y: 0.032372996211051941, - z: 0.16242524981498718 - }, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - on: true, - type: "Hall Light" - } - }) - }); - - var sconceLight1 = Entities.addEntity({ - type: "Light", - position: { - x: 543.75, - y: 496.24, - z: 511.13 - }, - name: "Sconce 1 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Hall Light" - } - }) - }); - - var sconceLight2 = Entities.addEntity({ - type: "Light", - position: { - x: 540.1, - y: 496.24, - z: 505.57 - }, - name: "Sconce 2 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Hall Light" - } - }) - }); - - rotation = { - w: 0.20082402229309082, - x: 0.20082402229309082, - y: -0.67800414562225342, - z: 0.67797362804412842 - }; - axis = { - x: 0, - y: 1, - z: 0 - }; - dQ = Quat.angleAxis(180, axis); - rotation = Quat.multiply(rotation, dQ); - - var lightSwitchGarage = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "Light Switch Garage", - script: lightsScriptURL, - position: { - x: 545.62, - y: 495.68, - z: 500.21 - }, - rotation: rotation, - dimensions: { - x: 0.10546875, - y: 0.032372996211051941, - z: 0.16242524981498718 - }, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - on: true, - type: "Garage Light" - } - }) - }); - - - - var sconceLight3 = Entities.addEntity({ - type: "Light", - position: { - x: 545.49468994140625, - y: 496.24026489257812, - z: 500.63516235351562 - }, - - name: "Sconce 3 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Garage Light" - } - }) - }); - - - var sconceLight4 = Entities.addEntity({ - type: "Light", - position: { - x: 550.90399169921875, - y: 496.24026489257812, - z: 507.90237426757812 - }, - name: "Sconce 4 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Garage Light" - } - }) - }); - - var sconceLight5 = Entities.addEntity({ - type: "Light", - position: { - x: 548.407958984375, - y: 496.24026489257812, - z: 509.5504150390625 - }, - name: "Sconce 5 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Garage Light" - } - }) - }); - - } - - - - function createDice() { - var diceProps = { - type: "Model", - modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx", - collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", - name: "dice", - position: { - x: 541, - y: 494.96, - z: 509.1 - }, - dimensions: { - x: 0.09, - y: 0.09, - z: 0.09 - }, - gravity: { - x: 0, - y: -3.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - shapeType: "box", - collisionsWillMove: true, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) - }; - var dice1 = Entities.addEntity(diceProps); - - diceProps.position = { - x: 541.05, - y: 494.96, - z: 509.0 - }; - - var dice2 = Entities.addEntity(diceProps); - - } - - - function createGates() { - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; - - var rotation = Quat.fromPitchYawRollDegrees(0, -16, 0); - var gate = Entities.addEntity({ - name: 'Front Door Fence', - type: 'Model', - modelURL: MODEL_URL, - shapeType: 'box', - position: { - x: 531.15, - y: 495.11, - z: 520.20 - }, - dimensions: { - x: 1.42, - y: 1.13, - z: 0.2 - }, - rotation: rotation, - collisionsWillMove: true, - gravity: { - x: 0, - y: -100, - z: 0 - }, - linearDamping: 1, - angularDamping: 10, - mass: 10, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - }, - grabbableKey: { - grabbable: false - } - }) - }); - } - - function createPingPongBallGun() { - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'; - var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; - - var position = { - x: 548.6, - y: 495.4, - z: 503.39 - }; - - var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); - - var pingPongGun = Entities.addEntity({ - type: "Model", - modelURL: MODEL_URL, - shapeType: 'box', - script: pingPongScriptURL, - position: position, - rotation: rotation, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - dimensions: { - x: 0.08, - y: 0.21, - z: 0.47 - }, - collisionsWillMove: true, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) - }); - } - - function createBasketballHoop() { - var position = { - x: 539.23, - y: 496.13, - z: 475.89 - }; - var rotation = Quat.fromPitchYawRollDegrees(0, 58.49, 0); - - var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; - var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; - - var hoop = Entities.addEntity({ - type: "Model", - modelURL: hoopURL, - position: position, - rotation: rotation, - shapeType: 'compound', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - dimensions: { - x: 1.89, - y: 3.99, - z: 3.79 - }, - compoundShapeURL: hoopCollisionHullURL, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - }, - grabbableKey: { - grabbable: false - } - }) - }); - } - - function createWand(position) { - var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; - var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/actual_no_top_collision_hull.obj'; - - var entity = Entities.addEntity({ - name: 'Bubble Wand', - type: "Model", - modelURL: WAND_MODEL, - position: position, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - dimensions: { - x: 0.05, - y: 0.25, - z: 0.05 - }, - //must be enabled to be grabbable in the physics engine - shapeType: 'compound', - collisionsWillMove: true, - compoundShapeURL: WAND_COLLISION_SHAPE, - //Look into why bubble wand is going through table when gravity is enabled - // gravity: {x: 0, y: -3.5, z: 0}, - // velocity: {x: 0, y: -0.01, z:0}, - script: wandScriptURL, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) - }); - - - } - - function createBasketBall(position) { - - var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - position: position, - collisionsWillMove: true, - shapeType: "sphere", - name: "basketball", - dimensions: { - x: 0.25, - y: 0.26, - z: 0.25 - }, - gravity: { - x: 0, - y: -7, - z: 0 - }, - restitution: 10, - linearDamping: 0.0, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/basketball/basketball.wav", - userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) - }); - - } - - function createDoll(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"; - - var naturalDimensions = { - x: 1.63, - y: 1.67, - z: 0.26 - }; - var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15); - var entity = Entities.addEntity({ - type: "Model", - name: "doll", - modelURL: modelURL, - script: dollScriptURL, - position: position, - shapeType: 'box', - dimensions: desiredDimensions, - gravity: { - x: 0, - y: -5, - z: 0 - }, - velocity: { - x: 0, - y: -0.1, - z: 0 - }, - collisionsWillMove: true, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) - }); - - } - - function createSprayCan(position) { - - var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - name: "spraycan", - script: sprayPaintScriptURL, - modelURL: modelURL, - position: position, - dimensions: { - x: 0.07, - y: 0.17, - z: 0.07 - }, - collisionsWillMove: true, - shapeType: 'box', - gravity: { - x: 0, - y: -0.5, - z: 0 - }, - velocity: { - x: 0, - y: -1, - z: 0 - }, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) - }); - - } - - function createPottedPlant(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/potted_plant/potted_plant.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - name: "Potted Plant", - modelURL: modelURL, - position: position, - dimensions: { - x: 1.10, - y: 2.18, - z: 1.07 - }, - collisionsWillMove: true, - shapeType: 'box', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - velocity: { - x: 0, - y: 0, - z: 0 - }, - linearDamping: 0.4, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - }, - grabbableKey: { - grabbable: false - } - }) - }); - } - - - function createCombinedArmChair(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/combined_chair.fbx"; - var RED_ARM_CHAIR_COLLISION_HULL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/red_arm_chair_collision_hull.obj"; - - var rotation = Quat.fromPitchYawRollDegrees(0, -143, 0); - - var entity = Entities.addEntity({ - type: "Model", - name: "Red Arm Chair", - modelURL: modelURL, - shapeType: 'compound', - compoundShapeURL: RED_ARM_CHAIR_COLLISION_HULL, - position: position, - rotation: rotation, - dimensions: { - x: 1.26, - y: 1.56, - z: 1.35 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -0.8, - z: 0 - }, - velocity: { - x: 0, - y: 0, - z: 0 - }, - linearDamping: 0.2, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - }, - grabbableKey: { - grabbable: false - } - }) - }); - - } - - function createBlocks(position) { - var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/"; - var collisionSoundURL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/ToyWoodBlock.L.wav"; - var NUM_BLOCKS_PER_COLOR = 4; - var i, j; - - var blockTypes = [{ - url: "planky_blue.fbx", - dimensions: { - x: 0.05, - y: 0.05, - z: 0.25 - } - }, { - url: "planky_green.fbx", - dimensions: { - x: 0.1, - y: 0.1, - z: 0.25 - } - }, { - url: "planky_natural.fbx", - dimensions: { - x: 0.05, - y: 0.05, - z: 0.05 - } - }, { - url: "planky_yellow.fbx", - dimensions: { - x: 0.03, - y: 0.05, - z: 0.25 - } - }, { - url: "planky_red.fbx", - dimensions: { - x: 0.1, - y: 0.05, - z: 0.25 - } - }, ]; - - var modelURL, entity; - for (i = 0; i < blockTypes.length; i++) { - for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) { - modelURL = baseURL + blockTypes[i].url; - entity = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - position: Vec3.sum(position, { - x: j / 10, - y: i / 10, - z: 0 - }), - shapeType: 'box', - name: "block", - dimensions: blockTypes[i].dimensions, - collisionsWillMove: true, - collisionSoundURL: collisionSoundURL, - gravity: { - x: 0, - y: -2.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) + compoundShapeURL: WAND_COLLISION_SHAPE, + //Look into why bubble wand is going through table when gravity is enabled + // gravity: {x: 0, y: -3.5, z: 0}, + // velocity: {x: 0, y: -0.01, z:0}, + script: wandScriptURL, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + } + }) }); - } + } - } - function cleanup() { - deleteAllToys(); - } + function createBasketBall(position) { - if (shouldDeleteOnEndScript) { + var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; - Script.scriptEnding.connect(cleanup); - } + var entity = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: position, + collisionsWillMove: true, + shapeType: "sphere", + name: "basketball", + dimensions: { + x: 0.25, + y: 0.26, + z: 0.25 + }, + gravity: { + x: 0, + y: -7, + z: 0 + }, + restitution: 10, + linearDamping: 0.0, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/basketball/basketball.wav", + userData: JSON.stringify({ + resetMe: { + resetMe: true, + } + }) + }); + + } + + function createDoll(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"; + + var naturalDimensions = { + x: 1.63, + y: 1.67, + z: 0.26 + }; + var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15); + var entity = Entities.addEntity({ + type: "Model", + name: "doll", + modelURL: modelURL, + script: dollScriptURL, + position: position, + shapeType: 'box', + dimensions: desiredDimensions, + gravity: { + x: 0, + y: -5, + z: 0 + }, + velocity: { + x: 0, + y: -0.1, + z: 0 + }, + collisionsWillMove: true, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + } + }) + }); + + } + + function createSprayCan(position) { + + var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + name: "spraycan", + script: sprayPaintScriptURL, + modelURL: modelURL, + position: position, + dimensions: { + x: 0.07, + y: 0.17, + z: 0.07 + }, + collisionsWillMove: true, + shapeType: 'box', + gravity: { + x: 0, + y: -0.5, + z: 0 + }, + velocity: { + x: 0, + y: -1, + z: 0 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + } + }) + }); + + } + + function createPottedPlant(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/potted_plant/potted_plant.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + name: "Potted Plant", + modelURL: modelURL, + position: position, + dimensions: { + x: 1.10, + y: 2.18, + z: 1.07 + }, + collisionsWillMove: true, + shapeType: 'box', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.4, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + }, + grabbableKey: { + grabbable: false + } + }) + }); + } + + + function createCombinedArmChair(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/combined_chair.fbx"; + var RED_ARM_CHAIR_COLLISION_HULL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/red_arm_chair_collision_hull.obj"; + + var rotation = Quat.fromPitchYawRollDegrees(0, -143, 0); + + var entity = Entities.addEntity({ + type: "Model", + name: "Red Arm Chair", + modelURL: modelURL, + shapeType: 'compound', + compoundShapeURL: RED_ARM_CHAIR_COLLISION_HULL, + position: position, + rotation: rotation, + dimensions: { + x: 1.26, + y: 1.56, + z: 1.35 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -0.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.2, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + }, + grabbableKey: { + grabbable: false + } + }) + }); + + } + + function createBlocks(position) { + var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/"; + var collisionSoundURL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/ToyWoodBlock.L.wav"; + var NUM_BLOCKS_PER_COLOR = 4; + var i, j; + + var blockTypes = [{ + url: "planky_blue.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_green.fbx", + dimensions: { + x: 0.1, + y: 0.1, + z: 0.25 + } + }, { + url: "planky_natural.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.05 + } + }, { + url: "planky_yellow.fbx", + dimensions: { + x: 0.03, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_red.fbx", + dimensions: { + x: 0.1, + y: 0.05, + z: 0.25 + } + }, ]; + + var modelURL, entity; + for (i = 0; i < blockTypes.length; i++) { + for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) { + modelURL = baseURL + blockTypes[i].url; + entity = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: Vec3.sum(position, { + x: j / 10, + y: i / 10, + z: 0 + }), + shapeType: 'box', + name: "block", + dimensions: blockTypes[i].dimensions, + collisionsWillMove: true, + collisionSoundURL: collisionSoundURL, + gravity: { + x: 0, + y: -2.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + } + }) + }); + + } + } + } + + function cleanup() { + deleteAllToys(); + } + + if (shouldDeleteOnEndScript) { + + Script.scriptEnding.connect(cleanup); + } }; \ No newline at end of file From fc8a4f4f2dba746f0883e606dae60ef8dcd114e3 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 12 Oct 2015 17:00:49 -0700 Subject: [PATCH 04/16] cleanup --- unpublishedScripts/masterReset.js | 1 - 1 file changed, 1 deletion(-) diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index fdedac3ec3..03dacef0a4 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -247,7 +247,6 @@ MasterReset = function() { grabbableKey: { grabbable: false } - }) }); From 0f998e81afd9f123083639e2d986220c689ba5fc Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 12 Oct 2015 17:03:32 -0700 Subject: [PATCH 05/16] add min reset distance --- unpublishedScripts/hiddenEntityReset.js | 4 ++-- unpublishedScripts/masterReset.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index f959923ad3..702aaec378 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -378,7 +378,8 @@ var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx'; var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target_collision_hull.obj'; - var RESET_DISTANCE = 1; + var MINIMUM_MOVE_LENGTH = 0.05; + var RESET_DISTANCE = 0.5; var TARGET_USER_DATA_KEY = 'hifi-ping_pong_target'; var NUMBER_OF_TARGETS = 6; var TARGETS_PER_ROW = 3; @@ -392,7 +393,6 @@ var VERTICAL_SPACING = TARGET_DIMENSIONS.y + 0.5; var HORIZONTAL_SPACING = TARGET_DIMENSIONS.z + 0.5; - var startPosition = { x: 548.68, y: 497.30, diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 03dacef0a4..a6c3bfdd16 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -350,7 +350,8 @@ MasterReset = function() { var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx'; var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target_collision_hull.obj'; - var RESET_DISTANCE = 1; + var MINIMUM_MOVE_LENGTH = 0.05; + var RESET_DISTANCE = 0.5; var TARGET_USER_DATA_KEY = 'hifi-ping_pong_target'; var NUMBER_OF_TARGETS = 6; var TARGETS_PER_ROW = 3; From 309cde7f28735d2a23ac7f3943e7f35ea6513ed1 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 13 Oct 2015 10:31:36 -0700 Subject: [PATCH 06/16] invert solidity of most toybox objects while held --- unpublishedScripts/hiddenEntityReset.js | 41 +- unpublishedScripts/masterReset.js | 1248 ++++++++++++----------- 2 files changed, 686 insertions(+), 603 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 702aaec378..1b3dd07e5e 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -319,6 +319,9 @@ userData: JSON.stringify({ resetMe: { resetMe: true + }, + grabbableKey: { + invertSolidWhileHeld: true } }) }); @@ -459,6 +462,9 @@ resetMe: { resetMe: true }, + grabbableKey: { + grabbable: false + } }) }; var target = Entities.addEntity(targetProperties); @@ -492,7 +498,15 @@ compoundShapeURL: COLLISION_HULL_URL, position: originalPositions[index], rotation: rotation, - script: scriptURL + script: scriptURL, + userData: JSON.stringify({ + resetMe: { + resetMe: true + }, + grabbableKey: { + grabbable: false + } + }) }; targets[index] = Entities.addEntity(targetProperties); @@ -553,6 +567,9 @@ userData: JSON.stringify({ resetMe: { resetMe: true + }, + grabbableKey: { + grabbable: false } }) }); @@ -588,7 +605,11 @@ userData: JSON.stringify({ resetMe: { resetMe: true + }, + grabbableKey: { + invertSolidWhileHeld: true } + }) }); @@ -856,6 +877,9 @@ userData: JSON.stringify({ resetMe: { resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true } }) }; @@ -945,6 +969,9 @@ userData: JSON.stringify({ resetMe: { resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true } }) }); @@ -1019,6 +1046,9 @@ userData: JSON.stringify({ resetMe: { resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true } }) }); @@ -1058,6 +1088,9 @@ userData: JSON.stringify({ resetMe: { resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true } }) }); @@ -1095,6 +1128,9 @@ userData: JSON.stringify({ resetMe: { resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true } }) }); @@ -1131,6 +1167,9 @@ userData: JSON.stringify({ resetMe: { resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true } }) }); diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index a6c3bfdd16..5eaa35372f 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -291,6 +291,9 @@ MasterReset = function() { userData: JSON.stringify({ resetMe: { resetMe: true + }, + grabbable: { + invertSolidWhileHeld: true } }) }); @@ -443,69 +446,78 @@ MasterReset = function() { function testTargetDistanceFromStart() { targets.forEach(function(target, index) { - var currentPosition = Entities.getEntityProperties(target, "position").position; - var originalPosition = originalPositions[index]; - var distance = Vec3.subtract(originalPosition, currentPosition); - var length = Vec3.length(distance); + var currentPosition = Entities.getEntityProperties(target, "position").position; + var originalPosition = originalPositions[index]; + var distance = Vec3.subtract(originalPosition, currentPosition); + var length = Vec3.length(distance); - var moving = Vec3.length(Vec3.subtract(currentPosition, lastPositions[index])); + var moving = Vec3.length(Vec3.subtract(currentPosition, lastPositions[index])); - lastPositions[index] = currentPosition; + lastPositions[index] = currentPosition; - if (length > RESET_DISTANCE && moving < MINIMUM_MOVE_LENGTH) { + if (length > RESET_DISTANCE && moving < MINIMUM_MOVE_LENGTH) { - Entities.deleteEntity(target); + Entities.deleteEntity(target); - var targetProperties = { - name: 'Target', - type: 'Model', - modelURL: MODEL_URL, - shapeType: 'compound', - collisionsWillMove: true, - dimensions: TARGET_DIMENSIONS, - compoundShapeURL: COLLISION_HULL_URL, - position: originalPositions[index], - rotation: rotation, - script: scriptURL + var targetProperties = { + name: 'Target', + type: 'Model', + modelURL: MODEL_URL, + shapeType: 'compound', + collisionsWillMove: true, + dimensions: TARGET_DIMENSIONS, + compoundShapeURL: COLLISION_HULL_URL, + position: originalPositions[index], + rotation: rotation, + script: scriptURL, + userData: JSON.stringify({ + resetMe: { + resetMe: true + }, + grabbableKey: { + grabbable: false + } + } + }) }; targets[index] = Entities.addEntity(targetProperties); } }); - } - - - function deleteEntity(entityID) { - if (entityID === targetIntervalClearer) { - deleteTargets(); - Script.clearInterval(distanceCheckInterval); - Entities.deletingEntity.disconnect(deleteEntity); - } - } - - function deleteTargets() { - while (targets.length > 0) { - Entities.deleteEntity(targets.pop()); - } - Entities.deleteEntity(targetIntervalClearer); - } - - Entities.deletingEntity.connect(deleteEntity); - var distanceCheckInterval = Script.setInterval(testTargetDistanceFromStart, 1000); - - addTargets(); - } - function createCat(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx"; - var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx"; - var animationSettings = JSON.stringify({ - running: true, - }); - var cat = Entities.addEntity({ + function deleteEntity(entityID) { + if (entityID === targetIntervalClearer) { + deleteTargets(); + Script.clearInterval(distanceCheckInterval); + Entities.deletingEntity.disconnect(deleteEntity); + } + } + + function deleteTargets() { + while (targets.length > 0) { + Entities.deleteEntity(targets.pop()); + } + Entities.deleteEntity(targetIntervalClearer); + } + + Entities.deletingEntity.connect(deleteEntity); + var distanceCheckInterval = Script.setInterval(testTargetDistanceFromStart, 1000); + + addTargets(); + +} + +function createCat(position) { + + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx"; + var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx"; + var animationSettings = JSON.stringify({ + running: true, + }); + var cat = Entities.addEntity({ type: "Model", modelURL: modelURL, name: "cat", @@ -525,18 +537,22 @@ MasterReset = function() { z: 0.90716040134429932 }, userData: JSON.stringify({ - resetMe: { - resetMe: true + resetMe: { + resetMe: true + }, + grabbableKey: { + grabbable: false + } } }) - }); + }); - } +} - function createFlashlight(position) { - var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx"; +function createFlashlight(position) { + var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx"; - var flashlight = Entities.addEntity({ + var flashlight = Entities.addEntity({ type: "Model", modelURL: modelURL, name: "flashlight", @@ -560,345 +576,353 @@ MasterReset = function() { }, shapeType: 'box', userData: JSON.stringify({ - resetMe: { - resetMe: true + resetMe: { + resetMe: true + }, + grabbableKey: { + invertSolidWhileHeld: true + } } }) - }); + }); - } +} - function createLights() { - var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx"; +function createLights() { + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx"; - var rotation = { - w: 0.63280689716339111, - x: 0.63280689716339111, - y: -0.31551080942153931, - z: 0.31548023223876953 - }; - var axis = { - x: 0, - y: 1, - z: 0 - }; - var dQ = Quat.angleAxis(180, axis); - rotation = Quat.multiply(rotation, dQ); + var rotation = { + w: 0.63280689716339111, + x: 0.63280689716339111, + y: -0.31551080942153931, + z: 0.31548023223876953 + }; + var axis = { + x: 0, + y: 1, + z: 0 + }; + var dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); - var lightSwitchHall = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "Light Switch Hall", - script: lightsScriptURL, - position: { - x: 543.27764892578125, - y: 495.67999267578125, - z: 511.00564575195312 - }, - rotation: rotation, - dimensions: { - x: 0.10546875, - y: 0.032372996211051941, - z: 0.16242524981498718 - }, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - on: true, - type: "Hall Light" - } - }) - }); + var lightSwitchHall = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Hall", + script: lightsScriptURL, + position: { + x: 543.27764892578125, + y: 495.67999267578125, + z: 511.00564575195312 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + on: true, + type: "Hall Light" + } + }) + }); - var sconceLight1 = Entities.addEntity({ - type: "Light", - position: { - x: 543.75, - y: 496.24, - z: 511.13 - }, - name: "Sconce 1 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Hall Light" - } - }) - }); + var sconceLight1 = Entities.addEntity({ + type: "Light", + position: { + x: 543.75, + y: 496.24, + z: 511.13 + }, + name: "Sconce 1 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Hall Light" + } + }) + }); - var sconceLight2 = Entities.addEntity({ - type: "Light", - position: { - x: 540.1, - y: 496.24, - z: 505.57 - }, - name: "Sconce 2 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Hall Light" - } - }) - }); + var sconceLight2 = Entities.addEntity({ + type: "Light", + position: { + x: 540.1, + y: 496.24, + z: 505.57 + }, + name: "Sconce 2 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Hall Light" + } + }) + }); - rotation = { - w: 0.20082402229309082, - x: 0.20082402229309082, - y: -0.67800414562225342, - z: 0.67797362804412842 - }; - axis = { - x: 0, - y: 1, - z: 0 - }; - dQ = Quat.angleAxis(180, axis); - rotation = Quat.multiply(rotation, dQ); + rotation = { + w: 0.20082402229309082, + x: 0.20082402229309082, + y: -0.67800414562225342, + z: 0.67797362804412842 + }; + axis = { + x: 0, + y: 1, + z: 0 + }; + dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); - var lightSwitchGarage = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "Light Switch Garage", - script: lightsScriptURL, - position: { - x: 545.62, - y: 495.68, - z: 500.21 - }, - rotation: rotation, - dimensions: { - x: 0.10546875, - y: 0.032372996211051941, - z: 0.16242524981498718 - }, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - on: true, - type: "Garage Light" - } - }) - }); + var lightSwitchGarage = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Garage", + script: lightsScriptURL, + position: { + x: 545.62, + y: 495.68, + z: 500.21 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + on: true, + type: "Garage Light" + } + }) + }); - var sconceLight3 = Entities.addEntity({ - type: "Light", - position: { - x: 545.49468994140625, - y: 496.24026489257812, - z: 500.63516235351562 - }, + var sconceLight3 = Entities.addEntity({ + type: "Light", + position: { + x: 545.49468994140625, + y: 496.24026489257812, + z: 500.63516235351562 + }, - name: "Sconce 3 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Garage Light" - } - }) - }); + name: "Sconce 3 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Garage Light" + } + }) + }); - var sconceLight4 = Entities.addEntity({ - type: "Light", - position: { - x: 550.90399169921875, - y: 496.24026489257812, - z: 507.90237426757812 - }, - name: "Sconce 4 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Garage Light" - } - }) - }); + var sconceLight4 = Entities.addEntity({ + type: "Light", + position: { + x: 550.90399169921875, + y: 496.24026489257812, + z: 507.90237426757812 + }, + name: "Sconce 4 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Garage Light" + } + }) + }); - var sconceLight5 = Entities.addEntity({ - type: "Light", - position: { - x: 548.407958984375, - y: 496.24026489257812, - z: 509.5504150390625 - }, - name: "Sconce 5 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - }, - isSpotlight: false, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - type: "Garage Light" - } - }) - }); + var sconceLight5 = Entities.addEntity({ + type: "Light", + position: { + x: 548.407958984375, + y: 496.24026489257812, + z: 509.5504150390625 + }, + name: "Sconce 5 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + }, + isSpotlight: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + type: "Garage Light" + } + }) + }); - } +} - function createDice() { - var diceProps = { - type: "Model", - modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx", - collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", - name: "dice", - position: { - x: 541, - y: 494.96, - z: 509.1 - }, - dimensions: { - x: 0.09, - y: 0.09, - z: 0.09 - }, - gravity: { - x: 0, - y: -3.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - shapeType: "box", - collisionsWillMove: true, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) - }; - var dice1 = Entities.addEntity(diceProps); - - diceProps.position = { - x: 541.05, +function createDice() { + var diceProps = { + type: "Model", + modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx", + collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", + name: "dice", + position: { + x: 541, y: 494.96, - z: 509.0 - }; - - var dice2 = Entities.addEntity(diceProps); - - } - - - function createGates() { - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; - - var rotation = Quat.fromPitchYawRollDegrees(0, -16, 0); - var gate = Entities.addEntity({ - name: 'Front Door Fence', - type: 'Model', - modelURL: MODEL_URL, - shapeType: 'box', - position: { - x: 531.15, - y: 495.11, - z: 520.20 - }, - dimensions: { - x: 1.42, - y: 1.13, - z: 0.2 - }, - rotation: rotation, - collisionsWillMove: true, - gravity: { - x: 0, - y: -100, - z: 0 - }, - linearDamping: 1, - angularDamping: 10, - mass: 10, - userData: JSON.stringify({ + z: 509.1 + }, + dimensions: { + x: 0.09, + y: 0.09, + z: 0.09 + }, + gravity: { + x: 0, + y: -3.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + shapeType: "box", + collisionsWillMove: true, + userData: JSON.stringify({ resetMe: { resetMe: true, }, grabbableKey: { - grabbable: false + invertSolidWhileHeld: true } - }) - }); - } + } + }) +}; +var dice1 = Entities.addEntity(diceProps); - function createPingPongBallGun() { - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'; - var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; +diceProps.position = { + x: 541.05, + y: 494.96, + z: 509.0 +}; - var position = { - x: 548.6, - y: 495.4, - z: 503.39 - }; +var dice2 = Entities.addEntity(diceProps); - var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); +} - var pingPongGun = Entities.addEntity({ + +function createGates() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; + + var rotation = Quat.fromPitchYawRollDegrees(0, -16, 0); + var gate = Entities.addEntity({ + name: 'Front Door Fence', + type: 'Model', + modelURL: MODEL_URL, + shapeType: 'box', + position: { + x: 531.15, + y: 495.11, + z: 520.20 + }, + dimensions: { + x: 1.42, + y: 1.13, + z: 0.2 + }, + rotation: rotation, + collisionsWillMove: true, + gravity: { + x: 0, + y: -100, + z: 0 + }, + linearDamping: 1, + angularDamping: 10, + mass: 10, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + }, + grabbableKey: { + grabbable: false + } + }) + }); +} + +function createPingPongBallGun() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'; + var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; + + var position = { + x: 548.6, + y: 495.4, + z: 503.39 + }; + + var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); + + var pingPongGun = Entities.addEntity({ type: "Model", modelURL: MODEL_URL, shapeType: 'box', @@ -917,57 +941,61 @@ MasterReset = function() { }, collisionsWillMove: true, userData: JSON.stringify({ - resetMe: { - resetMe: true, + resetMe: { + resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true + } } }) - }); - } + }); +} - function createBasketballHoop() { - var position = { - x: 539.23, - y: 496.13, - z: 475.89 - }; - var rotation = Quat.fromPitchYawRollDegrees(0, 58.49, 0); +function createBasketballHoop() { + var position = { + x: 539.23, + y: 496.13, + z: 475.89 + }; + var rotation = Quat.fromPitchYawRollDegrees(0, 58.49, 0); - var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; - var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; + var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; + var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; - var hoop = Entities.addEntity({ - type: "Model", - modelURL: hoopURL, - position: position, - rotation: rotation, - shapeType: 'compound', - gravity: { - x: 0, - y: -9.8, - z: 0 + var hoop = Entities.addEntity({ + type: "Model", + modelURL: hoopURL, + position: position, + rotation: rotation, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 1.89, + y: 3.99, + z: 3.79 + }, + compoundShapeURL: hoopCollisionHullURL, + userData: JSON.stringify({ + resetMe: { + resetMe: true, }, - dimensions: { - x: 1.89, - y: 3.99, - z: 3.79 - }, - compoundShapeURL: hoopCollisionHullURL, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - }, - grabbableKey: { - grabbable: false - } - }) - }); - } + grabbableKey: { + grabbable: false + } + }) + }); +} - function createWand(position) { - var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; - var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/actual_no_top_collision_hull.obj'; +function createWand(position) { + var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; + var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/actual_no_top_collision_hull.obj'; - var entity = Entities.addEntity({ + var entity = Entities.addEntity({ name: 'Bubble Wand', type: "Model", modelURL: WAND_MODEL, @@ -991,20 +1019,24 @@ MasterReset = function() { // velocity: {x: 0, y: -0.01, z:0}, script: wandScriptURL, userData: JSON.stringify({ - resetMe: { - resetMe: true, + resetMe: { + resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true + } } }) - }); + }); - } +} - function createBasketBall(position) { +function createBasketBall(position) { - var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; + var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; - var entity = Entities.addEntity({ + var entity = Entities.addEntity({ type: "Model", modelURL: modelURL, position: position, @@ -1030,24 +1062,28 @@ MasterReset = function() { }, collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/basketball/basketball.wav", userData: JSON.stringify({ - resetMe: { - resetMe: true, + resetMe: { + resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true + } } }) - }); + }); - } +} - function createDoll(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"; +function createDoll(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"; - var naturalDimensions = { - x: 1.63, - y: 1.67, - z: 0.26 - }; - var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15); - var entity = Entities.addEntity({ + var naturalDimensions = { + x: 1.63, + y: 1.67, + z: 0.26 + }; + var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15); + var entity = Entities.addEntity({ type: "Model", name: "doll", modelURL: modelURL, @@ -1067,19 +1103,23 @@ MasterReset = function() { }, collisionsWillMove: true, userData: JSON.stringify({ - resetMe: { - resetMe: true, + resetMe: { + resetMe: true, + }, + grabbableKey: { + invertSolidWhileHeld: true + } } }) - }); + }); - } +} - function createSprayCan(position) { +function createSprayCan(position) { - var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; + var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; - var entity = Entities.addEntity({ + var entity = Entities.addEntity({ type: "Model", name: "spraycan", script: sprayPaintScriptURL, @@ -1103,182 +1143,186 @@ MasterReset = function() { z: 0 }, userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) - }); - - } - - function createPottedPlant(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/potted_plant/potted_plant.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - name: "Potted Plant", - modelURL: modelURL, - position: position, - dimensions: { - x: 1.10, - y: 2.18, - z: 1.07 - }, - collisionsWillMove: true, - shapeType: 'box', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - velocity: { - x: 0, - y: 0, - z: 0 - }, - linearDamping: 0.4, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - }, - grabbableKey: { - grabbable: false - } - }) - }); - } - - - function createCombinedArmChair(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/combined_chair.fbx"; - var RED_ARM_CHAIR_COLLISION_HULL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/red_arm_chair_collision_hull.obj"; - - var rotation = Quat.fromPitchYawRollDegrees(0, -143, 0); - - var entity = Entities.addEntity({ - type: "Model", - name: "Red Arm Chair", - modelURL: modelURL, - shapeType: 'compound', - compoundShapeURL: RED_ARM_CHAIR_COLLISION_HULL, - position: position, - rotation: rotation, - dimensions: { - x: 1.26, - y: 1.56, - z: 1.35 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -0.8, - z: 0 - }, - velocity: { - x: 0, - y: 0, - z: 0 - }, - linearDamping: 0.2, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - }, - grabbableKey: { - grabbable: false - } - }) - }); - - } - - function createBlocks(position) { - var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/"; - var collisionSoundURL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/ToyWoodBlock.L.wav"; - var NUM_BLOCKS_PER_COLOR = 4; - var i, j; - - var blockTypes = [{ - url: "planky_blue.fbx", - dimensions: { - x: 0.05, - y: 0.05, - z: 0.25 - } - }, { - url: "planky_green.fbx", - dimensions: { - x: 0.1, - y: 0.1, - z: 0.25 - } - }, { - url: "planky_natural.fbx", - dimensions: { - x: 0.05, - y: 0.05, - z: 0.05 - } - }, { - url: "planky_yellow.fbx", - dimensions: { - x: 0.03, - y: 0.05, - z: 0.25 - } - }, { - url: "planky_red.fbx", - dimensions: { - x: 0.1, - y: 0.05, - z: 0.25 - } - }, ]; - - var modelURL, entity; - for (i = 0; i < blockTypes.length; i++) { - for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) { - modelURL = baseURL + blockTypes[i].url; - entity = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - position: Vec3.sum(position, { - x: j / 10, - y: i / 10, - z: 0 - }), - shapeType: 'box', - name: "block", - dimensions: blockTypes[i].dimensions, - collisionsWillMove: true, - collisionSoundURL: collisionSoundURL, - gravity: { - x: 0, - y: -2.5, - z: 0 + resetMe: { + resetMe: true, }, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - userData: JSON.stringify({ - resetMe: { - resetMe: true, - } - }) - }); + grabbableKey: { + invertSolidWhileHeld: true + } + } + }) + }); +} + +function createPottedPlant(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/potted_plant/potted_plant.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + name: "Potted Plant", + modelURL: modelURL, + position: position, + dimensions: { + x: 1.10, + y: 2.18, + z: 1.07 + }, + collisionsWillMove: true, + shapeType: 'box', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.4, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + }, + grabbableKey: { + grabbable: false } + }) + }); +} + + +function createCombinedArmChair(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/combined_chair.fbx"; + var RED_ARM_CHAIR_COLLISION_HULL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/red_arm_chair_collision_hull.obj"; + + var rotation = Quat.fromPitchYawRollDegrees(0, -143, 0); + + var entity = Entities.addEntity({ + type: "Model", + name: "Red Arm Chair", + modelURL: modelURL, + shapeType: 'compound', + compoundShapeURL: RED_ARM_CHAIR_COLLISION_HULL, + position: position, + rotation: rotation, + dimensions: { + x: 1.26, + y: 1.56, + z: 1.35 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -0.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.2, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + }, + grabbableKey: { + grabbable: false + } + }) + }); + +} + +function createBlocks(position) { + var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/"; + var collisionSoundURL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/ToyWoodBlock.L.wav"; + var NUM_BLOCKS_PER_COLOR = 4; + var i, j; + + var blockTypes = [{ + url: "planky_blue.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_green.fbx", + dimensions: { + x: 0.1, + y: 0.1, + z: 0.25 + } + }, { + url: "planky_natural.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.05 + } + }, { + url: "planky_yellow.fbx", + dimensions: { + x: 0.03, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_red.fbx", + dimensions: { + x: 0.1, + y: 0.05, + z: 0.25 + } + }, ]; + + var modelURL, entity; + for (i = 0; i < blockTypes.length; i++) { + for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) { + modelURL = baseURL + blockTypes[i].url; + entity = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: Vec3.sum(position, { + x: j / 10, + y: i / 10, + z: 0 + }), + shapeType: 'box', + name: "block", + dimensions: blockTypes[i].dimensions, + collisionsWillMove: true, + collisionSoundURL: collisionSoundURL, + gravity: { + x: 0, + y: -2.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + userData: JSON.stringify({ + resetMe: { + resetMe: true, + } + }) + }); + } } +} - function cleanup() { - deleteAllToys(); - } +function cleanup() { + deleteAllToys(); +} - if (shouldDeleteOnEndScript) { +if (shouldDeleteOnEndScript) { - Script.scriptEnding.connect(cleanup); - } + Script.scriptEnding.connect(cleanup); +} }; \ No newline at end of file From c84d2fc36a29ab8ad3fe5163fb9453329445b6f5 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 13 Oct 2015 10:44:43 -0700 Subject: [PATCH 07/16] fix target script url --- unpublishedScripts/hiddenEntityReset.js | 2 +- unpublishedScripts/masterReset.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 1b3dd07e5e..13e5f89914 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -498,7 +498,7 @@ compoundShapeURL: COLLISION_HULL_URL, position: originalPositions[index], rotation: rotation, - script: scriptURL, + script: targetsScriptURL, userData: JSON.stringify({ resetMe: { resetMe: true diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 5eaa35372f..f855caa9a1 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -469,7 +469,7 @@ MasterReset = function() { compoundShapeURL: COLLISION_HULL_URL, position: originalPositions[index], rotation: rotation, - script: scriptURL, + script: targetsScriptURL, userData: JSON.stringify({ resetMe: { resetMe: true From 93e908a592093671fbd6c1e19c97c2a58a5e54f6 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 13 Oct 2015 12:15:13 -0700 Subject: [PATCH 08/16] Don't reload/recenter some avatar data on startup, when we don't necessarilly have all the required data initialized. --- interface/src/Application.cpp | 6 +-- interface/src/Application.h | 2 +- interface/src/PluginContainerProxy.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 62 ++++++++++++++------------ interface/src/avatar/MyAvatar.h | 2 +- 5 files changed, 40 insertions(+), 34 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 30014f8906..aad480edde 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1559,7 +1559,7 @@ void Application::keyPressEvent(QKeyEvent* event) { cursor->setIcon(Cursor::Icon::DEFAULT); } } else { - resetSensors(); + resetSensors(true); } break; } @@ -3591,7 +3591,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi renderArgs->_viewport = originalViewport; } -void Application::resetSensors() { +void Application::resetSensors(bool andReload) { DependencyManager::get()->reset(); DependencyManager::get()->reset(); DependencyManager::get()->reset(); @@ -3603,7 +3603,7 @@ void Application::resetSensors() { QPoint windowCenter = mainWindow->geometry().center(); _glWidget->cursor().setPos(currentScreen, windowCenter); - getMyAvatar()->reset(); + getMyAvatar()->reset(andReload); QMetaObject::invokeMethod(DependencyManager::get().data(), "reset", Qt::QueuedConnection); } diff --git a/interface/src/Application.h b/interface/src/Application.h index a2125e7e09..dc714ad82a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -274,7 +274,7 @@ public slots: void setRawAvatarUpdateThreading(); void setRawAvatarUpdateThreading(bool isThreaded); - void resetSensors(); + void resetSensors(bool andReload = false); void setActiveFaceTracker(); #ifdef HAVE_IVIEWHMD diff --git a/interface/src/PluginContainerProxy.cpp b/interface/src/PluginContainerProxy.cpp index 19bb6ab8de..079d6d0bea 100644 --- a/interface/src/PluginContainerProxy.cpp +++ b/interface/src/PluginContainerProxy.cpp @@ -144,7 +144,7 @@ void PluginContainerProxy::unsetFullscreen(const QScreen* avoid) { void PluginContainerProxy::requestReset() { // We could signal qApp to sequence this, but it turns out that requestReset is only used from within the main thread anyway. - qApp->resetSensors(); + qApp->resetSensors(true); } void PluginContainerProxy::showDisplayPluginsTools() { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 605a81e9d9..f5c3acd386 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -140,16 +140,18 @@ QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) { return AvatarData::toByteArray(cullSmallChanges, sendAll); } -void MyAvatar::reset() { +void MyAvatar::reset(bool andReload) { // Gather animation mode... // This should be simpler when we have only graph animations always on. bool isRig = _rig->getEnableRig(); // seting rig animation to true, below, will clear the graph animation menu item, so grab it now. bool isGraph = _rig->getEnableAnimGraph() || Menu::getInstance()->isOptionChecked(MenuOption::EnableAnimGraph); // ... and get to sane configuration where other activity won't bother us. - qApp->setRawAvatarUpdateThreading(false); - _rig->disableHands = true; - setEnableRigAnimations(true); + if (andReload) { + qApp->setRawAvatarUpdateThreading(false); + _rig->disableHands = true; + setEnableRigAnimations(true); + } // Reset dynamic state. _wasPushing = _isPushing = _isBraking = _billboardValid = _straighteningLean = false; @@ -158,32 +160,34 @@ void MyAvatar::reset() { _targetVelocity = glm::vec3(0.0f); setThrust(glm::vec3(0.0f)); - // Get fresh data, in case we're really slow and out of wack. - _hmdSensorMatrix = qApp->getHMDSensorPose(); - _hmdSensorPosition = extractTranslation(_hmdSensorMatrix); - _hmdSensorOrientation = glm::quat_cast(_hmdSensorMatrix); + if (andReload) { + // Get fresh data, in case we're really slow and out of wack. + _hmdSensorMatrix = qApp->getHMDSensorPose(); + _hmdSensorPosition = extractTranslation(_hmdSensorMatrix); + _hmdSensorOrientation = glm::quat_cast(_hmdSensorMatrix); - // Reset body position/orientation under the head. - auto newBodySensorMatrix = deriveBodyFromHMDSensor(); // Based on current cached HMD position/rotation.. - auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix; - glm::vec3 worldBodyPos = extractTranslation(worldBodyMatrix); - glm::quat worldBodyRot = glm::normalize(glm::quat_cast(worldBodyMatrix)); + // Reset body position/orientation under the head. + auto newBodySensorMatrix = deriveBodyFromHMDSensor(); // Based on current cached HMD position/rotation.. + auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix; + glm::vec3 worldBodyPos = extractTranslation(worldBodyMatrix); + glm::quat worldBodyRot = glm::normalize(glm::quat_cast(worldBodyMatrix)); - // FIXME: Hack to retain the previous behavior wrt height. - // I'd like to make the body match head height, but that will have to wait for separate PR. - worldBodyPos.y = getPosition().y; + // FIXME: Hack to retain the previous behavior wrt height. + // I'd like to make the body match head height, but that will have to wait for separate PR. + worldBodyPos.y = getPosition().y; - setPosition(worldBodyPos); - setOrientation(worldBodyRot); - // If there is any discrepency between positioning and the head (as there is in initial deriveBodyFromHMDSensor), - // we can make that right by setting _bodySensorMatrix = newBodySensorMatrix. - // However, doing so will make the head want to point to the previous body orientation, as cached above. - //_bodySensorMatrix = newBodySensorMatrix; - //updateSensorToWorldMatrix(); // Uses updated position/orientation and _bodySensorMatrix changes + setPosition(worldBodyPos); + setOrientation(worldBodyRot); + // If there is any discrepency between positioning and the head (as there is in initial deriveBodyFromHMDSensor), + // we can make that right by setting _bodySensorMatrix = newBodySensorMatrix. + // However, doing so will make the head want to point to the previous body orientation, as cached above. + //_bodySensorMatrix = newBodySensorMatrix; + //updateSensorToWorldMatrix(); // Uses updated position/orientation and _bodySensorMatrix changes - _skeletonModel.simulate(0.1f); // non-zero - setEnableRigAnimations(false); - _skeletonModel.simulate(0.1f); + _skeletonModel.simulate(0.1f); // non-zero + setEnableRigAnimations(false); + _skeletonModel.simulate(0.1f); + } if (isRig) { setEnableRigAnimations(true); Menu::getInstance()->setIsOptionChecked(MenuOption::EnableRigAnimations, true); @@ -191,8 +195,10 @@ void MyAvatar::reset() { setEnableAnimGraph(true); Menu::getInstance()->setIsOptionChecked(MenuOption::EnableAnimGraph, true); } - _rig->disableHands = false; - qApp->setRawAvatarUpdateThreading(); + if (andReload) { + _rig->disableHands = false; + qApp->setRawAvatarUpdateThreading(); + } } void MyAvatar::update(float deltaTime) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index cca0c4152f..02c9f53082 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -58,7 +58,7 @@ public: AudioListenerMode getAudioListenerModeCamera() const { return FROM_CAMERA; } AudioListenerMode getAudioListenerModeCustom() const { return CUSTOM; } - void reset(); + void reset(bool andReload = false); void update(float deltaTime); void preRender(RenderArgs* renderArgs); From ad96d7692191bd959f7760cb6b740d8f19d26493 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 13 Oct 2015 15:06:11 -0700 Subject: [PATCH 09/16] implement comfort mode hack --- interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + interface/src/avatar/MyAvatar.cpp | 79 ++++++++++++++++++++++--------- 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ae41ca2493..3d671b0447 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -461,6 +461,7 @@ Menu::Menu() { 0, false, &ConnexionClient::getInstance(), SLOT(toggleConnexion(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ComfortMode, 0, true); MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands"); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 4c9c3ef7b5..216a410603 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -159,6 +159,7 @@ namespace MenuOption { const QString CenterPlayerInView = "Center Player In View"; const QString Chat = "Chat..."; const QString Collisions = "Collisions"; + const QString ComfortMode = "Comfort Mode"; const QString Connexion = "Activate 3D Connexion Devices"; const QString Console = "Console..."; const QString ControlWithSpeech = "Control With Speech"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 605a81e9d9..55690c98f1 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1514,33 +1514,68 @@ bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { void MyAvatar::updateOrientation(float deltaTime) { // Smoothly rotate body with arrow keys - float targetSpeed = (_driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT]) * YAW_SPEED; - if (targetSpeed != 0.0f) { - const float ROTATION_RAMP_TIMESCALE = 0.1f; - float blend = deltaTime / ROTATION_RAMP_TIMESCALE; - if (blend > 1.0f) { - blend = 1.0f; - } - _bodyYawDelta = (1.0f - blend) * _bodyYawDelta + blend * targetSpeed; - } else if (_bodyYawDelta != 0.0f) { - // attenuate body rotation speed - const float ROTATION_DECAY_TIMESCALE = 0.05f; - float attenuation = 1.0f - deltaTime / ROTATION_DECAY_TIMESCALE; - if (attenuation < 0.0f) { - attenuation = 0.0f; - } - _bodyYawDelta *= attenuation; + float targetSpeed = 0.0f; + + // FIXME - this comfort mode code is a total hack, remove it when we have new input mapping + bool isComfortMode = Menu::getInstance()->isOptionChecked(MenuOption::ComfortMode); + bool isHMDMode = qApp->getAvatarUpdater()->isHMDMode(); + + if (!isHMDMode || !isComfortMode) { + targetSpeed = (_driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT]) * YAW_SPEED; + + if (targetSpeed != 0.0f) { + const float ROTATION_RAMP_TIMESCALE = 0.1f; + float blend = deltaTime / ROTATION_RAMP_TIMESCALE; + if (blend > 1.0f) { + blend = 1.0f; + } + _bodyYawDelta = (1.0f - blend) * _bodyYawDelta + blend * targetSpeed; + } + else if (_bodyYawDelta != 0.0f) { + // attenuate body rotation speed + const float ROTATION_DECAY_TIMESCALE = 0.05f; + float attenuation = 1.0f - deltaTime / ROTATION_DECAY_TIMESCALE; + if (attenuation < 0.0f) { + attenuation = 0.0f; + } + _bodyYawDelta *= attenuation; + + float MINIMUM_ROTATION_RATE = 2.0f; + if (fabsf(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { + _bodyYawDelta = 0.0f; + } + } + + // update body orientation by movement inputs + setOrientation(getOrientation() * + glm::quat(glm::radians(glm::vec3(0.0f, _bodyYawDelta * deltaTime, 0.0f)))); + + } else { + // comfort mode.... + _bodyYawDelta = 0.0f; + + static quint64 lastPulse = 0; + quint64 now = usecTimestampNow(); + quint64 COMFORT_MODE_PULSE_TIMING = USECS_PER_SECOND / 2; // turn once per second + + float driveLeft = _driveKeys[ROT_LEFT]; + float driveRight= _driveKeys[ROT_RIGHT]; + + if ((driveLeft != 0.0f || driveRight != 0.0f) && (now - lastPulse > COMFORT_MODE_PULSE_TIMING)) { + lastPulse = now; + + const float SNAP_TURN_DELTA = 15.0f; // degrees + float direction = (driveLeft - driveRight) < 0.0f ? -1.0f : 1.0f; + float turnAmount = direction * SNAP_TURN_DELTA; + + // update body orientation by movement inputs + setOrientation(getOrientation() * + glm::quat(glm::radians(glm::vec3(0.0f, turnAmount, 0.0f)))); - float MINIMUM_ROTATION_RATE = 2.0f; - if (fabsf(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { - _bodyYawDelta = 0.0f; } } getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime); - // update body orientation by movement inputs - setOrientation(getOrientation() * - glm::quat(glm::radians(glm::vec3(0.0f, _bodyYawDelta * deltaTime, 0.0f)))); if (qApp->getAvatarUpdater()->isHMDMode()) { glm::quat orientation = glm::quat_cast(getSensorToWorldMatrix()) * getHMDSensorOrientation(); From c468cabe7e75cc7322f2fff42c83686e3d18d5cb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 13 Oct 2015 15:12:01 -0700 Subject: [PATCH 10/16] Fix crash when atp url is empty --- libraries/networking/src/AssetResourceRequest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/AssetResourceRequest.cpp b/libraries/networking/src/AssetResourceRequest.cpp index ecbe80cddb..eba9e45e5c 100644 --- a/libraries/networking/src/AssetResourceRequest.cpp +++ b/libraries/networking/src/AssetResourceRequest.cpp @@ -24,7 +24,7 @@ void AssetResourceRequest::doSend() { // Make request to atp auto assetClient = DependencyManager::get(); auto parts = _url.path().split(".", QString::SkipEmptyParts); - auto hash = parts[0]; + auto hash = parts.length() > 0 ? parts[0] : ""; auto extension = parts.length() > 1 ? parts[1] : ""; if (hash.length() != SHA256_HASH_HEX_LENGTH) { From 8a2e23cae4909057bb1bf2c7c9505b704dcaebe6 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 13 Oct 2015 16:20:52 -0700 Subject: [PATCH 11/16] CR feedback --- interface/src/avatar/MyAvatar.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 55690c98f1..aa579b670f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1530,8 +1530,7 @@ void MyAvatar::updateOrientation(float deltaTime) { blend = 1.0f; } _bodyYawDelta = (1.0f - blend) * _bodyYawDelta + blend * targetSpeed; - } - else if (_bodyYawDelta != 0.0f) { + } else if (_bodyYawDelta != 0.0f) { // attenuate body rotation speed const float ROTATION_DECAY_TIMESCALE = 0.05f; float attenuation = 1.0f - deltaTime / ROTATION_DECAY_TIMESCALE; @@ -1551,12 +1550,14 @@ void MyAvatar::updateOrientation(float deltaTime) { glm::quat(glm::radians(glm::vec3(0.0f, _bodyYawDelta * deltaTime, 0.0f)))); } else { - // comfort mode.... + // Comfort Mode: If you press any of the left/right rotation drive keys or input, you'll + // get an instantaneous 15 degree turn. If you keep holding the key down you'll get another + // snap turn every half second. _bodyYawDelta = 0.0f; static quint64 lastPulse = 0; quint64 now = usecTimestampNow(); - quint64 COMFORT_MODE_PULSE_TIMING = USECS_PER_SECOND / 2; // turn once per second + quint64 COMFORT_MODE_PULSE_TIMING = USECS_PER_SECOND / 2; // turn once per half second float driveLeft = _driveKeys[ROT_LEFT]; float driveRight= _driveKeys[ROT_RIGHT]; From 619fce0d7fa5720b863c62c86e0878d93d11664a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 14 Oct 2015 13:40:22 -0700 Subject: [PATCH 12/16] Fixing namespace usage in input-plugins --- .../src/input-plugins/Joystick.cpp | 334 +++++++++--------- .../src/input-plugins/Joystick.h | 146 ++++---- .../src/input-plugins/StandardController.cpp | 242 ++++++------- .../src/input-plugins/StandardController.h | 96 ++--- .../src/input-plugins/StandardControls.h | 114 +++--- 5 files changed, 468 insertions(+), 464 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/Joystick.cpp b/libraries/input-plugins/src/input-plugins/Joystick.cpp index 5c6f43c604..684b9e80d5 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.cpp +++ b/libraries/input-plugins/src/input-plugins/Joystick.cpp @@ -1,167 +1,167 @@ -// -// Joystick.cpp -// input-plugins/src/input-plugins -// -// Created by Stephen Birarda on 2014-09-23. -// Copyright 2014 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 -// - -#include - -#include - -#include "Joystick.h" - -#include "StandardControls.h" - -const float CONTROLLER_THRESHOLD = 0.3f; - -#ifdef HAVE_SDL2 -const float MAX_AXIS = 32768.0f; - -Joystick::Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController) : - InputDevice(name), - _sdlGameController(sdlGameController), - _sdlJoystick(SDL_GameControllerGetJoystick(_sdlGameController)), - _instanceId(instanceId) -{ - -} - -#endif - -Joystick::~Joystick() { - closeJoystick(); -} - -void Joystick::closeJoystick() { -#ifdef HAVE_SDL2 - SDL_GameControllerClose(_sdlGameController); -#endif -} - -void Joystick::update(float deltaTime, bool jointsCaptured) { - for (auto axisState : _axisStateMap) { - if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) { - _axisStateMap[axisState.first] = 0.0f; - } - } -} - -void Joystick::focusOutEvent() { - _axisStateMap.clear(); - _buttonPressedMap.clear(); -}; - -#ifdef HAVE_SDL2 - -void Joystick::handleAxisEvent(const SDL_ControllerAxisEvent& event) { - SDL_GameControllerAxis axis = (SDL_GameControllerAxis) event.axis; - _axisStateMap[makeInput((Controllers::StandardAxisChannel)axis).getChannel()] = (float)event.value / MAX_AXIS; -} - -void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) { - auto input = makeInput((Controllers::StandardButtonChannel)event.button); - bool newValue = event.state == SDL_PRESSED; - if (newValue) { - _buttonPressedMap.insert(input.getChannel()); - } else { - _buttonPressedMap.erase(input.getChannel()); - } -} - -#endif - - -void Joystick::registerToUserInputMapper(UserInputMapper& mapper) { - // Grab the current free device ID - _deviceID = mapper.getFreeDeviceID(); - - auto proxy = std::make_shared(_name); - proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; - proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; - proxy->getAvailabeInputs = [this] () -> QVector { - QVector availableInputs; - // Buttons - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::A), "A")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::B), "B")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::X), "X")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::Y), "Y")); - - // DPad - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DU), "DU")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DD), "DD")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DL), "DL")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DR), "DR")); - - // Bumpers - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LB), "LB")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RB), "RB")); - - // Stick press - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LS), "LS")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RS), "RS")); - - // Center buttons - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::START), "Start")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::BACK), "Back")); - - // Analog sticks - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LY), "LY")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LX), "LX")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RY), "RY")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RX), "RX")); - - // Triggers - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LT), "LT")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RT), "RT")); - - // Aliases, PlayStation style names - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LB), "L1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RB), "R1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LT), "L2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RT), "R2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LS), "L3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RS), "R3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::BACK), "Select")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::A), "Cross")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::B), "Circle")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::X), "Square")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::Y), "Triangle")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DU), "Up")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DD), "Down")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DL), "Left")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DR), "Right")); - - return availableInputs; - }; - proxy->resetDeviceBindings = [this, &mapper] () -> bool { - mapper.removeAllInputChannelsForDevice(_deviceID); - this->assignDefaultInputMapping(mapper); - return true; - }; - mapper.registerDevice(_deviceID, proxy); -} - -void Joystick::assignDefaultInputMapping(UserInputMapper& mapper) { -#ifdef HAVE_SDL2 - const float JOYSTICK_MOVE_SPEED = 1.0f; - const float DPAD_MOVE_SPEED = 0.5f; - const float JOYSTICK_YAW_SPEED = 0.5f; - const float JOYSTICK_PITCH_SPEED = 0.25f; - const float BOOM_SPEED = 0.1f; - -#endif -} - -UserInputMapper::Input Joystick::makeInput(Controllers::StandardButtonChannel button) { - return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); -} - -UserInputMapper::Input Joystick::makeInput(Controllers::StandardAxisChannel axis) { - return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); -} - +// +// Joystick.cpp +// input-plugins/src/input-plugins +// +// Created by Stephen Birarda on 2014-09-23. +// Copyright 2014 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 +// + +#include + +#include + +#include "Joystick.h" + +#include "StandardControls.h" + +const float CONTROLLER_THRESHOLD = 0.3f; + +#ifdef HAVE_SDL2 +const float MAX_AXIS = 32768.0f; + +Joystick::Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController) : + InputDevice(name), + _sdlGameController(sdlGameController), + _sdlJoystick(SDL_GameControllerGetJoystick(_sdlGameController)), + _instanceId(instanceId) +{ + +} + +#endif + +Joystick::~Joystick() { + closeJoystick(); +} + +void Joystick::closeJoystick() { +#ifdef HAVE_SDL2 + SDL_GameControllerClose(_sdlGameController); +#endif +} + +void Joystick::update(float deltaTime, bool jointsCaptured) { + for (auto axisState : _axisStateMap) { + if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) { + _axisStateMap[axisState.first] = 0.0f; + } + } +} + +void Joystick::focusOutEvent() { + _axisStateMap.clear(); + _buttonPressedMap.clear(); +}; + +#ifdef HAVE_SDL2 + +void Joystick::handleAxisEvent(const SDL_ControllerAxisEvent& event) { + SDL_GameControllerAxis axis = (SDL_GameControllerAxis) event.axis; + _axisStateMap[makeInput((controller::StandardAxisChannel)axis).getChannel()] = (float)event.value / MAX_AXIS; +} + +void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) { + auto input = makeInput((controller::StandardButtonChannel)event.button); + bool newValue = event.state == SDL_PRESSED; + if (newValue) { + _buttonPressedMap.insert(input.getChannel()); + } else { + _buttonPressedMap.erase(input.getChannel()); + } +} + +#endif + + +void Joystick::registerToUserInputMapper(UserInputMapper& mapper) { + // Grab the current free device ID + _deviceID = mapper.getFreeDeviceID(); + + auto proxy = std::make_shared(_name); + proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; + proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; + proxy->getAvailabeInputs = [this] () -> QVector { + QVector availableInputs; + // Buttons + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "A")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "B")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "X")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Y")); + + // DPad + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "DU")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "DD")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "DL")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "DR")); + + // Bumpers + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "LB")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "RB")); + + // Stick press + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "LS")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "RS")); + + // Center buttons + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::START), "Start")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Back")); + + // Analog sticks + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LY), "LY")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LX), "LX")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RY), "RY")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RX), "RX")); + + // Triggers + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "LT")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "RT")); + + // Aliases, PlayStation style names + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "L1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "R1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "L2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "R2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "L3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "R3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Select")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "Cross")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "Circle")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "Square")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Triangle")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "Up")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "Down")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "Left")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "Right")); + + return availableInputs; + }; + proxy->resetDeviceBindings = [this, &mapper] () -> bool { + mapper.removeAllInputChannelsForDevice(_deviceID); + this->assignDefaultInputMapping(mapper); + return true; + }; + mapper.registerDevice(_deviceID, proxy); +} + +void Joystick::assignDefaultInputMapping(UserInputMapper& mapper) { +#ifdef HAVE_SDL2 + const float JOYSTICK_MOVE_SPEED = 1.0f; + const float DPAD_MOVE_SPEED = 0.5f; + const float JOYSTICK_YAW_SPEED = 0.5f; + const float JOYSTICK_PITCH_SPEED = 0.25f; + const float BOOM_SPEED = 0.1f; + +#endif +} + +UserInputMapper::Input Joystick::makeInput(controller::StandardButtonChannel button) { + return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); +} + +UserInputMapper::Input Joystick::makeInput(controller::StandardAxisChannel axis) { + return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); +} + diff --git a/libraries/input-plugins/src/input-plugins/Joystick.h b/libraries/input-plugins/src/input-plugins/Joystick.h index 70949a8b83..2a7a11d230 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.h +++ b/libraries/input-plugins/src/input-plugins/Joystick.h @@ -1,73 +1,73 @@ -// -// Joystick.h -// input-plugins/src/input-plugins -// -// Created by Stephen Birarda on 2014-09-23. -// Copyright 2014 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 -// - -#ifndef hifi_Joystick_h -#define hifi_Joystick_h - -#include -#include - -#ifdef HAVE_SDL2 -#include -#undef main -#endif - -#include "InputDevice.h" -#include "StandardControls.h" - -class Joystick : public QObject, public InputDevice { - Q_OBJECT - Q_PROPERTY(QString name READ getName) - -#ifdef HAVE_SDL2 - Q_PROPERTY(int instanceId READ getInstanceId) -#endif - -public: - - const QString& getName() const { return _name; } - - // Device functions - virtual void registerToUserInputMapper(UserInputMapper& mapper) override; - virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; - virtual void update(float deltaTime, bool jointsCaptured) override; - virtual void focusOutEvent() override; - - Joystick() : InputDevice("Joystick") {} - ~Joystick(); - - UserInputMapper::Input makeInput(Controllers::StandardButtonChannel button); - UserInputMapper::Input makeInput(Controllers::StandardAxisChannel axis); - -#ifdef HAVE_SDL2 - Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController); -#endif - - void closeJoystick(); - -#ifdef HAVE_SDL2 - void handleAxisEvent(const SDL_ControllerAxisEvent& event); - void handleButtonEvent(const SDL_ControllerButtonEvent& event); -#endif - -#ifdef HAVE_SDL2 - int getInstanceId() const { return _instanceId; } -#endif - -private: -#ifdef HAVE_SDL2 - SDL_GameController* _sdlGameController; - SDL_Joystick* _sdlJoystick; - SDL_JoystickID _instanceId; -#endif -}; - -#endif // hifi_Joystick_h +// +// Joystick.h +// input-plugins/src/input-plugins +// +// Created by Stephen Birarda on 2014-09-23. +// Copyright 2014 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 +// + +#ifndef hifi_Joystick_h +#define hifi_Joystick_h + +#include +#include + +#ifdef HAVE_SDL2 +#include +#undef main +#endif + +#include "InputDevice.h" +#include "StandardControls.h" + +class Joystick : public QObject, public InputDevice { + Q_OBJECT + Q_PROPERTY(QString name READ getName) + +#ifdef HAVE_SDL2 + Q_PROPERTY(int instanceId READ getInstanceId) +#endif + +public: + + const QString& getName() const { return _name; } + + // Device functions + virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; + virtual void update(float deltaTime, bool jointsCaptured) override; + virtual void focusOutEvent() override; + + Joystick() : InputDevice("Joystick") {} + ~Joystick(); + + UserInputMapper::Input makeInput(controller::StandardButtonChannel button); + UserInputMapper::Input makeInput(controller::StandardAxisChannel axis); + +#ifdef HAVE_SDL2 + Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController); +#endif + + void closeJoystick(); + +#ifdef HAVE_SDL2 + void handleAxisEvent(const SDL_ControllerAxisEvent& event); + void handleButtonEvent(const SDL_ControllerButtonEvent& event); +#endif + +#ifdef HAVE_SDL2 + int getInstanceId() const { return _instanceId; } +#endif + +private: +#ifdef HAVE_SDL2 + SDL_GameController* _sdlGameController; + SDL_Joystick* _sdlJoystick; + SDL_JoystickID _instanceId; +#endif +}; + +#endif // hifi_Joystick_h diff --git a/libraries/input-plugins/src/input-plugins/StandardController.cpp b/libraries/input-plugins/src/input-plugins/StandardController.cpp index 988714a962..5460e22c96 100644 --- a/libraries/input-plugins/src/input-plugins/StandardController.cpp +++ b/libraries/input-plugins/src/input-plugins/StandardController.cpp @@ -1,121 +1,121 @@ -// -// StandardController.cpp -// input-plugins/src/input-plugins -// -// Created by Brad Hefta-Gaub on 2015-10-11. -// Copyright 2015 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 -// - -#include - -#include - -#include "StandardController.h" - -const float CONTROLLER_THRESHOLD = 0.3f; - -StandardController::~StandardController() { -} - -void StandardController::update(float deltaTime, bool jointsCaptured) { -} - -void StandardController::focusOutEvent() { - _axisStateMap.clear(); - _buttonPressedMap.clear(); -}; - -void StandardController::registerToUserInputMapper(UserInputMapper& mapper) { - // Grab the current free device ID - _deviceID = mapper.getStandardDeviceID(); - - auto proxy = std::make_shared(_name); - proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; - proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; - proxy->getAvailabeInputs = [this] () -> QVector { - QVector availableInputs; - // Buttons - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::A), "A")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::B), "B")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::X), "X")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::Y), "Y")); - - // DPad - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DU), "DU")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DD), "DD")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DL), "DL")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DR), "DR")); - - // Bumpers - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LB), "LB")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RB), "RB")); - - // Stick press - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LS), "LS")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RS), "RS")); - - // Center buttons - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::START), "Start")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::BACK), "Back")); - - // Analog sticks - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LY), "LY")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LX), "LX")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RY), "RY")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RX), "RX")); - - // Triggers - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LT), "LT")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RT), "RT")); - - // Poses - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LeftPose), "LeftPose")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RightPose), "RightPose")); - - // Aliases, PlayStation style names - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LB), "L1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RB), "R1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LT), "L2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RT), "R2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::LS), "L3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::RS), "R3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::BACK), "Select")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::A), "Cross")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::B), "Circle")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::X), "Square")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::Y), "Triangle")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DU), "Up")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DD), "Down")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DL), "Left")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Controllers::DR), "Right")); - - - return availableInputs; - }; - - proxy->resetDeviceBindings = [this, &mapper] () -> bool { - mapper.removeAllInputChannelsForDevice(_deviceID); - this->assignDefaultInputMapping(mapper); - return true; - }; - - mapper.registerStandardDevice(proxy); -} - -void StandardController::assignDefaultInputMapping(UserInputMapper& mapper) { -} - -UserInputMapper::Input StandardController::makeInput(Controllers::StandardButtonChannel button) { - return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); -} - -UserInputMapper::Input StandardController::makeInput(Controllers::StandardAxisChannel axis) { - return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); -} - -UserInputMapper::Input StandardController::makeInput(Controllers::StandardPoseChannel pose) { - return UserInputMapper::Input(_deviceID, pose, UserInputMapper::ChannelType::POSE); -} +// +// StandardController.cpp +// input-plugins/src/input-plugins +// +// Created by Brad Hefta-Gaub on 2015-10-11. +// Copyright 2015 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 +// + +#include + +#include + +#include "StandardController.h" + +const float CONTROLLER_THRESHOLD = 0.3f; + +StandardController::~StandardController() { +} + +void StandardController::update(float deltaTime, bool jointsCaptured) { +} + +void StandardController::focusOutEvent() { + _axisStateMap.clear(); + _buttonPressedMap.clear(); +}; + +void StandardController::registerToUserInputMapper(UserInputMapper& mapper) { + // Grab the current free device ID + _deviceID = mapper.getStandardDeviceID(); + + auto proxy = std::make_shared(_name); + proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; + proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; + proxy->getAvailabeInputs = [this] () -> QVector { + QVector availableInputs; + // Buttons + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "A")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "B")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "X")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Y")); + + // DPad + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "DU")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "DD")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "DL")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "DR")); + + // Bumpers + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "LB")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "RB")); + + // Stick press + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "LS")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "RS")); + + // Center buttons + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::START), "Start")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Back")); + + // Analog sticks + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LY), "LY")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LX), "LX")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RY), "RY")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RX), "RX")); + + // Triggers + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "LT")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "RT")); + + // Poses + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LEFT), "LeftPose")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RIGHT), "RightPose")); + + // Aliases, PlayStation style names + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "L1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "R1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "L2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "R2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "L3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "R3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Select")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "Cross")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "Circle")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "Square")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Triangle")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "Up")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "Down")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "Left")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "Right")); + + + return availableInputs; + }; + + proxy->resetDeviceBindings = [this, &mapper] () -> bool { + mapper.removeAllInputChannelsForDevice(_deviceID); + this->assignDefaultInputMapping(mapper); + return true; + }; + + mapper.registerStandardDevice(proxy); +} + +void StandardController::assignDefaultInputMapping(UserInputMapper& mapper) { +} + +UserInputMapper::Input StandardController::makeInput(controller::StandardButtonChannel button) { + return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); +} + +UserInputMapper::Input StandardController::makeInput(controller::StandardAxisChannel axis) { + return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); +} + +UserInputMapper::Input StandardController::makeInput(controller::StandardPoseChannel pose) { + return UserInputMapper::Input(_deviceID, pose, UserInputMapper::ChannelType::POSE); +} diff --git a/libraries/input-plugins/src/input-plugins/StandardController.h b/libraries/input-plugins/src/input-plugins/StandardController.h index fa660e15b8..ad1329d5ed 100644 --- a/libraries/input-plugins/src/input-plugins/StandardController.h +++ b/libraries/input-plugins/src/input-plugins/StandardController.h @@ -1,48 +1,48 @@ -// -// StandardController.h -// input-plugins/src/input-plugins -// -// Created by Brad Hefta-Gaub on 2015-10-11. -// Copyright 2015 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 -// - -#ifndef hifi_StandardController_h -#define hifi_StandardController_h - -#include -#include - -#include "InputDevice.h" - -#include "StandardControls.h" - -typedef std::shared_ptr StandardControllerPointer; - -class StandardController : public QObject, public InputDevice { - Q_OBJECT - Q_PROPERTY(QString name READ getName) - -public: - - const QString& getName() const { return _name; } - - // Device functions - virtual void registerToUserInputMapper(UserInputMapper& mapper) override; - virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; - virtual void update(float deltaTime, bool jointsCaptured) override; - virtual void focusOutEvent() override; - - StandardController() : InputDevice("Standard") {} - ~StandardController(); - - UserInputMapper::Input makeInput(Controllers::StandardButtonChannel button); - UserInputMapper::Input makeInput(Controllers::StandardAxisChannel axis); - UserInputMapper::Input makeInput(Controllers::StandardPoseChannel pose); - -private: -}; - -#endif // hifi_StandardController_h +// +// StandardController.h +// input-plugins/src/input-plugins +// +// Created by Brad Hefta-Gaub on 2015-10-11. +// Copyright 2015 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 +// + +#ifndef hifi_StandardController_h +#define hifi_StandardController_h + +#include +#include + +#include "InputDevice.h" + +#include "StandardControls.h" + +typedef std::shared_ptr StandardControllerPointer; + +class StandardController : public QObject, public InputDevice { + Q_OBJECT + Q_PROPERTY(QString name READ getName) + +public: + + const QString& getName() const { return _name; } + + // Device functions + virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; + virtual void update(float deltaTime, bool jointsCaptured) override; + virtual void focusOutEvent() override; + + StandardController() : InputDevice("Standard") {} + ~StandardController(); + + UserInputMapper::Input makeInput(controller::StandardButtonChannel button); + UserInputMapper::Input makeInput(controller::StandardAxisChannel axis); + UserInputMapper::Input makeInput(controller::StandardPoseChannel pose); + +private: +}; + +#endif // hifi_StandardController_h diff --git a/libraries/input-plugins/src/input-plugins/StandardControls.h b/libraries/input-plugins/src/input-plugins/StandardControls.h index 9b79bbdae1..e5943ff780 100644 --- a/libraries/input-plugins/src/input-plugins/StandardControls.h +++ b/libraries/input-plugins/src/input-plugins/StandardControls.h @@ -1,55 +1,59 @@ -// -// Created by Bradley Austin Davis 2015/10/09 -// Copyright 2015 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 -// -#pragma once - -namespace Controllers { - - // Needs to match order and values of SDL_GameControllerButton - enum StandardButtonChannel { - // Button quad - A = 0, - B, - X, - Y, - // Center buttons - BACK, - GUIDE, - START, - // Stick press - LS, - RS, - // Bumper press - LB, - RB, - // DPad - DU, - DD, - DL, - DR - }; - - // Needs to match order and values of SDL_GameControllerAxis - enum StandardAxisChannel { - // Left Analog stick - LX = 0, - LY, - // Right Analog stick - RX, - RY, - // Triggers - LT, - RT - }; - - // No correlation to SDL - enum StandardPoseChannel { - LeftPose = 0, - RightPose - }; - -} +// +// Created by Bradley Austin Davis 2015/10/09 +// Copyright 2015 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 +// +#pragma once + +namespace controller { + + // Needs to match order and values of SDL_GameControllerButton + enum StandardButtonChannel { + // Button quad + A = 0, + B, + X, + Y, + // Center buttons + BACK, + GUIDE, + START, + // Stick press + LS, + RS, + // Bumper press + LB, + RB, + // DPad + DU, + DD, + DL, + DR, + NUM_STANDARD_BUTTONS + }; + + // Needs to match order and values of SDL_GameControllerAxis + enum StandardAxisChannel { + // Left Analog stick + LX = 0, + LY, + // Right Analog stick + RX, + RY, + // Triggers + LT, + RT, + NUM_STANDARD_AXES + }; + + // No correlation to SDL + enum StandardPoseChannel { + LEFT = 0, + RIGHT, + HEAD, + NUM_STANDARD_POSES + }; + +} From 0063f9ae1d9e10fce4ef4e25fe5e9cf477c42340 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 14 Oct 2015 15:16:54 -0700 Subject: [PATCH 13/16] Merging old and new controller interfaces --- interface/CMakeLists.txt | 5 +- interface/src/Application.cpp | 6 +- interface/src/Application.h | 2 +- interface/src/devices/3DConnexionClient.h | 2 +- .../ControllerScriptingInterface.cpp | 140 ++-- .../scripting/ControllerScriptingInterface.h | 135 ++-- interface/src/ui/ApplicationCompositor.cpp | 2 +- libraries/controllers/CMakeLists.txt | 2 +- .../controllers/src/controllers/Endpoint.h | 2 +- .../src/controllers}/InputDevice.cpp | 0 .../src/controllers}/InputDevice.h | 0 .../NewControllerScriptingInterface.h | 89 --- ...ngInterface.cpp => ScriptingInterface.cpp} | 123 ++- .../src/controllers/ScriptingInterface.h | 138 ++++ .../src/controllers}/StandardController.cpp | 242 +++--- .../src/controllers}/StandardController.h | 96 +-- .../src/controllers}/StandardControls.h | 118 +-- .../src/controllers}/UserInputMapper.cpp | 736 +++++++++--------- .../src/controllers}/UserInputMapper.h | 56 +- .../controllers/impl/MappingBuilderProxy.cpp | 2 +- .../controllers/impl/MappingBuilderProxy.h | 8 +- .../controllers/impl/RouteBuilderProxy.cpp | 2 +- .../src/controllers/impl/RouteBuilderProxy.h | 8 +- libraries/entities-renderer/CMakeLists.txt | 2 +- libraries/input-plugins/CMakeLists.txt | 2 +- .../src/input-plugins/InputPlugin.cpp | 2 +- .../src/input-plugins/Joystick.cpp | 7 +- .../src/input-plugins/Joystick.h | 4 +- .../src/input-plugins/KeyboardMouseDevice.h | 2 +- .../src/input-plugins/SDL2Manager.h | 4 +- .../src/input-plugins/SixenseManager.h | 3 +- .../src/input-plugins/ViveControllerManager.h | 2 +- libraries/script-engine/CMakeLists.txt | 2 +- .../AbstractControllerScriptingInterface.h | 125 --- .../src/AbstractScriptingServicesInterface.h | 7 +- libraries/script-engine/src/ScriptEngine.cpp | 21 +- libraries/script-engine/src/ScriptEngine.h | 7 +- tests/controllers/qml/content.qml | 43 +- .../controllers/qml/controls/AnalogButton.qml | 2 +- .../controllers/qml/controls/AnalogStick.qml | 4 +- .../qml/controls/ScrollingGraph.qml | 2 +- .../controllers/qml/controls/ToggleButton.qml | 2 +- tests/controllers/src/main.cpp | 30 +- 43 files changed, 1086 insertions(+), 1101 deletions(-) rename libraries/{input-plugins/src/input-plugins => controllers/src/controllers}/InputDevice.cpp (100%) rename libraries/{input-plugins/src/input-plugins => controllers/src/controllers}/InputDevice.h (100%) delete mode 100644 libraries/controllers/src/controllers/NewControllerScriptingInterface.h rename libraries/controllers/src/controllers/{NewControllerScriptingInterface.cpp => ScriptingInterface.cpp} (77%) create mode 100644 libraries/controllers/src/controllers/ScriptingInterface.h rename libraries/{input-plugins/src/input-plugins => controllers/src/controllers}/StandardController.cpp (98%) rename libraries/{input-plugins/src/input-plugins => controllers/src/controllers}/StandardController.h (96%) rename libraries/{input-plugins/src/input-plugins => controllers/src/controllers}/StandardControls.h (95%) rename libraries/{input-plugins/src/input-plugins => controllers/src/controllers}/UserInputMapper.cpp (93%) mode change 100755 => 100644 rename libraries/{input-plugins/src/input-plugins => controllers/src/controllers}/UserInputMapper.h (96%) mode change 100755 => 100644 delete mode 100644 libraries/script-engine/src/AbstractControllerScriptingInterface.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 95de0649ad..43db834c3c 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -98,9 +98,8 @@ endif() # link required hifi libraries link_hifi_libraries(shared octree environment gpu procedural model render fbx networking model-networking entities avatars audio audio-client animation script-engine physics - render-utils entities-renderer ui auto-updater - plugins display-plugins input-plugins - controllers) + render-utils entities-renderer ui auto-updater + controllers plugins display-plugins input-plugins ) target_bullet() target_glew() diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e0e5003830..77f353a3ff 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -60,7 +60,7 @@ #include #include #include // this should probably be removed -#include +#include #include #include #include @@ -614,7 +614,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // Setup the userInputMapper with the actions auto userInputMapper = DependencyManager::get(); - connect(userInputMapper.data(), &UserInputMapper::actionEvent, &_controllerScriptingInterface, &AbstractControllerScriptingInterface::actionEvent); + connect(userInputMapper.data(), &UserInputMapper::actionEvent, &_controllerScriptingInterface, &ControllerScriptingInterface::actionEvent); connect(userInputMapper.data(), &UserInputMapper::actionEvent, [this](int action, float state) { if (state) { switch (action) { @@ -2708,7 +2708,7 @@ void Application::update(float deltaTime) { } // Dispatch input events - _controllerScriptingInterface.updateInputControllers(); + _controllerScriptingInterface.update(); // Transfer the user inputs to the driveKeys myAvatar->clearDriveKeys(); diff --git a/interface/src/Application.h b/interface/src/Application.h index dc714ad82a..61421c34d6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -161,7 +161,7 @@ public: ToolWindow* getToolWindow() { return _toolWindow ; } - virtual AbstractControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } + virtual controller::ScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine); QImage renderAvatarBillboard(RenderArgs* renderArgs); diff --git a/interface/src/devices/3DConnexionClient.h b/interface/src/devices/3DConnexionClient.h index cdf8e1e2a1..bddb86a857 100755 --- a/interface/src/devices/3DConnexionClient.h +++ b/interface/src/devices/3DConnexionClient.h @@ -13,7 +13,7 @@ #include #include -#include +#include #include "InterfaceLogging.h" diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 54aa72da6b..1a212fbea9 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -9,21 +9,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ControllerScriptingInterface.h" + #include #include #include #include -#include - #include "Application.h" #include "devices/MotionTracker.h" -#include "ControllerScriptingInterface.h" // TODO: this needs to be removed, as well as any related controller-specific information #include - ControllerScriptingInterface::ControllerScriptingInterface() : _mouseCaptured(false), _touchCaptured(false), @@ -34,7 +32,6 @@ ControllerScriptingInterface::ControllerScriptingInterface() : } ControllerScriptingInterface::~ControllerScriptingInterface() { - delete _newControllerScriptingInterface; } @@ -126,13 +123,6 @@ void ControllerScriptingInterface::registerControllerTypes(ScriptEngine* engine) qScriptRegisterMetaType(engine, inputChannelToScriptValue, inputChannelFromScriptValue); qScriptRegisterMetaType(engine, inputToScriptValue, inputFromScriptValue); qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue); - - wireUpControllers(engine); - - // hack in the new controller scripting interface... - _newControllerScriptingInterface = new controller::NewControllerScriptingInterface(); - engine->registerGlobalObject("NewControllers", _newControllerScriptingInterface); - } void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) { @@ -192,6 +182,7 @@ const PalmData* ControllerScriptingInterface::getActivePalm(int palmIndex) const return NULL; } +/* bool ControllerScriptingInterface::isPrimaryButtonPressed() const { const PalmData* primaryPalm = getPrimaryPalm(); if (primaryPalm) { @@ -345,6 +336,7 @@ glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex } return glm::vec3(0); // bad index } +*/ bool ControllerScriptingInterface::isKeyCaptured(QKeyEvent* event) const { return isKeyCaptured(KeyEvent(*event)); @@ -395,96 +387,49 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { return qApp->getUiSize(); } -QString ControllerScriptingInterface::sanatizeName(const QString& name) { - QString cleanName { name }; - cleanName.remove(QRegularExpression{"[\\(\\)\\.\\s]"}); - return cleanName; -} - -void ControllerScriptingInterface::wireUpControllers(ScriptEngine* engine) { - - // Controller.Standard.* - auto standardDevice = DependencyManager::get()->getStandardDevice(); - if (standardDevice) { - auto deviceName = sanatizeName(standardDevice->getName()); - auto deviceInputs = standardDevice->getAvailabeInputs(); - for (const auto& inputMapping : deviceInputs) { - auto input = inputMapping.first; - auto inputName = sanatizeName(inputMapping.second); - QString deviceInputName{ "Controller." + deviceName + "." + inputName }; - engine->registerValue(deviceInputName, input.getID()); - } - } - - // Controller.Hardware.* - auto devices = DependencyManager::get()->getDevices(); - for(const auto& deviceMapping : devices) { - auto device = deviceMapping.second.get(); - auto deviceName = sanatizeName(device->getName()); - auto deviceInputs = device->getAvailabeInputs(); - for (const auto& inputMapping : deviceInputs) { - auto input = inputMapping.first; - auto inputName = sanatizeName(inputMapping.second); - QString deviceInputName { "Controller.Hardware." + deviceName + "." + inputName }; - engine->registerValue(deviceInputName, input.getID()); - } - } - - // Controller.Actions.* - auto actionNames = DependencyManager::get()->getActionNames(); - int actionNumber = 0; - for (const auto& actionName : actionNames) { - QString safeActionName { "Controller.Actions." + sanatizeName(actionName) }; - engine->registerValue(safeActionName, actionNumber); - actionNumber++; - } -} - -AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { +controller::InputController::Pointer ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { // This is where we retreive the Device Tracker category and then the sub tracker within it - //TODO C++11 auto icIt = _inputControllers.find(0); - InputControllerMap::iterator icIt = _inputControllers.find(0); - + auto icIt = _inputControllers.find(0); if (icIt != _inputControllers.end()) { return (*icIt).second; - } else { + } - // Look for device - DeviceTracker::ID deviceID = DeviceTracker::getDeviceID(deviceName.toStdString()); - if (deviceID < 0) { - deviceID = 0; - } - // TODO in this current implementation, we just pick the device assuming there is one (normally the Leapmotion) - // in the near future we need to change that to a real mapping between the devices and the deviceName - // ALso we need to expand the spec so we can fall back on the "default" controller per categories - if (deviceID >= 0) { - // TODO here again the assumption it's the LeapMotion and so it's a MOtionTracker, this would need to be changed to support different types of devices - MotionTracker* motionTracker = dynamic_cast< MotionTracker* > (DeviceTracker::getDevice(deviceID)); - if (motionTracker) { - MotionTracker::Index trackerID = motionTracker->findJointIndex(tracker.toStdString()); - if (trackerID >= 0) { - AbstractInputController* inputController = new InputController(deviceID, trackerID, this); + // Look for device + DeviceTracker::ID deviceID = DeviceTracker::getDeviceID(deviceName.toStdString()); + if (deviceID < 0) { + deviceID = 0; + } + // TODO in this current implementation, we just pick the device assuming there is one (normally the Leapmotion) + // in the near future we need to change that to a real mapping between the devices and the deviceName + // ALso we need to expand the spec so we can fall back on the "default" controller per categories - _inputControllers.insert(InputControllerMap::value_type(inputController->getKey(), inputController)); - - return inputController; - } + if (deviceID >= 0) { + // TODO here again the assumption it's the LeapMotion and so it's a MOtionTracker, this would need to be changed to support different types of devices + MotionTracker* motionTracker = dynamic_cast< MotionTracker* > (DeviceTracker::getDevice(deviceID)); + if (motionTracker) { + MotionTracker::Index trackerID = motionTracker->findJointIndex(tracker.toStdString()); + if (trackerID >= 0) { + controller::InputController::Pointer inputController = std::make_shared(deviceID, trackerID, this); + controller::InputController::Key key = inputController->getKey(); + _inputControllers.insert(InputControllerMap::value_type(inputController->getKey(), inputController)); + return inputController; } } - - return 0; } + + return controller::InputController::Pointer(); } -void ControllerScriptingInterface::releaseInputController(AbstractInputController* input) { +void ControllerScriptingInterface::releaseInputController(controller::InputController::Pointer input) { _inputControllers.erase(input->getKey()); } -void ControllerScriptingInterface::updateInputControllers() { - //TODO C++11 for (auto it = _inputControllers.begin(); it != _inputControllers.end(); it++) { - for (InputControllerMap::iterator it = _inputControllers.begin(); it != _inputControllers.end(); it++) { - (*it).second->update(); +void ControllerScriptingInterface::update() { + controller::ScriptingInterface::update(); + + for (auto entry : _inputControllers) { + entry.second->update(); } } @@ -545,7 +490,6 @@ QVector ControllerScriptingInterface::getActionNames() const { } InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) : - AbstractInputController(), _deviceTrackerId(deviceTrackerId), _subTrackerId(subTrackerId), _isActive(false) @@ -568,7 +512,7 @@ void InputController::update() { joint->getLocFrame().getRotation(_eventCache.locRotation); _isActive = true; - emit spatialEvent(_eventCache); + //emit spatialEvent(_eventCache); } } } @@ -580,3 +524,19 @@ const unsigned int INPUTCONTROLLER_KEY_DEVICE_MASK = 16; InputController::Key InputController::getKey() const { return (((_deviceTrackerId & INPUTCONTROLLER_KEY_DEVICE_MASK) << INPUTCONTROLLER_KEY_DEVICE_OFFSET) | _subTrackerId); } + + +void ControllerScriptingInterface::emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); } +void ControllerScriptingInterface::emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); } + +void ControllerScriptingInterface::emitMouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { emit mouseMoveEvent(MouseEvent(*event, deviceID)); } +void ControllerScriptingInterface::emitMousePressEvent(QMouseEvent* event, unsigned int deviceID) { emit mousePressEvent(MouseEvent(*event, deviceID)); } +void ControllerScriptingInterface::emitMouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID) { emit mouseDoublePressEvent(MouseEvent(*event, deviceID)); } +void ControllerScriptingInterface::emitMouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { emit mouseReleaseEvent(MouseEvent(*event, deviceID)); } + +void ControllerScriptingInterface::emitTouchBeginEvent(const TouchEvent& event) { emit touchBeginEvent(event); } +void ControllerScriptingInterface::emitTouchEndEvent(const TouchEvent& event) { emit touchEndEvent(event); } +void ControllerScriptingInterface::emitTouchUpdateEvent(const TouchEvent& event) { emit touchUpdateEvent(event); } + +void ControllerScriptingInterface::emitWheelEvent(QWheelEvent* event) { emit wheelEvent(*event); } + diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index dfe87043cd..652bd640b1 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -14,15 +14,20 @@ #include -#include +#include +#include + +#include +#include +#include +#include +#include +#include +class ScriptEngine; -#include class PalmData; -namespace controller { - class NewControllerScriptingInterface; -} -class InputController : public AbstractInputController { +class InputController : public controller::InputController { Q_OBJECT public: @@ -53,30 +58,53 @@ signals: /// handles scripting of input controller commands from JS -class ControllerScriptingInterface : public AbstractControllerScriptingInterface { +class ControllerScriptingInterface : public controller::ScriptingInterface { Q_OBJECT + public: ControllerScriptingInterface(); ~ControllerScriptingInterface(); + Q_INVOKABLE QVector getAllActions(); + + Q_INVOKABLE bool addInputChannel(UserInputMapper::InputChannel inputChannel); + Q_INVOKABLE bool removeInputChannel(UserInputMapper::InputChannel inputChannel); + Q_INVOKABLE QVector getInputChannelsForAction(UserInputMapper::Action action); + + Q_INVOKABLE QVector getAvailableInputs(unsigned int device); + Q_INVOKABLE QVector getAllInputsForDevice(unsigned int device); + + Q_INVOKABLE QString getDeviceName(unsigned int device); + + Q_INVOKABLE float getActionValue(int action); + + Q_INVOKABLE void resetDevice(unsigned int device); + Q_INVOKABLE void resetAllDeviceBindings(); + Q_INVOKABLE int findDevice(QString name); + Q_INVOKABLE QVector getDeviceNames(); + + Q_INVOKABLE int findAction(QString actionName); + Q_INVOKABLE QVector getActionNames() const; + + virtual void registerControllerTypes(ScriptEngine* engine); - void emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); } - void emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); } + void emitKeyPressEvent(QKeyEvent* event); + void emitKeyReleaseEvent(QKeyEvent* event); void handleMetaEvent(HFMetaEvent* event); - void emitMouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mouseMoveEvent(MouseEvent(*event, deviceID)); } - void emitMousePressEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mousePressEvent(MouseEvent(*event, deviceID)); } - void emitMouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mouseDoublePressEvent(MouseEvent(*event, deviceID)); } - void emitMouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mouseReleaseEvent(MouseEvent(*event, deviceID)); } + void emitMouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0); + void emitMousePressEvent(QMouseEvent* event, unsigned int deviceID = 0); + void emitMouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID = 0); + void emitMouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0); - void emitTouchBeginEvent(const TouchEvent& event) { emit touchBeginEvent(event); } - void emitTouchEndEvent(const TouchEvent& event) { emit touchEndEvent(event); } - void emitTouchUpdateEvent(const TouchEvent& event) { emit touchUpdateEvent(event); } + void emitTouchBeginEvent(const TouchEvent& event); + void emitTouchEndEvent(const TouchEvent& event); + void emitTouchUpdateEvent(const TouchEvent& event); - void emitWheelEvent(QWheelEvent* event) { emit wheelEvent(*event); } + void emitWheelEvent(QWheelEvent* event); bool isKeyCaptured(QKeyEvent* event) const; bool isKeyCaptured(const KeyEvent& event) const; @@ -86,48 +114,10 @@ public: bool areActionsCaptured() const { return _actionsCaptured; } bool isJoystickCaptured(int joystickIndex) const; - void updateInputControllers(); + virtual void update() override; public slots: - Q_INVOKABLE virtual QVector getAllActions(); - - Q_INVOKABLE virtual bool addInputChannel(UserInputMapper::InputChannel inputChannel); - Q_INVOKABLE virtual bool removeInputChannel(UserInputMapper::InputChannel inputChannel); - Q_INVOKABLE virtual QVector getInputChannelsForAction(UserInputMapper::Action action); - - Q_INVOKABLE virtual QVector getAvailableInputs(unsigned int device); - Q_INVOKABLE virtual QVector getAllInputsForDevice(unsigned int device); - - Q_INVOKABLE virtual QString getDeviceName(unsigned int device); - - Q_INVOKABLE virtual float getActionValue(int action); - Q_INVOKABLE virtual void resetDevice(unsigned int device); - Q_INVOKABLE virtual void resetAllDeviceBindings(); - Q_INVOKABLE virtual int findDevice(QString name); - Q_INVOKABLE virtual QVector getDeviceNames(); - - Q_INVOKABLE virtual int findAction(QString actionName); - Q_INVOKABLE virtual QVector getActionNames() const; - - virtual bool isPrimaryButtonPressed() const; - virtual glm::vec2 getPrimaryJoystickPosition() const; - - virtual int getNumberOfButtons() const; - virtual bool isButtonPressed(int buttonIndex) const; - - virtual int getNumberOfTriggers() const; - virtual float getTriggerValue(int triggerIndex) const; - - virtual int getNumberOfJoysticks() const; - virtual glm::vec2 getJoystickPosition(int joystickIndex) const; - - virtual int getNumberOfSpatialControls() const; - virtual glm::vec3 getSpatialControlPosition(int controlIndex) const; - virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const; - virtual glm::vec3 getSpatialControlNormal(int controlIndex) const; - virtual glm::quat getSpatialControlRawRotation(int controlIndex) const; - virtual glm::vec3 getSpatialControlRawAngularVelocity(int controlIndex) const; virtual void captureKeyEvents(const KeyEvent& event); virtual void releaseKeyEvents(const KeyEvent& event); @@ -149,9 +139,31 @@ public slots: virtual glm::vec2 getViewportDimensions() const; /// Factory to create an InputController - virtual AbstractInputController* createInputController(const QString& deviceName, const QString& tracker); + virtual controller::InputController::Pointer createInputController(const QString& deviceName, const QString& tracker); + virtual void releaseInputController(controller::InputController::Pointer input); - virtual void releaseInputController(AbstractInputController* input); +signals: + void keyPressEvent(const KeyEvent& event); + void keyReleaseEvent(const KeyEvent& event); + + void actionStartEvent(const HFActionEvent& event); + void actionEndEvent(const HFActionEvent& event); + + void backStartEvent(); + void backEndEvent(); + + void mouseMoveEvent(const MouseEvent& event, unsigned int deviceID = 0); + void mousePressEvent(const MouseEvent& event, unsigned int deviceID = 0); + void mouseDoublePressEvent(const MouseEvent& event, unsigned int deviceID = 0); + void mouseReleaseEvent(const MouseEvent& event, unsigned int deviceID = 0); + + void touchBeginEvent(const TouchEvent& event); + void touchEndEvent(const TouchEvent& event); + void touchUpdateEvent(const TouchEvent& event); + + void wheelEvent(const WheelEvent& event); + + void actionEvent(int action, float state); private: QString sanatizeName(const QString& name); /// makes a name clean for inclusing in JavaScript @@ -168,12 +180,9 @@ private: QMultiMap _capturedKeys; QSet _capturedJoysticks; - typedef std::map< AbstractInputController::Key, AbstractInputController* > InputControllerMap; + using InputKey = controller::InputController::Key; + using InputControllerMap = std::map; InputControllerMap _inputControllers; - - void wireUpControllers(ScriptEngine* engine); - - controller::NewControllerScriptingInterface* _newControllerScriptingInterface = nullptr; }; const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4e5dd0da0c..4fc2f3ddb4 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -27,7 +27,7 @@ #include "Application.h" #include // TODO: any references to sixense should be removed here -#include +#include // Used to animate the magnification windows diff --git a/libraries/controllers/CMakeLists.txt b/libraries/controllers/CMakeLists.txt index fbabbe1463..5beffce461 100644 --- a/libraries/controllers/CMakeLists.txt +++ b/libraries/controllers/CMakeLists.txt @@ -4,7 +4,7 @@ set(TARGET_NAME controllers) setup_hifi_library(Script) # use setup_hifi_library macro to setup our project and link appropriate Qt modules -link_hifi_libraries(shared plugins input-plugins) +link_hifi_libraries(shared) GroupSources("src/controllers") diff --git a/libraries/controllers/src/controllers/Endpoint.h b/libraries/controllers/src/controllers/Endpoint.h index bea33517f5..5c6e6c028b 100644 --- a/libraries/controllers/src/controllers/Endpoint.h +++ b/libraries/controllers/src/controllers/Endpoint.h @@ -14,7 +14,7 @@ #include #include -#include +#include "UserInputMapper.h" class QScriptValue; diff --git a/libraries/input-plugins/src/input-plugins/InputDevice.cpp b/libraries/controllers/src/controllers/InputDevice.cpp similarity index 100% rename from libraries/input-plugins/src/input-plugins/InputDevice.cpp rename to libraries/controllers/src/controllers/InputDevice.cpp diff --git a/libraries/input-plugins/src/input-plugins/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h similarity index 100% rename from libraries/input-plugins/src/input-plugins/InputDevice.h rename to libraries/controllers/src/controllers/InputDevice.h diff --git a/libraries/controllers/src/controllers/NewControllerScriptingInterface.h b/libraries/controllers/src/controllers/NewControllerScriptingInterface.h deleted file mode 100644 index 659c8bfd05..0000000000 --- a/libraries/controllers/src/controllers/NewControllerScriptingInterface.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// Created by Bradley Austin Davis 2015/10/09 -// Copyright 2015 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 -// - -#pragma once -#ifndef hifi_Controllers_NewControllerScriptingInterface_h -#define hifi_Controllers_NewControllerScriptingInterface_h - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include "Mapping.h" - -class QScriptValue; - -namespace controller { - class NewControllerScriptingInterface : public QObject { - Q_OBJECT - Q_PROPERTY(QVariantMap Hardware READ getHardware CONSTANT FINAL) - Q_PROPERTY(QVariantMap Actions READ getActions CONSTANT FINAL) - Q_PROPERTY(QVariantMap Standard READ getStandard CONSTANT FINAL) - - public: - NewControllerScriptingInterface(); - Q_INVOKABLE float getValue(const int& source); - - Q_INVOKABLE void update(); - Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); - Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); - Q_INVOKABLE void disableMapping(const QString& mappingName) { - enableMapping(mappingName, false); - } - - - const QVariantMap& getHardware() { return _hardware; } - const QVariantMap& getActions() { return _actions; } - const QVariantMap& getStandard() { return _standard; } - - private: - - // FIXME move to unordered set / map - using MappingMap = std::map; - using MappingStack = std::list; - using InputToEndpointMap = std::map; - using EndpointSet = std::unordered_set; - using ValueMap = std::map; - using EndpointPair = std::pair; - using EndpointPairMap = std::map; - - void update(Mapping::Pointer& mapping, EndpointSet& consumed); - float getValue(const Endpoint::Pointer& endpoint); - Endpoint::Pointer endpointFor(const QJSValue& endpoint); - Endpoint::Pointer endpointFor(const QScriptValue& endpoint); - Endpoint::Pointer endpointFor(const UserInputMapper::Input& endpoint); - Endpoint::Pointer compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second); - - friend class MappingBuilderProxy; - friend class RouteBuilderProxy; - private: - uint16_t _nextFunctionId; - InputToEndpointMap _endpoints; - EndpointPairMap _compositeEndpoints; - - ValueMap _overrideValues; - MappingMap _mappingsByName; - MappingStack _activeMappings; - - QVariantMap _hardware; - QVariantMap _actions; - QVariantMap _standard; - }; -} - - -#endif diff --git a/libraries/controllers/src/controllers/NewControllerScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp similarity index 77% rename from libraries/controllers/src/controllers/NewControllerScriptingInterface.cpp rename to libraries/controllers/src/controllers/ScriptingInterface.cpp index 4bc5b9eeb5..9d2cdfd2de 100644 --- a/libraries/controllers/src/controllers/NewControllerScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -5,7 +5,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "NewControllerScriptingInterface.h" +#include "ScriptingInterface.h" #include #include @@ -14,19 +14,15 @@ #include #include -#include -#include -#include -#include #include "impl/MappingBuilderProxy.h" #include "Logging.h" +#include "InputDevice.h" static const uint16_t ACTIONS_DEVICE = UserInputMapper::Input::INVALID_DEVICE - (uint16_t)1; namespace controller { - class VirtualEndpoint : public Endpoint { public: VirtualEndpoint(const UserInputMapper::Input& id = UserInputMapper::Input(-1)) @@ -97,18 +93,15 @@ namespace controller { Endpoint::Pointer _second; }; - QString sanatizeName(const QString& name) { - QString cleanName{ name }; - cleanName.remove(QRegularExpression{ "[\\(\\)\\.\\s]" }); - return cleanName; - } + + QRegularExpression ScriptingInterface::SANITIZE_NAME_EXPRESSION{ "[\\(\\)\\.\\s]" }; QVariantMap createDeviceMap(const UserInputMapper::DeviceProxy* device) { auto userInputMapper = DependencyManager::get(); QVariantMap deviceMap; for (const auto& inputMapping : device->getAvailabeInputs()) { const auto& input = inputMapping.first; - const auto inputName = sanatizeName(inputMapping.second); + const auto inputName = QString(inputMapping.second).remove(ScriptingInterface::SANITIZE_NAME_EXPRESSION); qCDebug(controllers) << "\tInput " << input.getChannel() << (int)input.getType() << QString::number(input.getID(), 16) << ": " << inputName; deviceMap.insert(inputName, input.getID()); @@ -116,12 +109,12 @@ namespace controller { return deviceMap; } - NewControllerScriptingInterface::NewControllerScriptingInterface() { + ScriptingInterface::ScriptingInterface() { auto userInputMapper = DependencyManager::get(); auto devices = userInputMapper->getDevices(); for (const auto& deviceMapping : devices) { auto device = deviceMapping.second.get(); - auto deviceName = sanatizeName(device->getName()); + auto deviceName = QString(device->getName()).remove(ScriptingInterface::SANITIZE_NAME_EXPRESSION); qCDebug(controllers) << "Device" << deviceMapping.first << ":" << deviceName; // Expose the IDs to JS _hardware.insert(deviceName, createDeviceMap(device)); @@ -164,7 +157,8 @@ namespace controller { UserInputMapper::Input actionInput(ACTIONS_DEVICE, actionNumber++, UserInputMapper::ChannelType::AXIS); qCDebug(controllers) << "\tAction: " << actionName << " " << QString::number(actionInput.getID(), 16); // Expose the IDs to JS - _actions.insert(sanatizeName(actionName), actionInput.getID()); + QString cleanActionName = QString(actionName).remove(ScriptingInterface::SANITIZE_NAME_EXPRESSION); + _actions.insert(cleanActionName, actionInput.getID()); // Create the endpoints // FIXME action endpoints need to accumulate values, and have them cleared at each frame @@ -172,7 +166,7 @@ namespace controller { } } - QObject* NewControllerScriptingInterface::newMapping(const QString& mappingName) { + QObject* ScriptingInterface::newMapping(const QString& mappingName) { if (_mappingsByName.count(mappingName)) { qCWarning(controllers) << "Refusing to recreate mapping named " << mappingName; } @@ -182,7 +176,7 @@ namespace controller { return new MappingBuilderProxy(*this, mapping); } - void NewControllerScriptingInterface::enableMapping(const QString& mappingName, bool enable) { + void ScriptingInterface::enableMapping(const QString& mappingName, bool enable) { auto iterator = _mappingsByName.find(mappingName); if (_mappingsByName.end() == iterator) { qCWarning(controllers) << "Request to enable / disable unknown mapping " << mappingName; @@ -202,7 +196,7 @@ namespace controller { } } - float NewControllerScriptingInterface::getValue(const int& source) { + float ScriptingInterface::getValue(const int& source) const { // return (sin(secTimestampNow()) + 1.0f) / 2.0f; UserInputMapper::Input input(source); auto iterator = _endpoints.find(input); @@ -214,7 +208,7 @@ namespace controller { return getValue(endpoint); } - float NewControllerScriptingInterface::getValue(const Endpoint::Pointer& endpoint) { + float ScriptingInterface::getValue(const Endpoint::Pointer& endpoint) const { auto valuesIterator = _overrideValues.find(endpoint); if (_overrideValues.end() != valuesIterator) { return valuesIterator->second; @@ -223,19 +217,20 @@ namespace controller { return endpoint->value(); } - - void NewControllerScriptingInterface::update() { - static float last = secTimestampNow(); - float now = secTimestampNow(); - float delta = now - last; - last = now; + float ScriptingInterface::getButtonValue(StandardButtonChannel source, uint16_t device) const { + return getValue(UserInputMapper::Input(device, source, UserInputMapper::ChannelType::BUTTON).getID()); + } - foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { - inputPlugin->pluginUpdate(delta, false); - } + float ScriptingInterface::getAxisValue(StandardAxisChannel source, uint16_t device) const { + return getValue(UserInputMapper::Input(device, source, UserInputMapper::ChannelType::AXIS).getID()); + } + glm::mat4 ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { + return glm::mat4(); + } + + void ScriptingInterface::update() { auto userInputMapper = DependencyManager::get(); - userInputMapper->update(delta); _overrideValues.clear(); EndpointSet readEndpoints; @@ -295,9 +290,7 @@ namespace controller { } } - - - Endpoint::Pointer NewControllerScriptingInterface::endpointFor(const QJSValue& endpoint) { + Endpoint::Pointer ScriptingInterface::endpointFor(const QJSValue& endpoint) { if (endpoint.isNumber()) { return endpointFor(UserInputMapper::Input(endpoint.toInt())); } @@ -311,7 +304,7 @@ namespace controller { return Endpoint::Pointer(); } - Endpoint::Pointer NewControllerScriptingInterface::endpointFor(const QScriptValue& endpoint) { + Endpoint::Pointer ScriptingInterface::endpointFor(const QScriptValue& endpoint) { if (endpoint.isNumber()) { return endpointFor(UserInputMapper::Input(endpoint.toInt32())); } @@ -325,7 +318,7 @@ namespace controller { return Endpoint::Pointer(); } - Endpoint::Pointer NewControllerScriptingInterface::endpointFor(const UserInputMapper::Input& inputId) { + Endpoint::Pointer ScriptingInterface::endpointFor(const UserInputMapper::Input& inputId) { auto iterator = _endpoints.find(inputId); if (_endpoints.end() == iterator) { qWarning() << "Unknown input: " << QString::number(inputId.getID(), 16); @@ -334,7 +327,7 @@ namespace controller { return iterator->second; } - Endpoint::Pointer NewControllerScriptingInterface::compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second) { + Endpoint::Pointer ScriptingInterface::compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second) { EndpointPair pair(first, second); Endpoint::Pointer result; auto iterator = _compositeEndpoints.find(pair); @@ -347,6 +340,66 @@ namespace controller { return result; } + bool ScriptingInterface::isPrimaryButtonPressed() const { + return isButtonPressed(StandardButtonChannel::A); + } + + glm::vec2 ScriptingInterface::getPrimaryJoystickPosition() const { + return getJoystickPosition(0); + } + + int ScriptingInterface::getNumberOfButtons() const { + return StandardButtonChannel::NUM_STANDARD_BUTTONS; + } + + bool ScriptingInterface::isButtonPressed(int buttonIndex) const { + return getButtonValue((StandardButtonChannel)buttonIndex) == 0.0 ? false : true; + } + + int ScriptingInterface::getNumberOfTriggers() const { + return 2; + } + + float ScriptingInterface::getTriggerValue(int triggerIndex) const { + return getAxisValue(triggerIndex == 0 ? StandardAxisChannel::LT : StandardAxisChannel::RT); + } + + int ScriptingInterface::getNumberOfJoysticks() const { + return 2; + } + + glm::vec2 ScriptingInterface::getJoystickPosition(int joystickIndex) const { + StandardAxisChannel xid = StandardAxisChannel::LX; + StandardAxisChannel yid = StandardAxisChannel::LY; + if (joystickIndex != 0) { + xid = StandardAxisChannel::RX; + yid = StandardAxisChannel::RY; + } + vec2 result; + result.x = getAxisValue(xid); + result.y = getAxisValue(yid); + return result; + } + + int ScriptingInterface::getNumberOfSpatialControls() const { + return 2; + } + + glm::vec3 ScriptingInterface::getSpatialControlPosition(int controlIndex) const { + return vec3(); + } + + glm::vec3 ScriptingInterface::getSpatialControlVelocity(int controlIndex) const { + return vec3(); + } + + glm::vec3 ScriptingInterface::getSpatialControlNormal(int controlIndex) const { + return vec3(); + } + + glm::quat ScriptingInterface::getSpatialControlRawRotation(int controlIndex) const { + return quat(); + } } // namespace controllers //var mapping = Controller.newMapping(); diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h new file mode 100644 index 0000000000..043e06a67f --- /dev/null +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -0,0 +1,138 @@ +// +// AbstractControllerScriptingInterface.h +// libraries/script-engine/src +// +// Created by Brad Hefta-Gaub on 12/17/13. +// Copyright 2013 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 +// + +#pragma once +#ifndef hifi_AbstractControllerScriptingInterface_h +#define hifi_AbstractControllerScriptingInterface_h + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "UserInputMapper.h" +#include "StandardControls.h" +#include "Mapping.h" + +namespace controller { + class InputController : public QObject { + Q_OBJECT + + public: + using Key = unsigned int; + using Pointer = std::shared_ptr; + + virtual void update() = 0; + virtual Key getKey() const = 0; + + public slots: + virtual bool isActive() const = 0; + virtual glm::vec3 getAbsTranslation() const = 0; + virtual glm::quat getAbsRotation() const = 0; + virtual glm::vec3 getLocTranslation() const = 0; + virtual glm::quat getLocRotation() const = 0; + + signals: + //void spatialEvent(const SpatialEvent& event); + }; + + /// handles scripting of input controller commands from JS + class ScriptingInterface : public QObject { + Q_OBJECT + Q_PROPERTY(QVariantMap Hardware READ getHardware CONSTANT FINAL) + Q_PROPERTY(QVariantMap Actions READ getActions CONSTANT FINAL) + Q_PROPERTY(QVariantMap Standard READ getStandard CONSTANT FINAL) + + public: + ScriptingInterface(); + + Q_INVOKABLE float getValue(const int& source) const; + Q_INVOKABLE float getButtonValue(StandardButtonChannel source, uint16_t device = 0) const; + Q_INVOKABLE float getAxisValue(StandardAxisChannel source, uint16_t device = 0) const; + Q_INVOKABLE glm::mat4 getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; + Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); + Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); + Q_INVOKABLE void disableMapping(const QString& mappingName) { + enableMapping(mappingName, false); + } + + Q_INVOKABLE bool isPrimaryButtonPressed() const; + Q_INVOKABLE glm::vec2 getPrimaryJoystickPosition() const; + + Q_INVOKABLE int getNumberOfButtons() const; + Q_INVOKABLE bool isButtonPressed(int buttonIndex) const; + + Q_INVOKABLE int getNumberOfTriggers() const; + Q_INVOKABLE float getTriggerValue(int triggerIndex) const; + + Q_INVOKABLE int getNumberOfJoysticks() const; + Q_INVOKABLE glm::vec2 getJoystickPosition(int joystickIndex) const; + + Q_INVOKABLE int getNumberOfSpatialControls() const; + Q_INVOKABLE glm::vec3 getSpatialControlPosition(int controlIndex) const; + Q_INVOKABLE glm::vec3 getSpatialControlVelocity(int controlIndex) const; + Q_INVOKABLE glm::vec3 getSpatialControlNormal(int controlIndex) const; + Q_INVOKABLE glm::quat getSpatialControlRawRotation(int controlIndex) const; + + Q_INVOKABLE const QVariantMap& getHardware() { return _hardware; } + Q_INVOKABLE const QVariantMap& getActions() { return _actions; } + Q_INVOKABLE const QVariantMap& getStandard() { return _standard; } + + static QRegularExpression SANITIZE_NAME_EXPRESSION; + + public slots: + virtual void update(); + //virtual void registerControllerTypes(ScriptEngine* engine) = 0; + + private: + friend class MappingBuilderProxy; + friend class RouteBuilderProxy; + + // FIXME move to unordered set / map + using MappingMap = std::map; + using MappingStack = std::list; + using InputToEndpointMap = std::map; + using EndpointSet = std::unordered_set; + using ValueMap = std::map; + using EndpointPair = std::pair; + using EndpointPairMap = std::map; + + void update(Mapping::Pointer& mapping, EndpointSet& consumed); + float getValue(const Endpoint::Pointer& endpoint) const; + Endpoint::Pointer endpointFor(const QJSValue& endpoint); + Endpoint::Pointer endpointFor(const QScriptValue& endpoint); + Endpoint::Pointer endpointFor(const UserInputMapper::Input& endpoint); + Endpoint::Pointer compositeEndpointFor(Endpoint::Pointer first, Endpoint::Pointer second); + + QVariantMap _hardware; + QVariantMap _actions; + QVariantMap _standard; + + InputToEndpointMap _endpoints; + EndpointPairMap _compositeEndpoints; + + ValueMap _overrideValues; + MappingMap _mappingsByName; + MappingStack _activeMappings; + }; +} + + +#endif // hifi_AbstractControllerScriptingInterface_h diff --git a/libraries/input-plugins/src/input-plugins/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp similarity index 98% rename from libraries/input-plugins/src/input-plugins/StandardController.cpp rename to libraries/controllers/src/controllers/StandardController.cpp index 5460e22c96..9c423eded2 100644 --- a/libraries/input-plugins/src/input-plugins/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -1,121 +1,121 @@ -// -// StandardController.cpp -// input-plugins/src/input-plugins -// -// Created by Brad Hefta-Gaub on 2015-10-11. -// Copyright 2015 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 -// - -#include - -#include - -#include "StandardController.h" - -const float CONTROLLER_THRESHOLD = 0.3f; - -StandardController::~StandardController() { -} - -void StandardController::update(float deltaTime, bool jointsCaptured) { -} - -void StandardController::focusOutEvent() { - _axisStateMap.clear(); - _buttonPressedMap.clear(); -}; - -void StandardController::registerToUserInputMapper(UserInputMapper& mapper) { - // Grab the current free device ID - _deviceID = mapper.getStandardDeviceID(); - - auto proxy = std::make_shared(_name); - proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; - proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; - proxy->getAvailabeInputs = [this] () -> QVector { - QVector availableInputs; - // Buttons - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "A")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "B")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "X")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Y")); - - // DPad - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "DU")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "DD")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "DL")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "DR")); - - // Bumpers - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "LB")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "RB")); - - // Stick press - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "LS")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "RS")); - - // Center buttons - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::START), "Start")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Back")); - - // Analog sticks - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LY), "LY")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LX), "LX")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RY), "RY")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RX), "RX")); - - // Triggers - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "LT")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "RT")); - - // Poses - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LEFT), "LeftPose")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RIGHT), "RightPose")); - - // Aliases, PlayStation style names - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "L1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "R1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "L2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "R2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "L3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "R3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Select")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "Cross")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "Circle")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "Square")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Triangle")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "Up")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "Down")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "Left")); - availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "Right")); - - - return availableInputs; - }; - - proxy->resetDeviceBindings = [this, &mapper] () -> bool { - mapper.removeAllInputChannelsForDevice(_deviceID); - this->assignDefaultInputMapping(mapper); - return true; - }; - - mapper.registerStandardDevice(proxy); -} - -void StandardController::assignDefaultInputMapping(UserInputMapper& mapper) { -} - -UserInputMapper::Input StandardController::makeInput(controller::StandardButtonChannel button) { - return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); -} - -UserInputMapper::Input StandardController::makeInput(controller::StandardAxisChannel axis) { - return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); -} - -UserInputMapper::Input StandardController::makeInput(controller::StandardPoseChannel pose) { - return UserInputMapper::Input(_deviceID, pose, UserInputMapper::ChannelType::POSE); -} +// +// StandardController.cpp +// input-plugins/src/input-plugins +// +// Created by Brad Hefta-Gaub on 2015-10-11. +// Copyright 2015 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 +// + +#include + +#include + +#include "StandardController.h" + +const float CONTROLLER_THRESHOLD = 0.3f; + +StandardController::~StandardController() { +} + +void StandardController::update(float deltaTime, bool jointsCaptured) { +} + +void StandardController::focusOutEvent() { + _axisStateMap.clear(); + _buttonPressedMap.clear(); +}; + +void StandardController::registerToUserInputMapper(UserInputMapper& mapper) { + // Grab the current free device ID + _deviceID = mapper.getStandardDeviceID(); + + auto proxy = std::make_shared(_name); + proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; + proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; + proxy->getAvailabeInputs = [this] () -> QVector { + QVector availableInputs; + // Buttons + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "A")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "B")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "X")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Y")); + + // DPad + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "DU")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "DD")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "DL")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "DR")); + + // Bumpers + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "LB")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "RB")); + + // Stick press + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "LS")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "RS")); + + // Center buttons + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::START), "Start")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Back")); + + // Analog sticks + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LY), "LY")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LX), "LX")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RY), "RY")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RX), "RX")); + + // Triggers + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "LT")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "RT")); + + // Poses + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LEFT), "LeftPose")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RIGHT), "RightPose")); + + // Aliases, PlayStation style names + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LB), "L1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RB), "R1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LT), "L2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RT), "R2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LS), "L3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RS), "R3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::BACK), "Select")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::A), "Cross")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::B), "Circle")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::X), "Square")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::Y), "Triangle")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DU), "Up")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DD), "Down")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DL), "Left")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::DR), "Right")); + + + return availableInputs; + }; + + proxy->resetDeviceBindings = [this, &mapper] () -> bool { + mapper.removeAllInputChannelsForDevice(_deviceID); + this->assignDefaultInputMapping(mapper); + return true; + }; + + mapper.registerStandardDevice(proxy); +} + +void StandardController::assignDefaultInputMapping(UserInputMapper& mapper) { +} + +UserInputMapper::Input StandardController::makeInput(controller::StandardButtonChannel button) { + return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); +} + +UserInputMapper::Input StandardController::makeInput(controller::StandardAxisChannel axis) { + return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); +} + +UserInputMapper::Input StandardController::makeInput(controller::StandardPoseChannel pose) { + return UserInputMapper::Input(_deviceID, pose, UserInputMapper::ChannelType::POSE); +} diff --git a/libraries/input-plugins/src/input-plugins/StandardController.h b/libraries/controllers/src/controllers/StandardController.h similarity index 96% rename from libraries/input-plugins/src/input-plugins/StandardController.h rename to libraries/controllers/src/controllers/StandardController.h index ad1329d5ed..c393af80f4 100644 --- a/libraries/input-plugins/src/input-plugins/StandardController.h +++ b/libraries/controllers/src/controllers/StandardController.h @@ -1,48 +1,48 @@ -// -// StandardController.h -// input-plugins/src/input-plugins -// -// Created by Brad Hefta-Gaub on 2015-10-11. -// Copyright 2015 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 -// - -#ifndef hifi_StandardController_h -#define hifi_StandardController_h - -#include -#include - -#include "InputDevice.h" - -#include "StandardControls.h" - -typedef std::shared_ptr StandardControllerPointer; - -class StandardController : public QObject, public InputDevice { - Q_OBJECT - Q_PROPERTY(QString name READ getName) - -public: - - const QString& getName() const { return _name; } - - // Device functions - virtual void registerToUserInputMapper(UserInputMapper& mapper) override; - virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; - virtual void update(float deltaTime, bool jointsCaptured) override; - virtual void focusOutEvent() override; - - StandardController() : InputDevice("Standard") {} - ~StandardController(); - - UserInputMapper::Input makeInput(controller::StandardButtonChannel button); - UserInputMapper::Input makeInput(controller::StandardAxisChannel axis); - UserInputMapper::Input makeInput(controller::StandardPoseChannel pose); - -private: -}; - -#endif // hifi_StandardController_h +// +// StandardController.h +// input-plugins/src/input-plugins +// +// Created by Brad Hefta-Gaub on 2015-10-11. +// Copyright 2015 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 +// + +#ifndef hifi_StandardController_h +#define hifi_StandardController_h + +#include +#include + +#include "InputDevice.h" + +#include "StandardControls.h" + +typedef std::shared_ptr StandardControllerPointer; + +class StandardController : public QObject, public InputDevice { + Q_OBJECT + Q_PROPERTY(QString name READ getName) + +public: + + const QString& getName() const { return _name; } + + // Device functions + virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; + virtual void update(float deltaTime, bool jointsCaptured) override; + virtual void focusOutEvent() override; + + StandardController() : InputDevice("Standard") {} + ~StandardController(); + + UserInputMapper::Input makeInput(controller::StandardButtonChannel button); + UserInputMapper::Input makeInput(controller::StandardAxisChannel axis); + UserInputMapper::Input makeInput(controller::StandardPoseChannel pose); + +private: +}; + +#endif // hifi_StandardController_h diff --git a/libraries/input-plugins/src/input-plugins/StandardControls.h b/libraries/controllers/src/controllers/StandardControls.h similarity index 95% rename from libraries/input-plugins/src/input-plugins/StandardControls.h rename to libraries/controllers/src/controllers/StandardControls.h index e5943ff780..505b4f85c7 100644 --- a/libraries/input-plugins/src/input-plugins/StandardControls.h +++ b/libraries/controllers/src/controllers/StandardControls.h @@ -1,59 +1,59 @@ -// -// Created by Bradley Austin Davis 2015/10/09 -// Copyright 2015 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 -// -#pragma once - -namespace controller { - - // Needs to match order and values of SDL_GameControllerButton - enum StandardButtonChannel { - // Button quad - A = 0, - B, - X, - Y, - // Center buttons - BACK, - GUIDE, - START, - // Stick press - LS, - RS, - // Bumper press - LB, - RB, - // DPad - DU, - DD, - DL, - DR, - NUM_STANDARD_BUTTONS - }; - - // Needs to match order and values of SDL_GameControllerAxis - enum StandardAxisChannel { - // Left Analog stick - LX = 0, - LY, - // Right Analog stick - RX, - RY, - // Triggers - LT, - RT, - NUM_STANDARD_AXES - }; - - // No correlation to SDL - enum StandardPoseChannel { - LEFT = 0, - RIGHT, - HEAD, - NUM_STANDARD_POSES - }; - -} +// +// Created by Bradley Austin Davis 2015/10/09 +// Copyright 2015 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 +// +#pragma once + +namespace controller { + + // Needs to match order and values of SDL_GameControllerButton + enum StandardButtonChannel { + // Button quad + A = 0, + B, + X, + Y, + // Center buttons + BACK, + GUIDE, + START, + // Stick press + LS, + RS, + // Bumper press + LB, + RB, + // DPad + DU, + DD, + DL, + DR, + NUM_STANDARD_BUTTONS + }; + + // Needs to match order and values of SDL_GameControllerAxis + enum StandardAxisChannel { + // Left Analog stick + LX = 0, + LY, + // Right Analog stick + RX, + RY, + // Triggers + LT, + RT, + NUM_STANDARD_AXES + }; + + // No correlation to SDL + enum StandardPoseChannel { + LEFT = 0, + RIGHT, + HEAD, + NUM_STANDARD_POSES + }; + +} diff --git a/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp old mode 100755 new mode 100644 similarity index 93% rename from libraries/input-plugins/src/input-plugins/UserInputMapper.cpp rename to libraries/controllers/src/controllers/UserInputMapper.cpp index c29acc09af..8fc44ebf5b --- a/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -1,368 +1,368 @@ -// -// UserInputMapper.cpp -// input-plugins/src/input-plugins -// -// Created by Sam Gateau on 4/27/15. -// Copyright 2015 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 -// - -#include "UserInputMapper.h" -#include "StandardController.h" - -const UserInputMapper::Input UserInputMapper::Input::INVALID_INPUT = UserInputMapper::Input(UINT16_MAX); -const uint16_t UserInputMapper::Input::INVALID_DEVICE = INVALID_INPUT.getDevice(); -const uint16_t UserInputMapper::Input::INVALID_CHANNEL = INVALID_INPUT.getChannel(); -const uint16_t UserInputMapper::Input::INVALID_TYPE = (uint16_t)INVALID_INPUT.getType(); - -// Default contruct allocate the poutput size with the current hardcoded action channels -UserInputMapper::UserInputMapper() { - registerStandardDevice(); - assignDefaulActionScales(); - createActionNames(); -} - -UserInputMapper::~UserInputMapper() { -} - - -bool UserInputMapper::registerDevice(uint16 deviceID, const DeviceProxy::Pointer& proxy){ - proxy->_name += " (" + QString::number(deviceID) + ")"; - _registeredDevices[deviceID] = proxy; - return true; -} - -UserInputMapper::DeviceProxy::Pointer UserInputMapper::getDeviceProxy(const Input& input) { - auto device = _registeredDevices.find(input.getDevice()); - if (device != _registeredDevices.end()) { - return (device->second); - } else { - return DeviceProxy::Pointer(); - } -} - -QString UserInputMapper::getDeviceName(uint16 deviceID) { - if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { - return _registeredDevices[deviceID]->_name; - } - return QString("unknown"); -} - - -void UserInputMapper::resetAllDeviceBindings() { - for (auto device : _registeredDevices) { - device.second->resetDeviceBindings(); - } -} - -void UserInputMapper::resetDevice(uint16 deviceID) { - auto device = _registeredDevices.find(deviceID); - if (device != _registeredDevices.end()) { - device->second->resetDeviceBindings(); - } -} - -int UserInputMapper::findDevice(QString name) { - for (auto device : _registeredDevices) { - if (device.second->_name.split(" (")[0] == name) { - return device.first; - } - } - return 0; -} - -QVector UserInputMapper::getDeviceNames() { - QVector result; - for (auto device : _registeredDevices) { - QString deviceName = device.second->_name.split(" (")[0]; - result << deviceName; - } - return result; -} - - -bool UserInputMapper::addInputChannel(Action action, const Input& input, float scale) { - return addInputChannel(action, input, Input(), scale); -} - -bool UserInputMapper::addInputChannel(Action action, const Input& input, const Input& modifier, float scale) { - // Check that the device is registered - if (!getDeviceProxy(input)) { - qDebug() << "UserInputMapper::addInputChannel: The input comes from a device #" << input.getDevice() << "is unknown. no inputChannel mapped."; - return false; - } - - auto inputChannel = InputChannel(input, modifier, action, scale); - - // Insert or replace the input to modifiers - if (inputChannel.hasModifier()) { - auto& modifiers = _inputToModifiersMap[input.getID()]; - modifiers.push_back(inputChannel._modifier); - std::sort(modifiers.begin(), modifiers.end()); - } - - // Now update the action To Inputs side of things - _actionToInputsMap.insert(ActionToInputsMap::value_type(action, inputChannel)); - - return true; -} - -int UserInputMapper::addInputChannels(const InputChannels& channels) { - int nbAdded = 0; - for (auto& channel : channels) { - nbAdded += addInputChannel(channel._action, channel._input, channel._modifier, channel._scale); - } - return nbAdded; -} - -bool UserInputMapper::removeInputChannel(InputChannel inputChannel) { - // Remove from Input to Modifiers map - if (inputChannel.hasModifier()) { - _inputToModifiersMap.erase(inputChannel._input.getID()); - } - - // Remove from Action to Inputs map - std::pair ret; - ret = _actionToInputsMap.equal_range(inputChannel._action); - for (ActionToInputsMap::iterator it=ret.first; it!=ret.second; ++it) { - if (it->second == inputChannel) { - _actionToInputsMap.erase(it); - return true; - } - } - - return false; -} - -void UserInputMapper::removeAllInputChannels() { - _inputToModifiersMap.clear(); - _actionToInputsMap.clear(); -} - -void UserInputMapper::removeAllInputChannelsForDevice(uint16 device) { - QVector channels = getAllInputsForDevice(device); - for (auto& channel : channels) { - removeInputChannel(channel); - } -} - -void UserInputMapper::removeDevice(int device) { - removeAllInputChannelsForDevice((uint16) device); - _registeredDevices.erase(device); -} - -int UserInputMapper::getInputChannels(InputChannels& channels) const { - for (auto& channel : _actionToInputsMap) { - channels.push_back(channel.second); - } - - return _actionToInputsMap.size(); -} - -QVector UserInputMapper::getAllInputsForDevice(uint16 device) { - InputChannels allChannels; - getInputChannels(allChannels); - - QVector channels; - for (InputChannel inputChannel : allChannels) { - if (inputChannel._input._device == device) { - channels.push_back(inputChannel); - } - } - - return channels; -} - -void UserInputMapper::update(float deltaTime) { - - // Reset the axis state for next loop - for (auto& channel : _actionStates) { - channel = 0.0f; - } - - for (auto& channel : _poseStates) { - channel = PoseValue(); - } - - int currentTimestamp = 0; - - for (auto& channelInput : _actionToInputsMap) { - auto& inputMapping = channelInput.second; - auto& inputID = inputMapping._input; - bool enabled = true; - - // Check if this input channel has modifiers and collect the possibilities - auto modifiersIt = _inputToModifiersMap.find(inputID.getID()); - if (modifiersIt != _inputToModifiersMap.end()) { - Modifiers validModifiers; - bool isActiveModifier = false; - for (auto& modifier : modifiersIt->second) { - auto deviceProxy = getDeviceProxy(modifier); - if (deviceProxy->getButton(modifier, currentTimestamp)) { - validModifiers.push_back(modifier); - isActiveModifier |= (modifier.getID() == inputMapping._modifier.getID()); - } - } - enabled = (validModifiers.empty() && !inputMapping.hasModifier()) || isActiveModifier; - } - - // if enabled: default input or all modifiers on - if (enabled) { - auto deviceProxy = getDeviceProxy(inputID); - switch (inputMapping._input.getType()) { - case ChannelType::BUTTON: { - _actionStates[channelInput.first] += inputMapping._scale * float(deviceProxy->getButton(inputID, currentTimestamp));// * deltaTime; // weight the impulse by the deltaTime - break; - } - case ChannelType::AXIS: { - _actionStates[channelInput.first] += inputMapping._scale * deviceProxy->getAxis(inputID, currentTimestamp); - break; - } - case ChannelType::POSE: { - if (!_poseStates[channelInput.first].isValid()) { - _poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp); - } - break; - } - default: { - break; //silence please - } - } - } else{ - // Channel input not enabled - enabled = false; - } - } - - // Scale all the channel step with the scale - static const float EPSILON = 0.01f; - for (auto i = 0; i < NUM_ACTIONS; i++) { - _actionStates[i] *= _actionScales[i]; - // Emit only on change, and emit when moving back to 0 - if (fabsf(_actionStates[i] - _lastActionStates[i]) > EPSILON) { - _lastActionStates[i] = _actionStates[i]; - emit actionEvent(i, _actionStates[i]); - } - // TODO: emit signal for pose changes - } -} - -QVector UserInputMapper::getAllActions() const { - QVector actions; - for (auto i = 0; i < NUM_ACTIONS; i++) { - actions.append(Action(i)); - } - return actions; -} - -QVector UserInputMapper::getInputChannelsForAction(UserInputMapper::Action action) { - QVector inputChannels; - std::pair ret; - ret = _actionToInputsMap.equal_range(action); - for (ActionToInputsMap::iterator it=ret.first; it!=ret.second; ++it) { - inputChannels.append(it->second); - } - return inputChannels; -} - -int UserInputMapper::findAction(const QString& actionName) const { - auto actions = getAllActions(); - for (auto action : actions) { - if (getActionName(action) == actionName) { - return action; - } - } - // If the action isn't found, return -1 - return -1; -} - -QVector UserInputMapper::getActionNames() const { - QVector result; - for (auto i = 0; i < NUM_ACTIONS; i++) { - result << _actionNames[i]; - } - return result; -} - -void UserInputMapper::assignDefaulActionScales() { - _actionScales[LONGITUDINAL_BACKWARD] = 1.0f; // 1m per unit - _actionScales[LONGITUDINAL_FORWARD] = 1.0f; // 1m per unit - _actionScales[LATERAL_LEFT] = 1.0f; // 1m per unit - _actionScales[LATERAL_RIGHT] = 1.0f; // 1m per unit - _actionScales[VERTICAL_DOWN] = 1.0f; // 1m per unit - _actionScales[VERTICAL_UP] = 1.0f; // 1m per unit - _actionScales[YAW_LEFT] = 1.0f; // 1 degree per unit - _actionScales[YAW_RIGHT] = 1.0f; // 1 degree per unit - _actionScales[PITCH_DOWN] = 1.0f; // 1 degree per unit - _actionScales[PITCH_UP] = 1.0f; // 1 degree per unit - _actionScales[BOOM_IN] = 0.5f; // .5m per unit - _actionScales[BOOM_OUT] = 0.5f; // .5m per unit - _actionScales[LEFT_HAND] = 1.0f; // default - _actionScales[RIGHT_HAND] = 1.0f; // default - _actionScales[LEFT_HAND_CLICK] = 1.0f; // on - _actionScales[RIGHT_HAND_CLICK] = 1.0f; // on - _actionStates[SHIFT] = 1.0f; // on - _actionStates[ACTION1] = 1.0f; // default - _actionStates[ACTION2] = 1.0f; // default - _actionStates[TranslateX] = 1.0f; // default - _actionStates[TranslateY] = 1.0f; // default - _actionStates[TranslateZ] = 1.0f; // default - _actionStates[Roll] = 1.0f; // default - _actionStates[Pitch] = 1.0f; // default - _actionStates[Yaw] = 1.0f; // default -} - -// This is only necessary as long as the actions are hardcoded -// Eventually you can just add the string when you add the action -void UserInputMapper::createActionNames() { - _actionNames[LONGITUDINAL_BACKWARD] = "LONGITUDINAL_BACKWARD"; - _actionNames[LONGITUDINAL_FORWARD] = "LONGITUDINAL_FORWARD"; - _actionNames[LATERAL_LEFT] = "LATERAL_LEFT"; - _actionNames[LATERAL_RIGHT] = "LATERAL_RIGHT"; - _actionNames[VERTICAL_DOWN] = "VERTICAL_DOWN"; - _actionNames[VERTICAL_UP] = "VERTICAL_UP"; - _actionNames[YAW_LEFT] = "YAW_LEFT"; - _actionNames[YAW_RIGHT] = "YAW_RIGHT"; - _actionNames[PITCH_DOWN] = "PITCH_DOWN"; - _actionNames[PITCH_UP] = "PITCH_UP"; - _actionNames[BOOM_IN] = "BOOM_IN"; - _actionNames[BOOM_OUT] = "BOOM_OUT"; - _actionNames[LEFT_HAND] = "LEFT_HAND"; - _actionNames[RIGHT_HAND] = "RIGHT_HAND"; - _actionNames[LEFT_HAND_CLICK] = "LEFT_HAND_CLICK"; - _actionNames[RIGHT_HAND_CLICK] = "RIGHT_HAND_CLICK"; - _actionNames[SHIFT] = "SHIFT"; - _actionNames[ACTION1] = "ACTION1"; - _actionNames[ACTION2] = "ACTION2"; - _actionNames[CONTEXT_MENU] = "CONTEXT_MENU"; - _actionNames[TOGGLE_MUTE] = "TOGGLE_MUTE"; - _actionNames[TranslateX] = "TranslateX"; - _actionNames[TranslateY] = "TranslateY"; - _actionNames[TranslateZ] = "TranslateZ"; - _actionNames[Roll] = "Roll"; - _actionNames[Pitch] = "Pitch"; - _actionNames[Yaw] = "Yaw"; -} - -void UserInputMapper::registerStandardDevice() { - _standardController = std::make_shared(); - _standardController->registerToUserInputMapper(*this); -} - -float UserInputMapper::DeviceProxy::getValue(const Input& input, int timestamp) const { - switch (input.getType()) { - case UserInputMapper::ChannelType::BUTTON: - return getButton(input, timestamp) ? 1.0f : 0.0f; - - case UserInputMapper::ChannelType::AXIS: - return getAxis(input, timestamp); - - case UserInputMapper::ChannelType::POSE: - return getPose(input, timestamp)._valid ? 1.0f : 0.0f; - - default: - return 0.0f; - } -} +// +// UserInputMapper.cpp +// input-plugins/src/input-plugins +// +// Created by Sam Gateau on 4/27/15. +// Copyright 2015 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 +// + +#include "UserInputMapper.h" +#include "StandardController.h" + +const UserInputMapper::Input UserInputMapper::Input::INVALID_INPUT = UserInputMapper::Input(UINT16_MAX); +const uint16_t UserInputMapper::Input::INVALID_DEVICE = INVALID_INPUT.getDevice(); +const uint16_t UserInputMapper::Input::INVALID_CHANNEL = INVALID_INPUT.getChannel(); +const uint16_t UserInputMapper::Input::INVALID_TYPE = (uint16_t)INVALID_INPUT.getType(); + +// Default contruct allocate the poutput size with the current hardcoded action channels +UserInputMapper::UserInputMapper() { + registerStandardDevice(); + assignDefaulActionScales(); + createActionNames(); +} + +UserInputMapper::~UserInputMapper() { +} + + +bool UserInputMapper::registerDevice(uint16 deviceID, const DeviceProxy::Pointer& proxy){ + proxy->_name += " (" + QString::number(deviceID) + ")"; + _registeredDevices[deviceID] = proxy; + return true; +} + +UserInputMapper::DeviceProxy::Pointer UserInputMapper::getDeviceProxy(const Input& input) { + auto device = _registeredDevices.find(input.getDevice()); + if (device != _registeredDevices.end()) { + return (device->second); + } else { + return DeviceProxy::Pointer(); + } +} + +QString UserInputMapper::getDeviceName(uint16 deviceID) { + if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { + return _registeredDevices[deviceID]->_name; + } + return QString("unknown"); +} + + +void UserInputMapper::resetAllDeviceBindings() { + for (auto device : _registeredDevices) { + device.second->resetDeviceBindings(); + } +} + +void UserInputMapper::resetDevice(uint16 deviceID) { + auto device = _registeredDevices.find(deviceID); + if (device != _registeredDevices.end()) { + device->second->resetDeviceBindings(); + } +} + +int UserInputMapper::findDevice(QString name) { + for (auto device : _registeredDevices) { + if (device.second->_name.split(" (")[0] == name) { + return device.first; + } + } + return 0; +} + +QVector UserInputMapper::getDeviceNames() { + QVector result; + for (auto device : _registeredDevices) { + QString deviceName = device.second->_name.split(" (")[0]; + result << deviceName; + } + return result; +} + + +bool UserInputMapper::addInputChannel(Action action, const Input& input, float scale) { + return addInputChannel(action, input, Input(), scale); +} + +bool UserInputMapper::addInputChannel(Action action, const Input& input, const Input& modifier, float scale) { + // Check that the device is registered + if (!getDeviceProxy(input)) { + qDebug() << "UserInputMapper::addInputChannel: The input comes from a device #" << input.getDevice() << "is unknown. no inputChannel mapped."; + return false; + } + + auto inputChannel = InputChannel(input, modifier, action, scale); + + // Insert or replace the input to modifiers + if (inputChannel.hasModifier()) { + auto& modifiers = _inputToModifiersMap[input.getID()]; + modifiers.push_back(inputChannel._modifier); + std::sort(modifiers.begin(), modifiers.end()); + } + + // Now update the action To Inputs side of things + _actionToInputsMap.insert(ActionToInputsMap::value_type(action, inputChannel)); + + return true; +} + +int UserInputMapper::addInputChannels(const InputChannels& channels) { + int nbAdded = 0; + for (auto& channel : channels) { + nbAdded += addInputChannel(channel._action, channel._input, channel._modifier, channel._scale); + } + return nbAdded; +} + +bool UserInputMapper::removeInputChannel(InputChannel inputChannel) { + // Remove from Input to Modifiers map + if (inputChannel.hasModifier()) { + _inputToModifiersMap.erase(inputChannel._input.getID()); + } + + // Remove from Action to Inputs map + std::pair ret; + ret = _actionToInputsMap.equal_range(inputChannel._action); + for (ActionToInputsMap::iterator it=ret.first; it!=ret.second; ++it) { + if (it->second == inputChannel) { + _actionToInputsMap.erase(it); + return true; + } + } + + return false; +} + +void UserInputMapper::removeAllInputChannels() { + _inputToModifiersMap.clear(); + _actionToInputsMap.clear(); +} + +void UserInputMapper::removeAllInputChannelsForDevice(uint16 device) { + QVector channels = getAllInputsForDevice(device); + for (auto& channel : channels) { + removeInputChannel(channel); + } +} + +void UserInputMapper::removeDevice(int device) { + removeAllInputChannelsForDevice((uint16) device); + _registeredDevices.erase(device); +} + +int UserInputMapper::getInputChannels(InputChannels& channels) const { + for (auto& channel : _actionToInputsMap) { + channels.push_back(channel.second); + } + + return _actionToInputsMap.size(); +} + +QVector UserInputMapper::getAllInputsForDevice(uint16 device) { + InputChannels allChannels; + getInputChannels(allChannels); + + QVector channels; + for (InputChannel inputChannel : allChannels) { + if (inputChannel._input._device == device) { + channels.push_back(inputChannel); + } + } + + return channels; +} + +void UserInputMapper::update(float deltaTime) { + + // Reset the axis state for next loop + for (auto& channel : _actionStates) { + channel = 0.0f; + } + + for (auto& channel : _poseStates) { + channel = PoseValue(); + } + + int currentTimestamp = 0; + + for (auto& channelInput : _actionToInputsMap) { + auto& inputMapping = channelInput.second; + auto& inputID = inputMapping._input; + bool enabled = true; + + // Check if this input channel has modifiers and collect the possibilities + auto modifiersIt = _inputToModifiersMap.find(inputID.getID()); + if (modifiersIt != _inputToModifiersMap.end()) { + Modifiers validModifiers; + bool isActiveModifier = false; + for (auto& modifier : modifiersIt->second) { + auto deviceProxy = getDeviceProxy(modifier); + if (deviceProxy->getButton(modifier, currentTimestamp)) { + validModifiers.push_back(modifier); + isActiveModifier |= (modifier.getID() == inputMapping._modifier.getID()); + } + } + enabled = (validModifiers.empty() && !inputMapping.hasModifier()) || isActiveModifier; + } + + // if enabled: default input or all modifiers on + if (enabled) { + auto deviceProxy = getDeviceProxy(inputID); + switch (inputMapping._input.getType()) { + case ChannelType::BUTTON: { + _actionStates[channelInput.first] += inputMapping._scale * float(deviceProxy->getButton(inputID, currentTimestamp));// * deltaTime; // weight the impulse by the deltaTime + break; + } + case ChannelType::AXIS: { + _actionStates[channelInput.first] += inputMapping._scale * deviceProxy->getAxis(inputID, currentTimestamp); + break; + } + case ChannelType::POSE: { + if (!_poseStates[channelInput.first].isValid()) { + _poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp); + } + break; + } + default: { + break; //silence please + } + } + } else{ + // Channel input not enabled + enabled = false; + } + } + + // Scale all the channel step with the scale + static const float EPSILON = 0.01f; + for (auto i = 0; i < NUM_ACTIONS; i++) { + _actionStates[i] *= _actionScales[i]; + // Emit only on change, and emit when moving back to 0 + if (fabsf(_actionStates[i] - _lastActionStates[i]) > EPSILON) { + _lastActionStates[i] = _actionStates[i]; + emit actionEvent(i, _actionStates[i]); + } + // TODO: emit signal for pose changes + } +} + +QVector UserInputMapper::getAllActions() const { + QVector actions; + for (auto i = 0; i < NUM_ACTIONS; i++) { + actions.append(Action(i)); + } + return actions; +} + +QVector UserInputMapper::getInputChannelsForAction(UserInputMapper::Action action) { + QVector inputChannels; + std::pair ret; + ret = _actionToInputsMap.equal_range(action); + for (ActionToInputsMap::iterator it=ret.first; it!=ret.second; ++it) { + inputChannels.append(it->second); + } + return inputChannels; +} + +int UserInputMapper::findAction(const QString& actionName) const { + auto actions = getAllActions(); + for (auto action : actions) { + if (getActionName(action) == actionName) { + return action; + } + } + // If the action isn't found, return -1 + return -1; +} + +QVector UserInputMapper::getActionNames() const { + QVector result; + for (auto i = 0; i < NUM_ACTIONS; i++) { + result << _actionNames[i]; + } + return result; +} + +void UserInputMapper::assignDefaulActionScales() { + _actionScales[LONGITUDINAL_BACKWARD] = 1.0f; // 1m per unit + _actionScales[LONGITUDINAL_FORWARD] = 1.0f; // 1m per unit + _actionScales[LATERAL_LEFT] = 1.0f; // 1m per unit + _actionScales[LATERAL_RIGHT] = 1.0f; // 1m per unit + _actionScales[VERTICAL_DOWN] = 1.0f; // 1m per unit + _actionScales[VERTICAL_UP] = 1.0f; // 1m per unit + _actionScales[YAW_LEFT] = 1.0f; // 1 degree per unit + _actionScales[YAW_RIGHT] = 1.0f; // 1 degree per unit + _actionScales[PITCH_DOWN] = 1.0f; // 1 degree per unit + _actionScales[PITCH_UP] = 1.0f; // 1 degree per unit + _actionScales[BOOM_IN] = 0.5f; // .5m per unit + _actionScales[BOOM_OUT] = 0.5f; // .5m per unit + _actionScales[LEFT_HAND] = 1.0f; // default + _actionScales[RIGHT_HAND] = 1.0f; // default + _actionScales[LEFT_HAND_CLICK] = 1.0f; // on + _actionScales[RIGHT_HAND_CLICK] = 1.0f; // on + _actionStates[SHIFT] = 1.0f; // on + _actionStates[ACTION1] = 1.0f; // default + _actionStates[ACTION2] = 1.0f; // default + _actionStates[TRANSLATE_X] = 1.0f; // default + _actionStates[TRANSLATE_Y] = 1.0f; // default + _actionStates[TRANSLATE_Z] = 1.0f; // default + _actionStates[ROLL] = 1.0f; // default + _actionStates[PITCH] = 1.0f; // default + _actionStates[YAW] = 1.0f; // default +} + +// This is only necessary as long as the actions are hardcoded +// Eventually you can just add the string when you add the action +void UserInputMapper::createActionNames() { + _actionNames[LONGITUDINAL_BACKWARD] = "LONGITUDINAL_BACKWARD"; + _actionNames[LONGITUDINAL_FORWARD] = "LONGITUDINAL_FORWARD"; + _actionNames[LATERAL_LEFT] = "LATERAL_LEFT"; + _actionNames[LATERAL_RIGHT] = "LATERAL_RIGHT"; + _actionNames[VERTICAL_DOWN] = "VERTICAL_DOWN"; + _actionNames[VERTICAL_UP] = "VERTICAL_UP"; + _actionNames[YAW_LEFT] = "YAW_LEFT"; + _actionNames[YAW_RIGHT] = "YAW_RIGHT"; + _actionNames[PITCH_DOWN] = "PITCH_DOWN"; + _actionNames[PITCH_UP] = "PITCH_UP"; + _actionNames[BOOM_IN] = "BOOM_IN"; + _actionNames[BOOM_OUT] = "BOOM_OUT"; + _actionNames[LEFT_HAND] = "LEFT_HAND"; + _actionNames[RIGHT_HAND] = "RIGHT_HAND"; + _actionNames[LEFT_HAND_CLICK] = "LEFT_HAND_CLICK"; + _actionNames[RIGHT_HAND_CLICK] = "RIGHT_HAND_CLICK"; + _actionNames[SHIFT] = "SHIFT"; + _actionNames[ACTION1] = "ACTION1"; + _actionNames[ACTION2] = "ACTION2"; + _actionNames[CONTEXT_MENU] = "CONTEXT_MENU"; + _actionNames[TOGGLE_MUTE] = "TOGGLE_MUTE"; + _actionNames[TRANSLATE_X] = "TranslateX"; + _actionNames[TRANSLATE_Y] = "TranslateY"; + _actionNames[TRANSLATE_Z] = "TranslateZ"; + _actionNames[ROLL] = "Roll"; + _actionNames[PITCH] = "Pitch"; + _actionNames[YAW] = "Yaw"; +} + +void UserInputMapper::registerStandardDevice() { + _standardController = std::make_shared(); + _standardController->registerToUserInputMapper(*this); +} + +float UserInputMapper::DeviceProxy::getValue(const Input& input, int timestamp) const { + switch (input.getType()) { + case UserInputMapper::ChannelType::BUTTON: + return getButton(input, timestamp) ? 1.0f : 0.0f; + + case UserInputMapper::ChannelType::AXIS: + return getAxis(input, timestamp); + + case UserInputMapper::ChannelType::POSE: + return getPose(input, timestamp)._valid ? 1.0f : 0.0f; + + default: + return 0.0f; + } +} diff --git a/libraries/input-plugins/src/input-plugins/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h old mode 100755 new mode 100644 similarity index 96% rename from libraries/input-plugins/src/input-plugins/UserInputMapper.h rename to libraries/controllers/src/controllers/UserInputMapper.h index 304e74e8cc..2a42dfa1aa --- a/libraries/input-plugins/src/input-plugins/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -146,44 +146,52 @@ public: // Actions are the output channels of the Mapper, that's what the InputChannel map to // For now the Actions are hardcoded, this is bad, but we will fix that in the near future enum Action { - LONGITUDINAL_BACKWARD = 0, - LONGITUDINAL_FORWARD, + TRANSLATE_X = 0, + TRANSLATE_Y, + TRANSLATE_Z, + ROTATE_X, PITCH = ROTATE_X, + ROTATE_Y, YAW = ROTATE_Y, + ROTATE_Z, ROLL = ROTATE_Z, - LATERAL_LEFT, - LATERAL_RIGHT, + TRANSLATE_CAMERA_Z, - VERTICAL_DOWN, - VERTICAL_UP, - - YAW_LEFT, - YAW_RIGHT, - - PITCH_DOWN, - PITCH_UP, - - BOOM_IN, - BOOM_OUT, - LEFT_HAND, RIGHT_HAND, LEFT_HAND_CLICK, RIGHT_HAND_CLICK, - SHIFT, - ACTION1, ACTION2, CONTEXT_MENU, TOGGLE_MUTE, - TranslateX, - TranslateY, - TranslateZ, - Roll, - Pitch, - Yaw, + SHIFT, + + // Biseced aliases for TRANSLATE_Z + LONGITUDINAL_BACKWARD, + LONGITUDINAL_FORWARD, + + // Biseced aliases for TRANSLATE_X + LATERAL_LEFT, + LATERAL_RIGHT, + + // Biseced aliases for TRANSLATE_Y + VERTICAL_DOWN, + VERTICAL_UP, + + // Biseced aliases for ROTATE_Y + YAW_LEFT, + YAW_RIGHT, + + // Biseced aliases for ROTATE_X + PITCH_DOWN, + PITCH_UP, + + // Biseced aliases for TRANSLATE_CAMERA_Z + BOOM_IN, + BOOM_OUT, NUM_ACTIONS, }; diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp index a826b4fd4d..1e889f2dda 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp @@ -12,7 +12,7 @@ #include #include "RouteBuilderProxy.h" -#include "../NewControllerScriptingInterface.h" +#include "../ScriptingInterface.h" #include "../Logging.h" namespace controller { diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index 70495a9cfe..024faa7a4a 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -20,12 +20,14 @@ class QScriptValue; namespace controller { -class NewControllerScriptingInterface; +class ScriptingInterface; +// TODO migrate functionality to a MappingBuilder class and make the proxy defer to that +// (for easier use in both C++ and JS) class MappingBuilderProxy : public QObject { Q_OBJECT public: - MappingBuilderProxy(NewControllerScriptingInterface& parent, Mapping::Pointer mapping) + MappingBuilderProxy(ScriptingInterface& parent, Mapping::Pointer mapping) : _parent(parent), _mapping(mapping) { } Q_INVOKABLE QObject* from(const QJSValue& source); @@ -38,7 +40,7 @@ protected: QObject* from(const Endpoint::Pointer& source); friend class RouteBuilderProxy; - NewControllerScriptingInterface& _parent; + ScriptingInterface& _parent; Mapping::Pointer _mapping; }; diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp index e6b67e9ca6..50c3b534d1 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp @@ -12,7 +12,7 @@ #include #include "MappingBuilderProxy.h" -#include "../NewControllerScriptingInterface.h" +#include "../ScriptingInterface.h" #include "../Logging.h" namespace controller { diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index 63cd106edb..d7cf024468 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -19,12 +19,14 @@ class QScriptValue; namespace controller { -class NewControllerScriptingInterface; +class ScriptingInterface; +// TODO migrate functionality to a RouteBuilder class and make the proxy defer to that +// (for easier use in both C++ and JS) class RouteBuilderProxy : public QObject { Q_OBJECT public: - RouteBuilderProxy(NewControllerScriptingInterface& parent, Mapping::Pointer mapping, Route::Pointer route) + RouteBuilderProxy(ScriptingInterface& parent, Mapping::Pointer mapping, Route::Pointer route) : _parent(parent), _mapping(mapping), _route(route) { } Q_INVOKABLE void to(const QJSValue& destination); @@ -47,7 +49,7 @@ class RouteBuilderProxy : public QObject { Mapping::Pointer _mapping; Route::Pointer _route; - NewControllerScriptingInterface& _parent; + ScriptingInterface& _parent; }; } diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index bb90c04c95..4f2a525f07 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME entities-renderer) AUTOSCRIBE_SHADER_LIB(gpu model render render-utils) setup_hifi_library(Widgets Network Script) -link_hifi_libraries(shared gpu procedural model model-networking script-engine render render-utils) +link_hifi_libraries(shared gpu procedural model model-networking script-engine controllers render render-utils) target_bullet() diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 094a697012..4c33b2517a 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins gpu render-utils) +link_hifi_libraries(shared plugins controllers) GroupSources("src/input-plugins") diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index 2b16d905f5..b52dd3f658 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -22,7 +22,7 @@ InputPluginList getInputPlugins() { InputPlugin* PLUGIN_POOL[] = { new KeyboardMouseDevice(), new SDL2Manager(), - new SixenseManager(), + //new SixenseManager(), //new ViveControllerManager(), nullptr }; diff --git a/libraries/input-plugins/src/input-plugins/Joystick.cpp b/libraries/input-plugins/src/input-plugins/Joystick.cpp index 684b9e80d5..e7a0124deb 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.cpp +++ b/libraries/input-plugins/src/input-plugins/Joystick.cpp @@ -9,13 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - -#include - #include "Joystick.h" -#include "StandardControls.h" +#include +#include const float CONTROLLER_THRESHOLD = 0.3f; diff --git a/libraries/input-plugins/src/input-plugins/Joystick.h b/libraries/input-plugins/src/input-plugins/Joystick.h index 2a7a11d230..c6537acafe 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.h +++ b/libraries/input-plugins/src/input-plugins/Joystick.h @@ -20,8 +20,8 @@ #undef main #endif -#include "InputDevice.h" -#include "StandardControls.h" +#include +#include class Joystick : public QObject, public InputDevice { Q_OBJECT diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index e8a6131387..3c935cab26 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -16,7 +16,7 @@ #include -#include "InputDevice.h" +#include #include "InputPlugin.h" class QTouchEvent; diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.h b/libraries/input-plugins/src/input-plugins/SDL2Manager.h index 23e3ee059f..fec6972591 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.h +++ b/libraries/input-plugins/src/input-plugins/SDL2Manager.h @@ -16,9 +16,9 @@ #include #endif -#include "InputPlugin.h" -#include "UserInputMapper.h" +#include +#include "InputPlugin.h" #include "Joystick.h" class SDL2Manager : public InputPlugin { diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 9fa7f84a86..53ee7f3c29 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -24,8 +24,9 @@ #endif +#include + #include "InputPlugin.h" -#include "InputDevice.h" class QLibrary; diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h index 5cae8daaf4..bcc27d07ae 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h @@ -19,7 +19,7 @@ #include #include -#include "InputDevice.h" +#include #include "InputPlugin.h" #include #include diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index cfe0afd220..5e3d135034 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -1,3 +1,3 @@ set(TARGET_NAME script-engine) setup_hifi_library(Gui Network Script WebSockets Widgets) -link_hifi_libraries(shared networking octree gpu procedural model model-networking fbx entities animation audio physics) +link_hifi_libraries(shared networking octree gpu procedural model model-networking fbx entities controllers animation audio physics) diff --git a/libraries/script-engine/src/AbstractControllerScriptingInterface.h b/libraries/script-engine/src/AbstractControllerScriptingInterface.h deleted file mode 100644 index d6a6b51b62..0000000000 --- a/libraries/script-engine/src/AbstractControllerScriptingInterface.h +++ /dev/null @@ -1,125 +0,0 @@ -// -// AbstractControllerScriptingInterface.h -// libraries/script-engine/src -// -// Created by Brad Hefta-Gaub on 12/17/13. -// Copyright 2013 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 -// - -#ifndef hifi_AbstractControllerScriptingInterface_h -#define hifi_AbstractControllerScriptingInterface_h - -#include - -#include -#include - -#include "HFActionEvent.h" -#include "KeyEvent.h" -#include "MouseEvent.h" -#include "SpatialEvent.h" -#include "TouchEvent.h" -#include "WheelEvent.h" - -class ScriptEngine; - -class AbstractInputController : public QObject { - Q_OBJECT - -public: - typedef unsigned int Key; - - virtual void update() = 0; - - virtual Key getKey() const = 0; - -public slots: - - virtual bool isActive() const = 0; - virtual glm::vec3 getAbsTranslation() const = 0; - virtual glm::quat getAbsRotation() const = 0; - virtual glm::vec3 getLocTranslation() const = 0; - virtual glm::quat getLocRotation() const = 0; - -signals: - void spatialEvent(const SpatialEvent& event); - -}; - -/// handles scripting of input controller commands from JS -class AbstractControllerScriptingInterface : public QObject { - Q_OBJECT - -public slots: - virtual void registerControllerTypes(ScriptEngine* engine) = 0; - - virtual bool isPrimaryButtonPressed() const = 0; - virtual glm::vec2 getPrimaryJoystickPosition() const = 0; - - virtual int getNumberOfButtons() const = 0; - virtual bool isButtonPressed(int buttonIndex) const = 0; - - virtual int getNumberOfTriggers() const = 0; - virtual float getTriggerValue(int triggerIndex) const = 0; - - virtual int getNumberOfJoysticks() const = 0; - virtual glm::vec2 getJoystickPosition(int joystickIndex) const = 0; - - virtual int getNumberOfSpatialControls() const = 0; - virtual glm::vec3 getSpatialControlPosition(int controlIndex) const = 0; - virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const = 0; - virtual glm::vec3 getSpatialControlNormal(int controlIndex) const = 0; - virtual glm::quat getSpatialControlRawRotation(int controlIndex) const = 0; - - virtual void captureKeyEvents(const KeyEvent& event) = 0; - virtual void releaseKeyEvents(const KeyEvent& event) = 0; - - virtual void captureMouseEvents() = 0; - virtual void releaseMouseEvents() = 0; - - virtual void captureTouchEvents() = 0; - virtual void releaseTouchEvents() = 0; - - virtual void captureWheelEvents() = 0; - virtual void releaseWheelEvents() = 0; - - virtual void captureActionEvents() = 0; - virtual void releaseActionEvents() = 0; - - virtual void captureJoystick(int joystickIndex) = 0; - virtual void releaseJoystick(int joystickIndex) = 0; - - virtual glm::vec2 getViewportDimensions() const = 0; - - - virtual AbstractInputController* createInputController( const QString& category, const QString& tracker ) = 0; - -signals: - void keyPressEvent(const KeyEvent& event); - void keyReleaseEvent(const KeyEvent& event); - - void actionStartEvent(const HFActionEvent& event); - void actionEndEvent(const HFActionEvent& event); - - void backStartEvent(); - void backEndEvent(); - - void mouseMoveEvent(const MouseEvent& event, unsigned int deviceID = 0); - void mousePressEvent(const MouseEvent& event, unsigned int deviceID = 0); - void mouseDoublePressEvent(const MouseEvent& event, unsigned int deviceID = 0); - void mouseReleaseEvent(const MouseEvent& event, unsigned int deviceID = 0); - - void touchBeginEvent(const TouchEvent& event); - void touchEndEvent(const TouchEvent& event); - void touchUpdateEvent(const TouchEvent& event); - - void wheelEvent(const WheelEvent& event); - - void actionEvent(int action, float state); - -}; - -#endif // hifi_AbstractControllerScriptingInterface_h diff --git a/libraries/script-engine/src/AbstractScriptingServicesInterface.h b/libraries/script-engine/src/AbstractScriptingServicesInterface.h index 9d24531b60..565a415f63 100644 --- a/libraries/script-engine/src/AbstractScriptingServicesInterface.h +++ b/libraries/script-engine/src/AbstractScriptingServicesInterface.h @@ -12,7 +12,10 @@ #ifndef hifi_AbstractScriptingServicesInterface_h #define hifi_AbstractScriptingServicesInterface_h -class AbstractControllerScriptingInterface; +namespace controller { + class ScriptingInterface; +} + class Transform; class ScriptEngine; class QThread; @@ -22,7 +25,7 @@ class AbstractScriptingServicesInterface { public: /// Returns the controller interface for the application - virtual AbstractControllerScriptingInterface* getControllerScriptingInterface() = 0; + virtual controller::ScriptingInterface* getControllerScriptingInterface() = 0; /// Registers application specific services with a script engine. virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) = 0; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 76590f266b..40d4d664ce 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -76,16 +76,16 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) { out = qobject_cast(object.toQObject()); } -QScriptValue inputControllerToScriptValue(QScriptEngine *engine, AbstractInputController* const &in) { + +QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) { return engine->newQObject(in); } -void inputControllerFromScriptValue(const QScriptValue &object, AbstractInputController* &out) { - out = qobject_cast(object.toQObject()); +void inputControllerFromScriptValue(const QScriptValue &object, controller::InputController* &out) { + out = qobject_cast(object.toQObject()); } -ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, - AbstractControllerScriptingInterface* controllerScriptingInterface, bool wantSignals) : +ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, controller::ScriptingInterface* controllerScriptingInterface, bool wantSignals) : _scriptContents(scriptContents), _isFinished(false), @@ -93,7 +93,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isInitialized(false), _timerFunctionMap(), _wantSignals(wantSignals), - _controllerScriptingInterface(controllerScriptingInterface), _fileNameString(fileNameString), _quatLibrary(), _vec3Library(), @@ -301,7 +300,7 @@ void ScriptEngine::init() { globalObject().setProperty("AudioEffectOptions", audioEffectOptionsConstructorValue); qScriptRegisterMetaType(this, injectorToScriptValue, injectorFromScriptValue); - qScriptRegisterMetaType(this, inputControllerToScriptValue, inputControllerFromScriptValue); + //qScriptRegisterMetaType(this, inputControllerToScriptValue, inputControllerFromScriptValue); qScriptRegisterMetaType(this, avatarDataToScriptValue, avatarDataFromScriptValue); qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue); qScriptRegisterMetaType(this, webSocketToScriptValue, webSocketFromScriptValue); @@ -310,7 +309,7 @@ void ScriptEngine::init() { registerGlobalObject("Script", this); registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); - registerGlobalObject("Controller", _controllerScriptingInterface); +// registerGlobalObject("Controller", _controllerScriptingInterface); registerGlobalObject("Entities", entityScriptingInterface.data()); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); @@ -320,9 +319,9 @@ void ScriptEngine::init() { // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); - if (_controllerScriptingInterface) { - _controllerScriptingInterface->registerControllerTypes(this); - } + //if (_controllerScriptingInterface) { + // _controllerScriptingInterface->registerControllerTypes(this); + //} } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 1d3986143a..0108899571 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -26,8 +26,10 @@ #include #include #include +#include -#include "AbstractControllerScriptingInterface.h" + +#include "MouseEvent.h" #include "ArrayBufferClass.h" #include "AudioScriptingInterface.h" #include "Quat.h" @@ -53,7 +55,7 @@ class ScriptEngine : public QScriptEngine, public ScriptUser, public EntitiesScr public: ScriptEngine(const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString(""), - AbstractControllerScriptingInterface* controllerScriptingInterface = NULL, + controller::ScriptingInterface* controllerScriptingInterface = nullptr, bool wantSignals = true); ~ScriptEngine(); @@ -182,7 +184,6 @@ private: QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); void stopTimer(QTimer* timer); - AbstractControllerScriptingInterface* _controllerScriptingInterface; QString _fileNameString; Quat _quatLibrary; Vec3 _vec3Library; diff --git a/tests/controllers/qml/content.qml b/tests/controllers/qml/content.qml index 41d623a389..5f9bbd455e 100644 --- a/tests/controllers/qml/content.qml +++ b/tests/controllers/qml/content.qml @@ -8,17 +8,17 @@ import "./controls" Column { id: root - property var actions: NewControllers.Actions - property var standard: NewControllers.Standard + property var actions: Controllers.Actions + property var standard: Controllers.Standard property var testMapping: null property var xbox: null Component.onCompleted: { var patt = /^X360Controller/; - for (var prop in NewControllers.Hardware) { + for (var prop in Controllers.Hardware) { if(patt.test(prop)) { - root.xbox = NewControllers.Hardware[prop] + root.xbox = Controllers.Hardware[prop] break } } @@ -29,7 +29,7 @@ Column { Timer { interval: 50; running: true; repeat: true onTriggered: { - NewControllers.update(); + Controllers.update(); } } @@ -38,7 +38,7 @@ Column { Button { text: "Default Mapping" onClicked: { - var mapping = NewControllers.newMapping("Default"); + var mapping = Controllers.newMapping("Default"); mapping.from(xbox.A).to(standard.A); mapping.from(xbox.B).to(standard.B); mapping.from(xbox.X).to(standard.X); @@ -59,7 +59,7 @@ Column { mapping.from(xbox.RX).to(standard.RX); mapping.from(xbox.LT).to(standard.LT); mapping.from(xbox.RT).to(standard.RT); - NewControllers.enableMapping("Default"); + Controllers.enableMapping("Default"); enabled = false; text = "Built" } @@ -68,16 +68,35 @@ Column { Button { text: "Build Mapping" onClicked: { - var mapping = NewControllers.newMapping(); + var mapping = Controllers.newMapping(); // Inverting a value mapping.from(xbox.RY).invert().to(standard.RY); // Assigning a value from a function mapping.from(function() { return Math.sin(Date.now() / 250); }).to(standard.RX); // Constrainting a value to -1, 0, or 1, with a deadzone mapping.from(xbox.LY).deadZone(0.5).constrainToInteger().to(standard.LY); - mapping.join(standard.LB, standard.RB).pulse(0.5).to(actions.Yaw); + // change join to makeAxis + mapping.join(standard.LB, standard.RB).to(actions.Yaw); mapping.from(actions.Yaw).clamp(0, 1).invert().to(actions.YAW_RIGHT); mapping.from(actions.Yaw).clamp(-1, 0).to(actions.YAW_LEFT); + + // mapping.modifier(keyboard.Ctrl).scale(2.0) + +// mapping.from(keyboard.A).to(actions.TranslateLeft) +// mapping.from(keyboard.A, keyboard.Shift).to(actions.TurnLeft) +// mapping.from(keyboard.A, keyboard.Shift, keyboard.Ctrl).scale(2.0).to(actions.TurnLeft) + +// // First loopbacks +// // Then non-loopbacks by constraint level (number of inputs) +// mapping.from(xbox.RX).deadZone(0.2).to(xbox.RX) + +// mapping.from(standard.RB, standard.LB, keyboard.Shift).to(actions.TurnLeft) + + +// mapping.from(keyboard.A, keyboard.Shift).to(actions.TurnLeft) + + +// mapping.from(keyboard.W).when(keyboard.Shift).to(actions.Forward) testMapping = mapping; enabled = false text = "Built" @@ -105,7 +124,7 @@ Column { Row { spacing: 8 ScrollingGraph { - controlId: NewControllers.Actions.Yaw + controlId: Controllers.Actions.Yaw label: "Yaw" min: -3.0 max: 3.0 @@ -113,7 +132,7 @@ Column { } ScrollingGraph { - controlId: NewControllers.Actions.YAW_LEFT + controlId: Controllers.Actions.YAW_LEFT label: "Yaw Left" min: -3.0 max: 3.0 @@ -121,7 +140,7 @@ Column { } ScrollingGraph { - controlId: NewControllers.Actions.YAW_RIGHT + controlId: Controllers.Actions.YAW_RIGHT label: "Yaw Right" min: -3.0 max: 3.0 diff --git a/tests/controllers/qml/controls/AnalogButton.qml b/tests/controllers/qml/controls/AnalogButton.qml index 26f91458ac..141c131063 100644 --- a/tests/controllers/qml/controls/AnalogButton.qml +++ b/tests/controllers/qml/controls/AnalogButton.qml @@ -13,7 +13,7 @@ Item { property color color: 'black' function update() { - value = NewControllers.getValue(controlId); + value = Controllers.getValue(controlId); canvas.requestPaint(); } diff --git a/tests/controllers/qml/controls/AnalogStick.qml b/tests/controllers/qml/controls/AnalogStick.qml index 8860aea49c..5d011411c9 100644 --- a/tests/controllers/qml/controls/AnalogStick.qml +++ b/tests/controllers/qml/controls/AnalogStick.qml @@ -15,8 +15,8 @@ Item { function update() { value = Qt.vector2d( - NewControllers.getValue(controlIds[0]), - NewControllers.getValue(controlIds[1]) + Controllers.getValue(controlIds[0]), + Controllers.getValue(controlIds[1]) ); canvas.requestPaint(); } diff --git a/tests/controllers/qml/controls/ScrollingGraph.qml b/tests/controllers/qml/controls/ScrollingGraph.qml index 69f919aaf1..471d142d27 100644 --- a/tests/controllers/qml/controls/ScrollingGraph.qml +++ b/tests/controllers/qml/controls/ScrollingGraph.qml @@ -22,7 +22,7 @@ Item { property string label: "" function update() { - value = NewControllers.getValue(controlId); + value = Controllers.getValue(controlId); canvas.requestPaint(); } diff --git a/tests/controllers/qml/controls/ToggleButton.qml b/tests/controllers/qml/controls/ToggleButton.qml index 9ef54f5971..46a7b4bdfd 100644 --- a/tests/controllers/qml/controls/ToggleButton.qml +++ b/tests/controllers/qml/controls/ToggleButton.qml @@ -15,7 +15,7 @@ Item { Timer { interval: 50; running: true; repeat: true onTriggered: { - root.value = NewControllers.getValue(root.controlId); + root.value = Controllers.getValue(root.controlId); canvas.requestPaint(); } } diff --git a/tests/controllers/src/main.cpp b/tests/controllers/src/main.cpp index 7182862ff1..3a45195439 100644 --- a/tests/controllers/src/main.cpp +++ b/tests/controllers/src/main.cpp @@ -38,10 +38,10 @@ #include #include #include -#include +#include #include -#include +#include const QString& getQmlDir() { static QString dir; @@ -87,6 +87,22 @@ int main(int argc, char** argv) { } + QTimer timer; + QObject::connect(&timer, &QTimer::timeout, [] { + static float last = secTimestampNow(); + float now = secTimestampNow(); + float delta = now - last; + last = now; + + foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { + inputPlugin->pluginUpdate(delta, false); + } + + auto userInputMapper = DependencyManager::get(); + userInputMapper->update(delta); + }); + timer.start(50); + { DependencyManager::set(); foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { @@ -98,17 +114,9 @@ int main(int argc, char** argv) { keyboardMouseDevice->registerToUserInputMapper(*userInputMapper); } } - - //new PluginContainerProxy(); auto rootContext = engine.rootContext(); - - auto controllers = new NewControllerScriptingInterface(); - rootContext->setContextProperty("NewControllers", controllers); - QVariantMap map; - map.insert("Hardware", controllers->property("Hardware")); - map.insert("Actions", controllers->property("Actions")); - rootContext->setContextProperty("ControllerIds", map); + rootContext->setContextProperty("Controllers", new ScriptingInterface()); } engine.load(getQmlDir() + "main.qml"); app.exec(); From e39219c2b5a7e2d52b4de105d736c90015998255 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 14 Oct 2015 16:51:52 -0700 Subject: [PATCH 14/16] Fixes and PR comments --- .../scripts/controllerScriptingExamples.js | 38 +++++++++++++------ examples/mouseLook.js | 2 +- .../ControllerScriptingInterface.cpp | 19 +++++++++- .../scripting/ControllerScriptingInterface.h | 2 +- .../src/controllers/ScriptingInterface.cpp | 10 +++-- .../src/controllers/ScriptingInterface.h | 2 +- .../src/controllers/StandardControls.h | 5 +++ .../src/input-plugins/InputPlugin.cpp | 4 +- libraries/script-engine/src/ScriptEngine.cpp | 15 ++++---- libraries/script-engine/src/ScriptEngine.h | 1 + 10 files changed, 69 insertions(+), 29 deletions(-) diff --git a/examples/example/scripts/controllerScriptingExamples.js b/examples/example/scripts/controllerScriptingExamples.js index e678ff26eb..b3dc92029d 100644 --- a/examples/example/scripts/controllerScriptingExamples.js +++ b/examples/example/scripts/controllerScriptingExamples.js @@ -11,6 +11,16 @@ // Assumes you only have the default keyboard connected +function findAction(name) { + var actions = Controller.getAllActions(); + for (var i = 0; i < actions.length; i++) { + if (actions[i].actionName == name) { + return i; + } + } + // If the action isn't found, it will default to the first available action + return 0; +} var hydra = Controller.Hardware.Hydra2; @@ -46,44 +56,48 @@ Controller.resetAllDeviceBindings(); // Query all actions print("All Actions: \n" + Controller.getAllActions()); +var actionId = findAction("YAW_LEFT") + +print("Yaw Left action ID: " + actionId) + // Each action stores: // action: int representation of enum -print("Action 5 int: \n" + Controller.getAllActions()[5].action); +print("Action int: \n" + Controller.getAllActions()[actionId].action); // actionName: string representation of enum -print("Action 5 name: \n" + Controller.getAllActions()[5].actionName); +print("Action name: \n" + Controller.getAllActions()[actionId].actionName); // inputChannels: list of all inputchannels that control that action -print("Action 5 input channels: \n" + Controller.getAllActions()[5].inputChannels + "\n"); +print("Action input channels: \n" + Controller.getAllActions()[actionId].inputChannels + "\n"); // Each input channel stores: // action: Action that this InputChannel maps to -print("Input channel action: \n" + Controller.getAllActions()[5].inputChannels[0].action); +print("Input channel action: \n" + Controller.getAllActions()[actionId].inputChannels[0].action); // scale: sensitivity of input -print("Input channel scale: \n" + Controller.getAllActions()[5].inputChannels[0].scale); +print("Input channel scale: \n" + Controller.getAllActions()[actionId].inputChannels[0].scale); // input and modifier: Inputs -print("Input channel input and modifier: \n" + Controller.getAllActions()[5].inputChannels[0].input + "\n" + Controller.getAllActions()[5].inputChannels[0].modifier + "\n"); +print("Input channel input and modifier: \n" + Controller.getAllActions()[actionId].inputChannels[0].input + "\n" + Controller.getAllActions()[actionId].inputChannels[0].modifier + "\n"); // Each Input stores: // device: device of input -print("Input device: \n" + Controller.getAllActions()[5].inputChannels[0].input.device); +print("Input device: \n" + Controller.getAllActions()[actionId].inputChannels[0].input.device); // channel: channel of input -print("Input channel: \n" + Controller.getAllActions()[5].inputChannels[0].input.channel); +print("Input channel: \n" + Controller.getAllActions()[actionId].inputChannels[0].input.channel); // type: type of input (Unknown, Button, Axis, Joint) -print("Input type: \n" + Controller.getAllActions()[5].inputChannels[0].input.type); +print("Input type: \n" + Controller.getAllActions()[actionId].inputChannels[0].input.type); // id: id of input -print("Input id: \n" + Controller.getAllActions()[5].inputChannels[0].input.id + "\n"); +print("Input id: \n" + Controller.getAllActions()[actionId].inputChannels[0].input.id + "\n"); // You can get the name of a device from its id -print("Device 1 name: \n" + Controller.getDeviceName(Controller.getAllActions()[5].inputChannels[0].input.id)); +print("Device 1 name: \n" + Controller.getDeviceName(Controller.getAllActions()[actionId].inputChannels[0].input.id)); // You can also get all of a devices input channels print("Device 1's input channels: \n" + Controller.getAllInputsForDevice(1) + "\n"); @@ -119,7 +133,7 @@ for (i = 0; i < availableInputs.length; i++) { // You can modify key bindings by using these avaiable inputs // This will replace e (up) with 6 -var e = Controller.getAllActions()[5].inputChannels[0]; +var e = Controller.getAllActions()[actionId].inputChannels[0]; Controller.removeInputChannel(e); e.input = availableInputs[6].input; Controller.addInputChannel(e); \ No newline at end of file diff --git a/examples/mouseLook.js b/examples/mouseLook.js index 880ec138c4..81bc9d2813 100644 --- a/examples/mouseLook.js +++ b/examples/mouseLook.js @@ -38,7 +38,7 @@ var mouseLook = (function () { keyboardID = 0; function onKeyPressEvent(event) { - if (event.text == 'M') { + if (event.text == 'm') { active = !active; updateMapping(); } diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 1a212fbea9..f1f7b08587 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "Application.h" #include "devices/MotionTracker.h" @@ -115,7 +116,7 @@ void inputPairFromScriptValue(const QScriptValue& object, UserInputMapper::Input inputPair.second = QString(object.property("inputName").toVariant().toString()); } -void ControllerScriptingInterface::registerControllerTypes(ScriptEngine* engine) { +void ControllerScriptingInterface::registerControllerTypes(QScriptEngine* engine) { qScriptRegisterSequenceMetaType >(engine); qScriptRegisterSequenceMetaType >(engine); qScriptRegisterSequenceMetaType >(engine); @@ -426,11 +427,25 @@ void ControllerScriptingInterface::releaseInputController(controller::InputContr } void ControllerScriptingInterface::update() { - controller::ScriptingInterface::update(); + static float last = secTimestampNow(); + float now = secTimestampNow(); + float delta = now - last; + last = now; + + for(auto inputPlugin : PluginManager::getInstance()->getInputPlugins()) { + if (inputPlugin->isActive()) { + inputPlugin->pluginUpdate(delta, false); + } + } + + auto userInputMapper = DependencyManager::get(); + userInputMapper->update(delta); for (auto entry : _inputControllers) { entry.second->update(); } + + controller::ScriptingInterface::update(); } QVector ControllerScriptingInterface::getAllActions() { diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 652bd640b1..25d9a523d3 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -88,7 +88,7 @@ public: Q_INVOKABLE QVector getActionNames() const; - virtual void registerControllerTypes(ScriptEngine* engine); + virtual void registerControllerTypes(QScriptEngine* engine); void emitKeyPressEvent(QKeyEvent* event); void emitKeyReleaseEvent(QKeyEvent* event); diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index 9d2cdfd2de..a843775dcc 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -357,7 +357,7 @@ namespace controller { } int ScriptingInterface::getNumberOfTriggers() const { - return 2; + return StandardCounts::TRIGGERS; } float ScriptingInterface::getTriggerValue(int triggerIndex) const { @@ -365,7 +365,7 @@ namespace controller { } int ScriptingInterface::getNumberOfJoysticks() const { - return 2; + return StandardCounts::ANALOG_STICKS; } glm::vec2 ScriptingInterface::getJoystickPosition(int joystickIndex) const { @@ -382,22 +382,26 @@ namespace controller { } int ScriptingInterface::getNumberOfSpatialControls() const { - return 2; + return StandardCounts::POSES; } glm::vec3 ScriptingInterface::getSpatialControlPosition(int controlIndex) const { + // FIXME extract the position from the standard pose return vec3(); } glm::vec3 ScriptingInterface::getSpatialControlVelocity(int controlIndex) const { + // FIXME extract the velocity from the standard pose return vec3(); } glm::vec3 ScriptingInterface::getSpatialControlNormal(int controlIndex) const { + // FIXME extract the normal from the standard pose return vec3(); } glm::quat ScriptingInterface::getSpatialControlRawRotation(int controlIndex) const { + // FIXME extract the rotation from the standard pose return quat(); } } // namespace controllers diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index 043e06a67f..0e0e38e055 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -99,7 +99,7 @@ namespace controller { public slots: virtual void update(); - //virtual void registerControllerTypes(ScriptEngine* engine) = 0; + virtual void registerControllerTypes(QScriptEngine* engine) = 0; private: friend class MappingBuilderProxy; diff --git a/libraries/controllers/src/controllers/StandardControls.h b/libraries/controllers/src/controllers/StandardControls.h index 505b4f85c7..0990e34224 100644 --- a/libraries/controllers/src/controllers/StandardControls.h +++ b/libraries/controllers/src/controllers/StandardControls.h @@ -56,4 +56,9 @@ namespace controller { NUM_STANDARD_POSES }; + enum StandardCounts { + TRIGGERS = 2, + ANALOG_STICKS = 2, + POSES = 2, // FIXME 3? if we want to expose the head? + }; } diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index b52dd3f658..227bd12e1b 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -22,8 +22,8 @@ InputPluginList getInputPlugins() { InputPlugin* PLUGIN_POOL[] = { new KeyboardMouseDevice(), new SDL2Manager(), - //new SixenseManager(), - //new ViveControllerManager(), + new SixenseManager(), + new ViveControllerManager(), nullptr }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 40d4d664ce..494f038a61 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -76,7 +76,6 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) { out = qobject_cast(object.toQObject()); } - QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) { return engine->newQObject(in); } @@ -85,7 +84,8 @@ void inputControllerFromScriptValue(const QScriptValue &object, controller::Inpu out = qobject_cast(object.toQObject()); } -ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, controller::ScriptingInterface* controllerScriptingInterface, bool wantSignals) : +ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, + controller::ScriptingInterface* controllerScriptingInterface, bool wantSignals) : _scriptContents(scriptContents), _isFinished(false), @@ -93,6 +93,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isInitialized(false), _timerFunctionMap(), _wantSignals(wantSignals), + _controllerScriptingInterface(controllerScriptingInterface), _fileNameString(fileNameString), _quatLibrary(), _vec3Library(), @@ -300,7 +301,7 @@ void ScriptEngine::init() { globalObject().setProperty("AudioEffectOptions", audioEffectOptionsConstructorValue); qScriptRegisterMetaType(this, injectorToScriptValue, injectorFromScriptValue); - //qScriptRegisterMetaType(this, inputControllerToScriptValue, inputControllerFromScriptValue); + qScriptRegisterMetaType(this, inputControllerToScriptValue, inputControllerFromScriptValue); qScriptRegisterMetaType(this, avatarDataToScriptValue, avatarDataFromScriptValue); qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue); qScriptRegisterMetaType(this, webSocketToScriptValue, webSocketFromScriptValue); @@ -309,7 +310,7 @@ void ScriptEngine::init() { registerGlobalObject("Script", this); registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); -// registerGlobalObject("Controller", _controllerScriptingInterface); + registerGlobalObject("Controller", _controllerScriptingInterface); registerGlobalObject("Entities", entityScriptingInterface.data()); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); @@ -319,9 +320,9 @@ void ScriptEngine::init() { // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); - //if (_controllerScriptingInterface) { - // _controllerScriptingInterface->registerControllerTypes(this); - //} + if (_controllerScriptingInterface) { + _controllerScriptingInterface->registerControllerTypes(this); + } } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 0108899571..642159339e 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -184,6 +184,7 @@ private: QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); void stopTimer(QTimer* timer); + controller::ScriptingInterface* _controllerScriptingInterface; QString _fileNameString; Quat _quatLibrary; Vec3 _vec3Library; From 10df0f2d8c097889c32789a37ea2467eedd74e86 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 14 Oct 2015 17:07:10 -0700 Subject: [PATCH 15/16] Fix broken assignment-client build --- assignment-client/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index e543b3aa21..5b92dfba99 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -1,12 +1,12 @@ set(TARGET_NAME assignment-client) -setup_hifi_project(Core Gui Network Script Widgets WebSockets) +setup_hifi_project(Core Gui Network Script Quick Widgets WebSockets) # link in the shared libraries link_hifi_libraries( audio avatars octree environment gpu model fbx entities networking animation shared script-engine embedded-webserver - physics + controllers physics ) include_application_version() From 195045a4ec8a29c11ef65a1cecf433bcca756c98 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 14 Oct 2015 17:20:30 -0700 Subject: [PATCH 16/16] Next time remember to hit build all before commiting --- tests/controllers/src/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/controllers/src/main.cpp b/tests/controllers/src/main.cpp index 3a45195439..2056e34551 100644 --- a/tests/controllers/src/main.cpp +++ b/tests/controllers/src/main.cpp @@ -79,6 +79,12 @@ public: virtual const DisplayPlugin* getActiveDisplayPlugin() const override { return nullptr; } }; +class MyControllerScriptingInterface : public controller::ScriptingInterface { +public: + virtual void registerControllerTypes(QScriptEngine* engine) {}; +}; + + int main(int argc, char** argv) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; @@ -116,7 +122,7 @@ int main(int argc, char** argv) { } //new PluginContainerProxy(); auto rootContext = engine.rootContext(); - rootContext->setContextProperty("Controllers", new ScriptingInterface()); + rootContext->setContextProperty("Controllers", new MyControllerScriptingInterface()); } engine.load(getQmlDir() + "main.qml"); app.exec();