Merge remote-tracking branch 'upstream/master' into parenting

This commit is contained in:
HifiExperiments 2020-08-04 08:52:13 -07:00
commit 0d62798860
89 changed files with 16653 additions and 133 deletions

View file

@ -9,7 +9,7 @@ This variable is set by the `project(hifi)` command in `CMakeLists.txt` to `C:/P
### Packaging
To produce an installer, run the `package` target.
To produce an installer, run the `package` target. However you will want to follow the steps specific to your platform below.
#### Windows
@ -62,7 +62,6 @@ To produce an executable installer on Windows, the following are required:
1. Perform a clean cmake from a new terminal.
1. Open the `vircadia.sln` solution with elevated (administrator) permissions on Visual Studio and select the **Release** configuration.
1. Build the solution.
1. Build CMakeTargets->INSTALL
1. Build `packaged-server-console-npm-install` (found under **hidden/Server Console**)
1. Build `packaged-server-console` (found under **Server Console**)
This will add 2 folders to `build\server-console\` -

View file

@ -615,6 +615,10 @@ void Agent::setIsAvatar(bool isAvatar) {
delete _avatarQueryTimer;
_avatarQueryTimer = nullptr;
// Clear the skeleton model so that if agent is set to an avatar again the skeleton model is (re)loaded.
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
scriptedAvatar->setSkeletonModelURL(QUrl());
// The avatar mixer never times out a connection (e.g., based on identity or data packets)
// but rather keeps avatars in its list as long as "connected". As a result, clients timeout
// when we stop sending identity, but then get woken up again by the mixer itself, which sends

View file

@ -23,6 +23,7 @@
#include <AvatarLogging.h>
#include <EntityItem.h>
#include <EntityItemProperties.h>
#include <NetworkingConstants.h>
ScriptableAvatar::ScriptableAvatar() {
@ -221,7 +222,7 @@ void ScriptableAvatar::updateJointMappings() {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL);
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
DependencyManager::get<ResourceRequestObserver>()->update(
_skeletonModelURL, -1, "AvatarData::updateJointMappings");
QNetworkReply* networkReply = networkAccessManager.get(networkRequest);

View file

@ -122,7 +122,7 @@ bool DomainServer::forwardMetaverseAPIRequest(HTTPConnection* connection,
QUrl url{ MetaverseAPI::getCurrentMetaverseServerURL().toString() + metaversePath };
QNetworkRequest req(url);
req.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
req.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
if (accessTokenVariant.isValid()) {
@ -2458,7 +2458,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
url.setQuery("access_token=" + accessTokenVariant.toString());
QNetworkRequest req(url);
req.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
req.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply* reply = NetworkAccessManager::getInstance().put(req, doc.toJson());
@ -2559,7 +2559,7 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u
QNetworkRequest tokenRequest(tokenRequestUrl);
tokenRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
tokenRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
tokenRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
tokenRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply* tokenReply = NetworkAccessManager::getInstance().post(tokenRequest, tokenPostBody.toLocal8Bit());
@ -2871,7 +2871,7 @@ QNetworkReply* DomainServer::profileRequestGivenTokenReply(QNetworkReply* tokenR
QNetworkRequest profileRequest(profileURL);
profileRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
profileRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
profileRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
return NetworkAccessManager::getInstance().get(profileRequest);
}

View file

@ -121,14 +121,14 @@ if (APPLE)
# configure CMake to use a custom Info.plist
set_target_properties(${this_target} PROPERTIES MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in)
set(MACOSX_BUNDLE_BUNDLE_NAME "High Fidelity")
set(MACOSX_BUNDLE_BUNDLE_NAME "Vircadia")
if (PRODUCTION_BUILD)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.interface)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.vircadia.interface)
else ()
if (DEV_BUILD)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.interface-dev)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.vircadia.interface-dev)
elseif (PR_BUILD)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.interface-pr)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.vircadia.interface-pr)
endif ()
endif ()

View file

@ -7,7 +7,7 @@ MessageDialog {
objectName: "ConnectionFailureDialog"
title: "No Connection"
text: "Unable to connect to this domain. Click the 'GO TO' button on the toolbar to visit another domain."
text: "Unable to connect to this domain. Click the 'EXPLORE' button on the toolbar to visit another domain."
buttons: OriginalDialogs.StandardButton.Ok
icon: OriginalDialogs.StandardIcon.Warning
defaultButton: OriginalDialogs.StandardButton.NoButton;

View file

@ -137,7 +137,7 @@ Item {
if (webViewCoreUserAgent !== undefined) {
webViewCore.profile.httpUserAgent = webViewCoreUserAgent
} else {
webViewCore.profile.httpUserAgent += " (HighFidelityInterface)";
webViewCore.profile.httpUserAgent += " (VircadiaInterface)";
}
// Ensure the JS from the web-engine makes it to our logging
webViewCore.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {

View file

@ -19,7 +19,7 @@ Item {
buttons: OriginalDialogs.StandardButton.Ok,
defaultButton: OriginalDialogs.StandardButton.NoButton,
title: "No Connection",
text: "Unable to connect to this domain. Click the 'GO TO' button on the toolbar to visit another domain."
text: "Unable to connect to this domain. Click the 'EXPLORE' button on the toolbar to visit another domain."
});
object.selected.connect(function(button) {
if (button === OriginalDialogs.StandardButton.Ok) {

View file

@ -336,8 +336,8 @@ Item {
height: parent.height
colorScheme: hifi.colorSchemes.dark
minimumValue: 0.25
maximumValue: 1.0
stepSize: 0.02
maximumValue: 2.0
stepSize: 0.05
value: Render.viewportResolutionScale
live: true

View file

@ -2614,7 +2614,7 @@ QString Application::getUserAgent() {
return userAgent;
}
QString userAgent = "Mozilla/5.0 (HighFidelityInterface/" + BuildInfo::VERSION + "; "
QString userAgent = NetworkingConstants::VIRCADIA_USER_AGENT + "/" + BuildInfo::VERSION + "; "
+ QSysInfo::productType() + " " + QSysInfo::productVersion() + ")";
auto formatPluginName = [](QString name) -> QString { return name.trimmed().replace(" ", "-"); };
@ -3939,12 +3939,15 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers;
// when --url in command line, teleport to location
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
int urlIndex = arguments().indexOf(HIFI_URL_COMMAND_LINE_KEY);
QString addressLookupString;
if (urlIndex != -1) {
QUrl url(arguments().value(urlIndex + 1));
// when --url in command line, teleport to location
QCommandLineParser parser;
QCommandLineOption urlOption("url", "", "value");
parser.addOption(urlOption);
parser.parse(arguments());
if (parser.isSet(urlOption)) {
QUrl url = QUrl(parser.value(urlOption));
if (url.scheme() == URL_SCHEME_HIFIAPP) {
Setting::Handle<QVariant>("startUpApp").set(url.path());
} else {
@ -7655,7 +7658,7 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = QNetworkRequest(url);
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(networkRequest);
int requestNumber = ++_avatarAttachmentRequest;
connect(reply, &QNetworkReply::finished, [this, reply, url, requestNumber]() {

View file

@ -722,7 +722,7 @@ public:
* @function MyAvatar.restoreHandAnimation
* @param isLeft {boolean} Set to true if using the left hand
* @example <caption> Override left hand animation for three seconds. </caption>
* var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx";
* var ANIM_URL = "https://apidocs.vircadia.dev/models/ClapHands_Standing.fbx";
* MyAvatar.overrideHandAnimation(isLeft, ANIM_URL, 30, true, 0, 53);
* Script.setTimeout(function () {
* MyAvatar.restoreHandAnimation();
@ -780,7 +780,7 @@ public:
* hanging at its sides when it is not moving, the avatar will stand and clap its hands. Note that just as it did before, as soon as the avatar
* starts to move, the animation will smoothly blend into the walk animation used by the "walkFwd" animation role.</caption>
* // An animation of the avatar clapping its hands while standing. Restore default after 30s.
* var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx";
* var ANIM_URL = "https://apidocs.vircadia.dev/models/ClapHands_Standing.fbx";
* MyAvatar.overrideRoleAnimation("idleStand", ANIM_URL, 30, true, 0, 53);
* Script.setTimeout(function () {
* MyAvatar.restoreRoleAnimation();

View file

@ -407,13 +407,13 @@ void MyCharacterController::clearDetailedMotionStates() {
}
void MyCharacterController::buildPhysicsTransaction(PhysicsEngine::Transaction& transaction) {
for (size_t i = 0; i < _detailedMotionStates.size(); i++) {
_detailedMotionStates[i]->forceActive();
for (auto& detailedMotionState : _detailedMotionStates) {
detailedMotionState->forceActive();
}
if (_pendingFlags & PENDING_FLAG_REMOVE_DETAILED_FROM_SIMULATION) {
_pendingFlags &= ~PENDING_FLAG_REMOVE_DETAILED_FROM_SIMULATION;
for (size_t i = 0; i < _detailedMotionStates.size(); i++) {
transaction.objectsToRemove.push_back(_detailedMotionStates[i]);
for (auto& detailedMotionState : _detailedMotionStates) {
transaction.objectsToRemove.push_back(detailedMotionState);
}
// NOTE: the DetailedMotionStates are deleted after being added to PhysicsEngine::Transaction::_objectsToRemove
// See AvatarManager::handleProcessedPhysicsTransaction()

View file

@ -116,10 +116,10 @@ void OtherAvatar::updateSpaceProxy(workload::Transaction& transaction) const {
int OtherAvatar::parseDataFromBuffer(const QByteArray& buffer) {
int32_t bytesRead = Avatar::parseDataFromBuffer(buffer);
for (size_t i = 0; i < _detailedMotionStates.size(); i++) {
for (auto& detailedMotionState : _detailedMotionStates) {
// NOTE: we activate _detailedMotionStates is because they are KINEMATIC
// and Bullet will automagically call DetailedMotionState::getWorldTransform() when active.
_detailedMotionStates[i]->forceActive();
detailedMotionState->forceActive();
}
if (_moving && _motionState) {
_motionState->addDirtyFlags(Simulation::DIRTY_POSITION);

View file

@ -29,6 +29,7 @@
#include "Menu.h"
#include "OffscreenUi.h"
#include "commerce/QmlCommerce.h"
#include "NetworkingConstants.h"
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation";
@ -411,6 +412,10 @@ QString WindowScriptingInterface::checkVersion() {
return QCoreApplication::applicationVersion();
}
QString WindowScriptingInterface::getUserAgent() {
return NetworkingConstants::VIRCADIA_USER_AGENT;
}
QString WindowScriptingInterface::protocolSignature() {
return protocolVersionsSignatureBase64();
}

View file

@ -295,6 +295,13 @@ public slots:
*/
QString checkVersion();
/**jsdoc
* Gets Interface's user agent.
* @function Window.getUserAgent
* @returns {string} Interface's user agent.
*/
QString getUserAgent();
/**jsdoc
* Gets the signature for Interface's protocol version.
* @function Window.protocolSignature

View file

@ -27,6 +27,7 @@
#include <ThreadHelpers.h>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <SharedUtil.h>
const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "skeletons", "attachments" };
@ -225,7 +226,7 @@ void ModelHandler::update() {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest request(url);
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
request.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
QNetworkReply* reply = networkAccessManager.head(request);
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
}
@ -278,7 +279,7 @@ void ModelHandler::queryNewFiles(QString marker) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest request(url);
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
request.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(request);
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));

View file

@ -143,13 +143,13 @@ set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
include(CPackComponent)
set(CPACK_PACKAGE_NAME "HQ Launcher")
set(CPACK_PACKAGE_VENDOR "High Fidelity")
set(CPACK_PACKAGE_VENDOR "Vircadia")
set(CPACK_PACKAGE_VERSION ${BUILD_VERSION})
set(CPACK_PACKAGE_FILE_NAME "HQ Launcher")
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
set(DMG_SUBFOLDER_NAME "High Fidelity")
set(DMG_SUBFOLDER_NAME "Vircadia")
set(ESCAPED_DMG_SUBFOLDER_NAME "")
set(DMG_SUBFOLDER_ICON "${CMAKE_SOURCE_DIR}/cmake/installer/install-folder.rsrc")

View file

@ -276,12 +276,12 @@ if (APPLE)
include(CPackComponent)
set(CPACK_PACKAGE_NAME "HQ Launcher")
set(CPACK_PACKAGE_VENDOR "High Fidelity")
set(CPACK_PACKAGE_VENDOR "Vircadia")
set(CPACK_PACKAGE_FILE_NAME "HQ Launcher")
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
set(DMG_SUBFOLDER_NAME "High Fidelity")
set(DMG_SUBFOLDER_NAME "Vircadia")
set(ESCAPED_DMG_SUBFOLDER_NAME "")
set(DMG_SUBFOLDER_ICON "${CMAKE_SOURCE_DIR}/cmake/installer/install-folder.rsrc")

View file

@ -2,7 +2,7 @@ import QtQuick 2.3
import QtQuick 2.1
Text {
text: "High Fidelity"
text: "Vircadia"
font.bold: true
font.family: "Graphik Semibold"
font.pixelSize: 17

View file

@ -21,7 +21,7 @@ Launcher::Launcher(int& argc, char**argv) : QGuiApplication(argc, argv) {
_launcherWindow->rootContext()->setContextProperty("LauncherState", _launcherState.get());
_launcherWindow->rootContext()->setContextProperty("PathUtils", new PathUtils());
_launcherWindow->rootContext()->setContextProperty("Platform", platform);
_launcherWindow->setTitle("High Fidelity");
_launcherWindow->setTitle("Vircadia");
_launcherWindow->setFlags(Qt::FramelessWindowHint | Qt::Window);
_launcherWindow->setLauncherStatePtr(_launcherState);

View file

@ -12,7 +12,7 @@
#include <QStandardPaths>
#include <QFileInfo>
#include <QFile>
#include <QFile>
#include <QDebug>
#include <QTime>
@ -253,7 +253,7 @@ void LauncherInstaller::createApplicationRegistryKeys() {
success = insertRegistryKey(REGISTRY_PATH, "UninstallString", uninstallPath);
success = insertRegistryKey(REGISTRY_PATH, "DisplayVersion", std::string(LAUNCHER_BUILD_VERSION));
success = insertRegistryKey(REGISTRY_PATH, "DisplayIcon", applicationExe);
success = insertRegistryKey(REGISTRY_PATH, "Publisher", "High Fidelity");
success = insertRegistryKey(REGISTRY_PATH, "Publisher", "Vircadia");
auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());

View file

@ -31,7 +31,7 @@ bool hasSuffix(const std::string& path, const std::string& suffix) {
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setOrganizationName("High Fidelity");
QCoreApplication::setOrganizationName("Vircadia");
QCoreApplication::setApplicationName("HQ Launcher");
Q_INIT_RESOURCE(resources);

View file

@ -310,7 +310,7 @@ BOOL LauncherManager::getAndCreatePaths(PathType type, CString& outPath) {
outPath += DIRECTORY_NAME_INTERFACE;
} else if (type == PathType::Content_Directory) {
outPath += DIRECTORY_NAME_CONTENT;
}
}
return (CreateDirectory(outPath, NULL) || ERROR_ALREADY_EXISTS == GetLastError());
}
}
@ -377,7 +377,7 @@ BOOL LauncherManager::createConfigJSON() {
return TRUE;
}
LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, CString& domain,
LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, CString& domain,
CString& content, bool& loggedIn, CString& organizationBuildTag) {
CString configPath;
getAndCreatePaths(PathType::Interface_Directory, configPath);
@ -388,7 +388,7 @@ LauncherUtils::ResponseError LauncherManager::readConfigJSON(CString& version, C
}
Json::Value config;
configFile >> config;
if (config["version"].isString() &&
if (config["version"].isString() &&
config["domain"].isString() &&
config["content"].isString()) {
loggedIn = config["loggedIn"].asBool();
@ -446,7 +446,7 @@ LauncherUtils::ResponseError LauncherManager::readOrganizationJSON(const CString
CString url = _T("/organizations/") + hash + _T(".json");
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(getHttpUserAgent(),
true, L"orgs.highfidelity.com", url,
contentTypeJson, CStringA(),
contentTypeJson, CStringA(),
response, false);
if (error != LauncherUtils::ResponseError::NoError) {
return error;
@ -557,7 +557,7 @@ void LauncherManager::onMostRecentBuildsReceived(const CString& response, Launch
addToLog(_T("Already running most recent build. Launching interface.exe"));
} else {
addToLog(_T("Updating the launcher was not allowed --noUpdate"));
}
}
if (isInstalled) {
addToLog(_T("Installed version: ") + currentVersion);
if (!newInterfaceVersion) {
@ -576,7 +576,7 @@ void LauncherManager::onMostRecentBuildsReceived(const CString& response, Launch
}
}
_shouldWait = FALSE;
} else {
setFailed(true);
CString msg;
@ -587,7 +587,7 @@ void LauncherManager::onMostRecentBuildsReceived(const CString& response, Launch
}
}
LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString& username,
LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const CString& username,
const CString& password) {
CStringA post = "grant_type=password&username=";
post += username;
@ -599,9 +599,9 @@ LauncherUtils::ResponseError LauncherManager::getAccessTokenForCredentials(const
CString response;
LauncherUtils::ResponseError error = LauncherUtils::makeHTTPCall(getHttpUserAgent(),
true,
L"metaverse.highfidelity.com",
L"metaverse.highfidelity.com",
L"/oauth/token",
contentTypeText, post,
contentTypeText, post,
response, true);
if (error != LauncherUtils::ResponseError::NoError) {
return error;
@ -629,7 +629,7 @@ BOOL LauncherManager::createApplicationRegistryKeys(int size) {
success = LauncherUtils::insertRegistryKey(REGISTRY_PATH, "UninstallString", uninstallPath);
success = LauncherUtils::insertRegistryKey(REGISTRY_PATH, "DisplayVersion", LauncherUtils::cStringToStd(_latestVersion));
success = LauncherUtils::insertRegistryKey(REGISTRY_PATH, "DisplayIcon", applicationExe);
success = LauncherUtils::insertRegistryKey(REGISTRY_PATH, "Publisher", "High Fidelity");
success = LauncherUtils::insertRegistryKey(REGISTRY_PATH, "Publisher", "Vircadia");
success = LauncherUtils::insertRegistryKey(REGISTRY_PATH, "InstallDate", LauncherUtils::cStringToStd(CTime::GetCurrentTime().Format("%Y%m%d")));
success = LauncherUtils::insertRegistryKey(REGISTRY_PATH, "EstimatedSize", (DWORD)size);
success = LauncherUtils::insertRegistryKey(REGISTRY_PATH, "NoModify", (DWORD)1);
@ -686,9 +686,9 @@ BOOL LauncherManager::extractApplication() {
updateProgress(ProcessType::UnzipApplication, max(progress, 0.0f));
};
_currentProcess = ProcessType::UnzipApplication;
BOOL success = LauncherUtils::unzipFileOnThread(ProcessType::UnzipApplication,
BOOL success = LauncherUtils::unzipFileOnThread(ProcessType::UnzipApplication,
LauncherUtils::cStringToStd(_applicationZipPath),
LauncherUtils::cStringToStd(installPath),
LauncherUtils::cStringToStd(installPath),
onExtractFinished, onProgress);
if (success) {
addToLog(_T("Created thread for unzipping application."));
@ -737,7 +737,7 @@ void LauncherManager::restartNewLauncher() {
continueAction = ContinueActionOnStart::ContinueUpdate;
} else if (_keepLoggingIn) {
continueAction = ContinueActionOnStart::ContinueLogIn;
}
}
CStringW params;
params.Format(_T(" --restart --noUpdate --continueAction %s"), getContinueActionParam(continueAction));
LauncherUtils::launchApplication(_tempLauncherPath, params.GetBuffer());

View file

@ -51,7 +51,7 @@ void AutoUpdater::getLatestVersionData() {
QNetworkRequest latestVersionRequest(buildsURL);
latestVersionRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(latestVersionRequest);
connect(reply, &QNetworkReply::finished, this, &AutoUpdater::parseLatestVersionData);
}

View file

@ -14,6 +14,7 @@
#include <QtNetwork/QNetworkReply>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <SharedUtil.h>
#include <PathUtils.h>
@ -62,7 +63,7 @@ void JSBaker::loadScript() {
// setup the request to follow re-directs and always hit the network
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
networkRequest.setUrl(_jsURL);

View file

@ -13,6 +13,7 @@
#include <PathUtils.h>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <DependencyManager.h>
#include <hfm/ModelFormatRegistry.h>
@ -159,7 +160,7 @@ void ModelBaker::saveSourceModel() {
// setup the request to follow re-directs and always hit the network
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
networkRequest.setUrl(_modelURL);

View file

@ -19,6 +19,7 @@
#include <image/TextureProcessing.h>
#include <ktx/KTX.h>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <SharedUtil.h>
#include <TextureMeta.h>
@ -99,7 +100,7 @@ void TextureBaker::loadTexture() {
// setup the request to follow re-directs and always hit the network
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
networkRequest.setUrl(_textureURL);

View file

@ -1337,7 +1337,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
_model->setCullWithParent(_cullWithParent);
_model->setRenderWithZones(_renderWithZones);
emit requestRenderUpdate();
if(didVisualGeometryRequestSucceed) {
if (didVisualGeometryRequestSucceed) {
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
modelAddedToScene(entity->getEntityItemID(), NestableType::Entity, _model);
}

View file

@ -45,7 +45,7 @@ private:
PulsePropertyGroup _pulseProperties;
std::shared_ptr<graphics::ProceduralMaterial> _material { std::make_shared<graphics::ProceduralMaterial>() };
glm::vec3 _color { NAN };
float _alpha;
float _alpha { NAN };
glm::vec3 _position;
glm::vec3 _dimensions;

View file

@ -2793,6 +2793,17 @@ bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void
}
}
QVector<QUuid> oldRenderWithZones = properties.getRenderWithZones();
if (!oldRenderWithZones.isEmpty()) {
QVector<QUuid> newRenderWithZones;
for (QUuid oldRenderWithZoneID : oldRenderWithZones) {
if (args->ourTree->findEntityByEntityItemID(oldRenderWithZoneID)) {
newRenderWithZones.append(getMapped(oldRenderWithZoneID));
}
}
properties.setRenderWithZones(newRenderWithZones);
}
properties.setXNNeighborID(getMapped(properties.getXNNeighborID()));
properties.setXPNeighborID(getMapped(properties.getXPNeighborID()));
properties.setYNNeighborID(getMapped(properties.getYNNeighborID()));

View file

@ -127,7 +127,7 @@ void appendIndex(MeshData& data, QVector<int>& indices, int index, bool deduplic
glm::vec4 color;
bool hasColors = (data.colors.size() > 1);
bool hasColors = (data.colors.size() > 0);
if (hasColors) {
int colorIndex = data.colorsByVertex ? vertexIndex : index;
if (data.colorIndices.isEmpty()) {

View file

@ -17,6 +17,7 @@
#include <QNetworkRequest>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <SharedUtil.h>
QVariantHash FSTReader::parseMapping(QIODevice* device) {
@ -253,7 +254,7 @@ QVariantHash FSTReader::downloadMapping(const QString& url) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = QNetworkRequest(url);
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(networkRequest);
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);

View file

@ -58,7 +58,7 @@ const auto METAVERSE_SESSION_ID_HEADER = QString("HFM-SessionID").toLocal8Bit();
using UserAgentGetter = std::function<QString()>;
const auto DEFAULT_USER_AGENT_GETTER = []() -> QString { return HIGH_FIDELITY_USER_AGENT; };
const auto DEFAULT_USER_AGENT_GETTER = []() -> QString { return NetworkingConstants::VIRCADIA_USER_AGENT; };
class AccountManager : public QObject, public Dependency {
Q_OBJECT

View file

@ -21,6 +21,7 @@
#include "NetworkAccessManager.h"
#include "NetworkLogging.h"
#include "NetworkingConstants.h"
HTTPResourceRequest::~HTTPResourceRequest() {
if (_reply) {
@ -54,7 +55,7 @@ void HTTPResourceRequest::doSend() {
QNetworkRequest networkRequest(_url);
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
if (_cacheEnabled) {
networkRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);

View file

@ -30,6 +30,14 @@ namespace NetworkingConstants {
// Web Engine requests to this parent domain have an account authorization header added
const QString AUTH_HOSTNAME_BASE = "highfidelity.com";
const QStringList IS_AUTHABLE_HOSTNAME = { "highfidelity.com", "highfidelity.io" };
// Use a custom User-Agent to avoid ModSecurity filtering, e.g. by hosting providers.
const QByteArray VIRCADIA_USER_AGENT = "Mozilla/5.0 (VircadiaInterface)";
const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (VircadiaInterface)";
const QString METAVERSE_USER_AGENT = "Chrome/48.0 (VircadiaInterface)";
const QString MOBILE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36";
const QUrl BUILDS_XML_URL("https://highfidelity.com/builds.xml");
const QUrl MASTER_BUILDS_XML_URL("https://highfidelity.com/dev-builds.xml");

View file

@ -39,7 +39,7 @@ QNetworkReply* OAuthNetworkAccessManager::createRequest(QNetworkAccessManager::O
&& req.url().host() == MetaverseAPI::getCurrentMetaverseServerURL().host()) {
QNetworkRequest authenticatedRequest(req);
authenticatedRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
authenticatedRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
authenticatedRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
authenticatedRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER,
accountManager->getAccountInfo().getAccessToken().authorizationHeaderValue());

View file

@ -25,6 +25,7 @@
#include "HTTPResourceRequest.h"
#include "NetworkAccessManager.h"
#include "NetworkLogging.h"
#include "NetworkingConstants.h"
ResourceManager::ResourceManager(bool atpSupportEnabled) : _atpSupportEnabled(atpSupportEnabled) {
_thread.setObjectName("Resource Manager Thread");
@ -157,7 +158,7 @@ bool ResourceManager::resourceExists(const QUrl& url) {
QNetworkRequest request{ url };
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
request.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
auto reply = networkAccessManager.head(request);

View file

@ -22,6 +22,7 @@
#include "NetworkAccessManager.h"
#include "NetworkLogging.h"
#include "NetworkingConstants.h"
namespace SandboxUtils {
@ -29,7 +30,7 @@ QNetworkReply* getStatus() {
auto& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest sandboxStatus(SANDBOX_STATUS_URL);
sandboxStatus.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
sandboxStatus.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
sandboxStatus.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
return networkAccessManager.get(sandboxStatus);
}

View file

@ -543,12 +543,8 @@ void CharacterController::setLocalBoundingBox(const glm::vec3& minCorner, const
_minStepHeight = DEFAULT_MIN_STEP_HEIGHT_FACTOR * (_halfHeight + _radius);
_maxStepHeight = DEFAULT_MAX_STEP_HEIGHT_FACTOR * (_halfHeight + _radius);
if (_physicsEngine) {
// must REMOVE from world prior to shape update
_pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION | PENDING_FLAG_REMOVE_DETAILED_FROM_SIMULATION;
}
_pendingFlags |= PENDING_FLAG_UPDATE_SHAPE;
_pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION | PENDING_FLAG_ADD_DETAILED_TO_SIMULATION;
_pendingFlags |= PENDING_FLAG_UPDATE_SHAPE | PENDING_FLAG_REMOVE_FROM_SIMULATION | PENDING_FLAG_REMOVE_DETAILED_FROM_SIMULATION |
PENDING_FLAG_ADD_TO_SIMULATION | PENDING_FLAG_ADD_DETAILED_TO_SIMULATION;
}
// it's ok to change offset immediately -- there are no thread safety issues here

View file

@ -226,6 +226,7 @@ void Model::updateRenderItems() {
modelTransform.setScale(glm::vec3(1.0f));
PrimitiveMode primitiveMode = self->getPrimitiveMode();
auto renderWithZones = self->getRenderWithZones();
auto renderItemKeyGlobalFlags = self->getRenderItemKeyGlobalFlags();
bool cauterized = self->isCauterized();
@ -241,7 +242,8 @@ void Model::updateRenderItems() {
bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning();
transaction.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, meshState, useDualQuaternionSkinning,
invalidatePayloadShapeKey, primitiveMode, renderItemKeyGlobalFlags, cauterized](ModelMeshPartPayload& data) {
invalidatePayloadShapeKey, primitiveMode, renderItemKeyGlobalFlags,
cauterized, renderWithZones](ModelMeshPartPayload& data) {
if (useDualQuaternionSkinning) {
data.updateClusterBuffer(meshState.clusterDualQuaternions);
data.computeAdjustedLocalBound(meshState.clusterDualQuaternions);
@ -268,6 +270,7 @@ void Model::updateRenderItems() {
data.updateTransformForSkinnedMesh(renderTransform, modelTransform);
data.setCauterized(cauterized);
data.setRenderWithZones(renderWithZones);
data.updateKey(renderItemKeyGlobalFlags);
data.setShapeKey(invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning);
});
@ -962,6 +965,13 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) {
}
}
void Model::setPrimitiveMode(PrimitiveMode primitiveMode) {
if (_primitiveMode != primitiveMode) {
_primitiveMode = primitiveMode;
setRenderItemsNeedUpdate();
}
}
void Model::setCullWithParent(bool cullWithParent) {
if (_cullWithParent != cullWithParent) {
_cullWithParent = cullWithParent;
@ -979,13 +989,10 @@ void Model::setCullWithParent(bool cullWithParent) {
}
void Model::setRenderWithZones(const QVector<QUuid>& renderWithZones) {
render::Transaction transaction;
for (auto item : _modelMeshRenderItemIDs) {
transaction.updateItem<ModelMeshPartPayload>(item, [renderWithZones](ModelMeshPartPayload& data) {
data.setRenderWithZones(renderWithZones);
});
if (_renderWithZones != renderWithZones) {
_renderWithZones = renderWithZones;
setRenderItemsNeedUpdate();
}
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
}
const render::ItemKey Model::getRenderItemKeyGlobalFlags() const {

View file

@ -124,6 +124,7 @@ public:
void setCullWithParent(bool value);
void setRenderWithZones(const QVector<QUuid>& renderWithZones);
const QVector<QUuid>& getRenderWithZones() const { return _renderWithZones; }
// Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model.
const render::ItemKey getRenderItemKeyGlobalFlags() const;
@ -499,6 +500,7 @@ protected:
render::ItemKey _renderItemKeyGlobalFlags;
bool _cauterized { false };
bool _cullWithParent { false };
QVector<QUuid> _renderWithZones;
bool shouldInvalidatePayloadShapeKey(int meshIndex);

View file

@ -15,6 +15,7 @@
#include "../StencilMaskPass.h"
#include "NetworkAccessManager.h"
#include "NetworkingConstants.h"
static std::mutex fontMutex;
@ -97,7 +98,7 @@ Font::Pointer Font::load(const QString& family) {
QNetworkRequest networkRequest;
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
networkRequest.setUrl(family);
auto networkReply = networkAccessManager.get(networkRequest);

View file

@ -16,6 +16,7 @@
#include <QDirIterator>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <PathUtils.h>
#include "ScriptEngine.h"
@ -191,7 +192,7 @@ void ScriptsModel::requestDefaultFiles(QString marker) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest request(url);
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
request.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(request);
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
}

View file

@ -62,7 +62,7 @@ void XMLHttpRequestClass::abort() {
}
void XMLHttpRequestClass::setRequestHeader(const QString& name, const QString& value) {
_request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
_request.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
_request.setRawHeader(QByteArray(name.toLatin1()), QByteArray(value.toLatin1()));
}

View file

@ -81,9 +81,6 @@ const int BYTES_PER_FLAGS = 1;
typedef unsigned char colorPart;
typedef unsigned char nodeColor[BYTES_PER_COLOR + BYTES_PER_FLAGS];
// Use a custom User-Agent to avoid ModSecurity filtering, e.g. by hosting providers.
const QByteArray HIGH_FIDELITY_USER_AGENT = "Mozilla/5.0 (HighFidelityInterface)";
// Equivalent to time_t but in usecs instead of secs
quint64 usecTimestampNow(bool wantDebug = false);
void usecTimestampNowForceClockSkew(qint64 clockSkew);

View file

@ -16,6 +16,7 @@
#include <QtQml/QQmlContext>
#include "RequestFilters.h"
#include "NetworkingConstants.h"
#if !defined(Q_OS_ANDROID)
static const QString QML_WEB_ENGINE_STORAGE_NAME = "qmlWebEngine";
@ -26,8 +27,7 @@ static std::mutex FileTypeProfile_mutex;
FileTypeProfile::FileTypeProfile(QQmlContext* parent) :
ContextAwareProfile(parent)
{
static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)";
setHttpUserAgent(WEB_ENGINE_USER_AGENT);
setHttpUserAgent(NetworkingConstants::WEB_ENGINE_USER_AGENT);
setStorageName(QML_WEB_ENGINE_STORAGE_NAME);
setOffTheRecord(false);

View file

@ -27,10 +27,10 @@ namespace {
bool isAuthableHighFidelityURL(const QUrl& url) {
auto metaverseServerURL = MetaverseAPI::getCurrentMetaverseServerURL();
static const QStringList HF_HOSTS = {
"highfidelity.com", "highfidelity.io",
metaverseServerURL.toString(),
static QStringList HF_HOSTS = {
metaverseServerURL.toString()
};
HF_HOSTS << NetworkingConstants::IS_AUTHABLE_HOSTNAME;
const auto& scheme = url.scheme();
const auto& host = url.host();
@ -83,9 +83,9 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info,
}
}
static const QString USER_AGENT = "User-Agent";
const QString tokenStringMobile{ "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36" };
const QString tokenStringMetaverse{ "Chrome/48.0 (HighFidelityInterface)" };
const QString tokenStringLimitedCommerce{ "Chrome/48.0 (HighFidelityInterface limitedCommerce)" };
const QString tokenStringMobile{ NetworkingConstants::MOBILE_USER_AGENT };
const QString tokenStringMetaverse{ NetworkingConstants::METAVERSE_USER_AGENT };
const QString tokenStringLimitedCommerce{ "Chrome/48.0 (VircadiaInterface limitedCommerce)" };
const QString tokenString = !isAuthable ? tokenStringMobile : (accountManager->getLimitedCommerce() ? tokenStringLimitedCommerce : tokenStringMetaverse);
info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit());

View file

@ -26,8 +26,8 @@ if (osType == "Darwin") {
options["app-bundle-id"] = "com.highfidelity.hifi-screenshare";
} else if (osType == "Windows_NT") {
options["version-string"] = {
CompanyName: "High Fidelity, Inc.",
FileDescription: "High Fidelity Screenshare",
CompanyName: "Vircadia",
FileDescription: "Vircadia Screenshare",
ProductName: NAME,
OriginalFilename: NAME + ".exe"
}
@ -47,4 +47,3 @@ packager(options)
console.error("There was an error writing the packaged console: " + error.message);
process.exit(1);
});

View file

@ -389,7 +389,8 @@
function time() {
var d = new Date();
var month = (d.getMonth()).toString();
// Months are returned in range 0-11 instead of 1-12, so we have to add 1.
var month = (d.getMonth() + 1).toString();
var day = (d.getDate()).toString();
var h = (d.getHours()).toString();
var m = (d.getMinutes()).toString();

View file

@ -6,6 +6,7 @@
//
// Created by Fluffy Jenkins January 2020.
// Copyright 2020 Fluffy Jenkins
// Copyright 2020 Vircadia contributors.
//
// For any future coders, please keep me in the loop when making changes.
// Please tag me in any Pull Requests.
@ -98,6 +99,8 @@ function init() {
chatBar.sendToQml(JSON.stringify({visible: false, history: chatBarHistory}));
Controller.keyPressEvent.connect(keyPressEvent);
Messages.messageReceived.connect(messageReceived);
AvatarManager.avatarAddedEvent.connect(avatarJoinsDomain);
AvatarManager.avatarRemovedEvent.connect(avatarLeavesDomain);
connectWebSocket();
}
@ -510,13 +513,17 @@ function messageReceived(channel, message) {
}));
}
}
if (cmd.type === "ShowChatWindow") {
toggleMainChatWindow();
}
}
}
}
function time() {
var d = new Date();
var month = (d.getMonth()).toString();
// Months are returned in range 0-11 instead of 1-12, so we have to add 1.
var month = (d.getMonth() + 1).toString();
var day = (d.getDate()).toString();
var h = (d.getHours()).toString();
var m = (d.getMinutes()).toString();
@ -618,6 +625,46 @@ function setVisible(_visible) {
visible = _visible;
}
function avatarJoinsDomain(sessionID) {
Script.setTimeout(function () {
var messageText = AvatarManager.getPalData([sessionID]).data[0].sessionDisplayName + " has joined."
var messageColor = { red: 122, green: 122, blue: 122 };
addToLog(messageText, "Notice", messageColor, "Domain");
if (!mutedAudio["Domain"]) {
playNotificationSound();
}
if (!muted["Domain"]) {
Messages.sendLocalMessage(FLOOF_NOTIFICATION_CHANNEL, JSON.stringify({
sender: "(D)",
text: messageText,
colour: { text: messageColor }
}));
}
}, 500); // Wait 500ms for the avatar to load to properly get info about them.
}
function avatarLeavesDomain(sessionID) {
var messageText = AvatarManager.getPalData([sessionID]).data[0].sessionDisplayName + " has left."
var messageColor = { red: 122, green: 122, blue: 122 };
addToLog(messageText, "Notice", messageColor, "Domain");
if (!mutedAudio["Domain"]) {
playNotificationSound();
}
if (!muted["Domain"]) {
Messages.sendLocalMessage(FLOOF_NOTIFICATION_CHANNEL, JSON.stringify({
sender: "(D)",
text: messageText,
colour: { text: messageColor }
}));
}
}
function keyPressEvent(event) {
if (event.key === H_KEY && !event.isAutoRepeat && event.isControl) {
toggleMainChatWindow()
@ -636,11 +683,25 @@ function shutdown() {
} catch (e) {
// empty
}
try {
AvatarManager.avatarAddedEvent.disconnect(avatarJoinsDomain);
} catch (e) {
// empty
}
try {
AvatarManager.avatarRemovedEvent.disconnect(avatarLeavesDomain);
} catch (e) {
// empty
}
try {
Controller.keyPressEvent.disconnect(keyPressEvent);
} catch (e) {
// empty
}
chatBar.close();
chatHistory.close();
}

View file

@ -1,3 +1,17 @@
//
// notificationCore.js
//
// Created by Fluffy Jenkins January 2020.
// Copyright 2020 Fluffy Jenkins
// Copyright 2020 Vircadia contributors.
//
// For any future coders, please keep me in the loop when making changes.
// Please tag me in any Pull Requests.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
"use strict";
var notificationList = [];
@ -6,6 +20,7 @@ var sizeData = {30: {widthMul: 1.8, heightMul: 2.05, split: 35, size: 30}};
var DEFAULT_SIZE = 30;
var DEFAULT_OFFSET = 10;
var FLOOF_NOTIFICATION_CHANNEL = "Floof-Notif";
var MAIN_CHAT_APP_CHANNEL = "Chat";
var offset = DEFAULT_OFFSET;
@ -161,4 +176,19 @@ function notif(text, colour) {
notificationList.push(noti);
}
Script.scriptEnding.connect(cleanUp);
Controller.mousePressEvent.connect(function (event) {
// Overlays.getOverlayAtPoint applies only to 2D overlays.
var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
if (overlay) {
for (var i = 0; i < notificationList.length; i++) {
if (overlay === notificationList[i].id) {
Overlays.deleteOverlay(notificationList[i].id)
Messages.sendMessage(MAIN_CHAT_APP_CHANNEL, JSON.stringify({
type: "ShowChatWindow",
}));
}
}
}
});
Script.scriptEnding.connect(cleanUp);

20
scripts/system/inventory/.gitignore vendored Normal file
View file

@ -0,0 +1,20 @@
.DS_Store
node_modules
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View file

@ -0,0 +1,24 @@
# inventory
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View file

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

View file

@ -0,0 +1 @@
.draggable-card{background-color:#272727;margin:5px 0}.draggable-card .handle{width:40px!important}.top-level-folder{background-color:#272727}.top-level-folder .v-list-group__header__prepend-icon{background-color:rgba(0,0,0,.3);width:50px;height:50px;margin:5px 5px 7px 0!important;padding:5px 18px 5px 8px}.top-level-folder .handle{width:40px!important}.top-level-folder .folder-icon{margin-right:10px}.top-level-folder .folder-button{font-size:.795rem!important}.v-list-group .column-item{max-width:100%!important;margin-top:5px;margin-bottom:5px}.v-list-group .draggable-card{background-color:rgba(0,0,0,.3);padding-right:16px;padding-left:0!important}.v-list-group .draggable-card .handle{margin-right:16px}.app-version{text-align:center;color:hsla(0,0%,100%,.6);font-weight:lighter}.handle{background-color:rgba(0,0,0,.3)}.inventoryApp::-webkit-scrollbar{width:0!important}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon.ico><title>Inventory</title><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css><link href=css/app.a93e8b1f.css rel=preload as=style><link href=css/chunk-vendors.8540aa41.css rel=preload as=style><link href=js/app.a3555a80.js rel=preload as=script><link href=js/chunk-vendors.a0f21a27.js rel=preload as=script><link href=css/chunk-vendors.8540aa41.css rel=stylesheet><link href=css/app.a93e8b1f.css rel=stylesheet></head><body><noscript><strong>We're sorry but Inventory doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.a0f21a27.js></script><script src=js/app.a3555a80.js></script></body></html>

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#0c0" d="M17,14H19V17H22V19H19V22H17V19H14V17H17V14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.53C20.94,12.58 19.54,12 18,12A6,6 0 0,0 12,18C12,19.09 12.29,20.12 12.8,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 552 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M16.5,12C19,12 21,14 21,16.5C21,17.38 20.75,18.21 20.31,18.9L23.39,22L22,23.39L18.88,20.32C18.19,20.75 17.37,21 16.5,21C14,21 12,19 12,16.5C12,14 14,12 16.5,12M16.5,14A2.5,2.5 0 0,0 14,16.5A2.5,2.5 0 0,0 16.5,19A2.5,2.5 0 0,0 19,16.5A2.5,2.5 0 0,0 16.5,14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.03C20.85,11.21 18.82,10 16.5,10A6.5,6.5 0 0,0 10,16.5C10,18.25 10.69,19.83 11.81,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 761 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#0f0" d="M17,14H19V17H22V19H19V22H17V19H14V17H17V14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.53C20.94,12.58 19.54,12 18,12A6,6 0 0,0 12,18C12,19.09 12.29,20.12 12.8,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 552 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="white" d="M16.5,12C19,12 21,14 21,16.5C21,17.38 20.75,18.21 20.31,18.9L23.39,22L22,23.39L18.88,20.32C18.19,20.75 17.37,21 16.5,21C14,21 12,19 12,16.5C12,14 14,12 16.5,12M16.5,14A2.5,2.5 0 0,0 14,16.5A2.5,2.5 0 0,0 16.5,19A2.5,2.5 0 0,0 19,16.5A2.5,2.5 0 0,0 16.5,14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.03C20.85,11.21 18.82,10 16.5,10A6.5,6.5 0 0,0 10,16.5C10,18.25 10.69,19.83 11.81,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 775 B

View file

@ -0,0 +1,299 @@
//
// inventory.js
//
// Created by kasenvr@gmail.com on 2 Apr 2020
// Copyright 2020 Vircadia and contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* global AvatarList Clipboard console Controller Entities location Messages MyAvatar Script ScriptDiscoveryService Settings
Tablet Vec3 Window */
(function () { // BEGIN LOCAL_SCOPE
"use strict";
var AppUi = Script.require('appUi');
var ui;
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
// VARIABLES
var inventoryDataSettingString = "inventoryApp.data";
var inventoryData;
var inventorySettingsString = "inventoryApp.settings";
var inventorySettings;
var RECEIVING_ITEM_QUEUE_LIMIT = 5;
var receivingItemQueue = [];
var NEARBY_USERS_SEARCH_RADIUS = 25;
// APP EVENT AND MESSAGING ROUTING
function onWebAppEventReceived(event) {
var eventJSON = JSON.parse(event);
if (eventJSON.app === "inventory") { // This is our web app!
// print("inventory.js received a web event: " + event);
if (eventJSON.command === "ready") {
initializeInventoryApp();
}
if (eventJSON.command === "web-to-script-inventory") {
receiveInventory(eventJSON.data);
}
if (eventJSON.command === "web-to-script-settings") {
receiveSettings(eventJSON.data);
}
if (eventJSON.command === "use-item") {
useItem(eventJSON.data);
}
if (eventJSON.command === "share-item") {
shareItem(eventJSON.data);
}
if (eventJSON.command === "web-to-script-request-nearby-users") {
sendNearbyUsers();
}
if (eventJSON.command === "web-to-script-request-receiving-item-queue") {
sendReceivingItemQueue();
}
if (eventJSON.command === "web-to-script-update-receiving-item-queue") {
updateReceivingItemQueue(eventJSON.data);
}
}
}
tablet.webEventReceived.connect(onWebAppEventReceived);
function sendToWeb(command, data) {
var dataToSend = {
"app": "inventory",
"command": command,
"data": data
};
tablet.emitScriptEvent(JSON.stringify(dataToSend));
}
var inventoryMessagesChannel = "com.vircadia.inventory";
function onMessageReceived(channel, message, sender, localOnly) {
if (channel === inventoryMessagesChannel) {
var messageJSON = JSON.parse(message);
// Window.alert("Passed 0 " + messageJSON.recipient + " vs " + MyAvatar.sessionUUID);
if (messageJSON.command === "share-item"
&& messageJSON.recipient === MyAvatar.sessionUUID) { // We are receiving an item.
// Window.alert("Passed 1 " + messageJSON.recipient + " vs " + MyAvatar.sessionUUID);
pushReceivedItemToQueue(sender, messageJSON.type, messageJSON.name, messageJSON.url);
}
}
// print("Message received:");
// print("- channel: " + channel);
// print("- message: " + message);
// print("- sender: " + sender);
// print("- localOnly: " + localOnly);
}
function sendMessage(dataToSend) {
Messages.sendMessage(inventoryMessagesChannel, JSON.stringify(dataToSend));
}
// END APP EVENT AND MESSAGING ROUTING
// SEND AND RECEIVE INVENTORY STATE
function receiveInventory(receivedInventoryData) {
inventoryData = receivedInventoryData;
saveInventory();
}
function sendInventory() {
sendToWeb("script-to-web-inventory", inventoryData);
}
// END SEND AND RECEIVE INVENTORY STATE
// SEND AND RECEIVE SETTINGS STATE
function receiveSettings(receivedSettingsData) {
inventorySettings = receivedSettingsData;
saveSettings();
}
function sendSettings() {
sendToWeb("script-to-web-settings", inventorySettings);
}
// END SEND AND RECEIVE SETTINGS STATE
function saveInventory() {
Settings.setValue(inventoryDataSettingString, inventoryData);
}
function loadInventory() {
inventoryData = Settings.getValue(inventoryDataSettingString);
}
function saveSettings() {
Settings.setValue(inventorySettingsString, inventorySettings);
}
function loadSettings() {
inventorySettings = Settings.getValue(inventorySettingsString);
}
function pushReceivedItemToQueue(senderUUID, type, name, url) {
console.info("Receiving an item:", name, "from:", senderUUID);
var getAvatarData = AvatarList.getAvatar(senderUUID);
var senderName = getAvatarData.sessionDisplayName;
var senderDistance = Vec3.distance(MyAvatar.position, getAvatarData.position);
var packageRequest = {
"senderUUID": senderUUID,
"senderName": senderName,
"senderDistance": senderDistance,
"data": {
"type": type,
"name": name,
"url": url
}
};
if (receivingItemQueue.length === RECEIVING_ITEM_QUEUE_LIMIT) {
receivingItemQueue = receivingItemQueue.slice(1, RECEIVING_ITEM_QUEUE_LIMIT);
}
receivingItemQueue.push(packageRequest);
ui.messagesWaiting(receivingItemQueue.length > 0);
}
function sendReceivingItemQueue() {
sendToWeb("script-to-web-receiving-item-queue", receivingItemQueue);
}
function updateReceivingItemQueue(data) {
receivingItemQueue = data;
ui.messagesWaiting(receivingItemQueue.length > 0);
}
function sendNearbyUsers() {
var nearbyUsers = AvatarList.getAvatarsInRange(MyAvatar.position, NEARBY_USERS_SEARCH_RADIUS);
var nearbyUsersToSend = [];
nearbyUsers.forEach(function(user) {
var objectToWrite;
var aviDetails = AvatarList.getAvatar(user);
var aviName = aviDetails.displayName;
var aviDistance = Vec3.distance(MyAvatar.position, aviDetails.position);
// Window.alert("aviName" + aviName + "user" + user + "MyAvatar.sessionUUID" + MyAvatar.sessionUUID);
if (user !== MyAvatar.sessionUUID
|| Controller.getValue(Controller.Hardware.Keyboard.Shift)) { // Don't add ourselves to the list!
objectToWrite = { "name": aviName, "distance": aviDistance, "uuid": user };
nearbyUsersToSend.push(objectToWrite);
}
});
sendToWeb("script-to-web-nearby-users", nearbyUsersToSend);
}
function useItem(item) {
//TODO: Add animation support for avatars...?
// Convert the item.type before checking it...
item.type = item.type.toUpperCase();
// Depending on the type, we decide how to load this item.
if (item.type === "SCRIPT") {
ScriptDiscoveryService.loadScript(item.url, true, false, false, true, false);
}
if (item.type === "MODEL") {
Entities.addEntity({
type: "Model",
position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1.5 })),
rotation: MyAvatar.orientation,
modelURL: item.url,
collisionless: true
});
}
if (item.type === "AVATAR") {
MyAvatar.useFullAvatarURL(item.url);
}
if (item.type === "PLACE") {
location.handleLookupString(item.url, true);
}
if (item.type === "JSON") {
var jsonToLoad = item.url;
if (jsonToLoad) {
if (Clipboard.importEntities(jsonToLoad)) {
Clipboard.pasteEntities(
Vec3.sum(
MyAvatar.position,
Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1.5 })
)
);
}
}
}
if (item.type === "UNKNOWN") {
// We don't know how to handle this yet.
Window.alert("Unknown item type, unable to use.");
}
}
function shareItem(data) {
data.command = "share-item";
sendMessage(data);
}
function initializeInventoryApp() {
sendSettings();
sendInventory();
sendReceivingItemQueue();
}
function onOpened() {
}
function onClosed() {
}
function startup() {
loadInventory();
loadSettings();
Messages.messageReceived.connect(onMessageReceived);
Messages.subscribe(inventoryMessagesChannel);
ui = new AppUi({
buttonName: "INVENTORY",
home: Script.resolvePath("index.html"),
graphicsDirectory: Script.resolvePath("./"), // Where your button icons are located
onOpened: onOpened,
onClosed: onClosed
});
}
startup();
Script.scriptEnding.connect(function () {
Messages.messageReceived.disconnect(onMessageReceived);
Messages.unsubscribe(inventoryMessagesChannel);
});
}()); // END LOCAL_SCOPE

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

13049
scripts/system/inventory/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
{
"name": "Inventory",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@mdi/font": "^4.9.95",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vuedraggable": "^2.24.0",
"vuetify": "^2.3.4",
"vuex": "^3.5.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.3.1",
"@vue/cli-plugin-eslint": "^4.3.1",
"@vue/cli-service": "^4.3.1",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.26.10",
"sass-loader": "^8.0.0",
"vue-cli-plugin-vuetify": "^2.0.7",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.6.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"ChromeAndroid > 55",
"Chrome > 55"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,30 @@
<!--
//
// index.html
//
// Created by kasenvr@gmail.com on 7 Apr 2020
// Copyright 2020 Vircadia and contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#0c0" d="M17,14H19V17H22V19H19V22H17V19H14V17H17V14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.53C20.94,12.58 19.54,12 18,12A6,6 0 0,0 12,18C12,19.09 12.29,20.12 12.8,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 552 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M16.5,12C19,12 21,14 21,16.5C21,17.38 20.75,18.21 20.31,18.9L23.39,22L22,23.39L18.88,20.32C18.19,20.75 17.37,21 16.5,21C14,21 12,19 12,16.5C12,14 14,12 16.5,12M16.5,14A2.5,2.5 0 0,0 14,16.5A2.5,2.5 0 0,0 16.5,19A2.5,2.5 0 0,0 19,16.5A2.5,2.5 0 0,0 16.5,14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.03C20.85,11.21 18.82,10 16.5,10A6.5,6.5 0 0,0 10,16.5C10,18.25 10.69,19.83 11.81,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 761 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="#0f0" d="M17,14H19V17H22V19H19V22H17V19H14V17H17V14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.53C20.94,12.58 19.54,12 18,12A6,6 0 0,0 12,18C12,19.09 12.29,20.12 12.8,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 552 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path fill="white" d="M16.5,12C19,12 21,14 21,16.5C21,17.38 20.75,18.21 20.31,18.9L23.39,22L22,23.39L18.88,20.32C18.19,20.75 17.37,21 16.5,21C14,21 12,19 12,16.5C12,14 14,12 16.5,12M16.5,14A2.5,2.5 0 0,0 14,16.5A2.5,2.5 0 0,0 16.5,19A2.5,2.5 0 0,0 19,16.5A2.5,2.5 0 0,0 16.5,14M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V13.03C20.85,11.21 18.82,10 16.5,10A6.5,6.5 0 0,0 10,16.5C10,18.25 10.69,19.83 11.81,21H4C2.89,21 2,20.1 2,19V8C2,6.89 2.89,6 4,6H8V4C8,2.89 8.89,2 10,2M14,6V4H10V6H14Z" /></svg>

After

Width:  |  Height:  |  Size: 775 B

View file

@ -0,0 +1,299 @@
//
// inventory.js
//
// Created by kasenvr@gmail.com on 2 Apr 2020
// Copyright 2020 Vircadia and contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* global AvatarList Clipboard console Controller Entities location Messages MyAvatar Script ScriptDiscoveryService Settings
Tablet Vec3 Window */
(function () { // BEGIN LOCAL_SCOPE
"use strict";
var AppUi = Script.require('appUi');
var ui;
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
// VARIABLES
var inventoryDataSettingString = "inventoryApp.data";
var inventoryData;
var inventorySettingsString = "inventoryApp.settings";
var inventorySettings;
var RECEIVING_ITEM_QUEUE_LIMIT = 5;
var receivingItemQueue = [];
var NEARBY_USERS_SEARCH_RADIUS = 25;
// APP EVENT AND MESSAGING ROUTING
function onWebAppEventReceived(event) {
var eventJSON = JSON.parse(event);
if (eventJSON.app === "inventory") { // This is our web app!
// print("inventory.js received a web event: " + event);
if (eventJSON.command === "ready") {
initializeInventoryApp();
}
if (eventJSON.command === "web-to-script-inventory") {
receiveInventory(eventJSON.data);
}
if (eventJSON.command === "web-to-script-settings") {
receiveSettings(eventJSON.data);
}
if (eventJSON.command === "use-item") {
useItem(eventJSON.data);
}
if (eventJSON.command === "share-item") {
shareItem(eventJSON.data);
}
if (eventJSON.command === "web-to-script-request-nearby-users") {
sendNearbyUsers();
}
if (eventJSON.command === "web-to-script-request-receiving-item-queue") {
sendReceivingItemQueue();
}
if (eventJSON.command === "web-to-script-update-receiving-item-queue") {
updateReceivingItemQueue(eventJSON.data);
}
}
}
tablet.webEventReceived.connect(onWebAppEventReceived);
function sendToWeb(command, data) {
var dataToSend = {
"app": "inventory",
"command": command,
"data": data
};
tablet.emitScriptEvent(JSON.stringify(dataToSend));
}
var inventoryMessagesChannel = "com.vircadia.inventory";
function onMessageReceived(channel, message, sender, localOnly) {
if (channel === inventoryMessagesChannel) {
var messageJSON = JSON.parse(message);
// Window.alert("Passed 0 " + messageJSON.recipient + " vs " + MyAvatar.sessionUUID);
if (messageJSON.command === "share-item"
&& messageJSON.recipient === MyAvatar.sessionUUID) { // We are receiving an item.
// Window.alert("Passed 1 " + messageJSON.recipient + " vs " + MyAvatar.sessionUUID);
pushReceivedItemToQueue(sender, messageJSON.type, messageJSON.name, messageJSON.url);
}
}
// print("Message received:");
// print("- channel: " + channel);
// print("- message: " + message);
// print("- sender: " + sender);
// print("- localOnly: " + localOnly);
}
function sendMessage(dataToSend) {
Messages.sendMessage(inventoryMessagesChannel, JSON.stringify(dataToSend));
}
// END APP EVENT AND MESSAGING ROUTING
// SEND AND RECEIVE INVENTORY STATE
function receiveInventory(receivedInventoryData) {
inventoryData = receivedInventoryData;
saveInventory();
}
function sendInventory() {
sendToWeb("script-to-web-inventory", inventoryData);
}
// END SEND AND RECEIVE INVENTORY STATE
// SEND AND RECEIVE SETTINGS STATE
function receiveSettings(receivedSettingsData) {
inventorySettings = receivedSettingsData;
saveSettings();
}
function sendSettings() {
sendToWeb("script-to-web-settings", inventorySettings);
}
// END SEND AND RECEIVE SETTINGS STATE
function saveInventory() {
Settings.setValue(inventoryDataSettingString, inventoryData);
}
function loadInventory() {
inventoryData = Settings.getValue(inventoryDataSettingString);
}
function saveSettings() {
Settings.setValue(inventorySettingsString, inventorySettings);
}
function loadSettings() {
inventorySettings = Settings.getValue(inventorySettingsString);
}
function pushReceivedItemToQueue(senderUUID, type, name, url) {
console.info("Receiving an item:", name, "from:", senderUUID);
var getAvatarData = AvatarList.getAvatar(senderUUID);
var senderName = getAvatarData.sessionDisplayName;
var senderDistance = Vec3.distance(MyAvatar.position, getAvatarData.position);
var packageRequest = {
"senderUUID": senderUUID,
"senderName": senderName,
"senderDistance": senderDistance,
"data": {
"type": type,
"name": name,
"url": url
}
};
if (receivingItemQueue.length === RECEIVING_ITEM_QUEUE_LIMIT) {
receivingItemQueue = receivingItemQueue.slice(1, RECEIVING_ITEM_QUEUE_LIMIT);
}
receivingItemQueue.push(packageRequest);
ui.messagesWaiting(receivingItemQueue.length > 0);
}
function sendReceivingItemQueue() {
sendToWeb("script-to-web-receiving-item-queue", receivingItemQueue);
}
function updateReceivingItemQueue(data) {
receivingItemQueue = data;
ui.messagesWaiting(receivingItemQueue.length > 0);
}
function sendNearbyUsers() {
var nearbyUsers = AvatarList.getAvatarsInRange(MyAvatar.position, NEARBY_USERS_SEARCH_RADIUS);
var nearbyUsersToSend = [];
nearbyUsers.forEach(function(user) {
var objectToWrite;
var aviDetails = AvatarList.getAvatar(user);
var aviName = aviDetails.displayName;
var aviDistance = Vec3.distance(MyAvatar.position, aviDetails.position);
// Window.alert("aviName" + aviName + "user" + user + "MyAvatar.sessionUUID" + MyAvatar.sessionUUID);
if (user !== MyAvatar.sessionUUID
|| Controller.getValue(Controller.Hardware.Keyboard.Shift)) { // Don't add ourselves to the list!
objectToWrite = { "name": aviName, "distance": aviDistance, "uuid": user };
nearbyUsersToSend.push(objectToWrite);
}
});
sendToWeb("script-to-web-nearby-users", nearbyUsersToSend);
}
function useItem(item) {
//TODO: Add animation support for avatars...?
// Convert the item.type before checking it...
item.type = item.type.toUpperCase();
// Depending on the type, we decide how to load this item.
if (item.type === "SCRIPT") {
ScriptDiscoveryService.loadScript(item.url, true, false, false, true, false);
}
if (item.type === "MODEL") {
Entities.addEntity({
type: "Model",
position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1.5 })),
rotation: MyAvatar.orientation,
modelURL: item.url,
collisionless: true
});
}
if (item.type === "AVATAR") {
MyAvatar.useFullAvatarURL(item.url);
}
if (item.type === "PLACE") {
location.handleLookupString(item.url, true);
}
if (item.type === "JSON") {
var jsonToLoad = item.url;
if (jsonToLoad) {
if (Clipboard.importEntities(jsonToLoad)) {
Clipboard.pasteEntities(
Vec3.sum(
MyAvatar.position,
Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -1.5 })
)
);
}
}
}
if (item.type === "UNKNOWN") {
// We don't know how to handle this yet.
Window.alert("Unknown item type, unable to use.");
}
}
function shareItem(data) {
data.command = "share-item";
sendMessage(data);
}
function initializeInventoryApp() {
sendSettings();
sendInventory();
sendReceivingItemQueue();
}
function onOpened() {
}
function onClosed() {
}
function startup() {
loadInventory();
loadSettings();
Messages.messageReceived.connect(onMessageReceived);
Messages.subscribe(inventoryMessagesChannel);
ui = new AppUi({
buttonName: "INVENTORY",
home: Script.resolvePath("index.html"),
graphicsDirectory: Script.resolvePath("./"), // Where your button icons are located
onOpened: onOpened,
onClosed: onClosed
});
}
startup();
Script.scriptEnding.connect(function () {
Messages.messageReceived.disconnect(onMessageReceived);
Messages.unsubscribe(inventoryMessagesChannel);
});
}()); // END LOCAL_SCOPE

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View file

@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.5 100"><defs><style>.cls-1{fill:#1697f6;}.cls-2{fill:#7bc6ff;}.cls-3{fill:#1867c0;}.cls-4{fill:#aeddff;}</style></defs><title>Artboard 46</title><polyline class="cls-1" points="43.75 0 23.31 0 43.75 48.32"/><polygon class="cls-2" points="43.75 62.5 43.75 100 0 14.58 22.92 14.58 43.75 62.5"/><polyline class="cls-3" points="43.75 0 64.19 0 43.75 48.32"/><polygon class="cls-4" points="64.58 14.58 87.5 14.58 43.75 100 43.75 62.5 64.58 14.58"/></svg>

After

Width:  |  Height:  |  Size: 539 B

View file

@ -0,0 +1,78 @@
/*
styles.css
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
/* Top Level */
.draggable-card {
background-color: rgba(39, 39, 39, 1.0);
margin: 5px 0px;
}
.draggable-card .handle {
width: 40px !important;
}
.top-level-folder {
background-color: rgba(39, 39, 39, 1.0);
}
.top-level-folder .v-list-group__header__prepend-icon {
background-color: rgba(0, 0, 0, 0.3);
width: 50px;
height: 50px;
margin: 5px 5px 7px 0px !important;
padding: 5px 18px 5px 8px;
}
.top-level-folder .handle {
width: 40px !important;
}
.top-level-folder .folder-icon {
margin-right: 10px;
}
.top-level-folder .folder-button {
font-size: 0.795rem !important;
}
/* Second Level */
.v-list-group .column-item {
max-width: 100% !important;
margin-top: 5px;
margin-bottom: 5px;
}
.v-list-group .draggable-card {
background-color: rgba(0, 0, 0, 0.3);
padding-right: 16px;
padding-left: 0px !important;
}
.v-list-group .draggable-card .handle {
margin-right: 16px;
}
/* Menu Slideout */
.app-version {
text-align: center;
color: rgba(255, 255, 255, 0.6);
font-weight: lighter;
}
/* Universal */
.handle {
background-color: rgba(0, 0, 0, 0.3);
}
.inventoryApp::-webkit-scrollbar { width: 0 !important }

View file

@ -0,0 +1,391 @@
<!--
// ItemIterator.vue
//
// Created by Kalila L. on 13 April 2020.
// Copyright 2020 Vircadia and contributors..
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-->
<template>
<draggable :group="options" :list="itemsForIterator" handle=".handle">
<v-item-group
v-for="item in itemsForIterator"
v-bind:key="item.uuid"
>
<v-list-item
one-line
v-if="!item.items"
class="mx-auto draggable-card"
max-width="344"
outlined
>
<div class="handle pa-2">
<!-- <v-icon color="orange darken-2">mdi-blur-linear</v-icon> -->
<!-- <v-icon color="orange darken-2">mdi-package-variant</v-icon> -->
<v-icon color="orange darken-2">mdi-square-medium-outline</v-icon>
</div>
<v-list-item-content
class="pb-1 pt-2 pl-4"
>
<div v-show="settings.displayDensity.size > 0" class="overline" style="font-size: 0.825rem !important;">{{item.type}}</div>
<v-list-item-title class="subtitle-1 mb-1">{{item.name}}</v-list-item-title>
<v-list-item-subtitle v-show="settings.displayDensity.size == 2">{{item.url}}</v-list-item-subtitle>
</v-list-item-content>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<!-- settings.displayDensity.size >= 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size >= 1"
medium
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
<!-- settings.displayDensity.size < 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size < 1"
small
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
</template>
<v-list color="grey darken-3">
<v-list-item
@click="sendEvent('use-item', { 'type': item.type, 'url': item.url })"
>
<v-list-item-title>Use</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-play</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
editDialogStore.show = true;
editDialogStore.uuid = item.uuid;
editDialogStore.data.type = item.type.toUpperCase();
editDialogStore.data.folder = null;
editDialogStore.data.name = item.name;
editDialogStore.data.url = item.url;
"
>
<v-list-item-title>Edit</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-pencil</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
shareDialogStore.show = true;
shareDialogStore.data.url = item.url;
shareDialogStore.data.uuid = item.uuid;
"
>
<v-list-item-title>Share</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-share</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
removeDialogStore.show = true;
removeDialogStore.uuid = item.uuid;
"
color="red darken-1"
>
<v-list-item-title>Remove</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-minus</v-icon>
</v-list-item-action>
</v-list-item>
</v-list>
</v-menu>
</v-list-item>
<!-- The Folder List Item -->
<v-list-group
v-else
class="top-level-folder"
>
<!-- prepend-icon="mdi-blur-linear" put this in the list group, no idea how to make it a handle yet though... -->
<template v-slot:activator>
<v-list-item
one-line
class="mx-auto"
max-width="344"
outlined
>
<v-icon class="folder-icon" color="teal">mdi-folder-settings</v-icon>
{{item.name}}
</v-list-item>
</template>
<div class="text-center my-2">
<v-btn medium tile color="purple" class="mx-1 folder-button"
@click="
editFolderDialogStore.data.uuid = item.uuid;
editFolderDialogStore.data.name = item.name;
editFolderDialogStore.show = true;
"
>
<v-icon>mdi-pencil</v-icon>
</v-btn>
<v-btn medium tile color="red" class="mx-1 folder-button"
@click="
removeFolderDialogStore.show = true;
removeFolderDialogStore.uuid = item.uuid;
"
>
<v-icon>mdi-minus</v-icon>
</v-btn>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<v-btn
medium tile
color="blue"
class="mx-1 folder-button"
v-on="on"
>
<v-icon>mdi-sort</v-icon>
</v-btn>
</template>
<v-list color="grey darken-3">
<v-list-item
@click="sortFolder(item.uuid, 'az');"
>
<v-list-item-title>A-Z</v-list-item-title>
<v-list-item-action>
<v-icon large>mdi-sort-alphabetical-ascending</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="sortFolder(item.uuid, 'za');"
>
<v-list-item-title>Z-A</v-list-item-title>
<v-list-item-action>
<v-icon large>mdi-sort-alphabetical-descending</v-icon>
</v-list-item-action>
</v-list-item>
</v-list>
</v-menu>
</div>
<v-container fluid>
<itemiterator v-bind:key="item.uuid" :itemsForIterator="item.items"></itemiterator>
</v-container>
</v-list-group>
</v-item-group>
</draggable>
</template>
<script>
import { EventBus } from '../plugins/event-bus.js';
import draggable from 'vuedraggable';
export default {
name: 'itemiterator',
components: {
draggable
},
props: ['itemsForIterator'],
data: () => ({
settings: {}
}),
created: function () {
this.settings = this.$store.state.settings;
},
computed: {
options : function (){
return {
name: 'column-item',
pull: true,
put: true
}
},
settingsChanged() {
return this.$store.state.settings;
},
addDialogStore: {
get() {
return this.$store.state.addDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'addDialog',
with: value
});
}
},
editDialogStore: {
get() {
return this.$store.state.editDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'editDialog',
with: value
});
}
},
editFolderDialogStore: {
get() {
return this.$store.state.editFolderDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'editFolderDialog',
with: value
});
}
},
shareDialogStore: {
get() {
return this.$store.state.shareDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'shareDialog',
with: value
});
}
},
removeFolderDialogStore: {
get() {
return this.$store.state.removeFolderDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'removeFolderDialog',
with: value
});
}
},
removeDialogStore: {
get() {
return this.$store.state.removeDialog;
},
set(value) {
this.$store.commit('mutate', {
property: 'removeDialog',
with: value
});
}
}
},
watch: {
settingsChanged (newVal, oldVal) {
console.info ("Settings previous value:", oldVal);
if (newVal) {
this.settings = newVal;
}
}
},
methods: {
sendEvent: function(command, data) {
EventBus.$emit(command, data);
},
getIcon: function(itemType) {
itemType = itemType.toUpperCase();
var returnedItemIcon;
if (this.$store.state.iconType[itemType]) {
returnedItemIcon = this.$store.state.iconType[itemType].icon;
} else {
returnedItemIcon = this.$store.state.iconType.UNKNOWN.icon;
}
return returnedItemIcon;
},
getIconColor: function(itemType) {
itemType = itemType.toUpperCase();
var returnedItemIconColor;
if (this.$store.state.iconType[itemType]) {
returnedItemIconColor = this.$store.state.iconType[itemType].color;
} else {
returnedItemIconColor = this.$store.state.iconType.UNKNOWN.color;
}
return returnedItemIconColor;
},
sortFolder: function(uuid, sort) {
var findFolder = this.searchForItem(uuid);
if (findFolder) {
if (sort === "az") {
findFolder.returnedItem.items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
}
if (sort === "za") {
findFolder.returnedItem.items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA > nameB) {
return -1;
}
if (nameA < nameB) {
return 1;
}
// names must be equal
return 0;
});
}
}
},
searchForItem: function(uuid) {
var foundItem = this.recursiveSingularSearch(uuid, this.itemsForIterator);
if (foundItem) {
return {
"returnedItem": foundItem.returnedItem,
"iteration": foundItem.iteration,
"parentArray": foundItem.parentArray,
"itemUUID": uuid,
}
}
},
recursiveSingularSearch: function(uuid, indexToSearch) {
for (var i = 0; i < indexToSearch.length; i++) {
if (indexToSearch[i].uuid == uuid) {
var foundItem = {
"returnedItem": indexToSearch[i],
"iteration": i,
"parentArray": indexToSearch,
}
return foundItem;
} else if (Object.prototype.hasOwnProperty.call(indexToSearch[i], "items") && indexToSearch[i].items.length > 0) {
return this.recursiveSingularSearch(uuid, indexToSearch[i].items);
}
}
},
}
};
</script>

View file

@ -0,0 +1,272 @@
<!--
NotUsing.vue
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-->
<template v-if="!disabledProp">
<v-data-iterator
:items="items"
hide-default-footer
>
<template>
<v-col
cols="12"
sm="6"
md="4"
lg="3"
class="py-1 column-item"
>
<draggable :group="options" :list="items" handle=".handle">
<v-item-group
v-for="item in items"
v-bind:key="item.uuid"
>
<v-list-item
one-line
v-if="!item.hasChildren"
class="mx-auto draggable-card"
max-width="344"
outlined
>
<div class="handle pa-2">
<v-icon color="orange darken-2">mdi-blur-linear</v-icon>
</div>
<v-list-item-content
class="pb-1 pt-2 pl-4"
>
<div v-show="settings.displayDensity.size > 0" class="overline" style="font-size: 0.825rem !important;">{{item.type}}</div>
<v-list-item-title class="subtitle-1 mb-1">{{item.name}}</v-list-item-title>
<v-list-item-subtitle v-show="settings.displayDensity.size == 2">{{item.url}}</v-list-item-subtitle>
</v-list-item-content>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<!-- settings.displayDensity.size >= 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size >= 1"
medium
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
<!-- settings.displayDensity.size < 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size < 1"
small
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
</template>
<v-list color="grey darken-3">
<v-list-item
@click="useItem(item.type, item.url)"
>
<v-list-item-title>Use</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-play</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
editDialog.show = true;
editDialog.uuid = item.uuid;
editDialog.data.type = item.type.toUpperCase();
editDialog.data.folder = null;
editDialog.data.name = item.name;
editDialog.data.url = item.url;
getFolderList('edit');
"
>
<v-list-item-title>Edit</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-pencil</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="shareDialog.show = true; shareDialog.data.url = item.url; shareDialog.data.uuid = item.uuid; sendAppMessage('web-to-script-request-nearby-users', '')"
>
<v-list-item-title>Share</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-share</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="removeDialog.show = true; removeDialog.uuid = item.uuid;"
color="red darken-1"
>
<v-list-item-title>Remove</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-minus</v-icon>
</v-list-item-action>
</v-list-item>
</v-list>
</v-menu>
</v-list-item>
<!-- The Folder List Item -->
<v-list-group
v-if="item.hasChildren"
class="top-level-folder"
>
<!-- prepend-icon="mdi-blur-linear" put this in the list group, no idea how to make it a handle yet though... -->
<template v-slot:activator>
<v-list-item
one-line
class="mx-auto"
max-width="344"
outlined
>
<v-icon class="folder-icon" color="teal">mdi-folder-settings</v-icon>
{{item.name}}
</v-list-item>
</template>
<div class="text-center my-2">
<v-btn medium tile color="purple" class="mx-1 folder-button"
@click="
editFolderDialog.show = true;
editFolderDialog.uuid = item.uuid;
editFolderDialog.data.name = item.name;
"
>
<v-icon>mdi-pencil</v-icon>
</v-btn>
<v-btn medium tile color="red" class="mx-1 folder-button"
@click="removeFolderDialog.show = true; removeFolderDialog.uuid = item.uuid;"
>
<v-icon>mdi-minus</v-icon>
</v-btn>
<v-btn medium tile color="blue" class="mx-1 folder-button"
@click="sortFolder(item.uuid);"
>
<v-icon>mdi-ab-testing</v-icon>
</v-btn>
</div>
<v-col
cols="12"
sm="6"
md="4"
lg="3"
class="py-1 column-item"
>
<draggable
:list="item.items"
:group="options"
>
<v-item-group
v-for="item in item.items"
v-bind:key="item.uuid"
>
<v-list-item
one-line
class="mx-auto draggable-card"
outlined
>
<div class="handle pa-2">
<v-icon color="orange darken-2">mdi-blur-linear</v-icon>
</div>
<v-list-item-content class="pb-1 pt-2">
<div v-show="settings.displayDensity.size > 0" class="overline" style="font-size: 0.825rem !important;">{{item.type}}</div>
<v-list-item-title class="subtitle-1 mb-1">{{item.name}}</v-list-item-title>
<v-list-item-subtitle v-show="settings.displayDensity.size == 2">{{item.url}}</v-list-item-subtitle>
</v-list-item-content>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<!-- settings.displayDensity.size >= 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size >= 1"
medium
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
<!-- settings.displayDensity.size < 1 -->
<v-btn
:style="{backgroundColor: (getIconColor(item.type)) }"
v-show="settings.displayDensity.size < 1"
small
fab
dark
v-on="on"
>
<v-icon>{{getIcon(item.type)}}</v-icon>
</v-btn>
</template>
<v-list color="grey darken-3">
<v-list-item
@click="useItem(item.type, item.url)"
>
<v-list-item-title>Use</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-play</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="
editDialog.show = true;
editDialog.uuid = item.uuid;
editDialog.data.type = item.type.toUpperCase();
editDialog.data.folder = null;
editDialog.data.name = item.name;
editDialog.data.url = item.url;
getFolderList('edit');
"
>
<v-list-item-title>Edit</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-pencil</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="shareDialog.show = true; shareDialog.data.url = item.url; shareDialog.data.uuid = item.uuid; sendAppMessage('web-to-script-request-nearby-users', '')"
>
<v-list-item-title>Share</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-share</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item
@click="removeDialog.show = true; removeDialog.uuid = item.uuid;"
color="red darken-1"
>
<v-list-item-title>Remove</v-list-item-title>
<v-list-item-action>
<v-icon>mdi-minus</v-icon>
</v-list-item-action>
</v-list-item>
</v-list>
</v-menu>
</v-list-item>
</v-item-group>
</draggable>
</v-col>
</v-list-group>
</v-item-group>
</draggable>
</v-col>
</template>
</v-data-iterator>
</template>

View file

@ -0,0 +1,22 @@
/*
main.js
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import { store } from './plugins/store';
Vue.config.productionTip = false;
window.vm = new Vue({
vuetify,
store,
render: h => h(App)
}).$mount('#app');

View file

@ -0,0 +1,12 @@
/*
event-bus.js
Created by Kalila L. on 21 May 2020.
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
import Vue from 'vue';
export const EventBus = new Vue();

View file

@ -0,0 +1,321 @@
/*
store.js
Created by Kalila L. on 16 Apr 2020.
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
devtools: true,
state: {
items: [
// This is test data and is primarily used for in browser development.
{
"type": "script",
"name": "VRGrabScale",
"url": "https://gooawefaweawfgle.com/vr.js",
"folder": "No Folder",
"uuid": "54254354353"
},
{
"name": "Test Folder",
"folder": "No Folder",
"items": [
{
"name": "inception1",
"folder": "Test Folder",
"items": [
{
"name": "inception2",
"folder": "Test Folder",
"items": [
{
"type": "script",
"name": "itemincepted",
"url": "https://googfdafsgaergale.com/vr.js",
"folder": "FolderWithinAFolder",
"uuid": "hkjkjhkjk",
},
],
"uuid": "adsfa32"
},
],
"uuid": "s4g4sg"
},
],
"uuid": "sdfsdf",
},
{
"type": "script",
"name": "VRGrabScale",
"url": "https://googfdafsgaergale.com/vr.js",
"folder": "No Folder",
"uuid": "54hgfhgf254354353",
},
{
"type": "script",
"name": "TEST",
"url": "https://gooadfdagle.com/vr.js",
"folder": "No Folder",
"uuid": "542rfwat4t5fsddf4354353",
},
{
"type": "json",
"name": "TESTJSON",
"url": "https://gooadfdagle.com/vr.json",
"folder": "No Folder",
"uuid": "542rfwat4t54354353",
},
{
"type": "script",
"name": "TESTLONGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG",
"url": "https://googfdaffle.com/vrLONGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.js",
"folder": "No Folder",
"uuid": "5425ggsrg45354353",
},
{
"type": "whatttype",
"name": "BrokenIcon",
"url": "https://googfdaffle.com/vrLONGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG.js",
"folder": "No Folder",
"uuid": "5425ggsrg4fdaffdff535asdasd4353",
},
{
"type": "avatar",
"name": "AVI",
"url": "https://googlfadfe.com/vr.fst",
"folder": "No Folder",
"uuid": "542gregg45s3g4354353",
},
{
"type": "avatar",
"name": "AVI",
"url": "https://googlefdaf.com/vr.fst",
"folder": "No Folder",
"uuid": "5420798-087-54354353",
},
{
"type": "model",
"name": "3D MODEL",
"url": "https://googlee.com/vr.fbx",
"folder": "No Folder",
"uuid": "54254354980-7667jt353",
},
{
"type": "place",
"name": "PLACE DOMAIN",
"url": "https://googleee.com/vr.fbx",
"folder": "No Folder",
"uuid": "542543sg45s4gg54353",
},
],
settings: {
"displayDensity": {
"size": 1,
"labels": [
"List",
"Compact",
"Large",
],
},
},
iconType: {
"SCRIPT": {
"icon": "mdi-code-tags",
"color": "red",
},
"MODEL": {
"icon": "mdi-video-3d",
"color": "green",
},
"AVATAR": {
"icon": "mdi-account-convert",
"color": "purple",
},
"PLACE": {
"icon": "mdi-earth",
"color": "#0097A7", // cyan darken-2
},
"JSON": {
"icon": "mdi-inbox-multiple",
"color": "#37474F", // blue-grey darken-3
},
"UNKNOWN": {
"icon": "mdi-help",
"color": "grey",
}
},
supportedItemTypes: [
"SCRIPT",
"MODEL",
"AVATAR",
"PLACE",
"JSON",
"UNKNOWN",
],
removeDialog: {
show: false,
uuid: null,
},
removeFolderDialog: {
show: false,
uuid: null,
},
createFolderDialog: {
show: false,
valid: false,
data: {
"name": null,
},
},
addDialog: {
show: false,
valid: false,
data: {
"name": null,
"folder": null,
"url": null,
},
},
editDialog: {
show: false,
valid: false,
uuid: null, //
data: {
"type": null,
"name": null,
"url": null,
"folder": null,
},
},
editFolderDialog: {
show: false,
valid: false,
uuid: null, //
data: {
"name": null,
"folder": null,
},
},
receiveDialog: {
show: false,
valid: false,
data: {
"userUUID": null,
"userDisplayName": null,
"name": null,
"folder": null,
"type": null,
"url": null,
},
},
shareDialog: {
show: false,
valid: false,
data: {
"uuid": null, // UUID of the item you want to share. THIS IS THE KEY.
"url": null, // The item you want to share.
"recipient": null,
}
},
},
mutations: {
mutate (state, payload) {
state[payload.property] = payload.with;
// console.info("Payload:", payload.property, "with:", payload.with, "state is now:", this.state);
},
sortTopInventory (state, payload) {
let { items } = state;
if (payload.sort === "az") {
state.items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
}
if (payload.sort === "za") {
state.items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA > nameB) {
return -1;
}
if (nameA < nameB) {
return 1;
}
// names must be equal
return 0;
});
}
Vue.set(state,'items', items);
},
pushToItems (state, payload) {
let { items } = state;
items.push(payload);
Vue.set(state,'items', items);
},
moveFolder (state, payload) {
let { items } = state;
if (payload.parentFolderUUID === "top") {
payload.findFolder.returnedItem.folder = "No Folder";
// console.info("Going to push...", payload.findFolder.returnedItem);
// console.info("Containing these items...", payload.findFolder.returnedItem.items);
items.push(payload.findFolder.returnedItem);
Vue.set(state, 'items', items);
} else if (payload.findParentFolder) {
// console.info("Going to push...", payload.findFolder.returnedItem);
// console.info("Containing these items...", payload.findFolder.returnedItem.items);
// console.info("Into...", payload.findParentFolder.returnedItem);
payload.findFolder.returnedItem.folder = payload.findParentFolder.name;
payload.findParentFolder.returnedItem.items.push(payload.findFolder.returnedItem);
Vue.set(state,'items', items);
}
},
moveItem (state, payload) {
let { items } = state;
if (payload.parentFolderUUID === "top") {
payload.findItem.returnedItem.folder = "No Folder";
// console.info("Going to push...", payload.findFolder.returnedItem);
// console.info("Containing these items...", payload.findFolder.returnedItem.items);
items.push(payload.findItem.returnedItem);
Vue.set(state,'items', items);
} else if (payload.findParentFolder) {
// console.info("Going to push...", payload.findFolder.returnedItem);
// console.info("Containing these items...", payload.findFolder.returnedItem.items);
// console.info("Into...", payload.findParentFolder.returnedItem);
payload.findItem.returnedItem.folder = payload.findParentFolder.name;
payload.findParentFolder.returnedItem.items.push(payload.findItem.returnedItem);
Vue.set(state,'items', items);
}
}
}
})

View file

@ -0,0 +1,17 @@
/*
vuetify.js
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
import Vue from 'vue';
import Vuetify from 'vuetify/lib';
Vue.use(Vuetify);
export default new Vuetify({
});

View file

@ -0,0 +1,17 @@
/*
vue.config.js
Created by Kalila L. on 7 Apr 2020
Copyright 2020 Vircadia and contributors.
Distributed under the Apache License, Version 2.0.
See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
*/
module.exports = {
publicPath: "./",
assetsDir: "./",
"transpileDependencies": [
"vuetify"
]
}

View file

@ -474,9 +474,10 @@ function takeSnapshot() {
volume: 1.0
});
HMD.closeTablet();
var DOUBLE_RENDER_TIME_TO_MS = 2000; // If rendering is bogged down, allow double the render time to close the tablet.
Script.setTimeout(function () {
Window.takeSnapshot(false, includeAnimated, 1.91);
}, SNAPSHOT_DELAY);
}, Math.max(SNAPSHOT_DELAY, DOUBLE_RENDER_TIME_TO_MS / Rates.render ));
}, FINISH_SOUND_DELAY);
UserActivityLogger.logAction("snaphshot_taken", { location: location.href });
}

View file

@ -3,6 +3,7 @@
//
// Created by Nissim Hadar on 1 Sept 2018.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -46,7 +47,7 @@ TestRunnerDesktop::TestRunnerDesktop(
_installerThread = new QThread();
_installerWorker = new InstallerWorker();
_installerWorker->moveToThread(_installerThread);
_installerThread->start();
connect(this, SIGNAL(startInstaller()), _installerWorker, SLOT(runCommand()));
@ -77,9 +78,9 @@ void TestRunnerDesktop::setWorkingFolderAndEnableControls() {
setWorkingFolder(_workingFolderLabel);
#ifdef Q_OS_WIN
_installationFolder = _workingFolder + "/High Fidelity";
_installationFolder = _workingFolder + "/Vircadia";
#elif defined Q_OS_MAC
_installationFolder = _workingFolder + "/High_Fidelity";
_installationFolder = _workingFolder + "/Vircadia";
#endif
nitpick->enableRunTabControls();
@ -87,11 +88,11 @@ void TestRunnerDesktop::setWorkingFolderAndEnableControls() {
_timer = new QTimer(this);
connect(_timer, SIGNAL(timeout()), this, SLOT(checkTime()));
_timer->start(30 * 1000); //time specified in ms
#ifdef Q_OS_MAC
// Create MAC shell scripts
QFile script;
// This script waits for a process to start
script.setFileName(_workingFolder + "/waitForStart.sh");
if (!script.open(QIODevice::WriteOnly | QIODevice::Text)) {
@ -99,7 +100,7 @@ void TestRunnerDesktop::setWorkingFolderAndEnableControls() {
"Could not open 'waitForStart.sh'");
exit(-1);
}
script.write("#!/bin/sh\n\n");
script.write("PROCESS=\"$1\"\n");
script.write("until (pgrep -x $PROCESS >nul)\n");
@ -118,7 +119,7 @@ void TestRunnerDesktop::setWorkingFolderAndEnableControls() {
"Could not open 'waitForFinish.sh'");
exit(-1);
}
script.write("#!/bin/sh\n\n");
script.write("PROCESS=\"$1\"\n");
script.write("while (pgrep -x $PROCESS >nul)\n");
@ -129,7 +130,7 @@ void TestRunnerDesktop::setWorkingFolderAndEnableControls() {
script.write("echo \"$1\" \"finished\"\n");
script.close();
script.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner);
// Create an AppleScript to resize Interface. This is needed so that snapshots taken
// with the primary camera will be the correct size.
// This will be run from a normal shell script
@ -139,7 +140,7 @@ void TestRunnerDesktop::setWorkingFolderAndEnableControls() {
"Could not open 'setInterfaceSizeAndPosition.scpt'");
exit(-1);
}
script.write("set width to 960\n");
script.write("set height to 540\n");
script.write("set x to 100\n");
@ -155,7 +156,7 @@ void TestRunnerDesktop::setWorkingFolderAndEnableControls() {
"Could not open 'setInterfaceSizeAndPosition.sh'");
exit(-1);
}
script.write("#!/bin/sh\n\n");
script.write("echo resizing interface\n");
script.write(("osascript " + _workingFolder + "/setInterfaceSizeAndPosition.scpt\n").toStdString().c_str());
@ -193,7 +194,7 @@ void TestRunnerDesktop::downloadComplete() {
// Download of Build XML has completed
buildXMLDownloaded = true;
// Download the High Fidelity installer
// Download the Vircadia installer
QStringList urls;
QStringList filenames;
if (_runLatest->isChecked()) {
@ -251,23 +252,23 @@ void TestRunnerDesktop::runInstaller() {
"Could not open 'install_app.sh'");
exit(-1);
}
if (!QDir().exists(_installationFolder)) {
QDir().mkdir(_installationFolder);
}
// This script installs High Fidelity. It is run as "yes | install_app.sh... so "yes" is killed at the end
// This script installs Vircadia. It is run as "yes | install_app.sh... so "yes" is killed at the end
script.write("#!/bin/sh\n\n");
script.write("VOLUME=`hdiutil attach \"$1\" | grep Volumes | awk '{print $3}'`\n");
QString folderName {"High Fidelity"};
QString folderName {"Vircadia"};
if (!_runLatest->isChecked()) {
folderName += QString(" - ") + getPRNumberFromURL(_url->text());
}
script.write((QString("cp -Rf \"$VOLUME/") + folderName + "/interface.app\" \"" + _workingFolder + "/High_Fidelity/\"\n").toStdString().c_str());
script.write((QString("cp -Rf \"$VOLUME/") + folderName + "/Sandbox.app\" \"" + _workingFolder + "/High_Fidelity/\"\n").toStdString().c_str());
script.write("hdiutil detach \"$VOLUME\"\n");
script.write("killall yes\n");
script.close();
@ -303,10 +304,10 @@ void TestRunnerDesktop::verifyInstallationSucceeded() {
if (!interfaceExe.exists() || !assignmentClientExe.exists() || !domainServerExe.exists()) {
if (_runLatest->isChecked()) {
// On Windows, the reason is probably that UAC has blocked the installation. This is treated as a critical error
QMessageBox::critical(0, "Installation of High Fidelity has failed", "Please verify that UAC has been disabled");
QMessageBox::critical(0, "Installation of Vircadia has failed", "Please verify that UAC has been disabled");
exit(-1);
} else {
QMessageBox::critical(0, "Installation of High Fidelity not found", "Please verify that working folder contains a proper installation");
QMessageBox::critical(0, "Installation of vircadia not found", "Please verify that working folder contains a proper installation");
}
}
#endif
@ -320,10 +321,10 @@ void TestRunnerDesktop::saveExistingHighFidelityAppDataFolder() {
dataDirectory = QDir::homePath() + "/Library/Application Support";
#endif
if (_runLatest->isChecked()) {
_appDataFolder = dataDirectory + "/High Fidelity";
_appDataFolder = dataDirectory + "/Vircadia";
} else {
// We are running a PR build
_appDataFolder = dataDirectory + "/High Fidelity - " + getPRNumberFromURL(_url->text());
_appDataFolder = dataDirectory + "/Vircadia - " + getPRNumberFromURL(_url->text());
}
_savedAppDataFolder = dataDirectory + "/" + UNIQUE_FOLDER_NAME;
@ -419,13 +420,13 @@ void TestRunnerDesktop::killProcesses() {
}
#elif defined Q_OS_MAC
QString commandLine;
commandLine = QString("killall interface") + "; " + _workingFolder +"/waitForFinish.sh interface";
system(commandLine.toStdString().c_str());
commandLine = QString("killall Sandbox") + "; " + _workingFolder +"/waitForFinish.sh Sandbox";
system(commandLine.toStdString().c_str());
commandLine = QString("killall Console") + "; " + _workingFolder +"/waitForFinish.sh Console";
system(commandLine.toStdString().c_str());
#endif
@ -433,7 +434,7 @@ void TestRunnerDesktop::killProcesses() {
void TestRunnerDesktop::startLocalServerProcesses() {
QString commandLine;
#ifdef Q_OS_WIN
commandLine =
"start \"domain-server.exe\" \"" + QDir::toNativeSeparators(_installationFolder) + "\\domain-server.exe\"";
@ -501,9 +502,9 @@ void TestRunnerDesktop::runInterfaceWithTestScript() {
"Could not open 'runInterfaceTests.sh'");
exit(-1);
}
script.write("#!/bin/sh\n\n");
// First, run script to delete any entities in test area
commandLine =
"open -W \"" +_installationFolder + "/interface.app\" --args" +
@ -511,9 +512,9 @@ void TestRunnerDesktop::runInterfaceWithTestScript() {
" --no-updater" +
" --no-login-suggestion"
" --testScript " + deleteScript + " quitWhenFinished\n";
script.write(commandLine.toStdString().c_str());
// On The Mac, we need to resize Interface. The Interface window opens a few seconds after the process
// has started.
// Before starting interface, start a process that will resize interface 10s after it opens
@ -539,7 +540,7 @@ void TestRunnerDesktop::runInterfaceWithTestScript() {
emit startInterface();
#endif
// Helpful for debugging
appendLog(commandLine);
}
@ -555,7 +556,7 @@ void TestRunnerDesktop::interfaceExecutionComplete() {
evaluateResults();
// The High Fidelity AppData folder will be restored after evaluation has completed
// The Vircadia AppData folder will be restored after evaluation has completed
}
void TestRunnerDesktop::evaluateResults() {