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) {