Merge pull request #7222 from ZappoMan/depthReticleWork

more reticle improvements
This commit is contained in:
Howard Stearns 2016-02-29 17:42:03 -08:00
commit c0eef51d41
3 changed files with 111 additions and 13 deletions

View file

@ -22,3 +22,4 @@ Script.load("grab.js");
Script.load("directory.js");
Script.load("dialTone.js");
Script.load("attachedEntitiesManager.js");
Script.load("depthReticle.js");

View file

@ -5,6 +5,8 @@
// Copyright 2016 High Fidelity, Inc.
//
// When used in HMD, this script will make the reticle depth track to any clickable item in view.
// This script also handles auto-hiding the reticle after inactivity, as well as having the reticle
// seek the look at position upon waking up.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -17,8 +19,89 @@ var desiredDepth = APPARENT_2D_OVERLAY_DEPTH;
var TIME_BETWEEN_DEPTH_CHECKS = 100;
var MINIMUM_DEPTH_ADJUST = 0.01;
var NON_LINEAR_DIVISOR = 2;
var MINIMUM_SEEK_DISTANCE = 0.01;
Script.update.connect(function(deltaTime) {
var lastMouseMove = Date.now();
var lastMouseX = Reticle.position.x;
var lastMouseY = Reticle.position.y;
var HIDE_STATIC_MOUSE_AFTER = 3000; // 3 seconds
var shouldSeekToLookAt = false;
var fastMouseMoves = 0;
var averageMouseVelocity = 0;
var WEIGHTING = 1/20; // simple moving average over last 20 samples
var ONE_MINUS_WEIGHTING = 1 - WEIGHTING;
var AVERAGE_MOUSE_VELOCITY_FOR_SEEK_TO = 50;
Controller.mouseMoveEvent.connect(function(mouseEvent) {
var now = Date.now();
// if the reticle is hidden, show it...
if (!Reticle.visible) {
Reticle.visible = true;
if (HMD.active) {
shouldSeekToLookAt = true;
}
} else {
// even if the reticle is visible, if we're in HMD mode, and the person is moving their mouse quickly (shaking it)
// then they are probably looking for it, and we should move into seekToLookAt mode
if (HMD.active && !shouldSeekToLookAt) {
var dx = Reticle.position.x - lastMouseX;
var dy = Reticle.position.y - lastMouseY;
var dt = Math.max(1, (now - lastMouseMove)); // mSecs since last mouse move
var mouseMoveDistance = Math.sqrt((dx*dx) + (dy*dy));
var mouseVelocity = mouseMoveDistance / dt;
averageMouseVelocity = (ONE_MINUS_WEIGHTING * averageMouseVelocity) + (WEIGHTING * mouseVelocity);
if (averageMouseVelocity > AVERAGE_MOUSE_VELOCITY_FOR_SEEK_TO) {
shouldSeekToLookAt = true;
}
}
}
lastMouseMove = now;
lastMouseX = mouseEvent.x;
lastMouseY = mouseEvent.y;
});
function seekToLookAt() {
// if we're currently seeking the lookAt move the mouse toward the lookat
if (shouldSeekToLookAt) {
averageMouseVelocity = 0; // reset this, these never count for movement...
var lookAt2D = HMD.getHUDLookAtPosition2D();
var currentReticlePosition = Reticle.position;
var distanceBetweenX = lookAt2D.x - Reticle.position.x;
var distanceBetweenY = lookAt2D.y - Reticle.position.y;
var moveX = distanceBetweenX / NON_LINEAR_DIVISOR;
var moveY = distanceBetweenY / NON_LINEAR_DIVISOR;
var newPosition = { x: Reticle.position.x + moveX, y: Reticle.position.y + moveY };
var closeEnoughX = false;
var closeEnoughY = false;
if (moveX < MINIMUM_SEEK_DISTANCE) {
newPosition.x = lookAt2D.x;
closeEnoughX = true;
}
if (moveY < MINIMUM_SEEK_DISTANCE) {
newPosition.y = lookAt2D.y;
closeEnoughY = true;
}
Reticle.position = newPosition;
if (closeEnoughX && closeEnoughY) {
shouldSeekToLookAt = false;
}
}
}
function autoHideReticle() {
// if we haven't moved in a long period of time, and we're not pointing at some
// system overlay (like a window), then hide the reticle
if (Reticle.visible && !Reticle.pointingAtSystemOverlay) {
var now = Date.now();
var timeSinceLastMouseMove = now - lastMouseMove;
if (timeSinceLastMouseMove > HIDE_STATIC_MOUSE_AFTER) {
Reticle.visible = false;
}
}
}
function checkReticleDepth() {
var now = Date.now();
var timeSinceLastDepthCheck = now - lastDepthCheckTime;
if (timeSinceLastDepthCheck > TIME_BETWEEN_DEPTH_CHECKS) {
@ -56,6 +139,9 @@ Script.update.connect(function(deltaTime) {
}
}
}
function moveToDesiredDepth() {
// move the reticle toward the desired depth
if (desiredDepth != Reticle.depth) {
@ -69,4 +155,13 @@ Script.update.connect(function(deltaTime) {
Reticle.setDepth(newDepth);
}
}
Script.update.connect(function(deltaTime) {
autoHideReticle(); // auto hide reticle for desktop or HMD mode
if (HMD.active) {
seekToLookAt(); // handle moving the reticle toward the look at
checkReticleDepth(); // make sure reticle is at correct depth
moveToDesiredDepth(); // move the fade the reticle to the desired depth
}
});

View file

@ -212,19 +212,21 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) {
geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha));
//draw the mouse pointer
// Get the mouse coordinates and convert to NDC [-1, 1]
vec2 canvasSize = qApp->getCanvasSize(); // desktop, use actual canvas...
vec2 mousePosition = toNormalizedDeviceScale(vec2(qApp->getMouse()), canvasSize);
// Invert the Y axis
mousePosition.y *= -1.0f;
if (getReticleVisible()) {
// Get the mouse coordinates and convert to NDC [-1, 1]
vec2 canvasSize = qApp->getCanvasSize(); // desktop, use actual canvas...
vec2 mousePosition = toNormalizedDeviceScale(vec2(qApp->getMouse()), canvasSize);
// Invert the Y axis
mousePosition.y *= -1.0f;
Transform model;
model.setTranslation(vec3(mousePosition, 0));
vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize;
model.setScale(vec3(mouseSize, 1.0f));
batch.setModelTransform(model);
bindCursorTexture(batch);
geometryCache->renderUnitQuad(batch, vec4(1));
Transform model;
model.setTranslation(vec3(mousePosition, 0));
vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize;
model.setScale(vec3(mouseSize, 1.0f));
batch.setModelTransform(model);
bindCursorTexture(batch);
geometryCache->renderUnitQuad(batch, vec4(1));
}
});
}