From ae2f7f6ff687ab86f70a8fc8a77cefb29c9e9f04 Mon Sep 17 00:00:00 2001 From: AlessandroSigna Date: Thu, 22 Oct 2015 18:50:23 -0700 Subject: [PATCH 01/14] Fix paddleBall.js --- examples/controllers/hydra/paddleBall.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/controllers/hydra/paddleBall.js b/examples/controllers/hydra/paddleBall.js index 13c6e2eb62..91b2520e1d 100644 --- a/examples/controllers/hydra/paddleBall.js +++ b/examples/controllers/hydra/paddleBall.js @@ -32,14 +32,14 @@ var SPRING_FORCE = 15.0; var lastSoundTime = 0; var gameOn = false; var leftHanded = true; -var controllerID; +var hand; function setControllerID() { if (leftHanded) { - controllerID = 1; + hand = Controller.Standard.LeftHand; } else { - controllerID = 3; + hand = Controller.Standard.RightHand; } } @@ -63,7 +63,7 @@ var ball, paddle, paddleModel, line; function createEntities() { ball = Entities.addEntity( { type: "Sphere", - position: Controller.getSpatialControlPosition(controllerID), + position: Controller.getPoseValue(hand).translation, dimensions: { x: BALL_SIZE, y: BALL_SIZE, z: BALL_SIZE }, color: BALL_COLOR, gravity: { x: 0, y: GRAVITY, z: 0 }, @@ -73,27 +73,27 @@ function createEntities() { paddle = Entities.addEntity( { type: "Box", - position: Controller.getSpatialControlPosition(controllerID), + position: Controller.getPoseValue(hand).translation, dimensions: { x: PADDLE_SIZE, y: PADDLE_THICKNESS, z: PADDLE_SIZE * 0.80 }, color: PADDLE_COLOR, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, damping: 0.10, visible: false, - rotation: Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)), + rotation: Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation, collisionsWillMove: false }); modelURL = "http://public.highfidelity.io/models/attachments/pong_paddle.fbx"; paddleModel = Entities.addEntity( { type: "Model", - position: Vec3.sum(Controller.getSpatialControlPosition(controllerID), PADDLE_BOX_OFFSET), + position: Vec3.sum(Controller.getPoseValue(hand).translation, PADDLE_BOX_OFFSET), dimensions: { x: PADDLE_SIZE * 1.5, y: PADDLE_THICKNESS, z: PADDLE_SIZE * 1.25 }, color: PADDLE_COLOR, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: true, modelURL: modelURL, damping: 0.10, - rotation: Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)), + rotation: Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation, collisionsWillMove: false }); line = Overlays.addOverlay("line3d", { @@ -118,7 +118,7 @@ function deleteEntities() { } function update(deltaTime) { - var palmPosition = Controller.getSpatialControlPosition(controllerID); + var palmPosition = Controller.getPoseValue(hand).translation; var controllerActive = (Vec3.length(palmPosition) > 0); if (!gameOn && controllerActive) { @@ -133,7 +133,7 @@ function update(deltaTime) { } var paddleOrientation = leftHanded ? PADDLE_ORIENTATION : Quat.multiply(PADDLE_ORIENTATION, Quat.fromPitchYawRollDegrees(0, 180, 0)); - var paddleWorldOrientation = Quat.multiply(Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(controllerID)), paddleOrientation); + var paddleWorldOrientation = Quat.multiply(Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation), paddleOrientation); var holdPosition = Vec3.sum(leftHanded ? MyAvatar.getLeftPalmPosition() : MyAvatar.getRightPalmPosition(), Vec3.multiplyQbyV(paddleWorldOrientation, leftHanded ? HOLD_POSITION_LEFT_OFFSET : HOLD_POSITION_RIGHT_OFFSET )); @@ -146,10 +146,10 @@ function update(deltaTime) { Entities.editEntity(ball, { velocity: ballVelocity }); Overlays.editOverlay(line, { start: props.position, end: holdPosition }); Entities.editEntity(paddle, { position: holdPosition, - velocity: Controller.getSpatialControlVelocity(controllerID), + velocity: Controller.getPoseValue(hand).velocity, rotation: paddleWorldOrientation }); Entities.editEntity(paddleModel, { position: Vec3.sum(holdPosition, Vec3.multiplyQbyV(paddleWorldOrientation, PADDLE_BOX_OFFSET)), - velocity: Controller.getSpatialControlVelocity(controllerID), + velocity: Controller.getPoseValue(hand).velocity, rotation: paddleWorldOrientation }); } From 6001968d92732671eb80504bece7de2857d2f5f0 Mon Sep 17 00:00:00 2001 From: AlessandroSigna Date: Fri, 23 Oct 2015 13:52:22 -0700 Subject: [PATCH 02/14] Fix paddleBall.js --- examples/controllers/hydra/paddleBall.js | 32 ++++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/examples/controllers/hydra/paddleBall.js b/examples/controllers/hydra/paddleBall.js index 91b2520e1d..87e81b6801 100644 --- a/examples/controllers/hydra/paddleBall.js +++ b/examples/controllers/hydra/paddleBall.js @@ -37,9 +37,17 @@ var hand; function setControllerID() { if (leftHanded) { - hand = Controller.Standard.LeftHand; + hand = MyAvatar.getLeftHandPose(); } else { - hand = Controller.Standard.RightHand; + hand = MyAvatar.rightHandPosition; + } +} + +function getHandPose(){ + if (leftHanded) { + return MyAvatar.getLeftHandPose(); + } else { + return MyAvatar.rightHandPosition; } } @@ -63,7 +71,7 @@ var ball, paddle, paddleModel, line; function createEntities() { ball = Entities.addEntity( { type: "Sphere", - position: Controller.getPoseValue(hand).translation, + position: getHandPose().translation, dimensions: { x: BALL_SIZE, y: BALL_SIZE, z: BALL_SIZE }, color: BALL_COLOR, gravity: { x: 0, y: GRAVITY, z: 0 }, @@ -73,27 +81,29 @@ function createEntities() { paddle = Entities.addEntity( { type: "Box", - position: Controller.getPoseValue(hand).translation, + position: getHandPose().translation, dimensions: { x: PADDLE_SIZE, y: PADDLE_THICKNESS, z: PADDLE_SIZE * 0.80 }, color: PADDLE_COLOR, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, damping: 0.10, visible: false, - rotation: Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation, + //rotation: Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation, + rotation : getHandPose().rotation, collisionsWillMove: false }); modelURL = "http://public.highfidelity.io/models/attachments/pong_paddle.fbx"; paddleModel = Entities.addEntity( { type: "Model", - position: Vec3.sum(Controller.getPoseValue(hand).translation, PADDLE_BOX_OFFSET), + position: Vec3.sum(hand, PADDLE_BOX_OFFSET), dimensions: { x: PADDLE_SIZE * 1.5, y: PADDLE_THICKNESS, z: PADDLE_SIZE * 1.25 }, color: PADDLE_COLOR, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: true, modelURL: modelURL, damping: 0.10, - rotation: Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation, + //rotation: Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation, + rotation : getHandPose().rotation, collisionsWillMove: false }); line = Overlays.addOverlay("line3d", { @@ -118,7 +128,7 @@ function deleteEntities() { } function update(deltaTime) { - var palmPosition = Controller.getPoseValue(hand).translation; + var palmPosition = getHandPose().translation; var controllerActive = (Vec3.length(palmPosition) > 0); if (!gameOn && controllerActive) { @@ -133,7 +143,7 @@ function update(deltaTime) { } var paddleOrientation = leftHanded ? PADDLE_ORIENTATION : Quat.multiply(PADDLE_ORIENTATION, Quat.fromPitchYawRollDegrees(0, 180, 0)); - var paddleWorldOrientation = Quat.multiply(Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation), paddleOrientation); + var paddleWorldOrientation = Quat.multiply(getHandPose().rotation, paddleOrientation); var holdPosition = Vec3.sum(leftHanded ? MyAvatar.getLeftPalmPosition() : MyAvatar.getRightPalmPosition(), Vec3.multiplyQbyV(paddleWorldOrientation, leftHanded ? HOLD_POSITION_LEFT_OFFSET : HOLD_POSITION_RIGHT_OFFSET )); @@ -146,10 +156,10 @@ function update(deltaTime) { Entities.editEntity(ball, { velocity: ballVelocity }); Overlays.editOverlay(line, { start: props.position, end: holdPosition }); Entities.editEntity(paddle, { position: holdPosition, - velocity: Controller.getPoseValue(hand).velocity, + velocity: getHandPose().velocity, //fix this maybe rotation: paddleWorldOrientation }); Entities.editEntity(paddleModel, { position: Vec3.sum(holdPosition, Vec3.multiplyQbyV(paddleWorldOrientation, PADDLE_BOX_OFFSET)), - velocity: Controller.getPoseValue(hand).velocity, + velocity: getHandPose().velocity, //fix this maybe rotation: paddleWorldOrientation }); } From 37e1e43ce0b573ce77d08a38be06c363ab6d5253 Mon Sep 17 00:00:00 2001 From: AlessandroSigna Date: Fri, 23 Oct 2015 15:48:29 -0700 Subject: [PATCH 03/14] Fix paddleBall.js --- examples/controllers/hydra/paddleBall.js | 49 +++++++----------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/examples/controllers/hydra/paddleBall.js b/examples/controllers/hydra/paddleBall.js index 87e81b6801..d90a78c260 100644 --- a/examples/controllers/hydra/paddleBall.js +++ b/examples/controllers/hydra/paddleBall.js @@ -20,10 +20,11 @@ var BALL_SIZE = 0.08; var PADDLE_SIZE = 0.20; var PADDLE_THICKNESS = 0.06; var PADDLE_COLOR = { red: 184, green: 134, blue: 11 }; -var BALL_COLOR = { red: 255, green: 0, blue: 0 }; +var BALL_COLOR = { red: 0, green: 255, blue: 0 }; var LINE_COLOR = { red: 255, green: 255, blue: 0 }; var PADDLE_BOX_OFFSET = { x: 0.05, y: 0.0, z: 0.0 }; +//probably we need to fix these initial values (offsets and orientation) var HOLD_POSITION_LEFT_OFFSET = { x: -0.15, y: 0.05, z: -0.05 }; var HOLD_POSITION_RIGHT_OFFSET = { x: -0.15, y: 0.05, z: 0.05 }; var PADDLE_ORIENTATION = Quat.fromPitchYawRollDegrees(0,0,0); @@ -32,26 +33,7 @@ var SPRING_FORCE = 15.0; var lastSoundTime = 0; var gameOn = false; var leftHanded = true; -var hand; - -function setControllerID() { - if (leftHanded) { - hand = MyAvatar.getLeftHandPose(); - } else { - hand = MyAvatar.rightHandPosition; - } -} - -function getHandPose(){ - if (leftHanded) { - return MyAvatar.getLeftHandPose(); - } else { - return MyAvatar.rightHandPosition; - } -} - -setControllerID(); Menu.addMenu("PaddleBall"); Menu.addMenuItem({ menuName: "PaddleBall", menuItemName: "Left-Handed", isCheckable: true, isChecked: true }); @@ -71,7 +53,7 @@ var ball, paddle, paddleModel, line; function createEntities() { ball = Entities.addEntity( { type: "Sphere", - position: getHandPose().translation, + position: leftHanded ? MyAvatar.leftHandPose.translation : MyAvatar.rightHandPose.translation, dimensions: { x: BALL_SIZE, y: BALL_SIZE, z: BALL_SIZE }, color: BALL_COLOR, gravity: { x: 0, y: GRAVITY, z: 0 }, @@ -81,30 +63,28 @@ function createEntities() { paddle = Entities.addEntity( { type: "Box", - position: getHandPose().translation, + position: leftHanded ? MyAvatar.leftHandPose.translation : MyAvatar.rightHandPose.translation, dimensions: { x: PADDLE_SIZE, y: PADDLE_THICKNESS, z: PADDLE_SIZE * 0.80 }, color: PADDLE_COLOR, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, damping: 0.10, visible: false, - //rotation: Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation, - rotation : getHandPose().rotation, - collisionsWillMove: false }); + rotation : leftHanded ? MyAvatar.leftHandPose.rotation : MyAvatar.rightHandPose.rotation, + collisionsWillMove: false }); modelURL = "http://public.highfidelity.io/models/attachments/pong_paddle.fbx"; paddleModel = Entities.addEntity( { type: "Model", - position: Vec3.sum(hand, PADDLE_BOX_OFFSET), + position: Vec3.sum( leftHanded ? MyAvatar.leftHandPose.translation : MyAvatar.rightHandPose.translation, PADDLE_BOX_OFFSET), dimensions: { x: PADDLE_SIZE * 1.5, y: PADDLE_THICKNESS, z: PADDLE_SIZE * 1.25 }, color: PADDLE_COLOR, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: true, modelURL: modelURL, damping: 0.10, - //rotation: Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(hand).rotation, - rotation : getHandPose().rotation, - collisionsWillMove: false }); + rotation : leftHanded ? MyAvatar.leftHandPose.rotation : MyAvatar.rightHandPose.rotation, + collisionsWillMove: false }); line = Overlays.addOverlay("line3d", { start: { x: 0, y: 0, z: 0 }, @@ -128,7 +108,7 @@ function deleteEntities() { } function update(deltaTime) { - var palmPosition = getHandPose().translation; + var palmPosition = leftHanded ? MyAvatar.leftHandPose.translation : MyAvatar.rightHandPose.translation; var controllerActive = (Vec3.length(palmPosition) > 0); if (!gameOn && controllerActive) { @@ -143,8 +123,8 @@ function update(deltaTime) { } var paddleOrientation = leftHanded ? PADDLE_ORIENTATION : Quat.multiply(PADDLE_ORIENTATION, Quat.fromPitchYawRollDegrees(0, 180, 0)); - var paddleWorldOrientation = Quat.multiply(getHandPose().rotation, paddleOrientation); - var holdPosition = Vec3.sum(leftHanded ? MyAvatar.getLeftPalmPosition() : MyAvatar.getRightPalmPosition(), + var paddleWorldOrientation = Quat.multiply(leftHanded ? MyAvatar.leftHandPose.rotation : MyAvatar.rightHandPose.rotation, paddleOrientation); + var holdPosition = Vec3.sum(leftHanded ? MyAvatar.leftHandPose.translation : MyAvatar.rightHandPose.translation, Vec3.multiplyQbyV(paddleWorldOrientation, leftHanded ? HOLD_POSITION_LEFT_OFFSET : HOLD_POSITION_RIGHT_OFFSET )); var props = Entities.getEntityProperties(ball); @@ -156,10 +136,10 @@ function update(deltaTime) { Entities.editEntity(ball, { velocity: ballVelocity }); Overlays.editOverlay(line, { start: props.position, end: holdPosition }); Entities.editEntity(paddle, { position: holdPosition, - velocity: getHandPose().velocity, //fix this maybe + velocity: leftHanded ? MyAvatar.leftHandPose.velocity : MyAvatar.rightHandPose.velocity, rotation: paddleWorldOrientation }); Entities.editEntity(paddleModel, { position: Vec3.sum(holdPosition, Vec3.multiplyQbyV(paddleWorldOrientation, PADDLE_BOX_OFFSET)), - velocity: getHandPose().velocity, //fix this maybe + velocity: leftHanded ? MyAvatar.leftHandPose.velocity : MyAvatar.rightHandPose.velocity, rotation: paddleWorldOrientation }); } @@ -192,7 +172,6 @@ function menuItemEvent(menuItem) { leftHanded = Menu.isOptionChecked("Left-Handed"); } if ((leftHanded != oldHanded) && gameOn) { - setControllerID(); deleteEntities(); createEntities(); } From d5a90e273e418d02cfa0f69c8ee3687753df6b53 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 23 Oct 2015 15:56:55 -0700 Subject: [PATCH 04/14] fix AnyEndpoint support from JS --- .../src/controllers/UserInputMapper.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index e924718fca..30fd650eba 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -217,10 +217,10 @@ public: } virtual float value() override { - float result = 0; + float result = 0.0f; for (auto& child : _children) { float childResult = child->value(); - if (childResult != 0.0f) { + if (childResult != 0.0f && result == 0.0f) { result = childResult; } } @@ -856,6 +856,21 @@ Endpoint::Pointer UserInputMapper::endpointFor(const QScriptValue& endpoint) { return result; } + if (endpoint.isArray()) { + int length = endpoint.property("length").toInteger(); + Endpoint::List children; + for (int i = 0; i < length; i++) { + QScriptValue arrayItem = endpoint.property(i); + Endpoint::Pointer destination = endpointFor(arrayItem); + if (!destination) { + return Endpoint::Pointer(); + } + children.push_back(destination); + } + return std::make_shared(children); + } + + qWarning() << "Unsupported input type " << endpoint.toString(); return Endpoint::Pointer(); } From 6b795364c8ed52a2ee2a82d557906710066c86d7 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 23 Oct 2015 16:30:40 -0700 Subject: [PATCH 05/14] make handGrab treat shoulder bumbers and triggers as merged control --- examples/controllers/handControllerGrab.js | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 17d16d1718..80a3ea98a4 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -148,6 +148,7 @@ function MyController(hand, triggerAction) { this.state = STATE_OFF; this.pointer = null; // entity-id of line object this.triggerValue = 0; // rolling average of trigger value + this.rawTriggerValue = 0; var _this = this; @@ -244,12 +245,18 @@ function MyController(hand, triggerAction) { this.pointer = null; }; - this.updateSmoothedTrigger = function() { - var triggerValue = Controller.getValue(this.triggerAction); + this.eitherTrigger = function (value) { + _this.rawTriggerValue = value; + }; + + this.updateSmoothedTrigger = function () { + //var triggerValue = Controller.getValue(this.triggerAction); // this.rawTriggerValue; // + var triggerValue = this.rawTriggerValue; // smooth out trigger value this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); - } + + }; this.triggerSmoothedSqueezed = function() { return this.triggerValue > TRIGGER_ON_VALUE; @@ -259,8 +266,9 @@ function MyController(hand, triggerAction) { return this.triggerValue < TRIGGER_OFF_VALUE; }; - this.triggerSqueezed = function() { - var triggerValue = Controller.getValue(this.triggerAction); + this.triggerSqueezed = function() { + var triggerValue = Controller.getValue(this.triggerAction); // this.rawTriggerValue; // + print("triggerSqueezed() triggerValue:" + triggerValue); return triggerValue > TRIGGER_ON_VALUE; }; @@ -861,6 +869,12 @@ function MyController(hand, triggerAction) { var rightController = new MyController(RIGHT_HAND, Controller.Standard.RT); var leftController = new MyController(LEFT_HAND, Controller.Standard.LT); +var mapping = Controller.newMapping("handGrab"); +mapping.from([Controller.Standard.RB, Controller.Standard.RT]).to(rightController.eitherTrigger); +mapping.from([Controller.Standard.LB, Controller.Standard.LT]).to(leftController.eitherTrigger); +Controller.enableMapping("handGrab"); + + function update() { rightController.update(); leftController.update(); @@ -869,6 +883,7 @@ function update() { function cleanup() { rightController.cleanup(); leftController.cleanup(); + Controller.disableMapping("handGrab"); } Script.scriptEnding.connect(cleanup); From 9285cf8e2cff33e2389a1b0cde10ed85b05cae49 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 23 Oct 2015 17:12:26 -0700 Subject: [PATCH 06/14] fix hydraGrabHockey.js to use new API --- examples/example/games/hydraGrabHockey.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/example/games/hydraGrabHockey.js b/examples/example/games/hydraGrabHockey.js index b9f760fa08..26f9a443ab 100644 --- a/examples/example/games/hydraGrabHockey.js +++ b/examples/example/games/hydraGrabHockey.js @@ -59,9 +59,7 @@ function controller(side) { this.triggerHeld = false; this.triggerThreshold = 0.9; this.side = side; - this.palm = 2 * side; - this.tip = 2 * side + 1; - this.trigger = side; + this.trigger = side == LEFT ? Controller.Standard.LT : Controller.Standard.RT; this.originalGravity = { x: 0, y: 0, @@ -150,8 +148,8 @@ function controller(side) { this.updateControllerState = function() { - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); + this.palmPosition = this.side == RIGHT ? MyAvatar.rightHandPose.translation : MyAvatar.leftHandPose.translation; + this.tipPosition = this.side == RIGHT ? MyAvatar.rightHandTipPose.translation : MyAvatar.leftHandTipPose.translation; this.triggerValue = Controller.getTriggerValue(this.trigger); } From ed20e7d209dc12eb73f057ac4b3202e0525f8726 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 23 Oct 2015 17:14:13 -0700 Subject: [PATCH 07/14] CR feedback --- examples/controllers/handControllerGrab.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 80a3ea98a4..2b370a3b89 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -869,10 +869,10 @@ function MyController(hand, triggerAction) { var rightController = new MyController(RIGHT_HAND, Controller.Standard.RT); var leftController = new MyController(LEFT_HAND, Controller.Standard.LT); -var mapping = Controller.newMapping("handGrab"); +var mapping = Controller.newMapping("com.highfidelity.handControllerGrab"); mapping.from([Controller.Standard.RB, Controller.Standard.RT]).to(rightController.eitherTrigger); mapping.from([Controller.Standard.LB, Controller.Standard.LT]).to(leftController.eitherTrigger); -Controller.enableMapping("handGrab"); +Controller.enableMapping("com.highfidelity.handControllerGrab"); function update() { From 090dc5409b968356fcd69685ae84b04d3a78047a Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 23 Oct 2015 17:14:59 -0700 Subject: [PATCH 08/14] CR feedback --- examples/controllers/handControllerGrab.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 2b370a3b89..9e21429cdc 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -250,7 +250,6 @@ function MyController(hand, triggerAction) { }; this.updateSmoothedTrigger = function () { - //var triggerValue = Controller.getValue(this.triggerAction); // this.rawTriggerValue; // var triggerValue = this.rawTriggerValue; // smooth out trigger value this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + @@ -267,8 +266,7 @@ function MyController(hand, triggerAction) { }; this.triggerSqueezed = function() { - var triggerValue = Controller.getValue(this.triggerAction); // this.rawTriggerValue; // - print("triggerSqueezed() triggerValue:" + triggerValue); + var triggerValue = this.rawTriggerValue; return triggerValue > TRIGGER_ON_VALUE; }; From 9ba1b800d91655bda082a35035fcad1a138c4dd5 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 23 Oct 2015 17:15:39 -0700 Subject: [PATCH 09/14] CR feedback --- examples/controllers/handControllerGrab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 9e21429cdc..a61f52117b 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -881,7 +881,7 @@ function update() { function cleanup() { rightController.cleanup(); leftController.cleanup(); - Controller.disableMapping("handGrab"); + Controller.disableMapping("com.highfidelity.handControllerGrab"); } Script.scriptEnding.connect(cleanup); From 0fdd32709f6eb7c52c3dc98568823516cb94671b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 23 Oct 2015 13:28:36 -0700 Subject: [PATCH 10/14] Moving conditionals and endpoints out of UserInputMapper Conflicts: libraries/controllers/src/controllers/UserInputMapper.cpp --- .../src/controllers/UserInputMapper.cpp | 341 +----------------- .../controllers/{ => impl}/Conditional.cpp | 0 .../src/controllers/{ => impl}/Conditional.h | 0 .../src/controllers/{ => impl}/Endpoint.cpp | 0 .../src/controllers/{ => impl}/Endpoint.h | 4 +- .../src/controllers/{ => impl}/Filter.cpp | 0 .../src/controllers/{ => impl}/Filter.h | 0 .../src/controllers/{ => impl}/Mapping.cpp | 0 .../src/controllers/{ => impl}/Mapping.h | 0 .../controllers/impl/MappingBuilderProxy.h | 4 +- .../src/controllers/{ => impl}/Route.cpp | 0 .../src/controllers/{ => impl}/Route.h | 0 .../src/controllers/impl/RouteBuilderProxy.h | 8 +- .../impl/conditionals/AndConditional.cpp | 20 + .../impl/conditionals/AndConditional.h | 32 ++ .../impl/conditionals/EndpointConditional.cpp | 9 + .../impl/conditionals/EndpointConditional.h | 27 ++ .../impl/conditionals/NotConditional.cpp | 9 + .../impl/conditionals/NotConditional.h | 16 + .../impl/conditionals/ScriptConditional.cpp | 27 ++ .../impl/conditionals/ScriptConditional.h | 34 ++ .../impl/endpoints/ActionEndpoint.cpp | 40 ++ .../impl/endpoints/ActionEndpoint.h | 41 +++ .../impl/endpoints/AnyEndpoint.cpp | 63 ++++ .../controllers/impl/endpoints/AnyEndpoint.h | 32 ++ .../impl/endpoints/ArrayEndpoint.cpp | 9 + .../impl/endpoints/ArrayEndpoint.h | 43 +++ .../impl/endpoints/CompositeEndpoint.cpp | 32 ++ .../impl/endpoints/CompositeEndpoint.h | 26 ++ .../impl/endpoints/InputEndpoint.cpp | 41 +++ .../impl/endpoints/InputEndpoint.h | 39 ++ .../controllers/impl/endpoints/JSEndpoint.cpp | 9 + .../controllers/impl/endpoints/JSEndpoint.h | 41 +++ .../impl/endpoints/ScriptEndpoint.cpp | 43 +++ .../impl/endpoints/ScriptEndpoint.h | 39 ++ .../impl/endpoints/StandardEndpoint.cpp | 9 + .../impl/endpoints/StandardEndpoint.h | 60 +++ 37 files changed, 766 insertions(+), 332 deletions(-) rename libraries/controllers/src/controllers/{ => impl}/Conditional.cpp (100%) rename libraries/controllers/src/controllers/{ => impl}/Conditional.h (100%) rename libraries/controllers/src/controllers/{ => impl}/Endpoint.cpp (100%) rename libraries/controllers/src/controllers/{ => impl}/Endpoint.h (98%) rename libraries/controllers/src/controllers/{ => impl}/Filter.cpp (100%) rename libraries/controllers/src/controllers/{ => impl}/Filter.h (100%) rename libraries/controllers/src/controllers/{ => impl}/Mapping.cpp (100%) rename libraries/controllers/src/controllers/{ => impl}/Mapping.h (100%) rename libraries/controllers/src/controllers/{ => impl}/Route.cpp (100%) rename libraries/controllers/src/controllers/{ => impl}/Route.h (100%) create mode 100644 libraries/controllers/src/controllers/impl/conditionals/AndConditional.cpp create mode 100644 libraries/controllers/src/controllers/impl/conditionals/AndConditional.h create mode 100644 libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.cpp create mode 100644 libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h create mode 100644 libraries/controllers/src/controllers/impl/conditionals/NotConditional.cpp create mode 100644 libraries/controllers/src/controllers/impl/conditionals/NotConditional.h create mode 100644 libraries/controllers/src/controllers/impl/conditionals/ScriptConditional.cpp create mode 100644 libraries/controllers/src/controllers/impl/conditionals/ScriptConditional.h create mode 100644 libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp create mode 100644 libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h create mode 100644 libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp create mode 100644 libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h create mode 100644 libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.cpp create mode 100644 libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h create mode 100644 libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp create mode 100644 libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h create mode 100644 libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp create mode 100644 libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h create mode 100644 libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.cpp create mode 100644 libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h create mode 100644 libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp create mode 100644 libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h create mode 100644 libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.cpp create mode 100644 libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 30fd650eba..19a4b78207 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -24,9 +24,22 @@ #include "Logging.h" -#include "Endpoint.h" -#include "Route.h" -#include "Mapping.h" +#include "impl/conditionals/AndConditional.h" +#include "impl/conditionals/EndpointConditional.h" +#include "impl/conditionals/ScriptConditional.h" + +#include "impl/endpoints/ActionEndpoint.h" +#include "impl/endpoints/AnyEndpoint.h" +#include "impl/endpoints/ArrayEndpoint.h" +#include "impl/endpoints/CompositeEndpoint.h" +#include "impl/endpoints/InputEndpoint.h" +#include "impl/endpoints/JSEndpoint.h" +#include "impl/endpoints/ScriptEndpoint.h" +#include "impl/endpoints/StandardEndpoint.h" + +#include "impl/Route.h" +#include "impl/Mapping.h" + namespace controller { const uint16_t UserInputMapper::ACTIONS_DEVICE = Input::INVALID_DEVICE - 0xFF; @@ -42,300 +55,6 @@ controller::UserInputMapper::UserInputMapper() { namespace controller { -class ScriptEndpoint : public Endpoint { - Q_OBJECT; -public: - ScriptEndpoint(const QScriptValue& callable) - : Endpoint(Input::INVALID_INPUT), _callable(callable) { - } - - virtual float value(); - virtual void apply(float newValue, float oldValue, const Pointer& source); - -protected: - Q_INVOKABLE void updateValue(); - Q_INVOKABLE virtual void internalApply(float newValue, float oldValue, int sourceID); -private: - QScriptValue _callable; - float _lastValue = 0.0f; -}; - -class StandardEndpoint : public VirtualEndpoint { -public: - StandardEndpoint(const Input& input) : VirtualEndpoint(input) {} - virtual bool writeable() const override { return !_written; } - virtual bool readable() const override { return !_read; } - virtual void reset() override { - apply(0.0f, 0.0f, Endpoint::Pointer()); - apply(Pose(), Pose(), Endpoint::Pointer()); - _written = _read = false; - } - - virtual float value() override { - _read = true; - return VirtualEndpoint::value(); - } - - virtual void apply(float newValue, float oldValue, const Pointer& source) override { - // For standard endpoints, the first NON-ZERO write counts. - if (newValue != 0.0) { - _written = true; - } - VirtualEndpoint::apply(newValue, oldValue, source); - } - - virtual Pose pose() override { - _read = true; - return VirtualEndpoint::pose(); - } - - virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { - if (newValue != Pose()) { - _written = true; - } - VirtualEndpoint::apply(newValue, oldValue, source); - } - -private: - bool _written { false }; - bool _read { false }; -}; - - -class JSEndpoint : public Endpoint { -public: - JSEndpoint(const QJSValue& callable) - : Endpoint(Input::INVALID_INPUT), _callable(callable) { - } - - virtual float value() { - float result = (float)_callable.call().toNumber();; - return result; - } - - virtual void apply(float newValue, float oldValue, const Pointer& source) { - _callable.call(QJSValueList({ QJSValue(newValue) })); - } - -private: - QJSValue _callable; -}; - -float ScriptEndpoint::value() { - updateValue(); - return _lastValue; -} - -void ScriptEndpoint::updateValue() { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "updateValue", Qt::QueuedConnection); - return; - } - - _lastValue = (float)_callable.call().toNumber(); -} - -void ScriptEndpoint::apply(float newValue, float oldValue, const Pointer& source) { - internalApply(newValue, oldValue, source->getInput().getID()); -} - -void ScriptEndpoint::internalApply(float newValue, float oldValue, int sourceID) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "internalApply", Qt::QueuedConnection, - Q_ARG(float, newValue), - Q_ARG(float, oldValue), - Q_ARG(int, sourceID)); - return; - } - _callable.call(QScriptValue(), - QScriptValueList({ QScriptValue(newValue), QScriptValue(oldValue), QScriptValue(sourceID) })); -} - -static const Input INVALID_STANDARD_INPUT = Input(UserInputMapper::STANDARD_DEVICE, Input::INVALID_CHANNEL, ChannelType::INVALID); - -class CompositeEndpoint : public Endpoint, Endpoint::Pair { -public: - CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second) - : Endpoint(Input::INVALID_INPUT), Pair(first, second) { - if (first->getInput().device == UserInputMapper::STANDARD_DEVICE && - second->getInput().device == UserInputMapper::STANDARD_DEVICE) { - this->_input = INVALID_STANDARD_INPUT; - } - } - - virtual float value() { - float result = first->value() * -1.0f + second->value(); - return result; - } - - virtual void apply(float newValue, float oldValue, const Pointer& source) { - // Composites are read only - } -}; - -class ArrayEndpoint : public Endpoint { - friend class UserInputMapper; -public: - using Pointer = std::shared_ptr; - ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { } - - virtual float value() override { - return 0.0; - } - - virtual void apply(float newValue, float oldValue, const Endpoint::Pointer& source) override { - for (auto& child : _children) { - if (child->writeable()) { - child->apply(newValue, oldValue, source); - } - } - } - - virtual bool readable() const override { return false; } - -private: - Endpoint::List _children; -}; - -class AnyEndpoint : public Endpoint { - friend class UserInputMapper; -public: - using Pointer = std::shared_ptr; - AnyEndpoint(Endpoint::List children) : Endpoint(Input::INVALID_INPUT), _children(children) { - bool standard = true; - // Ensure if we're building a composite of standard devices the composite itself - // is treated as a standard device for rule processing order - for (auto endpoint : children) { - if (endpoint->getInput().device != UserInputMapper::STANDARD_DEVICE) { - standard = false; - break; - } - } - if (standard) { - this->_input = INVALID_STANDARD_INPUT; - } - } - - virtual float value() override { - float result = 0.0f; - for (auto& child : _children) { - float childResult = child->value(); - if (childResult != 0.0f && result == 0.0f) { - result = childResult; - } - } - return result; - } - - virtual void apply(float newValue, float oldValue, const Endpoint::Pointer& source) override { - qFatal("AnyEndpoint is read only"); - } - - // AnyEndpoint is used for reading, so return false if any child returns false (has been written to) - virtual bool writeable() const override { - for (auto& child : _children) { - if (!child->writeable()) { - return false; - } - } - return true; - } - - virtual bool readable() const override { - for (auto& child : _children) { - if (!child->readable()) { - return false; - } - } - return true; - } - -private: - Endpoint::List _children; -}; - -class InputEndpoint : public Endpoint { -public: - InputEndpoint(const Input& id = Input::INVALID_INPUT) - : Endpoint(id) { - } - - virtual float value() override { - _read = true; - if (isPose()) { - return pose().valid ? 1.0f : 0.0f; - } - auto userInputMapper = DependencyManager::get(); - auto deviceProxy = userInputMapper->getDeviceProxy(_input); - if (!deviceProxy) { - return 0.0f; - } - return deviceProxy->getValue(_input, 0); - } - - // FIXME need support for writing back to vibration / force feedback effects - virtual void apply(float newValue, float oldValue, const Pointer& source) override {} - - virtual Pose pose() override { - _read = true; - if (!isPose()) { - return Pose(); - } - auto userInputMapper = DependencyManager::get(); - auto deviceProxy = userInputMapper->getDeviceProxy(_input); - if (!deviceProxy) { - return Pose(); - } - return deviceProxy->getPose(_input, 0); - } - - virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { } - - virtual bool writeable() const { return false; } - virtual bool readable() const { return !_read; } - virtual void reset() { _read = false; } - -private: - bool _read { false }; -}; - -class ActionEndpoint : public Endpoint { -public: - ActionEndpoint(const Input& id = Input::INVALID_INPUT) - : Endpoint(id) { - } - - virtual float value() override { return _currentValue; } - virtual void apply(float newValue, float oldValue, const Pointer& source) override { - _currentValue += newValue; - if (_input != Input::INVALID_INPUT) { - auto userInputMapper = DependencyManager::get(); - userInputMapper->deltaActionState(Action(_input.getChannel()), newValue); - } - } - - virtual Pose pose() override { return _currentPose; } - virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { - _currentPose = newValue; - if (!_currentPose.isValid()) { - return; - } - if (_input != Input::INVALID_INPUT) { - auto userInputMapper = DependencyManager::get(); - userInputMapper->setActionState(Action(_input.getChannel()), _currentPose); - } - } - - virtual void reset() override { - _currentValue = 0.0f; - _currentPose = Pose(); - } - -private: - float _currentValue{ 0.0f }; - Pose _currentPose{}; -}; - UserInputMapper::~UserInputMapper() { } @@ -1019,33 +738,6 @@ Endpoint::Pointer UserInputMapper::parseEndpoint(const QJsonValue& value) { return result; } -class AndConditional : public Conditional { -public: - using Pointer = std::shared_ptr; - - AndConditional(Conditional::List children) : _children(children) { } - - virtual bool satisfied() override { - for (auto& conditional : _children) { - if (!conditional->satisfied()) { - return false; - } - } - return true; - } - -private: - Conditional::List _children; -}; - -class EndpointConditional : public Conditional { -public: - EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {} - virtual bool satisfied() override { return _endpoint && _endpoint->value() != 0.0; } -private: - Endpoint::Pointer _endpoint; -}; - Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value) { if (value.isArray()) { // Support "when" : [ "GamePad.RB", "GamePad.LB" ] @@ -1290,4 +982,3 @@ void UserInputMapper::disableMapping(const Mapping::Pointer& mapping) { } -#include "UserInputMapper.moc" diff --git a/libraries/controllers/src/controllers/Conditional.cpp b/libraries/controllers/src/controllers/impl/Conditional.cpp similarity index 100% rename from libraries/controllers/src/controllers/Conditional.cpp rename to libraries/controllers/src/controllers/impl/Conditional.cpp diff --git a/libraries/controllers/src/controllers/Conditional.h b/libraries/controllers/src/controllers/impl/Conditional.h similarity index 100% rename from libraries/controllers/src/controllers/Conditional.h rename to libraries/controllers/src/controllers/impl/Conditional.h diff --git a/libraries/controllers/src/controllers/Endpoint.cpp b/libraries/controllers/src/controllers/impl/Endpoint.cpp similarity index 100% rename from libraries/controllers/src/controllers/Endpoint.cpp rename to libraries/controllers/src/controllers/impl/Endpoint.cpp diff --git a/libraries/controllers/src/controllers/Endpoint.h b/libraries/controllers/src/controllers/impl/Endpoint.h similarity index 98% rename from libraries/controllers/src/controllers/Endpoint.h rename to libraries/controllers/src/controllers/impl/Endpoint.h index 7a94b06e7e..f5fe058d82 100644 --- a/libraries/controllers/src/controllers/Endpoint.h +++ b/libraries/controllers/src/controllers/impl/Endpoint.h @@ -16,8 +16,8 @@ #include -#include "Input.h" -#include "Pose.h" +#include "../Input.h" +#include "../Pose.h" class QScriptValue; diff --git a/libraries/controllers/src/controllers/Filter.cpp b/libraries/controllers/src/controllers/impl/Filter.cpp similarity index 100% rename from libraries/controllers/src/controllers/Filter.cpp rename to libraries/controllers/src/controllers/impl/Filter.cpp diff --git a/libraries/controllers/src/controllers/Filter.h b/libraries/controllers/src/controllers/impl/Filter.h similarity index 100% rename from libraries/controllers/src/controllers/Filter.h rename to libraries/controllers/src/controllers/impl/Filter.h diff --git a/libraries/controllers/src/controllers/Mapping.cpp b/libraries/controllers/src/controllers/impl/Mapping.cpp similarity index 100% rename from libraries/controllers/src/controllers/Mapping.cpp rename to libraries/controllers/src/controllers/impl/Mapping.cpp diff --git a/libraries/controllers/src/controllers/Mapping.h b/libraries/controllers/src/controllers/impl/Mapping.h similarity index 100% rename from libraries/controllers/src/controllers/Mapping.h rename to libraries/controllers/src/controllers/impl/Mapping.h diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index 93aa022647..ac9a5a300d 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -12,8 +12,8 @@ #include #include -#include "../Mapping.h" -#include "../Endpoint.h" +#include "Mapping.h" +#include "Endpoint.h" class QJSValue; class QScriptValue; diff --git a/libraries/controllers/src/controllers/Route.cpp b/libraries/controllers/src/controllers/impl/Route.cpp similarity index 100% rename from libraries/controllers/src/controllers/Route.cpp rename to libraries/controllers/src/controllers/impl/Route.cpp diff --git a/libraries/controllers/src/controllers/Route.h b/libraries/controllers/src/controllers/impl/Route.h similarity index 100% rename from libraries/controllers/src/controllers/Route.h rename to libraries/controllers/src/controllers/impl/Route.h diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index 0484c5890d..2303f6184f 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -11,10 +11,12 @@ #include -#include "../Filter.h" -#include "../Route.h" -#include "../Mapping.h" +#include "Filter.h" +#include "Route.h" +#include "Mapping.h" + #include "../UserInputMapper.h" + class QJSValue; class QScriptValue; class QJsonValue; diff --git a/libraries/controllers/src/controllers/impl/conditionals/AndConditional.cpp b/libraries/controllers/src/controllers/impl/conditionals/AndConditional.cpp new file mode 100644 index 0000000000..1633f9a439 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/conditionals/AndConditional.cpp @@ -0,0 +1,20 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "AndConditional.h" + +using namespace controller; + +bool AndConditional::satisfied() { + for (auto& conditional : _children) { + if (!conditional->satisfied()) { + return false; + } + } + return true; +} diff --git a/libraries/controllers/src/controllers/impl/conditionals/AndConditional.h b/libraries/controllers/src/controllers/impl/conditionals/AndConditional.h new file mode 100644 index 0000000000..5fc8b7df2a --- /dev/null +++ b/libraries/controllers/src/controllers/impl/conditionals/AndConditional.h @@ -0,0 +1,32 @@ +// +// Created by Bradley Austin Davis 2015/10/20 +// 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_AndConditional_h +#define hifi_Controllers_AndConditional_h + +#include "../Conditional.h" + +namespace controller { + +class AndConditional : public Conditional { +public: + using Pointer = std::shared_ptr; + + AndConditional(Conditional::List children) : _children(children) { } + + virtual bool satisfied() override; + +private: + Conditional::List _children; +}; + +} + + +#endif diff --git a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.cpp b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.cpp new file mode 100644 index 0000000000..03e16b8cf9 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.cpp @@ -0,0 +1,9 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "EndpointConditional.h" \ No newline at end of file diff --git a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h new file mode 100644 index 0000000000..1e4205afc7 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h @@ -0,0 +1,27 @@ +// +// Created by Bradley Austin Davis 2015/10/20 +// 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_EndpointConditional_h +#define hifi_Controllers_EndpointConditional_h + +#include "../Conditional.h" +#include "../Endpoint.h" + +namespace controller { + +class EndpointConditional : public Conditional { +public: + EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {} + virtual bool satisfied() override { return _endpoint && _endpoint->value() != 0.0; } +private: + Endpoint::Pointer _endpoint; +}; + +} +#endif diff --git a/libraries/controllers/src/controllers/impl/conditionals/NotConditional.cpp b/libraries/controllers/src/controllers/impl/conditionals/NotConditional.cpp new file mode 100644 index 0000000000..0c8d602b9e --- /dev/null +++ b/libraries/controllers/src/controllers/impl/conditionals/NotConditional.cpp @@ -0,0 +1,9 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "NotConditional.h" diff --git a/libraries/controllers/src/controllers/impl/conditionals/NotConditional.h b/libraries/controllers/src/controllers/impl/conditionals/NotConditional.h new file mode 100644 index 0000000000..3acda07106 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/conditionals/NotConditional.h @@ -0,0 +1,16 @@ +// +// Created by Bradley Austin Davis 2015/10/20 +// 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_NotConditional_h +#define hifi_Controllers_NotConditional_h + +#include "../Conditional.h" + + +#endif diff --git a/libraries/controllers/src/controllers/impl/conditionals/ScriptConditional.cpp b/libraries/controllers/src/controllers/impl/conditionals/ScriptConditional.cpp new file mode 100644 index 0000000000..277b63ed11 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/conditionals/ScriptConditional.cpp @@ -0,0 +1,27 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "ScriptConditional.h" + +#include + +using namespace controller; + +bool ScriptConditional::satisfied() { + updateValue(); + return _lastValue; +} + +void ScriptConditional::updateValue() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "updateValue", Qt::QueuedConnection); + return; + } + + _lastValue = _callable.call().toBool(); +} diff --git a/libraries/controllers/src/controllers/impl/conditionals/ScriptConditional.h b/libraries/controllers/src/controllers/impl/conditionals/ScriptConditional.h new file mode 100644 index 0000000000..800692d02c --- /dev/null +++ b/libraries/controllers/src/controllers/impl/conditionals/ScriptConditional.h @@ -0,0 +1,34 @@ +// +// Created by Bradley Austin Davis 2015/10/20 +// 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_ScriptConditional_h +#define hifi_Controllers_ScriptConditional_h + +#include + +#include + +#include "../Conditional.h" + +namespace controller { + +class ScriptConditional : public QObject, public Conditional { + Q_OBJECT; +public: + ScriptConditional(const QScriptValue& callable) : _callable(callable) { } + virtual bool satisfied() override; +protected: + Q_INVOKABLE void updateValue(); +private: + QScriptValue _callable; + bool _lastValue { false }; +}; + +} +#endif diff --git a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp new file mode 100644 index 0000000000..d07ef38185 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp @@ -0,0 +1,40 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "ActionEndpoint.h" + +#include + +#include "../../UserInputMapper.h" + +using namespace controller; + +void ActionEndpoint::apply(float newValue, float oldValue, const Pointer& source) { + _currentValue += newValue; + if (_input != Input::INVALID_INPUT) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->deltaActionState(Action(_input.getChannel()), newValue); + } +} + +void ActionEndpoint::apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) { + _currentPose = newValue; + if (!_currentPose.isValid()) { + return; + } + if (_input != Input::INVALID_INPUT) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->setActionState(Action(_input.getChannel()), _currentPose); + } +} + +void ActionEndpoint::reset() { + _currentValue = 0.0f; + _currentPose = Pose(); +} + diff --git a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h new file mode 100644 index 0000000000..eaae1e3798 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h @@ -0,0 +1,41 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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_ActionEndpoint_h +#define hifi_Controllers_ActionEndpoint_h + +#include "../Endpoint.h" + +#include "../../Actions.h" +#include + +#include "../../UserInputMapper.h" + +namespace controller { + +class ActionEndpoint : public Endpoint { +public: + ActionEndpoint(const Input& id = Input::INVALID_INPUT) : Endpoint(id) { } + + virtual float value() override { return _currentValue; } + virtual void apply(float newValue, float oldValue, const Pointer& source) override; + + virtual Pose pose() override { return _currentPose; } + virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override; + + virtual void reset() override; + +private: + float _currentValue{ 0.0f }; + Pose _currentPose{}; +}; + +} + +#endif diff --git a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp new file mode 100644 index 0000000000..b3310e4424 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp @@ -0,0 +1,63 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "AnyEndpoint.h" + +#include "../../UserInputMapper.h" + +using namespace controller; + +AnyEndpoint::AnyEndpoint(Endpoint::List children) : Endpoint(Input::INVALID_INPUT), _children(children) { + bool standard = true; + // Ensure if we're building a composite of standard devices the composite itself + // is treated as a standard device for rule processing order + for (auto endpoint : children) { + if (endpoint->getInput().device != UserInputMapper::STANDARD_DEVICE) { + standard = false; + break; + } + } + if (standard) { + this->_input.device = UserInputMapper::STANDARD_DEVICE; + } +} + +float AnyEndpoint::value() { + float result = 0; + for (auto& child : _children) { + float childResult = child->value(); + if (childResult != 0.0f) { + result = childResult; + } + } + return result; +} + +void AnyEndpoint::apply(float newValue, float oldValue, const Endpoint::Pointer& source) { + qFatal("AnyEndpoint is read only"); +} + +// AnyEndpoint is used for reading, so return false if any child returns false (has been written to) +bool AnyEndpoint::writeable() const { + for (auto& child : _children) { + if (!child->writeable()) { + return false; + } + } + return true; +} + +bool AnyEndpoint::readable() const { + for (auto& child : _children) { + if (!child->readable()) { + return false; + } + } + return true; +} + diff --git a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h new file mode 100644 index 0000000000..25db6a5a2a --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h @@ -0,0 +1,32 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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_AnyEndpoint_h +#define hifi_Controllers_AnyEndpoint_h + +#include "../Endpoint.h" + +namespace controller { + +class AnyEndpoint : public Endpoint { + friend class UserInputMapper; +public: + AnyEndpoint(Endpoint::List children); + virtual float value() override; + virtual void apply(float newValue, float oldValue, const Endpoint::Pointer& source) override; + virtual bool writeable() const override; + virtual bool readable() const override; + +private: + Endpoint::List _children; +}; + +} + +#endif diff --git a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.cpp new file mode 100644 index 0000000000..c083a7147d --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.cpp @@ -0,0 +1,9 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "ArrayEndpoint.h" \ No newline at end of file diff --git a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h new file mode 100644 index 0000000000..676f43868a --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h @@ -0,0 +1,43 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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_ArrayEndpoint_h +#define hifi_Controllers_ArrayEndpoint_h + +#include "../Endpoint.h" + +namespace controller { + +class ArrayEndpoint : public Endpoint { + friend class UserInputMapper; +public: + using Pointer = std::shared_ptr; + ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { } + + virtual float value() override { + return 0.0; + } + + virtual void apply(float newValue, float oldValue, const Endpoint::Pointer& source) override { + for (auto& child : _children) { + if (child->writeable()) { + child->apply(newValue, oldValue, source); + } + } + } + + virtual bool readable() const override { return false; } + +private: + Endpoint::List _children; +}; + +} + +#endif diff --git a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp new file mode 100644 index 0000000000..9d89a7d2b3 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp @@ -0,0 +1,32 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "CompositeEndpoint.h" + +#include "../../UserInputMapper.h" + +namespace controller { + +CompositeEndpoint::CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second) + : Endpoint(Input::INVALID_INPUT), Pair(first, second) { + if (first->getInput().device == UserInputMapper::STANDARD_DEVICE && + second->getInput().device == UserInputMapper::STANDARD_DEVICE) { + this->_input.device = UserInputMapper::STANDARD_DEVICE; + } +} + +float CompositeEndpoint::value() { + float result = first->value() * -1.0f + second->value(); + return result; +} + +void CompositeEndpoint::apply(float newValue, float oldValue, const Pointer& source) { + // Composites are read only +} + +} diff --git a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h new file mode 100644 index 0000000000..b525a2e4ab --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h @@ -0,0 +1,26 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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_CompositeEndpoint_h +#define hifi_Controllers_CompositeEndpoint_h + +#include "../Endpoint.h" + +namespace controller { + class CompositeEndpoint : public Endpoint, Endpoint::Pair { + public: + CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second); + + virtual float value() override; + virtual void apply(float newValue, float oldValue, const Pointer& source) override; + }; + +} + +#endif diff --git a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp new file mode 100644 index 0000000000..32cd5b65e0 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp @@ -0,0 +1,41 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "InputEndpoint.h" + +#include + +#include "../../UserInputMapper.h" + +using namespace controller; +float InputEndpoint::value(){ + _read = true; + if (isPose()) { + return pose().valid ? 1.0f : 0.0f; + } + auto userInputMapper = DependencyManager::get(); + auto deviceProxy = userInputMapper->getDeviceProxy(_input); + if (!deviceProxy) { + return 0.0f; + } + return deviceProxy->getValue(_input, 0); +} + +Pose InputEndpoint::pose() { + _read = true; + if (!isPose()) { + return Pose(); + } + auto userInputMapper = DependencyManager::get(); + auto deviceProxy = userInputMapper->getDeviceProxy(_input); + if (!deviceProxy) { + return Pose(); + } + return deviceProxy->getPose(_input, 0); +} + diff --git a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h new file mode 100644 index 0000000000..195cd33683 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h @@ -0,0 +1,39 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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_InputEndpoint_h +#define hifi_Controllers_InputEndpoint_h + +#include "../Endpoint.h" + +namespace controller { + +class InputEndpoint : public Endpoint { +public: + InputEndpoint(const Input& id = Input::INVALID_INPUT) + : Endpoint(id) { + } + + virtual float value() override; + // FIXME need support for writing back to vibration / force feedback effects + virtual void apply(float newValue, float oldValue, const Pointer& source) override {} + virtual Pose pose() override; + virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { } + + virtual bool writeable() const { return false; } + virtual bool readable() const { return !_read; } + virtual void reset() { _read = false; } + +private: + bool _read { false }; +}; + +} + +#endif diff --git a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.cpp new file mode 100644 index 0000000000..4560741d12 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.cpp @@ -0,0 +1,9 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "JSEndpoint.h" \ No newline at end of file diff --git a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h new file mode 100644 index 0000000000..38ac92bfb6 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h @@ -0,0 +1,41 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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_JSEndpoint_h +#define hifi_Controllers_JSEndpoint_h + +#include "../Endpoint.h" + +#include +#include + +namespace controller { + +class JSEndpoint : public Endpoint { +public: + JSEndpoint(const QJSValue& callable) + : Endpoint(Input::INVALID_INPUT), _callable(callable) { + } + + virtual float value() { + float result = (float)_callable.call().toNumber(); + return result; + } + + virtual void apply(float newValue, float oldValue, const Pointer& source) { + _callable.call(QJSValueList({ QJSValue(newValue) })); + } + +private: + QJSValue _callable; +}; + +} + +#endif diff --git a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp new file mode 100644 index 0000000000..3dedcef4e4 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp @@ -0,0 +1,43 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "ScriptEndpoint.h" + +#include + +using namespace controller; + +float ScriptEndpoint::value() { + updateValue(); + return _lastValue; +} + +void ScriptEndpoint::updateValue() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "updateValue", Qt::QueuedConnection); + return; + } + + _lastValue = (float)_callable.call().toNumber(); +} + +void ScriptEndpoint::apply(float newValue, float oldValue, const Pointer& source) { + internalApply(newValue, oldValue, source->getInput().getID()); +} + +void ScriptEndpoint::internalApply(float newValue, float oldValue, int sourceID) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "internalApply", Qt::QueuedConnection, + Q_ARG(float, newValue), + Q_ARG(float, oldValue), + Q_ARG(int, sourceID)); + return; + } + _callable.call(QScriptValue(), + QScriptValueList({ QScriptValue(newValue), QScriptValue(oldValue), QScriptValue(sourceID) })); +} diff --git a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h new file mode 100644 index 0000000000..e3c7abe812 --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h @@ -0,0 +1,39 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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_ScriptEndpoint_h +#define hifi_Controllers_ScriptEndpoint_h + +#include + +#include "../Endpoint.h" + +namespace controller { + +class ScriptEndpoint : public Endpoint { + Q_OBJECT; +public: + ScriptEndpoint(const QScriptValue& callable) + : Endpoint(Input::INVALID_INPUT), _callable(callable) { + } + + virtual float value(); + virtual void apply(float newValue, float oldValue, const Pointer& source); + +protected: + Q_INVOKABLE void updateValue(); + Q_INVOKABLE virtual void internalApply(float newValue, float oldValue, int sourceID); +private: + QScriptValue _callable; + float _lastValue = 0.0f; +}; + +} + +#endif diff --git a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.cpp new file mode 100644 index 0000000000..09920d249c --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.cpp @@ -0,0 +1,9 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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 "StandardEndpoint.h" \ No newline at end of file diff --git a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h new file mode 100644 index 0000000000..44803a22fd --- /dev/null +++ b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h @@ -0,0 +1,60 @@ +// +// Created by Bradley Austin Davis 2015/10/23 +// 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_StandardEndpoint_h +#define hifi_Controllers_StandardEndpoint_h + +#include "../Endpoint.h" + +namespace controller { + +class StandardEndpoint : public VirtualEndpoint { +public: + StandardEndpoint(const Input& input) : VirtualEndpoint(input) {} + virtual bool writeable() const override { return !_written; } + virtual bool readable() const override { return !_read; } + virtual void reset() override { + apply(0.0f, 0.0f, Endpoint::Pointer()); + apply(Pose(), Pose(), Endpoint::Pointer()); + _written = _read = false; + } + + virtual float value() override { + _read = true; + return VirtualEndpoint::value(); + } + + virtual void apply(float newValue, float oldValue, const Pointer& source) override { + // For standard endpoints, the first NON-ZERO write counts. + if (newValue != 0.0) { + _written = true; + } + VirtualEndpoint::apply(newValue, oldValue, source); + } + + virtual Pose pose() override { + _read = true; + return VirtualEndpoint::pose(); + } + + virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { + if (newValue != Pose()) { + _written = true; + } + VirtualEndpoint::apply(newValue, oldValue, source); + } + +private: + bool _written { false }; + bool _read { false }; +}; + +} + +#endif From d5425ac625b27bafdb01e6a9853756e80cd95856 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 23 Oct 2015 13:28:36 -0700 Subject: [PATCH 11/14] Moving conditionals and endpoints out of UserInputMapper Conflicts: libraries/controllers/src/controllers/UserInputMapper.cpp --- .../src/controllers/impl/conditionals/AndConditional.cpp | 1 + .../src/controllers/impl/conditionals/AndConditional.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/controllers/src/controllers/impl/conditionals/AndConditional.cpp b/libraries/controllers/src/controllers/impl/conditionals/AndConditional.cpp index 1633f9a439..772d4f1314 100644 --- a/libraries/controllers/src/controllers/impl/conditionals/AndConditional.cpp +++ b/libraries/controllers/src/controllers/impl/conditionals/AndConditional.cpp @@ -18,3 +18,4 @@ bool AndConditional::satisfied() { } return true; } + diff --git a/libraries/controllers/src/controllers/impl/conditionals/AndConditional.h b/libraries/controllers/src/controllers/impl/conditionals/AndConditional.h index 5fc8b7df2a..c60e4b15df 100644 --- a/libraries/controllers/src/controllers/impl/conditionals/AndConditional.h +++ b/libraries/controllers/src/controllers/impl/conditionals/AndConditional.h @@ -28,5 +28,4 @@ private: } - #endif From 4e6f64833fa2cb6fcffdb2705e77d82007231274 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 23 Oct 2015 11:25:06 -0700 Subject: [PATCH 12/14] Conditional support from JS --- examples/tests/controllerInterfaceTest.js | 2 + .../src/controllers/UserInputMapper.cpp | 43 ++++++++++++++++++- .../src/controllers/UserInputMapper.h | 4 ++ .../src/controllers/impl/Conditional.h | 1 + .../controllers/impl/RouteBuilderProxy.cpp | 12 +++++- .../src/controllers/impl/RouteBuilderProxy.h | 3 ++ 6 files changed, 62 insertions(+), 3 deletions(-) diff --git a/examples/tests/controllerInterfaceTest.js b/examples/tests/controllerInterfaceTest.js index 0dccd1209a..97ad9bbc38 100644 --- a/examples/tests/controllerInterfaceTest.js +++ b/examples/tests/controllerInterfaceTest.js @@ -4,8 +4,10 @@ ControllerTest = function() { var xbox = Controller.Hardware.GamePad; this.mappingEnabled = false; this.mapping = Controller.newMapping(); + this.mapping.from(standard.LX).when([standard.LB, standard.RB]).to(actions.Yaw); this.mapping.from(standard.RX).to(actions.StepYaw); this.mapping.from(standard.RY).invert().to(actions.Pitch); + this.mapping.from(standard.RY).invert().to(actions.Pitch); var testMakeAxis = false; diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 19a4b78207..2579c7dbec 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -738,6 +738,47 @@ Endpoint::Pointer UserInputMapper::parseEndpoint(const QJsonValue& value) { return result; } + +Conditional::Pointer UserInputMapper::conditionalFor(const QJSValue& condition) { + return Conditional::Pointer(); +} + +Conditional::Pointer UserInputMapper::conditionalFor(const QScriptValue& condition) { + if (condition.isArray()) { + int length = condition.property("length").toInteger(); + Conditional::List children; + for (int i = 0; i < length; i++) { + Conditional::Pointer destination = conditionalFor(condition.property(i)); + if (!destination) { + return Conditional::Pointer(); + } + children.push_back(destination); + } + return std::make_shared(children); + } + + if (condition.isNumber()) { + return conditionalFor(Input(condition.toInt32())); + } + + if (condition.isFunction()) { + return std::make_shared(condition); + } + + qWarning() << "Unsupported conditional type " << condition.toString(); + return Conditional::Pointer(); +} + +Conditional::Pointer UserInputMapper::conditionalFor(const Input& inputId) const { + Locker locker(_lock); + auto iterator = _endpointsByInput.find(inputId); + if (_endpointsByInput.end() == iterator) { + qWarning() << "Unknown input: " << QString::number(inputId.getID(), 16); + return Conditional::Pointer(); + } + return std::make_shared(iterator->second); +} + Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value) { if (value.isArray()) { // Support "when" : [ "GamePad.RB", "GamePad.LB" ] @@ -764,7 +805,6 @@ Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value) return Conditional::parse(value); } - Filter::Pointer UserInputMapper::parseFilter(const QJsonValue& value) { Filter::Pointer result; if (value.isString()) { @@ -780,7 +820,6 @@ Filter::Pointer UserInputMapper::parseFilter(const QJsonValue& value) { return result; } - Filter::List UserInputMapper::parseFilters(const QJsonValue& value) { if (value.isNull()) { return Filter::List(); diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 319037fcb1..0a6ed3acad 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -143,6 +143,7 @@ namespace controller { friend class MappingBuilderProxy; void runMappings(); + static void applyRoutes(const RouteList& route); static bool applyRoute(const RoutePointer& route, bool force = false); void enableMapping(const MappingPointer& mapping); @@ -151,6 +152,9 @@ namespace controller { EndpointPointer endpointFor(const QScriptValue& endpoint); EndpointPointer endpointFor(const Input& endpoint) const; EndpointPointer compositeEndpointFor(EndpointPointer first, EndpointPointer second); + ConditionalPointer conditionalFor(const QJSValue& endpoint); + ConditionalPointer conditionalFor(const QScriptValue& endpoint); + ConditionalPointer conditionalFor(const Input& endpoint) const; MappingPointer parseMapping(const QJsonValue& json); RoutePointer parseRoute(const QJsonValue& value); diff --git a/libraries/controllers/src/controllers/impl/Conditional.h b/libraries/controllers/src/controllers/impl/Conditional.h index 4d67d2871e..a216c8789f 100644 --- a/libraries/controllers/src/controllers/impl/Conditional.h +++ b/libraries/controllers/src/controllers/impl/Conditional.h @@ -28,6 +28,7 @@ namespace controller { using Pointer = std::shared_ptr; using List = std::list; using Factory = hifi::SimpleFactory; + using Lambda = std::function; virtual bool satisfied() = 0; virtual bool parseParameters(const QJsonValue& parameters) { return true; } diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp index c0d0758e4e..d56d699c28 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp @@ -33,7 +33,6 @@ void RouteBuilderProxy::to(const QScriptValue& destination) { } void RouteBuilderProxy::to(const Endpoint::Pointer& destination) { - auto sourceEndpoint = _route->source; _route->destination = destination; _mapping->routes.push_back(_route); deleteLater(); @@ -56,6 +55,17 @@ QObject* RouteBuilderProxy::filterQml(const QJSValue& expression) { return this; } +QObject* RouteBuilderProxy::when(const QScriptValue& expression) { + _route->conditional = _parent.conditionalFor(expression); + return this; +} + +QObject* RouteBuilderProxy::whenQml(const QJSValue& expression) { + _route->conditional = _parent.conditionalFor(expression); + return this; +} + + QObject* RouteBuilderProxy::filter(const QScriptValue& expression) { return this; } diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index 2303f6184f..4bcfba5acd 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -35,9 +35,11 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE void toQml(const QJSValue& destination); Q_INVOKABLE QObject* filterQml(const QJSValue& expression); + Q_INVOKABLE QObject* whenQml(const QJSValue& expression); Q_INVOKABLE void to(const QScriptValue& destination); Q_INVOKABLE QObject* debug(bool enable = true); + Q_INVOKABLE QObject* when(const QScriptValue& expression); Q_INVOKABLE QObject* filter(const QScriptValue& expression); Q_INVOKABLE QObject* clamp(float min, float max); Q_INVOKABLE QObject* pulse(float interval); @@ -49,6 +51,7 @@ class RouteBuilderProxy : public QObject { private: void to(const Endpoint::Pointer& destination); + void conditional(const Conditional::Pointer& conditional); void addFilter(Filter::Lambda lambda); void addFilter(Filter::Pointer filter); UserInputMapper& _parent; From 9aaef9aabd0034670c15539b45bdfaab0277b93f Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 23 Oct 2015 17:32:06 -0700 Subject: [PATCH 13/14] fix hydraPaint.js to use new API --- examples/example/painting/hydraPaint.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/examples/example/painting/hydraPaint.js b/examples/example/painting/hydraPaint.js index 29a3323e72..36137945cc 100644 --- a/examples/example/painting/hydraPaint.js +++ b/examples/example/painting/hydraPaint.js @@ -71,10 +71,8 @@ function controller(side, cycleColorButton) { this.triggerHeld = false; this.triggerThreshold = 0.9; this.side = side; - this.palm = 2 * side; - this.tip = 2 * side + 1; - this.trigger = side; - this.cycleColorButton = cycleColorButton; + this.trigger = side == LEFT ? Controller.Stantard.LT : Controller.Standard.RT; + this.cycleColorButton = side == LEFT ? Controller.Stantard.LeftPrimaryThumb : Controller.Standard.RightPrimaryThumb; this.points = []; this.normals = []; @@ -173,11 +171,10 @@ function controller(side, cycleColorButton) { this.updateControllerState = function() { - this.cycleColorButtonPressed = Controller.isButtonPressed(this.cycleColorButton); - this.palmPosition = Controller.getSpatialControlPosition(this.palm); - this.tipPosition = Controller.getSpatialControlPosition(this.tip); - this.palmNormal = Controller.getSpatialControlNormal(this.palm); - this.triggerValue = Controller.getTriggerValue(this.trigger); + this.cycleColorButtonPressed = Controller.getValue(this.cycleColorButton); + this.palmPosition = this.side == RIGHT ? MyAvatar.rightHandPose.translation : MyAvatar.leftHandPose.translation; + this.tipPosition = this.side == RIGHT ? MyAvatar.rightHandTipPose.translation : MyAvatar.leftHandTipPose.translation; + this.triggerValue = Controller.getValue(this.trigger); if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { @@ -215,8 +212,8 @@ function vectorIsZero(v) { } -var rightController = new controller(RIGHT, RIGHT_BUTTON_4); -var leftController = new controller(LEFT, LEFT_BUTTON_4); +var rightController = new controller(RIGHT); +var leftController = new controller(LEFT); Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); From 060f87d14a58e16cd0039863edc90e57837b8bfb Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 23 Oct 2015 17:33:45 -0700 Subject: [PATCH 14/14] CR feedback --- examples/controllers/handControllerGrab.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index a61f52117b..29d6595c3a 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -867,10 +867,12 @@ function MyController(hand, triggerAction) { var rightController = new MyController(RIGHT_HAND, Controller.Standard.RT); var leftController = new MyController(LEFT_HAND, Controller.Standard.LT); -var mapping = Controller.newMapping("com.highfidelity.handControllerGrab"); +var MAPPING_NAME = "com.highfidelity.handControllerGrab"; + +var mapping = Controller.newMapping(MAPPING_NAME); mapping.from([Controller.Standard.RB, Controller.Standard.RT]).to(rightController.eitherTrigger); mapping.from([Controller.Standard.LB, Controller.Standard.LT]).to(leftController.eitherTrigger); -Controller.enableMapping("com.highfidelity.handControllerGrab"); +Controller.enableMapping(MAPPING_NAME); function update() { @@ -881,7 +883,7 @@ function update() { function cleanup() { rightController.cleanup(); leftController.cleanup(); - Controller.disableMapping("com.highfidelity.handControllerGrab"); + Controller.disableMapping(MAPPING_NAME); } Script.scriptEnding.connect(cleanup);