mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-06 10:43:11 +02:00
Lots of little improvements and stability fixes
This commit is contained in:
parent
aafcf056c4
commit
eab2feb543
5 changed files with 163 additions and 24 deletions
|
@ -38,6 +38,7 @@
|
|||
#include "MainWindow.h"
|
||||
#include "Snapshot.h"
|
||||
#include "SnapshotUploader.h"
|
||||
#include "ToneMappingEffect.h"
|
||||
|
||||
// filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg
|
||||
// %1 <= username, %2 <= date and time, %3 <= current location
|
||||
|
@ -92,6 +93,7 @@ QString Snapshot::saveSnapshot(QImage image, const QString& filename) {
|
|||
return snapshotPath;
|
||||
}
|
||||
|
||||
QTimer Snapshot::snapshotTimer;
|
||||
|
||||
qint16 Snapshot::snapshotIndex = 0;
|
||||
QVariant Snapshot::oldAttachedEntityId = 0;
|
||||
|
@ -118,6 +120,8 @@ void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, const QString& f
|
|||
oldFarClipPlaneDistance = secondaryCameraRenderConfig->property("farClipPlaneDistance");
|
||||
|
||||
// Initialize some secondary camera render config options for 360 snapshot capture
|
||||
static_cast<ToneMappingConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping"))->setCurve(0);
|
||||
|
||||
secondaryCameraRenderConfig->resetSizeSpectatorCamera(2048, 2048);
|
||||
secondaryCameraRenderConfig->setProperty("attachedEntityId", "");
|
||||
secondaryCameraRenderConfig->setPosition(cameraPosition);
|
||||
|
@ -129,10 +133,9 @@ void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, const QString& f
|
|||
|
||||
snapshotIndex = 0;
|
||||
|
||||
QTimer* snapshotTimer = new QTimer();
|
||||
snapshotTimer->setSingleShot(false);
|
||||
snapshotTimer->setInterval(250);
|
||||
connect(snapshotTimer, &QTimer::timeout, [&] {
|
||||
snapshotTimer.setSingleShot(false);
|
||||
snapshotTimer.setInterval(250);
|
||||
connect(&snapshotTimer, &QTimer::timeout, [] {
|
||||
SecondaryCameraJobConfig* config = static_cast<SecondaryCameraJobConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCamera"));
|
||||
if (snapshotIndex == 0) {
|
||||
downImage = qApp->getActiveDisplayPlugin()->getSecondaryCameraScreenshot();
|
||||
|
@ -153,6 +156,7 @@ void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, const QString& f
|
|||
upImage = qApp->getActiveDisplayPlugin()->getSecondaryCameraScreenshot();
|
||||
} else {
|
||||
// Reset secondary camera render config
|
||||
static_cast<ToneMappingConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob.ToneMapping"))->setCurve(1);
|
||||
config->resetSizeSpectatorCamera(qApp->getWindow()->geometry().width(), qApp->getWindow()->geometry().height());
|
||||
config->setProperty("attachedEntityId", oldAttachedEntityId);
|
||||
config->setProperty("vFoV", oldvFoV);
|
||||
|
@ -162,15 +166,17 @@ void Snapshot::save360Snapshot(const glm::vec3& cameraPosition, const QString& f
|
|||
// Process six QImages
|
||||
QtConcurrent::run(convertToEquirectangular);
|
||||
|
||||
snapshotTimer->stop();
|
||||
snapshotTimer->deleteLater();
|
||||
snapshotTimer.stop();
|
||||
}
|
||||
|
||||
snapshotIndex++;
|
||||
});
|
||||
snapshotTimer->start();
|
||||
snapshotTimer.start();
|
||||
}
|
||||
void Snapshot::convertToEquirectangular() {
|
||||
// I got help from StackOverflow while writing this code:
|
||||
// https://stackoverflow.com/questions/34250742/converting-a-cubemap-into-equirectangular-panorama
|
||||
|
||||
float outputImageWidth = 8192.0f;
|
||||
float outputImageHeight = 4096.0f;
|
||||
QImage outputImage(outputImageWidth, outputImageHeight, QImage::Format_RGB32);
|
||||
|
|
|
@ -54,6 +54,7 @@ public slots:
|
|||
private:
|
||||
static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename = QString());
|
||||
|
||||
static QTimer snapshotTimer;
|
||||
static qint16 snapshotIndex;
|
||||
static QVariant oldAttachedEntityId;
|
||||
static QVariant oldOrientation;
|
||||
|
|
|
@ -28,7 +28,7 @@ Rectangle {
|
|||
// The letterbox used for popup messages
|
||||
Hifi.LetterboxMessage {
|
||||
id: letterboxMessage;
|
||||
z: 999; // Force the popup on top of everything else
|
||||
z: 998; // Force the popup on top of everything else
|
||||
}
|
||||
function letterbox(headerGlyph, headerText, message) {
|
||||
letterboxMessage.headerGlyph = headerGlyph;
|
||||
|
@ -45,7 +45,7 @@ Rectangle {
|
|||
id: titleBarContainer;
|
||||
// Size
|
||||
width: root.width;
|
||||
height: 50;
|
||||
height: 40;
|
||||
// Anchors
|
||||
anchors.left: parent.left;
|
||||
anchors.top: parent.top;
|
||||
|
@ -185,6 +185,46 @@ Rectangle {
|
|||
// SPECTATOR APP DESCRIPTION END
|
||||
//
|
||||
|
||||
Rectangle {
|
||||
z: 999;
|
||||
id: processingSnapshot;
|
||||
anchors.fill: parent;
|
||||
visible: !take360SnapshotButton.enabled;
|
||||
color: Qt.rgba(0.0, 0.0, 0.0, 0.8);
|
||||
|
||||
// This object is always used in a popup.
|
||||
// This MouseArea is used to prevent a user from being
|
||||
// able to click on a button/mouseArea underneath the popup/section.
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: true;
|
||||
propagateComposedEvents: false;
|
||||
}
|
||||
|
||||
AnimatedImage {
|
||||
id: processingImage;
|
||||
source: "processing.gif"
|
||||
width: 74;
|
||||
height: width;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
text: "Processing...";
|
||||
// Anchors
|
||||
anchors.top: processingImage.bottom;
|
||||
anchors.topMargin: 4;
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
width: paintedWidth;
|
||||
// Text size
|
||||
size: 26;
|
||||
// Style
|
||||
color: hifi.colors.white;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// SPECTATOR CONTROLS START
|
||||
//
|
||||
|
@ -194,7 +234,7 @@ Rectangle {
|
|||
height: root.height - spectatorDescriptionContainer.height - titleBarContainer.height;
|
||||
// Anchors
|
||||
anchors.top: spectatorDescriptionContainer.bottom;
|
||||
anchors.topMargin: 20;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 25;
|
||||
anchors.right: parent.right;
|
||||
|
@ -215,7 +255,8 @@ Rectangle {
|
|||
onClicked: {
|
||||
camIsOn = !camIsOn;
|
||||
sendToScript({method: (camIsOn ? 'spectatorCameraOn' : 'spectatorCameraOff')});
|
||||
spectatorCameraPreview.ready = camIsOn;
|
||||
fieldOfViewSlider.value = 45.0;
|
||||
sendToScript({method: 'updateCameravFoV', vFoV: fieldOfViewSlider.value});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,7 +265,7 @@ Rectangle {
|
|||
id: spectatorCameraImageContainer;
|
||||
anchors.left: parent.left;
|
||||
anchors.top: cameraToggleButton.bottom;
|
||||
anchors.topMargin: 20;
|
||||
anchors.topMargin: 8;
|
||||
anchors.right: parent.right;
|
||||
height: 250;
|
||||
color: cameraToggleButton.camIsOn ? "transparent" : "black";
|
||||
|
@ -263,6 +304,67 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: fieldOfView;
|
||||
visible: cameraToggleButton.camIsOn;
|
||||
anchors.top: spectatorCameraImageContainer.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 8;
|
||||
anchors.right: parent.right;
|
||||
height: 35;
|
||||
|
||||
HifiStylesUit.FiraSansRegular {
|
||||
id: fieldOfViewLabel;
|
||||
text: "Field of View (" + fieldOfViewSlider.value + "): ";
|
||||
size: 16;
|
||||
color: hifi.colors.lightGrayText;
|
||||
anchors.left: parent.left;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
width: 140;
|
||||
horizontalAlignment: Text.AlignLeft;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
||||
HifiControlsUit.Slider {
|
||||
id: fieldOfViewSlider;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.right: resetvFoV.left;
|
||||
anchors.rightMargin: 8;
|
||||
anchors.left: fieldOfViewLabel.right;
|
||||
anchors.leftMargin: 8;
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
from: 10.0;
|
||||
to: 120.0;
|
||||
value: 45.0;
|
||||
stepSize: 1;
|
||||
|
||||
onValueChanged: {
|
||||
sendToScript({method: 'updateCameravFoV', vFoV: value});
|
||||
}
|
||||
onPressedChanged: {
|
||||
if (!pressed) {
|
||||
sendToScript({method: 'updateCameravFoV', vFoV: value});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.GlyphButton {
|
||||
id: resetvFoV;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 6;
|
||||
height: parent.height - 8;
|
||||
width: height;
|
||||
glyph: hifi.glyphs.reload;
|
||||
onClicked: {
|
||||
fieldOfViewSlider.value = 45.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// "Monitor Shows" Switch Label Glyph
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
|
@ -338,19 +440,34 @@ Rectangle {
|
|||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
id: take360SnapshotButton;
|
||||
text: "Take 360 Snapshot";
|
||||
enabled: cameraToggleButton.camIsOn;
|
||||
id: takeSnapshotButton;
|
||||
visible: cameraToggleButton.camIsOn;
|
||||
text: "Take Still Snapshot";
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
color: hifi.buttons.blue;
|
||||
anchors.top: takeSnapshotFromControllerCheckBox.visible ? takeSnapshotFromControllerCheckBox.bottom : spectatorCameraImageContainer.bottom;
|
||||
anchors.top: takeSnapshotFromControllerCheckBox.visible ? takeSnapshotFromControllerCheckBox.bottom : fieldOfView.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: parent.left;
|
||||
width: parent.width/2 - 10;
|
||||
height: 40;
|
||||
onClicked: {
|
||||
sendToScript({method: 'takeSecondaryCameraSnapshot'});
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
id: take360SnapshotButton;
|
||||
visible: cameraToggleButton.camIsOn;
|
||||
text: "Take 360 Snapshot";
|
||||
colorScheme: hifi.colorSchemes.dark;
|
||||
color: hifi.buttons.blue;
|
||||
anchors.top: takeSnapshotFromControllerCheckBox.visible ? takeSnapshotFromControllerCheckBox.bottom : fieldOfView.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.right: parent.right;
|
||||
width: parent.width/2 - 10;
|
||||
height: 40;
|
||||
onClicked: {
|
||||
take360SnapshotButton.enabled = false;
|
||||
take360SnapshotButton.text = "360 SNAPSHOT PROCESSING...";
|
||||
take360SnapshotButton.text = "PROCESSING...";
|
||||
sendToScript({method: 'takeSecondaryCamera360Snapshot'});
|
||||
}
|
||||
}
|
||||
|
@ -409,7 +526,7 @@ Rectangle {
|
|||
break;
|
||||
case 'enable360SnapshotButton':
|
||||
take360SnapshotButton.text = "Take 360 Snapshot";
|
||||
take360SnapshotButton.enabled = cameraToggleButton.camIsOn;
|
||||
take360SnapshotButton.enabled = true;
|
||||
break;
|
||||
default:
|
||||
console.log('Unrecognized message from spectatorCamera.js:', JSON.stringify(message));
|
||||
|
|
BIN
unpublishedScripts/marketplace/spectator-camera/processing.gif
Normal file
BIN
unpublishedScripts/marketplace/spectator-camera/processing.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
|
@ -193,6 +193,7 @@
|
|||
tablet.screenChanged.connect(onTabletScreenChanged);
|
||||
Window.domainChanged.connect(onDomainChanged);
|
||||
Window.geometryChanged.connect(resizeViewFinderOverlay);
|
||||
Window.stillSnapshotTaken.connect(onStillSnapshotTaken);
|
||||
Window.equirectangularSnapshotTaken.connect(onEquirectangularSnapshotTaken);
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
HMD.displayModeChanged.connect(onHMDChanged);
|
||||
|
@ -394,14 +395,21 @@
|
|||
}
|
||||
var takeSnapshotControllerMapping;
|
||||
var takeSnapshotControllerMappingName = 'Hifi-SpectatorCamera-Mapping-TakeSnapshot';
|
||||
function onStillSnapshotTaken() {
|
||||
Render.getConfig("SecondaryCameraJob.ToneMapping").curve = 1;
|
||||
}
|
||||
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();
|
||||
Render.getConfig("SecondaryCameraJob.ToneMapping").curve = 0;
|
||||
// Wait a moment before taking the snapshot for the tonemapping curve to update
|
||||
Script.setTimeout(function () {
|
||||
Audio.playSound(SNAPSHOT_SOUND, {
|
||||
position: { x: MyAvatar.position.x, y: MyAvatar.position.y, z: MyAvatar.position.z },
|
||||
localOnly: true,
|
||||
volume: 1.0
|
||||
});
|
||||
Window.takeSecondaryCameraSnapshot();
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
function onEquirectangularSnapshotTaken() {
|
||||
|
@ -559,6 +567,12 @@
|
|||
case 'changeTakeSnapshotFromControllerPreference':
|
||||
setTakeSnapshotFromController(message.params);
|
||||
break;
|
||||
case 'updateCameravFoV':
|
||||
spectatorCameraConfig.vFoV = message.vFoV;
|
||||
break;
|
||||
case 'takeSecondaryCameraSnapshot':
|
||||
maybeTakeSnapshot();
|
||||
break;
|
||||
case 'takeSecondaryCamera360Snapshot':
|
||||
maybeTake360Snapshot();
|
||||
break;
|
||||
|
@ -589,6 +603,7 @@
|
|||
spectatorCameraOff();
|
||||
Window.domainChanged.disconnect(onDomainChanged);
|
||||
Window.geometryChanged.disconnect(resizeViewFinderOverlay);
|
||||
Window.stillSnapshotTaken.disconnect(onStillSnapshotTaken);
|
||||
Window.equirectangularSnapshotTaken.disconnect(onEquirectangularSnapshotTaken);
|
||||
addOrRemoveButton(true);
|
||||
if (tablet) {
|
||||
|
|
Loading…
Reference in a new issue