diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt
index f2690e0a7d..7bf6f05d9f 100644
--- a/cmake/externals/quazip/CMakeLists.txt
+++ b/cmake/externals/quazip/CMakeLists.txt
@@ -41,6 +41,9 @@ if (APPLE)
elseif (WIN32)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip5.lib CACHE FILEPATH "Location of QuaZip release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/quazip5d.lib CACHE FILEPATH "Location of QuaZip release library")
+elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
+ set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.so CACHE FILEPATH "Location of QuaZip release library")
else ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
diff --git a/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml b/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml
index b1b6de4644..aadd7c88ae 100644
--- a/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml
+++ b/interface/resources/qml/dialogs/+android/CustomQueryDialog.qml
@@ -254,7 +254,7 @@ ModalWindow {
text: root.warning;
wrapMode: Text.WordWrap;
font.italic: true;
- maximumLineCount: 2;
+ maximumLineCount: 3;
}
HiFiGlyphs {
diff --git a/interface/resources/qml/dialogs/CustomQueryDialog.qml b/interface/resources/qml/dialogs/CustomQueryDialog.qml
index 008ed5b860..0c86b93c4b 100644
--- a/interface/resources/qml/dialogs/CustomQueryDialog.qml
+++ b/interface/resources/qml/dialogs/CustomQueryDialog.qml
@@ -254,7 +254,7 @@ ModalWindow {
text: root.warning;
wrapMode: Text.WordWrap;
font.italic: true;
- maximumLineCount: 2;
+ maximumLineCount: 3;
}
HiFiGlyphs {
diff --git a/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml b/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml
index 623388e9b3..81a2c5c1e0 100644
--- a/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml
+++ b/interface/resources/qml/dialogs/TabletCustomQueryDialog.qml
@@ -282,7 +282,7 @@ TabletModalWindow {
text: root.warning;
wrapMode: Text.WordWrap;
font.italic: true;
- maximumLineCount: 2;
+ maximumLineCount: 3;
}
HiFiGlyphs {
diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
index 08e3e7a552..6b48f8d51d 100644
--- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
+++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
@@ -124,6 +124,14 @@ Rectangle {
root.numUpdatesAvailable = result.data.updates.length;
}
}
+
+ onAppInstalled: {
+ root.installedApps = Commerce.getInstalledApps();
+ }
+
+ onAppUninstalled: {
+ root.installedApps = Commerce.getInstalledApps();
+ }
}
Timer {
@@ -249,6 +257,145 @@ Rectangle {
Commerce.getWalletStatus();
}
}
+
+ Item {
+ id: installedAppsContainer;
+ z: 998;
+ visible: false;
+ anchors.top: titleBarContainer.bottom;
+ anchors.topMargin: -titleBarContainer.additionalDropdownHeight;
+ anchors.left: parent.left;
+ anchors.bottom: parent.bottom;
+ width: parent.width;
+
+ RalewayRegular {
+ id: installedAppsHeader;
+ anchors.top: parent.top;
+ anchors.topMargin: 10;
+ anchors.left: parent.left;
+ anchors.leftMargin: 12;
+ height: 80;
+ width: paintedWidth;
+ text: "All Installed Marketplace Apps";
+ color: hifi.colors.black;
+ size: 22;
+ }
+
+ ListView {
+ id: installedAppsList;
+ clip: true;
+ model: installedAppsModel;
+ snapMode: ListView.SnapToItem;
+ // Anchors
+ anchors.top: installedAppsHeader.bottom;
+ anchors.left: parent.left;
+ anchors.bottom: sideloadAppButton.top;
+ width: parent.width;
+ delegate: Item {
+ width: parent.width;
+ height: 40;
+
+ RalewayRegular {
+ text: model.appUrl;
+ // Text size
+ size: 16;
+ // Anchors
+ anchors.left: parent.left;
+ anchors.leftMargin: 12;
+ height: parent.height;
+ anchors.right: sideloadAppOpenButton.left;
+ anchors.rightMargin: 8;
+ elide: Text.ElideRight;
+ // Style
+ color: hifi.colors.black;
+ // Alignment
+ verticalAlignment: Text.AlignVCenter;
+
+ MouseArea {
+ anchors.fill: parent;
+ onClicked: {
+ Window.copyToClipboard((model.appUrl).slice(0, -9));
+ }
+ }
+ }
+
+ HifiControlsUit.Button {
+ id: sideloadAppOpenButton;
+ text: "OPEN";
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.top: parent.top;
+ anchors.topMargin: 2;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 2;
+ anchors.right: uninstallGlyph.left;
+ anchors.rightMargin: 8;
+ width: 80;
+ onClicked: {
+ Commerce.openApp(model.appUrl);
+ }
+ }
+
+ HiFiGlyphs {
+ id: uninstallGlyph;
+ text: hifi.glyphs.close;
+ color: hifi.colors.black;
+ size: 22;
+ anchors.top: parent.top;
+ anchors.right: parent.right;
+ anchors.rightMargin: 6;
+ width: 35;
+ height: parent.height;
+ horizontalAlignment: Text.AlignHCenter;
+ MouseArea {
+ anchors.fill: parent;
+ hoverEnabled: true;
+ onEntered: {
+ parent.text = hifi.glyphs.closeInverted;
+ }
+ onExited: {
+ parent.text = hifi.glyphs.close;
+ }
+ onClicked: {
+ Commerce.uninstallApp(model.appUrl);
+ }
+ }
+ }
+ }
+ }
+ HifiControlsUit.Button {
+ id: sideloadAppButton;
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 8;
+ anchors.left: parent.left;
+ anchors.leftMargin: 8;
+ anchors.right: closeAppListButton.left;
+ anchors.rightMargin: 8;
+ height: 40;
+ text: "SIDELOAD APP FROM LOCAL DISK";
+ onClicked: {
+ Window.browseChanged.connect(onFileOpenChanged);
+ Window.browseAsync("Locate your app's .app.json file", "", "*.app.json");
+ }
+ }
+ HifiControlsUit.Button {
+ id: closeAppListButton;
+ color: hifi.buttons.white;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 8;
+ anchors.right: parent.right;
+ anchors.rightMargin: 8;
+ width: 100;
+ height: 40;
+ text: "BACK";
+ onClicked: {
+ installedAppsContainer.visible = false;
+ }
+ }
+ }
HifiWallet.NeedsLogIn {
id: needsLogIn;
@@ -317,7 +464,7 @@ Rectangle {
//
Item {
id: purchasesContentsContainer;
- visible: root.activeView === "purchasesMain";
+ visible: root.activeView === "purchasesMain" && !installedAppsList.visible;
// Anchors
anchors.left: parent.left;
anchors.right: parent.right;
@@ -959,6 +1106,39 @@ Rectangle {
}
}
+ Keys.onPressed: {
+ if ((event.key == Qt.Key_F) && (event.modifiers & Qt.ControlModifier)) {
+ installedAppsContainer.visible = !installedAppsContainer.visible;
+ console.log("User changed visibility of installedAppsContainer to " + installedAppsContainer.visible);
+ }
+ }
+ function onFileOpenChanged(filename) {
+ // disconnect the event, otherwise the requests will stack up
+ try { // Not all calls to onFileOpenChanged() connect an event.
+ Window.browseChanged.disconnect(onFileOpenChanged);
+ } catch (e) {
+ console.log('Purchases.qml ignoring', e);
+ }
+ if (filename) {
+ Commerce.installApp(filename);
+ }
+ }
+ ListModel {
+ id: installedAppsModel;
+ }
+ onInstalledAppsChanged: {
+ installedAppsModel.clear();
+ var installedAppsArray = root.installedApps.split(",");
+ var installedAppsObject = [];
+ // "- 1" because the last app string ends with ","
+ for (var i = 0; i < installedAppsArray.length - 1; i++) {
+ installedAppsObject[i] = {
+ "appUrl": installedAppsArray[i]
+ }
+ }
+ installedAppsModel.append(installedAppsObject);
+ }
+
//
// Function Name: fromScript()
//
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index d801c9cb05..cd4562da54 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -1070,6 +1070,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
if (steamClient) {
qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << steamClient->getSteamVRBuildID();
}
+ setCrashAnnotation("steam", property(hifi::properties::STEAM).toBool() ? "1" : "0");
+
qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
qCDebug(interfaceapp) << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION;
qCDebug(interfaceapp) << "[VERSION] VERSION:" << BuildInfo::VERSION;
@@ -1155,6 +1157,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
const DomainHandler& domainHandler = nodeList->getDomainHandler();
connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainURLChanged(QUrl)));
+ connect(&domainHandler, &DomainHandler::domainURLChanged, [](QUrl domainURL){
+ setCrashAnnotation("domain", domainURL.toString().toStdString());
+ });
connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain()));
connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle()));
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
@@ -1200,6 +1205,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
auto dialogsManager = DependencyManager::get Properties The default scripts implement hand controller actions that use {@link Entities.callEntityMethod} to call entity script
+ * methods, if present in the entity being interacted with. All the entity methods are called with the following two arguments: Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take effect.
+ *
+ * Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take
+ * effect. Mappings and their routes are applied according to the following rules: A route in a {@link MappingObject} used by the {@link Controller} API. Create a route using {@link MappingObject} methods and apply this object's methods to process it, terminating with
- * {@link RouteObject#to} to apply it to a Functions:
+ * Functions
*
*
@@ -143,6 +143,61 @@ class ScriptEngine;
*
*
+ * Entity Methods:
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * Method Name Description Example
+ *
+ *
+ * startFarTrigger
continueFarTrigger
stopFarTrigger
These methods are called when a user is more than 0.3m away from the entity, the entity is triggerable, and the
+ * user starts, continues, or stops squeezing the trigger.
+ *
+ * A light switch that can be toggled on and off from a distance.
+ *
+ *
+ *
+ * startNearTrigger
continueNearTrigger
stopNearTrigger
These methods are called when a user is less than 0.3m away from the entity, the entity is triggerable, and the
+ * user starts, continues, or stops squeezing the trigger.
+ * A doorbell that can be rung when a user is near.
+ *
+ *
+ *
+ * startDistanceGrab
continueDistanceGrab
These methods are called when a user is more than 0.3m away from the entity, the entity is either cloneable, or
+ * grabbable and not locked, and the user starts or continues to squeeze the trigger.
+ * A comet that emits icy particle trails when a user is dragging it through the sky.
+ *
+ *
+ *
+ * startNearGrab
continueNearGrab
These methods are called when a user is less than 0.3m away from the entity, the entity is either cloneable, or
+ * grabbable and not locked, and the user starts or continues to squeeze the trigger.
+ * A ball that glows when it's being held close.
+ *
+ *
+ *
+ * releaseGrab
This method is called when a user releases the trigger when having been either distance or near grabbing an
+ * entity.
+ * Turn off the ball glow or comet trail with the user finishes grabbing it.
+ *
+ *
+ *
+ *
+ * startEquip
continueEquip
releaseEquip
These methods are called when a user starts, continues, or stops equipping an entity.
+ * A glass that stays in the user's hand after the trigger is clicked.
+ *
+ *
+ *
* @namespace Controller
*
* @hifi-interface
diff --git a/libraries/animation/src/AnimExpression.cpp b/libraries/animation/src/AnimExpression.cpp
index 79004a72a6..9777e9c6af 100644
--- a/libraries/animation/src/AnimExpression.cpp
+++ b/libraries/animation/src/AnimExpression.cpp
@@ -588,6 +588,7 @@ void AnimExpression::evalUnaryMinus(const AnimVariantMap& map, std::stack"hand,userID"
— where "hand" is "left"
or "right"
, and "userID"
+ * is the user's {@link MyAvatar|MyAvatar.sessionUUID}.
diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
index 3204e0502f..804709ebfa 100644
--- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
+++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
@@ -29,7 +29,8 @@ class ScriptingInterface;
*
Standard
control, action, or script function.Standard
control, action, or script function. Note: Loops are not
+ * permitted.
Some methods apply to routes with number data, some apply routes with {@link Pose} data, and some apply to both route * types.
diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 2491d4bbbd..8adb5138f2 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -396,17 +396,18 @@ public slots: /**jsdoc * Find all entities of a particular name that intersect a sphere defined by a center point and radius. * @function Entities.findEntitiesByName - * @param {Entities.EntityType} entityName - The name of the entity to search for. + * @param {string} entityName - The name of the entity to search for. * @param {Vec3} center - The point about which to search. * @param {number} radius - The radius within which to search. - * @param {boolean} caseSensitiveSearch - Choose whether to to return case sensitive results back. - * @returns {Uuid[]} An array of entity IDs of the specified type that intersect the search sphere. The array is empty if - * no entities could be found. - * @example
true
then the search is case-sensitive.
+ * @returns {Uuid[]} An array of entity IDs that have the specified name and intersect the search sphere. The array is empty
+ * if no entities could be found.
+ * @example Light
and Zone
entities are not
diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp
index 9a96364de2..055d94c3b3 100644
--- a/libraries/networking/src/AddressManager.cpp
+++ b/libraries/networking/src/AddressManager.cpp
@@ -333,12 +333,14 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
return false;
}
+static const QString LOCALHOST = "localhost";
+
bool isPossiblePlaceName(QString possiblePlaceName) {
bool result { false };
int length = possiblePlaceName.length();
static const int MINIMUM_PLACENAME_LENGTH = 1;
static const int MAXIMUM_PLACENAME_LENGTH = 64;
- if (possiblePlaceName.toLower() != "localhost" &&
+ if (possiblePlaceName.toLower() != LOCALHOST &&
length >= MINIMUM_PLACENAME_LENGTH && length <= MAXIMUM_PLACENAME_LENGTH) {
const QRegExp PLACE_NAME_REGEX = QRegExp("^[0-9A-Za-z](([0-9A-Za-z]|-(?!-))*[^\\W_]$|$)");
result = PLACE_NAME_REGEX.indexIn(possiblePlaceName) == 0;
@@ -358,7 +360,7 @@ void AddressManager::handleLookupString(const QString& lookupString, bool fromSu
sanitizedString = sanitizedString.remove(HIFI_SCHEME_REGEX);
lookupURL = QUrl(sanitizedString);
- if (lookupURL.scheme().isEmpty()) {
+ if (lookupURL.scheme().isEmpty() || lookupURL.scheme().toLower() == LOCALHOST) {
lookupURL = QUrl("hifi://" + sanitizedString);
}
} else {
@@ -607,7 +609,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri
if (ipAddressRegex.indexIn(lookupString) != -1) {
QString domainIPString = ipAddressRegex.cap(1);
- quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
+ quint16 domainPort = 0;
if (!ipAddressRegex.cap(2).isEmpty()) {
domainPort = (quint16) ipAddressRegex.cap(2).toInt();
}
@@ -629,7 +631,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri
if (hostnameRegex.indexIn(lookupString) != -1) {
QString domainHostname = hostnameRegex.cap(1);
- quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
+ quint16 domainPort = 0;
if (!hostnameRegex.cap(2).isEmpty()) {
domainPort = (quint16)hostnameRegex.cap(2).toInt();
diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp
index cd8064c4c0..871dc26899 100644
--- a/libraries/networking/src/DomainHandler.cpp
+++ b/libraries/networking/src/DomainHandler.cpp
@@ -166,7 +166,12 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) {
}
}
- if (_domainURL != domainURL || _sockAddr.getPort() != domainURL.port()) {
+ auto domainPort = domainURL.port();
+ if (domainPort == -1) {
+ domainPort = DEFAULT_DOMAIN_SERVER_PORT;
+ }
+
+ if (_domainURL != domainURL || _sockAddr.getPort() != domainPort) {
// re-set the domain info so that auth information is reloaded
hardReset();
@@ -192,12 +197,10 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) {
emit domainURLChanged(_domainURL);
- if (_sockAddr.getPort() != domainURL.port()) {
- qCDebug(networking) << "Updated domain port to" << domainURL.port();
+ if (_sockAddr.getPort() != domainPort) {
+ qCDebug(networking) << "Updated domain port to" << domainPort;
+ _sockAddr.setPort(domainPort);
}
-
- // grab the port by reading the string after the colon
- _sockAddr.setPort(domainURL.port());
}
}
diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp
index ab7c2ec252..3ea3616b15 100644
--- a/libraries/physics/src/PhysicalEntitySimulation.cpp
+++ b/libraries/physics/src/PhysicalEntitySimulation.cpp
@@ -153,6 +153,8 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
// remove the objects (aka MotionStates) from physics
_physicsEngine->removeSetOfObjects(_physicalObjects);
+ clearOwnershipData();
+
// delete the MotionStates
for (auto stateItr : _physicalObjects) {
EntityMotionState* motionState = static_castNote: Can only be connected to via this.preload = function (...) { ... }
in the entity script.
Available in: | Client Entity Scripts | Server Entity Scripts |
---|
Note: Can only be connected to via this.unoad = function () { ... }
in the entity script.
Available in: | Client Entity Scripts | Server Entity Scripts |
---|