mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-10 10:18:34 +02:00
Instead of manually setting anim vars to play the kneel animation and enable/disable IK, use the MyAvatar.overrideAnimation() and MyAvatar.restoreAnimtion() functions, which did not exist when away.js was written. This should make it more robust and eliminate the issue with IK being stuck in the disabled state.
255 lines
8.7 KiB
JavaScript
255 lines
8.7 KiB
JavaScript
"use strict";
|
|
/*jslint vars: true, plusplus: true*/
|
|
/*global HMD, AudioDevice, MyAvatar, Controller, Script, Overlays, print*/
|
|
//
|
|
// away.js
|
|
// examples
|
|
//
|
|
// Created by Howard Stearns 11/3/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
|
|
//
|
|
// Goes into "paused" when the '.' key (and automatically when started in HMD), and normal when pressing any key.
|
|
// See MAIN CONTROL, below, for what "paused" actually does.
|
|
var OVERLAY_WIDTH = 1920;
|
|
var OVERLAY_HEIGHT = 1080;
|
|
var OVERLAY_RATIO = OVERLAY_WIDTH / OVERLAY_HEIGHT;
|
|
var OVERLAY_DATA = {
|
|
width: OVERLAY_WIDTH,
|
|
height: OVERLAY_HEIGHT,
|
|
imageURL: "http://hifi-content.s3.amazonaws.com/alan/production/images/images/Overlay-Viz-blank.png",
|
|
color: {red: 255, green: 255, blue: 255},
|
|
alpha: 1
|
|
};
|
|
|
|
var lastOverlayPosition = { x: 0, y: 0, z: 0};
|
|
var OVERLAY_DATA_HMD = {
|
|
position: lastOverlayPosition,
|
|
width: OVERLAY_WIDTH,
|
|
height: OVERLAY_HEIGHT,
|
|
url: "http://hifi-content.s3.amazonaws.com/alan/production/images/images/Overlay-Viz-blank.png",
|
|
color: {red: 255, green: 255, blue: 255},
|
|
alpha: 1,
|
|
scale: 2,
|
|
isFacingAvatar: true,
|
|
drawInFront: true
|
|
};
|
|
|
|
var AWAY_INTRO = {
|
|
url: "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/kneel.fbx",
|
|
playbackRate: 30.0,
|
|
loopFlag: false,
|
|
startFrame: 0.0,
|
|
endFrame: 83.0
|
|
};
|
|
|
|
function playAwayAnimation() {
|
|
MyAvatar.overrideAnimation(AWAY_INTRO.url, AWAY_INTRO.playbackRate, AWAY_INTRO.loopFlag, AWAY_INTRO.startFrame, AWAY_INTRO.endFrame);
|
|
}
|
|
|
|
function stopAwayAnimation() {
|
|
MyAvatar.restoreAnimation();
|
|
}
|
|
|
|
// OVERLAY
|
|
var overlay = Overlays.addOverlay("image", OVERLAY_DATA);
|
|
var overlayHMD = Overlays.addOverlay("image3d", OVERLAY_DATA_HMD);
|
|
|
|
function moveCloserToCamera(positionAtHUD) {
|
|
// we don't actually want to render at the slerped look at... instead, we want to render
|
|
// slightly closer to the camera than that.
|
|
var MOVE_CLOSER_TO_CAMERA_BY = -0.25;
|
|
var cameraFront = Quat.getFront(Camera.orientation);
|
|
var closerToCamera = Vec3.multiply(cameraFront, MOVE_CLOSER_TO_CAMERA_BY); // slightly closer to camera
|
|
var slightlyCloserPosition = Vec3.sum(positionAtHUD, closerToCamera);
|
|
|
|
return slightlyCloserPosition;
|
|
}
|
|
|
|
function showOverlay() {
|
|
var properties = {visible: true};
|
|
|
|
if (HMD.active) {
|
|
// make sure desktop version is hidden
|
|
Overlays.editOverlay(overlay, { visible: false });
|
|
|
|
lastOverlayPosition = HMD.getHUDLookAtPosition3D();
|
|
var actualOverlayPositon = moveCloserToCamera(lastOverlayPosition);
|
|
Overlays.editOverlay(overlayHMD, { visible: true, position: actualOverlayPositon });
|
|
} else {
|
|
// make sure HMD is hidden
|
|
Overlays.editOverlay(overlayHMD, { visible: false });
|
|
|
|
// Update for current screen size, keeping overlay proportions constant.
|
|
var screen = Controller.getViewportDimensions();
|
|
|
|
// keep the overlay it's natural size and always center it...
|
|
Overlays.editOverlay(overlay, { visible: true,
|
|
x: ((screen.x - OVERLAY_WIDTH) / 2),
|
|
y: ((screen.y - OVERLAY_HEIGHT) / 2) });
|
|
}
|
|
}
|
|
|
|
function hideOverlay() {
|
|
Overlays.editOverlay(overlay, {visible: false});
|
|
Overlays.editOverlay(overlayHMD, {visible: false});
|
|
}
|
|
|
|
hideOverlay();
|
|
|
|
function maybeMoveOverlay() {
|
|
if (isAway) {
|
|
// if we switched from HMD to Desktop, make sure to hide our HUD overlay and show the
|
|
// desktop overlay
|
|
if (!HMD.active) {
|
|
showOverlay(); // this will also recenter appropriately
|
|
}
|
|
|
|
if (HMD.active) {
|
|
// Note: instead of moving it directly to the lookAt, we will move it slightly toward the
|
|
// new look at. This will result in a more subtle slerp toward the look at and reduce jerkiness
|
|
var EASE_BY_RATIO = 0.1;
|
|
var lookAt = HMD.getHUDLookAtPosition3D();
|
|
var lookAtChange = Vec3.subtract(lookAt, lastOverlayPosition);
|
|
var halfWayBetweenOldAndLookAt = Vec3.multiply(lookAtChange, EASE_BY_RATIO);
|
|
var newOverlayPosition = Vec3.sum(lastOverlayPosition, halfWayBetweenOldAndLookAt);
|
|
lastOverlayPosition = newOverlayPosition;
|
|
|
|
var actualOverlayPositon = moveCloserToCamera(lastOverlayPosition);
|
|
Overlays.editOverlay(overlayHMD, { visible: true, position: actualOverlayPositon });
|
|
|
|
// make sure desktop version is hidden
|
|
Overlays.editOverlay(overlay, { visible: false });
|
|
}
|
|
}
|
|
}
|
|
|
|
// MAIN CONTROL
|
|
var wasMuted, isAway;
|
|
var wasOverlaysVisible = Menu.isOptionChecked("Overlays");
|
|
var eventMappingName = "io.highfidelity.away"; // goActive on hand controller button events, too.
|
|
var eventMapping = Controller.newMapping(eventMappingName);
|
|
|
|
// backward compatible version of getting HMD.mounted, so it works in old clients
|
|
function safeGetHMDMounted() {
|
|
if (HMD.mounted === undefined) {
|
|
return true;
|
|
}
|
|
return HMD.mounted;
|
|
}
|
|
|
|
var wasHmdMounted = safeGetHMDMounted();
|
|
|
|
function goAway() {
|
|
if (isAway) {
|
|
return;
|
|
}
|
|
isAway = true;
|
|
print('going "away"');
|
|
wasMuted = AudioDevice.getMuted();
|
|
if (!wasMuted) {
|
|
AudioDevice.toggleMute();
|
|
}
|
|
MyAvatar.setEnableMeshVisible(false); // just for our own display, without changing point of view
|
|
playAwayAnimation(); // animation is still seen by others
|
|
showOverlay();
|
|
|
|
// remember the View > Overlays state...
|
|
wasOverlaysVisible = Menu.isOptionChecked("Overlays");
|
|
|
|
// show overlays so that people can see the "Away" message
|
|
Menu.setIsOptionChecked("Overlays", true);
|
|
|
|
// tell the Reticle, we want to stop capturing the mouse until we come back
|
|
Reticle.allowMouseCapture = false;
|
|
if (HMD.active) {
|
|
Reticle.visible = false;
|
|
}
|
|
wasHmdMounted = safeGetHMDMounted(); // always remember the correct state
|
|
}
|
|
|
|
function goActive() {
|
|
if (!isAway) {
|
|
return;
|
|
}
|
|
isAway = false;
|
|
print('going "active"');
|
|
if (!wasMuted) {
|
|
AudioDevice.toggleMute();
|
|
}
|
|
MyAvatar.setEnableMeshVisible(true); // IWBNI we respected Developer->Avatar->Draw Mesh setting.
|
|
stopAwayAnimation();
|
|
hideOverlay();
|
|
|
|
// restore overlays state to what it was when we went "away"
|
|
Menu.setIsOptionChecked("Overlays", wasOverlaysVisible);
|
|
|
|
// tell the Reticle, we are ready to capture the mouse again and it should be visible
|
|
Reticle.allowMouseCapture = true;
|
|
Reticle.visible = true;
|
|
if (HMD.active) {
|
|
Reticle.position = HMD.getHUDLookAtPosition2D();
|
|
}
|
|
wasHmdMounted = safeGetHMDMounted(); // always remember the correct state
|
|
}
|
|
|
|
function maybeGoActive(event) {
|
|
if (event.isAutoRepeat) { // isAutoRepeat is true when held down (or when Windows feels like it)
|
|
return;
|
|
}
|
|
if (!isAway && (event.text == 'ESC')) {
|
|
goAway();
|
|
} else {
|
|
goActive();
|
|
}
|
|
}
|
|
|
|
var wasHmdActive = HMD.active;
|
|
var wasMouseCaptured = Reticle.mouseCaptured;
|
|
|
|
function maybeGoAway() {
|
|
if (HMD.active !== wasHmdActive) {
|
|
wasHmdActive = !wasHmdActive;
|
|
if (wasHmdActive) {
|
|
goAway();
|
|
}
|
|
}
|
|
|
|
// If the mouse has gone from captured, to non-captured state, then it likely means the person is still in the HMD, but
|
|
// tabbed away from the application (meaning they don't have mouse control) and they likely want to go into an away state
|
|
if (Reticle.mouseCaptured !== wasMouseCaptured) {
|
|
wasMouseCaptured = !wasMouseCaptured;
|
|
if (!wasMouseCaptured) {
|
|
goAway();
|
|
}
|
|
}
|
|
|
|
// If you've removed your HMD from your head, and we can detect it, we will also go away...
|
|
var hmdMounted = safeGetHMDMounted();
|
|
if (HMD.active && !hmdMounted && wasHmdMounted) {
|
|
wasHmdMounted = hmdMounted;
|
|
goAway();
|
|
}
|
|
}
|
|
|
|
Script.update.connect(maybeMoveOverlay);
|
|
|
|
Script.update.connect(maybeGoAway);
|
|
Controller.mousePressEvent.connect(goActive);
|
|
Controller.keyPressEvent.connect(maybeGoActive);
|
|
// Note peek() so as to not interfere with other mappings.
|
|
eventMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(goActive);
|
|
eventMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(goActive);
|
|
eventMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(goActive);
|
|
eventMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(goActive);
|
|
Controller.enableMapping(eventMappingName);
|
|
|
|
Script.scriptEnding.connect(function () {
|
|
Script.update.disconnect(maybeGoAway);
|
|
goActive();
|
|
Controller.disableMapping(eventMappingName);
|
|
Controller.mousePressEvent.disconnect(goActive);
|
|
Controller.keyPressEvent.disconnect(maybeGoActive);
|
|
});
|