Merge branch 'master' of github.com:highfidelity/hifi into fix-avatar-entities-delete

This commit is contained in:
Seth Alves 2016-10-17 17:42:17 -07:00
commit 5d085798cb
26 changed files with 426 additions and 138 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 246 KiB

View file

@ -87,6 +87,8 @@ ModalWindow {
if (selectDirectory) {
currentSelection.text = d.capitalizeDrive(helper.urlToPath(initialFolder));
d.currentSelectionIsFolder = true;
d.currentSelectionUrl = initialFolder;
}
helper.contentsChanged.connect(function() {

View file

@ -94,6 +94,7 @@
#include <RenderShadowTask.h>
#include <RenderDeferredTask.h>
#include <ResourceCache.h>
#include <SandboxUtils.h>
#include <SceneScriptingInterface.h>
#include <ScriptEngines.h>
#include <ScriptCache.h>
@ -415,8 +416,6 @@ bool setupEssentials(int& argc, char** argv) {
static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";
bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
bool previousSessionCrashed = CrashHandler::checkForResetSettings(suppressPrompt);
CrashHandler::writeRunningMarkerFiler();
qAddPostRoutine(CrashHandler::deleteRunningMarkerFile);
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>();
@ -504,8 +503,11 @@ Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context);
Setting::Handle<int> sessionRunTime{ "sessionRunTime", 0 };
Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runServer, QString runServerPathOption) :
QApplication(argc, argv),
_shouldRunServer(runServer),
_runServerPath(runServerPathOption),
_runningMarker(this, RUNNING_MARKER_FILENAME),
_window(new MainWindow(desktop())),
_sessionRunTimer(startupTimer),
_previousSessionCrashed(setupEssentials(argc, argv)),
@ -529,7 +531,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
_maxOctreePPS(maxOctreePacketsPerSecond.get()),
_lastFaceTrackerUpdate(0)
{
_runningMarker.startRunningMarker();
PluginContainer* pluginContainer = dynamic_cast<PluginContainer*>(this); // set the container for any plugins that care
PluginManager::getInstance()->setContainer(pluginContainer);
@ -575,6 +577,28 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
qCDebug(interfaceapp) << "[VERSION] We will use DEVELOPMENT global services.";
#endif
bool wantsSandboxRunning = shouldRunServer();
static bool determinedSandboxState = false;
SandboxUtils sandboxUtils;
sandboxUtils.ifLocalSandboxRunningElse([&]() {
qCDebug(interfaceapp) << "Home sandbox appears to be running.....";
determinedSandboxState = true;
}, [&, wantsSandboxRunning]() {
qCDebug(interfaceapp) << "Home sandbox does not appear to be running....";
determinedSandboxState = true;
if (wantsSandboxRunning) {
QString contentPath = getRunServerPath();
SandboxUtils::runLocalSandbox(contentPath, true, RUNNING_MARKER_FILENAME);
}
});
quint64 MAX_WAIT_TIME = USECS_PER_SECOND * 4;
auto startWaiting = usecTimestampNow();
while (!determinedSandboxState && (usecTimestampNow() - startWaiting <= MAX_WAIT_TIME)) {
QCoreApplication::processEvents();
usleep(USECS_PER_MSEC * 50); // 20hz
}
_bookmarks = new Bookmarks(); // Before setting up the menu
@ -1265,7 +1289,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
// Get sandbox content set version, if available
auto acDirPath = PathUtils::getRootDataDirectory() + BuildInfo::MODIFIED_ORGANIZATION + "/assignment-client/";
auto contentVersionPath = acDirPath + "content-version.txt";
qDebug() << "Checking " << contentVersionPath << " for content version";
qCDebug(interfaceapp) << "Checking " << contentVersionPath << " for content version";
auto contentVersion = 0;
QFile contentVersionFile(contentVersionPath);
if (contentVersionFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
@ -1273,7 +1297,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
// toInt() returns 0 if the conversion fails, so we don't need to specifically check for failure
contentVersion = line.toInt();
}
qDebug() << "Server content version: " << contentVersion;
qCDebug(interfaceapp) << "Server content version: " << contentVersion;
bool hasTutorialContent = contentVersion >= 1;
@ -1283,10 +1307,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
bool shouldGoToTutorial = hasHMDAndHandControllers && hasTutorialContent && !tutorialComplete.get();
qDebug() << "Has HMD + Hand Controllers: " << hasHMDAndHandControllers << ", current plugin: " << _displayPlugin->getName();
qDebug() << "Has tutorial content: " << hasTutorialContent;
qDebug() << "Tutorial complete: " << tutorialComplete.get();
qDebug() << "Should go to tutorial: " << shouldGoToTutorial;
qCDebug(interfaceapp) << "Has HMD + Hand Controllers: " << hasHMDAndHandControllers << ", current plugin: " << _displayPlugin->getName();
qCDebug(interfaceapp) << "Has tutorial content: " << hasTutorialContent;
qCDebug(interfaceapp) << "Tutorial complete: " << tutorialComplete.get();
qCDebug(interfaceapp) << "Should go to tutorial: " << shouldGoToTutorial;
// when --url in command line, teleport to location
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
@ -1299,11 +1323,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
const QString TUTORIAL_PATH = "/tutorial_begin";
if (shouldGoToTutorial) {
DependencyManager::get<AddressManager>()->ifLocalSandboxRunningElse([=]() {
qDebug() << "Home sandbox appears to be running, going to Home.";
sandboxUtils.ifLocalSandboxRunningElse([=]() {
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
}, [=]() {
qDebug() << "Home sandbox does not appear to be running, going to Entry.";
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
if (firstRun.get()) {
showHelp();
}
@ -1324,18 +1348,18 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
// If this is a first run we short-circuit the address passed in
if (isFirstRun) {
if (hasHMDAndHandControllers) {
DependencyManager::get<AddressManager>()->ifLocalSandboxRunningElse([=]() {
qDebug() << "Home sandbox appears to be running, going to Home.";
sandboxUtils.ifLocalSandboxRunningElse([=]() {
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
DependencyManager::get<AddressManager>()->goToLocalSandbox();
}, [=]() {
qDebug() << "Home sandbox does not appear to be running, going to Entry.";
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
DependencyManager::get<AddressManager>()->goToEntry();
});
} else {
DependencyManager::get<AddressManager>()->goToEntry();
}
} else {
qDebug() << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
}
}

View file

@ -46,6 +46,8 @@
#include <ThreadSafeValueCache.h>
#include <shared/FileLogger.h>
#include <RunningMarker.h>
#include "avatar/MyAvatar.h"
#include "Bookmarks.h"
#include "Camera.h"
@ -87,6 +89,8 @@ static const UINT UWM_SHOW_APPLICATION =
RegisterWindowMessage("UWM_SHOW_APPLICATION_{71123FD6-3DA8-4DC1-9C27-8A12A6250CBA}_" + qgetenv("USERNAME"));
#endif
static const QString RUNNING_MARKER_FILENAME = "Interface.running";
class Application;
#if defined(qApp)
#undef qApp
@ -103,7 +107,16 @@ class Application : public QApplication,
// TODO? Get rid of those
friend class OctreePacketProcessor;
private:
bool _shouldRunServer { false };
QString _runServerPath;
RunningMarker _runningMarker;
public:
// startup related getter/setters
bool shouldRunServer() const { return _shouldRunServer; }
bool hasRunServerPath() const { return !_runServerPath.isEmpty(); }
QString getRunServerPath() const { return _runServerPath; }
// virtual functions required for PluginContainer
virtual ui::Menu* getPrimaryMenu() override;
@ -127,7 +140,7 @@ public:
static void initPlugins(const QStringList& arguments);
static void shutdownPlugins();
Application(int& argc, char** argv, QElapsedTimer& startup_time);
Application(int& argc, char** argv, QElapsedTimer& startup_time, bool runServer, QString runServerPathOption);
~Application();
void postLambdaEvent(std::function<void()> f) override;

View file

@ -34,7 +34,7 @@ void ConnectionMonitor::init() {
}
auto dialogsManager = DependencyManager::get<DialogsManager>();
connect(&_timer, &QTimer::timeout, dialogsManager.data(), &DialogsManager::showAddressBar);
connect(&_timer, &QTimer::timeout, dialogsManager.data(), &DialogsManager::indicateDomainConnectionFailure);
}
void ConnectionMonitor::disconnectedFromDomain() {

View file

@ -23,9 +23,10 @@
#include <QVBoxLayout>
#include <QtCore/QUrl>
#include "Application.h"
#include "Menu.h"
static const QString RUNNING_MARKER_FILENAME = "Interface.running";
#include <RunningMarker.h>
bool CrashHandler::checkForResetSettings(bool suppressPrompt) {
QSettings::setDefaultFormat(QSettings::IniFormat);
@ -39,7 +40,7 @@ bool CrashHandler::checkForResetSettings(bool suppressPrompt) {
// If option does not exist in Interface.ini so assume default behavior.
bool displaySettingsResetOnCrash = !displayCrashOptions.isValid() || displayCrashOptions.toBool();
QFile runningMarkerFile(runningMarkerFilePath());
QFile runningMarkerFile(RunningMarker::getMarkerFilePath(RUNNING_MARKER_FILENAME));
bool wasLikelyCrash = runningMarkerFile.exists();
if (suppressPrompt) {
@ -161,20 +162,3 @@ void CrashHandler::handleCrash(CrashHandler::Action action) {
}
}
void CrashHandler::writeRunningMarkerFiler() {
QFile runningMarkerFile(runningMarkerFilePath());
if (!runningMarkerFile.exists()) {
runningMarkerFile.open(QIODevice::WriteOnly);
runningMarkerFile.close();
}
}
void CrashHandler::deleteRunningMarkerFile() {
QFile runningMarkerFile(runningMarkerFilePath());
if (runningMarkerFile.exists()) {
runningMarkerFile.remove();
}
}
const QString CrashHandler::runningMarkerFilePath() {
return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + RUNNING_MARKER_FILENAME;
}

View file

@ -19,9 +19,6 @@ class CrashHandler {
public:
static bool checkForResetSettings(bool suppressPrompt = false);
static void writeRunningMarkerFiler();
static void deleteRunningMarkerFile();
private:
enum Action {
DELETE_INTERFACE_INI,
@ -31,8 +28,6 @@ private:
static Action promptUserForAction(bool showCrashMessage);
static void handleCrash(Action action);
static const QString runningMarkerFilePath();
};
#endif // hifi_CrashHandler_h

View file

@ -37,6 +37,8 @@
#include <CrashReporter.h>
#endif
int main(int argc, const char* argv[]) {
#if HAS_BUGSPLAT
static QString BUG_SPLAT_DATABASE = "interface_alpha";
@ -128,22 +130,9 @@ int main(int argc, const char* argv[]) {
parser.addOption(runServerOption);
parser.addOption(serverContentPathOption);
parser.parse(arguments);
if (parser.isSet(runServerOption)) {
QString applicationDirPath = QFileInfo(arguments[0]).path();
QString serverPath = applicationDirPath + "/server-console/server-console.exe";
qDebug() << "Application dir path is: " << applicationDirPath;
qDebug() << "Server path is: " << serverPath;
QStringList args;
if (parser.isSet(serverContentPathOption)) {
QString serverContentPath = QFileInfo(arguments[0]).path() + "/" + parser.value(serverContentPathOption);
args << "--" << "--contentPath" << serverContentPath;
}
qDebug() << QFileInfo(arguments[0]).path();
qDebug() << QProcess::startDetached(serverPath, args);
// Sleep a short amount of time to give the server a chance to start
usleep(2000000);
}
bool runServer = parser.isSet(runServerOption);
bool serverContentPathOptionIsSet = parser.isSet(serverContentPathOption);
QString serverContentPathOptionValue = serverContentPathOptionIsSet ? parser.value(serverContentPathOption) : QString();
QElapsedTimer startupTime;
startupTime.start();
@ -166,10 +155,11 @@ int main(int argc, const char* argv[]) {
SteamClient::init();
int exitCode;
{
QSettings::setDefaultFormat(QSettings::IniFormat);
Application app(argc, const_cast<char**>(argv), startupTime);
Application app(argc, const_cast<char**>(argv), startupTime, runServer, serverContentPathOptionValue);
// If we failed the OpenGLVersion check, log it.
if (override) {
@ -223,7 +213,6 @@ int main(int argc, const char* argv[]) {
QTranslator translator;
translator.load("i18n/interface_en");
app.installTranslator(&translator);
qCDebug(interfaceapp, "Created QT Application.");
exitCode = app.exec();
server.close();

View file

@ -59,6 +59,10 @@ void DialogsManager::showFeed() {
emit setUseFeed(true);
}
void DialogsManager::indicateDomainConnectionFailure() {
OffscreenUi::information("No Connection", "Unable to connect to this domain. Click the 'GO TO' button on the toolbar to visit another domain.");
}
void DialogsManager::toggleDiskCacheEditor() {
maybeCreateDialog(_diskCacheEditor);
_diskCacheEditor->toggle();

View file

@ -46,6 +46,7 @@ public slots:
void toggleAddressBar();
void showAddressBar();
void showFeed();
void indicateDomainConnectionFailure();
void toggleDiskCacheEditor();
void toggleLoginDialog();
void showLoginDialog();

View file

@ -43,9 +43,7 @@ const QString SNAPSHOTS_DIRECTORY = "Snapshots";
const QString URL = "highfidelity_url";
Setting::Handle<QString> Snapshot::snapshotsLocation("snapshotsLocation",
QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
Setting::Handle<bool> Snapshot::hasSetSnapshotsLocation("hasSetSnapshotsLocation", false);
Setting::Handle<QString> Snapshot::snapshotsLocation("snapshotsLocation");
SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) {
@ -105,42 +103,44 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) {
const int IMAGE_QUALITY = 100;
if (!isTemporary) {
QString snapshotFullPath;
if (!hasSetSnapshotsLocation.get()) {
snapshotFullPath = QFileDialog::getExistingDirectory(nullptr, "Choose Snapshots Directory", snapshotsLocation.get());
hasSetSnapshotsLocation.set(true);
QString snapshotFullPath = snapshotsLocation.get();
if (snapshotFullPath.isEmpty()) {
snapshotFullPath = OffscreenUi::getExistingDirectory(nullptr, "Choose Snapshots Directory", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
snapshotsLocation.set(snapshotFullPath);
} else {
snapshotFullPath = snapshotsLocation.get();
}
if (!snapshotFullPath.endsWith(QDir::separator())) {
snapshotFullPath.append(QDir::separator());
if (!snapshotFullPath.isEmpty()) { // not cancelled
if (!snapshotFullPath.endsWith(QDir::separator())) {
snapshotFullPath.append(QDir::separator());
}
snapshotFullPath.append(filename);
QFile* imageFile = new QFile(snapshotFullPath);
imageFile->open(QIODevice::WriteOnly);
shot.save(imageFile, 0, IMAGE_QUALITY);
imageFile->close();
return imageFile;
}
snapshotFullPath.append(filename);
QFile* imageFile = new QFile(snapshotFullPath);
imageFile->open(QIODevice::WriteOnly);
shot.save(imageFile, 0, IMAGE_QUALITY);
imageFile->close();
return imageFile;
} else {
QTemporaryFile* imageTempFile = new QTemporaryFile(QDir::tempPath() + "/XXXXXX-" + filename);
if (!imageTempFile->open()) {
qDebug() << "Unable to open QTemporaryFile for temp snapshot. Will not save.";
return NULL;
}
shot.save(imageTempFile, 0, IMAGE_QUALITY);
imageTempFile->close();
return imageTempFile;
}
// Either we were asked for a tempororary, or the user didn't set a directory.
QTemporaryFile* imageTempFile = new QTemporaryFile(QDir::tempPath() + "/XXXXXX-" + filename);
if (!imageTempFile->open()) {
qDebug() << "Unable to open QTemporaryFile for temp snapshot. Will not save.";
return NULL;
}
imageTempFile->setAutoRemove(isTemporary);
shot.save(imageTempFile, 0, IMAGE_QUALITY);
imageTempFile->close();
return imageTempFile;
}
void Snapshot::uploadSnapshot(const QString& filename) {

View file

@ -39,7 +39,6 @@ public:
static SnapshotMetaData* parseSnapshotData(QString snapshotPath);
static Setting::Handle<QString> snapshotsLocation;
static Setting::Handle<bool> hasSetSnapshotsLocation;
static void uploadSnapshot(const QString& filename);
private:
static QFile* savedFileForSnapshot(QImage & image, bool isTemporary);

View file

@ -831,32 +831,3 @@ void AddressManager::addCurrentAddressToHistory(LookupTrigger trigger) {
}
}
void AddressManager::ifLocalSandboxRunningElse(std::function<void()> localSandboxRunningDoThis,
std::function<void()> localSandboxNotRunningDoThat) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest sandboxStatus(SANDBOX_STATUS_URL);
sandboxStatus.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
sandboxStatus.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(sandboxStatus);
connect(reply, &QNetworkReply::finished, this, [reply, localSandboxRunningDoThis, localSandboxNotRunningDoThat]() {
auto statusData = reply->readAll();
auto statusJson = QJsonDocument::fromJson(statusData);
if (!statusJson.isEmpty()) {
auto statusObject = statusJson.object();
auto serversValue = statusObject.value("servers");
if (!serversValue.isUndefined() && serversValue.isObject()) {
auto serversObject = serversValue.toObject();
auto serversCount = serversObject.size();
const int MINIMUM_EXPECTED_SERVER_COUNT = 5;
if (serversCount >= MINIMUM_EXPECTED_SERVER_COUNT) {
localSandboxRunningDoThis();
return;
}
}
}
localSandboxNotRunningDoThat();
});
}

View file

@ -25,7 +25,6 @@
const QString HIFI_URL_SCHEME = "hifi";
const QString DEFAULT_HIFI_ADDRESS = "hifi://welcome";
const QString SANDBOX_HIFI_ADDRESS = "hifi://localhost";
const QString SANDBOX_STATUS_URL = "http://localhost:60332/status";
const QString INDEX_PATH = "/";
const QString GET_PLACE = "/api/v1/places/%1";
@ -78,11 +77,6 @@ public:
const QStack<QUrl>& getBackStack() const { return _backStack; }
const QStack<QUrl>& getForwardStack() const { return _forwardStack; }
/// determines if the local sandbox is likely running. It does not account for custom setups, and is only
/// intended to detect the standard local sandbox install.
void ifLocalSandboxRunningElse(std::function<void()> localSandboxRunningDoThis,
std::function<void()> localSandboxNotRunningDoThat);
public slots:
void handleLookupString(const QString& lookupString, bool fromSuggestions = false);

View file

@ -0,0 +1,96 @@
//
// SandboxUtils.cpp
// libraries/networking/src
//
// Created by Brad Hefta-Gaub on 2016-10-15.
// 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
//
#include <QDataStream>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkReply>
#include <QProcess>
#include <QStandardPaths>
#include <QThread>
#include <QTimer>
#include <NumericalConstants.h>
#include <SharedUtil.h>
#include <RunningMarker.h>
#include "SandboxUtils.h"
#include "NetworkAccessManager.h"
void SandboxUtils::ifLocalSandboxRunningElse(std::function<void()> localSandboxRunningDoThis,
std::function<void()> localSandboxNotRunningDoThat) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest sandboxStatus(SANDBOX_STATUS_URL);
sandboxStatus.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
sandboxStatus.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(sandboxStatus);
connect(reply, &QNetworkReply::finished, this, [reply, localSandboxRunningDoThis, localSandboxNotRunningDoThat]() {
if (reply->error() == QNetworkReply::NoError) {
auto statusData = reply->readAll();
auto statusJson = QJsonDocument::fromJson(statusData);
if (!statusJson.isEmpty()) {
auto statusObject = statusJson.object();
auto serversValue = statusObject.value("servers");
if (!serversValue.isUndefined() && serversValue.isObject()) {
auto serversObject = serversValue.toObject();
auto serversCount = serversObject.size();
const int MINIMUM_EXPECTED_SERVER_COUNT = 5;
if (serversCount >= MINIMUM_EXPECTED_SERVER_COUNT) {
localSandboxRunningDoThis();
return;
}
}
}
}
localSandboxNotRunningDoThat();
});
}
void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName) {
QString applicationDirPath = QFileInfo(QCoreApplication::applicationFilePath()).path();
QString serverPath = applicationDirPath + "/server-console/server-console.exe";
qDebug() << "Application dir path is: " << applicationDirPath;
qDebug() << "Server path is: " << serverPath;
qDebug() << "autoShutdown: " << autoShutdown;
bool hasContentPath = !contentPath.isEmpty();
bool passArgs = autoShutdown || hasContentPath;
QStringList args;
if (passArgs) {
args << "--";
}
if (hasContentPath) {
QString serverContentPath = applicationDirPath + "/" + contentPath;
args << "--contentPath" << serverContentPath;
}
if (autoShutdown) {
QString interfaceRunningStateFile = RunningMarker::getMarkerFilePath(runningMarkerName);
args << "--shutdownWatcher" << interfaceRunningStateFile;
}
qDebug() << applicationDirPath;
qDebug() << "Launching sandbox with:" << args;
qDebug() << QProcess::startDetached(serverPath, args);
// Sleep a short amount of time to give the server a chance to start
usleep(2000000); /// do we really need this??
}

View file

@ -0,0 +1,32 @@
//
// SandboxUtils.h
// libraries/networking/src
//
// Created by Brad Hefta-Gaub on 2016-10-15.
// 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
//
#ifndef hifi_SandboxUtils_h
#define hifi_SandboxUtils_h
#include <functional>
#include <QtCore/QObject>
const QString SANDBOX_STATUS_URL = "http://localhost:60332/status";
class SandboxUtils : public QObject {
Q_OBJECT
public:
/// determines if the local sandbox is likely running. It does not account for custom setups, and is only
/// intended to detect the standard local sandbox install.
void ifLocalSandboxRunningElse(std::function<void()> localSandboxRunningDoThis,
std::function<void()> localSandboxNotRunningDoThat);
static void runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName);
};
#endif // hifi_SandboxUtils_h

View file

@ -0,0 +1,76 @@
//
// RunningMarker.cpp
// libraries/shared/src
//
// Created by Brad Hefta-Gaub on 2016-10-16
// 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
//
#include "RunningMarker.h"
#include <QFile>
#include <QStandardPaths>
#include <QThread>
#include <QTimer>
#include "NumericalConstants.h"
#include "PathUtils.h"
RunningMarker::RunningMarker(QObject* parent, QString name) :
_parent(parent),
_name(name)
{
}
void RunningMarker::startRunningMarker() {
static const int RUNNING_STATE_CHECK_IN_MSECS = MSECS_PER_SECOND;
// start the nodeThread so its event loop is running
QThread* runningMarkerThread = new QThread(_parent);
runningMarkerThread->setObjectName("Running Marker Thread");
runningMarkerThread->start();
writeRunningMarkerFiler(); // write the first file, even before timer
QTimer* runningMarkerTimer = new QTimer(_parent);
QObject::connect(runningMarkerTimer, &QTimer::timeout, [=](){
writeRunningMarkerFiler();
});
runningMarkerTimer->start(RUNNING_STATE_CHECK_IN_MSECS);
// put the time on the thread
runningMarkerTimer->moveToThread(runningMarkerThread);
}
RunningMarker::~RunningMarker() {
deleteRunningMarkerFile();
}
void RunningMarker::writeRunningMarkerFiler() {
QFile runningMarkerFile(getFilePath());
// always write, even it it exists, so that it touches the files
if (runningMarkerFile.open(QIODevice::WriteOnly)) {
runningMarkerFile.close();
}
}
void RunningMarker::deleteRunningMarkerFile() {
QFile runningMarkerFile(getFilePath());
if (runningMarkerFile.exists()) {
runningMarkerFile.remove();
}
}
QString RunningMarker::getFilePath() {
return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + _name;
}
QString RunningMarker::getMarkerFilePath(QString name) {
return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + name;
}

View file

@ -0,0 +1,35 @@
//
// RunningMarker.h
// interface/src
//
// Created by Brad Hefta-Gaub on 2016-10-15.
// 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
//
#ifndef hifi_RunningMarker_h
#define hifi_RunningMarker_h
#include <QObject>
#include <QString>
class RunningMarker {
public:
RunningMarker(QObject* parent, QString name);
~RunningMarker();
void startRunningMarker();
QString getFilePath();
static QString getMarkerFilePath(QString name);
protected:
void writeRunningMarkerFiler();
void deleteRunningMarkerFile();
QObject* _parent { nullptr };
QString _name;
};
#endif // hifi_RunningMarker_h

View file

@ -616,6 +616,28 @@ QString OffscreenUi::fileSaveDialog(const QString& caption, const QString& dir,
return fileDialog(map);
}
QString OffscreenUi::existingDirectoryDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) {
if (QThread::currentThread() != thread()) {
QString result;
QMetaObject::invokeMethod(this, "existingDirectoryDialog", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QString, result),
Q_ARG(QString, caption),
Q_ARG(QString, dir),
Q_ARG(QString, filter),
Q_ARG(QString*, selectedFilter),
Q_ARG(QFileDialog::Options, options));
return result;
}
QVariantMap map;
map.insert("caption", caption);
map.insert("dir", QUrl::fromLocalFile(dir));
map.insert("filter", filter);
map.insert("options", static_cast<int>(options));
map.insert("selectDirectory", true);
return fileDialog(map);
}
QString OffscreenUi::getOpenFileName(void* ignored, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
return DependencyManager::get<OffscreenUi>()->fileOpenDialog(caption, dir, filter, selectedFilter, options);
}
@ -624,6 +646,10 @@ QString OffscreenUi::getSaveFileName(void* ignored, const QString &caption, cons
return DependencyManager::get<OffscreenUi>()->fileSaveDialog(caption, dir, filter, selectedFilter, options);
}
QString OffscreenUi::getExistingDirectory(void* ignored, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
return DependencyManager::get<OffscreenUi>()->existingDirectoryDialog(caption, dir, filter, selectedFilter, options);
}
bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) {
if (!filterEnabled(originalDestination, event)) {
return false;

View file

@ -115,11 +115,14 @@ public:
Q_INVOKABLE QString fileOpenDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
Q_INVOKABLE QString fileSaveDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
Q_INVOKABLE QString existingDirectoryDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
// Compatibility with QFileDialog::getOpenFileName
static QString getOpenFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
// Compatibility with QFileDialog::getSaveFileName
static QString getSaveFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
// Compatibility with QFileDialog::getExistingDirectory
static QString getExistingDirectory(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
Q_INVOKABLE QVariant inputDialog(const Icon icon, const QString& title, const QString& label = QString(), const QVariant& current = QVariant());
Q_INVOKABLE QVariant customInputDialog(const Icon icon, const QString& title, const QVariantMap& config);

View file

@ -59,13 +59,15 @@ void OculusDisplayPlugin::customizeContext() {
ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &_textureSwapChain);
if (!OVR_SUCCESS(result)) {
logFatal("Failed to create swap textures");
logCritical("Failed to create swap textures");
return;
}
int length = 0;
result = ovr_GetTextureSwapChainLength(_session, _textureSwapChain, &length);
if (!OVR_SUCCESS(result) || !length) {
qFatal("Unable to count swap chain textures");
logCritical("Unable to count swap chain textures");
return;
}
for (int i = 0; i < length; ++i) {
GLuint chainTexId;
@ -83,6 +85,7 @@ void OculusDisplayPlugin::customizeContext() {
_sceneLayer.ColorTexture[0] = _textureSwapChain;
// not needed since the structure was zeroed on init, but explicit
_sceneLayer.ColorTexture[1] = nullptr;
_customized = true;
}
void OculusDisplayPlugin::uncustomizeContext() {
@ -98,10 +101,14 @@ void OculusDisplayPlugin::uncustomizeContext() {
ovr_DestroyTextureSwapChain(_session, _textureSwapChain);
_textureSwapChain = nullptr;
_outputFramebuffer.reset();
_customized = false;
Parent::uncustomizeContext();
}
void OculusDisplayPlugin::hmdPresent() {
if (!_customized) {
return;
}
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex)

View file

@ -32,5 +32,6 @@ private:
static const QString NAME;
ovrTextureSwapChain _textureSwapChain;
gpu::FramebufferPointer _outputFramebuffer;
bool _customized { false };
};

View file

@ -39,12 +39,12 @@ void logWarning(const char* what) {
qWarning(oculus) << what << ":" << getError().ErrorString;
}
void logFatal(const char* what) {
void logCritical(const char* what) {
std::string error("[oculus] ");
error += what;
error += ": ";
error += getError().ErrorString;
qFatal(error.c_str());
qCritical(error.c_str());
}

View file

@ -15,7 +15,7 @@
#include <controllers/Forward.h>
void logWarning(const char* what);
void logFatal(const char* what);
void logCritical(const char* what);
bool oculusAvailable();
ovrSession acquireOculusSession();
void releaseOculusSession();

View file

@ -2770,10 +2770,10 @@ var handleHandMessages = function(channel, message, sender) {
Messages.messageReceived.connect(handleHandMessages);
var BASIC_TIMER_INTERVAL = 20; // 20ms = 50hz good enough
var BASIC_TIMER_INTERVAL_MS = 20; // 20ms = 50hz good enough
var updateIntervalTimer = Script.setInterval(function(){
update();
}, BASIC_TIMER_INTERVAL);
update(BASIC_TIMER_INTERVAL_MS / 1000);
}, BASIC_TIMER_INTERVAL_MS);
function cleanup() {
Script.clearInterval(updateIntervalTimer);

View file

@ -128,6 +128,12 @@ function shutdown() {
}
}
function forcedShutdown() {
if (!isShuttingDown) {
shutdownCallback(0);
}
}
function shutdownCallback(idx) {
if (idx == 0 && !isShuttingDown) {
isShuttingDown = true;
@ -226,6 +232,7 @@ if (shouldQuit) {
// Check command line arguments to see how to find binaries
var argv = require('yargs').argv;
var pathFinder = require('./modules/path-finder.js');
var interfacePath = null;
@ -774,6 +781,7 @@ function maybeShowSplash() {
}
}
const trayIconOS = (osType == "Darwin") ? "osx" : "win";
var trayIcons = {};
trayIcons[ProcessGroupStates.STARTED] = "console-tray-" + trayIconOS + ".png";
@ -842,6 +850,34 @@ function onContentLoaded() {
// start the home server
homeServer.start();
}
// If we were launched with the shutdownWatcher option, then we need to watch for the interface app
// shutting down. The interface app will regularly update a running state file which we will check.
// If the file doesn't exist or stops updating for a significant amount of time, we will shut down.
if (argv.shutdownWatcher) {
console.log("Shutdown watcher requested... argv.shutdownWatcher:", argv.shutdownWatcher);
var MAX_TIME_SINCE_EDIT = 5000; // 5 seconds between updates
var firstAttemptToCheck = new Date().getTime();
var shutdownWatchInterval = setInterval(function(){
var stats = fs.stat(argv.shutdownWatcher, function(err, stats) {
if (err) {
var sinceFirstCheck = new Date().getTime() - firstAttemptToCheck;
if (sinceFirstCheck > MAX_TIME_SINCE_EDIT) {
console.log("Running state file is missing, assume interface has shutdown... shutting down snadbox.");
forcedShutdown();
clearTimeout(shutdownWatchInterval);
}
} else {
var sinceEdit = new Date().getTime() - stats.mtime.getTime();
if (sinceEdit > MAX_TIME_SINCE_EDIT) {
console.log("Running state of interface hasn't updated in MAX time... shutting down.");
forcedShutdown();
clearTimeout(shutdownWatchInterval);
}
}
});
}, 1000);
}
}