From 7cab0363a929fb86e7f13b9f552488d1acb856c4 Mon Sep 17 00:00:00 2001 From: humbletim Date: Mon, 5 Jun 2017 15:13:56 -0400 Subject: [PATCH 1/9] standalone 21180 branch with just the C++ changes --- interface/resources/images/cursor-none.png | Bin 0 -> 133 bytes interface/src/Application.cpp | 38 ++++++++++-------- interface/src/Application.h | 5 ++- interface/src/Menu.cpp | 5 +++ interface/src/Menu.h | 1 + interface/src/avatar/MyAvatar.cpp | 30 +++++++++++--- interface/src/avatar/MyAvatar.h | 5 +++ .../src/avatars-renderer/Avatar.cpp | 4 +- libraries/avatars/src/AvatarData.cpp | 34 +++++++++++----- libraries/avatars/src/AvatarData.h | 7 ++++ libraries/avatars/src/ScriptAvatarData.cpp | 8 ++++ libraries/avatars/src/ScriptAvatarData.h | 3 ++ .../src/display-plugins/CompositorHelper.cpp | 12 +++++- .../src/display-plugins/CompositorHelper.h | 4 ++ libraries/ui/src/CursorManager.cpp | 1 + libraries/ui/src/CursorManager.h | 1 + 16 files changed, 123 insertions(+), 35 deletions(-) create mode 100644 interface/resources/images/cursor-none.png diff --git a/interface/resources/images/cursor-none.png b/interface/resources/images/cursor-none.png new file mode 100644 index 0000000000000000000000000000000000000000..0b3f499242563a99230b69da0b8483ed8305f9e5 GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Rm@;DWu&Co?cG za29w(7BeuosDLn|L;8^r1_lQ95>H=O_J^$8Le|V%OcrM`Ffa&tx;TbdoK8-VU|pOb e(!<2Tz`!EFz}RZPs)&Jsfx*+&&t;ucLK6Uz(jKb- literal 0 HcmV?d00001 diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5e3e09e778..ed9b76d070 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -882,14 +882,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _glWidget->setFocusPolicy(Qt::StrongFocus); _glWidget->setFocus(); -#ifdef Q_OS_MAC - auto cursorTarget = _window; // OSX doesn't seem to provide for hiding the cursor only on the GL widget -#else - // On windows and linux, hiding the top level cursor also means it's invisible when hovering over the - // window menu, which is a pain, so only hide it for the GL surface - auto cursorTarget = _glWidget; -#endif - cursorTarget->setCursor(Qt::BlankCursor); + bool useSystemCursor = cmdOptionExists(argc, constArgv, "--system-cursor"); + showCursor(useSystemCursor ? Cursor::Icon::SYSTEM : Cursor::Icon::DEFAULT); // enable mouse tracking; otherwise, we only get drag events _glWidget->setMouseTracking(true); @@ -1547,9 +1541,16 @@ void Application::checkChangeCursor() { } } -void Application::showCursor(const QCursor& cursor) { +void Application::showCursor(const Cursor::Icon& cursor) { QMutexLocker locker(&_changeCursorLock); - _desiredCursor = cursor; + + auto managedCursor = Cursor::Manager::instance().getCursor(); + auto curIcon = managedCursor->getIcon(); + if (curIcon != cursor) { + managedCursor->setIcon(cursor); + curIcon = cursor; + } + _desiredCursor = cursor == Cursor::Icon::SYSTEM ? Qt::ArrowCursor : Qt::BlankCursor; _cursorNeedsChanging = true; } @@ -1958,9 +1959,9 @@ void Application::initializeUi() { _window->setMenuBar(new Menu()); auto compositorHelper = DependencyManager::get(); - connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, [=] { + connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, this, [=] { if (isHMDMode()) { - showCursor(compositorHelper->getAllowMouseCapture() ? Qt::BlankCursor : Qt::ArrowCursor); + showCursor(compositorHelper->getAllowMouseCapture() ? Cursor::Icon::DEFAULT : Cursor::Icon::SYSTEM); } }); @@ -2784,9 +2785,11 @@ void Application::keyPressEvent(QKeyEvent* event) { auto cursor = Cursor::Manager::instance().getCursor(); auto curIcon = cursor->getIcon(); if (curIcon == Cursor::Icon::DEFAULT) { - cursor->setIcon(Cursor::Icon::LINK); + showCursor(Cursor::Icon::SYSTEM); + } else if (curIcon == Cursor::Icon::SYSTEM) { + showCursor(Cursor::Icon::LINK); } else { - cursor->setIcon(Cursor::Icon::DEFAULT); + showCursor(Cursor::Icon::DEFAULT); } } else { resetSensors(true); @@ -3958,10 +3961,13 @@ void Application::updateMyAvatarLookAtPosition() { } } else { AvatarSharedPointer lookingAt = myAvatar->getLookAtTargetAvatar().lock(); - if (lookingAt && myAvatar.get() != lookingAt.get()) { + bool haveLookAtCandidate = lookingAt && myAvatar.get() != lookingAt.get(); + auto avatar = static_pointer_cast(lookingAt); + bool mutualLookAtSnappingEnabled = avatar && avatar->getLookAtSnappingEnabled() && myAvatar->getLookAtSnappingEnabled(); + if (haveLookAtCandidate && mutualLookAtSnappingEnabled) { // If I am looking at someone else, look directly at one of their eyes isLookingAtSomeone = true; - auto lookingAtHead = static_pointer_cast(lookingAt)->getHead(); + auto lookingAtHead = avatar->getHead(); const float MAXIMUM_FACE_ANGLE = 65.0f * RADIANS_PER_DEGREE; glm::vec3 lookingAtFaceOrientation = lookingAtHead->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD; diff --git a/interface/src/Application.h b/interface/src/Application.h index e8507c39e8..2d2278c904 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -54,6 +54,7 @@ #include "BandwidthRecorder.h" #include "FancyCamera.h" #include "ConnectionMonitor.h" +#include "CursorManager.h" #include "gpu/Context.h" #include "Menu.h" #include "octree/OctreePacketProcessor.h" @@ -163,7 +164,7 @@ public: QSize getDeviceSize() const; bool hasFocus() const; - void showCursor(const QCursor& cursor); + void showCursor(const Cursor::Icon& cursor); bool isThrottleRendering() const; @@ -639,7 +640,7 @@ private: void checkChangeCursor(); mutable QMutex _changeCursorLock { QMutex::Recursive }; - QCursor _desiredCursor{ Qt::BlankCursor }; + Qt::CursorShape _desiredCursor{ Qt::BlankCursor }; bool _cursorNeedsChanging { false }; QThread* _deadlockWatchdogThread; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 4138798484..98560acd57 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -504,6 +504,11 @@ Menu::Menu() { action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowOtherLookAtVectors, 0, false); connect(action, &QAction::triggered, [this]{ Avatar::setShowOtherLookAtVectors(isOptionChecked(MenuOption::ShowOtherLookAtVectors)); }); + action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableLookAtSnapping, 0, true); + connect(action, &QAction::triggered, [this, avatar]{ + avatar->setProperty("lookAtSnappingEnabled", isOptionChecked(MenuOption::EnableLookAtSnapping)); + }); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::FixGaze, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawDefaultPose, 0, false, avatar.get(), SLOT(setEnableDebugDrawDefaultPose(bool))); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b6d72f5446..676340a894 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -177,6 +177,7 @@ namespace MenuOption { const QString ShowDSConnectTable = "Show Domain Connection Timing"; const QString ShowMyLookAtVectors = "Show My Eye Vectors"; const QString ShowOtherLookAtVectors = "Show Other Eye Vectors"; + const QString EnableLookAtSnapping = "Enable LookAt Snapping"; const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats"; const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; const QString SimulateEyeTracking = "Simulate"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9996df2afc..7b5fefb2d0 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -834,6 +834,9 @@ void MyAvatar::saveData() { settings.setValue("scale", _targetScale); + settings.setValue("yawSpeed", _yawSpeed); + settings.setValue("pitchSpeed", _pitchSpeed); + settings.setValue("fullAvatarURL", _fullAvatarURLFromPreferences == AvatarData::defaultFullAvatarModelUrl() ? "" : @@ -974,6 +977,9 @@ void MyAvatar::loadData() { getHead()->setBasePitch(loadSetting(settings, "headPitch", 0.0f)); + _yawSpeed = loadSetting(settings, "yawSpeed", _yawSpeed); + _pitchSpeed = loadSetting(settings, "pitchSpeed", _pitchSpeed); + _targetScale = loadSetting(settings, "scale", 1.0f); setScale(glm::vec3(_targetScale)); @@ -1099,6 +1105,15 @@ int MyAvatar::parseDataFromBuffer(const QByteArray& buffer) { return buffer.size(); } +ScriptAvatarData* MyAvatar::getTargetAvatar() const { + auto avatar = std::static_pointer_cast(_lookAtTargetAvatar.lock()); + if (avatar) { + return new ScriptAvatar(avatar); + } else { + return nullptr; + } +} + void MyAvatar::updateLookAtTargetAvatar() { // // Look at the avatar whose eyes are closest to the ray in direction of my avatar's head @@ -1127,9 +1142,8 @@ void MyAvatar::updateLookAtTargetAvatar() { if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) { _lookAtTargetAvatar = avatarPointer; _targetAvatarPosition = avatarPointer->getPosition(); - smallestAngleTo = angleTo; } - if (isLookingAtMe(avatar)) { + if (_lookAtSnappingEnabled && avatar->getLookAtSnappingEnabled() && isLookingAtMe(avatar)) { // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face. glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); // A position, in world space, on my avatar. @@ -1146,14 +1160,19 @@ void MyAvatar::updateLookAtTargetAvatar() { ViewFrustum viewFrustum; qApp->copyViewFrustum(viewFrustum); + glm::vec3 viewPosition = viewFrustum.getPosition(); + glm::quat viewOrientation = viewFrustum.getOrientation(); +#if DEBUG_ALWAYS_LOOKAT_EYES_NOT_CAMERA + viewPosition = (avatarLeftEye + avatarRightEye) / 2.0f; +#endif // scale gazeOffset by IPD, if wearing an HMD. if (qApp->isHMDMode()) { glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left); glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right); glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); - glm::vec3 humanLeftEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * leftEyeHeadLocal); - glm::vec3 humanRightEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * rightEyeHeadLocal); + glm::vec3 humanLeftEye = + (viewOrientation * leftEyeHeadLocal); + glm::vec3 humanRightEye = viewPosition + (viewOrientation * rightEyeHeadLocal); auto hmdInterface = DependencyManager::get(); float ipdScale = hmdInterface->getIPDScale(); @@ -1167,7 +1186,7 @@ void MyAvatar::updateLookAtTargetAvatar() { } // And now we can finally add that offset to the camera. - glm::vec3 corrected = viewFrustum.getPosition() + gazeOffset; + glm::vec3 corrected = viewPosition + gazeOffset; avatar->getHead()->setCorrectedLookAtPosition(corrected); @@ -2199,6 +2218,7 @@ void MyAvatar::updateMotionBehaviorFromMenu() { _motionBehaviors &= ~AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED; } setCollisionsEnabled(menu->isOptionChecked(MenuOption::EnableAvatarCollisions)); + setProperty("lookAtSnappingEnabled", menu->isOptionChecked(MenuOption::EnableLookAtSnapping)); } void MyAvatar::setCollisionsEnabled(bool enabled) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index fde350a43e..2f5be25a4b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "AtRestDetector.h" #include "MyCharacterController.h" @@ -132,6 +133,9 @@ class MyAvatar : public Avatar { Q_PROPERTY(bool characterControllerEnabled READ getCharacterControllerEnabled WRITE setCharacterControllerEnabled) Q_PROPERTY(bool useAdvancedMovementControls READ useAdvancedMovementControls WRITE setUseAdvancedMovementControls) + Q_PROPERTY(float yawSpeed MEMBER _yawSpeed) + Q_PROPERTY(float pitchSpeed MEMBER _pitchSpeed) + public: enum DriveKeys { TRANSLATE_X = 0, @@ -368,6 +372,7 @@ public: Q_INVOKABLE glm::vec3 getEyePosition() const { return getHead()->getEyePosition(); } Q_INVOKABLE glm::vec3 getTargetAvatarPosition() const { return _targetAvatarPosition; } + Q_INVOKABLE ScriptAvatarData* getTargetAvatar() const; Q_INVOKABLE glm::vec3 getLeftHandPosition() const; Q_INVOKABLE glm::vec3 getRightHandPosition() const; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index d78287a0e7..4575adc762 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -506,8 +506,8 @@ void Avatar::postUpdate(float deltaTime) { if (isMyAvatar() ? showMyLookAtVectors : showOtherLookAtVectors) { const float EYE_RAY_LENGTH = 10.0; - const glm::vec4 BLUE(0.0f, 0.0f, 1.0f, 1.0f); - const glm::vec4 RED(1.0f, 0.0f, 0.0f, 1.0f); + const glm::vec4 BLUE(0.0f, 0.0f, _lookAtSnappingEnabled ? 1.0f : 0.25f, 1.0f); + const glm::vec4 RED(_lookAtSnappingEnabled ? 1.0f : 0.25f, 0.0f, 0.0f, 1.0f); int leftEyeJoint = getJointIndex("LeftEye"); glm::vec3 leftEyePosition; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d82068b8ac..ee46da42f8 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -85,6 +85,8 @@ AvatarData::AvatarData() : ASSERT(sizeof(AvatarDataPacket::AdditionalFlags) == AvatarDataPacket::ADDITIONAL_FLAGS_SIZE); ASSERT(sizeof(AvatarDataPacket::ParentInfo) == AvatarDataPacket::PARENT_INFO_SIZE); ASSERT(sizeof(AvatarDataPacket::FaceTrackerInfo) == AvatarDataPacket::FACE_TRACKER_INFO_SIZE); + + connect(this, &AvatarData::lookAtSnappingChanged, this, &AvatarData::markIdentityDataChanged); } AvatarData::~AvatarData() { @@ -1479,14 +1481,18 @@ void AvatarData::parseAvatarIdentityPacket(const QByteArray& data, Identity& ide >> identityOut.displayName >> identityOut.sessionDisplayName >> identityOut.avatarEntityData - >> identityOut.sequenceId; + >> identityOut.sequenceId + >> identityOut.lookAtSnappingEnabled + ; #ifdef WANT_DEBUG qCDebug(avatars) << __FUNCTION__ << "identityOut.uuid:" << identityOut.uuid << "identityOut.skeletonModelURL:" << identityOut.skeletonModelURL << "identityOut.displayName:" << identityOut.displayName - << "identityOut.sessionDisplayName:" << identityOut.sessionDisplayName; + << "identityOut.sessionDisplayName:" << identityOut.sessionDisplayName + << "identityOut.lookAtSnappingEnabled:" << identityOut.lookAtSnappingEnabled + ; #endif } @@ -1541,6 +1547,13 @@ void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityC identityChanged = true; } + if (_lookAtSnappingEnabled != identity.lookAtSnappingEnabled) { +#ifdef DEBUG_LOOKAT_SNAPPING + qCDebug(avatars) << __FUNCTION__ << identity.sessionDisplayName << "_lookAtSnappingEnabled" << _lookAtSnappingEnabled << "->" << identity.lookAtSnappingEnabled; +#endif + setProperty("lookAtSnappingEnabled", identity.lookAtSnappingEnabled); + identityChanged = true; + } } QByteArray AvatarData::identityByteArray() const { @@ -1549,13 +1562,16 @@ QByteArray AvatarData::identityByteArray() const { const QUrl& urlToSend = cannonicalSkeletonModelURL(emptyURL); // depends on _skeletonModelURL _avatarEntitiesLock.withReadLock([&] { - identityStream << getSessionUUID() - << urlToSend - << _attachmentData - << _displayName - << getSessionDisplayNameForTransport() // depends on _sessionDisplayName - << _avatarEntityData - << _identitySequenceId; + identityStream + << getSessionUUID() + << urlToSend + << _attachmentData + << _displayName + << getSessionDisplayNameForTransport() // depends on _sessionDisplayName + << _avatarEntityData + << _identitySequenceId + << _lookAtSnappingEnabled + ; }); return identityData; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 4104615cfe..6f29b6af22 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -323,6 +323,7 @@ class AvatarData : public QObject, public SpatiallyNestable { Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition) Q_PROPERTY(float scale READ getTargetScale WRITE setTargetScale) + Q_PROPERTY(float density READ getDensity) Q_PROPERTY(glm::vec3 handPosition READ getHandPosition WRITE setHandPosition) Q_PROPERTY(float bodyYaw READ getBodyYaw WRITE setBodyYaw) Q_PROPERTY(float bodyPitch READ getBodyPitch WRITE setBodyPitch) @@ -344,6 +345,7 @@ class AvatarData : public QObject, public SpatiallyNestable { // sessionDisplayName is sanitized, defaulted version displayName that is defined by the AvatarMixer rather than by Interface clients. // The result is unique among all avatars present at the time. Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName) + Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged) Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript) Q_PROPERTY(QVector attachmentData READ getAttachmentData WRITE setAttachmentData) @@ -532,6 +534,7 @@ public: QString sessionDisplayName; AvatarEntityMap avatarEntityData; quint64 sequenceId; + bool lookAtSnappingEnabled; }; static void parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut); @@ -545,6 +548,8 @@ public: const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } const QString& getDisplayName() const { return _displayName; } const QString& getSessionDisplayName() const { return _sessionDisplayName; } + bool getLookAtSnappingEnabled() const { return _lookAtSnappingEnabled; } + virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); virtual void setDisplayName(const QString& displayName); @@ -633,6 +638,7 @@ public: signals: void displayNameChanged(); + void lookAtSnappingChanged(bool enabled); public slots: void sendAvatarDataPacket(); @@ -697,6 +703,7 @@ protected: QVector _attachmentData; QString _displayName; QString _sessionDisplayName { }; + bool _lookAtSnappingEnabled { true }; QUrl cannonicalSkeletonModelURL(const QUrl& empty) const; QHash _jointIndices; ///< 1-based, since zero is returned for missing keys diff --git a/libraries/avatars/src/ScriptAvatarData.cpp b/libraries/avatars/src/ScriptAvatarData.cpp index 01d7f293d8..49e53952d4 100644 --- a/libraries/avatars/src/ScriptAvatarData.cpp +++ b/libraries/avatars/src/ScriptAvatarData.cpp @@ -15,6 +15,7 @@ ScriptAvatarData::ScriptAvatarData(AvatarSharedPointer avatarData) : _avatarData(avatarData) { QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged); + QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged); } // @@ -152,6 +153,13 @@ QString ScriptAvatarData::getSessionDisplayName() const { return QString(); } } +bool ScriptAvatarData::getLookAtSnappingEnabled() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getLookAtSnappingEnabled(); + } else { + return false; + } +} // // IDENTIFIER PROPERTIES // END diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index d763b6e97a..4a95333402 100644 --- a/libraries/avatars/src/ScriptAvatarData.h +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -45,6 +45,7 @@ class ScriptAvatarData : public QObject { Q_PROPERTY(QUuid sessionUUID READ getSessionUUID) Q_PROPERTY(QString displayName READ getDisplayName NOTIFY displayNameChanged) Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName) + Q_PROPERTY(bool lookAtSnappingEnabled READ getLookAtSnappingEnabled NOTIFY lookAtSnappingChanged) // // ATTACHMENT AND JOINT PROPERTIES @@ -95,6 +96,7 @@ public: QUuid getSessionUUID() const; QString getDisplayName() const; QString getSessionDisplayName() const; + bool getLookAtSnappingEnabled() const; // // ATTACHMENT AND JOINT PROPERTIES @@ -127,6 +129,7 @@ public: signals: void displayNameChanged(); + void lookAtSnappingChanged(bool enabled); public slots: glm::quat getAbsoluteJointRotationInObjectFrame(int index) const; diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index d8e0c59da7..00e49b78db 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -436,7 +436,7 @@ glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const mousePosition -= 1.0; mousePosition.y *= -1.0f; - vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize; + vec2 mouseSize = CURSOR_PIXEL_SIZE * Cursor::Manager::instance().getScale() / canvasSize; result = glm::scale(glm::translate(glm::mat4(), vec3(mousePosition, 0.0f)), vec3(mouseSize, 1.0f)); } return result; @@ -450,3 +450,13 @@ QVariant ReticleInterface::getPosition() const { void ReticleInterface::setPosition(QVariant position) { _compositor->setReticlePosition(vec2FromVariant(position)); } + +float ReticleInterface::getScale() const { + auto& cursorManager = Cursor::Manager::instance(); + return cursorManager.getScale(); +} + +void ReticleInterface::setScale(float scale) { + auto& cursorManager = Cursor::Manager::instance(); + cursorManager.setScale(scale); +} diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index 5be2d68cf9..73e010fdd4 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -179,6 +179,7 @@ class ReticleInterface : public QObject { Q_PROPERTY(QVariant position READ getPosition WRITE setPosition) Q_PROPERTY(bool visible READ getVisible WRITE setVisible) Q_PROPERTY(float depth READ getDepth WRITE setDepth) + Q_PROPERTY(float scale READ getScale WRITE setScale) Q_PROPERTY(glm::vec2 maximumPosition READ getMaximumPosition) Q_PROPERTY(bool mouseCaptured READ isMouseCaptured) Q_PROPERTY(bool allowMouseCapture READ getAllowMouseCapture WRITE setAllowMouseCapture) @@ -200,6 +201,9 @@ public: Q_INVOKABLE float getDepth() { return _compositor->getReticleDepth(); } Q_INVOKABLE void setDepth(float depth) { _compositor->setReticleDepth(depth); } + Q_INVOKABLE float getScale() const; + Q_INVOKABLE void setScale(float scale); + Q_INVOKABLE QVariant getPosition() const; Q_INVOKABLE void setPosition(QVariant position); diff --git a/libraries/ui/src/CursorManager.cpp b/libraries/ui/src/CursorManager.cpp index f768b5f227..28b84efb32 100644 --- a/libraries/ui/src/CursorManager.cpp +++ b/libraries/ui/src/CursorManager.cpp @@ -35,6 +35,7 @@ namespace Cursor { static uint16_t _customIconId = Icon::USER_BASE; Manager::Manager() { + ICONS[Icon::SYSTEM] = PathUtils::resourcesPath() + "images/cursor-none.png"; ICONS[Icon::DEFAULT] = PathUtils::resourcesPath() + "images/arrow.png"; ICONS[Icon::LINK] = PathUtils::resourcesPath() + "images/link.png"; } diff --git a/libraries/ui/src/CursorManager.h b/libraries/ui/src/CursorManager.h index 99d5ccdc77..6c0bf162b3 100644 --- a/libraries/ui/src/CursorManager.h +++ b/libraries/ui/src/CursorManager.h @@ -18,6 +18,7 @@ namespace Cursor { }; enum Icon { + SYSTEM, DEFAULT, LINK, GRAB, From d3127ba97557551b76847a314d9d6d1e76905f6a Mon Sep 17 00:00:00 2001 From: humbletim Date: Mon, 19 Jun 2017 20:18:39 -0400 Subject: [PATCH 2/9] remove unintended merge line --- libraries/avatars/src/AvatarData.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 7f02de8a29..affd5af147 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -370,7 +370,6 @@ public: virtual ~AvatarData(); static const QUrl& defaultFullAvatarModelUrl(); - QUrl cannonicalSkeletonModelURL(const QUrl& empty) const; virtual bool isMyAvatar() const { return false; } From fbeaa01f7db70dec523c76c649603d8c4c7f5529 Mon Sep 17 00:00:00 2001 From: humbletim Date: Tue, 20 Jun 2017 01:51:33 -0400 Subject: [PATCH 3/9] remerge master / remove debug block --- libraries/avatars/src/AvatarData.cpp | 3 --- libraries/avatars/src/AvatarData.h | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index b0423f4272..29907d6a3e 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1552,9 +1552,6 @@ void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityC } if (_lookAtSnappingEnabled != identity.lookAtSnappingEnabled) { -#ifdef DEBUG_LOOKAT_SNAPPING - qCDebug(avatars) << __FUNCTION__ << identity.sessionDisplayName << "_lookAtSnappingEnabled" << _lookAtSnappingEnabled << "->" << identity.lookAtSnappingEnabled; -#endif setProperty("lookAtSnappingEnabled", identity.lookAtSnappingEnabled); identityChanged = true; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index affd5af147..fafe878027 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -370,6 +370,7 @@ public: virtual ~AvatarData(); static const QUrl& defaultFullAvatarModelUrl(); + QUrl cannonicalSkeletonModelURL(const QUrl& empty) const; virtual bool isMyAvatar() const { return false; } @@ -548,7 +549,6 @@ public: const QString& getDisplayName() const { return _displayName; } const QString& getSessionDisplayName() const { return _sessionDisplayName; } bool getLookAtSnappingEnabled() const { return _lookAtSnappingEnabled; } - virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); virtual void setDisplayName(const QString& displayName); @@ -703,7 +703,6 @@ protected: QString _displayName; QString _sessionDisplayName { }; bool _lookAtSnappingEnabled { true }; - QUrl cannonicalSkeletonModelURL(const QUrl& empty) const; QHash _jointIndices; ///< 1-based, since zero is returned for missing keys QStringList _jointNames; ///< in order of depth-first traversal From 9053531bda7d157b46e95c7070d5c65bdf907537 Mon Sep 17 00:00:00 2001 From: humbletim Date: Mon, 3 Jul 2017 12:03:46 -0400 Subject: [PATCH 4/9] fix missing viewPosition + offset --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ab1e644420..db841e1bdf 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1271,7 +1271,7 @@ void MyAvatar::updateLookAtTargetAvatar() { glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right); glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); - glm::vec3 humanLeftEye = + (viewOrientation * leftEyeHeadLocal); + glm::vec3 humanLeftEye = viewPosition + (viewOrientation * leftEyeHeadLocal); glm::vec3 humanRightEye = viewPosition + (viewOrientation * rightEyeHeadLocal); auto hmdInterface = DependencyManager::get(); From 190e1ac7d9307049cd04d73cd800fd62d432a1b7 Mon Sep 17 00:00:00 2001 From: humbletim Date: Tue, 18 Jul 2017 17:22:16 -0400 Subject: [PATCH 5/9] move/scope viewOrientation into the related code block --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index db841e1bdf..d2d15ea708 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1261,12 +1261,12 @@ void MyAvatar::updateLookAtTargetAvatar() { qApp->copyViewFrustum(viewFrustum); glm::vec3 viewPosition = viewFrustum.getPosition(); - glm::quat viewOrientation = viewFrustum.getOrientation(); #if DEBUG_ALWAYS_LOOKAT_EYES_NOT_CAMERA viewPosition = (avatarLeftEye + avatarRightEye) / 2.0f; #endif // scale gazeOffset by IPD, if wearing an HMD. if (qApp->isHMDMode()) { + glm::quat viewOrientation = viewFrustum.getOrientation(); glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left); glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right); glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); From d9de0a8687d9ef70aa42fb9605395fc2e8ee3e13 Mon Sep 17 00:00:00 2001 From: humbletim Date: Tue, 18 Jul 2017 17:46:59 -0400 Subject: [PATCH 6/9] bump AvatarMixer protocol version --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 240697d890..1c357818e1 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -69,7 +69,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::AvatarData: case PacketType::BulkAvatarData: case PacketType::KillAvatar: - return static_cast(AvatarMixerPacketVersion::IsReplicatedInAvatarIdentity); + return static_cast(AvatarMixerPacketVersion::AvatarIdentityLookAtSnapping); case PacketType::MessagesData: return static_cast(MessageDataVersion::TextOrBinaryData); case PacketType::ICEServerHeartbeat: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 848bfd97cf..b7d3aa1eac 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -247,7 +247,8 @@ enum class AvatarMixerPacketVersion : PacketVersion { AvatarIdentitySequenceId, MannequinDefaultAvatar, AvatarIdentitySequenceFront, - IsReplicatedInAvatarIdentity + IsReplicatedInAvatarIdentity, + AvatarIdentityLookAtSnapping, }; enum class DomainConnectRequestVersion : PacketVersion { From cbbe03cee7277d241fc4194a910145cd6dd9c8e1 Mon Sep 17 00:00:00 2001 From: beholder Date: Fri, 25 Aug 2017 02:32:03 +0300 Subject: [PATCH 7/9] 6788: You can deselect your current view mode --- interface/resources/qml/desktop/Desktop.qml | 19 ++++++- .../qml/hifi/tablet/TabletMenuStack.qml | 44 ++++++++++++++-- interface/src/Menu.cpp | 22 ++++++-- libraries/ui/src/VrMenu.cpp | 50 ++++++++++++++++--- 4 files changed, 120 insertions(+), 15 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index ca7226a6ab..ec0bb7245b 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -50,7 +50,24 @@ FocusScope { property bool desktopRoot: true // The VR version of the primary menu - property var rootMenu: Menu { objectName: "rootMenu" } + property var rootMenu: Menu { + objectName: "rootMenu" + + // for some reasons it is not possible to use just '({})' here as it gets empty when passed to TableRoot/DesktopRoot + property var exclusionGroupsByMenuItem : ListModel {} + + function addExclusionGroup(menuItem, exclusionGroup) + { + console.debug('entering Desktop::addExclusionGroup: menuItem = ', menuItem, 'exclusionGroup = ', exclusionGroup); + exclusionGroupsByMenuItem.append( + { + 'menuItem' : menuItem.toString(), + 'exclusionGroup' : exclusionGroup.toString() + } + ); + console.debug('Desktop::addExclusionGroup: ', exclusionGroup, 'rootMenu: ', this); + } + } // FIXME: Alpha gradients display as fuschia under QtQuick 2.5 on OSX/AMD // because shaders are 4.2, and do not include #version declarations. diff --git a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml index 9076cd6c48..c088088a1c 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml @@ -64,8 +64,10 @@ Item { d.pop(); } - function toModel(items) { + function toModel(items, newMenu) { var result = modelMaker.createObject(tabletMenu); + var exclusionGroups = {}; + for (var i = 0; i < items.length; ++i) { var item = items[i]; if (!item.visible) continue; @@ -77,6 +79,28 @@ Item { if (item.text !== "Users Online") { result.append({"name": item.text, "item": item}) } + + for(var j = 0; j < tabletMenu.rootMenu.exclusionGroupsByMenuItem.count; ++j) + { + var entry = tabletMenu.rootMenu.exclusionGroupsByMenuItem.get(j); + if(entry.menuItem == item.toString()) + { + var exclusionGroupId = entry.exclusionGroup; + console.debug('item exclusionGroupId: ', exclusionGroupId) + + if(!exclusionGroups[exclusionGroupId]) + { + exclusionGroups[exclusionGroupId] = exclusiveGroupMaker.createObject(newMenu); + console.debug('new exclusion group created: ', exclusionGroups[exclusionGroupId]) + } + + var exclusionGroup = exclusionGroups[exclusionGroupId]; + + item.exclusiveGroup = exclusionGroup + console.debug('item.exclusiveGroup: ', item.exclusiveGroup) + } + } + break; case MenuItemType.Separator: result.append({"name": "", "item": item}) @@ -133,10 +157,24 @@ Item { } } + property Component exclusiveGroupMaker: Component { + ExclusiveGroup { + Component.onDestruction: { + console.debug('ExclusionGroup destroyed: ', this) + } + } + } + function buildMenu(items) { - var model = toModel(items); // Menus must be childed to desktop for Z-ordering - var newMenu = menuViewMaker.createObject(tabletMenu, { model: model, isSubMenu: topMenu !== null }); + var newMenu = menuViewMaker.createObject(tabletMenu); + console.debug('newMenu created: ', newMenu) + + var model = toModel(items, newMenu); + + newMenu.model = model; + newMenu.isSubMenu = topMenu !== null; + pushMenu(newMenu); return newMenu; } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 2c4a515736..17cf782b70 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -56,6 +56,8 @@ Menu* Menu::getInstance() { return dynamic_cast(qApp->getWindow()->menuBar()); } +const char* exclusionGroupKey = "exclusionGroup"; + Menu::Menu() { auto dialogsManager = DependencyManager::get(); auto accountManager = DependencyManager::get(); @@ -222,32 +224,42 @@ Menu::Menu() { cameraModeGroup->setExclusive(true); // View > First Person - cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( + auto firstPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( viewMenu, MenuOption::FirstPerson, Qt::CTRL | Qt::Key_F, true, qApp, SLOT(cameraMenuChanged()))); + firstPersonAction->setProperty(exclusionGroupKey, QVariant::fromValue(cameraModeGroup)); + // View > Third Person - cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( + auto thirdPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( viewMenu, MenuOption::ThirdPerson, Qt::CTRL | Qt::Key_G, false, qApp, SLOT(cameraMenuChanged()))); + thirdPersonAction->setProperty(exclusionGroupKey, QVariant::fromValue(cameraModeGroup)); + // View > Mirror - cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( + auto viewMirrorAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash( viewMenu, MenuOption::FullscreenMirror, Qt::CTRL | Qt::Key_H, false, qApp, SLOT(cameraMenuChanged()))); + viewMirrorAction->setProperty(exclusionGroupKey, QVariant::fromValue(cameraModeGroup)); + // View > Independent [advanced] - cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, + auto viewIndependentAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::IndependentMode, 0, false, qApp, SLOT(cameraMenuChanged()), UNSPECIFIED_POSITION, "Advanced")); + viewIndependentAction->setProperty(exclusionGroupKey, QVariant::fromValue(cameraModeGroup)); + // View > Entity Camera [advanced] - cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, + auto viewEntityCameraAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CameraEntityMode, 0, false, qApp, SLOT(cameraMenuChanged()), UNSPECIFIED_POSITION, "Advanced")); + viewEntityCameraAction->setProperty(exclusionGroupKey, QVariant::fromValue(cameraModeGroup)); + viewMenu->addSeparator(); // View > Center Player In View diff --git a/libraries/ui/src/VrMenu.cpp b/libraries/ui/src/VrMenu.cpp index 3959e950e9..b81f259b66 100644 --- a/libraries/ui/src/VrMenu.cpp +++ b/libraries/ui/src/VrMenu.cpp @@ -26,12 +26,14 @@ static unsigned int USER_DATA_ID = 0; // and qml object and inject the pointer into both objects class MenuUserData : public QObjectUserData { public: - MenuUserData(QAction* action, QObject* qmlObject) { + MenuUserData(QAction* action, QObject* qmlObject, QObject* qmlParent) { if (!USER_DATA_ID) { USER_DATA_ID = DependencyManager::get()->getMenuUserDataId(); } _action = action; _qml = qmlObject; + _qmlParent = qmlParent; + action->setUserData(USER_DATA_ID, this); qmlObject->setUserData(USER_DATA_ID, this); qmlObject->setObjectName(uuid.toString()); @@ -43,6 +45,41 @@ public: _shutdownConnection = QObject::connect(qApp, &QCoreApplication::aboutToQuit, [=] { QObject::disconnect(_changedConnection); }); + + class ExclusionGroupSetter : public QObject { + public: + ExclusionGroupSetter(QObject* from, QObject* to, QObject* qmlParent) : QObject(from), _from(from), _to(to), _qmlParent(qmlParent) { + _from->installEventFilter(this); + } + + ~ExclusionGroupSetter() { + _from->removeEventFilter(this); + } + protected: + bool eventFilter(QObject* o, QEvent* e) { + if (e->type() == QEvent::DynamicPropertyChange) { + QDynamicPropertyChangeEvent* dpc = static_cast(e); + if (dpc->propertyName() == "exclusionGroup") + { + // unfortunately Qt doesn't support passing dynamic properties between C++ / QML, so we have to use this ugly helper function + QMetaObject::invokeMethod(_qmlParent, + "addExclusionGroup", + Qt::DirectConnection, + Q_ARG(QVariant, QVariant::fromValue(_to)), + Q_ARG(QVariant, _from->property(dpc->propertyName()))); + } + } + + return QObject::eventFilter(o, e); + } + + private: + QObject* _from; + QObject* _to; + QObject* _qmlParent; + }; + + new ExclusionGroupSetter(action, qmlObject, qmlParent); } ~MenuUserData() { @@ -110,6 +147,7 @@ private: QMetaObject::Connection _changedConnection; QAction* _action { nullptr }; QObject* _qml { nullptr }; + QObject* _qmlParent{ nullptr }; }; @@ -157,16 +195,16 @@ void VrMenu::addMenu(QMenu* menu) { } // Bind the QML and Widget together - new MenuUserData(menu->menuAction(), result); + new MenuUserData(menu->menuAction(), result, qmlParent); } -void bindActionToQmlAction(QObject* qmlAction, QAction* action) { +void bindActionToQmlAction(QObject* qmlAction, QAction* action, QObject* qmlParent) { auto text = action->text(); if (text == "Login") { qDebug(uiLogging) << "Login action " << action; } - new MenuUserData(action, qmlAction); + new MenuUserData(action, qmlAction, qmlParent); QObject::connect(action, &QAction::toggled, [=](bool checked) { qmlAction->setProperty("checked", checked); }); @@ -195,7 +233,7 @@ void VrMenu::addAction(QMenu* menu, QAction* action) { QObject* result = reinterpret_cast(returnedValue); // returnedValue.value(); Q_ASSERT(result); // Bind the QML and Widget together - bindActionToQmlAction(result, action); + bindActionToQmlAction(result, action, _rootMenu); } void VrMenu::addSeparator(QMenu* menu) { @@ -231,7 +269,7 @@ void VrMenu::insertAction(QAction* before, QAction* action) { Q_ASSERT(invokeResult); QObject* result = reinterpret_cast(returnedValue); // returnedValue.value(); Q_ASSERT(result); - bindActionToQmlAction(result, action); + bindActionToQmlAction(result, action, _rootMenu); } class QQuickMenuBase; From a0a43ebf263e2fcb5c74c6a83258fc0105a4516f Mon Sep 17 00:00:00 2001 From: beholder Date: Tue, 29 Aug 2017 23:23:16 +0300 Subject: [PATCH 8/9] show checkbox or radiobutton dependently on exclusiveGroup presence --- interface/resources/qml/desktop/Desktop.qml | 2 - .../qml/hifi/tablet/TabletMenuItem.qml | 46 ++++++++++++++----- .../qml/hifi/tablet/TabletMenuStack.qml | 3 -- libraries/ui/src/VrMenu.cpp | 2 +- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index ec0bb7245b..579b4e7fd6 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -58,14 +58,12 @@ FocusScope { function addExclusionGroup(menuItem, exclusionGroup) { - console.debug('entering Desktop::addExclusionGroup: menuItem = ', menuItem, 'exclusionGroup = ', exclusionGroup); exclusionGroupsByMenuItem.append( { 'menuItem' : menuItem.toString(), 'exclusionGroup' : exclusionGroup.toString() } ); - console.debug('Desktop::addExclusionGroup: ', exclusionGroup, 'rootMenu: ', this); } } diff --git a/interface/resources/qml/hifi/tablet/TabletMenuItem.qml b/interface/resources/qml/hifi/tablet/TabletMenuItem.qml index 25f672e7a9..71e59e0d01 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenuItem.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenuItem.qml @@ -26,24 +26,48 @@ Item { visible: source.visible width: parent.width - CheckBox { + Item { id: check - // FIXME: Should use radio buttons if source.exclusiveGroup. + anchors { left: parent.left leftMargin: hifi.dimensions.menuPadding.x + 15 verticalCenter: label.verticalCenter } - width: 20 - visible: source.visible && source.type === 1 && source.checkable - checked: setChecked() - function setChecked() { - if (!source || source.type !== 1 || !source.checkable) { - return false; + + width: checkbox.visible ? checkbox.width : radiobutton.width + height: checkbox.visible ? checkbox.height : radiobutton.height + + CheckBox { + id: checkbox + // FIXME: Should use radio buttons if source.exclusiveGroup. + width: 20 + visible: source.visible && source.type === 1 && source.checkable && !source.exclusiveGroup + checked: setChecked() + function setChecked() { + if (!source || source.type !== 1 || !source.checkable) { + return false; + } + // FIXME this works for native QML menus but I don't think it will + // for proxied QML menus + return source.checked; + } + } + + RadioButton { + id: radiobutton + // FIXME: Should use radio buttons if source.exclusiveGroup. + width: 20 + visible: source.visible && source.type === 1 && source.checkable && source.exclusiveGroup + checked: setChecked() + function setChecked() { + if (!source || source.type !== 1 || !source.checkable) { + return false; + } + // FIXME this works for native QML menus but I don't think it will + // for proxied QML menus + return source.checked; } - // FIXME this works for native QML menus but I don't think it will - // for proxied QML menus - return source.checked; } } diff --git a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml index c088088a1c..e7eefbc5e7 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml @@ -159,9 +159,6 @@ Item { property Component exclusiveGroupMaker: Component { ExclusiveGroup { - Component.onDestruction: { - console.debug('ExclusionGroup destroyed: ', this) - } } } diff --git a/libraries/ui/src/VrMenu.cpp b/libraries/ui/src/VrMenu.cpp index b81f259b66..70daff944a 100644 --- a/libraries/ui/src/VrMenu.cpp +++ b/libraries/ui/src/VrMenu.cpp @@ -56,7 +56,7 @@ public: _from->removeEventFilter(this); } protected: - bool eventFilter(QObject* o, QEvent* e) { + virtual bool eventFilter(QObject* o, QEvent* e) override { if (e->type() == QEvent::DynamicPropertyChange) { QDynamicPropertyChangeEvent* dpc = static_cast(e); if (dpc->propertyName() == "exclusionGroup") From 5b264a867aefa0b6e5ed509f9706724844924701 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 29 Aug 2017 16:05:01 -0700 Subject: [PATCH 9/9] fix wallet login (and share code with snapshot login) --- scripts/system/commerce/wallet.js | 10 ++-------- scripts/system/libraries/accountUtils.js | 16 ++++++++++++++++ scripts/system/snapshot.js | 13 +++---------- 3 files changed, 21 insertions(+), 18 deletions(-) create mode 100644 scripts/system/libraries/accountUtils.js diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 4b758f0add..7f24e7f634 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -14,7 +14,7 @@ /*global XXX */ (function () { // BEGIN LOCAL_SCOPE - + Script.include("/~/system/libraries/accountUtils.js"); // Function Name: onButtonClicked() // @@ -59,13 +59,7 @@ tablet.gotoHomeScreen(); break; case 'walletSetup_loginClicked': - if ((HMD.active && Settings.getValue("hmdTabletBecomesToolbar", false)) - || (!HMD.active && Settings.getValue("desktopTabletBecomesToolbar", true))) { - Menu.triggerOption("Login / Sign Up"); - tablet.gotoHomeScreen(); - } else { - tablet.loadQMLOnTop("../../../dialogs/TabletLoginDialog.qml"); - } + openLoginWindow(); break; default: print('Unrecognized message from QML:', JSON.stringify(message)); diff --git a/scripts/system/libraries/accountUtils.js b/scripts/system/libraries/accountUtils.js new file mode 100644 index 0000000000..6df0aa3a87 --- /dev/null +++ b/scripts/system/libraries/accountUtils.js @@ -0,0 +1,16 @@ +// +// accountUtils.js +// scripts/system/libraries/libraries +// +// Copyright 2017 High Fidelity, Inc. +// + +openLoginWindow = function openLoginWindow() { + if ((HMD.active && Settings.getValue("hmdTabletBecomesToolbar", false)) + || (!HMD.active && Settings.getValue("desktopTabletBecomesToolbar", true))) { + Menu.triggerOption("Login / Sign Up"); + } else { + tablet.loadQMLOnTop("../../dialogs/TabletLoginDialog.qml"); + HMD.openTablet(); + } +}; diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index df5ed45fed..e5c60af77b 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -10,7 +10,8 @@ /* globals Tablet, Script, HMD, Settings, DialogsManager, Menu, Reticle, OverlayWebWindow, Desktop, Account, MyAvatar, Snapshot */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ -(function() { // BEGIN LOCAL_SCOPE +(function () { // BEGIN LOCAL_SCOPE +Script.include("/~/system/libraries/accountUtils.js"); var SNAPSHOT_DELAY = 500; // 500ms var FINISH_SOUND_DELAY = 350; @@ -52,15 +53,7 @@ try { print('Failed to resolve request api, error: ' + err); } -function openLoginWindow() { - if ((HMD.active && Settings.getValue("hmdTabletBecomesToolbar", false)) - || (!HMD.active && Settings.getValue("desktopTabletBecomesToolbar", true))) { - Menu.triggerOption("Login / Sign Up"); - } else { - tablet.loadQMLOnTop("../../dialogs/TabletLoginDialog.qml"); - HMD.openTablet(); - } -} + function removeFromStoryIDsToMaybeDelete(story_id) { storyIDsToMaybeDelete.splice(storyIDsToMaybeDelete.indexOf(story_id), 1);