mirror of
https://github.com/overte-org/community-apps.git
synced 2025-04-14 00:26:42 +02:00
646 lines
24 KiB
JavaScript
646 lines
24 KiB
JavaScript
"use strict";
|
|
/*jslint vars:true, plusplus:true, forin:true*/
|
|
/*global Tablet, Script, */
|
|
/* eslint indent: ["error", 4, { "outerIIFEBody": 1 }] */
|
|
//
|
|
// tabletCam_app.js
|
|
//
|
|
// Created by Zach Fox on 2019-04-14
|
|
// Copyright 2022 Overte e.V.
|
|
//
|
|
// Camera with more advanced features than the SNAP application, with an higher resolution capability.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
(function () { // BEGIN LOCAL_SCOPE
|
|
var AppUi = Script.require('./modules/appUi.js');
|
|
|
|
var secondaryCameraConfig = Render.getConfig("SecondaryCamera");
|
|
var tabletCamAvatarEntity = false;
|
|
var previousNearClipDistance = false;
|
|
var previousFarClipDistance = false;
|
|
var previousvFoV = false;
|
|
var NEAR_CLIP_DISTANCE = 0.001;
|
|
var FAR_CLIP_DISTANCE = 16384;
|
|
var vFoV = Settings.getValue("tabletCam/vFoV", 60);
|
|
var secondaryCameraResolutionWidth = 1000;
|
|
var secondaryCameraResolutionHeight = secondaryCameraResolutionWidth / aspectRatio;
|
|
|
|
var PREVIEW_SHORT_SIDE_RESOLUTION = 400;
|
|
var secondaryCameraResolutionPreviewWidth = PREVIEW_SHORT_SIDE_RESOLUTION;
|
|
var secondaryCameraResolutionPreviewHeight = PREVIEW_SHORT_SIDE_RESOLUTION / aspectRatio;
|
|
|
|
var CAMERA_ENTITY_NAME = "CAMERA SNAP-PRO OV-22";
|
|
var APPLICATION_CAPTION = "SNAP-PRO";
|
|
|
|
var tabletCamRunning = false;
|
|
|
|
var TABLET_CAM_ENTITY_PROPERTIES = {
|
|
"type": "Model",
|
|
"modelURL": Script.resolvePath("models/camera.fbx"),
|
|
"shapeType": "simple-hull",
|
|
"dimensions": {"x":0.1600, "y":0.1021, "z":0.1137},
|
|
"damping": 0,
|
|
"angularDamping": 0,
|
|
"shape": "Cube",
|
|
"isVisibleInSecondaryCamera": false,
|
|
"name": CAMERA_ENTITY_NAME,
|
|
"grab": {
|
|
"grabbable": true
|
|
},
|
|
"registrationPoint": {
|
|
"x": 0.42,
|
|
"y": 0.4,
|
|
"z": 0
|
|
}
|
|
};
|
|
|
|
function enableTabletCam() {
|
|
if (!tabletCamRunning) {
|
|
wireSignals(true);
|
|
|
|
setTakePhotoControllerMappingStatus(true);
|
|
|
|
secondaryCameraConfig.enableSecondaryCameraRenderConfigs(true);
|
|
setSnapshotQuality(snapshotQuality);
|
|
var props = TABLET_CAM_ENTITY_PROPERTIES;
|
|
var dynamicProps = getDynamicTabletCamAvatarEntityProperties();
|
|
for (var key in dynamicProps) {
|
|
props[key] = dynamicProps[key];
|
|
}
|
|
tabletCamAvatarEntity = Entities.addEntity(props, "avatar");
|
|
previousFarClipDistance = secondaryCameraConfig.farClipPlaneDistance;
|
|
previousNearClipDistance = secondaryCameraConfig.nearClipPlaneDistance;
|
|
previousvFoV = secondaryCameraConfig.vFoV;
|
|
secondaryCameraConfig.nearClipPlaneDistance = NEAR_CLIP_DISTANCE;
|
|
secondaryCameraConfig.farClipPlaneDistance = FAR_CLIP_DISTANCE;
|
|
secondaryCameraConfig.vFoV = vFoV;
|
|
|
|
secondaryCameraConfig.attachedEntityId = tabletCamAvatarEntity;
|
|
tabletCamRunning = true;
|
|
}
|
|
|
|
updateTabletCamLocalEntity();
|
|
|
|
// Remove the existing tabletCamAvatarEntity model from the domain if one exists.
|
|
// It's easy for this to happen if the user crashes while the Tablet Cam is on.
|
|
// We do this down here (after the new one is rezzed) so that we don't accidentally delete
|
|
// the newly-rezzed model.
|
|
var entityIDs = Entities.findEntitiesByName(CAMERA_ENTITY_NAME, MyAvatar.position, 100, false);
|
|
entityIDs.forEach(function (currentEntityID) {
|
|
var currentEntityOwner = Entities.getEntityProperties(currentEntityID, ['owningAvatarID']).owningAvatarID;
|
|
if (currentEntityOwner === MyAvatar.sessionUUID && currentEntityID !== tabletCamAvatarEntity) {
|
|
Entities.deleteEntity(currentEntityID);
|
|
}
|
|
});
|
|
}
|
|
|
|
var frontCamInUse = Settings.getValue("tabletCam/frontCamInUse", true);
|
|
function switchCams(forceFrontCamValue) {
|
|
if (!tabletCamAvatarEntity || (!!HMD.tabletID && !tabletCamLocalEntity)) {
|
|
console.log("User tried to switch cams, but TabletCam wasn't ready!");
|
|
return;
|
|
}
|
|
|
|
frontCamInUse = forceFrontCamValue || !frontCamInUse;
|
|
Settings.setValue("tabletCam/frontCamInUse", frontCamInUse);
|
|
|
|
var newTabletCamAvatarEntityProps = getDynamicTabletCamAvatarEntityProperties();
|
|
Entities.editEntity(tabletCamAvatarEntity, newTabletCamAvatarEntityProps);
|
|
|
|
updateTabletCamLocalEntity();
|
|
}
|
|
|
|
function disableTabletCam() {
|
|
function deleteTabletCamAvatarEntity() {
|
|
if (flash) {
|
|
Entities.deleteEntity(flash);
|
|
flash = false;
|
|
}
|
|
|
|
if (tabletCamAvatarEntity) {
|
|
Entities.deleteEntity(tabletCamAvatarEntity);
|
|
tabletCamAvatarEntity = false;
|
|
detached = false; // TO BE CONFIRMED
|
|
Settings.setValue("tabletCam/detached", detached); // TO BE CONFIRMED
|
|
}
|
|
}
|
|
|
|
wireSignals(false);
|
|
|
|
setTakePhotoControllerMappingStatus(false);
|
|
|
|
if (tabletCamRunning) {
|
|
secondaryCameraConfig.farClipPlaneDistance = previousFarClipDistance;
|
|
secondaryCameraConfig.nearClipPlaneDistance = previousNearClipDistance;
|
|
secondaryCameraConfig.vFoV = previousvFoV;
|
|
secondaryCameraConfig.attachedEntityId = false;
|
|
secondaryCameraConfig.enableSecondaryCameraRenderConfigs(false);
|
|
}
|
|
|
|
deleteTabletCamAvatarEntity();
|
|
|
|
if (tabletCamLocalEntity) {
|
|
Entities.deleteEntity(tabletCamLocalEntity);
|
|
tabletCamLocalEntity = false;
|
|
detached = false; // TO BE CONFIRMED
|
|
Settings.setValue("tabletCam/detached", detached); // TO BE CONFIRMED
|
|
}
|
|
|
|
tabletCamRunning = false;
|
|
}
|
|
|
|
var tabletCamLocalEntityWidth = 0.282;
|
|
var tabletCamLocalEntityHeight = 0.282;
|
|
var tabletCamLocalEntityDim = { x: tabletCamLocalEntityWidth, y: tabletCamLocalEntityHeight };
|
|
var tabletCamLocalEntity = false;
|
|
var LOCAL_ENTITY_STATIC_PROPERTIES = {
|
|
type: "Image",
|
|
imageURL: "resource://spectatorCameraFrame",
|
|
emissive: true,
|
|
grab: {
|
|
"grabbable": false
|
|
},
|
|
alpha: 1,
|
|
triggerable: false
|
|
};
|
|
function updateTabletCamLocalEntity() {
|
|
if (!HMD.tabletID) {
|
|
return;
|
|
}
|
|
|
|
if (tabletCamLocalEntity) {
|
|
Entities.deleteEntity(tabletCamLocalEntity);
|
|
tabletCamLocalEntity = false;
|
|
}
|
|
var props = LOCAL_ENTITY_STATIC_PROPERTIES;
|
|
props.dimensions = tabletCamLocalEntityDim;
|
|
if (!!HMD.tabletID) {
|
|
props.parentID = HMD.tabletID;
|
|
props.localPosition = [0, 0.0225, -0.008];
|
|
if (frontCamInUse) {
|
|
props.localRotation = Quat.fromVec3Degrees([0, 180, 180]);
|
|
} else {
|
|
props.localRotation = Quat.fromVec3Degrees([0, 0, 180]);
|
|
}
|
|
} else {
|
|
props.parentID = Uuid.NULL;
|
|
props.localPosition = inFrontOf(0.5);
|
|
props.localRotation = MyAvatar.orientation;
|
|
}
|
|
|
|
tabletCamLocalEntity = Entities.addEntity(props, "local");
|
|
}
|
|
|
|
function onDomainChanged() {
|
|
if (tabletCamRunning) {
|
|
disableTabletCam();
|
|
}
|
|
}
|
|
|
|
function tabletVisibilityChanged() {
|
|
if (!ui.tablet.tabletShown && ui.isOpen) {
|
|
ui.close();
|
|
}
|
|
}
|
|
|
|
var flash = Settings.getValue("tabletCam/flashEnabled", false);;
|
|
function setFlashStatus(enabled) {
|
|
if (!tabletCamAvatarEntity) {
|
|
return;
|
|
}
|
|
|
|
Settings.setValue("tabletCam/flashEnabled", enabled);
|
|
|
|
var cameraPosition = Entities.getEntityProperties(tabletCamAvatarEntity, ["positon"]).position;
|
|
if (enabled) {
|
|
Audio.playSound(SOUND_FLASH_ON, {
|
|
position: cameraPosition,
|
|
localOnly: true,
|
|
volume: 0.8
|
|
});
|
|
flash = Entities.addEntity({
|
|
"collisionless": true,
|
|
"collidesWith": "",
|
|
"collisionMask": 0,
|
|
"color": {
|
|
"blue": 173,
|
|
"green": 252,
|
|
"red": 255
|
|
},
|
|
"cutoff": 90,
|
|
"dimensions": {
|
|
"x": 4,
|
|
"y": 4,
|
|
"z": 4
|
|
},
|
|
"dynamic": false,
|
|
"falloffRadius": 0.20000000298023224,
|
|
"intensity": 27,
|
|
"isSpotlight": true,
|
|
"localRotation": { w: 1, x: 0, y: 0, z: 0 },
|
|
"localPosition": { x: 0, y: 0, z: -0.005 },
|
|
"name": "Tablet Camera Flash",
|
|
"type": "Light",
|
|
"parentID": tabletCamAvatarEntity,
|
|
}, "avatar");
|
|
} else {
|
|
if (flash) {
|
|
Audio.playSound(SOUND_FLASH_OFF, {
|
|
position: cameraPosition,
|
|
localOnly: true,
|
|
volume: 0.8
|
|
});
|
|
Entities.deleteEntity(flash);
|
|
flash = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
function takePhoto() {
|
|
var tabletCamAvatarEntityPosition = Entities.getEntityProperties(tabletCamAvatarEntity, ["position"]).position;
|
|
Audio.playSound(SOUND_SNAPSHOT, {
|
|
position: { x: tabletCamAvatarEntityPosition.x, y: tabletCamAvatarEntityPosition.y, z: tabletCamAvatarEntityPosition.z },
|
|
localOnly: true,
|
|
volume: 0.2
|
|
});
|
|
Window.takeSecondaryCameraSnapshot();
|
|
}
|
|
|
|
function maybeTakePhoto() {
|
|
if (tabletCamAvatarEntity) {
|
|
secondaryCameraConfig.resetSizeSpectatorCamera(secondaryCameraResolutionWidth, secondaryCameraResolutionHeight);
|
|
// Wait a moment before taking the photo for the resolution to update
|
|
Script.setTimeout(function () {
|
|
takePhoto();
|
|
}, 250);
|
|
}
|
|
}
|
|
|
|
var snapshotQuality = Settings.getValue("tabletCam/quality", "normal");
|
|
function setSnapshotQuality(quality) {
|
|
snapshotQuality = quality;
|
|
Settings.setValue("tabletCam/quality", snapshotQuality);
|
|
|
|
var shortSideTargetResolution = 1000;
|
|
if (snapshotQuality === "low") {
|
|
shortSideTargetResolution = 500;
|
|
} else if (snapshotQuality === "normal") {
|
|
shortSideTargetResolution = 1000;
|
|
} else if (snapshotQuality === "high") {
|
|
shortSideTargetResolution = 2160;
|
|
} else if (snapshotQuality === "extreme") {
|
|
shortSideTargetResolution = 4320;
|
|
}
|
|
|
|
if (tallOrientation && !HMD.active) {
|
|
secondaryCameraResolutionWidth = shortSideTargetResolution;
|
|
secondaryCameraResolutionHeight = secondaryCameraResolutionWidth / aspectRatio;
|
|
|
|
secondaryCameraResolutionPreviewWidth = PREVIEW_SHORT_SIDE_RESOLUTION;
|
|
secondaryCameraResolutionPreviewHeight = secondaryCameraResolutionPreviewWidth / aspectRatio;
|
|
} else {
|
|
secondaryCameraResolutionHeight = shortSideTargetResolution;
|
|
secondaryCameraResolutionWidth = secondaryCameraResolutionHeight / aspectRatio;
|
|
|
|
secondaryCameraResolutionPreviewHeight = PREVIEW_SHORT_SIDE_RESOLUTION;
|
|
secondaryCameraResolutionPreviewWidth = secondaryCameraResolutionPreviewHeight / aspectRatio;
|
|
}
|
|
|
|
secondaryCameraConfig.resetSizeSpectatorCamera(secondaryCameraResolutionPreviewWidth, secondaryCameraResolutionPreviewHeight);
|
|
}
|
|
|
|
var aspectRatio = parseFloat(Settings.getValue("tabletCam/aspectRatio", "0.8"));
|
|
function setAspectRatio(ratio) {
|
|
aspectRatio = ratio;
|
|
Settings.setValue("tabletCam/aspectRatio", aspectRatio);
|
|
|
|
setSnapshotQuality(snapshotQuality);
|
|
}
|
|
|
|
var tallOrientation = Settings.getValue("tabletCam/tallOrientation", true);
|
|
function setOrientation(orientation) {
|
|
tallOrientation = orientation;
|
|
Settings.setValue("tabletCam/tallOrientation", tallOrientation);
|
|
|
|
setSnapshotQuality(snapshotQuality);
|
|
}
|
|
|
|
function photoDirChanged(snapshotPath) {
|
|
Window.browseDirChanged.disconnect(photoDirChanged);
|
|
if (snapshotPath !== "") { // not cancelled
|
|
Snapshot.setSnapshotsLocation(snapshotPath);
|
|
ui.sendMessage({
|
|
method: "photoDirectoryChanged",
|
|
photoDirectory: snapshotPath
|
|
});
|
|
}
|
|
}
|
|
|
|
function fromQml(message) {
|
|
switch (message.method) {
|
|
case 'switchCams':
|
|
switchCams(message.frontCamInUse);
|
|
break;
|
|
case 'switchOrientation':
|
|
setOrientation(!tallOrientation);
|
|
break;
|
|
case 'setFlashStatus':
|
|
setFlashStatus(message.enabled);
|
|
break;
|
|
case 'takePhoto':
|
|
maybeTakePhoto();
|
|
break;
|
|
case 'updateCameravFoV':
|
|
vFoV = message.vFoV;
|
|
secondaryCameraConfig.vFoV = vFoV;
|
|
Settings.setValue("tabletCam/vFoV", vFoV);
|
|
break;
|
|
case 'setSnapshotQuality':
|
|
setSnapshotQuality(message.quality);
|
|
break;
|
|
case 'setAspectRatio':
|
|
setAspectRatio(message.aspectRatio);
|
|
break;
|
|
case 'activeViewChanged':
|
|
if (message.activeView === "settingsView" || message.activeView === "reviewView") {
|
|
//disableTabletCam();
|
|
} else {
|
|
enableTabletCam();
|
|
}
|
|
break;
|
|
case 'setPhotoDirectory':
|
|
Window.browseDirChanged.connect(photoDirChanged);
|
|
Window.browseDirAsync("Choose Photo Directory", "", "");
|
|
break;
|
|
case 'setDetached':
|
|
detached = message.detached;
|
|
Settings.setValue("tabletCam/detached", detached);
|
|
var newTabletCamAvatarEntityProps = getDynamicTabletCamAvatarEntityProperties();
|
|
Entities.editEntity(tabletCamAvatarEntity, newTabletCamAvatarEntityProps);
|
|
break;
|
|
default:
|
|
print('Unrecognized message from TabletCam.qml.');
|
|
}
|
|
}
|
|
|
|
function setTakePhotoControllerMappingStatus(status) {
|
|
if (!takePhotoControllerMapping) {
|
|
return;
|
|
}
|
|
if (status) {
|
|
takePhotoControllerMapping.enable();
|
|
} else {
|
|
takePhotoControllerMapping.disable();
|
|
}
|
|
}
|
|
|
|
var takePhotoControllerMapping;
|
|
var takePhotoControllerMappingName = 'Hifi-TabletCam-Mapping-TakePhoto';
|
|
function registerTakePhotoControllerMapping() {
|
|
takePhotoControllerMapping = Controller.newMapping(takePhotoControllerMappingName);
|
|
if (controllerType === "OculusTouch") {
|
|
takePhotoControllerMapping.from(Controller.Standard.RS).to(function (value) {
|
|
if (value === 1.0) {
|
|
maybeTakePhoto();
|
|
}
|
|
return;
|
|
});
|
|
} else if (controllerType === "Vive") {
|
|
takePhotoControllerMapping.from(Controller.Standard.RightPrimaryThumb).to(function (value) {
|
|
if (value === 1.0) {
|
|
maybeTakePhoto();
|
|
}
|
|
return;
|
|
});
|
|
}
|
|
}
|
|
|
|
var controllerType = "Other";
|
|
function registerButtonMappings() {
|
|
var VRDevices = Controller.getDeviceNames().toString();
|
|
if (VRDevices) {
|
|
if (VRDevices.indexOf("Vive") !== -1) {
|
|
controllerType = "Vive";
|
|
} else if (VRDevices.indexOf("OculusTouch") !== -1) {
|
|
controllerType = "OculusTouch";
|
|
} else {
|
|
return; // Neither Vive nor Touch detected
|
|
}
|
|
}
|
|
|
|
if (!takePhotoControllerMapping) {
|
|
registerTakePhotoControllerMapping();
|
|
}
|
|
}
|
|
|
|
function onHMDChanged(isHMDMode) {
|
|
registerButtonMappings();
|
|
disableTabletCam();
|
|
}
|
|
|
|
var cameraRollPaths = JSON.parse(Settings.getValue("tabletCam/cameraRollPaths", '{"paths": []}'));
|
|
function onStillSnapshotTaken(path) {
|
|
var tempObject = {};
|
|
tempObject.imagePath = "file:///" + path;
|
|
|
|
cameraRollPaths.paths.unshift(tempObject);
|
|
if (cameraRollPaths.paths.length > 15) {
|
|
cameraRollPaths.paths.pop();
|
|
}
|
|
Settings.setValue("tabletCam/cameraRollPaths", JSON.stringify(cameraRollPaths));
|
|
|
|
secondaryCameraConfig.resetSizeSpectatorCamera(secondaryCameraResolutionPreviewWidth, secondaryCameraResolutionPreviewHeight);
|
|
ui.sendMessage({
|
|
method: 'stillSnapshotTaken',
|
|
lastStillSnapshotPath: tempObject.imagePath
|
|
});
|
|
}
|
|
|
|
var signalsWired = false;
|
|
function wireSignals(shouldWire) {
|
|
if (signalsWired === shouldWire) {
|
|
return;
|
|
}
|
|
|
|
signalsWired = shouldWire;
|
|
|
|
if (shouldWire) {
|
|
Window.stillSnapshotTaken.connect(onStillSnapshotTaken);
|
|
} else {
|
|
Window.stillSnapshotTaken.disconnect(onStillSnapshotTaken);
|
|
}
|
|
}
|
|
|
|
function inFrontOf(distance, position, orientation) {
|
|
return Vec3.sum(position || MyAvatar.position,
|
|
Vec3.multiply(distance, Quat.getForward(orientation || MyAvatar.orientation)));
|
|
}
|
|
|
|
var detached = false;
|
|
Settings.setValue("tabletCam/detached", detached);
|
|
function getDynamicTabletCamAvatarEntityProperties() {
|
|
var dynamicProps = {
|
|
dimensions: {"x":0.1600, "y":0.1021, "z":0.1137}
|
|
};
|
|
|
|
if (detached) {
|
|
//print("DETACHED MODE");
|
|
dynamicProps.collisionless = false;
|
|
dynamicProps.ignoreForCollisions = false;
|
|
dynamicProps.grab = {
|
|
"grabbable": true,
|
|
"equippableLeftRotation": {
|
|
"x": -0.0000152587890625,
|
|
"y": -0.0000152587890625,
|
|
"z": -0.0000152587890625,
|
|
"w": 1
|
|
},
|
|
"equippableRightRotation": {
|
|
"x": -0.0000152587890625,
|
|
"y": -0.0000152587890625,
|
|
"z": -0.0000152587890625,
|
|
"w": 1
|
|
}
|
|
};
|
|
dynamicProps.visible = true;
|
|
dynamicProps.parentID = Uuid.NULL;
|
|
dynamicProps.parentJointIndex = 65535;
|
|
dynamicProps.triggerable = true;
|
|
if (tabletCamAvatarEntity) {
|
|
var currentProps = Entities.getEntityProperties(tabletCamAvatarEntity, ["position", "rotation"]);
|
|
if (!!HMD.tabletID) {
|
|
dynamicProps.position = inFrontOf(0.2, currentProps.position, currentProps.rotation);
|
|
} else {
|
|
dynamicProps.position = currentProps.position;
|
|
}
|
|
dynamicProps.rotation = currentProps.rotation;
|
|
} else {
|
|
dynamicProps.position = inFrontOf(0.5);
|
|
dynamicProps.rotation = MyAvatar.orientation;
|
|
}
|
|
dynamicProps.velocity = [0, 0, 0];
|
|
dynamicProps.angularVelocity = [0, 0, 0];
|
|
} else {
|
|
dynamicProps.triggerable = false;
|
|
dynamicProps.collisionless = true;
|
|
dynamicProps.ignoreForCollisions = true;
|
|
dynamicProps.grab = {
|
|
"grabbable": false
|
|
};
|
|
dynamicProps.visible = false;
|
|
|
|
if (!!HMD.tabletID) {
|
|
//print("TABLET MODE");
|
|
dynamicProps.parentID = HMD.tabletID;
|
|
dynamicProps.parentJointIndex = 65535;
|
|
dynamicProps.dimensions = [0.01, 0.01, 0.01];
|
|
} else {
|
|
//print("DESKTOP USER CAMERA MODE");
|
|
var cameraMode = Camera.mode;
|
|
// If:
|
|
// - User is in third person mode
|
|
// - User is using the rear-facing camera
|
|
if (cameraMode !== "first person" && !frontCamInUse) {
|
|
dynamicProps.parentID = MyAvatar.sessionUUID;
|
|
dynamicProps.parentJointIndex = MyAvatar.getJointIndex("_CAMERA_MATRIX");
|
|
} else {
|
|
dynamicProps.parentID = MyAvatar.sessionUUID;
|
|
var jointIndex = MyAvatar.getJointIndex("HeadTop_End");
|
|
if (jointIndex === -1) {
|
|
jointIndex = MyAvatar.getJointIndex("Head");
|
|
}
|
|
dynamicProps.parentJointIndex = jointIndex;
|
|
}
|
|
}
|
|
|
|
dynamicProps.localPosition = {
|
|
"x": 0,
|
|
"y": !!HMD.tabletID ? 0.215 : (frontCamInUse ? -0.03 : (Camera.mode !== "first person" ? 0 : -0.02)),
|
|
"z": !!HMD.tabletID ? (frontCamInUse ? -0.02 : 0.1) : (frontCamInUse ? 1 : (Camera.mode !== "first person" ? 0 : 0.05))
|
|
};
|
|
|
|
if (!!HMD.tabletID) {
|
|
dynamicProps.localRotation = {
|
|
"x": 0,
|
|
"y": frontCamInUse ? 0 : 1,
|
|
"z": 0,
|
|
"w": frontCamInUse ? 1 : 0
|
|
};
|
|
} else {
|
|
dynamicProps.localRotation = {
|
|
"x": 0,
|
|
"y": frontCamInUse || (!frontCamInUse && Camera.mode !== "first person") ? 0 : 1,
|
|
"z": 0,
|
|
"w": frontCamInUse || (!frontCamInUse && Camera.mode !== "first person") ? 1 : 0
|
|
};
|
|
}
|
|
}
|
|
|
|
return dynamicProps;
|
|
}
|
|
|
|
function onModeUpdated(newMode) {
|
|
if (tabletCamAvatarEntity) {
|
|
var newTabletCamAvatarEntityProps = getDynamicTabletCamAvatarEntityProperties();
|
|
Entities.editEntity(tabletCamAvatarEntity, newTabletCamAvatarEntityProps);
|
|
}
|
|
}
|
|
|
|
function onClosed() {
|
|
if (!detached) {
|
|
disableTabletCam();
|
|
}
|
|
|
|
if (tabletCamLocalEntity) {
|
|
Entities.deleteEntity(tabletCamLocalEntity);
|
|
tabletCamLocalEntity = false;
|
|
}
|
|
}
|
|
|
|
function buttonActive(isActive) {
|
|
ui.button.editProperties({isActive: isActive || tabletCamRunning});
|
|
}
|
|
|
|
var ui;
|
|
function startup() {
|
|
ui = new AppUi({
|
|
buttonName: APPLICATION_CAPTION,
|
|
home: Script.resolvePath("./ui/TabletCam.qml"),
|
|
// Selfie by Path Lord from the Noun Project
|
|
graphicsDirectory: Script.resolvePath("appIcons/"),
|
|
onOpened: enableTabletCam,
|
|
onClosed: onClosed,
|
|
onMessage: fromQml,
|
|
buttonActive: buttonActive
|
|
});
|
|
|
|
Window.domainChanged.connect(onDomainChanged);
|
|
ui.tablet.tabletShownChanged.connect(tabletVisibilityChanged);
|
|
HMD.displayModeChanged.connect(onHMDChanged);
|
|
Camera.modeUpdated.connect(onModeUpdated);
|
|
|
|
registerButtonMappings();
|
|
}
|
|
startup();
|
|
|
|
function shutdown() {
|
|
disableTabletCam();
|
|
Window.domainChanged.disconnect(onDomainChanged);
|
|
ui.tablet.tabletShownChanged.disconnect(tabletVisibilityChanged);
|
|
HMD.displayModeChanged.disconnect(onHMDChanged);
|
|
Camera.modeUpdated.disconnect(onModeUpdated);
|
|
if (takePhotoControllerMapping) {
|
|
takePhotoControllerMapping.disable();
|
|
}
|
|
wireSignals(false);
|
|
}
|
|
Script.scriptEnding.connect(shutdown);
|
|
|
|
// "Camera Shutter, Fast, A.wav" by InspectorJ (www.jshaw.co.uk) of Freesound.org
|
|
var SOUND_SNAPSHOT = SoundCache.getSound(Script.resolvePath("sounds/snap.wav"));
|
|
var SOUND_FLASH_ON = SoundCache.getSound(Script.resolvePath("sounds/flashOn.wav"));
|
|
var SOUND_FLASH_OFF = SoundCache.getSound(Script.resolvePath("sounds/flashOff.wav"));
|
|
}()); // END LOCAL_SCOPE
|