Merge branch 'master' of github.com:highfidelity/hifi into fix-aa-cube-bug

This commit is contained in:
Seth Alves 2016-01-21 16:15:06 -08:00
commit c2edb0a559
158 changed files with 7177 additions and 3378 deletions

1
.gitattributes vendored
View file

@ -25,3 +25,4 @@
*.svg binary
*.ttf binary
*.wav binary
*.rsrc binary

4
.gitignore vendored
View file

@ -46,3 +46,7 @@ gvr-interface/libs/*
# ignore files for various dev environments
TAGS
*.swp
# ignore node files for the console
node_modules
npm-debug.log

View file

@ -30,20 +30,28 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
if (WIN32)
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
# set path for Microsoft SDKs
# if get build error about missing 'glu32' this path is likely wrong
# Uncomment the line with 8.1 if running Windows 8.1
if (NOT WINDOW_SDK_PATH)
set(DEBUG_DISCOVERED_SDK_PATH TRUE)
endif()
# sets path for Microsoft SDKs
# if you get build error about missing 'glu32' this path is likely wrong
if (MSVC10)
set(WINDOW_SDK_PATH "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1 ")
set(WINDOW_SDK_PATH "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1 " CACHE PATH "Windows SDK PATH")
elseif (MSVC12)
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(WINDOW_SDK_FOLDER "x64")
else()
set(WINDOW_SDK_FOLDER "x86")
endif()
set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\${WINDOW_SDK_FOLDER}")
set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\${WINDOW_SDK_FOLDER}" CACHE PATH "Windows SDK PATH")
endif ()
message (WINDOW_SDK_PATH= ${WINDOW_SDK_PATH})
if (DEBUG_DISCOVERED_SDK_PATH)
message(STATUS "The discovered Windows SDK path is ${WINDOW_SDK_PATH}")
endif ()
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${WINDOW_SDK_PATH})
# /wd4351 disables warning C4351: new behavior: elements of array will be default initialized
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /wd4351")
@ -107,6 +115,8 @@ else ()
endif ()
endif ()
set(QT_DIR $ENV{QT_DIR})
if (WIN32)
if (NOT EXISTS ${QT_CMAKE_PREFIX_PATH})
message(FATAL_ERROR "Could not determine QT_CMAKE_PREFIX_PATH.")
@ -170,9 +180,9 @@ else ()
set(UPPER_CMAKE_BUILD_TYPE DEBUG)
endif ()
set(HIFI_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(MACRO_DIR "${HIFI_CMAKE_DIR}/macros")
set(EXTERNAL_PROJECT_DIR "${HIFI_CMAKE_DIR}/externals")
set(HF_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(MACRO_DIR "${HF_CMAKE_DIR}/macros")
set(EXTERNAL_PROJECT_DIR "${HF_CMAKE_DIR}/externals")
file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake")
foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS})
@ -201,6 +211,8 @@ if (NOT DEFINED SERVER_ONLY)
set(SERVER_ONLY 0)
endif()
set_packaging_parameters()
# add subdirectories for all targets
if (NOT ANDROID)
add_subdirectory(assignment-client)
@ -209,8 +221,7 @@ if (NOT ANDROID)
set_target_properties(domain-server PROPERTIES FOLDER "Apps")
add_subdirectory(ice-server)
set_target_properties(ice-server PROPERTIES FOLDER "Apps")
add_subdirectory(stack-manager)
set_target_properties(stack-manager PROPERTIES FOLDER "Apps")
add_subdirectory(server-console)
if (NOT SERVER_ONLY)
add_subdirectory(interface)
set_target_properties(interface PROPERTIES FOLDER "Apps")
@ -233,5 +244,4 @@ if (HIFI_MEMORY_DEBUGGING)
endif (UNIX)
endif ()
include_application_version()
generate_installers()

25
INSTALL.md Normal file
View file

@ -0,0 +1,25 @@
Follow the [build guide](BUILD.md) to figure out how to build High Fidelity for your platform.
During generation, CMake should produce an `install` target and a `package` target.
###Install
The `install` target will copy the High Fidelity targets and their dependencies to your `CMAKE_INSTALL_PREFIX`.
###Packaging
To produce an installer, run the `package` target.
####Windows
To produce an executable installer on Windows, the following are required:
- [Nullsoft Scriptable Install System](http://nsis.sourceforge.net/Download) - 3.0b3
- [UAC Plug-in for Nullsoft](http://nsis.sourceforge.net/UAC_plug-in) - 0.2.4c
- [nsProcess Plug-in for Nullsoft](http://nsis.sourceforge.net/NsProcess_plugin) - 1.6
Run the `package` target to create an executable installer using the Nullsoft Scriptable Install System.
####OS X
Run the `package` target to create an Apple Disk Image (.dmg).

19
LICENSE
View file

@ -1,13 +1,12 @@
Copyright 2014 High Fidelity, Inc.
Copyright (c) 2013-2016, High Fidelity, Inc.
All rights reserved.
licensing@highfidelity.io
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Licensed under the Apache License version 2.0 (the "License");
You may not use this software except in compliance with the License.
You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
This software includes third-party software.
Please see each individual software license for additional details.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
This software is distributed "as-is" without any warranties, conditions, or representations whether express or implied, including without limitation the implied warranties and conditions of merchantability, merchantable quality, fitness for a particular purpose, performance, durability, title, non-infringement, and those arising from statute or from custom or usage of trade or course of dealing.

View file

@ -9,6 +9,8 @@ link_hifi_libraries(
controllers physics
)
include_application_version()
package_libraries_for_deployment()
consolidate_stack_components()
if (WIN32)
package_libraries_for_deployment()
endif()
install_beside_console()

View file

@ -12,7 +12,7 @@
#include <QCommandLineParser>
#include <QThread>
#include <ApplicationVersion.h>
#include <BuildInfo.h>
#include <LogHandler.h>
#include <SharedUtil.h>
#include <HifiConfigVariantMap.h>
@ -22,6 +22,8 @@
#include "AssignmentClient.h"
#include "AssignmentClientMonitor.h"
#include "AssignmentClientApp.h"
#include <QtCore/QDir>
#include <QtCore/QStandardPaths>
AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
@ -42,10 +44,10 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
ShutdownEventListener::getInstance();
# endif
setOrganizationName("High Fidelity");
setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION);
setOrganizationDomain("highfidelity.io");
setApplicationName("assignment-client");
setApplicationName(BUILD_VERSION);
setApplicationVersion(BuildInfo::VERSION);
// use the verbose message handler in Logging
qInstallMessageHandler(LogHandler::verboseMessageHandler);
@ -92,6 +94,12 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
const QCommandLineOption monitorPortOption(ASSIGNMENT_CLIENT_MONITOR_PORT_OPTION, "assignment-client monitor port", "port");
parser.addOption(monitorPortOption);
const QCommandLineOption httpStatusPortOption(ASSIGNMENT_HTTP_STATUS_PORT, "http status server port", "http-status-port");
parser.addOption(httpStatusPortOption);
const QCommandLineOption logDirectoryOption(ASSIGNMENT_LOG_DIRECTORY, "directory to store logs", "log-directory");
parser.addOption(logDirectoryOption);
if (!parser.parse(QCoreApplication::arguments())) {
qCritical() << parser.errorText() << endl;
parser.showHelp();
@ -130,6 +138,18 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
numForks = minForks;
}
quint16 httpStatusPort { 0 };
if (parser.isSet(httpStatusPortOption)) {
httpStatusPort = parser.value(httpStatusPortOption).toUShort();
}
QDir logDirectory { "." };
if (parser.isSet(logDirectoryOption)) {
logDirectory = parser.value(logDirectoryOption);
} else {
logDirectory = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
}
Assignment::Type requestAssignmentType = Assignment::AllTypes;
if (argumentVariantMap.contains(ASSIGNMENT_TYPE_OVERRIDE_OPTION)) {
requestAssignmentType = (Assignment::Type) argumentVariantMap.value(ASSIGNMENT_TYPE_OVERRIDE_OPTION).toInt();
@ -200,7 +220,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
AssignmentClientMonitor* monitor = new AssignmentClientMonitor(numForks, minForks, maxForks,
requestAssignmentType, assignmentPool,
listenPort, walletUUID, assignmentServerHostname,
assignmentServerPort);
assignmentServerPort, httpStatusPort, logDirectory);
monitor->setParent(this);
connect(this, &QCoreApplication::aboutToQuit, monitor, &AssignmentClientMonitor::aboutToQuit);
} else {

View file

@ -25,6 +25,8 @@ const QString ASSIGNMENT_NUM_FORKS_OPTION = "n";
const QString ASSIGNMENT_MIN_FORKS_OPTION = "min";
const QString ASSIGNMENT_MAX_FORKS_OPTION = "max";
const QString ASSIGNMENT_CLIENT_MONITOR_PORT_OPTION = "monitor-port";
const QString ASSIGNMENT_HTTP_STATUS_PORT = "http-status-port";
const QString ASSIGNMENT_LOG_DIRECTORY = "log-directory";
class AssignmentClientApp : public QCoreApplication {
Q_OBJECT

View file

@ -12,6 +12,9 @@
#include <memory>
#include <signal.h>
#include <QDir>
#include <QStandardPaths>
#include <AddressManager.h>
#include <LogHandler.h>
#include <udt/PacketHeaders.h>
@ -20,6 +23,7 @@
#include "AssignmentClientApp.h"
#include "AssignmentClientChildData.h"
#include "SharedUtil.h"
#include <QtCore/QJsonDocument>
const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor";
const int WAIT_FOR_CHILD_MSECS = 1000;
@ -29,7 +33,9 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen
const unsigned int maxAssignmentClientForks,
Assignment::Type requestAssignmentType, QString assignmentPool,
quint16 listenPort, QUuid walletUUID, QString assignmentServerHostname,
quint16 assignmentServerPort) :
quint16 assignmentServerPort, quint16 httpStatusServerPort, QDir logDirectory) :
_logDirectory(logDirectory),
_httpManager(QHostAddress::LocalHost, httpStatusServerPort, "", this),
_numAssignmentClientForks(numAssignmentClientForks),
_minAssignmentClientForks(minAssignmentClientForks),
_maxAssignmentClientForks(maxAssignmentClientForks),
@ -38,6 +44,7 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen
_walletUUID(walletUUID),
_assignmentServerHostname(assignmentServerHostname),
_assignmentServerPort(assignmentServerPort)
{
qDebug() << "_requestAssignmentType =" << _requestAssignmentType;
@ -80,24 +87,21 @@ void AssignmentClientMonitor::simultaneousWaitOnChildren(int waitMsecs) {
}
}
void AssignmentClientMonitor::childProcessFinished() {
QProcess* childProcess = qobject_cast<QProcess*>(sender());
qint64 processID = _childProcesses.key(childProcess);
if (processID > 0) {
qDebug() << "Child process" << processID << "has finished. Removing from internal map.";
_childProcesses.remove(processID);
void AssignmentClientMonitor::childProcessFinished(qint64 pid) {
if (_childProcesses.remove(pid)) {
qDebug() << "Child process" << pid << "has finished. Removed from internal map.";
}
}
void AssignmentClientMonitor::stopChildProcesses() {
qDebug() << "Stopping child processes";
auto nodeList = DependencyManager::get<NodeList>();
// ask child processes to terminate
foreach(QProcess* childProcess, _childProcesses) {
if (childProcess->processId() > 0) {
qDebug() << "Attempting to terminate child process" << childProcess->processId();
childProcess->terminate();
for (auto& ac : _childProcesses) {
if (ac.process->processId() > 0) {
qDebug() << "Attempting to terminate child process" << ac.process->processId();
ac.process->terminate();
}
}
@ -105,10 +109,10 @@ void AssignmentClientMonitor::stopChildProcesses() {
if (_childProcesses.size() > 0) {
// ask even more firmly
foreach(QProcess* childProcess, _childProcesses) {
if (childProcess->processId() > 0) {
qDebug() << "Attempting to kill child process" << childProcess->processId();
childProcess->kill();
for (auto& ac : _childProcesses) {
if (ac.process->processId() > 0) {
qDebug() << "Attempting to kill child process" << ac.process->processId();
ac.process->kill();
}
}
@ -155,17 +159,60 @@ void AssignmentClientMonitor::spawnChildClient() {
_childArguments.append("--" + ASSIGNMENT_CLIENT_MONITOR_PORT_OPTION);
_childArguments.append(QString::number(DependencyManager::get<NodeList>()->getLocalSockAddr().getPort()));
// Setup log files
const QString DATETIME_FORMAT = "yyyyMMdd.hh.mm.ss.zzz";
if (!_logDirectory.exists()) {
qDebug() << "Log directory (" << _logDirectory.absolutePath() << ") does not exist, creating.";
_logDirectory.mkpath(_logDirectory.absolutePath());
}
auto nowString = QDateTime::currentDateTime().toString(DATETIME_FORMAT);
auto stdoutFilenameTemp = QString("ac-%1-stdout.txt").arg(nowString);
auto stderrFilenameTemp = QString("ac-%1-stderr.txt").arg(nowString);
QString stdoutPathTemp = _logDirectory.absoluteFilePath(stdoutFilenameTemp);
QString stderrPathTemp = _logDirectory.absoluteFilePath(stderrFilenameTemp);
// reset our output and error files
assignmentClient->setStandardOutputFile(stdoutPathTemp);
assignmentClient->setStandardErrorFile(stderrPathTemp);
// make sure that the output from the child process appears in our output
assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels);
assignmentClient->start(QCoreApplication::applicationFilePath(), _childArguments);
// Update log path to use PID in filename
auto stdoutFilename = QString("ac-%1_%2-stdout.txt").arg(nowString).arg(assignmentClient->processId());
auto stderrFilename = QString("ac-%1_%2-stderr.txt").arg(nowString).arg(assignmentClient->processId());
QString stdoutPath = _logDirectory.absoluteFilePath(stdoutFilename);
QString stderrPath = _logDirectory.absoluteFilePath(stderrFilename);
qDebug() << "Renaming " << stdoutPathTemp << " to " << stdoutPath;
if (!_logDirectory.rename(stdoutFilenameTemp, stdoutFilename)) {
qDebug() << "Failed to rename " << stdoutFilenameTemp;
stdoutPath = stdoutPathTemp;
stdoutFilename = stdoutFilenameTemp;
}
qDebug() << "Renaming " << stderrPathTemp << " to " << stderrPath;
if (!QFile::rename(stderrPathTemp, stderrPath)) {
qDebug() << "Failed to rename " << stderrFilenameTemp;
stderrPath = stderrPathTemp;
stderrFilename = stderrFilenameTemp;
}
qDebug() << "Child stdout being written to: " << stdoutFilename;
qDebug() << "Child stderr being written to: " << stderrFilename;
if (assignmentClient->processId() > 0) {
auto pid = assignmentClient->processId();
// make sure we hear that this process has finished when it does
connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(childProcessFinished()));
connect(assignmentClient, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
this, [this, pid]() { childProcessFinished(pid); });
qDebug() << "Spawned a child client with PID" << assignmentClient->processId();
_childProcesses.insert(assignmentClient->processId(), assignmentClient);
_childProcesses.insert(assignmentClient->processId(), { assignmentClient, stdoutPath, stderrPath });
}
}
@ -253,9 +300,38 @@ void AssignmentClientMonitor::handleChildStatusPacket(QSharedPointer<ReceivedMes
quint8 assignmentType;
message->readPrimitive(&assignmentType);
childData->setChildType((Assignment::Type) assignmentType);
childData->setChildType(Assignment::Type(assignmentType));
// note when this child talked
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
}
}
bool AssignmentClientMonitor::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler) {
if (url.path() == "/status") {
QByteArray response;
QJsonObject status;
QJsonObject servers;
for (auto& ac : _childProcesses) {
QJsonObject server;
server["pid"] = ac.process->processId();
server["logStdout"] = ac.logStdoutPath;
server["logStderr"] = ac.logStderrPath;
servers[QString::number(ac.process->processId())] = server;
}
status["servers"] = servers;
QJsonDocument document { status };
connection->respond(HTTPConnection::StatusCode200, document.toJson());
} else {
connection->respond(HTTPConnection::StatusCode404);
}
return true;
}

View file

@ -16,28 +16,39 @@
#include <QtCore/qpointer.h>
#include <QtCore/QProcess>
#include <QtCore/QDateTime>
#include <QDir>
#include <Assignment.h>
#include "AssignmentClientChildData.h"
#include <HTTPManager.h>
#include <HTTPConnection.h>
extern const char* NUM_FORKS_PARAMETER;
class AssignmentClientMonitor : public QObject {
struct ACProcess {
QProcess* process; // looks like a dangling pointer, but is parented by the AssignmentClientMonitor
QString logStdoutPath;
QString logStderrPath;
};
class AssignmentClientMonitor : public QObject, public HTTPRequestHandler {
Q_OBJECT
public:
AssignmentClientMonitor(const unsigned int numAssignmentClientForks, const unsigned int minAssignmentClientForks,
const unsigned int maxAssignmentClientForks, Assignment::Type requestAssignmentType,
QString assignmentPool, quint16 listenPort, QUuid walletUUID, QString assignmentServerHostname,
quint16 assignmentServerPort);
quint16 assignmentServerPort, quint16 httpStatusServerPort, QDir logDirectory);
~AssignmentClientMonitor();
void stopChildProcesses();
private slots:
void checkSpares();
void childProcessFinished();
void childProcessFinished(qint64 pid);
void handleChildStatusPacket(QSharedPointer<ReceivedMessage> message);
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler = false) override;
public slots:
void aboutToQuit();
@ -47,6 +58,10 @@ private:
QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children
QDir _logDirectory;
HTTPManager _httpManager;
const unsigned int _numAssignmentClientForks;
const unsigned int _minAssignmentClientForks;
const unsigned int _maxAssignmentClientForks;
@ -57,7 +72,7 @@ private:
QString _assignmentServerHostname;
quint16 _assignmentServerPort;
QMap<qint64, QProcess*> _childProcesses;
QMap<qint64, ACProcess> _childProcesses;
};
#endif // hifi_AssignmentClientMonitor_h

View file

@ -24,6 +24,7 @@
#include "NodeType.h"
#include "SendAssetTask.h"
#include "UploadAssetTask.h"
#include <ServerPathUtils.h>
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
@ -49,8 +50,27 @@ void AssetServer::run() {
auto nodeList = DependencyManager::get<NodeList>();
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
_resourcesDirectory = QDir(QCoreApplication::applicationDirPath()).filePath("resources/assets");
const QString RESOURCES_PATH = "assets";
_resourcesDirectory = QDir(ServerPathUtils::getDataDirectory()).filePath(RESOURCES_PATH);
if (!_resourcesDirectory.exists()) {
qDebug() << "Asset resources directory not found, searching for existing asset resources";
QString oldDataDirectory = QCoreApplication::applicationDirPath();
auto oldResourcesDirectory = QDir(oldDataDirectory).filePath("resources/" + RESOURCES_PATH);
if (QDir(oldResourcesDirectory).exists()) {
qDebug() << "Existing assets found in " << oldResourcesDirectory << ", copying to " << _resourcesDirectory;
QDir resourcesParentDirectory = _resourcesDirectory.filePath("..");
if (!resourcesParentDirectory.exists()) {
qDebug() << "Creating data directory " << resourcesParentDirectory.absolutePath();
resourcesParentDirectory.mkpath(".");
}
QFile::copy(oldResourcesDirectory, _resourcesDirectory.absolutePath());
}
qDebug() << "Creating resources directory";
_resourcesDirectory.mkpath(".");
}

View file

@ -828,7 +828,7 @@ void AudioMixer::broadcastMixes() {
usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000; // ns to us
if (quint64(usecToSleep) > USECS_PER_SECOND) {
if (usecToSleep > int(USECS_PER_SECOND)) {
qDebug() << "DANGER: amount to sleep is" << usecToSleep;
qDebug() << "NextFrame is" << nextFrame << "and timer nsecs elapsed is" << timer.nsecsElapsed();
}

View file

@ -27,6 +27,9 @@
#include "OctreeQueryNode.h"
#include "OctreeServerConsts.h"
#include <QtCore/QStandardPaths>
#include <ServerPathUtils.h>
#include <QtCore/QDir>
int OctreeServer::_clientCount = 0;
const int MOVING_AVERAGE_SAMPLE_COUNTS = 1000000;
@ -280,10 +283,10 @@ OctreeServer::~OctreeServer() {
void OctreeServer::initHTTPManager(int port) {
// setup the embedded web server
QString documentRoot = QString("%1/resources/web").arg(QCoreApplication::applicationDirPath());
QString documentRoot = QString("%1/web").arg(ServerPathUtils::getDataDirectory());
// setup an httpManager with us as the request handler and the parent
_httpManager = new HTTPManager(port, documentRoot, this, this);
_httpManager = new HTTPManager(QHostAddress::AnyIPv4, port, documentRoot, this, this);
}
bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler) {
@ -1031,6 +1034,7 @@ void OctreeServer::readConfiguration() {
if (!readOptionString(QString("persistFilename"), settingsSectionObject, persistFilename)) {
persistFilename = getMyDefaultPersistFilename();
}
strcpy(_persistFilename, qPrintable(persistFilename));
qDebug("persistFilename=%s", _persistFilename);
@ -1139,9 +1143,52 @@ void OctreeServer::domainSettingsRequestComplete() {
// if we want Persistence, set up the local file and persist thread
if (_wantPersist) {
// If persist filename does not exist, let's see if there is one beside the application binary
// If there is, let's copy it over to our target persist directory
auto persistPath = ServerPathUtils::getDataFilePath("entities/" + QString(_persistFilename));
if (!QFile::exists(persistPath)) {
qDebug() << "Persist file does not exist, checking for existence of persist file next to application";
static const QString OLD_DEFAULT_PERSIST_FILENAME = "resources/models.json.gz";
QString oldResourcesDirectory = QCoreApplication::applicationDirPath();
// This is the old persist path, based on the current persist filename, which could
// be a custom filename set by the user.
auto oldPersistPath = QDir(oldResourcesDirectory).absoluteFilePath(_persistFilename);
// This is the old default persist path.
auto oldDefaultPersistPath = QDir(oldResourcesDirectory).absoluteFilePath(OLD_DEFAULT_PERSIST_FILENAME);
qDebug() << "Checking for existing persist file at " << oldPersistPath << " and " << oldDefaultPersistPath;
QString pathToCopyFrom;
bool shouldCopy = false;
if (QFile::exists(oldPersistPath)) {
shouldCopy = true;
pathToCopyFrom = oldPersistPath;
} else if (QFile::exists(oldDefaultPersistPath)) {
shouldCopy = true;
pathToCopyFrom = oldDefaultPersistPath;
}
if (shouldCopy) {
qDebug() << "Old persist file found, copying from " << pathToCopyFrom << " to " << persistPath;
QDir persistFileDirectory = QDir(persistPath).filePath("..");
if (!persistFileDirectory.exists()) {
qDebug() << "Creating data directory " << persistFileDirectory.path();
persistFileDirectory.mkpath(".");
}
QFile::copy(pathToCopyFrom, persistPath);
} else {
qDebug() << "No existing persist file found";
}
}
// now set up PersistThread
_persistThread = new OctreePersistThread(_tree, _persistFilename, _persistInterval,
_persistThread = new OctreePersistThread(_tree, persistPath, _persistInterval,
_wantBackup, _settings, _debugTimestampNow, _persistAsFileType);
_persistThread->initialize(true);
}

View file

@ -21,10 +21,23 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to Faceshift include directory")
set(LIBRARY_DEBUG_PATH "lib/Debug")
set(LIBRARY_RELEASE_PATH "lib/Release")
if (WIN32)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/Debug/faceshift.lib CACHE FILEPATH "Faceshift libraries")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/Release/faceshift.lib CACHE FILEPATH "Faceshift libraries")
set(LIBRARY_PREFIX "")
set(LIBRARY_EXT "lib")
elseif (APPLE)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/Debug/libfaceshift.a CACHE FILEPATH "Faceshift libraries")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/Release/libfaceshift.a CACHE FILEPATH "Faceshift libraries")
set(LIBRARY_EXT "a")
set(LIBRARY_PREFIX "lib")
if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
set(LIBRARY_DEBUG_PATH "build")
set(LIBRARY_RELEASE_PATH "build")
endif ()
endif()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG
${INSTALL_DIR}/${LIBRARY_DEBUG_PATH}/${LIBRARY_PREFIX}faceshift.${LIBRARY_EXT} CACHE FILEPATH "Faceshift libraries")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE
${INSTALL_DIR}/${LIBRARY_RELEASE_PATH}/${LIBRARY_PREFIX}faceshift.${LIBRARY_EXT} CACHE FILEPATH "Faceshift libraries")

View file

@ -1,52 +0,0 @@
set(EXTERNAL_NAME quazip)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
cmake_policy(SET CMP0046 OLD)
include(ExternalProject)
if (WIN32)
# windows shell does not like backslashes expanded on the command line,
# so convert all backslashes in the QT path to forward slashes
string(REPLACE \\ / QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
elseif ($ENV{QT_CMAKE_PREFIX_PATH})
set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
endif ()
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.6.2.zip
URL_MD5 514851970f1a14d815bdc3ad6267af4d
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib -DZLIB_ROOT=${ZLIB_ROOT}
LOG_DOWNLOAD 1
LOG_CONFIGURE 1
LOG_BUILD 1
)
add_dependencies(quazip zlib)
# Hide this external target (for ide users)
set_target_properties(${EXTERNAL_NAME} PROPERTIES
FOLDER "hidden/externals"
INSTALL_NAME_DIR ${INSTALL_DIR}/lib
BUILD_WITH_INSTALL_RPATH True)
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include CACHE PATH "List of QuaZip include directories")
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${${EXTERNAL_NAME_UPPER}_INCLUDE_DIR} CACHE PATH "List of QuaZip include directories")
set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/lib CACHE FILEPATH "Location of QuaZip DLL")
if (APPLE)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library")
elseif (WIN32)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip.lib CACHE FILEPATH "Location of QuaZip release library")
else ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip.so CACHE FILEPATH "Location of QuaZip release library")
endif ()
include(SelectLibraryConfigurations)
select_library_configurations(${EXTERNAL_NAME_UPPER})
# Force selected libraries into the cache
set(${EXTERNAL_NAME_UPPER}_LIBRARY ${${EXTERNAL_NAME_UPPER}_LIBRARY} CACHE FILEPATH "Location of QuaZip libraries")
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of QuaZip libraries")

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View file

@ -1,28 +0,0 @@
macro(CONSOLIDATE_STACK_COMPONENTS)
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE)
if (WIN32)
# Copy all the output for this target into the common deployment location
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_directory $<TARGET_FILE_DIR:${TARGET_NAME}> ${CMAKE_BINARY_DIR}/full-stack-deployment
)
# Copy icon files for interface and stack manager
if (TARGET_NAME STREQUAL "interface" OR TARGET_NAME STREQUAL "stack-manager")
if (TARGET_NAME STREQUAL "interface")
set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/icon/interface.ico")
set (ICON_DESTINATION_NAME "interface.ico")
elseif (TARGET_NAME STREQUAL "stack-manager")
set (ICON_FILE_PATH "${PROJECT_SOURCE_DIR}/assets/icon.ico")
set (ICON_DESTINATION_NAME "stack-manager.ico")
endif ()
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy ${ICON_FILE_PATH} ${CMAKE_BINARY_DIR}/full-stack-deployment/${ICON_DESTINATION_NAME}
)
endif ()
endif ()
endif ()
endmacro()

View file

@ -0,0 +1,16 @@
#
# FixPathForNSIS.cmake
#
# Created by Sam Gateau on 1/14/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
#
macro(fix_path_for_nsis INITIAL_PATH RESULTING_PATH)
# replace forward slash with backslash
string(REPLACE "/" "\\\\" _BACKSLASHED_PATH ${INITIAL_PATH})
# set the resulting path variable
set(${RESULTING_PATH} ${_BACKSLASHED_PATH})
endmacro()

View file

@ -0,0 +1,58 @@
#
# FixupInterface.cmake
# cmake/macros
#
# Copyright 2016 High Fidelity, Inc.
# Created by Stephen Birarda on January 6th, 2016
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(fixup_interface)
if (APPLE)
string(REPLACE " " "\\ " ESCAPED_BUNDLE_NAME ${INTERFACE_BUNDLE_NAME})
string(REPLACE " " "\\ " ESCAPED_INSTALL_PATH ${INTERFACE_INSTALL_DIR})
set(_INTERFACE_INSTALL_PATH "${ESCAPED_INSTALL_PATH}/${ESCAPED_BUNDLE_NAME}.app")
# install QtWebProcess from Qt to the application bundle
# since it is missed by macdeployqt
# https://bugreports.qt.io/browse/QTBUG-35211
set(LIBEXEC_PATH "${_INTERFACE_INSTALL_PATH}/Contents/libexec")
install(
PROGRAMS "${QT_DIR}/libexec/QtWebProcess"
DESTINATION ${LIBEXEC_PATH}
COMPONENT ${CLIENT_COMPONENT}
)
set(QTWEBPROCESS_PATH "\${CMAKE_INSTALL_PREFIX}/${LIBEXEC_PATH}")
# we also need a qt.conf in the directory of QtWebProcess
install(CODE "
file(WRITE ${QTWEBPROCESS_PATH}/qt.conf
\"[Paths]\nPlugins = ../PlugIns\nImports = ../Resources/qml\nQml2Imports = ../Resources/qml\"
)"
COMPONENT ${CLIENT_COMPONENT}
)
find_program(MACDEPLOYQT_COMMAND macdeployqt PATHS "${QT_DIR}/bin" NO_DEFAULT_PATH)
if (NOT MACDEPLOYQT_COMMAND AND (PRODUCTION_BUILD OR PR_BUILD))
message(FATAL_ERROR "Could not find macdeployqt at ${QT_DIR}/bin.\
It is required to produce an relocatable interface application.\
Check that the environment variable QT_DIR points to your Qt installation.\
")
endif ()
install(CODE "
execute_process(COMMAND ${MACDEPLOYQT_COMMAND}\
\${CMAKE_INSTALL_PREFIX}/${_INTERFACE_INSTALL_PATH}/\
-verbose=2 -qmldir=${CMAKE_SOURCE_DIR}/interface/resources/qml/\
-executable=\${CMAKE_INSTALL_PREFIX}/${_INTERFACE_INSTALL_PATH}/Contents/libexec/QtWebProcess\
)"
COMPONENT ${CLIENT_COMPONENT}
)
endif ()
endmacro()

View file

@ -10,21 +10,69 @@
#
macro(GENERATE_INSTALLERS)
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE AND WIN32)
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/full-stack-deployment")
find_program(MAKENSIS_COMMAND makensis PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS])
if (NOT MAKENSIS_COMMAND)
message(FATAL_ERROR "The Nullsoft Scriptable Install Systems is required for generating packaged installers on Windows (http://nsis.sourceforge.net/)")
endif ()
add_custom_target(
build-package ALL
DEPENDS interface assignment-client domain-server stack-manager
COMMAND set INSTALLER_SOURCE_DIR=${CMAKE_BINARY_DIR}/full-stack-deployment
COMMAND set INSTALLER_NAME=${CMAKE_BINARY_DIR}/${INSTALLER_NAME}
COMMAND set INSTALLER_SCRIPTS_DIR=${CMAKE_SOURCE_DIR}/examples
COMMAND set INSTALLER_COMPANY=${INSTALLER_COMPANY}
COMMAND set INSTALLER_DIRECTORY=${INSTALLER_DIRECTORY}
COMMAND CMD /C "\"${MAKENSIS_COMMAND}\" ${CMAKE_SOURCE_DIR}/tools/nsis/release.nsi"
include(CPackComponent)
set(CPACK_MODULE_PATH ${CPACK_MODULE_PATH} "${HF_CMAKE_DIR}/templates")
set(_DISPLAY_NAME ${BUILD_ORGANIZATION})
set(CPACK_PACKAGE_NAME ${_DISPLAY_NAME})
set(CPACK_PACKAGE_VENDOR "High Fidelity")
set(CPACK_PACKAGE_VERSION ${BUILD_VERSION})
set(CPACK_PACKAGE_FILE_NAME "HighFidelity-Alpha-${BUILD_VERSION}")
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
set(CPACK_NSIS_PACKAGE_NAME ${_DISPLAY_NAME})
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${_DISPLAY_NAME})
if (WIN32)
set(CPACK_NSIS_MUI_ICON "${HF_CMAKE_DIR}/installer/installer.ico")
# install and reference the Add/Remove icon
set(ADD_REMOVE_ICON_NAME "installer.ico")
set(ADD_REMOVE_ICON_BAD_PATH "${HF_CMAKE_DIR}/installer/${ADD_REMOVE_ICON_NAME}")
fix_path_for_nsis(${ADD_REMOVE_ICON_BAD_PATH} ADD_REMOVE_ICON_PATH)
set(CPACK_NSIS_INSTALLED_ICON_NAME ${ADD_REMOVE_ICON_NAME})
# use macro to put backslashes in header image path since nsis requires them
set(_INSTALLER_HEADER_BAD_PATH "${HF_CMAKE_DIR}/installer/installer-header.bmp")
set(INSTALLER_HEADER_IMAGE "")
fix_path_for_nsis(${_INSTALLER_HEADER_BAD_PATH} INSTALLER_HEADER_IMAGE)
set(_UNINSTALLER_HEADER_BAD_PATH "${HF_CMAKE_DIR}/installer/uninstaller-header.bmp")
set(UNINSTALLER_HEADER_IMAGE "")
fix_path_for_nsis(${_UNINSTALLER_HEADER_BAD_PATH} UNINSTALLER_HEADER_IMAGE)
elseif (APPLE)
# produce a drag and drop DMG on OS X
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "/")
set(CPACK_PACKAGING_INSTALL_PREFIX /)
set(CPACK_OSX_PACKAGE_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET})
# make sure a High Fidelity directory exists, in case this hits prior to other installs
install(CODE "file(MAKE_DIRECTORY \"\${CMAKE_INSTALL_PREFIX}/${DMG_SUBFOLDER_NAME}\")")
# add the resource file to the Icon file inside the folder
install(CODE
"execute_process(COMMAND Rez -append ${DMG_SUBFOLDER_ICON} -o \${CMAKE_INSTALL_PREFIX}/${ESCAPED_DMG_SUBFOLDER_NAME}/Icon\\r)"
)
# modify the folder to use that custom icon
install(CODE "execute_process(COMMAND SetFile -a C \${CMAKE_INSTALL_PREFIX}/${ESCAPED_DMG_SUBFOLDER_NAME})")
# hide the special Icon? file
install(CODE "execute_process(COMMAND SetFile -a V \${CMAKE_INSTALL_PREFIX}/${ESCAPED_DMG_SUBFOLDER_NAME}/Icon\\r)")
endif ()
# configure a cpack properties file for custom variables in template
set(CPACK_CONFIGURED_PROP_FILE "${CMAKE_CURRENT_BINARY_DIR}/CPackCustomProperties.cmake")
configure_file("${HF_CMAKE_DIR}/templates/CPackProperties.cmake.in" ${CPACK_CONFIGURED_PROP_FILE})
set(CPACK_PROPERTIES_FILE ${CPACK_CONFIGURED_PROP_FILE})
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
cpack_add_component(${CLIENT_COMPONENT} DISPLAY_NAME "High Fidelity Client")
cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "High Fidelity Server")
include(CPack)
endmacro()

View file

@ -1,36 +0,0 @@
#
# IncludeApplicationVersion.cmake
# cmake/macros
#
# Created by Leonardo Murillo on 07/14/2015.
# Copyright 2015 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
#
macro(INCLUDE_APPLICATION_VERSION)
#
# We are relying on Jenkins defined environment variables to determine the origin of this build
# and will only package if this is a PR or Release build
if (DEFINED ENV{JOB_ID})
set(DEPLOY_PACKAGE 1)
set(BUILD_SEQ $ENV{JOB_ID})
set(INSTALLER_COMPANY "High Fidelity")
set(INSTALLER_DIRECTORY "${INSTALLER_COMPANY}")
set(INSTALLER_NAME "interface-win64-${BUILD_SEQ}.exe")
elseif (DEFINED ENV{ghprbPullId})
set(DEPLOY_PACKAGE 1)
set(BUILD_SEQ "PR-$ENV{ghprbPullId}")
set(INSTALLER_COMPANY "High Fidelity - PR")
set(INSTALLER_DIRECTORY "${INSTALLER_COMPANY}\\${BUILD_SEQ}")
set(INSTALLER_NAME "pr-interface-win64-${BUILD_SEQ}.exe")
else ()
set(BUILD_SEQ "dev")
set(INSTALLER_COMPANY "High Fidelity - Dev")
set(INSTALLER_DIRECTORY "${INSTALLER_COMPANY}")
set(INSTALLER_NAME "dev-interface-win64.exe")
endif ()
configure_file("${MACRO_DIR}/ApplicationVersion.h.in" "${PROJECT_BINARY_DIR}/includes/ApplicationVersion.h")
include_directories("${PROJECT_BINARY_DIR}/includes")
endmacro(INCLUDE_APPLICATION_VERSION)

View file

@ -0,0 +1,72 @@
#
# InstallBesideConsole.cmake
# cmake/macros
#
# Copyright 2016 High Fidelity, Inc.
# Created by Stephen Birarda on January 5th, 2016
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(install_beside_console)
if (WIN32 OR APPLE)
# install this component beside the installed server-console executable
if (APPLE)
set(CONSOLE_APP_CONTENTS "${CONSOLE_INSTALL_APP_PATH}/Contents")
set(COMPONENT_DESTINATION "${CONSOLE_APP_CONTENTS}/MacOS/Components.app/Contents/MacOS")
else ()
set(COMPONENT_DESTINATION ${CONSOLE_INSTALL_DIR})
endif ()
if (APPLE)
install(
TARGETS ${TARGET_NAME}
RUNTIME DESTINATION ${COMPONENT_DESTINATION}
COMPONENT ${SERVER_COMPONENT}
)
else ()
# setup install of executable and things copied by fixup/windeployqt
install(
FILES "$<TARGET_FILE_DIR:${TARGET_NAME}>/"
DESTINATION ${COMPONENT_DESTINATION}
COMPONENT ${SERVER_COMPONENT}
)
# on windows for PR and production builds, sign the executable
set(EXECUTABLE_COMPONENT ${SERVER_COMPONENT})
optional_win_executable_signing()
endif ()
if (TARGET_NAME STREQUAL domain-server)
if (APPLE)
set(RESOURCES_DESTINATION ${COMPONENT_DESTINATION})
else ()
set(RESOURCES_DESTINATION ${CONSOLE_INSTALL_DIR})
endif ()
# install the resources folder for the domain-server where its executable will be
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/resources
DESTINATION ${RESOURCES_DESTINATION}
USE_SOURCE_PERMISSIONS
COMPONENT ${SERVER_COMPONENT}
)
endif ()
if (APPLE)
# during the install phase, call fixup to drop the shared libraries for these components in the right place
set(EXECUTABLE_NEEDING_FIXUP "\${CMAKE_INSTALL_PREFIX}/${COMPONENT_DESTINATION}/${TARGET_NAME}")
install(CODE "
include(BundleUtilities)
fixup_bundle(\"${EXECUTABLE_NEEDING_FIXUP}\" \"\" \"${FIXUP_LIBS}\")
" COMPONENT ${SERVER_COMPONENT})
endif ()
endif ()
# set variables used by manual ssleay library copy
set(TARGET_INSTALL_DIR ${COMPONENT_DESTINATION})
set(TARGET_INSTALL_COMPONENT ${SERVER_COMPONENT})
manually_install_ssl_eay()
endmacro()

View file

@ -0,0 +1,28 @@
#
# ManuallyInstallSSLEay.cmake
#
# Created by Stephen Birarda on 1/15/16.
# Copyright 2014 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
#
macro(manually_install_ssl_eay)
# on windows we have had issues with targets missing ssleay library
# not convinced we actually need it (I assume it would show up in the dependency tree)
# but to be safe we install it manually beside the current target
if (WIN32)
# we need to find SSL_EAY_LIBRARY_* so we can install it beside this target
# so we have to call find_package(OpenSSL) here even though this target may not specifically need it
find_package(OpenSSL REQUIRED)
install(
FILES "${OPENSSL_DLL_PATH}/ssleay32.dll"
DESTINATION ${TARGET_INSTALL_DIR}
COMPONENT ${TARGET_INSTALL_COMPONENT}
)
endif()
endmacro()

View file

@ -0,0 +1,34 @@
#
# OptionalWinExecutableSigning.cmake
# cmake/macros
#
# Copyright 2016 High Fidelity, Inc.
# Created by Stephen Birarda on January 12, 2016
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(optional_win_executable_signing)
if (WIN32 AND PRODUCTION_BUILD)
if (DEFINED ENV{HF_PFX_FILE})
if (DEFINED ENV{HF_PFX_PASSPHRASE})
message(STATUS "Executable for ${TARGET_NAME} will be signed with SignTool.")
if (NOT EXECUTABLE_PATH)
set(EXECUTABLE_PATH "$<TARGET_FILE:${TARGET_NAME}>")
endif ()
# setup a post build command to sign the executable
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${SIGNTOOL_EXECUTABLE} sign /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://tsa.starfieldtech.com /td SHA256 ${EXECUTABLE_PATH}
)
else ()
message(FATAL_ERROR "HF_PFX_PASSPHRASE must be set for executables to be signed.")
endif ()
else ()
message(WARNING "Creating a production build but not code signing since HF_PFX_FILE is not set.")
endif ()
endif ()
endmacro()

View file

@ -10,10 +10,9 @@
#
macro(PACKAGE_LIBRARIES_FOR_DEPLOYMENT)
if (WIN32)
configure_file(
${HIFI_CMAKE_DIR}/templates/FixupBundlePostBuild.cmake.in
${HF_CMAKE_DIR}/templates/FixupBundlePostBuild.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake
@ONLY
)
@ -42,18 +41,5 @@ macro(PACKAGE_LIBRARIES_FOR_DEPLOYMENT)
POST_BUILD
COMMAND CMD /C "SET PATH=%PATH%;${QT_DIR}/bin && ${WINDEPLOYQT_COMMAND} ${EXTRA_DEPLOY_OPTIONS} $<$<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>,$<CONFIG:RelWithDebInfo>>:--release> $<TARGET_FILE:${TARGET_NAME}>"
)
elseif (DEFINED BUILD_BUNDLE AND BUILD_BUNDLE AND APPLE)
find_program(MACDEPLOYQT_COMMAND macdeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH)
if (NOT MACDEPLOYQT_COMMAND)
message(FATAL_ERROR "Could not find macdeployqt at ${QT_DIR}/bin. macdeployqt is required.")
endif ()
# add a post-build command to call macdeployqt to copy Qt plugins
add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
COMMAND ${MACDEPLOYQT_COMMAND} ${CMAKE_CURRENT_BINARY_DIR}/\${CONFIGURATION}/${TARGET_NAME}.app -verbose 0
)
endif ()
endmacro()

View file

@ -0,0 +1,109 @@
#
# SetPackagingParameters.cmake
# cmake/macros
#
# Created by Leonardo Murillo on 07/14/2015.
# Copyright 2015 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
# This macro checks some Jenkins defined environment variables to determine the origin of this build
# and decides how targets should be packaged.
macro(SET_PACKAGING_PARAMETERS)
set(PR_BUILD 0)
set(PRODUCTION_BUILD 0)
set(DEV_BUILD 0)
set(RELEASE_TYPE $ENV{RELEASE_TYPE})
set(RELEASE_NUMBER $ENV{RELEASE_NUMBER})
if (RELEASE_TYPE STREQUAL "PRODUCTION")
set(DEPLOY_PACKAGE TRUE)
set(PRODUCTION_BUILD 1)
set(BUILD_VERSION ${RELEASE_NUMBER})
set(BUILD_ORGANIZATION "High Fidelity")
set(HIGH_FIDELITY_PROTOCOL "hifi")
set(INTERFACE_BUNDLE_NAME "High Fidelity")
set(INTERFACE_ICON_PREFIX "interface")
elseif (RELEASE_TYPE STREQUAL "PR")
set(DEPLOY_PACKAGE TRUE)
set(PR_BUILD 1)
set(BUILD_VERSION "PR${RELEASE_NUMBER}")
set(BUILD_ORGANIZATION "High Fidelity - ${BUILD_VERSION}")
set(INTERFACE_BUNDLE_NAME "High Fidelity")
set(INTERFACE_ICON_PREFIX "interface-beta")
else ()
set(DEV_BUILD 1)
set(BUILD_VERSION "dev")
set(BUILD_ORGANIZATION "High Fidelity - ${BUILD_VERSION}")
set(INTERFACE_BUNDLE_NAME "Interface")
set(INTERFACE_ICON_PREFIX "interface-beta")
endif ()
if (APPLE)
set(DMG_SUBFOLDER_NAME "${BUILD_ORGANIZATION}")
set(ESCAPED_DMG_SUBFOLDER_NAME "")
string(REPLACE " " "\\ " ESCAPED_DMG_SUBFOLDER_NAME ${DMG_SUBFOLDER_NAME})
set(DMG_SUBFOLDER_ICON "${HF_CMAKE_DIR}/installer/install-folder.rsrc")
set(CONSOLE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
set(INTERFACE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
else ()
set(CONSOLE_INSTALL_DIR ".")
set(INTERFACE_INSTALL_DIR ".")
endif ()
if (WIN32)
set(INTERFACE_EXEC_PREFIX "interface")
set(INTERFACE_ICON_FILENAME "${INTERFACE_ICON_PREFIX}.ico")
set(CONSOLE_EXEC_NAME "server-console.exe")
set(DS_EXEC_NAME "domain-server.exe")
set(AC_EXEC_NAME "assignment-client.exe")
# start menu shortcuts
set(INTERFACE_SM_SHORTCUT_NAME "High Fidelity")
set(CONSOLE_SM_SHORTCUT_NAME "Server Console")
# check if we need to find signtool
if (PRODUCTION_BUILD OR PR_BUILD)
find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64")
if (NOT SIGNTOOL_EXECUTABLE)
message(FATAL_ERROR "Code signing of executables was requested but signtool.exe could not be found.")
endif ()
endif ()
set(GENERATED_UNINSTALLER_EXEC_NAME "Uninstall.exe")
set(REGISTRY_HKLM_INSTALL_ROOT "Software")
set(POST_INSTALL_OPTIONS_REG_GROUP "PostInstallOptions")
set(CLIENT_DESKTOP_SHORTCUT_REG_KEY "ClientDesktopShortcut")
set(CONSOLE_DESKTOP_SHORTCUT_REG_KEY "ConsoleDesktopShortcut")
set(CONSOLE_STARTUP_REG_KEY "ConsoleStartupShortcut")
set(LAUNCH_NOW_REG_KEY "LaunchAfterInstall")
endif ()
if (APPLE)
set(CONSOLE_EXEC_NAME "Server Console.app")
set(CONSOLE_INSTALL_APP_PATH "${CONSOLE_INSTALL_DIR}/${CONSOLE_EXEC_NAME}")
set(INTERFACE_INSTALL_APP_PATH "${CONSOLE_INSTALL_DIR}/${INTERFACE_BUNDLE_NAME}.app")
set(INTERFACE_ICON_FILENAME "${INTERFACE_ICON_PREFIX}.icns")
endif()
# setup component categories for installer
set(DDE_COMPONENT dde)
set(CLIENT_COMPONENT client)
set(SERVER_COMPONENT server)
# create a header file our targets can use to find out the application version
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/includes")
configure_file("${HF_CMAKE_DIR}/templates/BuildInfo.h.in" "${CMAKE_BINARY_DIR}/includes/BuildInfo.h")
endmacro(SET_PACKAGING_PARAMETERS)

View file

@ -12,12 +12,12 @@ macro(SETUP_HIFI_PLUGIN)
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Plugins")
if (APPLE)
set(PLUGIN_PATH "interface.app/Contents/MacOS/plugins")
set(PLUGIN_PATH "${INTERFACE_BUNDLE_NAME}.app/Contents/PlugIns")
else()
set(PLUGIN_PATH "plugins")
endif()
IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_GENERATOR STREQUAL "Unix Makefiles")
set(PLUGIN_FULL_PATH "${CMAKE_BINARY_DIR}/interface/${PLUGIN_PATH}/")
else()
set(PLUGIN_FULL_PATH "${CMAKE_BINARY_DIR}/interface/$<CONFIGURATION>/${PLUGIN_PATH}/")
@ -35,5 +35,4 @@ macro(SETUP_HIFI_PLUGIN)
"$<TARGET_FILE:${TARGET_NAME}>"
${PLUGIN_FULL_PATH}
)
endmacro()

View file

@ -22,11 +22,10 @@ macro(SETUP_HIFI_PROJECT)
endif ()
endforeach()
if (DEFINED BUILD_BUNDLE AND BUILD_BUNDLE AND APPLE)
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${TARGET_SRCS} ${AUTOMTC_SRC} ${AUTOSCRIBE_SHADER_LIB_SRC})
else ()
add_executable(${TARGET_NAME} ${TARGET_SRCS} ${AUTOMTC_SRC} ${AUTOSCRIBE_SHADER_LIB_SRC})
endif()
add_executable(${TARGET_NAME} ${TARGET_SRCS} ${AUTOMTC_SRC} ${AUTOSCRIBE_SHADER_LIB_SRC})
# include the generated application version header
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes")
set(${TARGET_NAME}_DEPENDENCY_QT_MODULES ${ARGN})
list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES Core)

View file

@ -6,15 +6,23 @@
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_NSIGHT)
if (WIN32)
if (USE_NSIGHT)
if (WIN32 AND USE_NSIGHT)
# grab the global CHECKED_FOR_NSIGHT_ONCE property
get_property(NSIGHT_CHECKED GLOBAL PROPERTY CHECKED_FOR_NSIGHT_ONCE)
if (NOT NSIGHT_CHECKED)
# try to find the Nsight package and add it to the build if we find it
find_package(NSIGHT)
if (NSIGHT_FOUND)
include_directories(${NSIGHT_INCLUDE_DIRS})
add_definitions(-DNSIGHT_FOUND)
target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}")
endif ()
endif()
endif (WIN32)
# set the global CHECKED_FOR_NSIGHT_ONCE property so that we only debug that we couldn't find it once
set_property(GLOBAL PROPERTY CHECKED_FOR_NSIGHT_ONCE TRUE)
endif ()
if (NSIGHT_FOUND)
include_directories(${NSIGHT_INCLUDE_DIRS})
add_definitions(-DNSIGHT_FOUND)
target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}")
endif ()
endif ()
endmacro()

View file

@ -1,16 +0,0 @@
#
# Copyright 2015 High Fidelity, Inc.
# Created by Leonardo Murillo on 2015/11/20
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_QUAZIP)
add_dependency_external_projects(quazip)
find_package(QuaZip REQUIRED)
target_include_directories(${TARGET_NAME} PUBLIC ${QUAZIP_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${QUAZIP_LIBRARIES})
if (WIN32)
add_paths_to_fixup_libs(${QUAZIP_DLL_PATH})
endif ()
endmacro()

View file

@ -252,15 +252,6 @@ endif ()
if (WIN32)
add_paths_to_fixup_libs(${OPENSSL_DLL_PATH})
#
# For some reason fixup misses the following DLL and only copies libeay32. There's gotta be a better way to handle this
# but for now resorting to the following interm solution
if (DEFINED DEPLOY_PACKAGE AND DEPLOY_PACKAGE)
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy ${OPENSSL_DLL_PATH}/ssleay32.dll ${CMAKE_BINARY_DIR}/full-stack-deployment/
)
endif ()
endif ()
mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES OPENSSL_SEARCH_DIRS)

View file

@ -1,29 +0,0 @@
#
# FindQuaZip.h
# StackManagerQt/cmake/modules
#
# Created by Mohammed Nafees.
# Copyright (c) 2014 High Fidelity. All rights reserved.
#
# QUAZIP_FOUND - QuaZip library was found
# QUAZIP_INCLUDE_DIR - Path to QuaZip include dir
# QUAZIP_INCLUDE_DIRS - Path to QuaZip and zlib include dir (combined from QUAZIP_INCLUDE_DIR + ZLIB_INCLUDE_DIR)
# QUAZIP_LIBRARIES - List of QuaZip libraries
# QUAZIP_ZLIB_INCLUDE_DIR - The include dir of zlib headers
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
hifi_library_search_hints("quazip")
if (WIN32)
find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES include/quazip HINTS ${QUAZIP_SEARCH_DIRS})
elseif (APPLE)
find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES include/quazip HINTS ${QUAZIP_SEARCH_DIRS})
else ()
find_path(QUAZIP_INCLUDE_DIRS quazip.h PATH_SUFFIXES quazip HINTS ${QUAZIP_SEARCH_DIRS})
endif ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(QUAZIP DEFAULT_MSG QUAZIP_INCLUDE_DIRS)
mark_as_advanced(QUAZIP_INCLUDE_DIRS QUAZIP_SEARCH_DIRS)

View file

@ -1,12 +1,15 @@
//
// ApplicationVersion.h.in
// BuildInfo.h.in
// cmake/macros
//
// Created by Leonardo Murillo on 8/13/15.
// Created by Stephen Birarda on 1/14/16.
// Copyright 2015 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
//
const QString BUILD_VERSION = "@BUILD_SEQ@";
namespace BuildInfo {
const QString MODIFIED_ORGANIZATION = "@BUILD_ORGANIZATION@";
const QString VERSION = "@BUILD_VERSION@";
}

View file

@ -0,0 +1,35 @@
#
# CPackProperties.cmake.in
# cmake/templates
#
# Copyright 2016 High Fidelity, Inc.
# Created by Stephen Birarda on January 11, 2016
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SM_SHORTCUT_NAME@")
set(INTERFACE_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe")
set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SM_SHORTCUT_NAME@")
set(CONSOLE_WIN_EXEC_NAME "@CONSOLE_EXEC_NAME@")
set(DS_EXEC_NAME "@DS_EXEC_NAME@")
set(AC_EXEC_NAME "@AC_EXEC_NAME@")
set(HIGH_FIDELITY_PROTOCOL "@HIGH_FIDELITY_PROTOCOL@")
set(PRODUCTION_BUILD "@PRODUCTION_BUILD@")
set(PR_BUILD "@PR_BUILD@")
set(BUILD_ORGANIZATION "@BUILD_ORGANIZATION@")
set(POST_INSTALL_OPTIONS_PATH "@POST_INSTALL_OPTIONS_PATH@")
set(CLIENT_COMPONENT_NAME "@CLIENT_COMPONENT@")
set(SERVER_COMPONENT_NAME "@SERVER_COMPONENT@")
set(SIGNTOOL_EXECUTABLE "@SIGNTOOL_EXECUTABLE@")
set(UNINSTALLER_NAME "@GENERATED_UNINSTALLER_EXEC_NAME@")
set(REGISTRY_HKLM_INSTALL_ROOT "@REGISTRY_HKLM_INSTALL_ROOT@")
set(POST_INSTALL_OPTIONS_REG_GROUP "@POST_INSTALL_OPTIONS_REG_GROUP@")
set(CLIENT_DESKTOP_SHORTCUT_REG_KEY "@CLIENT_DESKTOP_SHORTCUT_REG_KEY@")
set(CONSOLE_DESKTOP_SHORTCUT_REG_KEY "@CONSOLE_DESKTOP_SHORTCUT_REG_KEY@")
set(CONSOLE_STARTUP_REG_KEY "@CONSOLE_STARTUP_REG_KEY@")
set(LAUNCH_NOW_REG_KEY "@LAUNCH_NOW_REG_KEY@")
set(INSTALLER_HEADER_IMAGE "@INSTALLER_HEADER_IMAGE@")
set(UNINSTALLER_HEADER_IMAGE "@UNINSTALLER_HEADER_IMAGE@")
set(ADD_REMOVE_ICON_PATH "@ADD_REMOVE_ICON_PATH@")

View file

@ -11,7 +11,6 @@
include(BundleUtilities)
# replace copy_resolved_item_into_bundle
#
# The official version of copy_resolved_item_into_bundle will print out a "warning:" when
@ -19,38 +18,37 @@ include(BundleUtilities)
# should rise to the level of a "warning" so we replace this message with a "status:"
#
function(copy_resolved_item_into_bundle resolved_item resolved_embedded_item)
if(WIN32)
# ignore case on Windows
string(TOLOWER "${resolved_item}" resolved_item_compare)
string(TOLOWER "${resolved_embedded_item}" resolved_embedded_item_compare)
else()
set(resolved_item_compare "${resolved_item}")
set(resolved_embedded_item_compare "${resolved_embedded_item}")
endif()
if (WIN32)
# ignore case on Windows
string(TOLOWER "${resolved_item}" resolved_item_compare)
string(TOLOWER "${resolved_embedded_item}" resolved_embedded_item_compare)
else()
set(resolved_item_compare "${resolved_item}")
set(resolved_embedded_item_compare "${resolved_embedded_item}")
endif()
if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
# this is our only change from the original version
message(STATUS "status: resolved_item == resolved_embedded_item - not copying...")
else()
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${resolved_item}" "${resolved_embedded_item}")
if(UNIX AND NOT APPLE)
file(RPATH_REMOVE FILE "${resolved_embedded_item}")
endif()
if ("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}")
# this is our only change from the original version
message(STATUS "status: resolved_item == resolved_embedded_item - not copying...")
else()
#message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${resolved_item}" "${resolved_embedded_item}")
if(UNIX AND NOT APPLE)
file(RPATH_REMOVE FILE "${resolved_embedded_item}")
endif()
endif()
endfunction()
message(STATUS "FIXUP_LIBS for fixup_bundle called for bundle ${BUNDLE_EXECUTABLE} are @FIXUP_LIBS@")
message(STATUS "Scanning for plugins from ${BUNDLE_PLUGIN_DIR}")
if (APPLE)
set(PLUGIN_EXTENSION "dylib")
set(PLUGIN_EXTENSION "dylib")
elseif (WIN32)
set(PLUGIN_EXTENSION "dll")
set(PLUGIN_EXTENSION "dll")
else()
set(PLUGIN_EXTENSION "so")
set(PLUGIN_EXTENSION "so")
endif()
file(GLOB RUNTIME_PLUGINS "${BUNDLE_PLUGIN_DIR}/*.${PLUGIN_EXTENSION}")
fixup_bundle("${BUNDLE_EXECUTABLE}" "${RUNTIME_PLUGINS}" "@FIXUP_LIBS@")
file(GLOB EXTRA_PLUGINS "${BUNDLE_PLUGIN_DIR}/*.${PLUGIN_EXTENSION}")
fixup_bundle("${BUNDLE_EXECUTABLE}" "${EXTRA_PLUGINS}" "@FIXUP_LIBS@")

View file

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "@CONFIGURE_ICON_PATH@"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
{
"releaseType": "@RELEASE_TYPE@",
"buildIdentifier": "@BUILD_VERSION@"
}

View file

@ -34,8 +34,10 @@ target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES})
# libcrypto uses dlopen in libdl
if (UNIX)
target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS})
endif (UNIX)
endif ()
include_application_version()
package_libraries_for_deployment()
consolidate_stack_components()
if (WIN32)
package_libraries_for_deployment()
endif ()
install_beside_console()

View file

@ -386,8 +386,8 @@
"name": "persistFilename",
"label": "Entities Filename",
"help": "the path to the file entities are stored in. Make sure the path exists.",
"placeholder": "resources/models.json.gz",
"default": "resources/models.json.gz",
"placeholder": "models.json.gz",
"default": "models.json.gz",
"advanced": true
},
{

View file

@ -126,6 +126,20 @@ var viewHelpers = {
}
}
var qs = (function(a) {
if (a == "") return {};
var b = {};
for (var i = 0; i < a.length; ++i)
{
var p=a[i].split('=', 2);
if (p.length == 1)
b[p[0]] = "";
else
b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
}
return b;
})(window.location.search.substr(1).split('&'));
$(document).ready(function(){
/*
* Clamped-width.
@ -272,9 +286,80 @@ $(document).ready(function(){
// $('body').scrollspy({ target: '#setup-sidebar'})
reloadSettings();
reloadSettings(function(success){
if (success) {
handleAction();
} else {
swal({
title: '',
type: 'error',
text: "There was a problem loading the domain settings.\nPlease refresh the page to try again.",
});
}
});
});
function handleAction() {
// check if we were passed an action to handle
var action = qs["action"];
if (action == "share") {
// figure out if we already have a stored domain ID
if (Settings.data.values.metaverse.id.length > 0) {
// we need to ask the API what a shareable name for this domain is
getDomainFromAPI(function(data){
// check if we have owner_places (for a real domain) or a name (for a temporary domain)
if (data && data.status == "success") {
var shareName;
if (data.domain.owner_places) {
shareName = data.domain.owner_places[0].name
} else if (data.domain.name) {
shareName = data.domain.name;
}
var shareLink = "hifi://" + shareName;
console.log(shareLink);
// show a dialog with a copiable share URL
swal({
title: "Share",
type: "input",
inputPlaceholder: shareLink,
inputValue: shareLink,
text: "Copy this URL to invite friends to your domain.",
closeOnConfirm: true
});
$('.sweet-alert input').select();
} else {
// show an error alert
swal({
title: '',
type: 'error',
text: "There was a problem retreiving domain information from High Fidelity API.",
confirmButtonText: 'Try again',
showCancelButton: true,
closeOnConfirm: false
}, function(isConfirm){
if (isConfirm) {
// they want to try getting domain share info again
showSpinnerAlert("Requesting domain information...")
handleAction();
} else {
swal.close();
}
});
}
});
} else {
// no domain ID present, just show the share dialog
createTemporaryDomain();
}
}
}
function dynamicButton(button_id, text) {
return $("<button type='button' id='" + button_id + "' class='btn btn-primary'>" + text + "</button>");
}
@ -577,29 +662,33 @@ function placeTableRowForPlaceObject(place) {
return placeTableRow(place.name, placePathOrIndex, false);
}
function reloadPlacesOrTemporaryName() {
function getDomainFromAPI(callback) {
// we only need to do this if we have a current domain ID
var domainID = Settings.data.values.metaverse.id;
if (domainID.length > 0) {
var domainURL = Settings.METAVERSE_URL + "/api/v1/domains/" + domainID;
$.getJSON(domainURL, function(data){
// check if we have owner_places (for a real domain) or a name (for a temporary domain)
if (data.status == "success") {
if (data.domain.owner_places) {
// add a table row for each of these names
_.each(data.domain.owner_places, function(place){
$('#' + Settings.PLACES_TABLE_ID + " tbody").append(placeTableRowForPlaceObject(place));
});
} else if (data.domain.name) {
// add a table row for this temporary domain name
$('#' + Settings.PLACES_TABLE_ID + " tbody").append(placeTableRow(data.domain.name, '/', true));
}
}
});
$.getJSON(domainURL, callback).fail(callback);
}
}
function reloadPlacesOrTemporaryName() {
getDomainFromAPI(function(data){
// check if we have owner_places (for a real domain) or a name (for a temporary domain)
if (data.status == "success") {
if (data.domain.owner_places) {
// add a table row for each of these names
_.each(data.domain.owner_places, function(place){
$('#' + Settings.PLACES_TABLE_ID + " tbody").append(placeTableRowForPlaceObject(place));
});
} else if (data.domain.name) {
// add a table row for this temporary domain name
$('#' + Settings.PLACES_TABLE_ID + " tbody").append(placeTableRow(data.domain.name, '/', true));
}
}
})
}
function appendDomainIDButtons() {
var domainIDInput = $(Settings.DOMAIN_ID_SELECTOR);
@ -728,7 +817,7 @@ function createTemporaryDomain() {
});
}
function reloadSettings() {
function reloadSettings(callback) {
$.getJSON('/settings.json', function(data){
_.extend(data, viewHelpers)
@ -757,6 +846,12 @@ function reloadSettings() {
placement: 'right',
title: 'This setting is in the master config file and cannot be changed'
});
// call the callback now that settings are loaded
callback(true);
}).fail(function() {
// call the failure object since settings load faild
callback(false)
});
}

File diff suppressed because one or more lines are too long

View file

@ -24,7 +24,7 @@
#include <QUrlQuery>
#include <AccountManager.h>
#include <ApplicationVersion.h>
#include <BuildInfo.h>
#include <HifiConfigVariantMap.h>
#include <HTTPConnection.h>
#include <LogUtils.h>
@ -35,6 +35,7 @@
#include <ShutdownEventListener.h>
#include <UUID.h>
#include <LogHandler.h>
#include <ServerPathUtils.h>
#include "DomainServerNodeData.h"
#include "NodeConnectionData.h"
@ -46,7 +47,7 @@ const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.io";
DomainServer::DomainServer(int argc, char* argv[]) :
QCoreApplication(argc, argv),
_gatekeeper(this),
_httpManager(DOMAIN_SERVER_HTTP_PORT, QString("%1/resources/web/").arg(QCoreApplication::applicationDirPath()), this),
_httpManager(QHostAddress::AnyIPv4, DOMAIN_SERVER_HTTP_PORT, QString("%1/resources/web/").arg(QCoreApplication::applicationDirPath()), this),
_httpsManager(NULL),
_allAssignments(),
_unfulfilledAssignments(),
@ -71,17 +72,19 @@ DomainServer::DomainServer(int argc, char* argv[]) :
connect(this, &QCoreApplication::aboutToQuit, this, &DomainServer::aboutToQuit);
setOrganizationName("High Fidelity");
setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION);
setOrganizationDomain("highfidelity.io");
setApplicationName("domain-server");
setApplicationVersion(BUILD_VERSION);
setApplicationVersion(BuildInfo::VERSION);
QSettings::setDefaultFormat(QSettings::IniFormat);
// make sure we have a fresh AccountManager instance
// (need this since domain-server can restart itself and maintain static variables)
AccountManager::getInstance(true);
_settingsManager.setupConfigMap(arguments());
auto args = arguments();
_settingsManager.setupConfigMap(args);
// setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us
#ifdef _WIN32
@ -110,6 +113,8 @@ DomainServer::DomainServer(int argc, char* argv[]) :
// preload some user public keys so they can connect on first request
_gatekeeper.preloadAllowedUserPublicKeys();
optionallyGetTemporaryName(args);
}
}
@ -157,7 +162,7 @@ bool DomainServer::optionallyReadX509KeyAndCertificate() {
QSslCertificate sslCertificate(&certFile);
QSslKey privateKey(&keyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, keyPassphraseString.toUtf8());
_httpsManager = new HTTPSManager(DOMAIN_SERVER_HTTPS_PORT, sslCertificate, privateKey, QString(), this, this);
_httpsManager = new HTTPSManager(QHostAddress::AnyIPv4, DOMAIN_SERVER_HTTPS_PORT, sslCertificate, privateKey, QString(), this, this);
qDebug() << "TCP server listening for HTTPS connections on" << DOMAIN_SERVER_HTTPS_PORT;
@ -209,6 +214,80 @@ bool DomainServer::optionallySetupOAuth() {
return true;
}
static const QString METAVERSE_DOMAIN_ID_KEY_PATH = "metaverse.id";
void DomainServer::optionallyGetTemporaryName(const QStringList& arguments) {
// check for the temporary name parameter
const QString GET_TEMPORARY_NAME_SWITCH = "--get-temp-name";
if (arguments.contains(GET_TEMPORARY_NAME_SWITCH)) {
// make sure we don't already have a domain ID
const QVariant* idValueVariant = valueForKeyPath(_settingsManager.getSettingsMap(), METAVERSE_DOMAIN_ID_KEY_PATH);
if (idValueVariant) {
qWarning() << "Temporary domain name requested but a domain ID is already present in domain-server settings."
<< "Will not request temporary name.";
return;
}
// we've been asked to grab a temporary name from the API
// so fire off that request now
auto& accountManager = AccountManager::getInstance();
// ask our auth endpoint for our balance
JSONCallbackParameters callbackParameters;
callbackParameters.jsonCallbackReceiver = this;
callbackParameters.jsonCallbackMethod = "handleTempDomainSuccess";
callbackParameters.errorCallbackReceiver = this;
callbackParameters.errorCallbackMethod = "handleTempDomainError";
accountManager.sendRequest("/api/v1/domains/temporary", AccountManagerAuth::None,
QNetworkAccessManager::PostOperation, callbackParameters);
}
}
void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) {
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
// grab the information for the new domain
static const QString DATA_KEY = "data";
static const QString DOMAIN_KEY = "domain";
static const QString ID_KEY = "id";
static const QString NAME_KEY = "name";
auto domainObject = jsonObject[DATA_KEY].toObject()[DOMAIN_KEY].toObject();
if (!domainObject.isEmpty()) {
auto id = domainObject[ID_KEY].toString();
auto name = domainObject[NAME_KEY].toString();
qInfo() << "Received new temporary domain name" << name;
qDebug() << "The temporary domain ID is" << id;
// store the new domain ID and auto network setting immediately
QString newSettingsJSON = QString("{\"metaverse\": { \"id\": \"%1\", \"automatic_networking\": \"full\"}}").arg(id);
auto settingsDocument = QJsonDocument::fromJson(newSettingsJSON.toUtf8());
_settingsManager.recurseJSONObjectAndOverwriteSettings(settingsDocument.object());
// store the new ID and auto networking setting on disk
_settingsManager.persistToFile();
// change our domain ID immediately
DependencyManager::get<LimitedNodeList>()->setSessionUUID(QUuid { id });
// change our automatic networking settings so that we're communicating with the ICE server
setupICEHeartbeatForFullNetworking();
} else {
qWarning() << "There were problems parsing the API response containing a temporary domain name. Please try again"
<< "via domain-server relaunch or from the domain-server settings.";
}
}
void DomainServer::handleTempDomainError(QNetworkReply& requestReply) {
qWarning() << "A temporary name was requested but there was an error creating one. Please try again via domain-server relaunch"
<< "or from the domain-server settings.";
}
const QString DOMAIN_CONFIG_ID_KEY = "id";
const QString METAVERSE_AUTOMATIC_NETWORKING_KEY_PATH = "metaverse.automatic_networking";
@ -259,7 +338,6 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
// set our LimitedNodeList UUID to match the UUID from our config
// nodes will currently use this to add resources to data-web that relate to our domain
const QString METAVERSE_DOMAIN_ID_KEY_PATH = "metaverse.id";
const QVariant* idValueVariant = valueForKeyPath(settingsMap, METAVERSE_DOMAIN_ID_KEY_PATH);
if (idValueVariant) {
nodeList->setSessionUUID(idValueVariant->toString());
@ -372,19 +450,7 @@ void DomainServer::setupAutomaticNetworking() {
_settingsManager.valueOrDefaultValueForKeyPath(METAVERSE_AUTOMATIC_NETWORKING_KEY_PATH).toString();
if (_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) {
// call our sendHeartbeatToIceServer immediately anytime a local or public socket changes
connect(nodeList.data(), &LimitedNodeList::localSockAddrChanged,
this, &DomainServer::sendHeartbeatToIceServer);
connect(nodeList.data(), &LimitedNodeList::publicSockAddrChanged,
this, &DomainServer::sendHeartbeatToIceServer);
// we need this DS to know what our public IP is - start trying to figure that out now
nodeList->startSTUNPublicSocketUpdate();
// setup a timer to heartbeat with the ice-server every so often
QTimer* iceHeartbeatTimer = new QTimer(this);
connect(iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::sendHeartbeatToIceServer);
iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS);
setupICEHeartbeatForFullNetworking();
}
if (!didSetupAccountManagerWithAccessToken()) {
@ -434,6 +500,26 @@ void DomainServer::setupAutomaticNetworking() {
dataHeartbeatTimer->start(DOMAIN_SERVER_DATA_WEB_HEARTBEAT_MSECS);
}
void DomainServer::setupICEHeartbeatForFullNetworking() {
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
// call our sendHeartbeatToIceServer immediately anytime a local or public socket changes
connect(limitedNodeList.data(), &LimitedNodeList::localSockAddrChanged,
this, &DomainServer::sendHeartbeatToIceServer);
connect(limitedNodeList.data(), &LimitedNodeList::publicSockAddrChanged,
this, &DomainServer::sendHeartbeatToIceServer);
// we need this DS to know what our public IP is - start trying to figure that out now
limitedNodeList->startSTUNPublicSocketUpdate();
if (!_iceHeartbeatTimer) {
// setup a timer to heartbeat with the ice-server every so often
_iceHeartbeatTimer = new QTimer { this };
connect(_iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::sendHeartbeatToIceServer);
_iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS);
}
}
void DomainServer::loginFailed() {
qDebug() << "Login to data server has failed. domain-server will now quit";
QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
@ -1068,7 +1154,7 @@ QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) {
const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "resources/web/assignment";
QString pathForAssignmentScript(const QUuid& assignmentUUID) {
QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION);
QString newPath { ServerPathUtils::getDataDirectory() + "/" + QString(ASSIGNMENT_SCRIPT_HOST_LOCATION) };
newPath += "/scripts/";
// append the UUID for this script as the new filename, remove the curly braces
newPath += uuidStringWithoutCurlyBraces(assignmentUUID);

View file

@ -75,16 +75,22 @@ private slots:
void handleConnectedNode(SharedNodePointer newNode);
void handleTempDomainSuccess(QNetworkReply& requestReply);
void handleTempDomainError(QNetworkReply& requestReply);
private:
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
bool optionallySetupOAuth();
bool optionallyReadX509KeyAndCertificate();
bool optionallySetupAssignmentPayment();
void optionallyGetTemporaryName(const QStringList& arguments);
bool didSetupAccountManagerWithAccessToken();
bool resetAccountManagerAccessToken();
void setupAutomaticNetworking();
void setupICEHeartbeatForFullNetworking();
void sendHeartbeatToDataServer(const QString& networkAddress);
unsigned int countConnectedUsers();
@ -145,6 +151,8 @@ private:
HifiSockAddr _iceServerSocket;
QTimer* _iceHeartbeatTimer { nullptr }; // this looks like it dangles when created but it's parented to the DomainServer
friend class DomainGatekeeper;
};

View file

@ -193,7 +193,7 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection
qDebug() << "DomainServerSettingsManager postedObject -" << postedObject;
// we recurse one level deep below each group for the appropriate setting
recurseJSONObjectAndOverwriteSettings(postedObject, _configMap.getUserConfig());
recurseJSONObjectAndOverwriteSettings(postedObject);
// store whatever the current _settingsMap is to file
persistToFile();
@ -407,8 +407,9 @@ QJsonObject DomainServerSettingsManager::settingDescriptionFromGroup(const QJson
return QJsonObject();
}
void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject,
QVariantMap& settingsVariant) {
void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject) {
auto& settingsVariant = _configMap.getUserConfig();
// Iterate on the setting groups
foreach(const QString& rootKey, postedObject.keys()) {
QJsonValue rootValue = postedObject[rootKey];
@ -481,6 +482,9 @@ void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
settingsVariant.remove(rootKey);
}
}
// re-merge the user and master configs after a settings change
_configMap.mergeMasterAndUserConfigs();
}
void DomainServerSettingsManager::persistToFile() {

View file

@ -46,7 +46,7 @@ private slots:
private:
QJsonObject responseObjectForType(const QString& typeValue, bool isAuthenticated = false);
void recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, QVariantMap& settingsVariant);
void recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject);
void updateSetting(const QString& key, const QJsonValue& newValue, QVariantMap& settingMap,
const QJsonObject& settingDescription);
@ -56,6 +56,8 @@ private:
double _descriptionVersion;
QJsonArray _descriptionArray;
HifiConfigVariantMap _configMap;
friend class DomainServer;
};
#endif // hifi_DomainServerSettingsManager_h

View file

@ -134,12 +134,11 @@ var blacklist = [];
//we've created various ways of visualizing looking for and moving distant objects
var USE_ENTITY_LINES_FOR_SEARCHING = false;
var USE_OVERLAY_LINES_FOR_SEARCHING = true;
var USE_PARTICLE_BEAM_FOR_SEARCHING = false;
var USE_ENTITY_LINES_FOR_MOVING = false;
var USE_OVERLAY_LINES_FOR_MOVING = false;
var USE_PARTICLE_BEAM_FOR_MOVING = true;
var TEMPORARY_PARTICLE_BEAM_LIFETIME = 30;
var USE_SPOTLIGHT = false;
var USE_POINTLIGHT = false;
@ -475,24 +474,6 @@ function MyController(hand) {
}
};
this.handleParticleBeam = function(position, orientation, color) {
var rotation = Quat.angleAxis(0, {
x: 1,
y: 0,
z: 0
});
var finalRotation = Quat.multiply(orientation, rotation);
var lifespan = LINE_LENGTH / 10;
var speed = 5;
var spread = 2;
if (this.particleBeam === null) {
this.createParticleBeam(position, finalRotation, color, speed, spread, lifespan);
} else {
this.updateParticleBeam(position, finalRotation, color, speed, spread, lifespan);
}
};
this.handleDistantParticleBeam = function(handPosition, objectPosition, color) {
@ -505,7 +486,6 @@ function MyController(hand) {
var lifespan = distance / speed;
if (this.particleBeam === null) {
this.createParticleBeam(objectPosition, finalRotation, color, speed, spread, lifespan);
} else {
@ -520,6 +500,7 @@ function MyController(hand) {
isEmitting: true,
position: position,
visible: false,
lifetime: 60,
"name": "Particle Beam",
"color": color,
"maxParticles": 2000,
@ -555,15 +536,6 @@ function MyController(hand) {
},
"particleRadius": 0.015,
"radiusSpread": 0.005,
// "radiusStart": 0.01,
// "radiusFinish": 0.01,
// "colorSpread": {
// "red": 0,
// "green": 0,
// "blue": 0
// },
// "colorStart": color,
// "colorFinish": color,
"alpha": 1,
"alphaSpread": 0,
"alphaStart": 1,
@ -712,9 +684,8 @@ function MyController(hand) {
this.particleBeamOff = function() {
if (this.particleBeam !== null) {
Entities.editEntity(this.particleBeam, {
visible: false
})
Entities.deleteEntity(this.particleBeam);
this.particleBeam = null;
}
}
@ -744,7 +715,7 @@ function MyController(hand) {
this.overlayLineOff();
}
if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) {
if (USE_PARTICLE_BEAM_FOR_MOVING === true) {
this.particleBeamOff();
}
this.searchSphereOff();
@ -814,8 +785,7 @@ function MyController(hand) {
var distantPickRay = {
origin: PICK_WITH_HAND_RAY ? handPosition : Camera.position,
direction: PICK_WITH_HAND_RAY ? Quat.getUp(this.getHandRotation()) :
Vec3.mix(Quat.getUp(this.getHandRotation()), Quat.getFront(Camera.orientation), HAND_HEAD_MIX_RATIO),
direction: PICK_WITH_HAND_RAY ? Quat.getUp(this.getHandRotation()) : Vec3.mix(Quat.getUp(this.getHandRotation()), Quat.getFront(Camera.orientation), HAND_HEAD_MIX_RATIO),
length: PICK_MAX_DISTANCE
};
@ -925,11 +895,11 @@ function MyController(hand) {
if (typeof grabbableData.spatialKey === 'undefined') {
// We want to give a temporary position offset to this object so it is pulled close to hand
var intersectionPointToCenterDistance = Vec3.length(Vec3.subtract(intersection.intersection,
intersection.properties.position));
intersection.properties.position));
this.temporaryPositionOffset = Vec3.normalize(Vec3.subtract(intersection.properties.position, handPosition));
this.temporaryPositionOffset = Vec3.multiply(this.temporaryPositionOffset,
intersectionPointToCenterDistance *
FAR_TO_NEAR_GRAB_PADDING_FACTOR);
intersectionPointToCenterDistance *
FAR_TO_NEAR_GRAB_PADDING_FACTOR);
}
this.setState(this.state == STATE_SEARCHING ? STATE_DISTANCE_HOLDING : STATE_EQUIP);
this.searchSphereOff();
@ -946,10 +916,6 @@ function MyController(hand) {
this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
}
if (USE_PARTICLE_BEAM_FOR_SEARCHING === true) {
this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR);
}
var SEARCH_SPHERE_SIZE = 0.011;
var SEARCH_SPHERE_FOLLOW_RATE = 0.50;
@ -1160,7 +1126,6 @@ function MyController(hand) {
}
if (USE_PARTICLE_BEAM_FOR_MOVING === true) {
this.handleDistantParticleBeam(handPosition, grabbedProperties.position, INTERSECT_COLOR)
// this.handleDistantParticleBeam(handPosition, this.currentObjectPosition, INTERSECT_COLOR)
}
if (USE_POINTLIGHT === true) {
this.handlePointLight(this.grabbedEntity);
@ -1598,8 +1563,8 @@ function MyController(hand) {
if (this.actionID !== null) {
//sometimes we want things to stay right where they are when we let go.
var releaseVelocityData = getEntityCustomData(GRABBABLE_DATA_KEY,
this.grabbedEntity,
DEFAULT_GRABBABLE_DATA);
this.grabbedEntity,
DEFAULT_GRABBABLE_DATA);
if (releaseVelocityData.disableReleaseVelocity === true) {
Entities.deleteAction(this.grabbedEntity, this.actionID);
@ -1702,12 +1667,6 @@ function MyController(hand) {
var rightController = new MyController(RIGHT_HAND);
var leftController = new MyController(LEFT_HAND);
//preload the particle beams so that they are full length when you start searching
if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) {
rightController.createParticleBeam();
leftController.createParticleBeam();
}
var MAPPING_NAME = "com.highfidelity.handControllerGrab";
var mapping = Controller.newMapping(MAPPING_NAME);
@ -1784,31 +1743,7 @@ function cleanup() {
rightController.cleanup();
leftController.cleanup();
Controller.disableMapping(MAPPING_NAME);
if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) {
Script.update.disconnect(renewParticleBeamLifetimes);
}
}
Script.scriptEnding.connect(cleanup);
Script.update.connect(update);
// particle systems can end up hanging around if a user crashes or something else causes controller cleanup not to get called.
// we can't create the search system on-demand since it takes some time for the particles to reach their entire length.
// thus the system cannot have a fixed lifetime. this loop updates the lifetimes and will stop updating if a user crashes.
if (USE_PARTICLE_BEAM_FOR_SEARCHING === true || USE_PARTICLE_BEAM_FOR_MOVING === true) {
Script.update.connect(renewParticleBeamLifetimes)
}
var sinceLastParticleLifetimeUpdate = 0;
function renewParticleBeamLifetimes(deltaTime) {
//debounce this call since we don't want it 60x a second
sinceLastParticleLifetimeUpdate = sinceLastParticleLifetimeUpdate + deltaTime;
if (sinceLastParticleLifetimeUpdate > TEMPORARY_PARTICLE_BEAM_LIFETIME - 2) {
sinceLastParticleLifetimeUpdate = 0;
} else {
return;
}
rightController.renewParticleBeamLifetime();
leftController.renewParticleBeamLifetime();
}

View file

@ -0,0 +1,66 @@
//
// sphereLodTest.js
// examples/tests
//
// Created by Eric Levin on 1/21/16.
// Copyright 2016 High Fidelity, Inc.
// A test script for testing LODing of sphere entities and sphere overlays
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
MyAvatar.orientation = Quat.fromPitchYawRollDegrees(0, 0, 0);
orientation = Quat.safeEulerAngles(MyAvatar.orientation);
orientation.x = 0;
orientation = Quat.fromVec3Degrees(orientation);
var tablePosition = Vec3.sum(MyAvatar.position, Quat.getFront(orientation));
tablePosition.y += 0.5;
var tableDimensions = {
x: 1,
y: 0.2,
z: 1
};
var table = Entities.addEntity({
type: "Box",
position: tablePosition,
dimensions: tableDimensions,
color: {
red: 70,
green: 21,
blue: 21
}
});
var sphereDimensions = {x: 0.01, y: 0.01, z: 0.01};
var entitySpherePosition = Vec3.sum(tablePosition, {x: 0, y: tableDimensions.y/2 + sphereDimensions.y/2, z: 0});
var entitySphere = Entities.addEntity({
type: "Sphere",
position: entitySpherePosition,
color: {red: 200, green: 20, blue: 200},
dimensions: sphereDimensions
});
var overlaySpherePosition = Vec3.sum(tablePosition, {x: sphereDimensions.x, y: tableDimensions.y/2 + sphereDimensions.y/2, z: 0});
var overlaySphere = Overlays.addOverlay("sphere", {
position: overlaySpherePosition,
size: 0.01,
color: { red: 20, green: 200, blue: 0},
alpha: 1.0,
solid: true,
});
function cleanup() {
Entities.deleteEntity(table);
Entities.deleteEntity(entitySphere);
Overlays.deleteOverlay(overlaySphere);
}
Script.scriptEnding.connect(cleanup);

View file

@ -9,8 +9,8 @@ var pistol = Entities.addEntity({
position: center,
dimensions: {
x: 0.05,
y: .23,
z: .36
y: 0.23,
z: 0.36
},
script: scriptURL,
color: {
@ -20,9 +20,14 @@ var pistol = Entities.addEntity({
},
shapeType: 'box',
dynamic: true,
gravity: {x: 0, y: -5.0, z: 0},
gravity: {
x: 0,
y: -5.0,
z: 0
},
restitution: 0,
collisionSoundURL: "https://s3.amazonaws.com/hifi-public/sounds/Guns/Gun_Drop_and_Metalli_1.wav",
damping:0.5,
collisionSoundURL: "http://hifi-content.s3.amazonaws.com/james/pistol/sounds/drop.wav",
userData: JSON.stringify({
grabbableKey: {
spatialKey: {

View file

@ -1,6 +1,5 @@
//
// pistol.js
// examples/toybox/entityScripts
//
// Created by Eric Levin on11/11/15.
// Copyright 2015 High Fidelity, Inc.
@ -16,7 +15,6 @@
Script.include("../../libraries/constants.js");
var _this;
// if the trigger value goes below this while held, the can will stop spraying. if it goes above, it will spray
var DISABLE_LASER_THRESHOLD = 0.2;
var TRIGGER_CONTROLS = [
Controller.Standard.LT,

View file

@ -27,7 +27,7 @@ IceServer::IceServer(int argc, char* argv[]) :
_id(QUuid::createUuid()),
_serverSocket(),
_activePeers(),
_httpManager(ICE_SERVER_MONITORING_PORT, QString("%1/web/").arg(QCoreApplication::applicationDirPath()), this)
_httpManager(QHostAddress::AnyIPv4, ICE_SERVER_MONITORING_PORT, QString("%1/web/").arg(QCoreApplication::applicationDirPath()), this)
{
// start the ice-server socket
qDebug() << "ice-server socket is listening on" << ICE_SERVER_DEFAULT_PORT;

View file

@ -24,8 +24,6 @@ if (WIN32)
add_definitions(-DWINDOWS_LEAN_AND_MEAN) # needed to make sure windows doesn't go to crazy with its defines
endif()
include_application_version()
# grab the implementation and header files from src dirs
file(GLOB_RECURSE INTERFACE_SRCS "src/*.cpp" "src/*.h")
GroupSources("src")
@ -65,22 +63,23 @@ set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
if (APPLE)
# configure CMake to use a custom Info.plist
SET_TARGET_PROPERTIES( ${this_target} PROPERTIES MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in )
set_target_properties(${this_target} PROPERTIES MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in)
set(MACOSX_BUNDLE_BUNDLE_NAME Interface)
set(MACOSX_BUNDLE_GUI_IDENTIFIER io.highfidelity.Interface)
if (UPPER_CMAKE_BUILD_TYPE MATCHES RELEASE OR UPPER_CMAKE_BUILD_TYPE MATCHES RELWITHDEBINFO)
set(ICON_FILENAME "interface.icns")
if (PRODUCTION_BUILD)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.interface)
else ()
set(ICON_FILENAME "interface-beta.icns")
if (DEV_BUILD)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.interface-dev)
elseif (PR_BUILD)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.interface-pr)
endif ()
endif ()
# set how the icon shows up in the Info.plist file
SET(MACOSX_BUNDLE_ICON_FILE "${ICON_FILENAME}")
set(MACOSX_BUNDLE_ICON_FILE "${INTERFACE_ICON_FILENAME}")
# set where in the bundle to put the resources file
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/icon/${ICON_FILENAME} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/icon/${INTERFACE_ICON_FILENAME} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
set(DISCOVERED_RESOURCES "")
@ -90,27 +89,36 @@ if (APPLE)
# append the discovered resources to our list of interface sources
list(APPEND INTERFACE_SRCS ${DISCOVERED_RESOURCES})
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/icon/${ICON_FILENAME}")
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/icon/${INTERFACE_ICON_FILENAME}")
endif()
# create the executable, make it a bundle on OS X
if (APPLE)
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
# make sure the output name for the .app bundle is correct
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${INTERFACE_BUNDLE_NAME})
elseif(WIN32)
add_executable(${TARGET_NAME} WIN32 ${INTERFACE_SRCS} ${QM})
# configure an rc file for the chosen icon
set(CONFIGURE_ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/icon/${INTERFACE_ICON_FILENAME}")
set(CONFIGURE_ICON_RC_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Icon.rc")
configure_file("${HF_CMAKE_DIR}/templates/Icon.rc.in" ${CONFIGURE_ICON_RC_OUTPUT})
# add an executable that also has the icon itself and the configured rc file as resources
add_executable(${TARGET_NAME} WIN32 ${INTERFACE_SRCS} ${QM} ${CONFIGURE_ICON_RC_OUTPUT})
else()
add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM})
endif()
# These are external plugins, but we need to do the 'add dependency' here so that their
# binary directories get added to the fixup path
add_dependency_external_projects(sixense)
add_dependency_external_projects(sdl2)
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes")
if (WIN32)
add_dependency_external_projects(OpenVR)
endif()
if(WIN32 OR APPLE)
add_dependency_external_projects(neuron)
# These are external plugins, but we need to do the 'add dependency' here so that their
# binary directories get added to the fixup path
add_dependency_external_projects(sixense)
add_dependency_external_projects(sdl2)
add_dependency_external_projects(OpenVR)
add_dependency_external_projects(neuron)
endif()
# disable /OPT:REF and /OPT:ICF for the Debug builds
@ -125,7 +133,10 @@ link_hifi_libraries(shared octree environment gpu gl procedural model render
recording fbx networking model-networking entities avatars
audio audio-client animation script-engine physics
render-utils entities-renderer ui auto-updater
controllers plugins display-plugins input-plugins )
controllers plugins display-plugins input-plugins)
# include the binary directory of render-utils for shader includes
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/libraries/render-utils")
#fixme find a way to express faceshift as a plugin
target_bullet()
@ -133,7 +144,7 @@ target_glew()
target_opengl()
if (WIN32 OR APPLE)
target_faceshift()
target_faceshift()
endif()
# perform standard include and linking for found externals
@ -187,7 +198,7 @@ target_link_libraries(
# Issue causes build failure unless we add this directory.
# See https://bugreports.qt.io/browse/QTBUG-43351
if (WIN32)
add_paths_to_fixup_libs(${Qt5_DIR}/../../../plugins/qtwebengine)
add_paths_to_fixup_libs(${Qt5_DIR}/../../../plugins/qtwebengine)
endif()
# assume we are using a Qt build without bearer management
@ -200,30 +211,62 @@ if (APPLE)
target_link_libraries(${TARGET_NAME} ${OpenGL} ${AppKit})
# install command for OS X bundle
INSTALL(TARGETS ${TARGET_NAME}
BUNDLE DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/install" COMPONENT Runtime
RUNTIME DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/install" COMPONENT Runtime
# setup install of OS X interface bundle
install(TARGETS ${TARGET_NAME}
BUNDLE DESTINATION ${INTERFACE_INSTALL_DIR}
COMPONENT ${CLIENT_COMPONENT}
)
set(SCRIPTS_INSTALL_DIR "${INTERFACE_INSTALL_APP_PATH}/Contents/Resources")
# call the fixup_interface macro to add required bundling commands for installation
fixup_interface()
else (APPLE)
# copy the resources files beside the executable
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${PROJECT_SOURCE_DIR}/resources"
$<TARGET_FILE_DIR:${TARGET_NAME}>/resources
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${CMAKE_SOURCE_DIR}/examples"
$<TARGET_FILE_DIR:${TARGET_NAME}>/scripts
)
# link target to external libraries
if (WIN32)
target_link_libraries(${TARGET_NAME} wsock32.lib Winmm.lib)
else (WIN32)
# Nothing else required on linux apparently
# setup install of executable and things copied by fixup/windeployqt
install(
FILES "$<TARGET_FILE_DIR:${TARGET_NAME}>/"
DESTINATION ${INTERFACE_INSTALL_DIR}
COMPONENT ${CLIENT_COMPONENT}
)
set(SCRIPTS_INSTALL_DIR "${INTERFACE_INSTALL_DIR}")
set(EXECUTABLE_COMPONENT ${CLIENT_COMPONENT})
optional_win_executable_signing()
endif()
endif (APPLE)
if (WIN32)
set(EXTRA_DEPLOY_OPTIONS "--qmldir ${PROJECT_SOURCE_DIR}/resources/qml")
if (SCRIPTS_INSTALL_DIR)
# setup install of scripts beside interface executable
install(
DIRECTORY "${CMAKE_SOURCE_DIR}/examples/"
DESTINATION ${SCRIPTS_INSTALL_DIR}/scripts
COMPONENT ${CLIENT_COMPONENT}
)
endif()
package_libraries_for_deployment()
consolidate_stack_components()
if (WIN32)
set(EXTRA_DEPLOY_OPTIONS "--qmldir ${PROJECT_SOURCE_DIR}/resources/qml")
set(TARGET_INSTALL_DIR ${INTERFACE_INSTALL_DIR})
set(TARGET_INSTALL_COMPONENT ${CLIENT_COMPONENT})
manually_install_ssl_eay()
package_libraries_for_deployment()
endif()

View file

@ -36,6 +36,9 @@
#include <QtGui/QMouseEvent>
#include <QtGui/QDesktopServices>
#include <QtNetwork/QLocalSocket>
#include <QtNetwork/QLocalServer>
#include <QtQml/QQmlContext>
#include <QtQml/QQmlEngine>
#include <QtQuick/QQuickWindow>
@ -57,7 +60,7 @@
#include <ResourceScriptingInterface.h>
#include <AccountManager.h>
#include <AddressManager.h>
#include <ApplicationVersion.h>
#include <BuildInfo.h>
#include <AssetClient.h>
#include <AssetUpload.h>
#include <AutoUpdater.h>
@ -302,7 +305,7 @@ bool setupEssentials(int& argc, char** argv) {
listenPort = atoi(portStr);
}
// Set build version
QCoreApplication::setApplicationVersion(BUILD_VERSION);
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
Setting::preInit();
@ -5175,3 +5178,30 @@ void Application::setActiveDisplayPlugin(const QString& pluginName) {
}
updateDisplayMode();
}
void Application::handleLocalServerConnection() {
auto server = qobject_cast<QLocalServer*>(sender());
qDebug() << "Got connection on local server from additional instance - waiting for parameters";
auto socket = server->nextPendingConnection();
connect(socket, &QLocalSocket::readyRead, this, &Application::readArgumentsFromLocalSocket);
qApp->getWindow()->raise();
qApp->getWindow()->activateWindow();
}
void Application::readArgumentsFromLocalSocket() {
auto socket = qobject_cast<QLocalSocket*>(sender());
auto message = socket->readAll();
socket->deleteLater();
qDebug() << "Read from connection: " << message;
// If we received a message, try to open it as a URL
if (message.length() > 0) {
qApp->openUrl(QString::fromUtf8(message));
}
}

View file

@ -102,15 +102,15 @@ public:
Application(int& argc, char** argv, QElapsedTimer& startup_time);
~Application();
void postLambdaEvent(std::function<void()> f);
void postLambdaEvent(std::function<void()> f) override;
void initializeGL();
void initializeUi();
void paintGL();
void resizeGL();
bool event(QEvent* event);
bool eventFilter(QObject* object, QEvent* event);
bool event(QEvent* event) override;
bool eventFilter(QObject* object, QEvent* event) override;
glm::uvec2 getCanvasSize() const;
glm::uvec2 getUiSize() const;
@ -129,7 +129,7 @@ public:
// passes, mirror window passes, etc
ViewFrustum* getDisplayViewFrustum();
const ViewFrustum* getDisplayViewFrustum() const;
ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; }
ViewFrustum* getShadowViewFrustum() override { return &_shadowViewFrustum; }
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
EntityTreeRenderer* getEntities() { return DependencyManager::get<EntityTreeRenderer>().data(); }
QUndoStack* getUndoStack() { return &_undoStack; }
@ -164,7 +164,7 @@ public:
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine);
virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override;
QImage renderAvatarBillboard(RenderArgs* renderArgs);
@ -208,9 +208,9 @@ public:
void setMaxOctreePacketsPerSecond(int maxOctreePPS);
int getMaxOctreePacketsPerSecond();
render::ScenePointer getMain3DScene() { return _main3DScene; }
render::ScenePointer getMain3DScene() override { return _main3DScene; }
render::ScenePointer getMain3DScene() const { return _main3DScene; }
render::EnginePointer getRenderEngine() { return _renderEngine; }
render::EnginePointer getRenderEngine() override { return _renderEngine; }
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
const QRect& getMirrorViewRect() const { return _mirrorViewRect; }
@ -245,6 +245,9 @@ public slots:
void toggleLogDialog();
void toggleRunningScriptsWidget();
void handleLocalServerConnection();
void readArgumentsFromLocalSocket();
void showFriendsWindow();
void packageModel();

View file

@ -22,11 +22,11 @@
#include <RenderArgs.h>
#include <ViewFrustum.h>
#include "../../libraries/render-utils/stars_vert.h"
#include "../../libraries/render-utils/stars_frag.h"
#include <stars_vert.h>
#include <stars_frag.h>
#include "../../libraries/render-utils/standardTransformPNTC_vert.h"
#include "../../libraries/render-utils/starsGrid_frag.h"
#include <standardTransformPNTC_vert.h>
#include <starsGrid_frag.h>
//static const float TILT = 0.23f;
static const float TILT = 0.0f;

View file

@ -30,7 +30,7 @@ public:
virtual void updateActionWorker(float deltaTimeStep) override;
QByteArray serialize() const;
QByteArray serialize() const override;
virtual void deserialize(QByteArray serializedArguments) override;
virtual bool shouldSuppressLocationEdits() override { return _active && !_ownerEntity.expired(); }

View file

@ -11,7 +11,10 @@
#include <QCommandLineParser>
#include <QDebug>
#include <QDir>
#include <QLocalSocket>
#include <QLocalServer>
#include <QSettings>
#include <QSharedMemory>
#include <QTranslator>
#include <SharedUtil.h>
@ -19,65 +22,65 @@
#include "AddressManager.h"
#include "Application.h"
#include "InterfaceLogging.h"
#ifdef Q_OS_WIN
static BOOL CALLBACK enumWindowsCallback(HWND hWnd, LPARAM lParam) {
const UINT TIMEOUT = 200; // ms
DWORD_PTR response;
LRESULT result = SendMessageTimeout(hWnd, UWM_IDENTIFY_INSTANCES, 0, 0, SMTO_BLOCK | SMTO_ABORTIFHUNG, TIMEOUT, &response);
if (result == 0) { // Timeout; continue search.
return TRUE;
}
if (response == UWM_IDENTIFY_INSTANCES) {
HWND* target = (HWND*)lParam;
*target = hWnd;
return FALSE; // Found; terminate search.
}
return TRUE; // Not found; continue search.
}
#endif
#include "MainWindow.h"
int main(int argc, const char* argv[]) {
QString applicationName = "High Fidelity Interface - " + qgetenv("USERNAME");
bool instanceMightBeRunning = true;
#ifdef Q_OS_WIN
// Run only one instance of Interface at a time.
HANDLE mutex = CreateMutex(NULL, FALSE, "High Fidelity Interface - " + qgetenv("USERNAME"));
DWORD result = GetLastError();
if (result == ERROR_ALREADY_EXISTS || result == ERROR_ACCESS_DENIED) {
// Interface is already running.
HWND otherInstance = NULL;
EnumWindows(enumWindowsCallback, (LPARAM)&otherInstance);
if (otherInstance) {
// Show other instance.
SendMessage(otherInstance, UWM_SHOW_APPLICATION, 0, 0);
// Try to create a shared memory block - if it can't be created, there is an instance of
// interface already running. We only do this on Windows for now because of the potential
// for crashed instances to leave behind shared memory instances on unix.
QSharedMemory sharedMemory { applicationName };
instanceMightBeRunning = !sharedMemory.create(1, QSharedMemory::ReadOnly);
#endif
// Send command line --url value to other instance.
if (argc >= 3) {
QStringList arguments;
for (int i = 0; i < argc; i += 1) {
arguments << argv[i];
}
if (instanceMightBeRunning) {
// Try to connect and send message to existing interface instance
QLocalSocket socket;
QCommandLineParser parser;
QCommandLineOption urlOption("url", "", "value");
parser.addOption(urlOption);
parser.process(arguments);
socket.connectToServer(applicationName);
if (parser.isSet(urlOption)) {
QUrl url = QUrl(parser.value(urlOption));
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
QByteArray urlBytes = url.toString().toLatin1();
const char* urlChars = urlBytes.data();
COPYDATASTRUCT cds;
cds.cbData = urlBytes.length() + 1;
cds.lpData = (PVOID)urlChars;
SendMessage(otherInstance, WM_COPYDATA, 0, (LPARAM)&cds);
static const int LOCAL_SERVER_TIMEOUT_MS = 500;
// Try to connect - if we can't connect, interface has probably just gone down
if (socket.waitForConnected(LOCAL_SERVER_TIMEOUT_MS)) {
QStringList arguments;
for (int i = 0; i < argc; ++i) {
arguments << argv[i];
}
QCommandLineParser parser;
QCommandLineOption urlOption("url", "", "value");
parser.addOption(urlOption);
parser.process(arguments);
if (parser.isSet(urlOption)) {
QUrl url = QUrl(parser.value(urlOption));
if (url.isValid() && url.scheme() == HIFI_URL_SCHEME) {
qDebug() << "Writing URL to local socket";
socket.write(url.toString().toUtf8());
if (!socket.waitForBytesWritten(5000)) {
qDebug() << "Error writing URL to local socket";
}
}
}
socket.close();
qDebug() << "Interface instance appears to be running, exiting";
return EXIT_SUCCESS;
}
return 0;
}
#ifdef Q_OS_WIN
return EXIT_SUCCESS;
#endif
}
QElapsedTimer startupTime;
startupTime.start();
@ -102,18 +105,25 @@ int main(int argc, const char* argv[]) {
QSettings::setDefaultFormat(QSettings::IniFormat);
Application app(argc, const_cast<char**>(argv), startupTime);
// Setup local server
QLocalServer server { &app };
// We failed to connect to a local server, so we remove any existing servers.
server.removeServer(applicationName);
server.listen(applicationName);
QObject::connect(&server, &QLocalServer::newConnection, &app, &Application::handleLocalServerConnection);
QTranslator translator;
translator.load("i18n/interface_en");
app.installTranslator(&translator);
qCDebug(interfaceapp, "Created QT Application.");
exitCode = app.exec();
server.close();
}
Application::shutdownPlugins();
#ifdef Q_OS_WIN
ReleaseMutex(mutex);
#endif
qCDebug(interfaceapp, "Normal exit.");
return exitCode;

View file

@ -23,8 +23,9 @@
const int SOCKET_ERROR_EXIT_CODE = 2;
const int SOCKET_CHECK_INTERVAL_IN_MS = 30000;
HTTPManager::HTTPManager(quint16 port, const QString& documentRoot, HTTPRequestHandler* requestHandler, QObject* parent) :
HTTPManager::HTTPManager(const QHostAddress& listenAddress, quint16 port, const QString& documentRoot, HTTPRequestHandler* requestHandler, QObject* parent) :
QTcpServer(parent),
_listenAddress(listenAddress),
_documentRoot(documentRoot),
_requestHandler(requestHandler),
_port(port)
@ -178,7 +179,7 @@ void HTTPManager::isTcpServerListening() {
bool HTTPManager::bindSocket() {
qCDebug(embeddedwebserver) << "Attempting to bind TCP socket on port " << QString::number(_port);
if (listen(QHostAddress::AnyIPv4, _port)) {
if (listen(_listenAddress, _port)) {
qCDebug(embeddedwebserver) << "TCP socket is listening on" << serverAddress() << "and port" << serverPort();
return true;

View file

@ -33,7 +33,7 @@ class HTTPManager : public QTcpServer, public HTTPRequestHandler {
Q_OBJECT
public:
/// Initializes the manager.
HTTPManager(quint16 port, const QString& documentRoot, HTTPRequestHandler* requestHandler = NULL, QObject* parent = 0);
HTTPManager(const QHostAddress& listenAddress, quint16 port, const QString& documentRoot, HTTPRequestHandler* requestHandler = NULL, QObject* parent = 0);
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler = false);
@ -49,6 +49,7 @@ protected:
virtual void incomingConnection(qintptr socketDescriptor);
virtual bool requestHandledByRequestHandler(HTTPConnection* connection, const QUrl& url);
QHostAddress _listenAddress;
QString _documentRoot;
HTTPRequestHandler* _requestHandler;
QTimer* _isListeningTimer;

View file

@ -15,9 +15,9 @@
#include "HTTPSManager.h"
HTTPSManager::HTTPSManager(quint16 port, const QSslCertificate& certificate, const QSslKey& privateKey,
HTTPSManager::HTTPSManager(QHostAddress listenAddress, quint16 port, const QSslCertificate& certificate, const QSslKey& privateKey,
const QString& documentRoot, HTTPSRequestHandler* requestHandler, QObject* parent) :
HTTPManager(port, documentRoot, requestHandler, parent),
HTTPManager(listenAddress, port, documentRoot, requestHandler, parent),
_certificate(certificate),
_privateKey(privateKey),
_sslRequestHandler(requestHandler)

View file

@ -26,7 +26,8 @@ public:
class HTTPSManager : public HTTPManager, public HTTPSRequestHandler {
Q_OBJECT
public:
HTTPSManager(quint16 port,
HTTPSManager(QHostAddress listenAddress,
quint16 port,
const QSslCertificate& certificate,
const QSslKey& privateKey,
const QString& documentRoot,
@ -35,12 +36,12 @@ public:
void setCertificate(const QSslCertificate& certificate) { _certificate = certificate; }
void setPrivateKey(const QSslKey& privateKey) { _privateKey = privateKey; }
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler = false);
bool handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url, bool skipSubHandler = false);
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler = false) override;
bool handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url, bool skipSubHandler = false) override;
protected:
void incomingConnection(qintptr socketDescriptor);
bool requestHandledByRequestHandler(HTTPConnection* connection, const QUrl& url);
void incomingConnection(qintptr socketDescriptor) override;
bool requestHandledByRequestHandler(HTTPConnection* connection, const QUrl& url) override;
private:
QSslCertificate _certificate;
QSslKey _privateKey;

View file

@ -73,8 +73,8 @@ private:
#define SIMPLE_RENDERABLE() \
public: \
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { return _renderHelper.addToScene(self, scene, pendingChanges); } \
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { _renderHelper.removeFromScene(self, scene, pendingChanges); } \
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override { return _renderHelper.addToScene(self, scene, pendingChanges); } \
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) override { _renderHelper.removeFromScene(self, scene, pendingChanges); } \
private: \
SimpleRenderableEntityItem _renderHelper;

View file

@ -28,9 +28,9 @@ public:
static void createPipeline();
RenderablePolyLineEntityItem(const EntityItemID& entityItemID);
virtual void render(RenderArgs* args);
virtual void render(RenderArgs* args) override;
virtual void update(const quint64& now) override;
virtual bool needsToCallUpdate() const { return true; };
virtual bool needsToCallUpdate() const override { return true; };
SIMPLE_RENDERABLE();

View file

@ -2,6 +2,8 @@ set(TARGET_NAME networking)
setup_hifi_library(Network)
link_hifi_libraries(shared)
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes")
if (WIN32)
# we need ws2_32.lib on windows, but it's static so we don't bubble it up
target_link_libraries(${TARGET_NAME} ws2_32.lib)
@ -31,4 +33,3 @@ endif (UNIX)
# append tbb includes to our list of includes to bubble
target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${TBB_INCLUDE_DIRS})
include_application_version()

View file

@ -12,11 +12,13 @@
#include "udt/PacketHeaders.h"
#include "SharedUtil.h"
#include "UUID.h"
#include "ServerPathUtils.h"
#include <QtCore/QDataStream>
#include <ApplicationVersion.h>
#include <BuildInfo.h>
#include "Assignment.h"
#include <QtCore/QStandardPaths>
Assignment::Type Assignment::typeForNodeType(NodeType_t nodeType) {
switch (nodeType) {
@ -64,7 +66,7 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, const
// this is a newly created assignment, generate a random UUID
_uuid = QUuid::createUuid();
} else if (_command == Assignment::RequestCommand) {
_nodeVersion = BUILD_VERSION;
_nodeVersion = BuildInfo::VERSION;
}
}

View file

@ -95,16 +95,16 @@ void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) {
if (hostInfo.error() != QHostInfo::NoError) {
qCDebug(networking) << "Lookup failed for" << hostInfo.lookupId() << ":" << hostInfo.errorString();
emit lookupFailed();
}
foreach(const QHostAddress& address, hostInfo.addresses()) {
// just take the first IPv4 address
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
_address = address;
qCDebug(networking) << "QHostInfo lookup result for"
<< hostInfo.hostName() << "with lookup ID" << hostInfo.lookupId() << "is" << address.toString();
emit lookupCompleted();
break;
} else {
foreach(const QHostAddress& address, hostInfo.addresses()) {
// just take the first IPv4 address
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
_address = address;
qCDebug(networking) << "QHostInfo lookup result for"
<< hostInfo.hostName() << "with lookup ID" << hostInfo.lookupId() << "is" << address.toString();
emit lookupCompleted();
break;
}
}
}
}

View file

@ -110,6 +110,14 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short
_nodeSocket.setPacketFilterOperator(std::bind(&LimitedNodeList::isPacketVerified, this, _1));
_packetStatTimer.start();
if (_stunSockAddr.getAddress().isNull()) {
// we don't know the stun server socket yet, add it to unfiltered once known
connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::addSTUNHandlerToUnfiltered);
} else {
// we know the stun server socket, add it to unfiltered now
addSTUNHandlerToUnfiltered();
}
}
void LimitedNodeList::setSessionUUID(const QUuid& sessionUUID) {
@ -664,46 +672,48 @@ const int NUM_BYTES_STUN_HEADER = 20;
void LimitedNodeList::sendSTUNRequest() {
const int NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL = 10;
if (!_stunSockAddr.isNull()) {
const int NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL = 10;
if (!_hasCompletedInitialSTUN) {
qCDebug(networking) << "Sending intial stun request to" << STUN_SERVER_HOSTNAME;
if (!_hasCompletedInitialSTUN) {
qCDebug(networking) << "Sending intial stun request to" << STUN_SERVER_HOSTNAME;
if (_numInitialSTUNRequests > NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL) {
// we're still trying to do our initial STUN we're over the fail threshold
stopInitialSTUNUpdate(false);
if (_numInitialSTUNRequests > NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL) {
// we're still trying to do our initial STUN we're over the fail threshold
stopInitialSTUNUpdate(false);
}
++_numInitialSTUNRequests;
}
++_numInitialSTUNRequests;
char stunRequestPacket[NUM_BYTES_STUN_HEADER];
int packetIndex = 0;
const uint32_t RFC_5389_MAGIC_COOKIE_NETWORK_ORDER = htonl(RFC_5389_MAGIC_COOKIE);
// leading zeros + message type
const uint16_t REQUEST_MESSAGE_TYPE = htons(0x0001);
memcpy(stunRequestPacket + packetIndex, &REQUEST_MESSAGE_TYPE, sizeof(REQUEST_MESSAGE_TYPE));
packetIndex += sizeof(REQUEST_MESSAGE_TYPE);
// message length (no additional attributes are included)
uint16_t messageLength = 0;
memcpy(stunRequestPacket + packetIndex, &messageLength, sizeof(messageLength));
packetIndex += sizeof(messageLength);
memcpy(stunRequestPacket + packetIndex, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER));
packetIndex += sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER);
// transaction ID (random 12-byte unsigned integer)
const uint NUM_TRANSACTION_ID_BYTES = 12;
QUuid randomUUID = QUuid::createUuid();
memcpy(stunRequestPacket + packetIndex, randomUUID.toRfc4122().data(), NUM_TRANSACTION_ID_BYTES);
flagTimeForConnectionStep(ConnectionStep::SendSTUNRequest);
_nodeSocket.writeDatagram(stunRequestPacket, sizeof(stunRequestPacket), _stunSockAddr);
}
char stunRequestPacket[NUM_BYTES_STUN_HEADER];
int packetIndex = 0;
const uint32_t RFC_5389_MAGIC_COOKIE_NETWORK_ORDER = htonl(RFC_5389_MAGIC_COOKIE);
// leading zeros + message type
const uint16_t REQUEST_MESSAGE_TYPE = htons(0x0001);
memcpy(stunRequestPacket + packetIndex, &REQUEST_MESSAGE_TYPE, sizeof(REQUEST_MESSAGE_TYPE));
packetIndex += sizeof(REQUEST_MESSAGE_TYPE);
// message length (no additional attributes are included)
uint16_t messageLength = 0;
memcpy(stunRequestPacket + packetIndex, &messageLength, sizeof(messageLength));
packetIndex += sizeof(messageLength);
memcpy(stunRequestPacket + packetIndex, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER));
packetIndex += sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER);
// transaction ID (random 12-byte unsigned integer)
const uint NUM_TRANSACTION_ID_BYTES = 12;
QUuid randomUUID = QUuid::createUuid();
memcpy(stunRequestPacket + packetIndex, randomUUID.toRfc4122().data(), NUM_TRANSACTION_ID_BYTES);
flagTimeForConnectionStep(ConnectionStep::SendSTUNRequest);
_nodeSocket.writeDatagram(stunRequestPacket, sizeof(stunRequestPacket), _stunSockAddr);
}
void LimitedNodeList::processSTUNResponse(std::unique_ptr<udt::BasePacket> packet) {
@ -788,38 +798,50 @@ void LimitedNodeList::processSTUNResponse(std::unique_ptr<udt::BasePacket> packe
}
void LimitedNodeList::startSTUNPublicSocketUpdate() {
assert(!_initialSTUNTimer);
if (!_initialSTUNTimer ) {
// setup our initial STUN timer here so we can quickly find out our public IP address
_initialSTUNTimer = new QTimer { this };
if (!_initialSTUNTimer) {
// if we don't know the STUN IP yet we need to have ourselves be called once it is known
connect(_initialSTUNTimer.data(), &QTimer::timeout, this, &LimitedNodeList::sendSTUNRequest);
const int STUN_INITIAL_UPDATE_INTERVAL_MSECS = 250;
_initialSTUNTimer->setInterval(STUN_INITIAL_UPDATE_INTERVAL_MSECS);
// if we don't know the STUN IP yet we need to wait until it is known to start STUN requests
if (_stunSockAddr.getAddress().isNull()) {
connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::startSTUNPublicSocketUpdate);
connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::addSTUNHandlerToUnfiltered);
// in case we just completely fail to lookup the stun socket - add a 10s timeout that will trigger the fail case
// if we fail to lookup the socket then timeout the STUN address lookup
connect(&_stunSockAddr, &HifiSockAddr::lookupFailed, this, &LimitedNodeList::possiblyTimeoutSTUNAddressLookup);
// immediately send a STUN request once we know the socket
connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::sendSTUNRequest);
// start the initial STUN timer once we know the socket
connect(&_stunSockAddr, SIGNAL(lookupCompleted()), _initialSTUNTimer, SLOT(start()));
// in case we just completely fail to lookup the stun socket - add a 10s single shot that will trigger the fail case
const quint64 STUN_DNS_LOOKUP_TIMEOUT_MSECS = 10 * 1000;
QTimer* stunLookupFailTimer = new QTimer(this);
connect(stunLookupFailTimer, &QTimer::timeout, this, &LimitedNodeList::possiblyTimeoutSTUNAddressLookup);
stunLookupFailTimer->start(STUN_DNS_LOOKUP_TIMEOUT_MSECS);
QTimer* lookupTimeoutTimer = new QTimer { this };
lookupTimeoutTimer->setSingleShot(true);
connect(lookupTimeoutTimer, &QTimer::timeout, this, &LimitedNodeList::possiblyTimeoutSTUNAddressLookup);
// delete the lookup timeout timer once it has fired
connect(lookupTimeoutTimer, &QTimer::timeout, lookupTimeoutTimer, &QTimer::deleteLater);
lookupTimeoutTimer->start(STUN_DNS_LOOKUP_TIMEOUT_MSECS);
} else {
// setup our initial STUN timer here so we can quickly find out our public IP address
_initialSTUNTimer = new QTimer(this);
_initialSTUNTimer->start();
connect(_initialSTUNTimer.data(), &QTimer::timeout, this, &LimitedNodeList::sendSTUNRequest);
const int STUN_INITIAL_UPDATE_INTERVAL_MSECS = 250;
_initialSTUNTimer->start(STUN_INITIAL_UPDATE_INTERVAL_MSECS);
// send an initial STUN request right away
sendSTUNRequest();
// send an initial STUN request right away
sendSTUNRequest();
}
}
}
void LimitedNodeList::possiblyTimeoutSTUNAddressLookup() {
if (_stunSockAddr.getAddress().isNull()) {
if (_stunSockAddr.isNull()) {
// our stun address is still NULL, but we've been waiting for long enough - time to force a fail
stopInitialSTUNUpdate(false);
}
@ -859,7 +881,7 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) {
// Or, if we failed - if will check if we can eventually get a public socket
const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000;
QTimer* stunOccasionalTimer = new QTimer(this);
QTimer* stunOccasionalTimer = new QTimer { this };
connect(stunOccasionalTimer, &QTimer::timeout, this, &LimitedNodeList::sendSTUNRequest);
stunOccasionalTimer->start(STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS);

View file

@ -293,6 +293,7 @@ protected:
bool _thisNodeCanRez;
QPointer<QTimer> _initialSTUNTimer;
int _numInitialSTUNRequests = 0;
bool _hasCompletedInitialSTUN = false;
quint64 _firstSTUNTime = 0;

View file

@ -19,7 +19,6 @@
#include <QtCore/QThread>
#include <QtNetwork/QHostInfo>
#include <ApplicationVersion.h>
#include <LogHandler.h>
#include <UUID.h>

View file

@ -40,8 +40,8 @@ public:
virtual void updateActionWorker(float deltaTimeStep) = 0;
// these are from btActionInterface
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep);
virtual void debugDraw(btIDebugDraw* debugDrawer);
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) override;
virtual void debugDraw(btIDebugDraw* debugDrawer) override;
virtual QByteArray serialize() const override = 0;
virtual void deserialize(QByteArray serializedArguments) override = 0;

View file

@ -9,8 +9,11 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "HifiConfigVariantMap.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonArray>
@ -18,8 +21,8 @@
#include <QtCore/QStandardPaths>
#include <QtCore/QVariant>
#include "ServerPathUtils.h"
#include "SharedLogging.h"
#include "HifiConfigVariantMap.h"
QVariantMap HifiConfigVariantMap::mergeCLParametersWithJSONConfig(const QStringList& argumentList) {
@ -110,18 +113,61 @@ void HifiConfigVariantMap::loadMasterAndUserConfig(const QStringList& argumentLi
// load the user config
const QString USER_CONFIG_FILE_OPTION = "--user-config";
static const QString USER_CONFIG_FILE_NAME = "config.json";
int userConfigIndex = argumentList.indexOf(USER_CONFIG_FILE_OPTION);
if (userConfigIndex != -1) {
_userConfigFilename = argumentList[userConfigIndex + 1];
} else {
_userConfigFilename = QString("%1/%2/%3/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation),
QCoreApplication::organizationName(),
QCoreApplication::applicationName());
// we weren't passed a user config path
_userConfigFilename = ServerPathUtils::getDataFilePath(USER_CONFIG_FILE_NAME);
// as of 1/19/2016 this path was moved so we attempt a migration for first run post migration here
// figure out what the old path was
// if our build version is "dev" we should migrate from a different organization folder
auto oldConfigFilename = QString("%1/%2/%3/%4").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation),
QCoreApplication::organizationName(),
QCoreApplication::applicationName(),
USER_CONFIG_FILE_NAME);
oldConfigFilename = oldConfigFilename.replace("High Fidelity - dev", "High Fidelity");
// check if there's already a config file at the new path
QFile newConfigFile { _userConfigFilename };
if (!newConfigFile.exists()) {
QFile oldConfigFile { oldConfigFilename };
if (oldConfigFile.exists()) {
// we have the old file and not the new file - time to copy the file
// make the destination directory if it doesn't exist
auto dataDirectory = ServerPathUtils::getDataDirectory();
if (QDir().mkpath(dataDirectory)) {
if (oldConfigFile.copy(_userConfigFilename)) {
qDebug() << "Migrated config file from" << oldConfigFilename << "to" << _userConfigFilename;
} else {
qWarning() << "Could not copy previous config file from" << oldConfigFilename << "to" << _userConfigFilename
<< "- please try to copy manually and restart.";
}
} else {
qWarning() << "Could not create application data directory" << dataDirectory << "- unable to migrate previous config file.";
}
}
}
}
loadMapFromJSONFile(_userConfig, _userConfigFilename);
mergeMasterAndUserConfigs();
}
void HifiConfigVariantMap::mergeMasterAndUserConfigs() {
// the merged config is initially matched to the master config
_mergedConfig = _masterConfig;

View file

@ -13,6 +13,7 @@
#define hifi_HifiConfigVariantMap_h
#include <QtCore/QStringList>
#include <QtCore/QVariantMap>
class HifiConfigVariantMap {
public:
@ -25,6 +26,8 @@ public:
QVariantMap& getUserConfig() { return _userConfig; }
QVariantMap& getMergedConfig() { return _mergedConfig; }
void mergeMasterAndUserConfigs();
const QString& getUserConfigFilename() const { return _userConfigFilename; }
private:
QString _userConfigFilename;

View file

@ -42,6 +42,8 @@ LogHandler::LogHandler() :
const char* stringForLogType(LogMsgType msgType) {
switch (msgType) {
case LogInfo:
return "INFO";
case LogDebug:
return "DEBUG";
case LogWarning:

View file

@ -22,11 +22,12 @@
const int VERBOSE_LOG_INTERVAL_SECONDS = 5;
enum LogMsgType {
LogInfo = QtInfoMsg,
LogDebug = QtDebugMsg,
LogWarning = QtWarningMsg,
LogCritical = QtCriticalMsg,
LogFatal = QtFatalMsg,
LogSuppressed
LogSuppressed = 100
};
/// Handles custom message handling and sending of stats/logs to Logstash instance

View file

@ -0,0 +1,37 @@
//
// ServerPathUtils.cpp
// libraries/shared/src
//
// Created by Ryan Huffman on 01/12/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 "ServerPathUtils.h"
#include <QStandardPaths>
#include <QtCore/QDir>
#include <QtWidgets/qapplication.h>
#include <QDebug>
QString ServerPathUtils::getDataDirectory() {
auto dataPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
#ifdef Q_OS_WIN
dataPath += "/AppData/Roaming/";
#elif defined(Q_OS_OSX)
dataPath += "/Library/Application Support/";
#else
dataPath += "/.local/share/";
#endif
dataPath += qApp->organizationName() + "/" + qApp->applicationName();
return QDir::cleanPath(dataPath);
}
QString ServerPathUtils::getDataFilePath(QString filename) {
return QDir(getDataDirectory()).absoluteFilePath(filename);
}

View file

@ -0,0 +1,22 @@
//
// ServerPathUtils.h
// libraries/shared/src
//
// Created by Ryan Huffman on 01/12/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
//
#ifndef hifi_ServerPathUtils_h
#define hifi_ServerPathUtils_h
#include <QString>
namespace ServerPathUtils {
QString getDataDirectory();
QString getDataFilePath(QString filename);
}
#endif // hifi_ServerPathUtils_h

5
server-console/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
Server\ Console-*/
server-console-*/
electron-packager/
npm-debug.log
logs/

View file

@ -0,0 +1,74 @@
set(TARGET_NAME packaged-server-console)
if (PRODUCTION_BUILD)
set(PRODUCTION_OPTION "--production")
endif()
# add a target that will package the console
add_custom_target(${TARGET_NAME}-npm-install
COMMAND npm install
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_custom_target(${TARGET_NAME}
COMMAND npm run packager -- --out ${CMAKE_CURRENT_BINARY_DIR} ${PRODUCTION_OPTION}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${TARGET_NAME}-npm-install
)
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Server Console")
set_target_properties(${TARGET_NAME}-npm-install PROPERTIES FOLDER "hidden/Server Console")
# add a dependency from the package target to the server components
add_dependencies(${TARGET_NAME} assignment-client domain-server)
# set the packaged console folder depending on platform, so we can copy it
if (APPLE)
set(PACKAGED_CONSOLE_FOLDER "Server\\ Console-darwin-x64/${CONSOLE_EXEC_NAME}")
elseif (WIN32)
set(PACKAGED_CONSOLE_FOLDER "server-console-win32-x64")
elseif (UNIX)
set(PACKAGED_CONSOLE_FOLDER "server-console-linux-x64")
endif ()
# install the packaged Server Console in our install directory
if (APPLE)
install(
PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGED_CONSOLE_FOLDER}"
DESTINATION ${CONSOLE_INSTALL_DIR}
COMPONENT ${SERVER_COMPONENT}
)
elseif (WIN32)
set(CONSOLE_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGED_CONSOLE_FOLDER}")
install(
DIRECTORY "${CONSOLE_DESTINATION}/"
DESTINATION ${CONSOLE_INSTALL_DIR}
COMPONENT ${SERVER_COMPONENT}
)
# sign the copied server console executable after install
set(EXECUTABLE_PATH "${CONSOLE_DESTINATION}/${CONSOLE_EXEC_NAME}")
optional_win_executable_signing()
endif()
if (PR_BUILD OR PRODUCTION_BUILD)
set_target_properties(${TARGET_NAME} PROPERTIES EXCLUDE_FROM_ALL FALSE EXCLUDE_FROM_DEFAULT_BUILD FALSE)
if (APPLE)
set(BESIDE_CONSOLE_DIR "${CONSOLE_INSTALL_APP_PATH}/Contents/Resources")
else ()
set(BESIDE_CONSOLE_DIR ${CONSOLE_INSTALL_DIR})
endif ()
# configure our build info json file and install it beside the console
set(CONSOLE_BUILD_INFO_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build-info.json")
configure_file("${HF_CMAKE_DIR}/templates/console-build-info.json.in" ${CONSOLE_BUILD_INFO_OUTPUT})
install(
FILES ${CONSOLE_BUILD_INFO_OUTPUT}
DESTINATION ${BESIDE_CONSOLE_DIR}
COMPONENT ${SERVER_COMPONENT}
)
else ()
set_target_properties(${TARGET_NAME} PROPERTIES EXCLUDE_FROM_ALL TRUE EXCLUDE_FROM_DEFAULT_BUILD TRUE)
set_target_properties(${TARGET_NAME}-npm-install PROPERTIES EXCLUDE_FROM_ALL TRUE EXCLUDE_FROM_DEFAULT_BUILD TRUE)
endif ()

25
server-console/README.md Normal file
View file

@ -0,0 +1,25 @@
### Console
The High Fidelity Server Console, made with [Electron](http://electron.atom.io/).
### Running Locally
Make sure you have [Node.js](https://nodejs.org/en/) installed. Use the latest stable version.
```
npm install
npm start
```
To run, the console needs to find a build of Interface, domain-server, and assignment-client.
The command `npm start` tells the console to look for builds of those binaries in a build folder beside this console folder.
On platforms with separate build folders for release and debug libraries `npm start` will choose the debug binaries. On those platforms if you prefer to use local release builds you'll want `npm run local-release`.
### Packaging
CMake produces a target `packaged-server-console` that will bundle up everything you need for the Server Console on your platform.
It ensures that there are available builds for the domain-server and assignment-client. Then it produces an executable for the Server Console.
The install target will copy all of the produced executables to a directory, ready for testing or packaging for deployment.

View file

@ -0,0 +1,38 @@
{
"name": "hf-console",
"description": "High Fidelity Console",
"author": "High Fidelity",
"license": "Apache-2.0",
"version": "1.0.0",
"keywords": [
""
],
"devDependencies": {
"electron-compilers": "^1.0.1",
"electron-packager": "^5.2.1",
"electron-prebuilt": "0.35.4"
},
"repository": {
"type": "git",
"url": "https://github.com/highfidelity/hifi.git"
},
"main": "src/main.js",
"scripts": {
"start": "electron . --binary-type local-debug --debug",
"local-release": "electron . --binary-type local-release --debug",
"local-release-no-debug": "electron . --binary-type local-release",
"packager": "node packager.js"
},
"dependencies": {
"always-tail": "0.2.0",
"cheerio": "^0.19.0",
"extend": "^3.0.0",
"fs-extra": "^0.26.4",
"node-notifier": "^4.4.0",
"os-homedir": "^1.0.1",
"request": "2.67.0",
"request-progress": "1.0.2",
"unzip": "0.1.11",
"yargs": "^3.30.0"
}
}

View file

@ -0,0 +1,59 @@
var packager = require('electron-packager')
var osType = require('os').type();
var platform = null;
if (osType == "Darwin" || osType == "Linux") {
platform = osType.toLowerCase();
} else if (osType == "Windows_NT") {
platform = "win32"
}
var argv = require('yargs').argv;
// check which icon we should use, beta or regular
var iconName = argv.production ? "console" : "console-beta";
// setup the common options for the packager
var options = {
dir: __dirname,
name: "server-console",
version: "0.35.4",
overwrite: true,
prune: true,
arch: "x64",
platform: platform,
icon: "resources/" + iconName,
ignore: "logs|(S|s)erver(\\s|-)(C|c)onsole-\\S+|electron-packager|README.md|CMakeLists.txt|packager.js|.gitignore"
}
const EXEC_NAME = "server-console";
const SHORT_NAME = "Server Console";
const FULL_NAME = "High Fidelity Server Console";
// setup per OS options
if (osType == "Darwin") {
options["app-bundle-id"] = "com.highfidelity.server-console" + (argv.production ? "" : "-dev")
options["name"] = SHORT_NAME
} else if (osType == "Windows_NT") {
options["version-string"] = {
CompanyName: "High Fidelity, Inc.",
FileDescription: SHORT_NAME,
ProductName: FULL_NAME,
OriginalFilename: EXEC_NAME + ".exe"
}
}
// check if we were passed a custom out directory, pass it along if so
if (argv.out) {
options.out = argv.out
}
// call the packager to produce the executable
packager(options, function(error, appPath) {
if (error) {
console.error("There was an error writing the packaged console: " + error.message);
process.exit(1);
} else {
console.log("Wrote new app to " + appPath);
}
});

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

View file

@ -0,0 +1,145 @@
@font-face {
font-family: 'Raleway';
src: url('vendor/Raleway/Raleway-Regular.ttf');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Raleway';
src: url('vendor/Raleway/Raleway-ExtraLight.ttf');
font-weight: 200;
font-style: normal;
}
@font-face {
font-family: 'Raleway';
src: url('vendor/Raleway/Raleway-SemiBold.ttf');
font-weight: bold;
font-style: normal;
}
* {
font-family: "Raleway", "Open Sans", Arial, Helvetica, sans-serif;
line-height: 130%;
}
body {
margin: 0;
padding: 0;
color: #808785;
margin: 0 auto;
text-align: center;
font-size: 13.5pt;
-webkit-touch-callout: none; -webkit-user-select: none;
cursor: default;
overflow: hidden;
font-variant-numeric: lining-nums;
-moz-font-feature-settings: "lnum";
-webkit-font-feature-settings: "lnum";
font-feature-settings: "lnum";
}
#error-message {
background-color: #F7F8F8;
color: #EB4C5F;
padding: 20px;
margin: 20px 120px 0 120px;
}
.selectable {
-webkit-touch-callout: text;
-webkit-user-select: text;
cursor: text;
}
progress {
height: 1px;
width: 300px;
-webkit-appearance: none;
}
progress[value]::-webkit-progress-bar {
background-color: #DADADA;
/* border-radius: 2px; */
}
progress[value]::-webkit-progress-value {
background-color: #21B7D4;
/* border-radius: 2px; */
}
#progress-bytes {
font-weight: lighter;
color: #BBBBBB;
margin-top: 10px;
}
#download-summary {
margin-top: 80px;
}
.state {
padding-top: 100px;
}
h1 {
font-size: 29pt;
font-weight: normal;
}
#cancel-area {
margin-top: 100px;
}
a:link,
a:visited,
a:hover,
a:active {
color: #B4B4B4;
}
a:hover {
color: #2D88A4;
}
.one {
opacity: 0;
animation: dot 2.3s infinite;
animation-delay: 0.0s;
}
.two {
opacity: 0;
animation: dot 2.3s infinite;
animation-delay: 0.2s;
}
.three {
opacity: 0;
animation: dot 2.3s infinite;
animation-delay: 0.3s;
}
@-webkit-keyframes dot {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes dot {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>High Fidelity</title>
<script src="downloader.js"></script>
<link rel="stylesheet" type="text/css" href="downloader.css"></link>
</head>
<body onload="ready()">
<div id="state-downloading" class="state">
<h1>Downloading<span class="one">.</span><span class="two">.</span><span class="three">.</span></h1>
<progress max="100" value="80" id="download-progress"></progress>
<div id="progress-bytes">10 MB / 4.0 MB</div>
<div id="download-summary">
Sit tight, we are downloading content for your home
</div>
</div>
<div id="state-installing" class="state">
<h1>Installing<span class="one">.</span><span class="two">.</span><span class="three">.</span></h1>
<em>Just a moment</em>
</div>
<div id="state-complete" class="state">
<h1>Success!</h1>
<em>You're all set.</em>
</div>
<div id="state-error" class="state">
<h1>Houston...</h1>
<em>An unfortunate error has occurred:</em>
<div id="error-message" class="selectable">
</div>
</body>
</html>

View file

@ -0,0 +1,52 @@
function ready() {
console.log("Ready");
const electron = require('electron');
const remote = require('remote');
window.$ = require('./vendor/jquery/jquery-2.1.4.min.js');
$(".state").hide();
var currentState = null;
function updateState(state, args) {
if (state == 'downloading') {
function formatBytes(size) {
return (size / 1000000).toFixed('2');
}
$('#download-progress').attr('value', args.percentage * 100);
if (args.size !== null && args.size.transferred !== null && args.size.total !== null) {
var progressString = formatBytes(args.size.transferred) + "MB / " + formatBytes(args.size.total) + "MB";
$('#progress-bytes').html(progressString);
} else {
$('#progress-bytes').html("Retrieving resources...");
}
} else if (state == 'installing') {
} else if (state == 'complete') {
setTimeout(function() {
remote.getCurrentWindow().close();
}, 2000);
} else if (state == 'error') {
$('#error-message').html(args.message);
}
if (currentState != state) {
if (currentState) {
$('#state-' + currentState).hide();
}
$('#state-' + state).show();
currentState = state;
}
}
electron.ipcRenderer.on('update', function(event, message) {
updateState(message.state, message.args);
});
// updateState('error', { message: "This is an error message", progress: 0.5 });
// updateState('complete', { progress: 0 });
// updateState('downloading', { percentage: 0.5, size: { total: 83040400, transferred: 500308} });
updateState('downloading', { percentage: 0, size: null });
electron.ipcRenderer.send('ready');
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Some files were not shown because too many files have changed in this diff Show more