diff --git a/unpublishedScripts/marketplace/spectator-camera/Spectator Camera Marketplace Image.jpg b/unpublishedScripts/marketplace/spectator-camera/Spectator Camera Marketplace Image.jpg
new file mode 100644
index 0000000000..19696f88fb
Binary files /dev/null and b/unpublishedScripts/marketplace/spectator-camera/Spectator Camera Marketplace Image.jpg differ
diff --git a/unpublishedScripts/marketplace/spectator-camera/SpectatorCamera.qml b/unpublishedScripts/marketplace/spectator-camera/SpectatorCamera.qml
new file mode 100644
index 0000000000..c1b62368a9
--- /dev/null
+++ b/unpublishedScripts/marketplace/spectator-camera/SpectatorCamera.qml
@@ -0,0 +1,418 @@
+//
+// SpectatorCamera.qml
+// qml/hifi
+//
+// Spectator Camera v2.0
+//
+// Created by Zach Fox on 2018-04-18
+// Copyright 2018 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
+//
+
+import Hifi 1.0 as Hifi
+import QtQuick 2.7
+import "qrc:////qml//styles-uit" as HifiStylesUit
+import "qrc:////qml//controls-uit" as HifiControlsUit
+import "qrc:////qml//controls" as HifiControls
+import "qrc:////qml//hifi" as Hifi
+
+Rectangle {
+ HifiStylesUit.HifiConstants { id: hifi; }
+
+ id: root;
+ // Style
+ color: hifi.colors.baseGray;
+
+ // The letterbox used for popup messages
+ Hifi.LetterboxMessage {
+ id: letterboxMessage;
+ z: 999; // Force the popup on top of everything else
+ }
+ function letterbox(headerGlyph, headerText, message) {
+ letterboxMessage.headerGlyph = headerGlyph;
+ letterboxMessage.headerText = headerText;
+ letterboxMessage.text = message;
+ letterboxMessage.visible = true;
+ letterboxMessage.popupRadius = 0;
+ }
+
+ //
+ // TITLE BAR START
+ //
+ Item {
+ id: titleBarContainer;
+ // Size
+ width: root.width;
+ height: 50;
+ // Anchors
+ anchors.left: parent.left;
+ anchors.top: parent.top;
+
+ // "Spectator" text
+ HifiStylesUit.RalewaySemiBold {
+ id: titleBarText;
+ text: "Spectator Camera";
+ // Text size
+ size: hifi.fontSizes.overlayTitle;
+ // Anchors
+ anchors.fill: parent;
+ anchors.leftMargin: 16;
+ // Style
+ color: hifi.colors.lightGrayText;
+ // Alignment
+ horizontalAlignment: Text.AlignHLeft;
+ verticalAlignment: Text.AlignVCenter;
+ }
+
+ // Separator
+ HifiControlsUit.Separator {
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+ anchors.bottom: parent.bottom;
+ }
+ }
+ //
+ // TITLE BAR END
+ //
+
+ //
+ // SPECTATOR APP DESCRIPTION START
+ //
+ Item {
+ id: spectatorDescriptionContainer;
+ // Size
+ width: root.width;
+ height: childrenRect.height;
+ // Anchors
+ anchors.left: parent.left;
+ anchors.top: titleBarContainer.bottom;
+
+ // (i) Glyph
+ HifiStylesUit.HiFiGlyphs {
+ id: spectatorDescriptionGlyph;
+ text: hifi.glyphs.info;
+ // Size
+ width: 20;
+ height: parent.height;
+ size: 60;
+ // Anchors
+ anchors.left: parent.left;
+ anchors.leftMargin: 20;
+ anchors.top: parent.top;
+ anchors.topMargin: 0;
+ // Style
+ color: hifi.colors.lightGrayText;
+ horizontalAlignment: Text.AlignHLeft;
+ verticalAlignment: Text.AlignTop;
+ }
+
+ // "Spectator" app description text
+ HifiStylesUit.RalewayLight {
+ id: spectatorDescriptionText;
+ text: "Spectator lets you change what your monitor displays while you're using a VR headset. Use Spectator when streaming and recording video.";
+ // Text size
+ size: 14;
+ // Size
+ width: 350;
+ height: paintedHeight;
+ // Anchors
+ anchors.top: parent.top;
+ anchors.topMargin: 15;
+ anchors.left: spectatorDescriptionGlyph.right;
+ anchors.leftMargin: 40;
+ // Style
+ color: hifi.colors.lightGrayText;
+ wrapMode: Text.Wrap;
+ // Alignment
+ horizontalAlignment: Text.AlignHLeft;
+ verticalAlignment: Text.AlignVCenter;
+ }
+
+ // "Learn More" text
+ HifiStylesUit.RalewayRegular {
+ id: spectatorLearnMoreText;
+ text: "Learn More About Spectator";
+ // Text size
+ size: 14;
+ // Size
+ width: paintedWidth;
+ height: paintedHeight;
+ // Anchors
+ anchors.top: spectatorDescriptionText.bottom;
+ anchors.topMargin: 10;
+ anchors.left: spectatorDescriptionText.anchors.left;
+ anchors.leftMargin: spectatorDescriptionText.anchors.leftMargin;
+ // Style
+ color: hifi.colors.blueAccent;
+ wrapMode: Text.WordWrap;
+ font.underline: true;
+ // Alignment
+ horizontalAlignment: Text.AlignHLeft;
+ verticalAlignment: Text.AlignVCenter;
+
+ MouseArea {
+ anchors.fill: parent;
+ hoverEnabled: enabled;
+ onClicked: {
+ letterbox(hifi.glyphs.question,
+ "Spectator Camera",
+ "By default, your monitor shows a preview of what you're seeing in VR. " +
+ "Using the Spectator Camera app, your monitor can display the view " +
+ "from a virtual hand-held camera - perfect for taking selfies or filming " +
+ "your friends!
" +
+ "
Streaming and Recording
" +
+ "We recommend OBS for streaming and recording the contents of your monitor to services like " +
+ "Twitch, YouTube Live, and Facebook Live.
" +
+ "To get started using OBS, click this link now. The page will open in an external browser:
" +
+ 'OBS Official Overview Guide');
+ }
+ onEntered: parent.color = hifi.colors.blueHighlight;
+ onExited: parent.color = hifi.colors.blueAccent;
+ }
+ }
+
+ // Separator
+ HifiControlsUit.Separator {
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+ anchors.top: spectatorLearnMoreText.bottom;
+ anchors.topMargin: spectatorDescriptionText.anchors.topMargin;
+ }
+ }
+ //
+ // SPECTATOR APP DESCRIPTION END
+ //
+
+ Item {
+ visible: !HMD.active;
+ height: root.height - spectatorDescriptionContainer.height - titleBarContainer.height;
+ anchors.top: spectatorDescriptionContainer.bottom;
+ anchors.topMargin: 20;
+ anchors.left: parent.left;
+ anchors.leftMargin: 25;
+ anchors.right: parent.right;
+ anchors.rightMargin: anchors.leftMargin;
+
+ HifiStylesUit.FiraSansRegular {
+ text: "Spectator Camera only works in VR mode.\nPlease put on your headset.";
+ size: 18;
+ color: hifi.colors.lightGrayText;
+ anchors.fill: parent;
+ horizontalAlignment: Text.AlignHCenter;
+ verticalAlignment: Text.AlignVCenter;
+ wrapMode: Text.Wrap;
+ }
+ }
+
+ //
+ // SPECTATOR CONTROLS START
+ //
+ Item {
+ id: spectatorControlsContainer;
+ visible: HMD.active;
+ // Size
+ height: root.height - spectatorDescriptionContainer.height - titleBarContainer.height;
+ // Anchors
+ anchors.top: spectatorDescriptionContainer.bottom;
+ anchors.topMargin: 20;
+ anchors.left: parent.left;
+ anchors.leftMargin: 25;
+ anchors.right: parent.right;
+ anchors.rightMargin: anchors.leftMargin;
+
+ // "Camera On" Button
+ HifiControlsUit.Button {
+ property bool camIsOn: false;
+
+ id: cameraToggleButton;
+ color: camIsOn ? hifi.buttons.red : hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.left: parent.left;
+ anchors.top: parent.top;
+ anchors.right: parent.right;
+ height: 40;
+ text: camIsOn ? "TURN OFF SPECTATOR CAMERA" : "TURN ON SPECTATOR CAMERA";
+ onClicked: {
+ camIsOn = !camIsOn;
+ sendToScript({method: (camIsOn ? 'spectatorCameraOn' : 'spectatorCameraOff')});
+ spectatorCameraPreview.ready = camIsOn;
+ }
+ }
+
+ // Instructions or Preview
+ Rectangle {
+ id: spectatorCameraImageContainer;
+ anchors.left: parent.left;
+ anchors.top: cameraToggleButton.bottom;
+ anchors.topMargin: 20;
+ anchors.right: parent.right;
+ height: 250;
+ color: cameraToggleButton.camIsOn ? "transparent" : "black";
+
+ AnimatedImage {
+ source: "static.gif"
+ visible: !cameraToggleButton.camIsOn;
+ anchors.fill: parent;
+ opacity: 0.15;
+ }
+
+ // Instructions (visible when display texture isn't set)
+ HifiStylesUit.FiraSansRegular {
+ id: spectatorCameraInstructions;
+ text: "Turn on Spectator Camera for a preview\nof what your monitor shows.";
+ size: 16;
+ color: hifi.colors.lightGrayText;
+ visible: !cameraToggleButton.camIsOn;
+ anchors.fill: parent;
+ horizontalAlignment: Text.AlignHCenter;
+ verticalAlignment: Text.AlignVCenter;
+ }
+
+ // Spectator Camera Preview
+ Hifi.ResourceImageItem {
+ id: spectatorCameraPreview;
+ visible: cameraToggleButton.camIsOn;
+ url: monitorShowsSwitch.checked ? "resource://spectatorCameraFrame" : "resource://hmdPreviewFrame";
+ ready: cameraToggleButton.camIsOn;
+ mirrorVertically: true;
+ anchors.fill: parent;
+ onVisibleChanged: {
+ ready = cameraToggleButton.camIsOn;
+ update();
+ }
+ }
+ }
+
+
+ // "Monitor Shows" Switch Label Glyph
+ HifiStylesUit.HiFiGlyphs {
+ id: monitorShowsSwitchLabelGlyph;
+ text: hifi.glyphs.screen;
+ size: 32;
+ color: hifi.colors.blueHighlight;
+ anchors.top: spectatorCameraImageContainer.bottom;
+ anchors.topMargin: 13;
+ anchors.left: parent.left;
+ }
+ // "Monitor Shows" Switch Label
+ HifiStylesUit.RalewayLight {
+ id: monitorShowsSwitchLabel;
+ text: "MONITOR SHOWS:";
+ anchors.top: spectatorCameraImageContainer.bottom;
+ anchors.topMargin: 20;
+ anchors.left: monitorShowsSwitchLabelGlyph.right;
+ anchors.leftMargin: 6;
+ size: 16;
+ width: paintedWidth;
+ height: paintedHeight;
+ color: hifi.colors.lightGrayText;
+ verticalAlignment: Text.AlignVCenter;
+ }
+ // "Monitor Shows" Switch
+ HifiControlsUit.Switch {
+ id: monitorShowsSwitch;
+ height: 30;
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+ anchors.top: monitorShowsSwitchLabel.bottom;
+ anchors.topMargin: 10;
+ labelTextOff: "HMD Preview";
+ labelTextOn: "Camera View";
+ labelGlyphOnText: hifi.glyphs.alert;
+ onCheckedChanged: {
+ sendToScript({method: 'setMonitorShowsCameraView', params: checked});
+ }
+ }
+
+ // "Switch View From Controller" Checkbox
+ HifiControlsUit.CheckBox {
+ id: switchViewFromControllerCheckBox;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.left: parent.left;
+ anchors.top: monitorShowsSwitch.bottom;
+ anchors.topMargin: 25;
+ text: "";
+ boxSize: 24;
+ onClicked: {
+ sendToScript({method: 'changeSwitchViewFromControllerPreference', params: checked});
+ }
+ }
+
+ // "Take Snapshot" Checkbox
+ HifiControlsUit.CheckBox {
+ id: takeSnapshotFromControllerCheckBox;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.left: parent.left;
+ anchors.top: switchViewFromControllerCheckBox.bottom;
+ anchors.topMargin: 10;
+ text: "";
+ boxSize: 24;
+ onClicked: {
+ sendToScript({method: 'changeTakeSnapshotFromControllerPreference', params: checked});
+ }
+ }
+ }
+ //
+ // SPECTATOR CONTROLS END
+ //
+
+ //
+ // FUNCTION DEFINITIONS START
+ //
+ //
+ // Function Name: fromScript()
+ //
+ // Relevant Variables:
+ // None
+ //
+ // Arguments:
+ // message: The message sent from the SpectatorCamera JavaScript.
+ // Messages are in format "{method, params}", like json-rpc.
+ //
+ // Description:
+ // Called when a message is received from spectatorCamera.js.
+ //
+ function fromScript(message) {
+ switch (message.method) {
+ case 'updateSpectatorCameraCheckbox':
+ cameraToggleButton.camIsOn = message.params;
+ break;
+ case 'updateMonitorShowsSwitch':
+ monitorShowsSwitch.checked = message.params;
+ break;
+ case 'updateControllerMappingCheckbox':
+ switchViewFromControllerCheckBox.checked = message.switchViewSetting;
+ switchViewFromControllerCheckBox.enabled = true;
+ takeSnapshotFromControllerCheckBox.checked = message.takeSnapshotSetting;
+ takeSnapshotFromControllerCheckBox.enabled = true;
+
+ if (message.controller === "OculusTouch") {
+ switchViewFromControllerCheckBox.text = "Clicking Touch's Left Thumbstick Switches Monitor View";
+ takeSnapshotFromControllerCheckBox.text = "Clicking Touch's Right Thumbstick Takes Snapshot";
+ } else if (message.controller === "Vive") {
+ switchViewFromControllerCheckBox.text = "Clicking Left Thumb Pad Switches Monitor View";
+ takeSnapshotFromControllerCheckBox.text = "Clicking Right Thumb Pad Takes Snapshot";
+ } else {
+ switchViewFromControllerCheckBox.text = "Pressing Ctrl+0 Switches Monitor View";
+ switchViewFromControllerCheckBox.checked = true;
+ switchViewFromControllerCheckBox.enabled = false;
+ takeSnapshotFromControllerCheckBox.visible = false;
+ }
+ break;
+ case 'showPreviewTextureNotInstructions':
+ console.log('showPreviewTextureNotInstructions recvd', JSON.stringify(message));
+ spectatorCameraPreview.url = message.url;
+ spectatorCameraPreview.visible = message.setting;
+ break;
+ default:
+ console.log('Unrecognized message from spectatorCamera.js:', JSON.stringify(message));
+ }
+ }
+ signal sendToScript(var message);
+
+ //
+ // FUNCTION DEFINITIONS END
+ //
+}
diff --git a/unpublishedScripts/marketplace/spectator-camera/snap.wav b/unpublishedScripts/marketplace/spectator-camera/snap.wav
new file mode 100644
index 0000000000..e5b86c0c71
Binary files /dev/null and b/unpublishedScripts/marketplace/spectator-camera/snap.wav differ
diff --git a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.app.json b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.app.json
new file mode 100644
index 0000000000..e71c657581
--- /dev/null
+++ b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.app.json
@@ -0,0 +1,4 @@
+{
+ "scriptURL": "http://mpassets-staging.highfidelity.com/26156ea5-cdff-43c2-9581-d6b0fa5e00ef-v1/spectatorCamera.js",
+ "homeURL": "http://mpassets-staging.highfidelity.com/26156ea5-cdff-43c2-9581-d6b0fa5e00ef-v1/SpectatorCamera.qml"
+}
\ No newline at end of file
diff --git a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js
index 730a5808b8..ce445a5f8e 100644
--- a/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js
+++ b/unpublishedScripts/marketplace/spectator-camera/spectatorCamera.js
@@ -150,17 +150,15 @@
// Relevant Variables:
// -button: The tablet button.
// -buttonName: The name of the button.
- // -showSpectatorInDesktop: Set to "true" to show the "SPECTATOR" app in desktop mode.
var button = false;
var buttonName = "SPECTATOR";
- var showSpectatorInDesktop = false;
- function addOrRemoveButton(isShuttingDown, isHMDMode) {
+ function addOrRemoveButton(isShuttingDown) {
if (!tablet) {
print("Warning in addOrRemoveButton(): 'tablet' undefined!");
return;
}
if (!button) {
- if ((isHMDMode || showSpectatorInDesktop) && !isShuttingDown) {
+ if (!isShuttingDown) {
button = tablet.addButton({
text: buttonName,
icon: "icons/tablet-icons/spectator-i.svg",
@@ -169,7 +167,7 @@
button.clicked.connect(onTabletButtonClicked);
}
} else if (button) {
- if ((!isHMDMode && !showSpectatorInDesktop) || isShuttingDown) {
+ if (isShuttingDown) {
button.clicked.disconnect(onTabletButtonClicked);
tablet.removeButton(button);
button = false;
@@ -189,7 +187,7 @@
var tablet = null;
function startup() {
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
- addOrRemoveButton(false, HMD.active);
+ addOrRemoveButton(false);
tablet.screenChanged.connect(onTabletScreenChanged);
Window.domainChanged.connect(onDomainChanged);
Window.geometryChanged.connect(resizeViewFinderOverlay);
@@ -320,14 +318,14 @@
const SWITCH_VIEW_FROM_CONTROLLER_DEFAULT = false;
var switchViewFromController = !!Settings.getValue('spectatorCamera/switchViewFromController', SWITCH_VIEW_FROM_CONTROLLER_DEFAULT);
- function setControllerMappingStatus(status) {
- if (!controllerMapping) {
+ function setSwitchViewControllerMappingStatus(status) {
+ if (!switchViewControllerMapping) {
return;
}
if (status) {
- controllerMapping.enable();
+ switchViewControllerMapping.enable();
} else {
- controllerMapping.disable();
+ switchViewControllerMapping.disable();
}
}
function setSwitchViewFromController(setting) {
@@ -335,9 +333,30 @@
return;
}
switchViewFromController = setting;
- setControllerMappingStatus(switchViewFromController);
+ setSwitchViewControllerMappingStatus(switchViewFromController);
Settings.setValue('spectatorCamera/switchViewFromController', setting);
}
+
+ const TAKE_SNAPSHOT_FROM_CONTROLLER_DEFAULT = false;
+ var takeSnapshotFromController = !!Settings.getValue('spectatorCamera/takeSnapshotFromController', TAKE_SNAPSHOT_FROM_CONTROLLER_DEFAULT);
+ function setTakeSnapshotControllerMappingStatus(status) {
+ if (!takeSnapshotControllerMapping) {
+ return;
+ }
+ if (status) {
+ takeSnapshotControllerMapping.enable();
+ } else {
+ takeSnapshotControllerMapping.disable();
+ }
+ }
+ function setTakeSnapshotFromController(setting) {
+ if (setting === takeSnapshotFromController) {
+ return;
+ }
+ takeSnapshotFromController = setting;
+ setTakeSnapshotControllerMappingStatus(takeSnapshotFromController);
+ Settings.setValue('spectatorCamera/takeSnapshotFromController', setting);
+ }
// Function Name: registerButtonMappings()
//
@@ -345,11 +364,61 @@
// -Updates controller button mappings for Spectator Camera.
//
// Relevant Variables:
- // -controllerMappingName: The name of the controller mapping.
- // -controllerMapping: The controller mapping itself.
+ // -switchViewControllerMappingName: The name of the controller mapping.
+ // -switchViewControllerMapping: The controller mapping itself.
+ // -takeSnapshotControllerMappingName: The name of the controller mapping.
+ // -takeSnapshotControllerMapping: The controller mapping itself.
// -controllerType: "OculusTouch", "Vive", "Other".
- var controllerMappingName;
- var controllerMapping;
+ var switchViewControllerMapping;
+ var switchViewControllerMappingName = 'Hifi-SpectatorCamera-Mapping-SwitchView';
+ function registerSwitchViewControllerMapping() {
+ switchViewControllerMapping = Controller.newMapping(switchViewControllerMappingName);
+ if (controllerType === "OculusTouch") {
+ switchViewControllerMapping.from(Controller.Standard.LS).to(function (value) {
+ if (value === 1.0) {
+ setMonitorShowsCameraViewAndSendToQml(!monitorShowsCameraView);
+ }
+ return;
+ });
+ } else if (controllerType === "Vive") {
+ switchViewControllerMapping.from(Controller.Standard.LeftPrimaryThumb).to(function (value) {
+ if (value === 1.0) {
+ setMonitorShowsCameraViewAndSendToQml(!monitorShowsCameraView);
+ }
+ return;
+ });
+ }
+ }
+ var takeSnapshotControllerMapping;
+ var takeSnapshotControllerMappingName = 'Hifi-SpectatorCamera-Mapping-TakeSnapshot';
+ function maybeTakeSnapshot() {
+ if (camera) {
+ Audio.playSound(SNAPSHOT_SOUND, {
+ position: { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.position.z },
+ localOnly: true,
+ volume: 1.0
+ });
+ Window.takeSecondaryCameraSnapshot();
+ }
+ }
+ function registerTakeSnapshotControllerMapping() {
+ takeSnapshotControllerMapping = Controller.newMapping(takeSnapshotControllerMappingName);
+ if (controllerType === "OculusTouch") {
+ takeSnapshotControllerMapping.from(Controller.Standard.RS).to(function (value) {
+ if (value === 1.0) {
+ maybeTakeSnapshot();
+ }
+ return;
+ });
+ } else if (controllerType === "Vive") {
+ takeSnapshotControllerMapping.from(Controller.Standard.RightPrimaryThumb).to(function (value) {
+ if (value === 1.0) {
+ maybeTakeSnapshot();
+ }
+ return;
+ });
+ }
+ }
var controllerType = "Other";
function registerButtonMappings() {
var VRDevices = Controller.getDeviceNames().toString();
@@ -359,30 +428,32 @@
} else if (VRDevices.indexOf("OculusTouch") !== -1) {
controllerType = "OculusTouch";
} else {
- sendToQml({ method: 'updateControllerMappingCheckbox', setting: switchViewFromController, controller: controllerType });
+ sendToQml({
+ method: 'updateControllerMappingCheckbox',
+ switchViewSetting: switchViewFromController,
+ takeSnapshotSetting: takeSnapshotFromController,
+ controller: controllerType
+ });
return; // Neither Vive nor Touch detected
}
}
- controllerMappingName = 'Hifi-SpectatorCamera-Mapping';
- controllerMapping = Controller.newMapping(controllerMappingName);
- if (controllerType === "OculusTouch") {
- controllerMapping.from(Controller.Standard.LS).to(function (value) {
- if (value === 1.0) {
- setMonitorShowsCameraViewAndSendToQml(!monitorShowsCameraView);
- }
- return;
- });
- } else if (controllerType === "Vive") {
- controllerMapping.from(Controller.Standard.LeftPrimaryThumb).to(function (value) {
- if (value === 1.0) {
- setMonitorShowsCameraViewAndSendToQml(!monitorShowsCameraView);
- }
- return;
- });
+ if (!switchViewControllerMapping) {
+ registerSwitchViewControllerMapping();
}
- setControllerMappingStatus(switchViewFromController);
- sendToQml({ method: 'updateControllerMappingCheckbox', setting: switchViewFromController, controller: controllerType });
+ setSwitchViewControllerMappingStatus(switchViewFromController);
+
+ if (!takeSnapshotControllerMapping) {
+ registerTakeSnapshotControllerMapping();
+ }
+ setTakeSnapshotControllerMappingStatus(switchViewFromController);
+
+ sendToQml({
+ method: 'updateControllerMappingCheckbox',
+ switchViewSetting: switchViewFromController,
+ takeSnapshotSetting: takeSnapshotFromController,
+ controller: controllerType
+ });
}
// Function Name: onTabletButtonClicked()
@@ -393,7 +464,7 @@
// Relevant Variables:
// -SPECTATOR_CAMERA_QML_SOURCE: The path to the SpectatorCamera QML
// -onSpectatorCameraScreen: true/false depending on whether we're looking at the spectator camera app.
- var SPECTATOR_CAMERA_QML_SOURCE = "hifi/SpectatorCamera.qml";
+ var SPECTATOR_CAMERA_QML_SOURCE = Script.resolvePath("SpectatorCamera.qml");
var onSpectatorCameraScreen = false;
function onTabletButtonClicked() {
if (!tablet) {
@@ -405,15 +476,6 @@
tablet.gotoHomeScreen();
} else {
tablet.loadQMLSource(SPECTATOR_CAMERA_QML_SOURCE);
- sendToQml({ method: 'updateSpectatorCameraCheckbox', params: !!camera });
- sendToQml({ method: 'updateMonitorShowsSwitch', params: monitorShowsCameraView });
- if (!controllerMapping) {
- registerButtonMappings();
- } else {
- sendToQml({ method: 'updateControllerMappingCheckbox', setting: switchViewFromController, controller: controllerType });
- }
- Menu.setIsOptionChecked("Disable Preview", false);
- Menu.setIsOptionChecked("Mono Preview", true);
}
}
@@ -429,6 +491,23 @@
if (button) {
button.editProperties({ isActive: onSpectatorCameraScreen || camera });
}
+
+ if (onSpectatorCameraScreen) {
+ sendToQml({ method: 'updateSpectatorCameraCheckbox', params: !!camera });
+ sendToQml({ method: 'updateMonitorShowsSwitch', params: monitorShowsCameraView });
+ if (!switchViewControllerMapping) {
+ registerButtonMappings();
+ } else {
+ sendToQml({
+ method: 'updateControllerMappingCheckbox',
+ switchViewSetting: switchViewFromController,
+ takeSnapshotSetting: takeSnapshotFromController,
+ controller: controllerType
+ });
+ }
+ Menu.setIsOptionChecked("Disable Preview", false);
+ Menu.setIsOptionChecked("Mono Preview", true);
+ }
}
// Function Name: sendToQml()
@@ -459,6 +538,9 @@
case 'changeSwitchViewFromControllerPreference':
setSwitchViewFromController(message.params);
break;
+ case 'changeTakeSnapshotFromControllerPreference':
+ setTakeSnapshotFromController(message.params);
+ break;
default:
print('Unrecognized message from SpectatorCamera.qml:', JSON.stringify(message));
}
@@ -469,12 +551,11 @@
// Description:
// -Called from C++ when HMD mode is changed. The argument "isHMDMode" is true if HMD is on; false otherwise.
function onHMDChanged(isHMDMode) {
- if (!controllerMapping) {
+ if (!switchViewControllerMapping || !takeSnapshotControllerMapping) {
registerButtonMappings();
}
setDisplay(monitorShowsCameraView);
- addOrRemoveButton(false, isHMDMode);
- if (!isHMDMode && !showSpectatorInDesktop) {
+ if (!isHMDMode) {
spectatorCameraOff();
}
}
@@ -487,7 +568,7 @@
spectatorCameraOff();
Window.domainChanged.disconnect(onDomainChanged);
Window.geometryChanged.disconnect(resizeViewFinderOverlay);
- addOrRemoveButton(true, HMD.active);
+ addOrRemoveButton(true);
if (tablet) {
tablet.screenChanged.disconnect(onTabletScreenChanged);
if (onSpectatorCameraScreen) {
@@ -496,8 +577,11 @@
}
HMD.displayModeChanged.disconnect(onHMDChanged);
Controller.keyPressEvent.disconnect(keyPressEvent);
- if (controllerMapping) {
- controllerMapping.disable();
+ if (switchViewControllerMapping) {
+ switchViewControllerMapping.disable();
+ }
+ if (takeSnapshotControllerMapping) {
+ takeSnapshotControllerMapping.disable();
}
}
@@ -511,6 +595,7 @@
// These functions will be called when the script is loaded.
var CAMERA_ON_SOUND = SoundCache.getSound(Script.resolvePath("cameraOn.wav"));
+ var SNAPSHOT_SOUND = SoundCache.getSound(Script.resourcesPath() + "sounds/snapshot/snap.wav");
startup();
Script.scriptEnding.connect(shutdown);
diff --git a/unpublishedScripts/marketplace/spectator-camera/static.gif b/unpublishedScripts/marketplace/spectator-camera/static.gif
new file mode 100644
index 0000000000..fbe46f48e6
Binary files /dev/null and b/unpublishedScripts/marketplace/spectator-camera/static.gif differ