diff --git a/android/app/build.gradle b/android/app/build.gradle
index 92dece2414..3537df033d 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -28,7 +28,7 @@ android {
'-DSTABLE_BUILD=' + STABLE_BUILD,
'-DDISABLE_QML=OFF',
'-DDISABLE_KTX_CACHE=OFF',
- '-DUSE_BREAKPAD=' + (project.hasProperty("BACKTRACE_URL") && project.hasProperty("BACKTRACE_TOKEN") ? 'ON' : 'OFF');
+ '-DUSE_BREAKPAD=' + (System.getenv("CMAKE_BACKTRACE_URL") && System.getenv("CMAKE_BACKTRACE_TOKEN") ? 'ON' : 'OFF');
}
}
signingConfigs {
@@ -48,8 +48,8 @@ android {
buildTypes {
debug {
- buildConfigField "String", "BACKTRACE_URL", "\"" + (project.hasProperty("BACKTRACE_URL") ? BACKTRACE_URL : '') + "\""
- buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (project.hasProperty("BACKTRACE_TOKEN") ? BACKTRACE_TOKEN : '') + "\""
+ buildConfigField "String", "BACKTRACE_URL", "\"" + (System.getenv("CMAKE_BACKTRACE_URL") ? System.getenv("CMAKE_BACKTRACE_URL") : '') + "\""
+ buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (System.getenv("CMAKE_BACKTRACE_TOKEN") ? System.getenv("CMAKE_BACKTRACE_TOKEN") : '') + "\""
}
release {
minifyEnabled false
@@ -58,8 +58,8 @@ android {
project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") &&
project.hasProperty("HIFI_ANDROID_KEY_ALIAS") &&
project.hasProperty("HIFI_ANDROID_KEY_PASSWORD")? signingConfigs.release : null
- buildConfigField "String", "BACKTRACE_URL", "\"" + (project.hasProperty("BACKTRACE_URL") ? BACKTRACE_URL : '') + "\""
- buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (project.hasProperty("BACKTRACE_TOKEN") ? BACKTRACE_TOKEN : '') + "\""
+ buildConfigField "String", "BACKTRACE_URL", "\"" + (System.getenv("CMAKE_BACKTRACE_URL") ? System.getenv("CMAKE_BACKTRACE_URL") : '') + "\""
+ buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (System.getenv("CMAKE_BACKTRACE_TOKEN") ? System.getenv("CMAKE_BACKTRACE_TOKEN") : '') + "\""
}
}
@@ -74,6 +74,10 @@ android {
// so our merge has to depend on the external native build
variant.externalNativeBuildTasks.each { task ->
variant.mergeResources.dependsOn(task)
+ def uploadDumpSymsTask = rootProject.getTasksByName("uploadBreakpadDumpSyms${variant.name.capitalize()}", false).first()
+ def runDumpSymsTask = rootProject.getTasksByName("runBreakpadDumpSyms${variant.name.capitalize()}", false).first()
+ runDumpSymsTask.dependsOn(task)
+ variant.assemble.dependsOn(uploadDumpSymsTask)
}
variant.mergeAssets.doLast {
diff --git a/android/build.gradle b/android/build.gradle
index e2d92fe2f6..373569ca77 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -21,6 +21,7 @@ buildscript {
plugins {
id 'de.undercouch.download' version '3.3.0'
id "cz.malohlava" version "1.0.3"
+ id "io.github.http-builder-ng.http-plugin" version "0.1.1"
}
allprojects {
@@ -67,6 +68,7 @@ def baseFolder = new File(HIFI_ANDROID_PRECOMPILED)
def appDir = new File(projectDir, 'app')
def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a')
def baseUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/android/'
+def breakpadDumpSymsDir = new File("${appDir}/build/tmp/breakpadDumpSyms")
def qtFile='qt-5.9.3_linux_armv8-libcpp_openssl.tgz'
def qtChecksum='04599670ccca84bd2b15f6915568eb2d'
@@ -151,11 +153,11 @@ def packages = [
checksum: '14b02795d774457a33bbc60e00a786bc'
],
breakpad: [
- file: 'breakpad.zip',
- versionId: '2OwvCCZrF171wnte5T44AnjTYFhhJsGJ',
- checksum: 'a46062a3167dfedd4fb4916136e204d2',
+ file: 'breakpad.tgz',
+ versionId: '8VrYXz7oyc.QBxNia0BVJOUBvrFO61jI',
+ checksum: 'ddcb23df336b08017042ba4786db1d9e',
sharedLibFolder: 'lib',
- includeLibs: ['libbreakpad_client.a','libbreakpad.a']
+ includeLibs: ['libbreakpad_client.a']
]
]
@@ -549,7 +551,93 @@ task cleanDependencies(type: Delete) {
delete 'app/src/main/res/values/libs.xml'
}
+def runBreakpadDumpSyms = { buildType ->
+ gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS
+ def objDir = new File("${appDir}/build/intermediates/cmake/${buildType}/obj/arm64-v8a")
+ def stripDebugSymbol = "${appDir}/build/intermediates/transforms/stripDebugSymbol/${buildType}/0/lib/arm64-v8a/"
+ def outputDir = new File(breakpadDumpSymsDir, buildType)
+ if (!outputDir.exists()) {
+ outputDir.mkdirs()
+ }
+
+ objDir.eachFileRecurse (FileType.FILES) { file ->
+ if (file.name.endsWith('.so')) {
+ def output = file.name + ".sym"
+ def cmdArgs = [
+ file.toString(),
+ stripDebugSymbol
+ ]
+ def result = exec {
+ workingDir HIFI_ANDROID_PRECOMPILED + '/breakpad/bin'
+ commandLine './dump_syms'
+ args cmdArgs
+ ignoreExitValue true
+ standardOutput = new BufferedOutputStream(new FileOutputStream(new File(outputDir, output)))
+ }
+ }
+ }
+}
+
+task runBreakpadDumpSymsDebug() {
+ doLast {
+ runBreakpadDumpSyms("debug");
+ }
+}
+
+task runBreakpadDumpSymsRelease() {
+ doLast {
+ runBreakpadDumpSyms("release");
+ }
+}
+
+task zipDumpSymsDebug(type: Zip, dependsOn: runBreakpadDumpSymsDebug) {
+ from (new File(breakpadDumpSymsDir, "debug").absolutePath)
+ archiveName "symbols-${RELEASE_NUMBER}-debug.zip"
+ destinationDir(new File("${appDir}/build/tmp/"))
+}
+
+task zipDumpSymsRelease(type: Zip, dependsOn: runBreakpadDumpSymsRelease) {
+ from (new File(breakpadDumpSymsDir, "release").absolutePath)
+ archiveName "symbols-${RELEASE_NUMBER}-release.zip"
+ destinationDir(new File("${appDir}/build/tmp/"))
+}
+
+task uploadBreakpadDumpSymsDebug(type:io.github.httpbuilderng.http.HttpTask, dependsOn: zipDumpSymsDebug) {
+ onlyIf {
+ System.getenv("CMAKE_BACKTRACE_URL") && System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")
+ }
+ config {
+ request.uri = System.getenv("CMAKE_BACKTRACE_URL")
+ }
+ post {
+ request.uri.path = '/post'
+ request.uri.query = [format: 'symbols', token: System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")]
+ request.body = new File("${appDir}/build/tmp/", "symbols-${RELEASE_NUMBER}-debug.zip").bytes
+ request.contentType = 'application/octet-stream'
+ response.success {
+ println ("${appDir}/build/tmp/symbols-${RELEASE_NUMBER}-debug.zip uploaded")
+ }
+ }
+}
+
+task uploadBreakpadDumpSymsRelease(type:io.github.httpbuilderng.http.HttpTask, dependsOn: zipDumpSymsRelease) {
+ onlyIf {
+ System.getenv("CMAKE_BACKTRACE_URL") && System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")
+ }
+ config {
+ request.uri = System.getenv("CMAKE_BACKTRACE_URL")
+ }
+ post {
+ request.uri.path = '/post'
+ request.uri.query = [format: 'symbols', token: System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")]
+ request.body = new File("${appDir}/build/tmp/", "symbols-${RELEASE_NUMBER}-release.zip").bytes
+ request.contentType = 'application/octet-stream'
+ response.success {
+ println ("${appDir}/build/tmp/symbols-${RELEASE_NUMBER}-release.zip uploaded")
+ }
+ }
+}
// FIXME this code is prototyping the desired functionality for doing build time binary dependency resolution.
// See the comment on the qtBundle task above
diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml
index b43372da5c..9f1d307f0e 100644
--- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml
+++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml
@@ -646,6 +646,7 @@ Item {
height: 40;
enabled: root.hasPermissionToRezThis &&
MyAvatar.skeletonModelURL !== root.itemHref &&
+ !root.wornEntityID &&
root.valid;
onHoveredChanged: {
diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
index 0d2acf4ec3..8a5b1fb0e7 100644
--- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
+++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
@@ -957,7 +957,7 @@ Rectangle {
function updateCurrentlyWornWearables(wearables) {
for (var i = 0; i < purchasesModel.count; i++) {
for (var j = 0; j < wearables.length; j++) {
- if (purchasesModel.get(i).itemType === "wearable" &&
+ if (purchasesModel.get(i).item_type === "wearable" &&
wearables[j].entityCertID === purchasesModel.get(i).certificate_id &&
wearables[j].entityEdition.toString() === purchasesModel.get(i).edition_number) {
purchasesModel.setProperty(i, 'wornEntityID', wearables[j].entityID);
diff --git a/interface/resources/qml/hifi/commerce/wallet/Help.qml b/interface/resources/qml/hifi/commerce/wallet/Help.qml
index d76fe0d8a2..b453509712 100644
--- a/interface/resources/qml/hifi/commerce/wallet/Help.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/Help.qml
@@ -253,7 +253,11 @@ At the moment, there is currently no way to convert HFC to other currencies. Sta
} else if (link === "#blockchain") {
Qt.openUrlExternally("https://docs.highfidelity.com/high-fidelity-commerce");
} else if (link === "#bank") {
- Qt.openUrlExternally("hifi://BankOfHighFidelity");
+ if ((Account.metaverseServerURL).toString().indexOf("staging") >= 0) {
+ Qt.openUrlExternally("hifi://hifiqa-master-metaverse-staging"); // So that we can test in staging.
+ } else {
+ Qt.openUrlExternally("hifi://BankOfHighFidelity");
+ }
} else if (link === "#support") {
Qt.openUrlExternally("mailto:support@highfidelity.com");
}
diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml
index 2a6ddfddfb..3e0a56b4c5 100644
--- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml
@@ -76,7 +76,7 @@ Item {
anchors.top: parent.top;
anchors.left: parent.left;
anchors.leftMargin: 20;
- width: parent.width/2;
+ width: parent.width/2 - anchors.leftMargin;
height: 80;
}
@@ -252,64 +252,6 @@ Item {
anchors.bottom: parent.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
-
- Item {
- // On empty history. We don't want to flash and then replace, so don't show until we know we should.
- // The history is empty when it contains 1 item (the pending item count) AND there are no pending items.
- visible: transactionHistoryModel.count === 1 &&
- transactionHistoryModel.retrievedAtLeastOnePage &&
- transactionHistoryModel.get(0).count === 0;
- anchors.centerIn: parent;
- width: parent.width - 12;
- height: parent.height;
-
- HifiControlsUit.Separator {
- colorScheme: 1;
- anchors.left: parent.left;
- anchors.right: parent.right;
- anchors.top: parent.top;
- }
-
- RalewayRegular {
- id: noActivityText;
- text: "Congrats! Your wallet is all set!
" +
- "Where's my HFC?
" +
- "High Fidelity commerce is in open beta right now. Want more HFC? Get it by meeting with a banker at " +
- "BankOfHighFidelity!"
- // Text size
- size: 22;
- // Style
- color: hifi.colors.blueAccent;
- anchors.top: parent.top;
- anchors.topMargin: 36;
- anchors.left: parent.left;
- anchors.leftMargin: 12;
- anchors.right: parent.right;
- anchors.rightMargin: 12;
- height: paintedHeight;
- wrapMode: Text.WordWrap;
- horizontalAlignment: Text.AlignHCenter;
-
- onLinkActivated: {
- sendSignalToWallet({ method: "transactionHistory_goToBank" });
- }
- }
-
- HifiControlsUit.Button {
- id: bankButton;
- color: hifi.buttons.blue;
- colorScheme: hifi.colorSchemes.dark;
- anchors.top: noActivityText.bottom;
- anchors.topMargin: 30;
- anchors.horizontalCenter: parent.horizontalCenter;
- width: parent.width/2;
- height: 50;
- text: "VISIT BANK OF HIGH FIDELITY";
- onClicked: {
- sendSignalToWallet({ method: "transactionHistory_goToBank" });
- }
- }
- }
ListView {
id: transactionHistory;
@@ -411,6 +353,64 @@ Item {
}
}
}
+
+ Item {
+ // On empty history. We don't want to flash and then replace, so don't show until we know we should.
+ // The history is empty when it contains 1 item (the pending item count) AND there are no pending items.
+ visible: transactionHistoryModel.count === 1 &&
+ transactionHistoryModel.retrievedAtLeastOnePage &&
+ transactionHistoryModel.get(0).count === 0;
+ anchors.centerIn: parent;
+ width: parent.width - 12;
+ height: parent.height;
+
+ HifiControlsUit.Separator {
+ colorScheme: 1;
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+ anchors.top: parent.top;
+ }
+
+ RalewayRegular {
+ id: noActivityText;
+ text: "Congrats! Your wallet is all set!
" +
+ "Where's my HFC?
" +
+ "High Fidelity commerce is in open beta right now. Want more HFC? Get it by meeting with a banker at " +
+ "BankOfHighFidelity!"
+ // Text size
+ size: 22;
+ // Style
+ color: hifi.colors.blueAccent;
+ anchors.top: parent.top;
+ anchors.topMargin: 36;
+ anchors.left: parent.left;
+ anchors.leftMargin: 12;
+ anchors.right: parent.right;
+ anchors.rightMargin: 12;
+ height: paintedHeight;
+ wrapMode: Text.WordWrap;
+ horizontalAlignment: Text.AlignHCenter;
+
+ onLinkActivated: {
+ sendSignalToWallet({ method: "transactionHistory_goToBank" });
+ }
+ }
+
+ HifiControlsUit.Button {
+ id: bankButton;
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.top: noActivityText.bottom;
+ anchors.topMargin: 30;
+ anchors.horizontalCenter: parent.horizontalCenter;
+ width: parent.width/2;
+ height: 50;
+ text: "VISIT BANK OF HIGH FIDELITY";
+ onClicked: {
+ sendSignalToWallet({ method: "transactionHistory_goToBank" });
+ }
+ }
+ }
}
}
diff --git a/interface/src/CrashHandler_Breakpad.cpp b/interface/src/CrashHandler_Breakpad.cpp
index fe4979853e..f2a174b6ea 100644
--- a/interface/src/CrashHandler_Breakpad.cpp
+++ b/interface/src/CrashHandler_Breakpad.cpp
@@ -24,6 +24,7 @@
#include
#include
+#include
google_breakpad::ExceptionHandler* gBreakpadHandler;
@@ -43,7 +44,23 @@ QString obbDir() {
return dataAbsPath;
}
+void flushAnnotations() {
+ QSettings settings(obbDir() + "/annotations.json", JSON_FORMAT);
+ settings.clear();
+ settings.beginGroup("Annotations");
+ for (auto k : annotations.keys()) {
+ settings.setValue(k, annotations.value(k));
+ }
+ settings.endGroup();
+ settings.sync();
+}
+
bool startCrashHandler() {
+ annotations["version"] = BuildInfo::VERSION;
+ annotations["build_number"] = BuildInfo::BUILD_NUMBER;
+ annotations["build_type"] = BuildInfo::BUILD_TYPE_STRING;
+
+ flushAnnotations();
gBreakpadHandler = new google_breakpad::ExceptionHandler(
google_breakpad::MinidumpDescriptor(obbDir().toStdString()),
@@ -56,15 +73,7 @@ void setCrashAnnotation(std::string name, std::string value) {
QString qName = QString::fromStdString(name);
QString qValue = QString::fromStdString(value);
annotations[qName] = qValue;
-
- QSettings settings(obbDir() + "/annotations.json", JSON_FORMAT);
- settings.clear();
- settings.beginGroup("Annotations");
- for (auto k : annotations.keys()) {
- settings.setValue(k, annotations.value(k));
- }
- settings.endGroup();
- settings.sync();
+ flushAnnotations();
}
#endif
diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp
index 4d133706e6..c63095a204 100644
--- a/interface/src/avatar/AvatarManager.cpp
+++ b/interface/src/avatar/AvatarManager.cpp
@@ -186,6 +186,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
uint64_t updateExpiry = startTime + UPDATE_BUDGET;
int numAvatarsUpdated = 0;
int numAVatarsNotUpdated = 0;
+ bool physicsEnabled = qApp->isPhysicsEnabled();
render::Transaction transaction;
while (!sortedAvatars.empty()) {
@@ -202,7 +203,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
if (_shouldRender) {
avatar->ensureInScene(avatar, qApp->getMain3DScene());
}
- if (!avatar->isInPhysicsSimulation()) {
+ if (physicsEnabled && !avatar->isInPhysicsSimulation()) {
ShapeInfo shapeInfo;
avatar->computeShapeInfo(shapeInfo);
btCollisionShape* shape = const_cast(ObjectMotionState::getShapeManager()->getShape(shapeInfo));
diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp
index 6fc1bd8196..50c715b14a 100644
--- a/interface/src/avatar/AvatarMotionState.cpp
+++ b/interface/src/avatar/AvatarMotionState.cpp
@@ -154,6 +154,10 @@ const QUuid AvatarMotionState::getObjectID() const {
return _avatar->getSessionUUID();
}
+QString AvatarMotionState::getName() const {
+ return _avatar->getName();
+}
+
// virtual
QUuid AvatarMotionState::getSimulatorID() const {
return _avatar->getSessionUUID();
diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h
index 2738aba8ee..9228641b25 100644
--- a/interface/src/avatar/AvatarMotionState.h
+++ b/interface/src/avatar/AvatarMotionState.h
@@ -59,6 +59,7 @@ public:
virtual const QUuid getObjectID() const override;
+ virtual QString getName() const override;
virtual QUuid getSimulatorID() const override;
void setBoundingBox(const glm::vec3& corner, const glm::vec3& diagonal);
diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp
index 68c61e9385..a99838d810 100644
--- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp
+++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp
@@ -307,7 +307,6 @@ void Avatar::updateAvatarEntities() {
// NOTE: if this avatar entity is not attached to us, strip its entity script completely...
auto attachedScript = properties.getScript();
if (!isMyAvatar() && !attachedScript.isEmpty()) {
- qCDebug(avatars_renderer) << "removing entity script from avatar attached entity:" << entityID << "old script:" << attachedScript;
QString noScript;
properties.setScript(noScript);
}
diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp
index 4d31067c20..b990d3612b 100644
--- a/libraries/physics/src/PhysicalEntitySimulation.cpp
+++ b/libraries/physics/src/PhysicalEntitySimulation.cpp
@@ -312,11 +312,26 @@ void PhysicalEntitySimulation::handleDeactivatedMotionStates(const VectorOfMotio
assert(state);
if (state->getType() == MOTIONSTATE_TYPE_ENTITY) {
EntityMotionState* entityState = static_cast(state);
- if (!serverlessMode) {
- entityState->handleDeactivation();
- }
EntityItemPointer entity = entityState->getEntity();
_entitiesToSort.insert(entity);
+ if (!serverlessMode) {
+ if (entity->getClientOnly()) {
+ switch (entityState->getOwnershipState()) {
+ case EntityMotionState::OwnershipState::PendingBid:
+ _bids.removeFirst(entityState);
+ entityState->clearOwnershipState();
+ break;
+ case EntityMotionState::OwnershipState::LocallyOwned:
+ _owned.removeFirst(entityState);
+ entityState->clearOwnershipState();
+ break;
+ default:
+ break;
+ }
+ } else {
+ entityState->handleDeactivation();
+ }
+ }
}
}
}
diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h
index 3f04347f18..fdf996df25 100644
--- a/libraries/physics/src/PhysicalEntitySimulation.h
+++ b/libraries/physics/src/PhysicalEntitySimulation.h
@@ -37,6 +37,14 @@ public:
}
pop_back();
}
+ void removeFirst(EntityMotionState* state) {
+ for (uint32_t i = 0; i < size(); ++i) {
+ if ((*this)[i] == state) {
+ remove(i);
+ break;
+ }
+ }
+ }
};
class PhysicalEntitySimulation : public EntitySimulation {
diff --git a/scripts/system/+android/audio.js b/scripts/system/+android/audio.js
index 50919ed5d1..34dd52604a 100644
--- a/scripts/system/+android/audio.js
+++ b/scripts/system/+android/audio.js
@@ -46,7 +46,6 @@ function init() {
function onMuteClicked() {
Audio.muted = !Audio.muted;
- Menu.triggerOption("Out of Bounds Vector Access");
}
function onMutePressed() {
diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js
index 5d90898b82..a724c2037b 100644
--- a/scripts/system/controllers/controllerModules/inEditMode.js
+++ b/scripts/system/controllers/controllerModules/inEditMode.js
@@ -18,10 +18,16 @@ Script.include("/~/system/libraries/controllers.js");
Script.include("/~/system/libraries/utils.js");
(function () {
+ var MARGIN = 25;
+
function InEditMode(hand) {
this.hand = hand;
this.triggerClicked = false;
this.selectedTarget = null;
+ this.reticleMinX = MARGIN;
+ this.reticleMaxX;
+ this.reticleMinY = MARGIN;
+ this.reticleMaxY;
this.parameters = makeDispatcherModuleParameters(
160,
@@ -47,6 +53,16 @@ Script.include("/~/system/libraries/utils.js");
return (HMD.tabletScreenID && objectID === HMD.tabletScreenID)
|| (HMD.homeButtonID && objectID === HMD.homeButtonID);
};
+
+ this.calculateNewReticlePosition = function(intersection) {
+ var dims = Controller.getViewportDimensions();
+ this.reticleMaxX = dims.x - MARGIN;
+ this.reticleMaxY = dims.y - MARGIN;
+ var point2d = HMD.overlayFromWorldPoint(intersection);
+ point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX));
+ point2d.y = Math.max(this.reticleMinY, Math.min(point2d.y, this.reticleMaxY));
+ return point2d;
+ };
this.sendPickData = function(controllerData) {
if (controllerData.triggerClicks[this.hand]) {
@@ -72,6 +88,23 @@ Script.include("/~/system/libraries/utils.js");
this.triggerClicked = true;
}
+
+ this.sendPointingAtData(controllerData);
+ };
+
+ this.sendPointingAtData = function(controllerData) {
+ var rayPick = controllerData.rayPicks[this.hand];
+ var hudRayPick = controllerData.hudRayPicks[this.hand];
+ var point2d = this.calculateNewReticlePosition(hudRayPick.intersection);
+ var desktopWindow = Window.isPointOnDesktopWindow(point2d);
+ var tablet = this.pointingAtTablet(rayPick.objectID);
+ var rightHand = this.hand === RIGHT_HAND;
+ Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({
+ method: "pointingAt",
+ desktopWindow: desktopWindow,
+ tablet: tablet,
+ rightHand: rightHand
+ }));
};
this.exitModule = function() {
@@ -104,6 +137,7 @@ Script.include("/~/system/libraries/utils.js");
if (overlayLaser) {
var overlayLaserReady = overlayLaser.isReady(controllerData);
var target = controllerData.rayPicks[this.hand].objectID;
+ this.sendPointingAtData(controllerData);
if (overlayLaserReady.active && this.pointingAtTablet(target)) {
return this.exitModule();
}
diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js
index 1b41559160..33e67f7ebf 100644
--- a/scripts/system/libraries/entitySelectionTool.js
+++ b/scripts/system/libraries/entitySelectionTool.js
@@ -58,6 +58,14 @@ SelectionManager = (function() {
that.setSelections([messageParsed.entityID]);
} else if (messageParsed.method === "clearSelection") {
that.clearSelections();
+ } else if (messageParsed.method === "pointingAt") {
+ if (messageParsed.rightHand) {
+ that.pointingAtDesktopWindowRight = messageParsed.desktopWindow;
+ that.pointingAtTabletRight = messageParsed.tablet;
+ } else {
+ that.pointingAtDesktopWindowLeft = messageParsed.desktopWindow;
+ that.pointingAtTabletLeft = messageParsed.tablet;
+ }
}
}
@@ -93,6 +101,11 @@ SelectionManager = (function() {
that.worldDimensions = Vec3.ZERO;
that.worldRegistrationPoint = Vec3.HALF;
that.centerPosition = Vec3.ZERO;
+
+ that.pointingAtDesktopWindowLeft = false;
+ that.pointingAtDesktopWindowRight = false;
+ that.pointingAtTabletLeft = false;
+ that.pointingAtTabletRight = false;
that.saveProperties = function() {
that.savedProperties = {};
@@ -313,8 +326,6 @@ SelectionDisplay = (function() {
var CTRL_KEY_CODE = 16777249;
- var AVATAR_COLLISIONS_OPTION = "Enable Avatar Collisions";
-
var TRANSLATE_DIRECTION = {
X : 0,
Y : 1,
@@ -368,7 +379,7 @@ SelectionDisplay = (function() {
var ctrlPressed = false;
- var handleStretchCollisionOverride = false;
+ var replaceCollisionsAfterStretch = false;
var handlePropertiesTranslateArrowCones = {
shape: "Cone",
@@ -644,11 +655,6 @@ SelectionDisplay = (function() {
var activeTool = null;
var handleTools = {};
- that.shutdown = function() {
- that.restoreAvatarCollisionsFromStretch();
- }
- Script.scriptEnding.connect(that.shutdown);
-
// We get mouseMoveEvents from the handControllers, via handControllerPointer.
// But we dont' get mousePressEvents.
that.triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click');
@@ -667,7 +673,13 @@ SelectionDisplay = (function() {
activeHand = (activeHand === Controller.Standard.RightHand) ?
Controller.Standard.LeftHand : Controller.Standard.RightHand;
}
- if (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position)) {
+ var pointingAtDesktopWindow = (hand === Controller.Standard.RightHand &&
+ SelectionManager.pointingAtDesktopWindowRight) ||
+ (hand === Controller.Standard.LeftHand &&
+ SelectionManager.pointingAtDesktopWindowLeft);
+ var pointingAtTablet = (hand === Controller.Standard.RightHand && SelectionManager.pointingAtTabletRight) ||
+ (hand === Controller.Standard.LeftHand && SelectionManager.pointingAtTabletLeft);
+ if (pointingAtDesktopWindow || pointingAtTablet) {
return;
}
that.mousePressEvent({});
@@ -1832,13 +1844,6 @@ SelectionDisplay = (function() {
};
};
- that.restoreAvatarCollisionsFromStretch = function() {
- if (handleStretchCollisionOverride) {
- Menu.setIsOptionChecked(AVATAR_COLLISIONS_OPTION, true);
- handleStretchCollisionOverride = false;
- }
- }
-
// TOOL DEFINITION: HANDLE STRETCH TOOL
function makeStretchTool(stretchMode, directionEnum, directionVec, pivot, offset, stretchPanel, scaleHandle) {
var directionFor3DStretch = directionVec;
@@ -2041,9 +2046,12 @@ SelectionDisplay = (function() {
if (scaleHandle != null) {
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE_SELECTED });
}
- if (Menu.isOptionChecked(AVATAR_COLLISIONS_OPTION)) {
- Menu.setIsOptionChecked(AVATAR_COLLISIONS_OPTION, false);
- handleStretchCollisionOverride = true;
+
+ var collisionToRemove = "myAvatar";
+ if (properties.collidesWith.indexOf(collisionToRemove) > -1) {
+ var newCollidesWith = properties.collidesWith.replace(collisionToRemove, "");
+ Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith});
+ that.replaceCollisionsAfterStretch = true;
}
};
@@ -2054,7 +2062,13 @@ SelectionDisplay = (function() {
if (scaleHandle != null) {
Overlays.editOverlay(scaleHandle, { color: COLOR_SCALE_CUBE });
}
- that.restoreAvatarCollisionsFromStretch();
+
+ if (that.replaceCollisionsAfterStretch) {
+ var newCollidesWith = SelectionManager.savedProperties[SelectionManager.selections[0]].collidesWith;
+ Entities.editEntity(SelectionManager.selections[0], {collidesWith: newCollidesWith});
+ that.replaceCollisionsAfterStretch = false;
+ }
+
pushCommandForSelections();
};
@@ -2140,12 +2154,10 @@ SelectionDisplay = (function() {
}
var newPosition = Vec3.sum(initialPosition, changeInPosition);
- for (var i = 0; i < SelectionManager.selections.length; i++) {
- Entities.editEntity(SelectionManager.selections[i], {
- position: newPosition,
- dimensions: newDimensions
- });
- }
+ Entities.editEntity(SelectionManager.selections[0], {
+ position: newPosition,
+ dimensions: newDimensions
+ });
var wantDebug = false;
if (wantDebug) {