diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 19a2d39a05..4ab741e32c 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3238,8 +3238,6 @@ bool MyAvatar::pinJoint(int index, const glm::vec3& position, const glm::quat& o slamPosition(position); setWorldOrientation(orientation); - _skeletonModel->getRig().setMaxHipsOffsetLength(0.05f); - auto it = std::find(_pinnedJoints.begin(), _pinnedJoints.end(), index); if (it == _pinnedJoints.end()) { _pinnedJoints.push_back(index); @@ -3259,12 +3257,6 @@ bool MyAvatar::clearPinOnJoint(int index) { auto it = std::find(_pinnedJoints.begin(), _pinnedJoints.end(), index); if (it != _pinnedJoints.end()) { _pinnedJoints.erase(it); - - auto hipsIndex = getJointIndex("Hips"); - if (index == hipsIndex) { - _skeletonModel->getRig().setMaxHipsOffsetLength(FLT_MAX); - } - return true; } return false; diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 9280899a1e..fd57657d33 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -43,8 +43,6 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) { AnimPose result = AnimPose(worldToSensorMat * avatarTransform.getMatrix() * Matrices::Y_180); result.scale() = glm::vec3(1.0f, 1.0f, 1.0f); return result; - } else { - DebugDraw::getInstance().removeMarker("pinnedHips"); } glm::mat4 hipsMat = myAvatar->deriveBodyFromHMDSensor(); diff --git a/interface/src/scripting/WalletScriptingInterface.cpp b/interface/src/scripting/WalletScriptingInterface.cpp index 71a7076bdf..e2158b9fd7 100644 --- a/interface/src/scripting/WalletScriptingInterface.cpp +++ b/interface/src/scripting/WalletScriptingInterface.cpp @@ -16,6 +16,7 @@ CheckoutProxy::CheckoutProxy(QObject* qmlObject, QObject* parent) : QmlWrapper(q } WalletScriptingInterface::WalletScriptingInterface() { + } void WalletScriptingInterface::refreshWalletStatus() { @@ -26,4 +27,19 @@ void WalletScriptingInterface::refreshWalletStatus() { void WalletScriptingInterface::setWalletStatus(const uint& status) { _walletStatus = status; emit DependencyManager::get()->walletStatusResult(status); +} + +void WalletScriptingInterface::proveAvatarEntityOwnershipVerification(const QUuid& entityID) { + QSharedPointer contextOverlayInterface = DependencyManager::get(); + EntityItemProperties entityProperties = DependencyManager::get()->getEntityProperties(entityID, + contextOverlayInterface->getEntityPropertyFlags()); + if (entityProperties.getClientOnly()) { + if (!entityID.isNull() && entityProperties.getCertificateID().length() > 0) { + contextOverlayInterface->requestOwnershipVerification(entityID); + } else { + qCDebug(entities) << "Failed to prove ownership of:" << entityID << "is null or not a certified item"; + } + } else { + qCDebug(entities) << "Failed to prove ownership of:" << entityID << "is not an avatar entity"; + } } \ No newline at end of file diff --git a/interface/src/scripting/WalletScriptingInterface.h b/interface/src/scripting/WalletScriptingInterface.h index 5469e732c7..9e40aad087 100644 --- a/interface/src/scripting/WalletScriptingInterface.h +++ b/interface/src/scripting/WalletScriptingInterface.h @@ -21,6 +21,7 @@ #include #include "Application.h" #include "commerce/Wallet.h" +#include "ui/overlays/ContextOverlayInterface.h" class CheckoutProxy : public QmlWrapper { Q_OBJECT @@ -39,6 +40,7 @@ public: Q_INVOKABLE void refreshWalletStatus(); Q_INVOKABLE uint getWalletStatus() { return _walletStatus; } + Q_INVOKABLE void proveAvatarEntityOwnershipVerification(const QUuid& entityID); // setWalletStatus() should never be made Q_INVOKABLE. If it were, // scripts could cause the Wallet to incorrectly report its status. void setWalletStatus(const uint& status); @@ -46,6 +48,8 @@ public: signals: void walletStatusChanged(); void walletNotSetup(); + void ownershipVerificationSuccess(const QUuid& entityID); + void ownershipVerificationFailed(const QUuid& entityID); private: uint _walletStatus; diff --git a/interface/src/ui/LogDialog.cpp b/interface/src/ui/LogDialog.cpp index 00dc9be959..108edbfd39 100644 --- a/interface/src/ui/LogDialog.cpp +++ b/interface/src/ui/LogDialog.cpp @@ -38,7 +38,7 @@ const QString FATAL_TEXT = "[FATAL]"; const QString SUPPRESS_TEXT = "[SUPPRESS]"; const QString UNKNOWN_TEXT = "[UNKNOWN]"; -LogDialog::LogDialog(QWidget* parent, AbstractLoggerInterface* logger) : BaseLogDialog(parent) { +LogDialog::LogDialog(QWidget* parent, AbstractLoggerInterface* logger) : BaseLogDialog(parent), _windowGeometry("logDialogGeometry", QRect()) { _logger = logger; setWindowTitle("Log"); @@ -155,6 +155,11 @@ LogDialog::LogDialog(QWidget* parent, AbstractLoggerInterface* logger) : BaseLog _clearFilterButton->show(); connect(_clearFilterButton, &QPushButton::clicked, this, &LogDialog::handleClearFilterButton); handleClearFilterButton(); + + auto windowGeometry = _windowGeometry.get(); + if (windowGeometry.isValid()) { + setGeometry(windowGeometry); + } } void LogDialog::resizeEvent(QResizeEvent* event) { @@ -173,6 +178,11 @@ void LogDialog::resizeEvent(QResizeEvent* event) { ELEMENT_HEIGHT); } +void LogDialog::closeEvent(QCloseEvent* event) { + BaseLogDialog::closeEvent(event); + _windowGeometry.set(geometry()); +} + void LogDialog::handleRevealButton() { _logger->locateLog(); } diff --git a/interface/src/ui/LogDialog.h b/interface/src/ui/LogDialog.h index 5e4e084d5a..3cc7584fe8 100644 --- a/interface/src/ui/LogDialog.h +++ b/interface/src/ui/LogDialog.h @@ -13,6 +13,7 @@ #define hifi_LogDialog_h #include "BaseLogDialog.h" +#include class QCheckBox; class QPushButton; @@ -44,6 +45,8 @@ private slots: protected: void resizeEvent(QResizeEvent* event) override; + void closeEvent(QCloseEvent* event) override; + QString getCurrentLog() override; void printLogFile(); @@ -62,6 +65,7 @@ private: QString _filterSelection; AbstractLoggerInterface* _logger; + Setting::Handle _windowGeometry; }; #endif // hifi_LogDialog_h diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index d4138941ae..ed7b811fb0 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -266,6 +266,93 @@ void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemI } } +void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID) { + + setLastInspectedEntity(entityID); + + EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_lastInspectedEntity, _entityPropertyFlags); + + auto nodeList = DependencyManager::get(); + + if (entityProperties.getClientOnly()) { + if (entityProperties.verifyStaticCertificateProperties()) { + SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); + + if (entityServer) { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest networkRequest; + networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL(); + requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer"); + QJsonObject request; + request["certificate_id"] = entityProperties.getCertificateID(); + networkRequest.setUrl(requestURL); + + QNetworkReply* networkReply = NULL; + networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson()); + + connect(networkReply, &QNetworkReply::finished, [=]() { + QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object(); + jsonObject = jsonObject["data"].toObject(); + + if (networkReply->error() == QNetworkReply::NoError) { + if (!jsonObject["invalid_reason"].toString().isEmpty()) { + qCDebug(entities) << "invalid_reason not empty"; + } else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") { + qCDebug(entities) << "'transfer_status' is 'failed'"; + } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") { + qCDebug(entities) << "'transfer_status' is 'pending'"; + } else { + QString ownerKey = jsonObject["transfer_recipient_key"].toString(); + + QByteArray certID = entityProperties.getCertificateID().toUtf8(); + QByteArray text = DependencyManager::get()->getTree()->computeNonce(certID, ownerKey); + QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122(); + + int certIDByteArraySize = certID.length(); + int textByteArraySize = text.length(); + int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length(); + + auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, + certIDByteArraySize + textByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int), + true); + challengeOwnershipPacket->writePrimitive(certIDByteArraySize); + challengeOwnershipPacket->writePrimitive(textByteArraySize); + challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize); + challengeOwnershipPacket->write(certID); + challengeOwnershipPacket->write(text); + challengeOwnershipPacket->write(nodeToChallengeByteArray); + nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); + + // Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time + if (thread() != QThread::currentThread()) { + QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer"); + return; + } else { + startChallengeOwnershipTimer(); + } + } + } else { + qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << + "More info:" << networkReply->readAll(); + } + + networkReply->deleteLater(); + }); + } else { + qCWarning(context_overlay) << "Couldn't get Entity Server!"; + } + } else { + auto ledger = DependencyManager::get(); + _challengeOwnershipTimeoutTimer.stop(); + emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED)); + emit DependencyManager::get()->ownershipVerificationFailed(_lastInspectedEntity); + qCDebug(context_overlay) << "Entity" << _lastInspectedEntity << "failed static certificate verification!"; + } + } +} + static const QString INSPECTION_CERTIFICATE_QML_PATH = "hifi/commerce/inspectionCertificate/InspectionCertificate.qml"; void ContextOverlayInterface::openInspectionCertificate() { // lets open the tablet to the inspection certificate QML @@ -275,87 +362,7 @@ void ContextOverlayInterface::openInspectionCertificate() { _hmdScriptingInterface->openTablet(); setLastInspectedEntity(_currentEntityWithContextOverlay); - - EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_lastInspectedEntity, _entityPropertyFlags); - - auto nodeList = DependencyManager::get(); - - if (entityProperties.getClientOnly()) { - if (entityProperties.verifyStaticCertificateProperties()) { - SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); - - if (entityServer) { - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkRequest networkRequest; - networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); - networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL(); - requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer"); - QJsonObject request; - request["certificate_id"] = entityProperties.getCertificateID(); - networkRequest.setUrl(requestURL); - - QNetworkReply* networkReply = NULL; - networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson()); - - connect(networkReply, &QNetworkReply::finished, [=]() { - QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object(); - jsonObject = jsonObject["data"].toObject(); - - if (networkReply->error() == QNetworkReply::NoError) { - if (!jsonObject["invalid_reason"].toString().isEmpty()) { - qCDebug(entities) << "invalid_reason not empty"; - } else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") { - qCDebug(entities) << "'transfer_status' is 'failed'"; - } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") { - qCDebug(entities) << "'transfer_status' is 'pending'"; - } else { - QString ownerKey = jsonObject["transfer_recipient_key"].toString(); - - QByteArray certID = entityProperties.getCertificateID().toUtf8(); - QByteArray text = DependencyManager::get()->getTree()->computeNonce(certID, ownerKey); - QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122(); - - int certIDByteArraySize = certID.length(); - int textByteArraySize = text.length(); - int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length(); - - auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, - certIDByteArraySize + textByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int), - true); - challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(textByteArraySize); - challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize); - challengeOwnershipPacket->write(certID); - challengeOwnershipPacket->write(text); - challengeOwnershipPacket->write(nodeToChallengeByteArray); - nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); - - // Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time - if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer"); - return; - } else { - startChallengeOwnershipTimer(); - } - } - } else { - qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << - "More info:" << networkReply->readAll(); - } - - networkReply->deleteLater(); - }); - } else { - qCWarning(context_overlay) << "Couldn't get Entity Server!"; - } - } else { - auto ledger = DependencyManager::get(); - _challengeOwnershipTimeoutTimer.stop(); - emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED)); - qCDebug(context_overlay) << "Entity" << _lastInspectedEntity << "failed static certificate verification!"; - } - } + requestOwnershipVerification(_lastInspectedEntity); } } @@ -397,6 +404,7 @@ void ContextOverlayInterface::startChallengeOwnershipTimer() { connect(&_challengeOwnershipTimeoutTimer, &QTimer::timeout, this, [=]() { qCDebug(entities) << "Ownership challenge timed out for" << _lastInspectedEntity; emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_TIMEOUT)); + emit DependencyManager::get()->ownershipVerificationFailed(_lastInspectedEntity); }); _challengeOwnershipTimeoutTimer.start(5000); @@ -421,7 +429,9 @@ void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer if (verificationSuccess) { emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_SUCCESS)); + emit DependencyManager::get()->ownershipVerificationSuccess(_lastInspectedEntity); } else { emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED)); + emit DependencyManager::get()->ownershipVerificationFailed(_lastInspectedEntity); } } diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index 990a7fe599..6aad2a773b 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -26,6 +26,7 @@ #include "ui/overlays/Overlays.h" #include "scripting/HMDScriptingInterface.h" #include "scripting/SelectionScriptingInterface.h" +#include "scripting/WalletScriptingInterface.h" #include "EntityTree.h" #include "ContextOverlayLogging.h" @@ -33,12 +34,13 @@ /**jsdoc * @namespace ContextOverlay */ -class ContextOverlayInterface : public QObject, public Dependency { +class ContextOverlayInterface : public QObject, public Dependency { Q_OBJECT Q_PROPERTY(QUuid entityWithContextOverlay READ getCurrentEntityWithContextOverlay WRITE setCurrentEntityWithContextOverlay) Q_PROPERTY(bool enabled READ getEnabled WRITE setEnabled) Q_PROPERTY(bool isInMarketplaceInspectionMode READ getIsInMarketplaceInspectionMode WRITE setIsInMarketplaceInspectionMode) + QSharedPointer _entityScriptingInterface; EntityPropertyFlags _entityPropertyFlags; QSharedPointer _hmdScriptingInterface; @@ -47,9 +49,7 @@ class ContextOverlayInterface : public QObject, public Dependency { OverlayID _contextOverlayID { UNKNOWN_OVERLAY_ID }; std::shared_ptr _contextOverlay { nullptr }; public: - ContextOverlayInterface(); - Q_INVOKABLE QUuid getCurrentEntityWithContextOverlay() { return _currentEntityWithContextOverlay; } void setCurrentEntityWithContextOverlay(const QUuid& entityID) { _currentEntityWithContextOverlay = entityID; } void setLastInspectedEntity(const QUuid& entityID) { _challengeOwnershipTimeoutTimer.stop(); _lastInspectedEntity = entityID; } @@ -57,6 +57,8 @@ public: bool getEnabled() { return _enabled; } bool getIsInMarketplaceInspectionMode() { return _isInMarketplaceInspectionMode; } void setIsInMarketplaceInspectionMode(bool mode) { _isInMarketplaceInspectionMode = mode; } + void requestOwnershipVerification(const QUuid& entityID); + EntityPropertyFlags getEntityPropertyFlags() { return _entityPropertyFlags; } signals: void contextOverlayClicked(const QUuid& currentEntityWithContextOverlay); @@ -80,8 +82,7 @@ private: enum { MAX_SELECTION_COUNT = 16 }; - - bool _verboseLogging { true }; + bool _verboseLogging{ true }; bool _enabled { true }; EntityItemID _currentEntityWithContextOverlay{}; EntityItemID _lastInspectedEntity{}; diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index e9f9f8818f..849ea5ee6b 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -880,25 +880,6 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar return _relativePoses; } -AnimPose AnimInverseKinematics::applyHipsOffset() const { - glm::vec3 hipsOffset = _hipsOffset; - AnimPose relHipsPose = _relativePoses[_hipsIndex]; - float offsetLength = glm::length(hipsOffset); - const float MIN_HIPS_OFFSET_LENGTH = 0.03f; - if (offsetLength > MIN_HIPS_OFFSET_LENGTH) { - float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength); - glm::vec3 scaledHipsOffset = scaleFactor * hipsOffset; - if (_hipsParentIndex == -1) { - relHipsPose.trans() = _relativePoses[_hipsIndex].trans() + scaledHipsOffset; - } else { - AnimPose absHipsPose = _skeleton->getAbsolutePose(_hipsIndex, _relativePoses); - absHipsPose.trans() += scaledHipsOffset; - relHipsPose = _skeleton->getAbsolutePose(_hipsParentIndex, _relativePoses).inverse() * absHipsPose; - } - } - return relHipsPose; -} - //virtual const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) { // allows solutionSource to be overridden by an animVar @@ -996,27 +977,6 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars _relativePoses[_hipsIndex] = parentAbsPose.inverse() * absPose; _relativePoses[_hipsIndex].scale() = glm::vec3(1.0f); - _hipsOffset = Vectors::ZERO; - - } else if (_hipsIndex >= 0) { - - // if there is no hips target, shift hips according to the _hipsOffset from the previous frame - AnimPose relHipsPose = applyHipsOffset(); - - // determine if we should begin interpolating the hips. - for (size_t i = 0; i < targets.size(); i++) { - if (_prevJointChainInfoVec[i].target.getIndex() == _hipsIndex) { - if (_prevJointChainInfoVec[i].timer > 0.0f) { - // smoothly lerp in hipsOffset - float alpha = (JOINT_CHAIN_INTERP_TIME - _prevJointChainInfoVec[i].timer) / JOINT_CHAIN_INTERP_TIME; - AnimPose prevRelHipsPose(_prevJointChainInfoVec[i].jointInfoVec[0].rot, _prevJointChainInfoVec[i].jointInfoVec[0].trans); - ::blend(1, &prevRelHipsPose, &relHipsPose, alpha, &relHipsPose); - } - break; - } - } - - _relativePoses[_hipsIndex] = relHipsPose; } // if there is an active jointChainInfo for the hips store the post shifted hips into it. @@ -1084,11 +1044,6 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars solve(context, targets, dt, jointChainInfoVec); } - - if (_hipsTargetIndex < 0) { - PROFILE_RANGE_EX(simulation_animation, "ik/measureHipsOffset", 0xffff00ff, 0); - _hipsOffset = computeHipsOffset(targets, underPoses, dt, _hipsOffset); - } } if (context.getEnableDebugDrawIKConstraints()) { @@ -1099,69 +1054,6 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars return _relativePoses; } -glm::vec3 AnimInverseKinematics::computeHipsOffset(const std::vector& targets, const AnimPoseVec& underPoses, float dt, glm::vec3 prevHipsOffset) const { - - // measure new _hipsOffset for next frame - // by looking for discrepancies between where a targeted endEffector is - // and where it wants to be (after IK solutions are done) - glm::vec3 hipsOffset = prevHipsOffset; - glm::vec3 newHipsOffset = Vectors::ZERO; - for (auto& target: targets) { - int targetIndex = target.getIndex(); - if (targetIndex == _headIndex && _headIndex != -1) { - // special handling for headTarget - if (target.getType() == IKTarget::Type::RotationOnly) { - // we want to shift the hips to bring the underPose closer - // to where the head happens to be (overpose) - glm::vec3 under = _skeleton->getAbsolutePose(_headIndex, underPoses).trans(); - glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans(); - const float HEAD_OFFSET_SLAVE_FACTOR = 0.65f; - newHipsOffset += HEAD_OFFSET_SLAVE_FACTOR * (actual - under); - } else if (target.getType() == IKTarget::Type::HmdHead) { - // we want to shift the hips to bring the head to its designated position - glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans(); - hipsOffset += target.getTranslation() - actual; - // and ignore all other targets - newHipsOffset = hipsOffset; - break; - } else if (target.getType() == IKTarget::Type::RotationAndPosition) { - glm::vec3 actualPosition = _skeleton->getAbsolutePose(targetIndex, _relativePoses).trans(); - glm::vec3 targetPosition = target.getTranslation(); - newHipsOffset += targetPosition - actualPosition; - - // Add downward pressure on the hips - const float PRESSURE_SCALE_FACTOR = 0.95f; - const float PRESSURE_TRANSLATION_OFFSET = 1.0f; - newHipsOffset *= PRESSURE_SCALE_FACTOR; - newHipsOffset -= PRESSURE_TRANSLATION_OFFSET; - } - } else if (target.getType() == IKTarget::Type::RotationAndPosition) { - glm::vec3 actualPosition = _skeleton->getAbsolutePose(targetIndex, _relativePoses).trans(); - glm::vec3 targetPosition = target.getTranslation(); - newHipsOffset += targetPosition - actualPosition; - } - } - - // smooth transitions by relaxing hipsOffset toward the new value - const float HIPS_OFFSET_SLAVE_TIMESCALE = 0.10f; - float tau = dt < HIPS_OFFSET_SLAVE_TIMESCALE ? dt / HIPS_OFFSET_SLAVE_TIMESCALE : 1.0f; - hipsOffset += (newHipsOffset - hipsOffset) * tau; - - // clamp the hips offset - float hipsOffsetLength = glm::length(hipsOffset); - if (hipsOffsetLength > _maxHipsOffsetLength) { - hipsOffset *= _maxHipsOffsetLength / hipsOffsetLength; - } - - return hipsOffset; -} - -void AnimInverseKinematics::setMaxHipsOffsetLength(float maxLength) { - // manually adjust scale here - const float METERS_TO_CENTIMETERS = 100.0f; - _maxHipsOffsetLength = METERS_TO_CENTIMETERS * maxLength; -} - void AnimInverseKinematics::clearIKJointLimitHistory() { for (auto& pair : _constraints) { pair.second->clearHistory(); diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index bdfbad408d..ee1f9f43ad 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -57,8 +57,6 @@ public: void clearIKJointLimitHistory(); - void setMaxHipsOffsetLength(float maxLength); - float getMaxErrorOnLastSolve() { return _maxErrorOnLastSolve; } enum class SolutionSource { @@ -92,7 +90,6 @@ protected: void blendToPoses(const AnimPoseVec& targetPoses, const AnimPoseVec& underPose, float blendFactor); void preconditionRelativePosesToAvoidLimbLock(const AnimContext& context, const std::vector& targets); void setSecondaryTargets(const AnimContext& context); - AnimPose applyHipsOffset() const; // used to pre-compute information about each joint influeced by a spline IK target. struct SplineJointInfo { @@ -111,7 +108,6 @@ protected: void clearConstraints(); void initConstraints(); void initLimitCenterPoses(); - glm::vec3 computeHipsOffset(const std::vector& targets, const AnimPoseVec& underPoses, float dt, glm::vec3 prevHipsOffset) const; // no copies AnimInverseKinematics(const AnimInverseKinematics&) = delete; @@ -150,9 +146,6 @@ protected: mutable std::map> _splineJointInfoMap; - // experimental data for moving hips during IK - glm::vec3 _hipsOffset { Vectors::ZERO }; - float _maxHipsOffsetLength{ FLT_MAX }; int _headIndex { -1 }; int _hipsIndex { -1 }; int _hipsParentIndex { -1 }; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 309bb59cff..a939db92aa 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -372,18 +372,6 @@ void Rig::clearIKJointLimitHistory() { } } -void Rig::setMaxHipsOffsetLength(float maxLength) { - _maxHipsOffsetLength = maxLength; - auto ikNode = getAnimInverseKinematicsNode(); - if (ikNode) { - ikNode->setMaxHipsOffsetLength(_maxHipsOffsetLength); - } -} - -float Rig::getMaxHipsOffsetLength() const { - return _maxHipsOffsetLength; -} - float Rig::getIKErrorOnLastSolve() const { float result = 0.0f; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 87277af754..a7db86abf9 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -346,7 +346,6 @@ protected: bool _enabledAnimations { true }; mutable uint32_t _jointNameWarningCount { 0 }; - float _maxHipsOffsetLength { 1.0f }; bool _enableDebugDrawIKTargets { false }; bool _enableDebugDrawIKConstraints { false }; diff --git a/libraries/entities/src/EntityScriptServerLogClient.cpp b/libraries/entities/src/EntityScriptServerLogClient.cpp index 4405af5b1b..5853c9585e 100644 --- a/libraries/entities/src/EntityScriptServerLogClient.cpp +++ b/libraries/entities/src/EntityScriptServerLogClient.cpp @@ -51,9 +51,9 @@ void EntityScriptServerLogClient::enableToEntityServerScriptLog(bool enable) { if (_subscribed != enable) { if (enable) { - emit receivedNewLogLines("====================== Subscribded to the Entity Script Server's log ======================"); + emit receivedNewLogLines("====================== Subscribed to the Entity Script Server's log ======================"); } else { - emit receivedNewLogLines("==================== Unsubscribded from the Entity Script Server's log ===================="); + emit receivedNewLogLines("==================== Unsubscribed from the Entity Script Server's log ===================="); } } _subscribed = enable; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 14462e0558..4ed1ca38dc 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1455,18 +1455,22 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS QSet remainingModels; for (QHash::const_iterator model = models.constBegin(); model != models.constEnd(); model++) { // models with clusters must be parented to the cluster top - foreach (const QString& deformerID, _connectionChildMap.values(model.key())) { - foreach (const QString& clusterID, _connectionChildMap.values(deformerID)) { - if (!clusters.contains(clusterID)) { - continue; + // Unless the model is a root node. + bool isARootNode = !modelIDs.contains(_connectionParentMap.value(model.key())); + if (!isARootNode) { + foreach(const QString& deformerID, _connectionChildMap.values(model.key())) { + foreach(const QString& clusterID, _connectionChildMap.values(deformerID)) { + if (!clusters.contains(clusterID)) { + continue; + } + QString topID = getTopModelID(_connectionParentMap, models, _connectionChildMap.value(clusterID), url); + _connectionChildMap.remove(_connectionParentMap.take(model.key()), model.key()); + _connectionParentMap.insert(model.key(), topID); + goto outerBreak; } - QString topID = getTopModelID(_connectionParentMap, models, _connectionChildMap.value(clusterID), url); - _connectionChildMap.remove(_connectionParentMap.take(model.key()), model.key()); - _connectionParentMap.insert(model.key(), topID); - goto outerBreak; } + outerBreak: ; } - outerBreak: // make sure the parent is in the child map QString parent = _connectionParentMap.value(model.key()); @@ -1477,11 +1481,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } while (!remainingModels.isEmpty()) { QString first = *remainingModels.constBegin(); - foreach (const QString& id, remainingModels) { - if (id < first) { - first = id; - } - } QString topID = getTopModelID(_connectionParentMap, models, first, url); appendModelIDs(_connectionParentMap.value(topID), _connectionChildMap, models, remainingModels, modelIDs, true); } diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 0f69691bd5..d186ed41c3 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -248,7 +248,8 @@ enum class AvatarMixerPacketVersion : PacketVersion { IsReplicatedInAvatarIdentity, AvatarIdentityLookAtSnapping, UpdatedMannequinDefaultAvatar, - AvatarJointDefaultPoseFlags + AvatarJointDefaultPoseFlags, + FBXReaderNodeReparenting }; enum class DomainConnectRequestVersion : PacketVersion { diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 0b8c636678..efca0c3267 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -238,9 +238,9 @@ void CauterizedModel::updateRenderItems() { renderTransform = modelTransform; if (clusterTransformsCauterized.size() == 1) { #if defined(SKIN_DQ) - Transform transform(clusterTransforms[0].getRotation(), - clusterTransforms[0].getScale(), - clusterTransforms[0].getTranslation()); + Transform transform(clusterTransformsCauterized[0].getRotation(), + clusterTransformsCauterized[0].getScale(), + clusterTransformsCauterized[0].getTranslation()); renderTransform = modelTransform.worldTransform(Transform(transform)); #else renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0])); diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 1209d39dcf..0825d238bc 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -227,7 +227,7 @@ bool QmlWindowClass::isVisible() { glm::vec2 QmlWindowClass::getPosition() { if (QThread::currentThread() != thread()) { vec2 result; - BLOCKING_INVOKE_METHOD(this, "getPosition", Q_RETURN_ARG(vec2, result)); + BLOCKING_INVOKE_METHOD(this, "getPosition", Q_RETURN_ARG(glm::vec2, result)); return result; } @@ -241,7 +241,7 @@ glm::vec2 QmlWindowClass::getPosition() { void QmlWindowClass::setPosition(const glm::vec2& position) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setPosition", Q_ARG(vec2, position)); + QMetaObject::invokeMethod(this, "setPosition", Q_ARG(const glm::vec2&, position)); return; } @@ -262,7 +262,7 @@ glm::vec2 toGlm(const QSizeF& size) { glm::vec2 QmlWindowClass::getSize() { if (QThread::currentThread() != thread()) { vec2 result; - BLOCKING_INVOKE_METHOD(this, "getSize", Q_RETURN_ARG(vec2, result)); + BLOCKING_INVOKE_METHOD(this, "getSize", Q_RETURN_ARG(glm::vec2, result)); return result; } @@ -275,7 +275,7 @@ glm::vec2 QmlWindowClass::getSize() { void QmlWindowClass::setSize(const glm::vec2& size) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setSize", Q_ARG(vec2, size)); + QMetaObject::invokeMethod(this, "setSize", Q_ARG(const glm::vec2&, size)); return; } diff --git a/scripts/developer/debugging/debugWindow.js b/scripts/developer/debugging/debugWindow.js index 068efb351b..9522676007 100644 --- a/scripts/developer/debugging/debugWindow.js +++ b/scripts/developer/debugging/debugWindow.js @@ -22,14 +22,37 @@ if (scripts.length >= 2) { // Set up the qml ui var qml = Script.resolvePath('debugWindow.qml'); +var HMD_DEBUG_WINDOW_GEOMETRY_KEY = 'hmdDebugWindowGeometry'; +var hmdDebugWindowGeometryValue = Settings.getValue(HMD_DEBUG_WINDOW_GEOMETRY_KEY) + +var windowWidth = 400; +var windowHeight = 900; + +var hasPosition = false; +var windowX = 0; +var windowY = 0; + +if (hmdDebugWindowGeometryValue !== '') { + var geometry = JSON.parse(hmdDebugWindowGeometryValue); + + windowWidth = geometry.width + windowHeight = geometry.height + windowX = geometry.x + windowY = geometry.y + hasPosition = true; +} + var window = new OverlayWindow({ title: 'Debug Window', source: qml, - width: 400, height: 900, + width: windowWidth, height: windowHeight, }); -window.setPosition(25, 50); -window.closed.connect(function() { Script.stop(); }); +if (hasPosition) { + window.setPosition(windowX, windowY); +} + +window.closed.connect(function () { Script.stop(); }); var getFormattedDate = function() { var date = new Date(); @@ -65,6 +88,14 @@ ScriptDiscoveryService.clearDebugWindow.connect(function() { }); Script.scriptEnding.connect(function () { + var geometry = JSON.stringify({ + x: window.position.x, + y: window.position.y, + width: window.size.x, + height: window.size.y + }) + + Settings.setValue(HMD_DEBUG_WINDOW_GEOMETRY_KEY, geometry); window.close(); }) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index a250f77b2e..252f6efa9e 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -10,7 +10,7 @@ getControllerJointIndex, enableDispatcherModule, disableDispatcherModule, Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions, Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic, entityIsCloneable, - cloneEntity, DISPATCHER_PROPERTIES, TEAR_AWAY_DISTANCE + cloneEntity, DISPATCHER_PROPERTIES, TEAR_AWAY_DISTANCE, Uuid */ Script.include("/~/system/libraries/Xform.js"); @@ -269,6 +269,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.grabEntityProps = null; this.shouldSendStart = false; this.equipedWithSecondary = false; + this.handHasBeenRightsideUp = false; this.parameters = makeDispatcherModuleParameters( 300, @@ -486,15 +487,17 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var grabbedProperties = Entities.getEntityProperties(this.targetEntityID); // if an object is "equipped" and has a predefined offset, use it. - var offsets = getAttachPointForHotspotFromSettings(this.grabbedHotspot, this.hand); - if (offsets) { - this.offsetPosition = offsets[0]; - this.offsetRotation = offsets[1]; - } else { - var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; - if (this.grabbedHotspot.joints[handJointName]) { - this.offsetPosition = this.grabbedHotspot.joints[handJointName][0]; - this.offsetRotation = this.grabbedHotspot.joints[handJointName][1]; + if (this.grabbedHotspot) { + var offsets = getAttachPointForHotspotFromSettings(this.grabbedHotspot, this.hand); + if (offsets) { + this.offsetPosition = offsets[0]; + this.offsetRotation = offsets[1]; + } else { + var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; + if (this.grabbedHotspot.joints[handJointName]) { + this.offsetPosition = this.grabbedHotspot.joints[handJointName][0]; + this.offsetRotation = this.grabbedHotspot.joints[handJointName][1]; + } } } @@ -549,7 +552,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa // 100 ms seems to be sufficient time to force the check even occur after the object has been initialized. Script.setTimeout(grabEquipCheck, 100); } - }; this.endEquipEntity = function () { @@ -624,7 +626,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.grabbedHotspot = potentialEquipHotspot; this.targetEntityID = this.grabbedHotspot.entityID; this.startEquipEntity(controllerData); - this.messageGrabEnity = false; + this.messageGrabEntity = false; this.equipedWithSecondary = this.secondarySmoothedSqueezed(); return makeRunningValues(true, [potentialEquipHotspot.entityID], []); } else { @@ -640,6 +642,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.isReady = function (controllerData, deltaTime) { var timestamp = Date.now(); this.updateInputs(controllerData); + this.handHasBeenRightsideUp = false; return this.checkNearbyHotspots(controllerData, deltaTime, timestamp); }; @@ -671,7 +674,14 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa return makeRunningValues(false, [], []); } - var dropDetected = this.dropGestureProcess(deltaTime); + var handIsUpsideDown = this.dropGestureProcess(deltaTime); + var dropDetected = false; + if (this.handHasBeenRightsideUp) { + dropDetected = handIsUpsideDown; + } + if (!handIsUpsideDown) { + this.handHasBeenRightsideUp = true; + } if (this.triggerSmoothedReleased() || this.secondaryReleased()) { if (this.shouldSendStart) { @@ -692,7 +702,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa } // highlight the grabbed hotspot when the dropGesture is detected. - if (dropDetected) { + if (dropDetected && this.grabbedHotspot) { equipHotspotBuddy.updateHotspot(this.grabbedHotspot, timestamp); equipHotspotBuddy.highlightHotspot(this.grabbedHotspot); } diff --git a/scripts/system/html/css/colpick.css b/scripts/system/html/css/colpick.css index 564f60cb3b..98417a5e9a 100644 --- a/scripts/system/html/css/colpick.css +++ b/scripts/system/html/css/colpick.css @@ -26,6 +26,7 @@ colpick Color Picker / colpick.com /*Color selection box with gradients*/ .colpick_color { position: absolute; + touch-action: none; left: 7px; top: 7px; width: 156px; @@ -84,6 +85,7 @@ colpick Color Picker / colpick.com /*Vertical hue bar*/ .colpick_hue { position: absolute; + touch-action: none; top: 6px; left: 175px; width: 19px; @@ -94,6 +96,7 @@ colpick Color Picker / colpick.com /*Hue bar sliding indicator*/ .colpick_hue_arrs { position: absolute; + touch-action: none; left: -8px; width: 35px; height: 7px; @@ -101,6 +104,7 @@ colpick Color Picker / colpick.com } .colpick_hue_larr { position:absolute; + touch-action: none; width: 0; height: 0; border-top: 6px solid transparent; @@ -109,6 +113,7 @@ colpick Color Picker / colpick.com } .colpick_hue_rarr { position:absolute; + touch-action: none; right:0; width: 0; height: 0; @@ -119,6 +124,7 @@ colpick Color Picker / colpick.com /*New color box*/ .colpick_new_color { position: absolute; + touch-action: none; left: 207px; top: 6px; width: 60px; @@ -129,6 +135,7 @@ colpick Color Picker / colpick.com /*Current color box*/ .colpick_current_color { position: absolute; + touch-action: none; left: 277px; top: 6px; width: 60px; @@ -139,6 +146,7 @@ colpick Color Picker / colpick.com /*Input field containers*/ .colpick_field, .colpick_hex_field { position: absolute; + touch-action: none; height: 20px; width: 60px; overflow:hidden; @@ -198,6 +206,7 @@ colpick Color Picker / colpick.com /*Text inputs*/ .colpick_field input, .colpick_hex_field input { position: absolute; + touch-action: none; right: 11px; margin: 0; padding: 0; @@ -217,6 +226,7 @@ colpick Color Picker / colpick.com /*Field up/down arrows*/ .colpick_field_arrs { position: absolute; + touch-action: none; top: 0; right: 0; width: 9px; @@ -225,6 +235,7 @@ colpick Color Picker / colpick.com } .colpick_field_uarr { position: absolute; + touch-action: none; top: 5px; width: 0; height: 0; @@ -234,6 +245,7 @@ colpick Color Picker / colpick.com } .colpick_field_darr { position: absolute; + touch-action: none; bottom:5px; width: 0; height: 0; @@ -244,6 +256,7 @@ colpick Color Picker / colpick.com /*Submit/Select button*/ .colpick_submit { position: absolute; + touch-action: none; left: 207px; top: 149px; width: 130px; diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 72092b66ca..7008d0df66 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -653,16 +653,16 @@ function loaded() { var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y"); // Skybox - var elZoneSkyboxModeInherit = document.getElementById("property-zone-skybox-mode-inherit"); + var elZoneSkyboxModeInherit = document.getElementById("property-zone-skybox-mode-inherit"); var elZoneSkyboxModeDisabled = document.getElementById("property-zone-skybox-mode-disabled"); - var elZoneSkyboxModeEnabled = document.getElementById("property-zone-skybox-mode-enabled"); + var elZoneSkyboxModeEnabled = document.getElementById("property-zone-skybox-mode-enabled"); // Ambient light var elCopySkyboxURLToAmbientURL = document.getElementById("copy-skybox-url-to-ambient-url"); - var elZoneAmbientLightModeInherit = document.getElementById("property-zone-ambient-light-mode-inherit"); + var elZoneAmbientLightModeInherit = document.getElementById("property-zone-ambient-light-mode-inherit"); var elZoneAmbientLightModeDisabled = document.getElementById("property-zone-ambient-light-mode-disabled"); - var elZoneAmbientLightModeEnabled = document.getElementById("property-zone-ambient-light-mode-enabled"); + var elZoneAmbientLightModeEnabled = document.getElementById("property-zone-ambient-light-mode-enabled"); var elZoneAmbientLightIntensity = document.getElementById("property-zone-key-ambient-intensity"); var elZoneAmbientLightURL = document.getElementById("property-zone-key-ambient-url"); @@ -1013,9 +1013,9 @@ function loaded() { } else if (properties.type === "Zone") { // Key light - elZoneKeyLightModeInherit.checked = (properties.keyLightMode === 'inherit'); + elZoneKeyLightModeInherit.checked = (properties.keyLightMode === 'inherit'); elZoneKeyLightModeDisabled.checked = (properties.keyLightMode === 'disabled'); - elZoneKeyLightModeEnabled.checked = (properties.keyLightMode === 'enabled'); + elZoneKeyLightModeEnabled.checked = (properties.keyLightMode === 'enabled'); elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")"; @@ -1027,22 +1027,22 @@ function loaded() { elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2); // Skybox - elZoneSkyboxModeInherit.checked = (properties.skyboxMode === 'inherit'); + elZoneSkyboxModeInherit.checked = (properties.skyboxMode === 'inherit'); elZoneSkyboxModeDisabled.checked = (properties.skyboxMode === 'disabled'); - elZoneSkyboxModeEnabled.checked = (properties.skyboxMode === 'enabled'); + elZoneSkyboxModeEnabled.checked = (properties.skyboxMode === 'enabled'); // Ambient light - elZoneAmbientLightModeInherit.checked = (properties.ambientLightMode === 'inherit'); + elZoneAmbientLightModeInherit.checked = (properties.ambientLightMode === 'inherit'); elZoneAmbientLightModeDisabled.checked = (properties.ambientLightMode === 'disabled'); - elZoneAmbientLightModeEnabled.checked = (properties.ambientLightMode === 'enabled'); + elZoneAmbientLightModeEnabled.checked = (properties.ambientLightMode === 'enabled'); elZoneAmbientLightIntensity.value = properties.ambientLight.ambientIntensity.toFixed(2); elZoneAmbientLightURL.value = properties.ambientLight.ambientURL; // Haze - elZoneHazeModeInherit.checked = (properties.hazeMode === 'inherit'); + elZoneHazeModeInherit.checked = (properties.hazeMode === 'inherit'); elZoneHazeModeDisabled.checked = (properties.hazeMode === 'disabled'); - elZoneHazeModeEnabled.checked = (properties.hazeMode === 'enabled'); + elZoneHazeModeEnabled.checked = (properties.hazeMode === 'enabled'); elZoneHazeRange.value = properties.haze.hazeRange.toFixed(0); elZoneHazeColor.style.backgroundColor = "rgb(" + @@ -1308,15 +1308,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', + submit: false, // We don't want to have a submission button onShow: function(colpick) { $('#property-color-control2').attr('active', 'true'); }, onHide: function(colpick) { $('#property-color-control2').attr('active', 'false'); }, - onSubmit: function(hsb, hex, rgb, el) { + onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); - $(el).colpickHide(); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); } })); @@ -1332,15 +1332,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', + submit: false, // We don't want to have a submission button onShow: function(colpick) { $('#property-light-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-light-color').attr('active', 'false'); }, - onSubmit: function(hsb, hex, rgb, el) { + onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); - $(el).colpickHide(); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); } })); @@ -1387,15 +1387,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', + submit: false, // We don't want to have a submission button onShow: function(colpick) { $('#property-text-text-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-text-text-color').attr('active', 'false'); }, - onSubmit: function(hsb, hex, rgb, el) { + onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); - $(el).colpickHide(); $(el).attr('active', 'false'); emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b); } @@ -1411,15 +1411,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', + submit: false, // We don't want to have a submission button onShow: function(colpick) { $('#property-text-background-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-text-background-color').attr('active', 'false'); }, - onSubmit: function(hsb, hex, rgb, el) { + onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); - $(el).colpickHide(); emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b); } })); @@ -1436,15 +1436,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', + submit: false, // We don't want to have a submission button onShow: function(colpick) { $('#property-zone-key-light-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-key-light-color').attr('active', 'false'); }, - onSubmit: function(hsb, hex, rgb, el) { + onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); - $(el).colpickHide(); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'keyLight'); } })); @@ -1505,15 +1505,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', + submit: false, // We don't want to have a submission button onShow: function(colpick) { $('#property-zone-haze-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-haze-color').attr('active', 'false'); }, - onSubmit: function(hsb, hex, rgb, el) { + onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); - $(el).colpickHide(); emitColorPropertyUpdate('hazeColor', rgb.r, rgb.g, rgb.b, 'haze'); } })); @@ -1530,15 +1530,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', + submit: false, // We don't want to have a submission button onShow: function(colpick) { $('#property-zone-haze-glare-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-haze-glare-color').attr('active', 'false'); }, - onSubmit: function(hsb, hex, rgb, el) { + onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); - $(el).colpickHide(); emitColorPropertyUpdate('hazeGlareColor', rgb.r, rgb.g, rgb.b, 'haze'); } })); @@ -1572,15 +1572,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', + submit: false, // We don't want to have a submission button onShow: function(colpick) { $('#property-zone-skybox-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-skybox-color').attr('active', 'false'); }, - onSubmit: function(hsb, hex, rgb, el) { + onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); - $(el).colpickHide(); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox'); } })); diff --git a/scripts/system/run.js b/scripts/system/run.js index c34271b18d..8d1fb62619 100644 --- a/scripts/system/run.js +++ b/scripts/system/run.js @@ -35,4 +35,5 @@ button.editProperties({isActive: true}); } + Script.scriptEnding.connect(cleanup); }()); diff --git a/scripts/tutorials/createTetherballStick.js b/scripts/tutorials/createTetherballStick.js index 35f5fb0344..1b5bc36932 100644 --- a/scripts/tutorials/createTetherballStick.js +++ b/scripts/tutorials/createTetherballStick.js @@ -23,7 +23,7 @@ var BALL_DENSITY = 1000; var ACTION_DISTANCE = 0.35; var ACTION_TIMESCALE = 0.035; var MAX_DISTANCE_MULTIPLIER = 4; -var STICK_SCRIPT_URL = Script.resolvePath("./entity_scripts/tetherballStick.js?v=" + Date.now()); +var STICK_SCRIPT_URL = Script.resolvePath("./entity_scripts/tetherballStick.js"); var STICK_MODEL_URL = "http://hifi-content.s3.amazonaws.com/caitlyn/production/raveStick/newRaveStick2.fbx"; var COLLISION_SOUND_URL = "http://public.highfidelity.io/sounds/Footsteps/FootstepW3Left-12db.wav";