mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 21:15:07 +02:00
220 lines
8 KiB
JavaScript
220 lines
8 KiB
JavaScript
//
|
|
// WebTablet.js
|
|
//
|
|
// Created by Anthony J. Thibault on 8/8/2016
|
|
// Copyright 2016 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
|
|
//
|
|
/* global getControllerWorldLocation, setEntityCustomData, Tablet, WebTablet:true */
|
|
|
|
Script.include(Script.resolvePath("../libraries/utils.js"));
|
|
Script.include(Script.resolvePath("../libraries/controllers.js"));
|
|
|
|
var RAD_TO_DEG = 180 / Math.PI;
|
|
var X_AXIS = {x: 1, y: 0, z: 0};
|
|
var Y_AXIS = {x: 0, y: 1, z: 0};
|
|
var DEFAULT_DPI = 32;
|
|
var DEFAULT_WIDTH = 0.43;
|
|
var DEFAULT_VERTICAL_FIELD_OF_VIEW = 45; // degrees
|
|
var SENSOR_TO_ROOM_MATRIX = -2;
|
|
var CAMERA_MATRIX = -7;
|
|
var ROT_Y_180 = {x: 0, y: 1, z: 0, w: 0};
|
|
|
|
var TABLET_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Tablet-Model-v1-x.fbx";
|
|
var HOME_BUTTON_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-home-button.fbx";
|
|
// returns object with two fields:
|
|
// * position - position in front of the user
|
|
// * rotation - rotation of entity so it faces the user.
|
|
function calcSpawnInfo(hand, height) {
|
|
var noHands = -1;
|
|
if (HMD.active && hand != noHands) {
|
|
var handController = getControllerWorldLocation(hand, false);
|
|
var controllerPosition = handController.position;
|
|
var originalOrientation = Quat.lookAt(controllerPosition, HMD.position, Y_AXIS);
|
|
var yDisplacement = (height/2) + 0.2;
|
|
var tabletOffset = Vec3.multiplyQbyV(Quat.lookAt(controllerPosition, HMD.position, Y_AXIS), {x: 0, y: yDisplacement, z: -0.2});
|
|
var finalPosition = Vec3.sum(controllerPosition, tabletOffset);
|
|
return {
|
|
position: finalPosition,
|
|
rotation: Quat.lookAt(finalPosition, HMD.position, Y_AXIS)
|
|
};
|
|
} else {
|
|
var front = Quat.getFront(MyAvatar.orientation);
|
|
var finalPosition = Vec3.sum(Vec3.sum(MyAvatar.position, Vec3.multiply(0.6, front)), {x: 0, y: 0.6, z: 0});
|
|
return {
|
|
position: finalPosition,
|
|
rotation: Quat.lookAt(finalPosition, MyAvatar.getHeadPosition(), Y_AXIS)
|
|
};
|
|
}
|
|
}
|
|
|
|
// ctor
|
|
WebTablet = function (url, width, dpi, hand, clientOnly) {
|
|
|
|
var _this = this;
|
|
var ASPECT = 4.0 / 3.0;
|
|
this.width = width || DEFAULT_WIDTH;
|
|
var TABLET_HEIGHT_SCALE = 650 / 680; // Screen size of tablet entity isn't quite the desired aspect.
|
|
this.height = this.width * ASPECT * TABLET_HEIGHT_SCALE;
|
|
var DEPTH = 0.025;
|
|
var DPI = dpi || DEFAULT_DPI;
|
|
|
|
var tabletProperties = {
|
|
name: "WebTablet Tablet",
|
|
type: "Model",
|
|
modelURL: TABLET_URL,
|
|
userData: JSON.stringify({
|
|
"grabbableKey": {"grabbable": true}
|
|
}),
|
|
dimensions: {x: this.width, y: this.height, z: DEPTH},
|
|
parentID: MyAvatar.sessionUUID
|
|
};
|
|
|
|
// compute position, rotation & parentJointIndex of the tablet
|
|
this.calculateTabletAttachmentProperties(hand, tabletProperties);
|
|
|
|
this.tabletEntityID = Entities.addEntity(tabletProperties, clientOnly);
|
|
|
|
var WEB_ENTITY_Z_OFFSET = -0.0125;
|
|
if (this.webOverlayID) {
|
|
Overlays.deleteOverlay(this.webOverlayID);
|
|
}
|
|
|
|
this.webOverlayID = Overlays.addOverlay("web3d", {
|
|
name: "WebTablet Web",
|
|
url: url,
|
|
localPosition: { x: 0, y: 0, z: WEB_ENTITY_Z_OFFSET },
|
|
localRotation: Quat.angleAxis(180, Y_AXIS),
|
|
resolution: { x: 480, y: 640 },
|
|
dpi: DPI,
|
|
color: { red: 255, green: 255, blue: 255 },
|
|
alpha: 1.0,
|
|
parentID: this.tabletEntityID,
|
|
parentJointIndex: -1,
|
|
showKeyboardFocusHighlight: false
|
|
});
|
|
|
|
var HOME_BUTTON_Y_OFFSET = -0.25;
|
|
this.homeButtonEntity = Entities.addEntity({
|
|
name: "homeButton",
|
|
type: "Model",
|
|
modelURL: HOME_BUTTON_URL,
|
|
dimensions: { x: 0.04, y: 0.04, z: 0.02 },
|
|
collisionless: true,
|
|
localPosition: {x: 0, y: HOME_BUTTON_Y_OFFSET, z: -0.01},
|
|
parentID: this.tabletEntityID,
|
|
script: Script.resolvePath("../tablet-ui/HomeButton.js")
|
|
}, clientOnly);
|
|
|
|
setEntityCustomData('grabbableKey', this.homeButtonEntity, {wantsTrigger: true});
|
|
|
|
this.receive = function (channel, senderID, senderUUID, localOnly) {
|
|
if (_this.homeButtonEntity == senderID) {
|
|
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
|
tablet.gotoHomeScreen();
|
|
}
|
|
};
|
|
|
|
this.state = "idle";
|
|
|
|
this.getRoot = function() {
|
|
return Entities.getWebViewRoot(_this.webEntityID);
|
|
};
|
|
|
|
this.getLocation = function() {
|
|
return Entities.getEntityProperties(_this.tabletEntityID, ["localPosition", "localRotation"]);
|
|
};
|
|
this.clicked = false;
|
|
|
|
this.myOnHmdChanged = function () { _this.onHmdChanged(); };
|
|
HMD.displayModeChanged.connect(this.myOnHmdChanged);
|
|
};
|
|
|
|
WebTablet.prototype.setURL = function (url) {
|
|
Overlays.editOverlay(this.webOverlayID, { url: url });
|
|
};
|
|
|
|
WebTablet.prototype.setScriptURL = function (scriptURL) {
|
|
Overlays.editOverlay(this.webOverlayID, { scriptURL: scriptURL });
|
|
};
|
|
|
|
WebTablet.prototype.getOverlayObject = function () {
|
|
return Overlays.getOverlayObject(this.webOverlayID);
|
|
};
|
|
|
|
WebTablet.prototype.destroy = function () {
|
|
Overlays.deleteOverlay(this.webOverlayID);
|
|
Entities.deleteEntity(this.tabletEntityID);
|
|
Entities.deleteEntity(this.homeButtonEntity);
|
|
HMD.displayModeChanged.disconnect(this.myOnHmdChanged);
|
|
};
|
|
|
|
// calclulate the appropriate position of the tablet in world space, such that it fits in the center of the screen.
|
|
// with a bit of padding on the top and bottom.
|
|
WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function () {
|
|
var PADDING_FACTOR = 1.4;
|
|
var fov = (Settings.getValue('fieldOfView') || DEFAULT_VERTICAL_FIELD_OF_VIEW) * (Math.PI / 180);
|
|
var dist = (PADDING_FACTOR * this.height) / (2 * Math.tan(fov / 2));
|
|
return {
|
|
position: Vec3.sum(Camera.position, Vec3.multiply(dist, Quat.getFront(Camera.orientation))),
|
|
rotation: Quat.multiply(Camera.orientation, ROT_Y_180)
|
|
};
|
|
};
|
|
|
|
// compute position, rotation & parentJointIndex of the tablet
|
|
WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, tabletProperties) {
|
|
if (HMD.active) {
|
|
// in HMD mode, the tablet should be relative to the sensor to world matrix.
|
|
tabletProperties.parentJointIndex = SENSOR_TO_ROOM_MATRIX;
|
|
|
|
// compute the appropriate position of the tablet, near the hand controller that was used to spawn it.
|
|
var spawnInfo = calcSpawnInfo(hand, this.height);
|
|
tabletProperties.position = spawnInfo.position;
|
|
tabletProperties.rotation = spawnInfo.rotation;
|
|
} else {
|
|
// in desktop mode, the tablet should be relative to the camera
|
|
tabletProperties.parentJointIndex = CAMERA_MATRIX;
|
|
|
|
// compute the appropriate postion of the tablet such that it fits in the center of the screen nicely.
|
|
var attitude = this.calculateWorldAttitudeRelativeToCamera();
|
|
tabletProperties.position = attitude.position;
|
|
tabletProperties.rotation = attitude.rotation;
|
|
}
|
|
};
|
|
|
|
WebTablet.prototype.onHmdChanged = function () {
|
|
var NO_HANDS = -1;
|
|
var tabletProperties = {};
|
|
// compute position, rotation & parentJointIndex of the tablet
|
|
this.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties);
|
|
Entities.editEntity(this.tabletEntityID, tabletProperties);
|
|
};
|
|
|
|
WebTablet.prototype.pickle = function () {
|
|
return JSON.stringify({ webOverlayID: this.webOverlayID, tabletEntityID: this.tabletEntityID });
|
|
};
|
|
|
|
WebTablet.prototype.register = function() {
|
|
Messages.subscribe("home");
|
|
Messages.messageReceived.connect(this.receive);
|
|
};
|
|
|
|
WebTablet.prototype.unregister = function() {
|
|
Messages.unsubscribe("home");
|
|
Messages.messageReceived.disconnect(this.receive);
|
|
};
|
|
|
|
WebTablet.unpickle = function (string) {
|
|
if (!string) {
|
|
return;
|
|
}
|
|
var tablet = JSON.parse(string);
|
|
tablet.__proto__ = WebTablet.prototype;
|
|
return tablet;
|
|
};
|
|
|
|
WebTablet.prototype.getPosition = function () {
|
|
return Overlays.getProperty(this.webOverlayID, "position");
|
|
};
|