Merge branch 'master' of github.com:highfidelity/hifi into flag/shadows

This commit is contained in:
Zach Pomerantz 2016-01-22 10:03:06 -08:00
commit dee8e0ba9d
298 changed files with 9616 additions and 6908 deletions

1
.gitattributes vendored
View file

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

6
.gitignore vendored
View file

@ -36,7 +36,7 @@ interface/external/*/*
# Ignore interfaceCache for Linux users
interface/interfaceCache/
# ignore audio-client externals
# ignore audio-client externals
libraries/audio-client/external/*/*
!libraries/audio-client/external/*/readme.txt
@ -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

@ -15,7 +15,7 @@ endif ()
if (POLICY CMP0043)
cmake_policy(SET CMP0043 OLD)
endif ()
endif ()
if (POLICY CMP0042)
cmake_policy(SET CMP0042 OLD)
@ -26,24 +26,32 @@ set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
project(hifi)
add_definitions(-DGLM_FORCE_RADIANS)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
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")
set(WINDOW_SDK_FOLDER "x64")
else()
set(WINDOW_SDK_FOLDER "x86")
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")
@ -75,7 +83,7 @@ if ((NOT MSVC12) AND (NOT MSVC14))
endif()
endif ()
if (APPLE)
if (APPLE)
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++")
@ -85,16 +93,16 @@ if (NOT ANDROID_LIB_DIR)
set(ANDROID_LIB_DIR $ENV{ANDROID_LIB_DIR})
endif ()
if (ANDROID)
if (ANDROID)
if (NOT ANDROID_QT_CMAKE_PREFIX_PATH)
set(QT_CMAKE_PREFIX_PATH ${ANDROID_LIB_DIR}/Qt/5.4/android_armv7/lib/cmake)
else ()
set(QT_CMAKE_PREFIX_PATH ${ANDROID_QT_CMAKE_PREFIX_PATH})
endif ()
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
if (ANDROID_LIB_DIR)
list(APPEND CMAKE_FIND_ROOT_PATH ${ANDROID_LIB_DIR})
endif ()
@ -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.")
@ -119,34 +129,34 @@ get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE)
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH})
if (APPLE)
exec_program(sw_vers ARGS -productVersion OUTPUT_VARIABLE OSX_VERSION)
string(REGEX MATCH "^[0-9]+\\.[0-9]+" OSX_VERSION ${OSX_VERSION})
message(STATUS "Detected OS X version = ${OSX_VERSION}")
set(OSX_SDK "${OSX_VERSION}" CACHE String "OS X SDK version to look for inside Xcode bundle or at OSX_SDK_PATH")
# set our OS X deployment target
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
# find the SDK path for the desired SDK
find_path(
_OSX_DESIRED_SDK_PATH
NAME MacOSX${OSX_SDK}.sdk
_OSX_DESIRED_SDK_PATH
NAME MacOSX${OSX_SDK}.sdk
HINTS ${OSX_SDK_PATH}
PATHS /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
)
if (NOT _OSX_DESIRED_SDK_PATH)
message(STATUS "Could not find OS X ${OSX_SDK} SDK. Will fall back to default. If you want a specific SDK, please pass OSX_SDK and optionally OSX_SDK_PATH to CMake.")
else ()
message(STATUS "Found OS X ${OSX_SDK} SDK at ${_OSX_DESIRED_SDK_PATH}/MacOSX${OSX_SDK}.sdk")
# set that as the SDK to use
set(CMAKE_OSX_SYSROOT ${_OSX_DESIRED_SDK_PATH}/MacOSX${OSX_SDK}.sdk)
endif ()
endif ()
# Hide automoc folders (for IDEs)
@ -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})
@ -198,9 +208,11 @@ if (WIN32)
endif ()
if (NOT DEFINED SERVER_ONLY)
set(SERVER_ONLY 0)
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()
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).

25
LICENSE
View file

@ -1,13 +1,12 @@
Copyright 2014 High Fidelity, Inc.
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
http://www.apache.org/licenses/LICENSE-2.0
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.
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 software except in compliance with the License.
You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
This software includes third-party software.
Please see each individual software license for additional details.
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

@ -3,12 +3,14 @@ set(TARGET_NAME assignment-client)
setup_hifi_project(Core Gui Network Script Quick Widgets WebSockets)
# link in the shared libraries
link_hifi_libraries(
audio avatars octree environment gpu model fbx entities
link_hifi_libraries(
audio avatars octree gpu model fbx entities
networking animation recording shared script-engine embedded-webserver
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,15 +22,13 @@
#include "AssignmentClient.h"
#include "AssignmentClientMonitor.h"
#include "AssignmentClientApp.h"
#include <QtCore/QDir>
#include <QtCore/QStandardPaths>
AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
QCoreApplication(argc, argv)
{
// to work around the Qt constant wireless scanning, set the env for polling interval very high
const QByteArray EXTREME_BEARER_POLL_TIMEOUT = QString::number(INT_MAX).toLocal8Bit();
qputenv("QT_BEARER_POLL_TIMEOUT", EXTREME_BEARER_POLL_TIMEOUT);
# ifndef WIN32
setvbuf(stdout, NULL, _IOLBF, 0);
# endif
@ -42,10 +40,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);
@ -63,7 +61,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
const QCommandLineOption poolOption(ASSIGNMENT_POOL_OPTION, "set assignment pool", "pool-name");
parser.addOption(poolOption);
const QCommandLineOption portOption(ASSIGNMENT_CLIENT_LISTEN_PORT_OPTION,
"UDP port for this assignment client (or monitor)", "port");
parser.addOption(portOption);
@ -92,6 +90,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 +134,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();
@ -168,11 +184,11 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) {
assignmentServerPort = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toUInt();
}
if (parser.isSet(assignmentServerPortOption)) {
assignmentServerPort = parser.value(assignmentServerPortOption).toInt();
}
// check for an overidden listen port
quint16 listenPort = 0;
if (argumentVariantMap.contains(ASSIGNMENT_CLIENT_LISTEN_PORT_OPTION)) {
@ -200,7 +216,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,18 +159,61 @@ 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 });
}
}
void AssignmentClientMonitor::checkSpares() {
@ -222,12 +269,12 @@ void AssignmentClientMonitor::handleChildStatusPacket(QSharedPointer<ReceivedMes
// The parent only expects to be talking with prorams running on this same machine.
if (senderSockAddr.getAddress() == QHostAddress::LocalHost ||
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
if (!senderID.isNull()) {
// We don't have this node yet - we should add it
matchingNode = DependencyManager::get<LimitedNodeList>()->addOrUpdateNode
(senderID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false, false);
auto childData = std::unique_ptr<AssignmentClientChildData>
{ new AssignmentClientChildData(Assignment::Type::AllTypes) };
matchingNode->setLinkedData(std::move(childData));
@ -252,10 +299,39 @@ void AssignmentClientMonitor::handleChildStatusPacket(QSharedPointer<ReceivedMes
// get child's assignment type out of the packet
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,10 +50,42 @@ void AssetServer::run() {
auto nodeList = DependencyManager::get<NodeList>();
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
_resourcesDirectory = QDir(QCoreApplication::applicationDirPath()).filePath("resources/assets");
if (!_resourcesDirectory.exists()) {
qDebug() << "Creating resources directory";
_resourcesDirectory.mkpath(".");
const QString RESOURCES_PATH = "assets";
_resourcesDirectory = QDir(ServerPathUtils::getDataDirectory()).filePath(RESOURCES_PATH);
qDebug() << "Creating resources directory";
_resourcesDirectory.mkpath(".");
bool noExistingAssets = !_resourcesDirectory.exists() \
|| _resourcesDirectory.entryList(QDir::Files).size() == 0;
if (noExistingAssets) {
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(".");
}
auto files = QDir(oldResourcesDirectory).entryList(QDir::Files);
for (auto& file : files) {
auto from = oldResourcesDirectory + QDir::separator() + file;
auto to = _resourcesDirectory.absoluteFilePath(file);
qDebug() << "\tCopying from " << from << " to " << to;
QFile::copy(from, to);
}
}
}
qDebug() << "Serving files from: " << _resourcesDirectory.path();

View file

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

View file

@ -9,11 +9,15 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AssignmentClientApp.h"
#include <QtCore/QDebug>
#include <SharedUtil.h>
#include "AssignmentClientApp.h"
int main(int argc, char* argv[]) {
disableQtBearerPoll(); // Fixes wifi ping spikes
AssignmentClientApp app(argc, argv);
int acReturn = app.exec();

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);
@ -1096,7 +1100,7 @@ void OctreeServer::run() {
_tree->setIsServer(true);
qDebug() << "Waiting for connection to domain to request settings from domain-server.";
// wait until we have the domain-server settings, otherwise we bail
DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
connect(&domainHandler, &DomainHandler::settingsReceived, this, &OctreeServer::domainSettingsRequestComplete);
@ -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,7 +21,6 @@
#include <HTTPManager.h>
#include <ThreadedAssignment.h>
#include <EnvironmentData.h>
#include "OctreePersistThread.h"
#include "OctreeSendThread.h"

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

@ -1,30 +1,78 @@
#
# GenerateInstallers.cmake
# cmake/macros
#
# Created by Leonardo Murillo on 12/16/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(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"
)
endif ()
endmacro()
#
# GenerateInstallers.cmake
# cmake/macros
#
# Created by Leonardo Murillo on 12/16/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(GENERATE_INSTALLERS)
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

@ -1,25 +1,24 @@
#
#
# PackageLibrariesForDeployment.cmake
# cmake/macros
#
#
# Copyright 2015 High Fidelity, Inc.
# Created by Stephen Birarda on February 17, 2014
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
#
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
)
set(PLUGIN_PATH "plugins")
# add a post-build command to copy DLLs beside the executable
add_custom_command(
TARGET ${TARGET_NAME}
@ -29,31 +28,18 @@ macro(PACKAGE_LIBRARIES_FOR_DEPLOYMENT)
-DBUNDLE_PLUGIN_DIR=$<TARGET_FILE_DIR:${TARGET_NAME}>/${PLUGIN_PATH}
-P ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake
)
find_program(WINDEPLOYQT_COMMAND windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH)
if (NOT WINDEPLOYQT_COMMAND)
message(FATAL_ERROR "Could not find windeployqt at ${QT_DIR}/bin. windeployqt is required.")
endif ()
# add a post-build command to call windeployqt to copy Qt plugins
add_custom_command(
TARGET ${TARGET_NAME}
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

@ -1,36 +1,35 @@
#
#
# SetupHifiProject.cmake
#
#
# Copyright 2013 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(SETUP_HIFI_PROJECT)
project(${TARGET_NAME})
# grab the implemenation and header files
file(GLOB TARGET_SRCS src/*)
file(GLOB SRC_SUBDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src/*)
foreach(DIR ${SRC_SUBDIRS})
if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/${DIR}")
file(GLOB DIR_CONTENTS "src/${DIR}/*")
set(TARGET_SRCS ${TARGET_SRCS} "${DIR_CONTENTS}")
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)
# find these Qt modules and link them to our own target
find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED)
@ -44,7 +43,7 @@ macro(SETUP_HIFI_PROJECT)
foreach(QT_MODULE ${${TARGET_NAME}_DEPENDENCY_QT_MODULES})
target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE})
endforeach()
target_glm()
endmacro()

View file

@ -1,5 +1,5 @@
#
# CopyDirectoryBesideTarget.cmake
# CopyDirectoryBesideTarget.cmake
# cmake/macros
#
# Created by Stephen Birarda on 04/30/15.
@ -10,22 +10,22 @@
#
macro(SYMLINK_OR_COPY_DIRECTORY_BESIDE_TARGET _SHOULD_SYMLINK _DIRECTORY _DESTINATION)
# remove the current directory
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E remove_directory $<TARGET_FILE_DIR:${TARGET_NAME}>/${_DESTINATION}
)
if (${_SHOULD_SYMLINK})
# first create the destination
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory
$<TARGET_FILE_DIR:${TARGET_NAME}>/${_DESTINATION}
)
# the caller wants a symlink, so just add a command to symlink all contents of _DIRECTORY
# in the destination - we can't simply create a symlink for _DESTINATION
# because the remove_directory call above would delete the original files
@ -35,20 +35,20 @@ macro(SYMLINK_OR_COPY_DIRECTORY_BESIDE_TARGET _SHOULD_SYMLINK _DIRECTORY _DESTIN
foreach(_ITEM ${_DIR_ITEMS})
# get the filename for this item
get_filename_component(_ITEM_FILENAME ${_ITEM} NAME)
# add the command to symlink this item
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E create_symlink
${_ITEM}
$<TARGET_FILE_DIR:${TARGET_NAME}>/${_DESTINATION}/${_ITEM_FILENAME}
)
endforeach()
)
endforeach()
else ()
# copy the directory
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${_DIRECTORY}
TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${_DIRECTORY}
$<TARGET_FILE_DIR:${TARGET_NAME}>/${_DESTINATION}
)
endif ()

View file

@ -1,20 +1,28 @@
#
#
# Copyright 2015 High Fidelity, Inc.
# Created by Bradley Austin Davis on 2015/10/10
#
# 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_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)
endmacro()
# 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

@ -1,14 +1,14 @@
#
#
# Copyright 2015 High Fidelity, Inc.
# Created by Bradley Austin Davis on 2015/10/10
#
# 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_SIXENSE)
add_dependency_external_projects(sixense)
find_package(Sixense REQUIRED)
target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES})
add_definitions(-DHAVE_SIXENSE)
endmacro()
endmacro()

View file

@ -8,11 +8,11 @@
# OPENSSL_INCLUDE_DIR - the OpenSSL include directory
# OPENSSL_LIBRARIES - The libraries needed to use OpenSSL
# OPENSSL_VERSION - This is set to $major.$minor.$revision$path (eg. 0.9.8s)
#
#
# Modified on 7/16/2014 by Stephen Birarda
# This is an adapted version of the FindOpenSSL.cmake module distributed with Cmake 2.8.12.2
# The original license for that file is displayed below.
#
#
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
@ -50,18 +50,18 @@ if (WIN32)
)
set(_OPENSSL_ROOT_PATHS "${_programfiles}/OpenSSL" "${_programfiles}/OpenSSL-Win32" "C:/OpenSSL/" "C:/OpenSSL-Win32/")
endif()
unset(_programfiles)
set(_OPENSSL_ROOT_HINTS_AND_PATHS HINTS ${_OPENSSL_ROOT_HINTS} PATHS ${_OPENSSL_ROOT_PATHS})
else ()
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
hifi_library_search_hints("openssl")
set(_OPENSSL_ROOT_HINTS_AND_PATHS ${OPENSSL_SEARCH_DIRS})
endif ()
find_path(OPENSSL_INCLUDE_DIR NAMES openssl/ssl.h HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} ${_OPENSSL_INCLUDEDIR}
find_path(OPENSSL_INCLUDE_DIR NAMES openssl/ssl.h HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} ${_OPENSSL_INCLUDEDIR}
PATH_SUFFIXES include
)
@ -81,15 +81,15 @@ if (WIN32 AND NOT CYGWIN)
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
# libeay32MD.lib is identical to ../libeay32.lib, and
# ssleay32MD.lib is identical to ../ssleay32.lib
find_library(LIB_EAY_DEBUG NAMES libeay32MDd libeay32d
find_library(LIB_EAY_DEBUG NAMES libeay32MDd libeay32d
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "VC" "lib/VC"
)
find_library(LIB_EAY_RELEASE NAMES libeay32MD libeay32
find_library(LIB_EAY_RELEASE NAMES libeay32MD libeay32
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "VC" "lib/VC"
)
find_library(SSL_EAY_DEBUG NAMES ssleay32MDd ssleay32d
find_library(SSL_EAY_DEBUG NAMES ssleay32MDd ssleay32d
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "VC" "lib/VC"
)
@ -109,22 +109,22 @@ if (WIN32 AND NOT CYGWIN)
set(OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY})
find_path(OPENSSL_DLL_PATH NAMES ssleay32.dll PATH_SUFFIXES "bin" ${_OPENSSL_ROOT_HINTS_AND_PATHS})
elseif (MINGW)
# same player, for MinGW
set(LIB_EAY_NAMES libeay32)
set(SSL_EAY_NAMES ssleay32)
if (CMAKE_CROSSCOMPILING)
list(APPEND LIB_EAY_NAMES crypto)
list(APPEND SSL_EAY_NAMES ssl)
endif ()
find_library(LIB_EAY NAMES ${LIB_EAY_NAMES}
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "lib/MinGW"
)
find_library(SSL_EAY NAMES ${SSL_EAY_NAMES}
find_library(SSL_EAY NAMES ${SSL_EAY_NAMES}
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "lib/MinGW"
)
@ -147,7 +147,7 @@ else()
PATH_SUFFIXES lib
)
find_library(OPENSSL_CRYPTO_LIBRARY NAMES crypto HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} ${_OPENSSL_LIBDIR}
find_library(OPENSSL_CRYPTO_LIBRARY NAMES crypto HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} ${_OPENSSL_LIBDIR}
PATH_SUFFIXES lib
)
@ -196,7 +196,7 @@ if (OPENSSL_INCLUDE_DIR)
if(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
REGEX "^#[ ]?define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
# The version number is encoded as 0xMNNFFPPS: major minor fix patch status
# The status gives if this is a developer or prerelease and is ignored here.
# Major, minor, and fix directly translate into the version numbers shown in
@ -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

@ -1,56 +1,54 @@
#
#
# FixupBundlePostBuild.cmake.in
# cmake/templates
#
#
# Copyright 2015 High Fidelity, Inc.
# Created by Stephen Birarda on February 13, 2014
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
#
include(BundleUtilities)
# replace copy_resolved_item_into_bundle
# replace copy_resolved_item_into_bundle
#
# The official version of copy_resolved_item_into_bundle will print out a "warning:" when
# the resolved item matches the resolved embedded item. This not not really an issue that
# 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")
elseif (WIN32)
set(PLUGIN_EXTENSION "dll")
else()
set(PLUGIN_EXTENSION "so")
set(PLUGIN_EXTENSION "dylib")
elseif (WIN32)
set(PLUGIN_EXTENSION "dll")
else()
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

@ -65,7 +65,7 @@
{
"name": "viewpoint",
"label": "Viewpoint",
"placeholder": "/512,512,512"
"placeholder": "/0,0,0"
}
]
}
@ -308,7 +308,7 @@
"type": "checkbox",
"label": "Dynamic Jitter Buffers",
"help": "Dynamically buffer client audio based on perceived jitter in packet receipt timing",
"default": false,
"default": true,
"advanced": true
},
{
@ -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(),
@ -64,24 +65,22 @@ DomainServer::DomainServer(int argc, char* argv[]) :
LogUtils::init();
Setting::init();
// to work around the Qt constant wireless scanning, set the env for polling interval very high
const QByteArray EXTREME_BEARER_POLL_TIMEOUT = QString::number(INT_MAX).toLocal8Bit();
qputenv("QT_BEARER_POLL_TIMEOUT", EXTREME_BEARER_POLL_TIMEOUT);
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 +109,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 +158,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 +210,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 +334,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 +446,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 +496,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 +1150,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);
@ -1786,16 +1868,25 @@ void DomainServer::processPathQueryPacket(QSharedPointer<ReceivedMessage> messag
const QString PATHS_SETTINGS_KEYPATH_FORMAT = "%1.%2";
const QString PATH_VIEWPOINT_KEY = "viewpoint";
const QString INDEX_PATH = "/";
// check out paths in the _configMap to see if we have a match
const QVariant* pathMatch = valueForKeyPath(_settingsManager.getSettingsMap(),
QString(PATHS_SETTINGS_KEYPATH_FORMAT).arg(SETTINGS_PATHS_KEY)
.arg(pathQuery));
if (pathMatch) {
auto keypath = QString(PATHS_SETTINGS_KEYPATH_FORMAT).arg(SETTINGS_PATHS_KEY).arg(pathQuery);
const QVariant* pathMatch = valueForKeyPath(_settingsManager.getSettingsMap(), keypath);
if (pathMatch || pathQuery == INDEX_PATH) {
// we got a match, respond with the resulting viewpoint
auto nodeList = DependencyManager::get<LimitedNodeList>();
QString responseViewpoint = pathMatch->toMap()[PATH_VIEWPOINT_KEY].toString();
QString responseViewpoint;
// if we didn't match the path BUT this is for the index path then send back our default
if (pathMatch) {
responseViewpoint = pathMatch->toMap()[PATH_VIEWPOINT_KEY].toString();
} else {
const QString DEFAULT_INDEX_PATH = "/0,0,0/0,0,0,1";
responseViewpoint = DEFAULT_INDEX_PATH;
}
if (!responseViewpoint.isEmpty()) {
QByteArray viewpointUTF8 = responseViewpoint.toUtf8();

View file

@ -74,6 +74,9 @@ private slots:
void sendHeartbeatToIceServer();
void handleConnectedNode(SharedNodePointer newNode);
void handleTempDomainSuccess(QNetworkReply& requestReply);
void handleTempDomainError(QNetworkReply& requestReply);
private:
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
@ -81,10 +84,13 @@ private:
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();
@ -144,6 +150,8 @@ private:
DomainServerSettingsManager _settingsManager;
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

@ -23,6 +23,8 @@
#include "DomainServer.h"
int main(int argc, char* argv[]) {
disableQtBearerPoll(); // Fixes wifi ping spikes
#ifndef WIN32
setvbuf(stdout, NULL, _IOLBF, 0);
#endif

View file

@ -108,7 +108,7 @@ var GRABBABLE_PROPERTIES = [
"position",
"rotation",
"gravity",
"collisionMask",
"collidesWith",
"collisionsWillMove",
"locked",
"name",
@ -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;
@ -163,9 +162,9 @@ var STATE_CONTINUE_EQUIP = 14;
var STATE_WAITING_FOR_BUMPER_RELEASE = 15;
var STATE_EQUIP_SPRING = 16;
// collision masks are specified by comma-separated list of group names
// the possible list of names is: static, dynamic, kinematic, myAvatar, otherAvatar
var COLLISION_MASK_WHILE_GRABBED = "dynamic,otherAvatar";
// "collidesWith" is specified by comma-separated list of group names
// the possible group names are: static, dynamic, kinematic, myAvatar, otherAvatar
var COLLIDES_WITH_WHILE_GRABBED = "dynamic,otherAvatar";
function stateToName(state) {
switch (state) {
@ -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
};
@ -853,7 +823,7 @@ function MyController(hand) {
intersection = Entities.findRayIntersection(pickRayBacked, true, [], blacklist);
} else {
intersection = Entities.findRayIntersection(pickRayBacked, true);
}
}
if (intersection.intersects) {
rayPickedCandidateEntities.push(intersection.entityID);
@ -925,13 +895,14 @@ 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();
return;
}
@ -945,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;
@ -956,7 +923,7 @@ function MyController(hand) {
// If we hit something with our pick ray, move the search sphere toward that distance
this.searchSphereDistance = this.searchSphereDistance * SEARCH_SPHERE_FOLLOW_RATE + this.intersectionDistance * (1.0 - SEARCH_SPHERE_FOLLOW_RATE);
}
var searchSphereLocation = Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, this.searchSphereDistance));
this.searchSphereOn(searchSphereLocation, SEARCH_SPHERE_SIZE * this.searchSphereDistance, (this.triggerSmoothedGrab() || this.bumperSqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
if ((USE_OVERLAY_LINES_FOR_SEARCHING === true) && PICK_WITH_HAND_RAY) {
@ -1159,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);
@ -1597,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);
@ -1654,7 +1620,7 @@ function MyController(hand) {
// zero gravity and set ignoreForCollisions in a way that lets us put them back, after all grabs are done
if (data["refCount"] == 1) {
data["gravity"] = grabbedProperties.gravity;
data["collisionMask"] = grabbedProperties.collisionMask;
data["collidesWith"] = grabbedProperties.collidesWith;
data["collisionsWillMove"] = grabbedProperties.collisionsWillMove;
data["parentID"] = grabbedProperties.parentID;
data["parentJointIndex"] = grabbedProperties.parentJointIndex;
@ -1664,7 +1630,10 @@ function MyController(hand) {
y: 0,
z: 0
},
"collisionMask": COLLISION_MASK_WHILE_GRABBED
// bummer, it isn't easy to do bitwise collisionMask operations like this:
//"collisionMask": COLLISION_MASK_WHILE_GRABBED | grabbedProperties.collisionMask
// when using string values
"collidesWith": COLLIDES_WITH_WHILE_GRABBED
};
Entities.editEntity(entityID, whileHeldProperties);
}
@ -1680,7 +1649,7 @@ function MyController(hand) {
if (data["refCount"] < 1) {
Entities.editEntity(entityID, {
gravity: data["gravity"],
collisionMask: data["collisionMask"],
collidesWith: data["collidesWith"],
collisionsWillMove: data["collisionsWillMove"],
ignoreForCollisions: data["ignoreForCollisions"],
parentID: data["parentID"],
@ -1698,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);
@ -1780,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();
}
Script.update.connect(update);

View file

@ -1659,29 +1659,6 @@ PropertiesTool = function(opts) {
});
}
}
} else if (data.action == "centerAtmosphereToZone") {
if (selectionManager.hasSelection()) {
selectionManager.saveProperties();
for (var i = 0; i < selectionManager.selections.length; i++) {
var properties = selectionManager.savedProperties[selectionManager.selections[i]];
if (properties.type == "Zone") {
var centerOfZone = properties.boundingBox.center;
var atmosphereCenter = {
x: centerOfZone.x,
y: centerOfZone.y - properties.atmosphere.innerRadius,
z: centerOfZone.z
};
Entities.editEntity(selectionManager.selections[i], {
atmosphere: {
center: atmosphereCenter
},
});
}
}
pushCommandForSelections();
selectionManager._update();
}
}
}
});

View file

@ -1,71 +0,0 @@
//
// changingAtmosphereExample.js
// examples
//
// Created by Brad Hefta-Gaub on 4/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// This is an example script that demonstrates creating a zone using the atmosphere features that changes scatter properties
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var count = 0;
var stopAfter = 10000;
var zoneEntityA = Entities.addEntity({
type: "Zone",
position: { x: 1000, y: 1000, z: 1000},
dimensions: { x: 2000, y: 2000, z: 2000 },
keyLightColor: { red: 255, green: 0, blue: 0 },
stageSunModelEnabled: false,
shapeType: "sphere",
backgroundMode: "atmosphere",
atmosphere: {
center: { x: 1000, y: 0, z: 1000},
innerRadius: 1000.0,
outerRadius: 1025.0,
rayleighScattering: 0.0025, // Meaningful values 0 to ~0.01
mieScattering: 0.0010, // Meaningful values 0 to ~0.01
// First two, Meaningful values 0 to 1 each, blue, purple; third meaningful 0.3 to 1 - affects shape
scatteringWavelengths: { x: 0.650, y: 0.570, z: 0.475 },
hasStars: true
},
stage: {
latitude: 37.777,
longitude: 122.407,
altitude: 0.03,
day: 183,
hour: 5,
sunModelEnabled: true
}
});
// register the call back so it fires before each data send
Script.update.connect(function(deltaTime) {
// stop it...
if (count >= stopAfter) {
print("calling Script.stop()");
Script.stop();
}
count++;
var rayleighScattering = (count / 100000) % 0.01;
var mieScattering = (count / 100000) % 0.01;
var waveX = (count / 2000) % 1;
var waveZ = ((count / 2000) % 0.7) + 0.3;
Entities.editEntity(zoneEntityA, {
atmosphere: {
rayleighScattering: rayleighScattering,
mieScattering: mieScattering,
scatteringWavelengths: { x: waveX, y: waveX, z: waveZ }
},
});
});

View file

@ -1,65 +0,0 @@
//
// zoneAtmosphereExample.js
// examples
//
// Created by Brad Hefta-Gaub on 4/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// This is an example script that demonstrates creating a zone using the atmosphere features
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var count = 0;
var stopAfter = 10000;
var zoneEntityA = Entities.addEntity({
type: "Zone",
position: { x: 1000, y: 1000, z: 1000},
dimensions: { x: 2000, y: 2000, z: 2000 },
keyLightColor: { red: 255, green: 0, blue: 0 },
stageSunModelEnabled: false,
shapeType: "sphere",
backgroundMode: "atmosphere",
atmosphere: {
center: { x: 1000, y: 0, z: 1000},
innerRadius: 1000.0,
outerRadius: 1025.0,
rayleighScattering: 0.0025,
mieScattering: 0.0010,
scatteringWavelengths: { x: 0.650, y: 0.570, z: 0.475 },
hasStars: false
},
stage: {
latitude: 37.777,
longitude: 122.407,
altitude: 0.03,
day: 60,
hour: 0,
sunModelEnabled: true
}
});
// register the call back so it fires before each data send
Script.update.connect(function(deltaTime) {
// stop it...
if (count >= stopAfter) {
print("calling Script.stop()");
Script.stop();
}
count++;
var newHour = (count / 10) % 24;
var newIntensity = ((count / 10) % 24) / 24;
print("newHour:" + newHour);
print("newIntensity:" + newIntensity);
Entities.editEntity(zoneEntityA, {
stageHour: newHour,
keyLightIntensity: newIntensity
});
});

View file

@ -0,0 +1,16 @@
var messagesReceivedCount = 0;
function handleMessages(channel, message, sender) {
print('GOT MESSAGE')
if (sender === MyAvatar.sessionUUID) {
if (channel === 'messageTest') {
messagesReceivedCount++;
print('sendIndex/receiveCount::' + message + "/" + messagesReceivedCount);
}
}
}
Messages.messageReceived.connect(handleMessages);
Messages.subscribe('messageTest')
print('READY TO RECEIVE')

View file

@ -0,0 +1,18 @@
var messageIndex = 1;
var messageRate = 500;
function sendMessage(){
print('SENDING MESSAGE')
Messages.sendMessage('messageTest',messageIndex)
messageIndex++;
}
function cleanup(){
Script.clearInterval(messageInterval);
}
var messageInterval = Script.setInterval(function(){
sendMessage();
},messageRate);
Script.scriptEnding.connect(cleanup);

View file

@ -105,7 +105,8 @@
alphaStart: 0.5,
alphaFinish: 0.5,
textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png",
emitterShouldTrail: false
emitterShouldTrail: false,
lifetime: 1000
}
this.beam = Entities.addEntity(props);

View file

@ -360,20 +360,6 @@
var elZoneSkyboxColorBlue = document.getElementById("property-zone-skybox-color-blue");
var elZoneSkyboxURL = document.getElementById("property-zone-skybox-url");
var elZoneAtmosphereCenterX = document.getElementById("property-zone-atmosphere-center-x");
var elZoneAtmosphereCenterY = document.getElementById("property-zone-atmosphere-center-y");
var elZoneAtmosphereCenterZ = document.getElementById("property-zone-atmosphere-center-z");
var elCenterAtmosphereToZone = document.getElementById("center-atmosphere-in-zone");
var elZoneAtmosphereInnerRadius = document.getElementById("property-zone-atmosphere-inner-radius");
var elZoneAtmosphereOuterRadius = document.getElementById("property-zone-atmosphere-outer-radius");
var elZoneAtmosphereMieScattering = document.getElementById("property-zone-atmosphere-mie-scattering");
var elZoneAtmosphereRayleighScattering = document.getElementById("property-zone-atmosphere-rayleigh-scattering");
var elZoneAtmosphereScatteringWavelengthsX = document.getElementById("property-zone-atmosphere-scattering-wavelengths-x");
var elZoneAtmosphereScatteringWavelengthsY = document.getElementById("property-zone-atmosphere-scattering-wavelengths-y");
var elZoneAtmosphereScatteringWavelengthsZ = document.getElementById("property-zone-atmosphere-scattering-wavelengths-z");
var elZoneAtmosphereHasStars = document.getElementById("property-zone-atmosphere-has-stars");
var elPolyVoxSections = document.querySelectorAll(".poly-vox-section");
allSections.push(elPolyVoxSections);
var elVoxelVolumeSizeX = document.getElementById("property-voxel-volume-size-x");
@ -606,20 +592,7 @@
elZoneSkyboxColorBlue.value = properties.skybox.color.blue;
elZoneSkyboxURL.value = properties.skybox.url;
elZoneAtmosphereCenterX.value = properties.atmosphere.center.x;
elZoneAtmosphereCenterY.value = properties.atmosphere.center.y;
elZoneAtmosphereCenterZ.value = properties.atmosphere.center.z;
elZoneAtmosphereInnerRadius.value = properties.atmosphere.innerRadius;
elZoneAtmosphereOuterRadius.value = properties.atmosphere.outerRadius;
elZoneAtmosphereMieScattering.value = properties.atmosphere.mieScattering;
elZoneAtmosphereRayleighScattering.value = properties.atmosphere.rayleighScattering;
elZoneAtmosphereScatteringWavelengthsX.value = properties.atmosphere.scatteringWavelengths.x;
elZoneAtmosphereScatteringWavelengthsY.value = properties.atmosphere.scatteringWavelengths.y;
elZoneAtmosphereScatteringWavelengthsZ.value = properties.atmosphere.scatteringWavelengths.z;
elZoneAtmosphereHasStars.checked = properties.atmosphere.hasStars;
showElements(document.getElementsByClassName('skybox-section'), elZoneBackgroundMode.value == 'skybox');
showElements(document.getElementsByClassName('atmosphere-section'), elZoneBackgroundMode.value == 'atmosphere');
} else if (properties.type == "ParticleEffect") {
for (var i = 0; i < elParticleSections.length; i++) {
elParticleSections[i].style.display = 'block';
@ -874,25 +847,6 @@
elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox','url'));
var zoneAtmosphereCenterChangeFunction = createEmitGroupVec3PropertyUpdateFunction(
'atmosphere','center', elZoneAtmosphereCenterX, elZoneAtmosphereCenterY, elZoneAtmosphereCenterZ);
elZoneAtmosphereCenterX.addEventListener('change', zoneAtmosphereCenterChangeFunction);
elZoneAtmosphereCenterY.addEventListener('change', zoneAtmosphereCenterChangeFunction);
elZoneAtmosphereCenterZ.addEventListener('change', zoneAtmosphereCenterChangeFunction);
elZoneAtmosphereInnerRadius.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('atmosphere','innerRadius'));
elZoneAtmosphereOuterRadius.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('atmosphere','outerRadius'));
elZoneAtmosphereMieScattering.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('atmosphere','mieScattering'));
elZoneAtmosphereRayleighScattering.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('atmosphere','rayleighScattering'));
var zoneAtmosphereScatterWavelengthsChangeFunction = createEmitGroupVec3PropertyUpdateFunction(
'atmosphere','scatteringWavelengths', elZoneAtmosphereScatteringWavelengthsX,
elZoneAtmosphereScatteringWavelengthsY, elZoneAtmosphereScatteringWavelengthsZ);
elZoneAtmosphereScatteringWavelengthsX.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction);
elZoneAtmosphereScatteringWavelengthsY.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction);
elZoneAtmosphereScatteringWavelengthsZ.addEventListener('change', zoneAtmosphereScatterWavelengthsChangeFunction);
elZoneAtmosphereHasStars.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('atmosphere','hasStars'));
var voxelVolumeSizeChangeFunction = createEmitVec3PropertyUpdateFunction(
'voxelVolumeSize', elVoxelVolumeSizeX, elVoxelVolumeSizeY, elVoxelVolumeSizeZ);
elVoxelVolumeSizeX.addEventListener('change', voxelVolumeSizeChangeFunction);
@ -934,12 +888,6 @@
action: "reloadScript"
}));
});
elCenterAtmosphereToZone.addEventListener("click", function() {
EventBridge.emitWebEvent(JSON.stringify({
type: "action",
action: "centerAtmosphereToZone",
}));
});
elPreviewCameraButton.addEventListener("click", function() {
EventBridge.emitWebEvent(JSON.stringify({
type: "action",
@ -1601,7 +1549,6 @@
<select name="SelectBackgroundMode" id="property-zone-background-mode">
<option value='inherit'>Nothing</option>
<option value='skybox'>Skybox</option>
<option value='atmosphere'>Atmosphere</option>
</select>
</div>
</div>
@ -1626,61 +1573,6 @@
<input type="text" id="property-zone-skybox-url" class="url">
</div>
</div>
<div class="sub-section-header zone-section atmosphere-section">
<label>Atmosphere</label>
</div>
<div class="zone-section atmosphere-section property">
<div class="label">Atmosphere Center</div>
<div class="value">
<div class="input-area">X <br><input class="coord" type='number' id="property-zone-atmosphere-center-x"></div>
<div class="input-area">Y <br><input class="coord" type='number' id="property-zone-atmosphere-center-y"></div>
<div class="input-area">Z <br><input class="coord" type='number' id="property-zone-atmosphere-center-z"></div>
<div>
<input type="button" id="center-atmosphere-in-zone" value="Center to Zone">
</div>
</div>
</div>
<div class="zone-section atmosphere-section property">
<div class="label">Atmosphere Inner Radius</div>
<div class="value">
<input class="coord" type='number' id="property-zone-atmosphere-inner-radius" step="1">
</div>
</div>
<div class="zone-section atmosphere-section property">
<div class="label">Atmosphere Outer Radius</div>
<div class="value">
<input class="coord" type='number' id="property-zone-atmosphere-outer-radius" step="1">
</div>
</div>
<div class="zone-section atmosphere-section property">
<div class="label">Atmosphere Mie Scattering</div>
<div class="value">
<input class="coord no-spin" type='number' id="property-zone-atmosphere-mie-scattering" min="0" max="0.5" step="any">
</div>
</div>
<div class="zone-section atmosphere-section property">
<div class="label">Atmosphere Rayleigh Scattering</div>
<div class="value">
<input class="coord no-spin" type='number' id="property-zone-atmosphere-rayleigh-scattering" min="0" max="0.5" step="any">
</div>
</div>
<div class="zone-section atmosphere-section property">
<div class="label">Atmosphere Scattering Wavelenghts</div>
<div class="value">
<div class="input-area">X <br><input class="coord no-spin" type='number' id="property-zone-atmosphere-scattering-wavelengths-x" min="0" max="1" step="any"></div>
<div class="input-area">Y <br><input class="coord no-spin" type='number' id="property-zone-atmosphere-scattering-wavelengths-y" min="0" max="1" step="any"></div>
<div class="input-area">Z <br><input class="coord no-spin" type='number' id="property-zone-atmosphere-scattering-wavelengths-z" min="0" max="1" step="any"></div>
</div>
</div>
<div class="zone-section atmosphere-section property" style="display:none">
<span class="label">Atmosphere Has Stars</span>
<span class="value">
<input type='checkbox' id="property-zone-atmosphere-has-stars">
</span>
</div>
</div>
</body>
</html>

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

@ -540,7 +540,7 @@
var arrowProperties = {
dynamic: true,
collisionless: false,
collisionMask: "static,dynamic,otherAvatar", // workaround: not with kinematic --> no collision with bow
collidesWith: "static,dynamic,otherAvatar", // workaround: not with kinematic --> no collision with bow
velocity: releaseVelocity,
gravity: ARROW_GRAVITY,
lifetime: 10,

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

@ -12,7 +12,7 @@
Script.include("cookies.js");
var MENU = "Developer>Render>Debug Deferred Buffer";
var ACTIONS = ["Off", "Diffuse", "Alpha", "Specular", "Roughness", "Normal", "Depth", "Lighting", "Custom"];
var ACTIONS = ["Off", "Diffuse", "Metallic", "Roughness", "Normal", "Depth", "Lighting", "Shadow", "PyramidDepth", "AmbientOcclusion", "OcclusionBlurred", "Custom"];
var SETTINGS_KEY = "EngineDebugScript.DebugMode";
Number.prototype.clamp = function(min, max) {
@ -52,6 +52,7 @@ var overlaysCounter = new CounterWidget(panel, "Overlays", Render.overlay3D);
var resizing = false;
var previousMode = Settings.getValue(SETTINGS_KEY, -1);
previousMode = 8;
Menu.addActionGroup(MENU, ACTIONS, ACTIONS[previousMode + 1]);
Render.deferredDebugMode = previousMode;
Render.deferredDebugSize = { x: 0.0, y: -1.0, z: 1.0, w: 1.0 }; // Reset to default size
@ -98,12 +99,70 @@ panel.newSlider("Tone Mapping Exposure", -10, 10,
function() { return Render.tone.exposure; },
function (value) { return (value); });
panel.newSlider("Ambient Occlusion Resolution Level", 0.0, 4.0,
function (value) { Render.ambientOcclusion.resolutionLevel = value; },
function() { return Render.ambientOcclusion.resolutionLevel; },
function (value) { return (value); });
panel.newSlider("Ambient Occlusion Radius", 0.0, 2.0,
function (value) { Render.ambientOcclusion.radius = value; },
function() { return Render.ambientOcclusion.radius; },
function (value) { return (value.toFixed(2)); });
panel.newSlider("Ambient Occlusion Level", 0.0, 1.0,
function (value) { Render.ambientOcclusion.level = value; },
function() { return Render.ambientOcclusion.level; },
function (value) { return (value.toFixed(2)); });
panel.newSlider("Ambient Occlusion Num Samples", 1, 32,
function (value) { Render.ambientOcclusion.numSamples = value; },
function() { return Render.ambientOcclusion.numSamples; },
function (value) { return (value); });
panel.newSlider("Ambient Occlusion Num Spiral Turns", 0.0, 30.0,
function (value) { Render.ambientOcclusion.numSpiralTurns = value; },
function() { return Render.ambientOcclusion.numSpiralTurns; },
function (value) { return (value.toFixed(2)); });
panel.newCheckbox("Ambient Occlusion Dithering",
function (value) { Render.ambientOcclusion.ditheringEnabled = value; },
function() { return Render.ambientOcclusion.ditheringEnabled; },
function (value) { return (value); });
panel.newSlider("Ambient Occlusion Falloff Bias", 0.0, 0.2,
function (value) { Render.ambientOcclusion.falloffBias = value; },
function() { return Render.ambientOcclusion.falloffBias; },
function (value) { return (value.toFixed(2)); });
panel.newSlider("Ambient Occlusion Edge Sharpness", 0.0, 1.0,
function (value) { Render.ambientOcclusion.edgeSharpness = value; },
function() { return Render.ambientOcclusion.edgeSharpness; },
function (value) { return (value.toFixed(2)); });
panel.newSlider("Ambient Occlusion Blur Radius", 0.0, 6.0,
function (value) { Render.ambientOcclusion.blurRadius = value; },
function() { return Render.ambientOcclusion.blurRadius; },
function (value) { return (value); });
panel.newSlider("Ambient Occlusion Blur Deviation", 0.0, 3.0,
function (value) { Render.ambientOcclusion.blurDeviation = value; },
function() { return Render.ambientOcclusion.blurDeviation; },
function (value) { return (value.toFixed(2)); });
panel.newSlider("Ambient Occlusion GPU time", 0.0, 10.0,
function (value) {},
function() { return Render.ambientOcclusion.gpuTime; },
function (value) { return (value.toFixed(2) + " ms"); });
var tickTackPeriod = 500;
function updateCounters() {
opaquesCounter.update();
transparentsCounter.update();
overlaysCounter.update();
panel.update("Ambient Occlusion GPU time");
}
Script.setInterval(updateCounters, tickTackPeriod);

View file

@ -0,0 +1,161 @@
//
// weatherBox.js
// examples/widgets/weatherBox
//
// Created by Eric Levin on 1/20/16.
// Copyright 2016 High Fidelity, Inc.
//
// This script creates a weatherBox widget which (in final version) will display the current weather
//
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
Script.include("../libraries/utils.js");
var weatherBox, boxDimensions;
var orientation = Camera.getOrientation();
orientation = Quat.safeEulerAngles(orientation);
orientation.x = 0;
orientation = Quat.fromVec3Degrees(orientation);
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(orientation)));
var emitters = [];
var spheres = [];
createWeatherBox(center);
center.y += boxDimensions.y / 2;
createCloud(center);
for (var i = 0; i < 7; i++) {
createLightningStrike(center)
}
function createLightningStrike(basePosition) {
var normal = Vec3.subtract(position, MyAvatar.position);
normal.y = 0;
var textureURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/textures/lightning.png"
var linePoints = [];
var normals = [];
var strokeWidths = [];
var strokeWidth = 0.02
var currentPointPosition = {x: 0, y: 0, z: 0};
for (var i = 0; i < 8; i++) {
linePoints.push(currentPointPosition);
currentPointPosition = Vec3.sum(currentPointPosition, {x: randFloat(-0.05, 0.05), y: randFloat(-0.1, -0.05), z: randFloat(-0.05, 0.05)});
linePoints.push(currentPointPosition);
normals.push(normal);
normals.push(normal);
strokeWidth -= 0.002;
strokeWidths.push(strokeWidth);
strokeWidths.push(strokeWidth);
}
var position = Vec3.sum(basePosition, {x: randFloat(-boxDimensions.x/20, boxDimensions.x/20), y: 0, z: randFloat(-boxDimensions.x/20, boxDimensions.x/20)});
var bolt = Entities.addEntity({
type: "PolyLine",
textures: textureURL,
position: position,
dimensions: {
x: 10,
y: 10,
z: 10
},
linePoints: linePoints,
normals: normals,
strokeWidths: strokeWidths,
lifetime: randFloat(0.01, 0.2)
});
Script.setTimeout(function() {
createLightningStrike(position)
}, randInt(500, 5000));
}
function createWeatherBox(position) {
var naturalDimensions = {
x: 1.11,
y: 1.3,
z: 1.11
};
boxDimensions = Vec3.multiply(naturalDimensions, 0.7);
var modelURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/models/weatherBox.fbx"
weatherBox = Entities.addEntity({
type: "Model",
name: "Weather Box",
modelURL: modelURL,
position: position,
dimensions: boxDimensions
});
}
function createCloud(position) {
var props = {
"type": "ParticleEffect",
"position": position,
"isEmitting": true,
"maxParticles": 10000,
"lifespan": 3,
"emitRate": 2000,
"emitSpeed": 0.025,
"speedSpread": 0,
"emitDimensions": {
x: boxDimensions.x,
y: boxDimensions.x,
z: 0.1
},
"emitRadiusStart": 1,
"polarStart": 0,
"polarFinish": 1.570796012878418,
"azimuthStart": -3.1415927410125732,
"azimuthFinish": 3.1415927410125732,
"emitAcceleration": {
"x": 0,
"y": 0,
"z": 0
},
"particleRadius": 0.04,
"radiusSpread": 0.02,
"radiusStart": 0.04,
radiusFinish: 0.04,
"colorStart": {
"red": 40,
"green": 40,
"blue": 100
},
color: {
red: 40,
green: 40,
blue: 100
},
"colorFinish": {
"red": 40,
"green": 40,
"blue": 100
},
"alpha": 1,
"alphaSpread": 0,
"alphaStart": 0.3,
"alphaFinish": 0,
"emitterShouldTrail": true,
"textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png"
}
var oceanEmitter = Entities.addEntity(props);
emitters.push(oceanEmitter);
}
function cleanup() {
emitters.forEach(function(emitter) {
Entities.deleteEntity(emitter);
});
spheres.forEach(function(sphere) {
Entities.deleteEntity(sphere);
});
Entities.deleteEntity(weatherBox);
}
Script.scriptEnding.connect(cleanup);

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

@ -20,12 +20,10 @@ find_package(Qt5LinguistTools REQUIRED)
find_package(Qt5LinguistToolsMacros)
if (WIN32)
add_definitions(-D_USE_MATH_DEFINES) # apparently needed to get M_PI and other defines from cmath/math.h
add_definitions(-DWINDOWS_LEAN_AND_MEAN) # needed to make sure windows doesn't go to crazy with its defines
add_definitions(-D_USE_MATH_DEFINES) # apparently needed to get M_PI and other defines from cmath/math.h
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")
@ -45,8 +43,8 @@ else ()
list(REMOVE_ITEM INTERFACE_SRCS ${SPEECHRECOGNIZER_CPP})
endif ()
find_package(Qt5 COMPONENTS
Gui Multimedia Network OpenGL Qml Quick Script Svg
find_package(Qt5 COMPONENTS
Gui Multimedia Network OpenGL Qml Quick Script Svg
WebChannel WebEngine WebEngineWidgets WebKitWidgets WebSockets)
# grab the ui files in resources/ui
@ -65,23 +63,24 @@ 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 "")
# use the add_resources_to_os_x_bundle macro to recurse into resources
@ -89,28 +88,37 @@ 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
@ -121,11 +129,14 @@ if (WIN32)
endif()
# link required hifi libraries
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
link_hifi_libraries(shared octree 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,39 +144,39 @@ target_glew()
target_opengl()
if (WIN32 OR APPLE)
target_faceshift()
target_faceshift()
endif()
# perform standard include and linking for found externals
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
if (${${EXTERNAL}_UPPERCASE}_REQUIRED)
find_package(${EXTERNAL} REQUIRED)
else ()
find_package(${EXTERNAL})
endif ()
if (${${EXTERNAL}_UPPERCASE}_FOUND AND NOT DISABLE_${${EXTERNAL}_UPPERCASE})
add_definitions(-DHAVE_${${EXTERNAL}_UPPERCASE})
# include the library directories (ignoring warnings)
if (NOT ${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS)
set(${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIR})
endif ()
include_directories(SYSTEM ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS})
# perform the system include hack for OS X to ignore warnings
if (APPLE)
foreach(EXTERNAL_INCLUDE_DIR ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS})
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${EXTERNAL_INCLUDE_DIR}")
endforeach()
endif ()
if (NOT ${${EXTERNAL}_UPPERCASE}_LIBRARIES)
set(${${EXTERNAL}_UPPERCASE}_LIBRARIES ${${${EXTERNAL}_UPPERCASE}_LIBRARY})
endif ()
if (NOT APPLE OR NOT ${${EXTERNAL}_UPPERCASE} MATCHES "SIXENSE")
target_link_libraries(${TARGET_NAME} ${${${EXTERNAL}_UPPERCASE}_LIBRARIES})
elseif (APPLE AND NOT INSTALLER_BUILD)
@ -179,15 +190,15 @@ include_directories("${PROJECT_SOURCE_DIR}/src")
target_link_libraries(
${TARGET_NAME}
Qt5::Gui Qt5::Network Qt5::Multimedia Qt5::OpenGL
Qt5::Qml Qt5::Quick Qt5::Script Qt5::Svg
Qt5::Gui Qt5::Network Qt5::Multimedia Qt5::OpenGL
Qt5::Qml Qt5::Quick Qt5::Script Qt5::Svg
Qt5::WebChannel Qt5::WebEngine Qt5::WebEngineWidgets Qt5::WebKitWidgets
)
# Issue causes build failure unless we add this directory.
# See https://bugreports.qt.io/browse/QTBUG-43351
# 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
@ -199,31 +210,63 @@ if (APPLE)
find_library(AppKit AppKit)
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

@ -16,8 +16,6 @@ Windows.Window {
destroyOnCloseButton: false
property alias source: webview.url
function raiseWindow() { Desktop.raise(root) }
Controls.WebView {
id: webview
url: "about:blank"

View file

@ -21,16 +21,10 @@ Windows.Window {
destroyOnCloseButton: false
property alias source: pageLoader.source
function raiseWindow() { Desktop.raise(root) }
Loader {
id: pageLoader
objectName: "Loader"
focus: true
property var dialog: root
Keys.onPressed: {
console.log("QmlWindow pageLoader keypress")
}
}
} // dialog

View file

@ -1,229 +0,0 @@
import Hifi 1.0 as Hifi
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import "controls"
import "styles"
Hifi.VrMenu {
id: root
HifiConstants { id: hifi }
anchors.fill: parent
objectName: "VrMenu"
enabled: false
opacity: 0.0
z: 10000
property int animationDuration: 200
property var models: []
property var columns: []
onEnabledChanged: {
if (enabled && columns.length == 0) {
pushColumn(rootMenu.items);
}
opacity = enabled ? 1.0 : 0.0
offscreenFlags.navigationFocused = enabled;
}
// The actual animator
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.InOutBounce
}
}
onOpacityChanged: {
visible = (opacity != 0.0);
}
onVisibleChanged: {
if (!visible) reset();
}
property var menuBuilder: Component {
VrMenuView {
property int menuDepth: root.models.length - 1
model: root.models[menuDepth]
function fit(position, size, maxposition) {
var padding = 8;
if (position < padding) {
position = padding;
} else if (position + size + padding > maxposition) {
position = maxposition - (size + padding);
}
return position;
}
Component.onCompleted: {
if (menuDepth === 0) {
x = lastMousePosition.x - 20
y = lastMousePosition.y - 20
} else {
var lastColumn = root.columns[menuDepth - 1]
x = lastColumn.x + 64;
y = lastMousePosition.y - height / 2;
}
x = fit(x, width, parent.width);
y = fit(y, height, parent.height);
}
onSelected: {
root.selectItem(menuDepth, item)
}
}
}
function lastColumn() {
return columns[root.columns.length - 1];
}
function pushColumn(items) {
models.push(itemsToModel(items))
if (columns.length) {
var oldColumn = lastColumn();
//oldColumn.enabled = false
}
var newColumn = menuBuilder.createObject(root);
columns.push(newColumn);
forceActiveFocus();
}
function popColumn() {
if (columns.length > 0) {
var curColumn = columns.pop();
curColumn.visible = false;
curColumn.destroy();
models.pop();
}
if (columns.length == 0) {
enabled = false;
return;
}
curColumn = lastColumn();
curColumn.enabled = true;
curColumn.opacity = 1.0;
curColumn.forceActiveFocus();
}
function itemsToModel(items) {
var newListModel = Qt.createQmlObject('import QtQuick 2.2; ListModel {}', root);
for (var i = 0; i < items.length; ++i) {
var item = items[i];
switch (item.type) {
case 2:
newListModel.append({"type":item.type, "name": item.title, "item": item})
break;
case 1:
newListModel.append({"type":item.type, "name": item.text, "item": item})
break;
case 0:
newListModel.append({"type":item.type, "name": "-----", "item": item})
break;
}
}
return newListModel;
}
function selectItem(depth, source) {
var popped = false;
while (depth + 1 < columns.length) {
popColumn()
popped = true
}
switch (source.type) {
case 2:
lastColumn().enabled = false
pushColumn(source.items)
break;
case 1:
if (!popped) source.trigger()
enabled = false
break;
case 0:
break;
}
}
function reset() {
while (columns.length > 0) {
popColumn();
}
}
MouseArea {
anchors.fill: parent
id: mouseArea
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button == Qt.RightButton) {
root.popColumn();
} else {
root.enabled = false;
}
}
}
function addMenu(menu, newMenu) {
return menu.addMenu(newMenu);
}
function addItem(menu, newMenuItem) {
return menu.addItem(newMenuItem);
}
function insertItem(menu, beforeItem, newMenuItem) {
for (var i = 0; i < menu.items.length; ++i) {
if (menu.items[i] === beforeItem) {
return menu.insertItem(i, newMenuItem);
}
}
return addItem(menu, newMenuItem);
}
function removeItem(menu, menuItem) {
menu.removeItem(menuItem);
}
function previousItem() {
if (columns.length) {
lastColumn().incrementCurrentIndex()
}
}
function nextItem() {
if (columns.length) {
lastColumn().decrementCurrentIndex()
}
}
function selectCurrentItem() {
if (columns.length) {
var depth = columns.length - 1;
var index = lastColumn().currentIndex;
if (index >= 0) {
var model = models[depth];
var item = model.get(index).item;
selectItem(depth, item);
}
}
}
Keys.onDownPressed: previousItem();
Keys.onUpPressed: nextItem();
Keys.onSpacePressed: selectCurrentItem();
Keys.onReturnPressed: selectCurrentItem();
Keys.onRightPressed: selectCurrentItem();
Keys.onLeftPressed: popColumn();
Keys.onEscapePressed: popColumn();
}

View file

@ -1,77 +0,0 @@
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import "styles"
ListView {
id: root
HifiConstants { id: hifi }
width: 128
height: count * 32
onEnabledChanged: recalcSize();
onVisibleChanged: recalcSize();
onCountChanged: recalcSize();
signal selected(var item)
highlight: Rectangle {
width: root.currentItem ? root.currentItem.width : 0
height: root.currentItem ? root.currentItem.height : 0
color: "lightsteelblue"; radius: 3
}
delegate: VrMenuItem {
text: name
source: item
onImplicitHeightChanged: root.recalcSize()
onImplicitWidthChanged: root.recalcSize()
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: root.currentIndex = index
onClicked: root.selected(item)
}
}
function recalcSize() {
if (model.count !== count || !visible) {
return;
}
var originalIndex = currentIndex;
var maxWidth = width;
var newHeight = 0;
for (var i = 0; i < count; ++i) {
currentIndex = i;
if (!currentItem) {
continue;
}
if (currentItem && currentItem.implicitWidth > maxWidth) {
maxWidth = currentItem.implicitWidth
}
if (currentItem.visible) {
newHeight += currentItem.implicitHeight
}
}
if (maxWidth > width) {
width = maxWidth;
}
if (newHeight > height) {
height = newHeight
}
currentIndex = originalIndex;
}
Border {
id: border
anchors.fill: parent
anchors.margins: -8
z: parent.z - 1
border.color: hifi.colors.hifiBlue
color: hifi.colors.window
}
}

View file

@ -2,35 +2,15 @@ import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2 as OriginalDialogs;
import "dialogs"
import "../dialogs"
import "../menus"
// This is our primary 'desktop' object to which all VR dialogs and
// windows will be childed.
FocusScope {
id: desktop
anchors.fill: parent;
// Debugging help for figuring out focus issues
property var offscreenWindow;
onOffscreenWindowChanged: offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged);
function onWindowFocusChanged() {
console.log("Focus item is " + offscreenWindow.activeFocusItem);
var focusedItem = offscreenWindow.activeFocusItem ;
if (DebugQML && focusedItem) {
var rect = desktop.mapToItem(desktop, focusedItem.x, focusedItem.y, focusedItem.width, focusedItem.height);
focusDebugger.visible = true
focusDebugger.x = rect.x;
focusDebugger.y = rect.y;
focusDebugger.width = rect.width
focusDebugger.height = rect.height
}
}
Rectangle {
id: focusDebugger;
z: 9999; visible: false; color: "red"
ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 }
}
objectName: "desktop"
// Allows QML/JS to find the desktop through the parent chain
property bool desktopRoot: true
@ -38,38 +18,13 @@ FocusScope {
// The VR version of the primary menu
property var rootMenu: Menu { objectName: "rootMenu" }
// The tool window, one instance
property alias toolWindow: toolWindow
ToolWindow { id: toolWindow }
// FIXME support always on top flags
function raise(item) {
d.raiseWindow(item);
}
Component {
id: messageDialogBuilder
MessageDialog { }
}
Component {
id: nativeMessageDialogBuilder
OriginalDialogs.MessageDialog { }
}
function messageBox(properties) {
// Debugging: native message dialog for comparison
// nativeMessageDialogBuilder.createObject(desktop, properties);
return messageDialogBuilder.createObject(desktop, properties);
}
QtObject {
id: d
readonly property int zBasisNormal: 0
readonly property int zBasisAlwaysOnTop: 4096
readonly property int zBasisModal: 8192
readonly property var messageDialogBuilder: Component { MessageDialog { } }
readonly property var nativeMessageDialogBuilder: Component { OriginalDialogs.MessageDialog { } }
function findChild(item, name) {
for (var i = 0; i < item.children.length; ++i) {
@ -203,6 +158,43 @@ FocusScope {
}
}
MenuMouseHandler { id: menuPopperUpper }
function raise(item) {
d.raiseWindow(item);
}
function messageBox(properties) {
// Debugging: native message dialog for comparison
// d.nativeMessageDialogBuilder.createObject(desktop, properties);
return d.messageDialogBuilder.createObject(desktop, properties);
}
function popupMenu(point) {
menuPopperUpper.popup(desktop, rootMenu.items, point);
}
function toggleMenu(point) {
menuPopperUpper.toggle(desktop, rootMenu.items, point);
}
Keys.onEscapePressed: {
if (menuPopperUpper.closeLastMenu()) {
event.accepted = true;
return;
}
event.accepted = false;
}
Keys.onLeftPressed: {
if (menuPopperUpper.closeLastMenu()) {
event.accepted = true;
return;
}
event.accepted = false;
}
function unfocusWindows() {
var windows = d.getTopLevelWindows();
for (var i = 0; i < windows.length; ++i) {
@ -210,6 +202,36 @@ FocusScope {
}
desktop.focus = true;
}
// Debugging help for figuring out focus issues
property var offscreenWindow;
onOffscreenWindowChanged: {
offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged);
focusHack.start();
}
FocusHack { id: focusHack; }
function onWindowFocusChanged() {
console.log("Focus item is " + offscreenWindow.activeFocusItem);
var focusedItem = offscreenWindow.activeFocusItem ;
if (DebugQML && focusedItem) {
var rect = desktop.mapToItem(null, focusedItem.x, focusedItem.y, focusedItem.width, focusedItem.height);
focusDebugger.visible = true
focusDebugger.x = rect.x;
focusDebugger.y = rect.y;
focusDebugger.width = rect.width
focusDebugger.height = rect.height
}
}
Rectangle {
id: focusDebugger;
z: 9999; visible: false; color: "red"
ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 }
}
}

View file

@ -0,0 +1,26 @@
import QtQuick 2.5
FocusScope {
id: root
TextInput {
id: textInput;
focus: true
width: 10; height: 10
onActiveFocusChanged: root.destroy()
}
Timer {
id: focusTimer
running: false
interval: 100
onTriggered: textInput.forceActiveFocus()
}
function start() {
focusTimer.running = true;
}
}

View file

@ -8,23 +8,20 @@ import "../windows"
import "../styles"
// Work in progress....
Window {
ModalWindow {
id: root
HifiConstants { id: hifi }
signal selectedFile(var file);
signal canceled();
anchors.centerIn: parent
resizable: true
width: 640
height: 480
modality: Qt.ApplicationModal
property string settingsName: ""
property alias folder: folderModel.folder
property alias filterModel: selectionType.model
Rectangle {
anchors.fill: parent
color: "white"

View file

@ -7,19 +7,14 @@ import "../styles"
import "../windows"
// FIXME respect default button functionality
// FIXME force active focus at all times (modal dialog)
Window {
ModalWindow {
id: root
HifiConstants { id: hifi }
implicitWidth: 640
implicitHeight: 320
destroyOnCloseButton: true
destroyOnInvisible: true
visible: true
modality: Qt.ApplicationModal
anchors.centerIn: parent
frame: ModalFrame {}
signal selected(int button);

View file

@ -14,6 +14,7 @@ Window {
resizable: true
destroyOnInvisible: true
x: 40; y: 40
implicitWidth: 384; implicitHeight: 640
property var scripts: ScriptDiscoveryService;
property var scriptsModel: scripts.scriptsModelFilter
@ -77,7 +78,7 @@ Window {
}
function loadFromFile() {
var fileDialog = fileDialogBuilder.createObject(Desktop, { filterModel: fileFilters });
var fileDialog = fileDialogBuilder.createObject(desktop, { filterModel: fileFilters });
fileDialog.canceled.connect(function(){
console.debug("Cancelled file open")
})
@ -90,7 +91,7 @@ Window {
Rectangle {
color: "white"
implicitWidth: 384; implicitHeight: 640
anchors.fill: parent
Item {
anchors { fill: parent; margins: 8 }

View file

@ -0,0 +1,15 @@
import QtQuick 2.5
import "../desktop"
import ".."
Desktop {
id: desktop
// The tool window, one instance
property alias toolWindow: toolWindow
ToolWindow { id: toolWindow }
}

View file

@ -0,0 +1,149 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import "."
Item {
id: root
property int zBasis: 8192 - 1024
anchors.fill: parent
MouseArea {
id: menuRoot;
anchors.fill: parent
enabled: d.topMenu !== null
onClicked: {
d.clearMenus();
}
}
QtObject {
id: d
property var menuStack: []
property var topMenu: null;
property var modelMaker: Component { ListModel { } }
property var menuViewMaker: Component {
VrMenuView {
id: subMenu
onSelected: d.handleSelection(subMenu, currentItem, item)
}
}
function toModel(items) {
var result = modelMaker.createObject(desktop);
for (var i = 0; i < items.length; ++i) {
var item = items[i];
if (!item.visible) continue;
switch (item.type) {
case MenuItemType.Menu:
result.append({"name": item.title, "item": item})
break;
case MenuItemType.Item:
result.append({"name": item.text, "item": item})
break;
case MenuItemType.Separator:
result.append({"name": "", "item": item})
break;
}
}
return result;
}
function popMenu() {
if (menuStack.length) {
menuStack.pop().destroy();
}
if (menuStack.length) {
topMenu = menuStack[menuStack.length - 1];
topMenu.focus = true;
} else {
topMenu = null;
offscreenFlags.navigationFocused = false;
menuRoot.enabled = false;
}
}
function pushMenu(newMenu) {
menuStack.push(newMenu);
topMenu = newMenu;
topMenu.focus = true;
offscreenFlags.navigationFocused = true;
}
function clearMenus() {
while (menuStack.length) {
popMenu()
}
}
function clampMenuPosition(menu) {
var margins = 0;
if (menu.x < margins) {
menu.x = margins
} else if ((menu.x + menu.width + margins) > root.width) {
menu.x = root.width - (menu.width + margins);
}
if (menu.y < 0) {
menu.y = margins
} else if ((menu.y + menu.height + margins) > root.height) {
menu.y = root.height - (menu.height + margins);
}
}
function buildMenu(items, targetPosition) {
var model = toModel(items);
var newMenu = menuViewMaker.createObject(menuRoot, { model: model, z: topMenu ? topMenu.z + 1 : zBasis });
if (targetPosition) {
newMenu.x = targetPosition.x
newMenu.y = targetPosition.y - newMenu.height / 3 * 1
}
clampMenuPosition(newMenu);
pushMenu(newMenu);
return newMenu;
}
function handleSelection(parentMenu, selectedItem, item) {
while (topMenu && topMenu !== parentMenu) {
popMenu();
}
switch (item.type) {
case MenuItemType.Menu:
var target = Qt.vector2d(topMenu.x, topMenu.y).plus(Qt.vector2d(selectedItem.x + 96, selectedItem.y));
buildMenu(item.items, target).objectName = item.title;
break;
case MenuItemType.Item:
console.log("Triggering " + item.text)
item.trigger();
clearMenus();
break;
}
}
}
function popup(parent, items, point) {
d.clearMenus();
menuRoot.enabled = true;
d.buildMenu(items, point);
}
function toggle(parent, items, point) {
if (d.topMenu) {
d.clearMenus();
return;
}
popup(parent, items, point);
}
function closeLastMenu() {
if (d.menuStack.length) {
d.popMenu();
return true;
}
return false;
}
}

View file

@ -1,16 +1,13 @@
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import "controls"
import "styles"
import "../controls"
import "../styles"
Item {
id: root
HifiConstants {
id: hifi
}
// The model object
HifiConstants { id: hifi }
property alias text: label.text
property var source

View file

@ -0,0 +1,100 @@
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import "../styles"
FocusScope {
id: root
implicitHeight: border.height
implicitWidth: border.width
property alias currentItem: listView.currentItem
property alias model: listView.model
signal selected(var item)
Border {
id: border
anchors.fill: listView
anchors.margins: -8
border.color: hifi.colors.hifiBlue
color: hifi.colors.window
// color: "#7f7f7f7f"
}
ListView {
id: listView
x: 8; y: 8
HifiConstants { id: hifi }
width: 128
height: count * 32
onEnabledChanged: recalcSize();
onVisibleChanged: recalcSize();
onCountChanged: recalcSize();
focus: true
highlight: Rectangle {
width: listView.currentItem ? listView.currentItem.width : 0
height: listView.currentItem ? listView.currentItem.height : 0
color: "lightsteelblue"; radius: 3
}
delegate: VrMenuItem {
text: name
source: item
onImplicitHeightChanged: listView.recalcSize()
onImplicitWidthChanged: listView.recalcSize()
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: listView.currentIndex = index
onClicked: root.selected(item)
}
}
function recalcSize() {
if (model.count !== count || !visible) {
return;
}
var originalIndex = currentIndex;
var maxWidth = width;
var newHeight = 0;
for (var i = 0; i < count; ++i) {
currentIndex = i;
if (!currentItem) {
continue;
}
if (currentItem && currentItem.implicitWidth > maxWidth) {
maxWidth = currentItem.implicitWidth
}
if (currentItem.visible) {
newHeight += currentItem.implicitHeight
}
}
if (maxWidth > width) {
width = maxWidth;
}
if (newHeight > height) {
height = newHeight
}
currentIndex = originalIndex;
}
function previousItem() { currentIndex = (currentIndex + count - 1) % count; }
function nextItem() { currentIndex = (currentIndex + count + 1) % count; }
function selectCurrentItem() { if (currentIndex != -1) root.selected(currentItem.source); }
Keys.onUpPressed: previousItem();
Keys.onDownPressed: nextItem();
Keys.onSpacePressed: selectCurrentItem();
Keys.onRightPressed: selectCurrentItem();
Keys.onReturnPressed: selectCurrentItem();
}
}

View file

@ -17,9 +17,10 @@ Frame {
color: "#7f7f7f7f";
radius: 3;
MouseArea {
enabled: window.visible
anchors.fill: parent
acceptedButtons: Qt.AllButtons
onClicked: { }
onClicked: {}
onDoubleClicked: {}
onPressAndHold: {}
onReleased: {}

View file

@ -0,0 +1,12 @@
import QtQuick 2.5
import "."
Window {
id: root
anchors.centerIn: parent
modality: Qt.ApplicationModal
frame: ModalFrame{}
}

View file

@ -69,28 +69,9 @@ Fadable {
// Default to a standard frame. Can be overriden to provide custom
// frame styles, like a full desktop frame to simulate a modal window
property var frame;
property var frame: DefaultFrame { }
Component {
id: defaultFrameBuilder;
DefaultFrame { anchors.fill: parent }
}
Component {
id: modalFrameBuilder;
ModalFrame { anchors.fill: parent }
}
Component.onCompleted: {
if (!frame) {
if (modality === Qt.NonModal) {
frame = defaultFrameBuilder.createObject(window);
} else {
frame = modalFrameBuilder.createObject(window);
}
}
raise();
}
Component.onCompleted: raise();
children: [ frame, content, activator ]
@ -114,7 +95,7 @@ Fadable {
function raise() {
if (visible && parent) {
Desktop.raise(window)
desktop.raise(window)
if (!focus) {
focus = true;
}

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>
@ -303,7 +306,7 @@ bool setupEssentials(int& argc, char** argv) {
listenPort = atoi(portStr);
}
// Set build version
QCoreApplication::setApplicationVersion(BUILD_VERSION);
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
Setting::preInit();
@ -420,9 +423,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
auto controllerScriptingInterface = DependencyManager::get<controller::ScriptingInterface>().data();
_controllerScriptingInterface = dynamic_cast<ControllerScriptingInterface*>(controllerScriptingInterface);
// to work around the Qt constant wireless scanning, set the env for polling interval very high
const QByteArray EXTREME_BEARER_POLL_TIMEOUT = QString::number(INT_MAX).toLocal8Bit();
qputenv("QT_BEARER_POLL_TIMEOUT", EXTREME_BEARER_POLL_TIMEOUT);
_entityClipboard->createRootElement();
@ -796,7 +796,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
} else if (action == controller::toInt(controller::Action::CYCLE_CAMERA)) {
cycleCamera();
} else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) {
VrMenu::toggle(); // show context menu even on non-stereo displays
offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QCursor::pos()));
} else if (action == controller::toInt(controller::Action::RETICLE_X)) {
auto oldPos = QCursor::pos();
auto newPos = oldPos;
@ -1179,7 +1179,6 @@ void Application::initializeUi() {
AddressBarDialog::registerType();
ErrorDialog::registerType();
LoginDialog::registerType();
VrMenu::registerType();
Tooltip::registerType();
UpdateDialog::registerType();
@ -1189,7 +1188,7 @@ void Application::initializeUi() {
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
// OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to
// support the window management and scripting proxies for VR use
offscreenUi->createDesktop();
offscreenUi->createDesktop(QString("hifi/Desktop.qml"));
// FIXME either expose so that dialogs can set this themselves or
// do better detection in the offscreen UI of what has focus
@ -1247,8 +1246,6 @@ void Application::initializeUi() {
rootContext->setContextProperty("Render", DependencyManager::get<RenderScriptingInterface>().data());
_glWidget->installEventFilter(offscreenUi.data());
VrMenu::load();
VrMenu::executeQueuedLambdas();
offscreenUi->setMouseTranslator([=](const QPointF& pt) {
QPointF result = pt;
auto displayPlugin = getActiveDisplayPlugin();
@ -1886,12 +1883,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
break;
}
case Qt::Key_A:
if (isShifted) {
Menu::getInstance()->triggerOption(MenuOption::Atmosphere);
}
break;
case Qt::Key_Backslash:
Menu::getInstance()->triggerOption(MenuOption::Chat);
break;
@ -2066,7 +2057,8 @@ void Application::keyPressEvent(QKeyEvent* event) {
void Application::keyReleaseEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Alt && _altPressed && hasFocus()) {
VrMenu::toggle(); // show context menu even on non-stereo displays
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QCursor::pos()));
}
_keysPressed.remove(event->key());
@ -2698,8 +2690,6 @@ void Application::init() {
// Make sure Login state is up to date
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
_environment.init();
DependencyManager::get<DeferredLightingEffect>()->init();
DependencyManager::get<AvatarManager>()->init();
@ -3620,10 +3610,6 @@ public:
typedef Payload::DataPointer Pointer;
Stars _stars;
Environment* _environment;
BackgroundRenderData(Environment* environment) : _environment(environment) {
}
static render::ItemID _item; // unique WorldBoxRenderData
};
@ -3665,63 +3651,8 @@ namespace render {
"Application::payloadRender<BackgroundRenderData>() ... stars...");
// should be the first rendering pass - w/o depth buffer / lighting
// compute starfield alpha based on distance from atmosphere
float alpha = 1.0f;
bool hasStars = true;
if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
// TODO: handle this correctly for zones
const EnvironmentData& closestData = background->_environment->getClosestData(args->_viewFrustum->getPosition()); // was theCamera instead of _viewFrustum
if (closestData.getHasStars()) {
const float APPROXIMATE_DISTANCE_FROM_HORIZON = 0.1f;
const float DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON = 0.2f;
glm::vec3 sunDirection = (args->_viewFrustum->getPosition()/*getAvatarPosition()*/ - closestData.getSunLocation())
/ closestData.getAtmosphereOuterRadius();
float height = glm::distance(args->_viewFrustum->getPosition()/*theCamera.getPosition()*/, closestData.getAtmosphereCenter());
if (height < closestData.getAtmosphereInnerRadius()) {
// If we're inside the atmosphere, then determine if our keyLight is below the horizon
alpha = 0.0f;
if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) {
float directionY = glm::clamp(sunDirection.y,
-APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON)
+ APPROXIMATE_DISTANCE_FROM_HORIZON;
alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON);
}
} else if (height < closestData.getAtmosphereOuterRadius()) {
alpha = (height - closestData.getAtmosphereInnerRadius()) /
(closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius());
if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) {
float directionY = glm::clamp(sunDirection.y,
-APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON)
+ APPROXIMATE_DISTANCE_FROM_HORIZON;
alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON);
}
}
} else {
hasStars = false;
}
}
// finally render the starfield
if (hasStars) {
background->_stars.render(args, alpha);
}
// draw the sky dome
if (/*!selfAvatarOnly &&*/ Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
PerformanceTimer perfTimer("atmosphere");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... atmosphere...");
background->_environment->renderAtmospheres(batch, *(args->_viewFrustum));
}
static const float alpha = 1.0f;
background->_stars.render(args, alpha);
}
}
break;
@ -3761,12 +3692,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
// Background rendering decision
if (BackgroundRenderData::_item == 0) {
auto backgroundRenderData = make_shared<BackgroundRenderData>(&_environment);
auto backgroundRenderData = make_shared<BackgroundRenderData>();
auto backgroundRenderPayload = make_shared<BackgroundRenderData::Payload>(backgroundRenderData);
BackgroundRenderData::_item = _main3DScene->allocateID();
pendingChanges.resetItem(BackgroundRenderData::_item, backgroundRenderPayload);
} else {
}
// Assuming nothing get's rendered through that
@ -3806,7 +3735,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity());
DependencyManager::get<DeferredLightingEffect>()->setGlobalAtmosphere(skyStage->getAtmosphere());
auto skybox = model::SkyboxPointer();
if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) {
@ -3847,6 +3775,8 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
auto engineContext = _renderEngine->getRenderContext();
renderInterface->setItemCounts(engineContext->getItemsConfig());
renderInterface->setJobGPUTimes(engineContext->getAmbientOcclusion().gpuTime);
}
activeRenderingThread = nullptr;
@ -5181,3 +5111,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

@ -44,7 +44,6 @@
#include "avatar/MyAvatar.h"
#include "Bookmarks.h"
#include "Camera.h"
#include "Environment.h"
#include "FileLogger.h"
#include "gpu/Context.h"
#include "Menu.h"
@ -89,7 +88,7 @@ class Application;
class Application : public QApplication, public AbstractViewStateInterface, public AbstractScriptingServicesInterface, public AbstractUriHandler {
Q_OBJECT
// TODO? Get rid of those
friend class OctreePacketProcessor;
friend class PluginContainerProxy;
@ -102,15 +101,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 +128,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; }
@ -151,7 +150,7 @@ public:
Overlays& getOverlays() { return _overlays; }
bool isForeground() const { return _isForeground; }
uint32_t getFrameCount() { return _frameCount; }
float getFps() const { return _fps; }
float getTargetFrameRate(); // frames/second
@ -164,7 +163,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);
@ -172,8 +171,6 @@ public:
virtual QThread* getMainThread() { return thread(); }
virtual PickRay computePickRay(float x, float y) const;
virtual glm::vec3 getAvatarPosition() const;
virtual void overrideEnvironmentData(const EnvironmentData& newData) { _environment.override(newData); }
virtual void endOverrideEnvironmentData() { _environment.endOverride(); }
virtual qreal getDevicePixelRatio();
void setActiveDisplayPlugin(const QString& pluginName);
@ -208,9 +205,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 +242,9 @@ public slots:
void toggleLogDialog();
void toggleRunningScriptsWidget();
void handleLocalServerConnection();
void readArgumentsFromLocalSocket();
void showFriendsWindow();
void packageModel();
@ -258,7 +258,7 @@ public slots:
void resetSensors(bool andReload = false);
void setActiveFaceTracker();
#ifdef HAVE_IVIEWHMD
void setActiveEyeTracker();
void calibrateEyeTracker1Point();
@ -275,11 +275,11 @@ public slots:
void reloadResourceCaches();
void crashApplication();
void rotationModeChanged();
void runTests();
private slots:
void clearDomainOctreeDetails();
void idle(uint64_t now);
@ -291,12 +291,12 @@ private slots:
void faceTrackerMuteToggled();
void activeChanged(Qt::ApplicationState state);
void domainSettingsReceived(const QJsonObject& domainSettingsObject);
void handleDomainConnectionDeniedPacket(QSharedPointer<ReceivedMessage> message);
void notifyPacketVersionMismatch();
void loadSettings();
void saveSettings();
@ -318,13 +318,13 @@ private slots:
void packetSent(quint64 length);
void updateDisplayMode();
void updateInputModes();
private:
void initDisplay();
void init();
void cleanupBeforeQuit();
void emptyLocalCache();
void update(float deltaTime);
@ -344,45 +344,45 @@ private:
void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard = false);
int sendNackPackets();
void takeSnapshot();
MyAvatar* getMyAvatar() const;
void checkSkeleton();
void initializeAcceptedFiles();
int getRenderAmbientLight() const;
void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false, bool billboard = false);
bool importSVOFromURL(const QString& urlString);
bool nearbyEntitiesAreReadyForPhysics();
int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode);
void trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket);
void resizeEvent(QResizeEvent* size);
void keyPressEvent(QKeyEvent* event);
void keyReleaseEvent(QKeyEvent* event);
void focusOutEvent(QFocusEvent* event);
void focusInEvent(QFocusEvent* event);
void mouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0);
void mousePressEvent(QMouseEvent* event, unsigned int deviceID = 0);
void mouseDoublePressEvent(QMouseEvent* event, unsigned int deviceID = 0);
void mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0);
void touchBeginEvent(QTouchEvent* event);
void touchEndEvent(QTouchEvent* event);
void touchUpdateEvent(QTouchEvent* event);
void wheelEvent(QWheelEvent* event);
void dropEvent(QDropEvent* event);
void dragEnterEvent(QDragEnterEvent* event);
bool _dependencyManagerIsSetup;
@ -437,8 +437,6 @@ private:
float _rotateMirror;
float _raiseMirror;
Environment _environment;
QSet<int> _keysPressed;
bool _enableProcessOctreeThread;
@ -461,7 +459,7 @@ private:
quint64 _lastNackTime;
quint64 _lastSendDownstreamAudioStats;
bool _aboutToQuit;
Bookmarks* _bookmarks;
@ -470,9 +468,9 @@ private:
QThread _settingsThread;
QTimer _settingsTimer;
GLCanvas* _glWidget{ nullptr };
typedef bool (Application::* AcceptURLMethod)(const QString &);
static const QHash<QString, AcceptURLMethod> _acceptedExtensions;

View file

@ -323,7 +323,6 @@ Menu::Menu() {
// Developer > Render >>>
MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, 0, true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DebugAmbientOcclusion);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DebugShadows);

View file

@ -154,7 +154,6 @@ namespace MenuOption {
const QString AnimDebugDrawPosition= "Debug Draw Position";
const QString Antialiasing = "Antialiasing";
const QString AssetMigration = "ATP Asset Migration";
const QString Atmosphere = "Atmosphere";
const QString Attachments = "Attachments...";
const QString AudioNetworkStats = "Audio Network Stats";
const QString AudioNoiseReduction = "Audio Noise Reduction";
@ -187,8 +186,8 @@ namespace MenuOption {
const QString CopyPath = "Copy Path to Clipboard";
const QString CoupleEyelids = "Couple Eyelids";
const QString CrashInterface = "Crash Interface";
const QString DebugAmbientOcclusion = "Debug Ambient Occlusion";
const QString DebugShadows = "Debug Shadows";
const QString DebugShadows = "Shadows";
const QString DebugAmbientOcclusion = "Ambient Occlusion";
const QString DecreaseAvatarSize = "Decrease Avatar Size";
const QString DeleteBookmark = "Delete Bookmark...";
const QString DisableActivityLogger = "Disable Activity Logger";

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

@ -1230,3 +1230,33 @@ void Avatar::updatePalms() {
_leftPalmPositionCache.set(getUncachedLeftPalmPosition());
_rightPalmPositionCache.set(getUncachedRightPalmPosition());
}
void Avatar::setParentID(const QUuid& parentID) {
if (!isMyAvatar()) {
return;
}
bool success;
Transform beforeChangeTransform = getTransform(success);
SpatiallyNestable::setParentID(parentID);
if (success) {
setTransform(beforeChangeTransform, success);
if (!success) {
qDebug() << "Avatar::setParentID failed to reset avatar's location.";
}
}
}
void Avatar::setParentJointIndex(quint16 parentJointIndex) {
if (!isMyAvatar()) {
return;
}
bool success;
Transform beforeChangeTransform = getTransform(success);
SpatiallyNestable::setParentJointIndex(parentJointIndex);
if (success) {
setTransform(beforeChangeTransform, success);
if (!success) {
qDebug() << "Avatar::setParentJointIndex failed to reset avatar's location.";
}
}
}

View file

@ -167,6 +167,12 @@ public:
using SpatiallyNestable::setOrientation;
virtual void setOrientation(const glm::quat& orientation) override;
// these call through to the SpatiallyNestable versions, but they are here to expose these to javascript.
Q_INVOKABLE virtual const QUuid getParentID() const { return SpatiallyNestable::getParentID(); }
Q_INVOKABLE virtual void setParentID(const QUuid& parentID);
Q_INVOKABLE virtual quint16 getParentJointIndex() const { return SpatiallyNestable::getParentJointIndex(); }
Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex);
// NOT thread safe, must be called on main thread.
glm::vec3 getUncachedLeftPalmPosition() const;
glm::quat getUncachedLeftPalmRotation() const;

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

@ -134,7 +134,7 @@ glm::vec3 AvatarMotionState::getObjectGravity() const {
}
// virtual
const QUuid& AvatarMotionState::getObjectID() const {
const QUuid AvatarMotionState::getObjectID() const {
return _avatar->getSessionUUID();
}

View file

@ -53,7 +53,7 @@ public:
virtual glm::vec3 getObjectAngularVelocity() const override;
virtual glm::vec3 getObjectGravity() const override;
virtual const QUuid& getObjectID() const override;
virtual const QUuid getObjectID() const override;
virtual QUuid getSimulatorID() const override;

View file

@ -43,7 +43,6 @@
#include "Application.h"
#include "devices/Faceshift.h"
#include "AvatarManager.h"
#include "Environment.h"
#include "Menu.h"
#include "MyAvatar.h"
#include "Physics.h"

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,71 +22,72 @@
#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[]) {
disableQtBearerPoll(); // Fixes wifi ping spikes
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();
// Debug option to demonstrate that the client's local time does not
// need to be in sync with any other network node. This forces clock
// Debug option to demonstrate that the client's local time does not
// need to be in sync with any other network node. This forces clock
// skew for the individual client
const char* CLOCK_SKEW = "--clockSkew";
const char* clockSkewOption = getCmdOption(argc, argv, CLOCK_SKEW);
@ -102,19 +106,26 @@ 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;
}
}

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