From d842e532ee61e80b444e860ee851651dddeda741 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 4 Feb 2018 14:02:30 +1300 Subject: [PATCH 01/54] Remove Window.customPrompt() from JavaScript API --- interface/src/Application.cpp | 1 - .../scripting/WindowScriptingInterface.cpp | 22 ------------------- .../src/scripting/WindowScriptingInterface.h | 20 ----------------- libraries/ui/src/OffscreenUi.cpp | 17 -------------- libraries/ui/src/OffscreenUi.h | 2 -- 5 files changed, 62 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a54c94d53..31c0b3555c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5857,7 +5857,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe DependencyManager::get().data()->setToolbarScriptingInterface(toolbarScriptingInterface); scriptEngine->registerGlobalObject("Window", DependencyManager::get().data()); - qScriptRegisterMetaType(scriptEngine.data(), CustomPromptResultToScriptValue, CustomPromptResultFromScriptValue); scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, LocationScriptingInterface::locationSetter, "Window"); // register `location` on the global object. diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index d419d7484b..65873dc1dc 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -32,20 +32,6 @@ static const QString LAST_BROWSE_LOCATION_SETTING = "LastBrowseLocation"; static const QString LAST_BROWSE_ASSETS_LOCATION_SETTING = "LastBrowseAssetsLocation"; -QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result) { - if (!result.value.isValid()) { - return QScriptValue::UndefinedValue; - } - - Q_ASSERT(result.value.userType() == qMetaTypeId()); - return engine->toScriptValue(result.value.toMap()); -} - -void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result) { - result.value = object.toVariant(); -} - - WindowScriptingInterface::WindowScriptingInterface() { const DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged); @@ -140,14 +126,6 @@ void WindowScriptingInterface::disconnectedFromDomain() { emit domainChanged(""); } -CustomPromptResult WindowScriptingInterface::customPrompt(const QVariant& config) { - CustomPromptResult result; - bool ok = false; - auto configMap = config.toMap(); - result.value = OffscreenUi::getCustomInfo(OffscreenUi::ICON_NONE, "", configMap, &ok); - return ok ? result : CustomPromptResult(); -} - QString fixupPathForMac(const QString& directory) { // On OS X `directory` does not work as expected unless a file is included in the path, so we append a bogus // filename if the directory is valid. diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index dc71611c5b..d5f40b83c6 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -22,17 +22,6 @@ #include -class CustomPromptResult { -public: - QVariant value; -}; - -Q_DECLARE_METATYPE(CustomPromptResult); - -QScriptValue CustomPromptResultToScriptValue(QScriptEngine* engine, const CustomPromptResult& result); -void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptResult& result); - - /**jsdoc * The Window API provides various facilities not covered elsewhere: window dimensions, window focus, normal or entity camera * view, clipboard, announcements, user connections, common dialog boxes, snapshots, file import, domain changes, domain @@ -142,15 +131,6 @@ public slots: */ void promptAsync(const QString& message = "", const QString& defaultText = ""); - /**jsdoc - * Prompt the user for input in a custom, modal dialog. - * @deprecated This function is deprecated and will soon be removed. - * @function Window.customPrompt - * @param {object} config - Configures the modal dialog. - * @returns {object} The user's response. - */ - CustomPromptResult customPrompt(const QVariant& config); - /**jsdoc * Prompt the user to choose a directory. Displays a modal dialog that navigates the directory tree. * @function Window.browseDir diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 221f5013bf..f28e1954e4 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -384,19 +384,6 @@ QString OffscreenUi::getItem(const Icon icon, const QString& title, const QStrin return result.toString(); } -QVariant OffscreenUi::getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok) { - if (ok) { - *ok = false; - } - - QVariant result = DependencyManager::get()->customInputDialog(icon, title, config); - if (ok && result.isValid()) { - *ok = true; - } - - return result; -} - ModalDialogListener* OffscreenUi::getTextAsync(const Icon icon, const QString& title, const QString& label, const QString& text) { return DependencyManager::get()->inputDialogAsync(icon, title, label, text); } @@ -418,10 +405,6 @@ ModalDialogListener* OffscreenUi::getItemAsync(const Icon icon, const QString& t return inputDialogListener; } -ModalDialogListener* OffscreenUi::getCustomInfoAsync(const Icon icon, const QString& title, const QVariantMap& config) { - return DependencyManager::get()->customInputDialogAsync(icon, title, config); -} - QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const QString& label, const QVariant& current) { if (QThread::currentThread() != thread()) { QVariant result; diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index ab3a209820..8e10ebde08 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -231,10 +231,8 @@ public: static QString getText(const Icon icon, const QString & title, const QString & label, const QString & text = QString(), bool * ok = 0); static QString getItem(const Icon icon, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0); - static QVariant getCustomInfo(const Icon icon, const QString& title, const QVariantMap& config, bool* ok = 0); static ModalDialogListener* getTextAsync(const Icon icon, const QString & title, const QString & label, const QString & text = QString()); static ModalDialogListener* getItemAsync(const Icon icon, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true); - static ModalDialogListener* getCustomInfoAsync(const Icon icon, const QString& title, const QVariantMap& config); unsigned int getMenuUserDataId() const; QList &getModalDialogListeners(); From 8e2a3e8c99ff2bc1f36349db28d5d9a92d3dbfc7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 4 Feb 2018 14:15:48 +1300 Subject: [PATCH 02/54] Remove Overlays.getOverlayObject() from JavaScript API --- interface/src/ui/overlays/Overlays.cpp | 15 --------------- interface/src/ui/overlays/Overlays.h | 9 --------- scripts/system/libraries/WebTablet.js | 4 ---- 3 files changed, 28 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 6898b5ed2b..35274e4fbe 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -388,21 +388,6 @@ QString Overlays::getOverlayType(OverlayID overlayId) { return ""; } -QObject* Overlays::getOverlayObject(OverlayID id) { - if (QThread::currentThread() != thread()) { - QObject* result; - PROFILE_RANGE(script, __FUNCTION__); - BLOCKING_INVOKE_METHOD(this, "getOverlayObject", Q_RETURN_ARG(QObject*, result), Q_ARG(OverlayID, id)); - return result; - } - - Overlay::Pointer thisOverlay = getOverlay(id); - if (thisOverlay) { - return qobject_cast(&(*thisOverlay)); - } - return nullptr; -} - OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { if (!_enabled) { return UNKNOWN_OVERLAY_ID; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 113ee92b80..2da375f6e4 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -227,15 +227,6 @@ public slots: */ QString getOverlayType(OverlayID overlayId); - /**jsdoc - * Get the overlay script object. - * @function Overlays.getOverlayObject - * @deprecated This function is deprecated and will soon be removed. - * @param {Uuid} overlayID - The ID of the overlay to get the script object of. - * @returns {object} The script object for the overlay if found. - */ - QObject* getOverlayObject(OverlayID id); - /**jsdoc * Get the ID of the 2D overlay at a particular point on the screen or HUD. * @function Overlays.getOverlayAtPoint diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 05b4963280..2b7c0343e2 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -305,10 +305,6 @@ WebTablet.prototype.setScriptURL = function (scriptURL) { Overlays.editOverlay(this.webOverlayID, { scriptURL: scriptURL }); }; -WebTablet.prototype.getOverlayObject = function () { - return Overlays.getOverlayObject(this.webOverlayID); -}; - WebTablet.prototype.setWidth = function (width) { // imported from libraries/utils.js resizeTablet(width); From dd5cc8677d5a86f0772170b407916ecd2a84db63 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 4 Feb 2018 14:46:49 +1300 Subject: [PATCH 03/54] Remove Overlays.findRayIntersectionVector() from JavaScript API --- interface/src/ui/overlays/Overlays.h | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 2da375f6e4..3efe94c206 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -98,6 +98,11 @@ public: OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); } OverlayID addOverlay(const Overlay::Pointer& overlay); + RayToOverlayIntersectionResult findRayIntersectionVector(const PickRay& ray, bool precisionPicking, + const QVector& overlaysToInclude, + const QVector& overlaysToDiscard, + bool visibleOnly = false, bool collidableOnly = false); + bool mousePressEvent(QMouseEvent* event); bool mouseDoublePressEvent(QMouseEvent* event); bool mouseReleaseEvent(QMouseEvent* event); @@ -347,28 +352,6 @@ public slots: bool visibleOnly = false, bool collidableOnly = false); - // TODO: Apart from the name, this function signature on JavaScript is identical to that of findRayIntersection() and should - // probably be removed from the JavaScript API so as not to cause confusion. - /**jsdoc - * Find the closest 3D overlay intersected by a {@link PickRay}. - * @function Overlays.findRayIntersectionVector - * @deprecated Use {@link Overlays.findRayIntersection} instead; it has identical parameters and results. - * @param {PickRay} pickRay - The PickRay to use for finding overlays. - * @param {boolean} [precisionPicking=false] - Unused; exists to match Entity API. - * @param {Array.} [overlayIDsToInclude=[]] - Whitelist for intersection test. If empty then the result isn't limited - * to overlays in the list. - * @param {Array.} [overlayIDsToExclude=[]] - Blacklist for intersection test. If empty then the result doesn't - * exclude overlays in the list. - * @param {boolean} [visibleOnly=false] - Unused; exists to match Entity API. - * @param {boolean} [collidableOnly=false] - Unused; exists to match Entity API. - * @returns {Overlays.RayToOverlayIntersectionResult} The closest 3D overlay intersected by pickRay, taking - * into account overlayIDsToInclude and overlayIDsToExclude if they're not empty. - */ - RayToOverlayIntersectionResult findRayIntersectionVector(const PickRay& ray, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, - bool visibleOnly = false, bool collidableOnly = false); - /**jsdoc * Return a list of 3D overlays with bounding boxes that touch a search sphere. * @function Overlays.findOverlays From 0c0734a255a181cc6c5ee1f1d62f972d894d01cf Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 4 Feb 2018 14:54:14 +1300 Subject: [PATCH 04/54] Remove unused Overlays property, borderSize, and associated code --- interface/src/Application.cpp | 1 - interface/src/ui/overlays/Cube3DOverlay.cpp | 13 ------------- interface/src/ui/overlays/Cube3DOverlay.h | 5 ----- interface/src/ui/overlays/Shape3DOverlay.cpp | 12 ------------ interface/src/ui/overlays/Shape3DOverlay.h | 5 ----- scripts/developer/debugging/queryAACubeInspector.js | 1 - scripts/system/libraries/entitySelectionTool.js | 12 ++++-------- 7 files changed, 4 insertions(+), 45 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 31c0b3555c..bc567c0452 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4717,7 +4717,6 @@ void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { _keyboardFocusHighlight = std::make_shared(); _keyboardFocusHighlight->setAlpha(1.0f); - _keyboardFocusHighlight->setBorderSize(1.0f); _keyboardFocusHighlight->setColor({ 0xFF, 0xEF, 0x00 }); _keyboardFocusHighlight->setIsSolid(false); _keyboardFocusHighlight->setPulseMin(0.5); diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index f13f782482..29c4f592f5 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -125,13 +125,6 @@ Cube3DOverlay* Cube3DOverlay::createClone() const { void Cube3DOverlay::setProperties(const QVariantMap& properties) { Volume3DOverlay::setProperties(properties); - - auto borderSize = properties["borderSize"]; - - if (borderSize.isValid()) { - float value = borderSize.toFloat(); - setBorderSize(value); - } } /**jsdoc @@ -177,14 +170,8 @@ void Cube3DOverlay::setProperties(const QVariantMap& properties) { * parentID is an avatar skeleton. A value of 65535 means "no joint". * * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. - * - * @property {number} borderSize - Not used. */ QVariant Cube3DOverlay::getProperty(const QString& property) { - if (property == "borderSize") { - return _borderSize; - } - return Volume3DOverlay::getProperty(property); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.h b/interface/src/ui/overlays/Cube3DOverlay.h index e7b58ad911..5d83cbb2c1 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.h +++ b/interface/src/ui/overlays/Cube3DOverlay.h @@ -29,10 +29,6 @@ public: virtual Cube3DOverlay* createClone() const override; - float getBorderSize() const { return _borderSize; } - - void setBorderSize(float value) { _borderSize = value; } - void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -40,7 +36,6 @@ protected: Transform evalRenderTransform() override; private: - float _borderSize; // edges on a cube std::array _geometryIds; }; diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index 97342a80ab..64acdcccdb 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -99,13 +99,6 @@ void Shape3DOverlay::setProperties(const QVariantMap& properties) { } } } - - auto borderSize = properties["borderSize"]; - - if (borderSize.isValid()) { - float value = borderSize.toFloat(); - setBorderSize(value); - } } /**jsdoc @@ -153,13 +146,8 @@ void Shape3DOverlay::setProperties(const QVariantMap& properties) { * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. * * @property {Shape} shape=Hexagon - The geometrical shape of the overlay. - * @property {number} borderSize - Not used. */ QVariant Shape3DOverlay::getProperty(const QString& property) { - if (property == "borderSize") { - return _borderSize; - } - if (property == "shape") { return shapeStrings[_shape]; } diff --git a/interface/src/ui/overlays/Shape3DOverlay.h b/interface/src/ui/overlays/Shape3DOverlay.h index 7fc95ec981..0196c707d7 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.h +++ b/interface/src/ui/overlays/Shape3DOverlay.h @@ -30,10 +30,6 @@ public: virtual Shape3DOverlay* createClone() const override; - float getBorderSize() const { return _borderSize; } - - void setBorderSize(float value) { _borderSize = value; } - void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -41,7 +37,6 @@ protected: Transform evalRenderTransform() override; private: - float _borderSize; GeometryCache::Shape _shape { GeometryCache::Hexagon }; }; diff --git a/scripts/developer/debugging/queryAACubeInspector.js b/scripts/developer/debugging/queryAACubeInspector.js index 2d585ffce4..d8a87c3cf5 100644 --- a/scripts/developer/debugging/queryAACubeInspector.js +++ b/scripts/developer/debugging/queryAACubeInspector.js @@ -40,7 +40,6 @@ function updateOverlay(entityID, queryAACube) { blue: 255 }, alpha: 1, - // borderSize: ..., solid: false }); } diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index b8ba146757..4133447f97 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -339,8 +339,7 @@ SelectionDisplay = (function() { solid: grabberSolid, visible: false, dashed: false, - drawInFront: true, - borderSize: 1.4 + drawInFront: true }; var grabberPropertiesEdge = { @@ -351,8 +350,7 @@ SelectionDisplay = (function() { solid: grabberSolid, visible: false, dashed: false, - drawInFront: true, - borderSize: 1.4 + drawInFront: true }; var grabberPropertiesFace = { @@ -363,8 +361,7 @@ SelectionDisplay = (function() { solid: grabberSolid, visible: false, dashed: false, - drawInFront: true, - borderSize: 1.4 + drawInFront: true }; var grabberPropertiesCloner = { @@ -375,8 +372,7 @@ SelectionDisplay = (function() { solid: grabberSolid, visible: false, dashed: false, - drawInFront: true, - borderSize: 1.4 + drawInFront: true }; var spotLightLineProperties = { From 42498314f1d783727707a0a8b9b3c54f31580371 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 4 Feb 2018 14:59:06 +1300 Subject: [PATCH 05/54] Remove further unused variable noticed in passing --- interface/src/ui/ApplicationOverlay.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index b36b4f02df..23055cf246 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -42,8 +42,6 @@ private: int _domainStatusBorder; int _magnifierBorder; - ivec2 _previousBorderSize{ -1 }; - gpu::TexturePointer _uiTexture; gpu::TexturePointer _overlayDepthTexture; gpu::TexturePointer _overlayColorTexture; From efddec621f4f98581227285529fec80ebfb986f2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 4 Feb 2018 15:16:20 +1300 Subject: [PATCH 06/54] Remove Menu.addActionGroup() and removeActionGroup() from JavaScript API --- interface/src/Menu.cpp | 1 + .../src/scripting/MenuScriptingInterface.cpp | 16 ---------------- .../src/scripting/MenuScriptingInterface.h | 7 ------- libraries/ui/src/ui/Menu.cpp | 18 ------------------ libraries/ui/src/ui/Menu.h | 3 --- 5 files changed, 1 insertion(+), 44 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f3d8ea2344..464de87fdb 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -210,6 +210,7 @@ Menu::Menu() { auto avatarEntitiesBookmarks = DependencyManager::get(); avatarEntitiesBookmarks->setupMenus(this, avatarMenu); + // Display menu ---------------------------------- // FIXME - this is not yet matching Alan's spec because it doesn't have // menus for "2D"/"3D" - we need to add support for detecting the appropriate diff --git a/interface/src/scripting/MenuScriptingInterface.cpp b/interface/src/scripting/MenuScriptingInterface.cpp index d9372978e8..551cb36e65 100644 --- a/interface/src/scripting/MenuScriptingInterface.cpp +++ b/interface/src/scripting/MenuScriptingInterface.cpp @@ -94,22 +94,6 @@ bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString& return result; } -void MenuScriptingInterface::addActionGroup(const QString& groupName, const QStringList& actionList, - const QString& selected) { - static const char* slot = SLOT(menuItemTriggered()); - QMetaObject::invokeMethod(Menu::getInstance(), "addActionGroup", - Q_ARG(const QString&, groupName), - Q_ARG(const QStringList&, actionList), - Q_ARG(const QString&, selected), - Q_ARG(QObject*, this), - Q_ARG(const char*, slot)); -} - -void MenuScriptingInterface::removeActionGroup(const QString& groupName) { - QMetaObject::invokeMethod(Menu::getInstance(), "removeActionGroup", - Q_ARG(const QString&, groupName)); -} - bool MenuScriptingInterface::isOptionChecked(const QString& menuOption) { if (QThread::currentThread() == qApp->thread()) { return Menu::getInstance()->isOptionChecked(menuOption); diff --git a/interface/src/scripting/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h index 59cfc76d21..b4f6178d33 100644 --- a/interface/src/scripting/MenuScriptingInterface.h +++ b/interface/src/scripting/MenuScriptingInterface.h @@ -163,13 +163,6 @@ public slots: */ bool menuItemExists(const QString& menuName, const QString& menuitem); - /** - * TODO: Not working; don't document until fixed. - */ - void addActionGroup(const QString& groupName, const QStringList& actionList, - const QString& selected = QString()); - void removeActionGroup(const QString& groupName); - /**jsdoc * Check whether a checkable menu item is checked. * @function Menu.isOptionChecked diff --git a/libraries/ui/src/ui/Menu.cpp b/libraries/ui/src/ui/Menu.cpp index 4e61eba28f..577e2564a7 100644 --- a/libraries/ui/src/ui/Menu.cpp +++ b/libraries/ui/src/ui/Menu.cpp @@ -539,24 +539,6 @@ void Menu::setGroupingIsVisible(const QString& grouping, bool isVisible) { QMenuBar::repaint(); } -void Menu::addActionGroup(const QString& groupName, const QStringList& actionList, const QString& selected, QObject* receiver, const char* slot) { - auto menu = addMenu(groupName); - - QActionGroup* actionGroup = new QActionGroup(menu); - actionGroup->setExclusive(true); - - for (auto action : actionList) { - auto item = addCheckableActionToQMenuAndActionHash(menu, action, 0, action == selected, receiver, slot); - actionGroup->addAction(item); - } - - QMenuBar::repaint(); -} - -void Menu::removeActionGroup(const QString& groupName) { - removeMenu(groupName); -} - MenuWrapper::MenuWrapper(ui::Menu& rootMenu, QMenu* menu) : _rootMenu(rootMenu), _realMenu(menu) { auto offscreenUi = DependencyManager::get(); offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { diff --git a/libraries/ui/src/ui/Menu.h b/libraries/ui/src/ui/Menu.h index 25f8f74063..4ca69b44e6 100644 --- a/libraries/ui/src/ui/Menu.h +++ b/libraries/ui/src/ui/Menu.h @@ -110,9 +110,6 @@ public slots: void removeSeparator(const QString& menuName, const QString& separatorName); void removeMenuItem(const QString& menuName, const QString& menuitem); bool menuItemExists(const QString& menuName, const QString& menuitem); - void addActionGroup(const QString& groupName, const QStringList& actionList, const QString& selected = QString(), - QObject* receiver = nullptr, const char* slot = nullptr); - void removeActionGroup(const QString& groupName); bool isOptionChecked(const QString& menuOption) const; void setIsOptionChecked(const QString& menuOption, bool isChecked); From 615e54620b3a0e8da9160a37b956ff012b5943d2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 4 Feb 2018 15:38:33 +1300 Subject: [PATCH 07/54] Remove Menu.isInfoViewVisible() and closeInfoView() from JavaScript API --- .../src/scripting/MenuScriptingInterface.cpp | 16 ---------------- interface/src/scripting/MenuScriptingInterface.h | 6 ------ libraries/ui/src/ui/Menu.cpp | 10 ---------- libraries/ui/src/ui/Menu.h | 3 --- scripts/system/help.js | 10 ---------- 5 files changed, 45 deletions(-) diff --git a/interface/src/scripting/MenuScriptingInterface.cpp b/interface/src/scripting/MenuScriptingInterface.cpp index 551cb36e65..d6dc2fa703 100644 --- a/interface/src/scripting/MenuScriptingInterface.cpp +++ b/interface/src/scripting/MenuScriptingInterface.cpp @@ -131,19 +131,3 @@ void MenuScriptingInterface::setMenuEnabled(const QString& menuOption, bool isCh void MenuScriptingInterface::triggerOption(const QString& menuOption) { QMetaObject::invokeMethod(Menu::getInstance(), "triggerOption", Q_ARG(const QString&, menuOption)); } - -void MenuScriptingInterface::closeInfoView(const QString& path) { - QMetaObject::invokeMethod(Menu::getInstance(), "closeInfoView", Q_ARG(const QString&, path)); -} - -bool MenuScriptingInterface::isInfoViewVisible(const QString& path) { - if (QThread::currentThread() == qApp->thread()) { - return Menu::getInstance()->isInfoViewVisible(path); - } - - bool result; - BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isInfoViewVisible", - Q_RETURN_ARG(bool, result), Q_ARG(const QString&, path)); - return result; -} - diff --git a/interface/src/scripting/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h index b4f6178d33..649c444eaf 100644 --- a/interface/src/scripting/MenuScriptingInterface.h +++ b/interface/src/scripting/MenuScriptingInterface.h @@ -215,12 +215,6 @@ public slots: */ void setMenuEnabled(const QString& menuName, bool isEnabled); - /** - * TODO: Not used or useful; will not document until used. - */ - void closeInfoView(const QString& path); - bool isInfoViewVisible(const QString& path); - signals: /**jsdoc * Triggered when a menu item is clicked (or triggered by {@link Menu.triggerOption}). diff --git a/libraries/ui/src/ui/Menu.cpp b/libraries/ui/src/ui/Menu.cpp index 577e2564a7..d4566dc151 100644 --- a/libraries/ui/src/ui/Menu.cpp +++ b/libraries/ui/src/ui/Menu.cpp @@ -268,16 +268,6 @@ bool Menu::isOptionChecked(const QString& menuOption) const { return false; } -void Menu::closeInfoView(const QString& path) { - auto offscreenUi = DependencyManager::get(); - offscreenUi->hide(path); -} - -bool Menu::isInfoViewVisible(const QString& path) { - auto offscreenUi = DependencyManager::get(); - return offscreenUi->isVisible(path); -} - void Menu::triggerOption(const QString& menuOption) { QAction* action = _actionHash.value(menuOption); if (action) { diff --git a/libraries/ui/src/ui/Menu.h b/libraries/ui/src/ui/Menu.h index 4ca69b44e6..2977a5330a 100644 --- a/libraries/ui/src/ui/Menu.h +++ b/libraries/ui/src/ui/Menu.h @@ -122,9 +122,6 @@ public slots: void toggleDeveloperMenus(); void toggleAdvancedMenus(); - bool isInfoViewVisible(const QString& path); - void closeInfoView(const QString& path); - void triggerOption(const QString& menuOption); static bool isSomeSubmenuShown() { return _isSomeSubmenuShown; } diff --git a/scripts/system/help.js b/scripts/system/help.js index 9ab7fa3fb3..494b0a2cdb 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -47,22 +47,12 @@ button.clicked.connect(onClicked); tablet.screenChanged.connect(onScreenChanged); - var POLL_RATE = 500; - var interval = Script.setInterval(function () { - var visible = Menu.isInfoViewVisible('InfoView_html/help.html'); - if (visible !== enabled) { - enabled = visible; - button.editProperties({isActive: enabled}); - } - }, POLL_RATE); - Script.scriptEnding.connect(function () { if (onHelpScreen) { tablet.gotoHomeScreen(); } button.clicked.disconnect(onClicked); tablet.screenChanged.disconnect(onScreenChanged); - Script.clearInterval(interval); if (tablet) { tablet.removeButton(button); } From e3f9cce6e6a3548c917f909b473f3bbb9bcfe105 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 6 Feb 2018 12:14:33 +1300 Subject: [PATCH 08/54] Fix Record app dialog not always opening successfully --- .../marketplace/record/html/js/record.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/unpublishedScripts/marketplace/record/html/js/record.js b/unpublishedScripts/marketplace/record/html/js/record.js index aae4d1c89a..39278e9d7e 100644 --- a/unpublishedScripts/marketplace/record/html/js/record.js +++ b/unpublishedScripts/marketplace/record/html/js/record.js @@ -252,16 +252,17 @@ function onFinishOnOpenClicked() { } function signalBodyLoaded() { - EventBridge.emitWebEvent(JSON.stringify({ - type: EVENT_BRIDGE_TYPE, - action: BODY_LOADED_ACTION - })); + var EVENTBRIDGE_OPEN_DELAY = 500; // Delay required to ensure EventBridge is ready for use. + setTimeout(function () { + EventBridge.scriptEventReceived.connect(onScriptEventReceived); + EventBridge.emitWebEvent(JSON.stringify({ + type: EVENT_BRIDGE_TYPE, + action: BODY_LOADED_ACTION + })); + }, EVENTBRIDGE_OPEN_DELAY); } function onBodyLoaded() { - - EventBridge.scriptEventReceived.connect(onScriptEventReceived); - elRecordings = document.getElementById("recordings"); elRecordingsTable = document.getElementById("recordings-table"); From 7f6471fcd189ad04feaa3cec153583bb3752df69 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 6 Feb 2018 13:24:41 +1300 Subject: [PATCH 09/54] Fix recording just made not being automatically played back --- unpublishedScripts/marketplace/record/record.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unpublishedScripts/marketplace/record/record.js b/unpublishedScripts/marketplace/record/record.js index 68c7ea3f5a..dda78dbd02 100644 --- a/unpublishedScripts/marketplace/record/record.js +++ b/unpublishedScripts/marketplace/record/record.js @@ -139,7 +139,8 @@ } function setMappingCallback(status) { - if (status !== "") { + // FIXME: "" is for RC < 63, null is for RC >= 63. Remove the former when RC63 is no longer used. + if (status !== "" && status !== null) { error("Error mapping recording to " + mappingPath + " on Asset Server!", status); return; } From 75cf22ca7fe7bab1c59ca08d4d99bccf0eba9cf6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 7 Feb 2018 09:45:21 +1300 Subject: [PATCH 10/54] Remove support for old High Fidelity versions --- unpublishedScripts/marketplace/record/record.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/unpublishedScripts/marketplace/record/record.js b/unpublishedScripts/marketplace/record/record.js index dda78dbd02..08400dbb85 100644 --- a/unpublishedScripts/marketplace/record/record.js +++ b/unpublishedScripts/marketplace/record/record.js @@ -139,8 +139,7 @@ } function setMappingCallback(status) { - // FIXME: "" is for RC < 63, null is for RC >= 63. Remove the former when RC63 is no longer used. - if (status !== "" && status !== null) { + if (status !== null) { error("Error mapping recording to " + mappingPath + " on Asset Server!", status); return; } From adb6f66a05a7ce4d9181712e5c24b8222983e70b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 8 Feb 2018 09:51:48 +1300 Subject: [PATCH 11/54] Handle tablet entities and overlays not being available --- scripts/system/audio.js | 5 +++-- .../system/controllers/controllerDispatcher.js | 2 +- .../controllers/controllerModules/inEditMode.js | 7 ++++--- .../controllerModules/inVREditMode.js | 5 +++-- .../controllerModules/nearParentGrabOverlay.js | 4 ++-- .../controllers/controllerModules/stylusInput.js | 4 ++-- scripts/system/controllers/grab.js | 5 ++++- scripts/system/edit.js | 8 ++++---- scripts/system/help.js | 5 ++--- scripts/system/libraries/WebTablet.js | 5 ++++- scripts/system/libraries/entitySelectionTool.js | 11 ++++++++--- scripts/system/libraries/utils.js | 14 ++++++++++++++ scripts/system/marketplaces/marketplaces.js | 5 +++-- scripts/system/menu.js | 5 +++-- scripts/system/tablet-ui/tabletUI.js | 16 ++++++++-------- scripts/system/tablet-users.js | 5 ++--- .../marketplace/shapes/modules/laser.js | 12 +++++++++++- 17 files changed, 78 insertions(+), 40 deletions(-) diff --git a/scripts/system/audio.js b/scripts/system/audio.js index a93177ca38..ee82c0c6ea 100644 --- a/scripts/system/audio.js +++ b/scripts/system/audio.js @@ -42,8 +42,9 @@ function onClicked() { // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); } else { - var entity = HMD.tabletID; - Entities.editEntity(entity, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) }); + if (HMD.tabletID) { + Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) }); + } tablet.loadQMLSource(AUDIO_QML_SOURCE); } } diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 16f1d086b7..b2455b3f5a 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -146,7 +146,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; this.setIgnorePointerItems = function() { - if (HMD.tabletID !== this.tabletID) { + if (HMD.tabletID && HMD.tabletID !== this.tabletID) { this.tabletID = HMD.tabletID; Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist); Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist); diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index 763258573d..202290f2df 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -32,7 +32,7 @@ Script.include("/~/system/libraries/utils.js"); this.nearTablet = function(overlays) { for (var i = 0; i < overlays.length; i++) { - if (overlays[i] === HMD.tabletID) { + if (HMD.tabletID && overlays[i] === HMD.tabletID) { return true; } } @@ -44,7 +44,8 @@ Script.include("/~/system/libraries/utils.js"); }; this.pointingAtTablet = function(objectID) { - return objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID; + return (HMD.tabletScreenID && objectID === HMD.tabletScreenID) + || (HMD.homeButtonID && objectID === HMD.homeButtonID); }; this.sendPickData = function(controllerData) { @@ -106,7 +107,7 @@ Script.include("/~/system/libraries/utils.js"); if (nearOverlay) { var nearOverlayReady = nearOverlay.isReady(controllerData); - if (nearOverlayReady.active && nearOverlay.grabbedThingID === HMD.tabletID) { + if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) { return this.exitModule(); } } diff --git a/scripts/system/controllers/controllerModules/inVREditMode.js b/scripts/system/controllers/controllerModules/inVREditMode.js index 38eca65dd3..7b78d5e1c4 100644 --- a/scripts/system/controllers/controllerModules/inVREditMode.js +++ b/scripts/system/controllers/controllerModules/inVREditMode.js @@ -31,7 +31,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); ); this.pointingAtTablet = function (objectID) { - return objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID; + return (HMD.tabletScreenID && objectID === HMD.tabletScreenID) + || (HMD.homeButtonID && objectID === HMD.homeButtonID); }; this.isReady = function (controllerData) { @@ -76,7 +77,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); : "LeftNearParentingGrabOverlay"); if (nearOverlay) { var nearOverlayReady = nearOverlay.isReady(controllerData); - if (nearOverlayReady.active && nearOverlay.grabbedThingID === HMD.tabletID) { + if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) { return makeRunningValues(false, [], []); } } diff --git a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js index fa0fe31de2..0f876816b3 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js @@ -117,7 +117,7 @@ Script.include("/~/system/libraries/utils.js"); Overlays.editOverlay(this.grabbedThingID, reparentProps); // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix - if (this.grabbedThingID === HMD.tabletID) { + if (HMD.tabletID && this.grabbedThingID === HMD.tabletID) { resizeTablet(getTabletWidthFromSettings(), reparentProps.parentJointIndex); } @@ -143,7 +143,7 @@ Script.include("/~/system/libraries/utils.js"); }); // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix - if (this.grabbedThingID === HMD.tabletID) { + if (HMD.tabletID && this.grabbedThingID === HMD.tabletID) { resizeTablet(getTabletWidthFromSettings(), this.previousParentJointIndex[this.grabbedThingID]); } } diff --git a/scripts/system/controllers/controllerModules/stylusInput.js b/scripts/system/controllers/controllerModules/stylusInput.js index aa65135289..a512fd89db 100644 --- a/scripts/system/controllers/controllerModules/stylusInput.js +++ b/scripts/system/controllers/controllerModules/stylusInput.js @@ -20,7 +20,7 @@ Script.include("/~/system/libraries/controllers.js"); var stylusTargetIDs = []; for (var index = 0; index < stylusTargets.length; index++) { var stylusTarget = stylusTargets[index]; - if (stylusTarget.distance <= maxNormalDistance && stylusTarget.id !== HMD.tabletID) { + if (stylusTarget.distance <= maxNormalDistance && !(HMD.tabletID && stylusTarget.id === HMD.tabletID)) { stylusTargetIDs.push(stylusTarget.id); } } @@ -96,7 +96,7 @@ Script.include("/~/system/libraries/controllers.js"); var i, stylusTarget; for (i = 0; i < candidateOverlays.length; i++) { - if (candidateOverlays[i] !== HMD.tabletID && + if (!(HMD.tabletID && candidateOverlays[i] === HMD.tabletID) && Overlays.getProperty(candidateOverlays[i], "visible")) { stylusTarget = getOverlayDistance(controllerPosition, candidateOverlays[i]); if (stylusTarget) { diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index a51cea67f8..b62cb3dd90 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -263,7 +263,10 @@ function Grabber() { filter: Picks.PICK_OVERLAYS, enabled: true }); - RayPick.setIncludeItems(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]); + var tabletItems = getMainTabletIDs(); + if (tabletItems.length > 0) { + RayPick.setIncludeItems(this.mouseRayOverlays, tabletItems); + } var renderStates = [{name: "grabbed", end: beacon}]; this.mouseRayEntities = Pointers.createPointer(PickType.Ray, { joint: "Mouse", diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 863c185cb4..42c1cc4b51 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -31,6 +31,7 @@ Script.include([ "libraries/entityCameraTool.js", "libraries/gridTool.js", "libraries/entityList.js", + "libraries/utils.js", "particle_explorer/particleExplorerTool.js", "libraries/entityIconOverlayManager.js" ]); @@ -733,8 +734,7 @@ function findClickedEntity(event) { } var pickRay = Camera.computePickRay(event.x, event.y); - - var overlayResult = Overlays.findRayIntersection(pickRay, true, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]); + var overlayResult = Overlays.findRayIntersection(pickRay, true, getMainTabletIDs()); if (overlayResult.intersects) { return null; } @@ -922,7 +922,7 @@ function mouseReleaseEvent(event) { function wasTabletClicked(event) { var rayPick = Camera.computePickRay(event.x, event.y); - var result = Overlays.findRayIntersection(rayPick, true, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]); + var result = Overlays.findRayIntersection(rayPick, true, getMainTabletIDs()); return result.intersects; } @@ -945,7 +945,7 @@ function mouseClickEvent(event) { toolBar.setActive(true); var pickRay = result.pickRay; var foundEntity = result.entityID; - if (foundEntity === HMD.tabletID) { + if (HMD.tabletID && foundEntity === HMD.tabletID) { return; } properties = Entities.getEntityProperties(foundEntity); diff --git a/scripts/system/help.js b/scripts/system/help.js index 9ab7fa3fb3..6fe0da8a86 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -30,9 +30,8 @@ if (onHelpScreen) { tablet.gotoHomeScreen(); } else { - var tabletEntity = HMD.tabletID; - if (tabletEntity) { - Entities.editEntity(tabletEntity, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})}); + if (HMD.tabletID) { + Entities.editEntity(HMD.tabletID, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})}); } Menu.triggerOption('Help...'); onHelpScreen = true; diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 05b4963280..c4ad2b43a7 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -334,7 +334,7 @@ WebTablet.prototype.destroy = function () { }; WebTablet.prototype.geometryChanged = function (geometry) { - if (!HMD.active) { + if (!HMD.active && HMD.tabletID) { var tabletProperties = {}; // compute position, rotation & parentJointIndex of the tablet this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties); @@ -462,6 +462,9 @@ WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMou }; WebTablet.prototype.onHmdChanged = function () { + if (!HMD.tabletID) { + return; + } var tabletProperties = {}; // compute position, rotation & parentJointIndex of the tablet this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties); diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index b8ba146757..eea541a430 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -19,7 +19,10 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; SPACE_LOCAL = "local"; SPACE_WORLD = "world"; -Script.include("./controllers.js"); +Script.include([ + "./controllers.js", + "./utils.js" +]); function objectTranslationPlanePoint(position, dimensions) { var newPosition = { x: position.x, y: position.y, z: position.z }; @@ -3650,7 +3653,8 @@ SelectionDisplay = (function() { var pickRay = generalComputePickRay(event.x, event.y); // TODO_Case6491: Move this out to setup just to make it once - var interactiveOverlays = [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, selectionBox]; + var interactiveOverlays = getMainTabletIDs(); + interactiveOverlays.push(selectionBox); for (var key in grabberTools) { if (grabberTools.hasOwnProperty(key)) { interactiveOverlays.push(key); @@ -3663,7 +3667,8 @@ SelectionDisplay = (function() { var results = testRayIntersect(pickRay, interactiveOverlays); if (results.intersects) { var hitOverlayID = results.overlayID; - if ((hitOverlayID === HMD.tabletID) || (hitOverlayID === HMD.tabletScreenID) || (hitOverlayID === HMD.homeButtonID)) { + if ((HMD.tabletID && hitOverlayID === HMD.tabletID) || (HMD.tabletScreenID && hitOverlayID === HMD.tabletScreenID) + || (HMD.homeButtonID && hitOverlayID === HMD.homeButtonID)) { // EARLY EXIT-(mouse clicks on the tablet should override the edit affordances) return false; } diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js index bc83cc582c..442a9f6d24 100644 --- a/scripts/system/libraries/utils.js +++ b/scripts/system/libraries/utils.js @@ -428,3 +428,17 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride) dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim } }); }; + +getMainTabletIDs = function () { + var tabletIDs = []; + if (HMD.tabletID) { + tabletIDs.push(HMD.tabletID); + } + if (HMD.tabletScreenID) { + tabletIDs.push(HMD.tabletScreenID); + } + if (HMD.homeButtonID) { + tabletIDs.push(HMD.homeButtonID); + } + return tabletIDs; +}; \ No newline at end of file diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index facb932eb0..5d905f7553 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -104,8 +104,9 @@ var selectionDisplay = null; // for gridTool.js to ignore tablet.gotoHomeScreen(); } else { Wallet.refreshWalletStatus(); - var entity = HMD.tabletID; - Entities.editEntity(entity, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) }); + if (HMD.tabletID) { + Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) }); + } showMarketplace(); } } diff --git a/scripts/system/menu.js b/scripts/system/menu.js index c7a44d3e48..c27dae6780 100644 --- a/scripts/system/menu.js +++ b/scripts/system/menu.js @@ -28,8 +28,9 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet- // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); } else { - var entity = HMD.tabletID; - Entities.editEntity(entity, {textures: JSON.stringify({"tex.close": HOME_BUTTON_TEXTURE})}); + if (HMD.tabletID) { + Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) }); + } tablet.gotoMenuScreen(); } } diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 36a1cbcdd9..100d0e82ee 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -41,14 +41,14 @@ if (!UIWebTablet) { return false; } - if (Overlays.getProperty(HMD.tabletID, "type") != "model") { + if (Overlays.getProperty(HMD.tabletID, "type") !== "model") { if (debugTablet) { print("TABLET is invalid due to frame: " + JSON.stringify(Overlays.getProperty(HMD.tabletID, "type"))); } return false; } - if (Overlays.getProperty(HMD.homeButtonID, "type") != "circle3d" || - Overlays.getProperty(HMD.tabletScreenID, "type") != "web3d") { + if (Overlays.getProperty(HMD.homeButtonID, "type") !== "circle3d" || + Overlays.getProperty(HMD.tabletScreenID, "type") !== "web3d") { if (debugTablet) { print("TABLET is invalid due to other"); } @@ -112,7 +112,7 @@ } function showTabletUI() { - checkTablet() + checkTablet(); if (!tabletRezzed || !tabletIsValid()) { closeTabletUI(); @@ -157,7 +157,7 @@ } function closeTabletUI() { - checkTablet() + checkTablet(); gTablet.tabletShown = false; if (UIWebTablet) { if (UIWebTablet.onClose) { @@ -178,14 +178,14 @@ print("TABLET closeTabletUI, UIWebTablet is null"); } tabletRezzed = false; - gTablet = null + gTablet = null; } function updateShowTablet() { var now = Date.now(); - checkTablet() + checkTablet(); // close the WebTablet if it we go into toolbar mode. var tabletShown = gTablet.tabletShown; @@ -270,7 +270,7 @@ } if (channel === "home") { if (UIWebTablet) { - checkTablet() + checkTablet(); gTablet.landscape = false; } } diff --git a/scripts/system/tablet-users.js b/scripts/system/tablet-users.js index 6181173818..92aefd1e80 100644 --- a/scripts/system/tablet-users.js +++ b/scripts/system/tablet-users.js @@ -48,9 +48,8 @@ // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); } else { - var tabletEntity = HMD.tabletID; - if (tabletEntity) { - Entities.editEntity(tabletEntity, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})}); + if (HMD.tabletID) { + Entities.editEntity(HMD.tabletID, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})}); } shouldActivateButton = true; tablet.gotoWebScreen(USERS_URL); diff --git a/unpublishedScripts/marketplace/shapes/modules/laser.js b/unpublishedScripts/marketplace/shapes/modules/laser.js index d5feda0e1f..067b605047 100644 --- a/unpublishedScripts/marketplace/shapes/modules/laser.js +++ b/unpublishedScripts/marketplace/shapes/modules/laser.js @@ -173,8 +173,18 @@ Laser = function (side) { // Normal laser operation with trigger. intersection = Overlays.findRayIntersection(pickRay, PRECISION_PICKING, NO_INCLUDE_IDS, NO_EXCLUDE_IDS, VISIBLE_ONLY); + var tabletIDs = []; + if (HMD.tabletID) { + tabletIDs.push(HMD.tabletID); + } + if (HMD.tabletScreenID) { + tabletIDs.push(HMD.tabletScreenID); + } + if (HMD.homeButtonID) { + tabletIDs.push(HMD.homeButtonID); + } if (Reticle.pointingAtSystemOverlay || (intersection.overlayID - && [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID].indexOf(intersection.overlayID) !== -1)) { + && tabletIDs.indexOf(intersection.overlayID) !== -1)) { // No laser if pointing at HUD overlay or tablet; system provides lasers for these cases. if (isLaserOn) { isLaserOn = false; From 2fc954909bf8b721f5aecbfa26aa37494da6409a Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Tue, 23 Jan 2018 14:41:46 -0500 Subject: [PATCH 12/54] [Case 4315] Fixes black color preview for color pickers (details below). The original/starting color preview in the picker was black as opposed to reflecting the entity's color upon clicking the color picker. Known Issue(s)/TODO(s): * Color preview restore color functionality isn't working. * Clicking the initial color preview doesn't restore the color. * The original color preview isn't being visually retained when the user changes the color via the picker. Tested HMD & Desktop Modes. Changes Committed: modified: scripts/system/html/js/entityProperties.js --- scripts/system/html/js/entityProperties.js | 94 +++++++++++++++++----- 1 file changed, 74 insertions(+), 20 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 7008d0df66..be9bba5f0d 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -29,7 +29,7 @@ var ICON_FOR_TYPE = { var EDITOR_TIMEOUT_DURATION = 1500; var KEY_P = 80; // Key code for letter p used for Parenting hotkey. -var colorPickers = []; +var colorPickers = {}; var lastEntityID = null; function debugPrint(message) { @@ -69,8 +69,8 @@ function enableProperties() { function disableProperties() { disableChildren(document.getElementById("properties-list"), "input, textarea, checkbox, .dropdown dl, .color-picker"); disableChildren(document, ".colpick"); - for (var i = 0; i < colorPickers.length; i++) { - colorPickers[i].colpickHide(); + for (var pickKey in colorPickers) { + colorPickers[pickKey].colpickHide(); } var elLocked = document.getElementById("property-locked"); @@ -83,7 +83,6 @@ function disableProperties() { function showElements(els, show) { for (var i = 0; i < els.length; i++) { els[i].style.display = (show) ? 'table' : 'none'; - } } @@ -1304,13 +1303,19 @@ function loaded() { elColorRed.addEventListener('change', colorChangeFunction); elColorGreen.addEventListener('change', colorChangeFunction); elColorBlue.addEventListener('change', colorChangeFunction); - colorPickers.push($('#property-color-control2').colpick({ + colorPickers['#property-color-control2'] = $('#property-color-control2').colpick({ 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'); + // The original color preview within the picker needs to be updated on show because + // prior to the picker being shown we don't have access to the selections' starting color. + colorPickers['#property-color-control2'].colpickSetColor({ + "r": elColorRed.value, + "g": elColorGreen.value, + "b": elColorBlue.value}); }, onHide: function(colpick) { $('#property-color-control2').attr('active', 'false'); @@ -1319,7 +1324,7 @@ function loaded() { $(el).css('background-color', '#' + hex); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); } - })); + }); elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight')); @@ -1328,13 +1333,20 @@ function loaded() { elLightColorRed.addEventListener('change', lightColorChangeFunction); elLightColorGreen.addEventListener('change', lightColorChangeFunction); elLightColorBlue.addEventListener('change', lightColorChangeFunction); - colorPickers.push($('#property-light-color').colpick({ + colorPickers['#property-light-color'] = $('#property-light-color').colpick({ 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'); + // The original color preview within the picker needs to be updated on show because + // prior to the picker being shown we don't have access to the selections' starting color. + colorPickers['#property-light-color'].colpickSetColor({ + "r": elLightColorRed.value, + "g": elLightColorGreen.value, + "b": elLightColorBlue.value + }); }, onHide: function(colpick) { $('#property-light-color').attr('active', 'false'); @@ -1343,7 +1355,7 @@ function loaded() { $(el).css('background-color', '#' + hex); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); } - })); + }); elLightIntensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('intensity', 1)); elLightFalloffRadius.addEventListener('change', createEmitNumberPropertyUpdateFunction('falloffRadius', 1)); @@ -1383,13 +1395,20 @@ function loaded() { elTextTextColorRed.addEventListener('change', textTextColorChangeFunction); elTextTextColorGreen.addEventListener('change', textTextColorChangeFunction); elTextTextColorBlue.addEventListener('change', textTextColorChangeFunction); - colorPickers.push($('#property-text-text-color').colpick({ + colorPickers['#property-text-text-color'] = $('#property-text-text-color').colpick({ 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'); + // The original color preview within the picker needs to be updated on show because + // prior to the picker being shown we don't have access to the selections' starting color. + colorPickers['#property-text-text-color'].colpickSetColor({ + "r": elTextTextColorRed.value, + "g": elTextTextColorGreen.value, + "b": elTextTextColorBlue.value + }); }, onHide: function(colpick) { $('#property-text-text-color').attr('active', 'false'); @@ -1399,7 +1418,7 @@ function loaded() { $(el).attr('active', 'false'); emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b); } - })); + }); var textBackgroundColorChangeFunction = createEmitColorPropertyUpdateFunction( 'backgroundColor', elTextBackgroundColorRed, elTextBackgroundColorGreen, elTextBackgroundColorBlue); @@ -1407,13 +1426,20 @@ function loaded() { elTextBackgroundColorRed.addEventListener('change', textBackgroundColorChangeFunction); elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction); elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction); - colorPickers.push($('#property-text-background-color').colpick({ + colorPickers['#property-text-background-color'] = $('#property-text-background-color').colpick({ 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'); + // The original color preview within the picker needs to be updated on show because + // prior to the picker being shown we don't have access to the selections' starting color. + colorPickers['#property-text-background-color'].colpickSetColor({ + "r": elTextBackgroundColorRed.value, + "g": elTextBackgroundColorGreen.value, + "b": elTextBackgroundColorBlue.value + }); }, onHide: function(colpick) { $('#property-text-background-color').attr('active', 'false'); @@ -1422,7 +1448,7 @@ function loaded() { $(el).css('background-color', '#' + hex); emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b); } - })); + }); // Key light var keyLightModeChanged = createZoneComponentModeChangedFunction('keyLightMode', @@ -1432,13 +1458,20 @@ function loaded() { elZoneKeyLightModeDisabled.addEventListener('change', keyLightModeChanged); elZoneKeyLightModeEnabled.addEventListener('change', keyLightModeChanged); - colorPickers.push($('#property-zone-key-light-color').colpick({ + colorPickers['#property-zone-key-light-color'] = $('#property-zone-key-light-color').colpick({ 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'); + // The original color preview within the picker needs to be updated on show because + // prior to the picker being shown we don't have access to the selections' starting color. + colorPickers['#property-zone-key-light-color'].colpickSetColor({ + "r": elZoneKeyLightColorRed.value, + "g": elZoneKeyLightColorGreen.value, + "b": elZoneKeyLightColorBlue.value + }); }, onHide: function(colpick) { $('#property-zone-key-light-color').attr('active', 'false'); @@ -1447,7 +1480,7 @@ function loaded() { $(el).css('background-color', '#' + hex); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'keyLight'); } - })); + }); var zoneKeyLightColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('keyLight', 'color', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue); @@ -1501,13 +1534,20 @@ function loaded() { elZoneHazeRange.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeRange')); - colorPickers.push($('#property-zone-haze-color').colpick({ + colorPickers['#property-zone-haze-color'] = $('#property-zone-haze-color').colpick({ 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'); + // The original color preview within the picker needs to be updated on show because + // prior to the picker being shown we don't have access to the selections' starting color. + colorPickers['#property-zone-haze-color'].colpickSetColor({ + "r": elZoneHazeColorRed.value, + "g": elZoneHazeColorGreen.value, + "b": elZoneHazeColorBlue.value + }); }, onHide: function(colpick) { $('#property-zone-haze-color').attr('active', 'false'); @@ -1516,7 +1556,7 @@ function loaded() { $(el).css('background-color', '#' + hex); emitColorPropertyUpdate('hazeColor', rgb.r, rgb.g, rgb.b, 'haze'); } - })); + }); var zoneHazeColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('haze', 'hazeColor', elZoneHazeColorRed, elZoneHazeColorGreen, @@ -1526,13 +1566,20 @@ function loaded() { elZoneHazeColorGreen.addEventListener('change', zoneHazeColorChangeFunction); elZoneHazeColorBlue.addEventListener('change', zoneHazeColorChangeFunction); - colorPickers.push($('#property-zone-haze-glare-color').colpick({ + colorPickers['#property-zone-haze-glare-color'] = $('#property-zone-haze-glare-color').colpick({ 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'); + // The original color preview within the picker needs to be updated on show because + // prior to the picker being shown we don't have access to the selections' starting color. + colorPickers['#property-zone-haze-glare-color'].colpickSetColor({ + "r": elZoneHazeGlareColorRed.value, + "g": elZoneHazeGlareColorGreen.value, + "b": elZoneHazeGlareColorBlue.value + }); }, onHide: function(colpick) { $('#property-zone-haze-glare-color').attr('active', 'false'); @@ -1541,7 +1588,7 @@ function loaded() { $(el).css('background-color', '#' + hex); emitColorPropertyUpdate('hazeGlareColor', rgb.r, rgb.g, rgb.b, 'haze'); } - })); + }); var zoneHazeGlareColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('haze', 'hazeGlareColor', elZoneHazeGlareColorRed, elZoneHazeGlareColorGreen, @@ -1568,13 +1615,20 @@ function loaded() { elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction); elZoneSkyboxColorGreen.addEventListener('change', zoneSkyboxColorChangeFunction); elZoneSkyboxColorBlue.addEventListener('change', zoneSkyboxColorChangeFunction); - colorPickers.push($('#property-zone-skybox-color').colpick({ + colorPickers['#property-zone-skybox-color'] = $('#property-zone-skybox-color').colpick({ 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'); + // The original color preview within the picker needs to be updated on show because + // prior to the picker being shown we don't have access to the selections' starting color. + colorPickers['#property-zone-skybox-color'].colpickSetColor({ + "r": elZoneSkyboxColorRed.value, + "g": elZoneSkyboxColorGreen.value, + "b": elZoneSkyboxColorBlue.value + }); }, onHide: function(colpick) { $('#property-zone-skybox-color').attr('active', 'false'); @@ -1583,7 +1637,7 @@ function loaded() { $(el).css('background-color', '#' + hex); emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox'); } - })); + }); elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox', 'url')); From 6c5961820ca208f7e1396f555e9a3681281ba1fa Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Tue, 23 Jan 2018 15:12:53 -0500 Subject: [PATCH 13/54] [Case 4315] Fixes Color Picker preview restore functionality (details below). * The original color preview is now visually retained when the user changes the color via the picker when using the Non-Submit configuration (No OK button). * Clicking the initial old color preview section restores the original/initial color of the object. Tested Desktop & HMD Modes. Changes Committed: modified: scripts/system/html/css/colpick.css modified: scripts/system/html/js/colpick.js --- scripts/system/html/css/colpick.css | 8 ++++---- scripts/system/html/js/colpick.js | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/css/colpick.css b/scripts/system/html/css/colpick.css index 98417a5e9a..fc50c4b3fb 100644 --- a/scripts/system/html/css/colpick.css +++ b/scripts/system/html/css/colpick.css @@ -279,7 +279,7 @@ colpick Color Picker / colpick.com } /*full layout with no submit button*/ -.colpick_full_ns .colpick_submit, .colpick_full_ns .colpick_current_color{ +.colpick_full_ns .colpick_submit { display:none; } .colpick_full_ns .colpick_new_color { @@ -320,11 +320,11 @@ colpick Color Picker / colpick.com } /*rgbhex layout, no submit button*/ -.colpick_rgbhex_ns .colpick_submit, .colpick_rgbhex_ns .colpick_current_color{ +.colpick_rgbhex_ns .colpick_submit { display:none; } .colpick_rgbhex_ns .colpick_new_color{ - width:68px; + width:34px; border: 1px solid #8f8f8f; } .colpick_rgbhex_ns .colpick_rgb_r { @@ -379,7 +379,7 @@ colpick Color Picker / colpick.com } /*hex layout, no submit button*/ -.colpick_hex_ns .colpick_submit, .colpick_hex_ns .colpick_current_color { +.colpick_hex_ns .colpick_submit { display:none; } .colpick_hex_ns .colpick_hex_field { diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index f808262e9e..99054c6103 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -302,6 +302,9 @@ For usage and examples: colpick.com/plugin setSelector(col, cal.get(0)); setHue(col, cal.get(0)); setNewColor(col, cal.get(0)); + // If the user triggered this behavior, then any prior color change should be negated. + cal.data('colpick').onChange.apply(cal.parent(), [col, hsbToHex(col), + hsbToRgb(col), cal.data('colpick').el, 0]); }; return { init: function (opt) { From 35bf8f1d01f6b1bb8172eb887cf354e08afa7558 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 9 Feb 2018 16:24:54 -0500 Subject: [PATCH 14/54] [Case 4315] ESLint Pass; Simple errors addressed (details below). Initial ESLint Pass on colpick.js. Issue Count reduced from 185 to 100 via: eslint -c .eslintrc.js scripts/system/html/js/colpick.js --fix Changes Committed: modified: scripts/system/html/js/colpick.js --- scripts/system/html/js/colpick.js | 149 +++++++++++++++++------------- 1 file changed, 85 insertions(+), 64 deletions(-) diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index 99054c6103..b19cbe0bae 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -25,15 +25,15 @@ For usage and examples: colpick.com/plugin submitText: 'OK', height: 156 }, - //Fill the inputs of the plugin - fillRGBFields = function (hsb, cal) { + // Fill the inputs of the plugin + fillRGBFields = function (hsb, cal) { var rgb = hsbToRgb(hsb); $(cal).data('colpick').fields .eq(1).val(rgb.r).end() .eq(2).val(rgb.g).end() .eq(3).val(rgb.b).end(); }, - fillHSBFields = function (hsb, cal) { + fillHSBFields = function (hsb, cal) { $(cal).data('colpick').fields .eq(4).val(Math.round(hsb.h)).end() .eq(5).val(Math.round(hsb.s)).end() @@ -42,7 +42,7 @@ For usage and examples: colpick.com/plugin fillHexFields = function (hsb, cal) { $(cal).data('colpick').fields.eq(0).val(hsbToHex(hsb)); }, - //Set the round selector position + // Set the round selector position setSelector = function (hsb, cal) { $(cal).data('colpick').selector.css('backgroundColor', '#' + hsbToHex({h: hsb.h, s: 100, b: 100})); $(cal).data('colpick').selectorIndic.css({ @@ -50,18 +50,18 @@ For usage and examples: colpick.com/plugin top: parseInt($(cal).data('colpick').height * (100-hsb.b)/100, 10) }); }, - //Set the hue selector position + // Set the hue selector position setHue = function (hsb, cal) { $(cal).data('colpick').hue.css('top', parseInt($(cal).data('colpick').height - $(cal).data('colpick').height * hsb.h/360, 10)); }, - //Set current and new colors + // Set current and new colors setCurrentColor = function (hsb, cal) { $(cal).data('colpick').currentColor.css('backgroundColor', '#' + hsbToHex(hsb)); }, setNewColor = function (hsb, cal) { $(cal).data('colpick').newColor.css('backgroundColor', '#' + hsbToHex(hsb)); }, - //Called when the new color is changed + // Called when the new color is changed change = function (ev) { var cal = $(this).parent().parent(), col; if (this.parentNode.className.indexOf('_hex') > 0) { @@ -93,7 +93,7 @@ For usage and examples: colpick.com/plugin setNewColor(col, cal.get(0)); cal.data('colpick').onChange.apply(cal.parent(), [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 0]); }, - //Change style on blur and on focus of inputs + // Change style on blur and on focus of inputs blur = function (ev) { $(this).parent().removeClass('colpick_focus'); }, @@ -101,7 +101,7 @@ For usage and examples: colpick.com/plugin $(this).parent().parent().data('colpick').fields.parent().removeClass('colpick_focus'); $(this).parent().addClass('colpick_focus'); }, - //Increment/decrement arrows functions + // Increment/decrement arrows functions downIncrement = function (ev) { ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; var field = $(this).parent().find('input').focus(); @@ -130,7 +130,7 @@ For usage and examples: colpick.com/plugin $(document).off('mousemove', moveIncrement); return false; }, - //Hue slider functions + // Hue slider functions downHue = function (ev) { ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; var current = { @@ -143,7 +143,7 @@ For usage and examples: colpick.com/plugin var pageY = ((ev.type == 'touchstart') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); change.apply( current.cal.data('colpick') - .fields.eq(4).val(parseInt(360*(current.cal.data('colpick').height - (pageY - current.y))/current.cal.data('colpick').height, 10)) + .fields.eq(4).val(parseInt(360*(current.cal.data('colpick').height - (pageY - current.y))/current.cal.data('colpick').height, 10)) .get(0), [current.cal.data('colpick').livePreview] ); @@ -153,7 +153,7 @@ For usage and examples: colpick.com/plugin var pageY = ((ev.type == 'touchmove') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); change.apply( ev.data.cal.data('colpick') - .fields.eq(4).val(parseInt(360*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageY - ev.data.y))))/ev.data.cal.data('colpick').height, 10)) + .fields.eq(4).val(parseInt(360*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageY - ev.data.y))))/ev.data.cal.data('colpick').height, 10)) .get(0), [ev.data.preview] ); @@ -166,7 +166,7 @@ For usage and examples: colpick.com/plugin $(document).off('mousemove touchmove',moveHue); return false; }, - //Color selector functions + // Color selector functions downSelector = function (ev) { ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; var current = { @@ -179,7 +179,7 @@ For usage and examples: colpick.com/plugin $(document).on('mousemove touchmove',current,moveSelector); var payeX,pageY; - if(ev.type == 'touchstart') { + if (ev.type == 'touchstart') { pageX = ev.originalEvent.changedTouches[0].pageX, pageY = ev.originalEvent.changedTouches[0].pageY; } else { @@ -189,16 +189,16 @@ For usage and examples: colpick.com/plugin change.apply( current.cal.data('colpick').fields - .eq(6).val(parseInt(100*(current.cal.data('colpick').height - (pageY - current.pos.top))/current.cal.data('colpick').height, 10)).end() - .eq(5).val(parseInt(100*(pageX - current.pos.left)/current.cal.data('colpick').height, 10)) - .get(0), + .eq(6).val(parseInt(100*(current.cal.data('colpick').height - (pageY - current.pos.top))/current.cal.data('colpick').height, 10)).end() + .eq(5).val(parseInt(100*(pageX - current.pos.left)/current.cal.data('colpick').height, 10)) + .get(0), [current.preview] ); return false; }, moveSelector = function (ev) { var payeX,pageY; - if(ev.type == 'touchmove') { + if (ev.type == 'touchmove') { pageX = ev.originalEvent.changedTouches[0].pageX, pageY = ev.originalEvent.changedTouches[0].pageY; } else { @@ -208,9 +208,9 @@ For usage and examples: colpick.com/plugin change.apply( ev.data.cal.data('colpick').fields - .eq(6).val(parseInt(100*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageY - ev.data.pos.top))))/ev.data.cal.data('colpick').height, 10)).end() - .eq(5).val(parseInt(100*(Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageX - ev.data.pos.left))))/ev.data.cal.data('colpick').height, 10)) - .get(0), + .eq(6).val(parseInt(100*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageY - ev.data.pos.top))))/ev.data.cal.data('colpick').height, 10)).end() + .eq(5).val(parseInt(100*(Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageX - ev.data.pos.left))))/ev.data.cal.data('colpick').height, 10)) + .get(0), [ev.data.preview] ); return false; @@ -222,7 +222,7 @@ For usage and examples: colpick.com/plugin $(document).off('mousemove touchmove',moveSelector); return false; }, - //Submit button + // Submit button clickSubmit = function (ev) { var cal = $(this).parent(); var col = cal.data('colpick').color; @@ -230,7 +230,7 @@ For usage and examples: colpick.com/plugin setCurrentColor(col, cal.get(0)); cal.data('colpick').onSubmit(col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el); }, - //Show/hide the color picker + // Show/hide the color picker show = function (ev) { // Prevent the trigger of any direct parent ev.stopPropagation(); @@ -248,9 +248,11 @@ For usage and examples: colpick.com/plugin if (cal.data('colpick').onShow.apply(this, [cal.get(0)]) != false) { cal.show(); } - //Hide when user clicks outside + // Hide when user clicks outside $('html').mousedown({cal:cal}, hide); - cal.mousedown(function(ev){ev.stopPropagation();}) + cal.mousedown(function(ev){ + ev.stopPropagation(); + }); }, hide = function (ev) { if (ev.data.cal.data('colpick').onHide.apply(this, [ev.data.cal.get(0)]) != false) { @@ -265,7 +267,7 @@ For usage and examples: colpick.com/plugin w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth) }; }, - //Fix the values if the user enters a negative or high value + // Fix the values if the user enters a negative or high value fixHSB = function (hsb) { return { h: Math.min(360, Math.max(0, hsb.h)), @@ -309,8 +311,8 @@ For usage and examples: colpick.com/plugin return { init: function (opt) { opt = $.extend({}, defaults, opt||{}); - //Set color - if (typeof opt.color == 'string') { + // Set color + if (typeof opt.color === 'string') { opt.color = hexToHsb(opt.color); } else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) { opt.color = rgbToHsb(opt.color); @@ -320,44 +322,44 @@ For usage and examples: colpick.com/plugin return this; } - //For each selected DOM element + // For each selected DOM element return this.each(function () { - //If the element does not have an ID + // If the element does not have an ID if (!$(this).data('colpickId')) { var options = $.extend({}, opt); options.origColor = opt.color; - //Generate and assign a random ID + // Generate and assign a random ID var id = 'collorpicker_' + parseInt(Math.random() * 1000); $(this).data('colpickId', id); - //Set the tpl's ID and get the HTML + // Set the tpl's ID and get the HTML var cal = $(tpl).attr('id', id); - //Add class according to layout + // Add class according to layout cal.addClass('colpick_'+options.layout+(options.submit?'':' colpick_'+options.layout+'_ns')); - //Add class if the color scheme is not default - if(options.colorScheme != 'light') { + // Add class if the color scheme is not default + if (options.colorScheme != 'light') { cal.addClass('colpick_'+options.colorScheme); } - //Setup submit button + // Setup submit button cal.find('div.colpick_submit').html(options.submitText).click(clickSubmit); - //Setup input fields + // Setup input fields options.fields = cal.find('input').change(change).blur(blur).focus(focus); cal.find('div.colpick_field_arrs').mousedown(downIncrement).end().find('div.colpick_current_color').click(restoreOriginal); - //Setup hue selector + // Setup hue selector options.selector = cal.find('div.colpick_color').on('mousedown touchstart',downSelector); options.selectorIndic = options.selector.find('div.colpick_selector_outer'); - //Store parts of the plugin + // Store parts of the plugin options.el = this; options.hue = cal.find('div.colpick_hue_arrs'); huebar = options.hue.parent(); - //Paint the hue bar + // Paint the hue bar var UA = navigator.userAgent.toLowerCase(); var isIE = navigator.appName === 'Microsoft Internet Explorer'; var IEver = isIE ? parseFloat( UA.match( /msie ([0-9]{1,}[\.0-9]{0,})/ )[1] ) : 0; var ngIE = ( isIE && IEver < 10 ); var stops = ['#ff0000','#ff0080','#ff00ff','#8000ff','#0000ff','#0080ff','#00ffff','#00ff80','#00ff00','#80ff00','#ffff00','#ff8000','#ff0000']; - if(ngIE) { + if (ngIE) { var i, div; - for(i=0; i<=11; i++) { + for (i=0; i<=11; i++) { div = $('
').attr('style','height:8.333333%; filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='+stops[i]+', endColorstr='+stops[i+1]+'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='+stops[i]+', endColorstr='+stops[i+1]+')";'); huebar.append(div); } @@ -368,7 +370,7 @@ For usage and examples: colpick.com/plugin cal.find('div.colpick_hue').on('mousedown touchstart',downHue); options.newColor = cal.find('div.colpick_new_color'); options.currentColor = cal.find('div.colpick_current_color'); - //Store options and fill with default color + // Store options and fill with default color cal.data('colpick', options); fillRGBFields(options.color, cal.get(0)); fillHSBFields(options.color, cal.get(0)); @@ -377,7 +379,7 @@ For usage and examples: colpick.com/plugin setSelector(options.color, cal.get(0)); setCurrentColor(options.color, cal.get(0)); setNewColor(options.color, cal.get(0)); - //Append to body if flat=false, else show in place + // Append to body if flat=false, else show in place if (options.flat) { cal.appendTo(this).show(); cal.css({ @@ -394,7 +396,7 @@ For usage and examples: colpick.com/plugin } }); }, - //Shows the picker + // Shows the picker showPicker: function() { return this.each( function () { if ($(this).data('colpickId')) { @@ -402,7 +404,7 @@ For usage and examples: colpick.com/plugin } }); }, - //Hides the picker + // Hides the picker hidePicker: function() { return this.each( function () { if ($(this).data('colpickId')) { @@ -410,10 +412,10 @@ For usage and examples: colpick.com/plugin } }); }, - //Sets a color as new and current (default) + // Sets a color as new and current (default) setColor: function(col, setCurrent) { setCurrent = (typeof setCurrent === "undefined") ? 1 : setCurrent; - if (typeof col == 'string') { + if (typeof col === 'string') { col = hexToHsb(col); } else if (col.r != undefined && col.g != undefined && col.b != undefined) { col = rgbToHsb(col); @@ -435,7 +437,7 @@ For usage and examples: colpick.com/plugin setNewColor(col, cal.get(0)); cal.data('colpick').onChange.apply(cal.parent(), [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 1]); - if(setCurrent) { + if (setCurrent) { setCurrentColor(col, cal.get(0)); } } @@ -443,7 +445,7 @@ For usage and examples: colpick.com/plugin } }; }(); - //Color space convertions + // Color space convertions var hexToRgb = function (hex) { var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16); return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)}; @@ -459,12 +461,20 @@ For usage and examples: colpick.com/plugin hsb.b = max; hsb.s = max != 0 ? 255 * delta / max : 0; if (hsb.s != 0) { - if (rgb.r == max) hsb.h = (rgb.g - rgb.b) / delta; - else if (rgb.g == max) hsb.h = 2 + (rgb.b - rgb.r) / delta; - else hsb.h = 4 + (rgb.r - rgb.g) / delta; - } else hsb.h = -1; + if (rgb.r == max) { + hsb.h = (rgb.g - rgb.b) / delta; + } else if (rgb.g == max) { + hsb.h = 2 + (rgb.b - rgb.r) / delta; + } else { + hsb.h = 4 + (rgb.r - rgb.g) / delta; + } + } else { + hsb.h = -1; + } hsb.h *= 60; - if (hsb.h < 0) hsb.h += 360; + if (hsb.h < 0) { + hsb.h += 360; + } hsb.s *= 100/255; hsb.b *= 100/255; return hsb; @@ -474,20 +484,30 @@ For usage and examples: colpick.com/plugin var h = hsb.h; var s = hsb.s*255/100; var v = hsb.b*255/100; - if(s == 0) { + if (s == 0) { rgb.r = rgb.g = rgb.b = v; } else { var t1 = v; var t2 = (255-s)*v/255; var t3 = (t1-t2)*(h%60)/60; - if(h==360) h = 0; - if(h<60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3} - else if(h<120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3} - else if(h<180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3} - else if(h<240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3} - else if(h<300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3} - else if(h<360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3} - else {rgb.r=0; rgb.g=0; rgb.b=0} + if (h==360) { + h = 0; + } + if (h<60) { + rgb.r=t1; rgb.b=t2; rgb.g=t2+t3; + } else if (h<120) { + rgb.g=t1; rgb.b=t2; rgb.r=t1-t3; + } else if (h<180) { + rgb.g=t1; rgb.r=t2; rgb.b=t2+t3; + } else if (h<240) { + rgb.b=t1; rgb.r=t2; rgb.g=t1-t3; + } else if (h<300) { + rgb.b=t1; rgb.g=t2; rgb.r=t2+t3; + } else if (h<360) { + rgb.r=t1; rgb.g=t2; rgb.b=t1-t3; + } else { + rgb.r=0; rgb.g=0; rgb.b=0; + } } return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)}; }; @@ -524,3 +544,4 @@ For usage and examples: colpick.com/plugin } }); })(jQuery); + From 691aafcf29e20ef2507cf71c3ea1b383fb0f2242 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 9 Feb 2018 16:42:43 -0500 Subject: [PATCH 15/54] [Case 4315] ESLint Pass 2 for colpick.js (details below). Resolves all error Line exceeds the maximum line length of 128 max-len issues. Issue Count reduced from 85 to 70. Changes Committed: modified: scripts/system/html/js/colpick.js --- scripts/system/html/js/colpick.js | 78 +++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index b19cbe0bae..feb584aa1d 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -1,6 +1,7 @@ /* colpick Color Picker -Copyright 2013 Jose Vargas. Licensed under GPL license. Based on Stefan Petre's Color Picker www.eyecon.ro, dual licensed under the MIT and GPL licenses +Copyright 2013 Jose Vargas. Licensed under GPL license. Based on Stefan Petre's Color Picker www.eyecon.ro, dual licensed +under the MIT and GPL licenses For usage and examples: colpick.com/plugin */ @@ -8,7 +9,31 @@ For usage and examples: colpick.com/plugin (function ($) { var colpick = function () { var - tpl = '
#
R
G
B
H
S
B
', + tpl = '
' + + '
' + + '
' + + '
' + + '
' + + '
#
' + + '
' + + '
R
' + + '
' + + '
' + + '
G
' + + '
' + + '
B
' + + '
' + + '
' + + '
H
' + + '
' + + '
' + + '
S
' + + '
' + + '
' + + '
B
' + + '
' + + '
' + + '
', defaults = { showEvent: 'click', onShow: function () {}, @@ -52,7 +77,8 @@ For usage and examples: colpick.com/plugin }, // Set the hue selector position setHue = function (hsb, cal) { - $(cal).data('colpick').hue.css('top', parseInt($(cal).data('colpick').height - $(cal).data('colpick').height * hsb.h/360, 10)); + $(cal).data('colpick').hue.css('top', + parseInt($(cal).data('colpick').height - $(cal).data('colpick').height * hsb.h / 360, 10)); }, // Set current and new colors setCurrentColor = function (hsb, cal) { @@ -91,7 +117,8 @@ For usage and examples: colpick.com/plugin setSelector(col, cal.get(0)); setHue(col, cal.get(0)); setNewColor(col, cal.get(0)); - cal.data('colpick').onChange.apply(cal.parent(), [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 0]); + cal.data('colpick').onChange.apply(cal.parent(), + [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 0]); }, // Change style on blur and on focus of inputs blur = function (ev) { @@ -107,7 +134,8 @@ For usage and examples: colpick.com/plugin var field = $(this).parent().find('input').focus(); var current = { el: $(this).parent().addClass('colpick_slider'), - max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255), + max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : + (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255), y: ev.pageY, field: field, val: parseInt(field.val(), 10), @@ -143,7 +171,8 @@ For usage and examples: colpick.com/plugin var pageY = ((ev.type == 'touchstart') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); change.apply( current.cal.data('colpick') - .fields.eq(4).val(parseInt(360*(current.cal.data('colpick').height - (pageY - current.y))/current.cal.data('colpick').height, 10)) + .fields.eq(4).val(parseInt(360 * (current.cal.data('colpick').height - + (pageY - current.y)) / current.cal.data('colpick').height, 10)) .get(0), [current.cal.data('colpick').livePreview] ); @@ -153,7 +182,9 @@ For usage and examples: colpick.com/plugin var pageY = ((ev.type == 'touchmove') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); change.apply( ev.data.cal.data('colpick') - .fields.eq(4).val(parseInt(360*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageY - ev.data.y))))/ev.data.cal.data('colpick').height, 10)) + .fields.eq(4).val(parseInt(360 * (ev.data.cal.data('colpick').height - + Math.max(0, Math.min(ev.data.cal.data('colpick').height, (pageY - ev.data.y)))) / + ev.data.cal.data('colpick').height, 10)) .get(0), [ev.data.preview] ); @@ -189,7 +220,8 @@ For usage and examples: colpick.com/plugin change.apply( current.cal.data('colpick').fields - .eq(6).val(parseInt(100*(current.cal.data('colpick').height - (pageY - current.pos.top))/current.cal.data('colpick').height, 10)).end() + .eq(6).val(parseInt(100 * (current.cal.data('colpick').height - (pageY - current.pos.top)) / + current.cal.data('colpick').height, 10)).end() .eq(5).val(parseInt(100*(pageX - current.pos.left)/current.cal.data('colpick').height, 10)) .get(0), [current.preview] @@ -208,8 +240,11 @@ For usage and examples: colpick.com/plugin change.apply( ev.data.cal.data('colpick').fields - .eq(6).val(parseInt(100*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageY - ev.data.pos.top))))/ev.data.cal.data('colpick').height, 10)).end() - .eq(5).val(parseInt(100*(Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageX - ev.data.pos.left))))/ev.data.cal.data('colpick').height, 10)) + .eq(6).val(parseInt(100 * (ev.data.cal.data('colpick').height - + Math.max(0, Math.min(ev.data.cal.data('colpick').height, (pageY - ev.data.pos.top)))) / + ev.data.cal.data('colpick').height, 10)).end() + .eq(5).val(parseInt(100 * (Math.max(0, Math.min(ev.data.cal.data('colpick').height, + (pageX - ev.data.pos.left)))) / ev.data.cal.data('colpick').height, 10)) .get(0), [ev.data.preview] ); @@ -343,7 +378,8 @@ For usage and examples: colpick.com/plugin cal.find('div.colpick_submit').html(options.submitText).click(clickSubmit); // Setup input fields options.fields = cal.find('input').change(change).blur(blur).focus(focus); - cal.find('div.colpick_field_arrs').mousedown(downIncrement).end().find('div.colpick_current_color').click(restoreOriginal); + cal.find('div.colpick_field_arrs').mousedown(downIncrement); + cal.find('div.colpick_current_color').click(restoreOriginal); // Setup hue selector options.selector = cal.find('div.colpick_color').on('mousedown touchstart',downSelector); options.selectorIndic = options.selector.find('div.colpick_selector_outer'); @@ -356,16 +392,27 @@ For usage and examples: colpick.com/plugin var isIE = navigator.appName === 'Microsoft Internet Explorer'; var IEver = isIE ? parseFloat( UA.match( /msie ([0-9]{1,}[\.0-9]{0,})/ )[1] ) : 0; var ngIE = ( isIE && IEver < 10 ); - var stops = ['#ff0000','#ff0080','#ff00ff','#8000ff','#0000ff','#0080ff','#00ffff','#00ff80','#00ff00','#80ff00','#ffff00','#ff8000','#ff0000']; + var stops = ['#ff0000', '#ff0080', '#ff00ff', '#8000ff', '#0000ff', '#0080ff', '#00ffff', '#00ff80', + '#00ff00', '#80ff00', '#ffff00', '#ff8000', '#ff0000']; if (ngIE) { var i, div; for (i=0; i<=11; i++) { - div = $('
').attr('style','height:8.333333%; filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='+stops[i]+', endColorstr='+stops[i+1]+'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='+stops[i]+', endColorstr='+stops[i+1]+')";'); + div = $('
').attr('style', + 'height:8.333333%; filter:progid:' + + 'DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=' + stops[i] + + ', endColorstr=' + stops[i + 1] + + '); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=' + + stops[i] + ', endColorstr=' + stops[i + 1] + ')";'); huebar.append(div); } } else { stopList = stops.join(','); - huebar.attr('style','background:-webkit-linear-gradient(top,'+stopList+'); background: -o-linear-gradient(top,'+stopList+'); background: -ms-linear-gradient(top,'+stopList+'); background:-moz-linear-gradient(top,'+stopList+'); -webkit-linear-gradient(top,'+stopList+'); background:linear-gradient(to bottom,'+stopList+'); '); + huebar.attr('style', 'background:-webkit-linear-gradient(top,' + stopList + + '); background: -o-linear-gradient(top,' + stopList + + '); background: -ms-linear-gradient(top,' + stopList + + '); background:-moz-linear-gradient(top,' + stopList + + '); -webkit-linear-gradient(top,' + stopList + + '); background:linear-gradient(to bottom,' + stopList + '); '); } cal.find('div.colpick_hue').on('mousedown touchstart',downHue); options.newColor = cal.find('div.colpick_new_color'); @@ -436,7 +483,8 @@ For usage and examples: colpick.com/plugin setSelector(col, cal.get(0)); setNewColor(col, cal.get(0)); - cal.data('colpick').onChange.apply(cal.parent(), [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 1]); + cal.data('colpick').onChange.apply(cal.parent(), + [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 1]); if (setCurrent) { setCurrentColor(col, cal.get(0)); } From 0a1e05326eeea6fdbb95aaf9176f19792ff6580e Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 9 Feb 2018 16:49:44 -0500 Subject: [PATCH 16/54] [Case 4315] ESLint Pass 3, adds global declarations (details below). This resolves 23 error is not defined no-undef errors related to global objects. Issue Count reduced from 70 to 47. Changes Committed: modified: scripts/system/html/js/colpick.js --- scripts/system/html/js/colpick.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index feb584aa1d..0ac6996bde 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -6,6 +6,8 @@ under the MIT and GPL licenses For usage and examples: colpick.com/plugin */ +/* global console, document, Element, EventBridge, jQuery, navigator, window, _ $ */ + (function ($) { var colpick = function () { var From ef1fd19a982a67a5c1653671226d33f43c86f673 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 9 Feb 2018 17:01:52 -0500 Subject: [PATCH 17/54] [Case 4315] ESLint Pass 4 for colpick.js (details below). Resolved payeX vs pageX issues. Resolved stopList & huebar undefined issues. Issue Count reduced from 47 to 29. Changes Committed: modified: scripts/system/html/js/colpick.js --- scripts/system/html/js/colpick.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index 0ac6996bde..44e887056a 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -211,7 +211,7 @@ For usage and examples: colpick.com/plugin $(document).on('mouseup touchend',current,upSelector); $(document).on('mousemove touchmove',current,moveSelector); - var payeX,pageY; + var pageX,pageY; if (ev.type == 'touchstart') { pageX = ev.originalEvent.changedTouches[0].pageX, pageY = ev.originalEvent.changedTouches[0].pageY; @@ -231,7 +231,7 @@ For usage and examples: colpick.com/plugin return false; }, moveSelector = function (ev) { - var payeX,pageY; + var pageX,pageY; if (ev.type == 'touchmove') { pageX = ev.originalEvent.changedTouches[0].pageX, pageY = ev.originalEvent.changedTouches[0].pageY; @@ -388,7 +388,7 @@ For usage and examples: colpick.com/plugin // Store parts of the plugin options.el = this; options.hue = cal.find('div.colpick_hue_arrs'); - huebar = options.hue.parent(); + var huebar = options.hue.parent(); // Paint the hue bar var UA = navigator.userAgent.toLowerCase(); var isIE = navigator.appName === 'Microsoft Internet Explorer'; @@ -408,7 +408,7 @@ For usage and examples: colpick.com/plugin huebar.append(div); } } else { - stopList = stops.join(','); + var stopList = stops.join(','); huebar.attr('style', 'background:-webkit-linear-gradient(top,' + stopList + '); background: -o-linear-gradient(top,' + stopList + '); background: -ms-linear-gradient(top,' + stopList + From 83749b16c7811028e0e81aea69f6f34e9d08f8d7 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 9 Feb 2018 17:35:03 -0500 Subject: [PATCH 18/54] [Case 4315] ESLint Pass 5 resolves hex already defined issue (details below). * var hex was declared both the hexToRGB and hexToHsb functions. * hexToRGB was updated to have a more explicit var name * hexToRGB & hexToHSB also had the function param name updated to clarify the expected object type. Also error statements and early returns were added should an unsupported object type be received. * Issue Count is now 28 Changes Committed: modified: scripts/system/html/js/colpick.js --- scripts/system/html/js/colpick.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index 44e887056a..d748698cde 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -496,12 +496,22 @@ For usage and examples: colpick.com/plugin }; }(); // Color space convertions - var hexToRgb = function (hex) { - var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16); - return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)}; + var hexToRgb = function (hexString) { + if (typeof hexString !== "string") { + print("Error - ColPick.js::hexToRgb expects string object."); + return; + } + + var hexNumber = parseInt(((hexString.indexOf('#') > -1) ? hexString.substring(1) : hexString), 16); + return { r: hexNumber >> 16, g: (hexNumber & 0x00FF00) >> 8, b: (hexNumber & 0x0000FF)}; }; - var hexToHsb = function (hex) { - return rgbToHsb(hexToRgb(hex)); + var hexToHsb = function (hexString) { + if (typeof hexString !== "string") { + print("Error - ColPick.js::hexToHsb expects string object."); + return; + } + + return rgbToHsb(hexToRgb(hexString)); }; var rgbToHsb = function (rgb) { var hsb = {h: 0, s: 0, b: 0}; From 59e0b8476aeca4fe7501df96d2488da7175db023 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 9 Feb 2018 17:57:42 -0500 Subject: [PATCH 19/54] [Case 4315] ESLint Pass 6 Pt 1 for colpick.js (details below). First portion of vetted equality check fixes. Issue Count reduced from 28 to 8. Changes Committed: modified: scripts/system/html/js/colpick.js --- scripts/system/html/js/colpick.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index d748698cde..7c640633e3 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -170,7 +170,7 @@ For usage and examples: colpick.com/plugin $(document).on('mouseup touchend',current,upHue); $(document).on('mousemove touchmove',current,moveHue); - var pageY = ((ev.type == 'touchstart') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); + var pageY = ((ev.type === 'touchstart') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); change.apply( current.cal.data('colpick') .fields.eq(4).val(parseInt(360 * (current.cal.data('colpick').height - @@ -181,7 +181,7 @@ For usage and examples: colpick.com/plugin return false; }, moveHue = function (ev) { - var pageY = ((ev.type == 'touchmove') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); + var pageY = ((ev.type === 'touchmove') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY ); change.apply( ev.data.cal.data('colpick') .fields.eq(4).val(parseInt(360 * (ev.data.cal.data('colpick').height - @@ -212,7 +212,7 @@ For usage and examples: colpick.com/plugin $(document).on('mousemove touchmove',current,moveSelector); var pageX,pageY; - if (ev.type == 'touchstart') { + if (ev.type === 'touchstart') { pageX = ev.originalEvent.changedTouches[0].pageX, pageY = ev.originalEvent.changedTouches[0].pageY; } else { @@ -232,7 +232,7 @@ For usage and examples: colpick.com/plugin }, moveSelector = function (ev) { var pageX,pageY; - if (ev.type == 'touchmove') { + if (ev.type === 'touchmove') { pageX = ev.originalEvent.changedTouches[0].pageX, pageY = ev.originalEvent.changedTouches[0].pageY; } else { @@ -282,7 +282,7 @@ For usage and examples: colpick.com/plugin left -= calW; } cal.css({left: left + 'px', top: top + 'px'}); - if (cal.data('colpick').onShow.apply(this, [cal.get(0)]) != false) { + if (cal.data('colpick').onShow.apply(this, [cal.get(0)]) !== false) { cal.show(); } // Hide when user clicks outside @@ -292,13 +292,13 @@ For usage and examples: colpick.com/plugin }); }, hide = function (ev) { - if (ev.data.cal.data('colpick').onHide.apply(this, [ev.data.cal.get(0)]) != false) { + if (ev.data.cal.data('colpick').onHide.apply(this, [ev.data.cal.get(0)]) !== false) { ev.data.cal.hide(); } $('html').off('mousedown', hide); }, getViewport = function () { - var m = document.compatMode == 'CSS1Compat'; + var m = document.compatMode === 'CSS1Compat'; return { l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft), w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth) @@ -351,9 +351,9 @@ For usage and examples: colpick.com/plugin // Set color if (typeof opt.color === 'string') { opt.color = hexToHsb(opt.color); - } else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) { + } else if (opt.color.r !== undefined && opt.color.g !== undefined && opt.color.b !== undefined) { opt.color = rgbToHsb(opt.color); - } else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) { + } else if (opt.color.h !== undefined && opt.color.s !== undefined && opt.color.b !== undefined) { opt.color = fixHSB(opt.color); } else { return this; @@ -373,7 +373,7 @@ For usage and examples: colpick.com/plugin // Add class according to layout cal.addClass('colpick_'+options.layout+(options.submit?'':' colpick_'+options.layout+'_ns')); // Add class if the color scheme is not default - if (options.colorScheme != 'light') { + if (options.colorScheme !== 'light') { cal.addClass('colpick_'+options.colorScheme); } // Setup submit button @@ -466,9 +466,9 @@ For usage and examples: colpick.com/plugin setCurrent = (typeof setCurrent === "undefined") ? 1 : setCurrent; if (typeof col === 'string') { col = hexToHsb(col); - } else if (col.r != undefined && col.g != undefined && col.b != undefined) { + } else if (col.r !== undefined && col.g !== undefined && col.b !== undefined) { col = rgbToHsb(col); - } else if (col.h != undefined && col.s != undefined && col.b != undefined) { + } else if (col.h !== undefined && col.s !== undefined && col.b !== undefined) { col = fixHSB(col); } else { return this; From fed85a7a5309200fca79e4dbdb28a3ec4a21effd Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 9 Feb 2018 18:12:57 -0500 Subject: [PATCH 20/54] [Case 4315] ESLint Pass 6 Pt 2 for colpick equality checks (details below). * Suppressing equality checking issues within color conversion helper functions. * These issues are suppressed as opposed to resolved because their resolution causes issues with the color picker's understanding of the color it's being set to along with the respective hue. This is likely due to rounding issues; however, it may also be something related to the equality operator implicit conversions semantics of JavaScript. It's something that can be looked into later if desired. * Bug Steps upon resolving check as opposed to suppressing them: - Select a shape entity for example. - Note the visual color and actual RGB values for that entity's color upon selection. - Click the Color Wheel. - Notice the automatic change of the color for the entity when the picker is shown. - If the issue doesn't show itself right away, alter the color for the entity close the picker, and repeat steps 2-3. * Issue Count reduced from 8 to 1 Changes Committed: modified: scripts/system/html/js/colpick.js --- scripts/system/html/js/colpick.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index 7c640633e3..94b5d8521c 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -519,11 +519,11 @@ For usage and examples: colpick.com/plugin var max = Math.max(rgb.r, rgb.g, rgb.b); var delta = max - min; hsb.b = max; - hsb.s = max != 0 ? 255 * delta / max : 0; - if (hsb.s != 0) { - if (rgb.r == max) { + hsb.s = max != 0 ? 255 * delta / max : 0; // eslint-disable-line eqeqeq + if (hsb.s != 0) { // eslint-disable-line eqeqeq + if (rgb.r == max) { // eslint-disable-line eqeqeq hsb.h = (rgb.g - rgb.b) / delta; - } else if (rgb.g == max) { + } else if (rgb.g == max) { // eslint-disable-line eqeqeq hsb.h = 2 + (rgb.b - rgb.r) / delta; } else { hsb.h = 4 + (rgb.r - rgb.g) / delta; @@ -544,13 +544,13 @@ For usage and examples: colpick.com/plugin var h = hsb.h; var s = hsb.s*255/100; var v = hsb.b*255/100; - if (s == 0) { + if (s == 0) { // eslint-disable-line eqeqeq rgb.r = rgb.g = rgb.b = v; } else { var t1 = v; var t2 = (255-s)*v/255; var t3 = (t1-t2)*(h%60)/60; - if (h==360) { + if (h==360) { // eslint-disable-line eqeqeq h = 0; } if (h<60) { @@ -578,7 +578,7 @@ For usage and examples: colpick.com/plugin rgb.b.toString(16) ]; $.each(hex, function (nr, val) { - if (val.length == 1) { + if (val.length == 1) { // eslint-disable-line eqeqeq hex[nr] = '0' + val; } }); From b058b346bd2059395f2fdc3e29455413979777f1 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 9 Feb 2018 18:25:50 -0500 Subject: [PATCH 21/54] [Case 4315] ESLint Pass 7 for colpick.js resolves regex error (details below). Issue Count for colpick is now 0. Changes Committed: modified: scripts/system/html/js/colpick.js --- scripts/system/html/js/colpick.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index 94b5d8521c..199c624bc5 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -392,7 +392,7 @@ For usage and examples: colpick.com/plugin // Paint the hue bar var UA = navigator.userAgent.toLowerCase(); var isIE = navigator.appName === 'Microsoft Internet Explorer'; - var IEver = isIE ? parseFloat( UA.match( /msie ([0-9]{1,}[\.0-9]{0,})/ )[1] ) : 0; + var IEver = isIE ? parseFloat( UA.match( /msie ([0-9]{1,}[.0-9]{0,})/ )[1] ) : 0; var ngIE = ( isIE && IEver < 10 ); var stops = ['#ff0000', '#ff0080', '#ff00ff', '#8000ff', '#0000ff', '#0080ff', '#00ffff', '#00ff80', '#00ff00', '#80ff00', '#ffff00', '#ff8000', '#ff0000']; From abdd50fb455feacb2c27306a6322c5e4387e5b14 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 9 Feb 2018 14:58:48 -0800 Subject: [PATCH 22/54] it's a start --- .gitignore | 5 ++- .../hifi/commerce/common/FirstUseTutorial.qml | 4 +- .../hifi/commerce/purchases/PurchasedItem.qml | 42 ++++++++++-------- .../qml/hifi/commerce/purchases/Purchases.qml | 24 ++++++---- interface/resources/qml/js/Utils.jsc | Bin 6516 -> 6596 bytes scripts/system/commerce/wallet.js | 2 +- scripts/system/marketplaces/marketplaces.js | 5 ++- 7 files changed, 50 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index f45572c388..1ffb93fe80 100644 --- a/.gitignore +++ b/.gitignore @@ -85,4 +85,7 @@ npm-debug.log android/app/src/main/assets # Resource binary file -interface/compiledResources \ No newline at end of file +interface/compiledResources + +# GPUCache +interface/resources/GPUCache/* \ No newline at end of file diff --git a/interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml b/interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml index bcc641acd5..9944838e03 100644 --- a/interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml +++ b/interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml @@ -90,11 +90,11 @@ Rectangle { id: introText2; text: "My Purchases"; // Text size - size: 28; + size: 22; // Anchors anchors.top: introText1.bottom; anchors.left: parent.left; - anchors.leftMargin: 12; + anchors.leftMargin: 24; anchors.right: parent.right; height: paintedHeight; // Style diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 05e280b839..361b9931a4 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -39,7 +39,10 @@ Item { property int itemEdition; property int numberSold; property int limitedRun; - property bool isWearable; + property string itemType; + property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"]; + property var buttonTextNormal: ["REZ", "WEAR", "SWAP", "INSTALL", "WEAR"]; + property var buttonTextClicked: ["REZZED", "WORN", "SWAPPED", "INSTALLED", "WORN"] property string originalStatusText; property string originalStatusColor; @@ -73,10 +76,10 @@ Item { color: hifi.colors.white; // Size anchors.left: parent.left; - anchors.leftMargin: 8; + anchors.leftMargin: 16; anchors.right: parent.right; - anchors.rightMargin: 8; - anchors.top: parent.top; + anchors.rightMargin: 16; + anchors.verticalCenter: parent.verticalCenter; height: root.height - 10; Image { @@ -311,7 +314,7 @@ Item { id: rezzedNotifContainer; z: 998; visible: false; - color: hifi.colors.blueHighlight; + color: "#1FC6A6"; anchors.fill: buttonContainer; MouseArea { anchors.fill: parent; @@ -321,7 +324,7 @@ Item { RalewayBold { anchors.fill: parent; - text: "REZZED"; + text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)]; size: 18; color: hifi.colors.white; verticalAlignment: Text.AlignVCenter; @@ -337,25 +340,28 @@ Item { Button { id: buttonContainer; - property int color: hifi.buttons.red; + property int color: hifi.buttons.blue; property int colorScheme: hifi.colorSchemes.light; anchors.top: parent.top; + anchors.topMargin: 4; anchors.bottom: parent.bottom; + anchors.bottomMargin: 4; anchors.right: parent.right; + anchors.rightMargin: 4; width: height; - enabled: (root.canRezCertifiedItems || root.isWearable) && root.purchaseStatus !== "invalidated"; + enabled: (root.canRezCertifiedItems || root.itemType === "wearable") && root.purchaseStatus !== "invalidated"; onClicked: { - sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable}); + sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start(); - UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.isWearable ? "rez" : "wear"); + UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.itemType === "wearable" ? "rez" : "wear"); } style: ButtonStyle { - background: Rectangle { + radius: 4; gradient: Gradient { GradientStop { position: 0.2 @@ -413,10 +419,10 @@ Item { font.capitalization: Font.AllUppercase color: enabled ? hifi.buttons.textColor[control.color] : hifi.buttons.disabledTextColor[control.colorScheme] - size: 16; + size: 15; verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter - text: root.isWearable ? "Wear It" : "Rez It" + text: (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)] } } } @@ -425,11 +431,11 @@ Item { DropShadow { anchors.fill: mainContainer; - horizontalOffset: 3; - verticalOffset: 3; - radius: 8.0; - samples: 17; - color: "#80000000"; + horizontalOffset: 0; + verticalOffset: 4; + radius: 4.0; + samples: 9 + color: Qt.rgba(0, 0, 0, 0.25); source: mainContainer; } diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 2743677683..922ba54822 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -308,11 +308,11 @@ Rectangle { anchors.bottom: parent.bottom; anchors.bottomMargin: 10; anchors.left: parent.left; - anchors.leftMargin: 4; + anchors.leftMargin: 16; width: paintedWidth; text: isShowingMyItems ? "My Items" : "My Purchases"; color: hifi.colors.baseGray; - size: 28; + size: 22; } HifiControlsUit.TextField { @@ -323,8 +323,8 @@ Rectangle { hasRoundedBorder: true; anchors.left: myText.right; anchors.leftMargin: 16; - anchors.top: parent.top; - anchors.bottom: parent.bottom; + height: 39; + anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; placeholderText: "filter items"; @@ -454,16 +454,24 @@ Rectangle { numberSold: model.number_sold; limitedRun: model.limited_run; displayedItemCount: model.displayedItemCount; - isWearable: model.categories.indexOf("Wearables") > -1; - anchors.topMargin: 12; - anchors.bottomMargin: 12; + itemType: { + if (model.download_url.indexOf(".fst") > -1) { + "avatar"; + } else if (model.categories.indexOf("Wearables") > -1) { + "wearable"; + } else { + "entity"; + } + } + anchors.topMargin: 10; + anchors.bottomMargin: 10; Connections { onSendToPurchases: { if (msg.method === 'purchases_itemInfoClicked') { sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId}); } else if (msg.method === "purchases_rezClicked") { - sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, isWearable: isWearable}); + sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, itemType: itemType}); } else if (msg.method === 'purchases_itemCertificateClicked') { inspectionCertificate.visible = true; inspectionCertificate.isLightbox = true; diff --git a/interface/resources/qml/js/Utils.jsc b/interface/resources/qml/js/Utils.jsc index 8da68e4e192018ee2b4f3d835ec91f36f0161eca..ab20e996b9469915ac6a89901da175143e6b5024 100644 GIT binary patch delta 604 zcmexjbi`Pvu*@VmC9xz?kb!}Lfs>VC&A*2iV;C72bXXY}mb_f{tI)LMb*EnX9J{G= zWjE?fVPxWFpL~eXjmbb{GZ&K)lcEI!149}^CPNNGDuWe+J{UTKSV!qu$P@xQv&;%5r0+3J# zickeer~z51p@D&c!LzePrQ-kp|4@m^A9y8vAm%nqfJ$c|q`_`zm;seYK$lnmm56{y zI39Phm>j})kdv7eWRZ)?jLG}?J(xDJOx`D`JXuG8Z}JL$VaC6c_wai&DZm7I_&)Iq z-167~3SS0>5B8H41jOnE9)IGGd+4!a)=UuiXrJc6pLZgSU+*D*n>GUj15EV<2e8B^ z{2Kn8s9?FPGD3MA9~ zMq$_Fat`Uu69ftv87(F=3MGm|!vW+*kU5~R2l;h#rBDLn4g!mi%G zd85u0My4%nlMgYvF+C98%*ABHq-@E+z>vm}$&ka4%3#Hy4~8yaRtiHBLn1>mL-yoY zme9>xSavcq8f?zvxX;LFu-T8xhB-~cvzy7I+abZT(?w;5Z?~9lcMw!410*y7MW_HI z)PW*Y0TOCJ7HViFnI&N2cysApZo@sr}K+4E}OiT- Date: Tue, 13 Feb 2018 10:11:18 +1300 Subject: [PATCH 23/54] A further guard --- scripts/system/controllers/controllerDispatcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index b2455b3f5a..345ab33c0d 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -479,7 +479,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; } function mouseReleaseOnOverlay(overlayID, event) { - if (overlayID === HMD.homeButtonID && event.button === "Primary") { + if (HMD.homeButtonID && overlayID === HMD.homeButtonID && event.button === "Primary") { Messages.sendLocalMessage("home", overlayID); } } From 95e9eb8e4abebbbaa919224a8f638a78fc91482a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 12 Feb 2018 17:06:57 -0800 Subject: [PATCH 24/54] Lots of progress --- interface/resources/fonts/hifi-glyphs.ttf | Bin 31232 -> 32536 bytes .../qml/hifi/commerce/checkout/Checkout.qml | 69 +++++++++++++----- .../hifi/commerce/purchases/PurchasedItem.qml | 57 +++++++++++---- .../qml/hifi/commerce/purchases/Purchases.qml | 16 +++- .../qml/styles-uit/HifiConstants.qml | 4 + interface/src/Application.cpp | 34 +++++---- interface/src/Application.h | 2 + interface/src/commerce/QmlCommerce.cpp | 13 ++++ interface/src/commerce/QmlCommerce.h | 4 + .../entities/src/EntityScriptingInterface.cpp | 5 ++ .../entities/src/EntityScriptingInterface.h | 6 ++ scripts/system/marketplaces/marketplaces.js | 17 +++-- 12 files changed, 174 insertions(+), 53 deletions(-) diff --git a/interface/resources/fonts/hifi-glyphs.ttf b/interface/resources/fonts/hifi-glyphs.ttf index 4cc5a0fe4f098a287c1df067c8bff37695f96d34..8db0377f88864810e7f893132449ad8e258e68cd 100644 GIT binary patch delta 1778 zcmX|BYit}>6+Y+AoqK2QJl2nSB>S*;W_D-2b{(&GXJ_2H>o!qq1dW}@Z9){4lvT5h zqu7p>-KGvdyya2)h89Z*g%o}O?VnUUtN=f%mWR~PN+2OYkx)Sq5&Ym!Bm`1H$U(EI zxYE7fxku-Gy65UU=jngqH}7dS0U-a02OeC6w}Am{ ze+U4@BM;BikGyrb2Y@F4;P~U~?ahl1e$WOW9|Dk#Gwtr??b{#$Z2t}blrw9Wp0Lk- z?+O6h1lW9TwbMRrK2iK70Hl2J>T0LorZv0)fEEChR@Zx5#n0{g5&-@H04LYZKi+=l zzCWD;kPic3X}!I*3AgYR0M4Zk+GwwL{yul@IKah^0C0Ene79$>Tz&{(>nZ@77!-#9 z<3CKEc`S49zd$39t`EL*>*gIKw{Ct7TlnhE0)7T(cCTO)kG0@#ScG|49K=chgPk9c z0j`2Hu<}6ha9SlOaEEpK#?0;8gBJt$^ znvmp2b9C;3-4pEExjusyJc7T#t6)GGns5-7;5Yy_>bAqJ!1J5KQ3G2Tg@Na@0*RA& z9GzqUa@}co^(3x@m5?*eDhrr|l`t^TwGxK~EUZLvQg=e1*_K<6Bg89Z#LC`#l`0;h z#@=uBzN{(xM>AZvI$0~X_cy8%oG>J&S1V%3xyDQ}sVTa|T^*mr{OD+IaFj<3TNrq? z{N-oE3FOtif1AHCsI0%KQ&}I$2qqeal{<}0(JNJr>nEuzTZ{{dkGS~8Xby8$$|UJ( z-zK`1>hW$!@H)N=8sx!;DVT*A=HY($BpiWba1u5Ez-N}zaGML*jCe~9D{$s_9_tW&CAU7uQ@i9 z%?_9DEe)>)_Q(RF@H4i%-x2t3@AV!c_EsJ~AtNH8L0%S8c!sU#R&MhlsSyhF4MDS(ChHj+vx|Y|pyrw&rWeM?l zbwU;4@6~<^B_a!Xh;e2rjC1MR5>p7HgfWG4E~`|buMwt5hC+oRs~JU32gE#lAK%9> z!W7KFJpkpj0|Va| zMi2?-dZ8eX>=)2VCq~@DD76F6f3$^(eMb&XqkbPQVC4X2 zuo?NE&DthbO*^aZ{Xu=r(-c*UWr;~KMJj2un7wH%o3?E(8^*G#F8}nKIaO%9CP_6( zqZDcGvazdQ&~bPcYA_A;!LGq9%{Kk4`qt~TRwKq=Fr#kHm{Om@z*IrxOdFxUE RU)lNNrJVNvNq_6+{{ZQFEu#Pc delta 506 zcmX|-Pe>GT6vsbrW?a_PN=#T{p%p?1S=w31NpL;s+9A-lJ#L?N1OHfx?@7&K_$jRKEZ}fzEtBH)|UysezmWF6K*xFSHt&=rbf$Ti>;Q8YrX zncAgVM-V91wi+jx!~?YvL%)~ zq-iG8DbuR-xJ$C&e|BTy|Mj+vesu*20yIT_8i=W3*y}t;FhB|8So(HmEqr(Ac;|op E2i!<=3IG5A diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 809f48361d..c141b48d32 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -37,11 +37,14 @@ Rectangle { property double balanceAfterPurchase; property bool alreadyOwned: false; property int itemPrice: -1; - property bool itemIsJson: true; + property bool isCertified; + property string itemType; + property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"]; + property var buttonTextNormal: ["REZ IT", "WEAR IT", "SWAP CONTENT SET", "INSTALL IT", "WEAR IT"]; + property var buttonTextClicked: ["REZZED", "WORN", "SWAPPED", "INSTALLED", "WORN"] property bool shouldBuyWithControlledFailure: false; property bool debugCheckoutSuccess: false; property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); - property bool isWearable; property string referrer; // Style color: hifi.colors.white; @@ -85,7 +88,9 @@ Rectangle { UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message); } else { root.itemHref = result.data.download_url; - root.isWearable = result.data.categories.indexOf("Wearables") > -1; + if (result.data.categories.indexOf("Wearables") > -1) { + root.itemType = "wearable"; + } root.activeView = "checkoutSuccess"; UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned); } @@ -122,7 +127,25 @@ Rectangle { } onItemHrefChanged: { - itemIsJson = root.itemHref.endsWith('.json'); + if (root.itemHref.indexOf(".fst") > -1) { + root.itemType = "avatar"; + } else if (root.itemHref.endsWith('.json.gz')) { + root.itemType = "contentSet"; + } else if (root.itemHref.endsWith('.json')) { + root.itemType = "entity"; // "wearable" type handled later + } else if (root.itemHref.endsWith('.js')) { + root.itemType = "app"; + } else { + root.itemType = "entity"; + } + } + + onItemTypeChanged: { + if (root.itemType === "entity" || root.itemType === "wearable" || root.itemType === "contentSet") { + root.isCertified = true; + } else { + root.isCertified = false; + } } onItemPriceChanged: { @@ -464,7 +487,7 @@ Rectangle { // "Buy" button HifiControlsUit.Button { id: buyButton; - enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || !itemIsJson; + enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || (!root.isCertified); color: hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; anchors.top: checkoutActionButtonsContainer.top; @@ -472,9 +495,9 @@ Rectangle { height: 40; anchors.left: parent.left; anchors.right: parent.right; - text: (itemIsJson ? ((purchasesReceived && balanceReceived) ? "Confirm Purchase" : "--") : "Get Item"); + text: ((root.isCertified) ? ((purchasesReceived && balanceReceived) ? "Confirm Purchase" : "--") : "Get Item"); onClicked: { - if (itemIsJson) { + if (root.isCertified) { buyButton.enabled = false; if (!root.shouldBuyWithControlledFailure) { Commerce.buy(itemId, itemPrice); @@ -576,7 +599,7 @@ Rectangle { RalewayBold { anchors.fill: parent; - text: "REZZED"; + text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)]; size: 18; color: hifi.colors.white; verticalAlignment: Text.AlignVCenter; @@ -592,7 +615,7 @@ Rectangle { // "Rez" button HifiControlsUit.Button { id: rezNowButton; - enabled: root.canRezCertifiedItems || root.isWearable; + enabled: root.canRezCertifiedItems || root.itemType === "wearable"; buttonGlyph: hifi.glyphs.lightning; color: hifi.buttons.red; colorScheme: hifi.colorSchemes.light; @@ -601,17 +624,27 @@ Rectangle { height: 50; anchors.left: parent.left; anchors.right: parent.right; - text: root.isWearable ? "Wear It" : "Rez It" + text: (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]; onClicked: { - sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable}); - rezzedNotifContainer.visible = true; - rezzedNotifContainerTimer.start(); - UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.isWearable ? "rez" : "wear"); + if (root.itemType === "contentSet") { + lightboxPopup.titleText = "Replace Content"; + lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain."; + lightboxPopup.button1text = "CANCEL"; + lightboxPopup.button1method = "root.visible = false;" + lightboxPopup.button2text = "CONFIRM"; + lightboxPopup.button2method = "sendToScript({method: 'checkout_rezClicked', itemHref: " + root.itemHref + ", itemType: " + root.itemType + "});"; + lightboxPopup.visible = true; + } else { + sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); + rezzedNotifContainer.visible = true; + rezzedNotifContainerTimer.start(); + UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.itemType); + } } } RalewaySemiBold { id: noPermissionText; - visible: !root.canRezCertifiedItems && !root.isWearable; + visible: !root.canRezCertifiedItems && root.itemType !== "wearable"; text: 'You do not have Certified Rez permissions in this domain.' // Text size size: 16; @@ -640,7 +673,7 @@ Rectangle { } RalewaySemiBold { id: explainRezText; - visible: !root.isWearable; + visible: root.itemType === "entity"; text: 'What does "Rez" mean?' // Text size size: 16; @@ -851,7 +884,7 @@ Rectangle { buyButton.color = hifi.buttons.red; root.shouldBuyWithControlledFailure = true; } else { - buyButton.text = (itemIsJson ? ((purchasesReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item"); + buyButton.text = (root.isCertified ? ((purchasesReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item"); buyButton.color = hifi.buttons.blue; root.shouldBuyWithControlledFailure = false; } @@ -901,7 +934,7 @@ Rectangle { } function setBuyText() { - if (root.itemIsJson) { + if (root.isCertified) { if (root.purchasesReceived && root.balanceReceived) { if (root.balanceAfterPurchase < 0) { if (root.alreadyOwned) { diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 361b9931a4..41f2d919cd 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -41,8 +41,11 @@ Item { property int limitedRun; property string itemType; property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"]; - property var buttonTextNormal: ["REZ", "WEAR", "SWAP", "INSTALL", "WEAR"]; - property var buttonTextClicked: ["REZZED", "WORN", "SWAPPED", "INSTALLED", "WORN"] + property var buttonTextNormal: ["REZ", "WEAR", "REPLACE", "INSTALL", "WEAR"]; + property var buttonTextClicked: ["REZZED", "WORN", "REPLACED", "INSTALLED", "WORN"] + property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar]; + property bool showConfirmation: false; + property bool hasPermissionToRezThis; property string originalStatusText; property string originalStatusColor; @@ -50,6 +53,23 @@ Item { height: 110; width: parent.width; + Connections { + target: Commerce; + + onContentSetChanged: { + if (contentSetMarketplaceID === root.itemId) { + showConfirmation = true; + } + } + } + + onItemTypeChanged: { + if ((itemType === "entity" && (!Entities.canRezCertified() && !Entities.canRezTmpCertified())) || + (itemType === "contentSet" && !Entities.canReplaceContent())) { + root.hasPermissionToRezThis = false; + } + } + onPurchaseStatusChangedChanged: { if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") { root.originalStatusText = statusText.text; @@ -60,6 +80,15 @@ Item { } } + onShowConfirmationChanged: { + if (root.showConfirmation) { + rezzedNotifContainer.visible = true; + rezzedNotifContainerTimer.start(); + UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.itemType); + root.showConfirmation = false; + } + } + Timer { id: confirmedTimer; interval: 3000; @@ -325,7 +354,7 @@ Item { RalewayBold { anchors.fill: parent; text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)]; - size: 18; + size: 15; color: hifi.colors.white; verticalAlignment: Text.AlignVCenter; horizontalAlignment: Text.AlignHCenter; @@ -353,10 +382,12 @@ Item { enabled: (root.canRezCertifiedItems || root.itemType === "wearable") && root.purchaseStatus !== "invalidated"; onClicked: { - sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); - rezzedNotifContainer.visible = true; - rezzedNotifContainerTimer.start(); - UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.itemType === "wearable" ? "rez" : "wear"); + if (root.itemType === "contentSet") { + sendToPurchases({method: 'showReplaceContentLightbox', itemId: root.itemId, itemHref: root.itemHref}); + } else { + sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); + root.showConfirmation = true; + } } style: ButtonStyle { @@ -396,13 +427,13 @@ Item { label: Item { HiFiGlyphs { - id: lightningIcon; - text: hifi.glyphs.lightning; + id: rezIcon; + text: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; // Size - size: 32; + size: 60; // Anchors anchors.top: parent.top; - anchors.topMargin: 12; + anchors.topMargin: 0; anchors.left: parent.left; anchors.right: parent.right; horizontalAlignment: Text.AlignHCenter; @@ -411,8 +442,8 @@ Item { : hifi.buttons.disabledTextColor[control.colorScheme] } RalewayBold { - anchors.top: lightningIcon.bottom; - anchors.topMargin: -20; + anchors.top: rezIcon.bottom; + anchors.topMargin: -4; anchors.right: parent.right; anchors.left: parent.left; anchors.bottom: parent.bottom; diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 922ba54822..956bfa7c26 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -455,10 +455,16 @@ Rectangle { limitedRun: model.limited_run; displayedItemCount: model.displayedItemCount; itemType: { - if (model.download_url.indexOf(".fst") > -1) { + if (model.root_file_url.indexOf(".fst") > -1) { "avatar"; } else if (model.categories.indexOf("Wearables") > -1) { "wearable"; + } else if (model.root_file_url.endsWith('.json.gz')) { + "contentSet"; + } else if (model.root_file_url.endsWith('.json')) { + "entity"; + } else if (model.root_file_url.endsWith('.js')) { + "app"; } else { "entity"; } @@ -490,6 +496,14 @@ Rectangle { lightboxPopup.button1text = "CLOSE"; lightboxPopup.button1method = "root.visible = false;" lightboxPopup.visible = true; + } else if (msg.method === "showReplaceContentLightbox") { + lightboxPopup.titleText = "Replace Content"; + lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain."; + lightboxPopup.button1text = "CANCEL"; + lightboxPopup.button1method = "root.visible = false;" + lightboxPopup.button2text = "CONFIRM"; + lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemId + "', '" + msg.itemHref + "'); root.visible = false;"; + lightboxPopup.visible = true; } else if (msg.method === "setFilterText") { filterBar.text = msg.filterText; } diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 5da587ea57..16b74f6b54 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -354,5 +354,9 @@ Item { readonly property string wallet: "\ue027" readonly property string paperPlane: "\ue028" readonly property string passphrase: "\ue029" + readonly property string globe: "\ue02c" + readonly property string wand: "\ue02d" + readonly property string hat: "\ue02e" + readonly property string install: "\ue02f" } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index be2a54b8e9..576d080947 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6176,6 +6176,24 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { return true; } +void Application::replaceDomainContent(const QString& url) { + qCDebug(interfaceapp) << "Attempting to replace domain content: " << url; + QByteArray urlData(url.toUtf8()); + auto limitedNodeList = DependencyManager::get(); + limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { + return node->getType() == NodeType::EntityServer && node->getActiveSocket(); + }, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) { + auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true); + octreeFilePacket->write(urlData); + limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); + }); + auto addressManager = DependencyManager::get(); + addressManager->handleLookupString(DOMAIN_SPAWNING_POINT); + QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT; + qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress; + DependencyManager::get()->setHomeLocationToAddress(newHomeAddress); +} + bool Application::askToReplaceDomainContent(const QString& url) { QString methodDetails; const int MAX_CHARACTERS_PER_LINE = 90; @@ -6195,21 +6213,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { QString details; if (static_cast(answer.toInt()) == QMessageBox::Yes) { // Given confirmation, send request to domain server to replace content - qCDebug(interfaceapp) << "Attempting to replace domain content: " << url; - QByteArray urlData(url.toUtf8()); - auto limitedNodeList = DependencyManager::get(); - limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { - return node->getType() == NodeType::EntityServer && node->getActiveSocket(); - }, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) { - auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true); - octreeFilePacket->write(urlData); - limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode); - }); - auto addressManager = DependencyManager::get(); - addressManager->handleLookupString(DOMAIN_SPAWNING_POINT); - QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT; - qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress; - DependencyManager::get()->setHomeLocationToAddress(newHomeAddress); + replaceDomainContent(url); details = "SuccessfulRequestToReplaceContent"; } else { details = "UserDeclinedToReplaceContent"; diff --git a/interface/src/Application.h b/interface/src/Application.h index ddb8ce11e5..2dd83f39eb 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -284,6 +284,8 @@ public: bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; } void saveNextPhysicsStats(QString filename); + void replaceDomainContent(const QString& url); + signals: void svoImportRequested(const QString& url); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index c9caa393ce..ba52edba4f 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -15,6 +15,8 @@ #include "Ledger.h" #include "Wallet.h" #include +#include +#include QmlCommerce::QmlCommerce() { auto ledger = DependencyManager::get(); @@ -163,3 +165,14 @@ void QmlCommerce::transferHfcToUsername(const QString& username, const int& amou QString key = keys[0]; ledger->transferHfcToUsername(key, username, amount, optionalMessage); } + +void QmlCommerce::replaceContentSet(const QString& id, const QString& url) { + qApp->replaceDomainContent(url); + QJsonObject messageProperties = { + { "status", "SuccessfulRequestToReplaceContent" }, + { "content_set_url", url } + }; + UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); + + emit contentSetChanged(id); +} diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index b261ee6de6..aa939a439d 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -48,6 +48,8 @@ signals: void transferHfcToNodeResult(QJsonObject result); void transferHfcToUsernameResult(QJsonObject result); + void contentSetChanged(const QString& contentSetMarketplaceID); + protected: Q_INVOKABLE void getWalletStatus(); @@ -71,6 +73,8 @@ protected: Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage); + + Q_INVOKABLE void replaceContentSet(const QString& id, const QString& url); }; #endif // hifi_QmlCommerce_h diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 4342f0e683..f9449cca34 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -101,6 +101,11 @@ bool EntityScriptingInterface::canWriteAssets() { return nodeList->getThisNodeCanWriteAssets(); } +bool EntityScriptingInterface::canReplaceContent() { + auto nodeList = DependencyManager::get(); + return nodeList->getThisNodeCanReplaceContent(); +} + void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { if (_entityTree) { disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index d1b321dbca..30e1e6ce1c 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -144,6 +144,12 @@ public slots: */ Q_INVOKABLE bool canWriteAssets(); + /**jsdoc + * @function Entities.canReplaceContent + * @return {bool} `true` if the DomainServer will allow this Node/Avatar to replace the domain's content set + */ + Q_INVOKABLE bool canReplaceContent(); + /**jsdoc * Add a new entity with the specified properties. If `clientOnly` is true, the entity will * not be sent to the server and will only be visible/accessible on the local client. diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index b43fe545fa..95d9294063 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -65,7 +65,7 @@ var selectionDisplay = null; // for gridTool.js to ignore var onMarketplaceScreen = false; var onCommerceScreen = false; - var debugCheckout = false; + var debugCheckout = true; var debugError = false; function showMarketplace() { if (!debugCheckout) { @@ -75,11 +75,11 @@ var selectionDisplay = null; // for gridTool.js to ignore tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH); tablet.sendToQml({ method: 'updateCheckoutQML', params: { - itemId: '0d90d21c-ce7a-4990-ad18-e9d2cf991027', - itemName: 'Test Flaregun', - itemPrice: (debugError ? 10 : 17), - itemHref: 'http://mpassets.highfidelity.com/0d90d21c-ce7a-4990-ad18-e9d2cf991027-v1/flaregun.json', - categories: ["Wearables", "Miscellaneous"] + itemId: 'e197e3d7-eafc-4aa5-9341-acee57174fe9', + itemName: 'Oasis', + itemPrice: (debugError ? 10 : 11), + itemHref: 'http://mpassets-staging.highfidelity.com/e197e3d7-eafc-4aa5-9341-acee57174fe9-v1/oasis_Aug15.json.gz', + categories: ["Miscellaneous"] } }); } @@ -240,6 +240,11 @@ var selectionDisplay = null; // for gridTool.js to ignore var wearableLocalDimensions = null; var wearableDimensions = null; + if (itemType === "contentSet") { + console.log("Item is a content set; codepath shouldn't go here.") + return; + } + if (isWearable) { var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms"); if (!wearableTransforms) { From 0809210dc3cb92948f0173828e244d405681b743 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 13 Feb 2018 11:16:48 -0800 Subject: [PATCH 25/54] No permission card --- .../hifi/commerce/purchases/PurchasedItem.qml | 100 +++++++++++++++++- .../qml/hifi/commerce/purchases/Purchases.qml | 84 +++------------ .../AccountServicesScriptingInterface.h | 2 +- 3 files changed, 113 insertions(+), 73 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 41f2d919cd..9db847eada 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -29,7 +29,6 @@ Item { id: root; property string purchaseStatus; property bool purchaseStatusChanged; - property bool canRezCertifiedItems: false; property string itemName; property string itemId; property string itemPreviewImageUrl; @@ -67,6 +66,8 @@ Item { if ((itemType === "entity" && (!Entities.canRezCertified() && !Entities.canRezTmpCertified())) || (itemType === "contentSet" && !Entities.canReplaceContent())) { root.hasPermissionToRezThis = false; + } else { + root.hasPermissionToRezThis = true; } } @@ -128,15 +129,19 @@ Item { } } - + TextMetrics { + id: itemNameTextMetrics; + font: itemName.font; + text: itemName.text; + } RalewaySemiBold { id: itemName; anchors.top: itemPreviewImage.top; anchors.topMargin: 4; anchors.left: itemPreviewImage.right; anchors.leftMargin: 8; - anchors.right: buttonContainer.left; - anchors.rightMargin: 8; + width: root.hasPermissionToRezThis ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width) : + Math.min(itemNameTextMetrics.tightBoundingRect.width + 2, buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - noPermissionGlyph.width + 2); height: paintedHeight; // Text size size: 24; @@ -162,6 +167,91 @@ Item { } } } + HiFiGlyphs { + id: noPermissionGlyph; + visible: !root.hasPermissionToRezThis; + anchors.verticalCenter: itemName.verticalCenter; + anchors.left: itemName.right; + anchors.leftMargin: itemName.truncated ? -14 : -2; + text: hifi.glyphs.info; + // Size + size: 40; + width: 32; + // Style + color: hifi.colors.redAccent; + + MouseArea { + anchors.fill: parent; + hoverEnabled: true; + + onEntered: { + noPermissionGlyph.color = hifi.colors.redHighlight; + } + onExited: { + noPermissionGlyph.color = hifi.colors.redAccent; + } + onClicked: { + permissionExplanationCard.visible = true; + } + } + } + Rectangle { + id: permissionExplanationCard; + z: 995; + visible: false; + anchors.fill: parent; + color: hifi.colors.white; + + RalewayRegular { + id: permissionExplanationText; + text: { + if (root.itemType === "contentSet") { + "You do not have 'Replace Content' permissions in this domain. Learn more"; + } else if (root.itemType === "entity") { + "You do not have 'Rez Certified' permissions in this domain. Learn more"; + } + } + size: 16; + anchors.left: parent.left; + anchors.leftMargin: 30; + anchors.top: parent.top; + anchors.bottom: parent.bottom; + anchors.right: permissionExplanationGlyph.left; + color: hifi.colors.baseGray; + wrapMode: Text.WordWrap; + verticalAlignment: Text.AlignVCenter; + + onLinkActivated: { + sendToPurchases({method: 'showPermissionsExplanation', itemType: root.itemType}); + } + } + // "Close" button + HiFiGlyphs { + id: permissionExplanationGlyph; + text: hifi.glyphs.close; + color: hifi.colors.baseGray; + size: 26; + anchors.top: parent.top; + anchors.bottom: parent.bottom; + anchors.right: parent.right; + width: 77; + horizontalAlignment: Text.AlignHCenter; + verticalAlignment: Text.AlignVCenter; + MouseArea { + anchors.fill: parent; + hoverEnabled: true; + onEntered: { + parent.text = hifi.glyphs.closeInverted; + } + onExited: { + parent.text = hifi.glyphs.close; + } + onClicked: { + permissionExplanationCard.visible = false; + } + } + } + } Item { id: certificateContainer; @@ -379,7 +469,7 @@ Item { anchors.right: parent.right; anchors.rightMargin: 4; width: height; - enabled: (root.canRezCertifiedItems || root.itemType === "wearable") && root.purchaseStatus !== "invalidated"; + enabled: root.hasPermissionToRezThis && root.purchaseStatus !== "invalidated"; onClicked: { if (root.itemType === "contentSet") { diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 956bfa7c26..daa23d29c8 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -32,7 +32,6 @@ Rectangle { property bool securityImageResultReceived: false; property bool purchasesReceived: false; property bool punctuationMode: false; - property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); property bool pendingInventoryReply: true; property bool isShowingMyItems: false; property bool isDebuggingFirstUseTutorial: false; @@ -365,69 +364,6 @@ Rectangle { id: filteredPurchasesModel; } - Rectangle { - id: cantRezCertified; - visible: !root.canRezCertifiedItems; - color: "#FFC3CD"; - radius: 4; - border.color: hifi.colors.redAccent; - border.width: 1; - anchors.top: separator.bottom; - anchors.topMargin: 12; - anchors.left: parent.left; - anchors.leftMargin: 16; - anchors.right: parent.right; - anchors.rightMargin: 16; - height: 80; - - HiFiGlyphs { - id: lightningIcon; - text: hifi.glyphs.lightning; - // Size - size: 36; - // Anchors - anchors.top: parent.top; - anchors.topMargin: 18; - anchors.left: parent.left; - anchors.leftMargin: 12; - horizontalAlignment: Text.AlignHCenter; - // Style - color: hifi.colors.lightGray; - } - - RalewayRegular { - text: "You don't have permission to rez certified items in this domain. " + - 'Learn More'; - // Text size - size: 18; - // Anchors - anchors.top: parent.top; - anchors.topMargin: 4; - anchors.left: lightningIcon.right; - anchors.leftMargin: 8; - anchors.right: parent.right; - anchors.rightMargin: 8; - anchors.bottom: parent.bottom; - anchors.bottomMargin: 4; - // Style - color: hifi.colors.baseGray; - wrapMode: Text.WordWrap; - // Alignment - verticalAlignment: Text.AlignVCenter; - - onLinkActivated: { - lightboxPopup.titleText = "Rez Permission Required"; - lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.

" + - "Use the GOTO app to visit another domain or go to your own sandbox."; - lightboxPopup.button1text = "CLOSE"; - lightboxPopup.button1method = "root.visible = false;" - lightboxPopup.button2text = "OPEN GOTO"; - lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});"; - lightboxPopup.visible = true; - } - } - } - ListView { id: purchasesContentsList; visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0); @@ -436,13 +372,12 @@ Rectangle { snapMode: ListView.SnapToItem; highlightRangeMode: ListView.StrictlyEnforceRange; // Anchors - anchors.top: root.canRezCertifiedItems ? separator.bottom : cantRezCertified.bottom; + anchors.top: separator.bottom; anchors.topMargin: 12; anchors.left: parent.left; anchors.bottom: parent.bottom; width: parent.width; delegate: PurchasedItem { - canRezCertifiedItems: root.canRezCertifiedItems; itemName: title; itemId: id; itemPreviewImageUrl: preview; @@ -466,7 +401,7 @@ Rectangle { } else if (model.root_file_url.endsWith('.js')) { "app"; } else { - "entity"; + "unknown"; } } anchors.topMargin: 10; @@ -504,6 +439,21 @@ Rectangle { lightboxPopup.button2text = "CONFIRM"; lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemId + "', '" + msg.itemHref + "'); root.visible = false;"; lightboxPopup.visible = true; + } else if (msg.method === "showPermissionsExplanation") { + if (msg.itemType === "entity") { + lightboxPopup.titleText = "Rez Certified Permission"; + lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.

" + + "Use the GOTO app to visit another domain or go to your own sandbox."; + lightboxPopup.button2text = "OPEN GOTO"; + lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});"; + } else if (msg.itemType === "contentSet") { + lightboxPopup.titleText = "Replace Content Permission"; + lightboxPopup.bodyText = "You do not have the permission 'Replace Content' in this domain's server settings. The domain owner " + + "must enable it for you before you can replace content sets in this domain."; + } + lightboxPopup.button1text = "CLOSE"; + lightboxPopup.button1method = "root.visible = false;" + lightboxPopup.visible = true; } else if (msg.method === "setFilterText") { filterBar.text = msg.filterText; } diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h index 012c37305d..cfa51697af 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.h +++ b/interface/src/scripting/AccountServicesScriptingInterface.h @@ -38,7 +38,7 @@ class AccountServicesScriptingInterface : public QObject { Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged) Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged) Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged) - Q_PROPERTY(QUrl metaverseServerURL READ getMetaverseServerURL) + Q_PROPERTY(QUrl metaverseServerURL READ getMetaverseServerURL CONSTANT) public: static AccountServicesScriptingInterface* getInstance(); From 1b7253dc7f8d20d8e2acc5a66c1d752cf556061f Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 13 Feb 2018 13:54:50 -0800 Subject: [PATCH 26/54] Already Owned endpoint --- interface/src/commerce/Ledger.cpp | 11 +++++++++++ interface/src/commerce/Ledger.h | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 10ddd4c110..f319881035 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -336,3 +336,14 @@ void Ledger::transferHfcToUsername(const QString& hfc_key, const QString& userna auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure"); } + +void Ledger::alreadyOwnedSuccess(QNetworkReply& reply) { apiResponse("alreadyOwned", reply); } +void Ledger::alreadyOwnedFailure(QNetworkReply& reply) { failResponse("alreadyOwned", reply); } +void Ledger::alreadyOwned(const QString& marketplaceId) { + auto wallet = DependencyManager::get(); + QString endpoint = "already_owned"; + QJsonObject request; + request["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys()); + request["marketplace_item_id"] = marketplaceId; + send(endpoint, "alreadyOwnedSuccess", "alreadyOwnedFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::None, request); +} diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 1b56c893ab..ac9fe950d9 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -35,6 +35,7 @@ public: void certificateInfo(const QString& certificateId); void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage); void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage); + void alreadyOwned(const QString& marketplaceId); enum CertificateStatus { CERTIFICATE_STATUS_UNKNOWN = 0, @@ -55,6 +56,7 @@ signals: void certificateInfoResult(QJsonObject result); void transferHfcToNodeResult(QJsonObject result); void transferHfcToUsernameResult(QJsonObject result); + void alreadyOwnedResult(QJsonObject result); void updateCertificateStatus(const QString& certID, uint certStatus); @@ -79,6 +81,8 @@ public slots: void transferHfcToNodeFailure(QNetworkReply& reply); void transferHfcToUsernameSuccess(QNetworkReply& reply); void transferHfcToUsernameFailure(QNetworkReply& reply); + void alreadyOwnedSuccess(QNetworkReply& reply); + void alreadyOwnedFailure(QNetworkReply& reply); private: QJsonObject apiResponse(const QString& label, QNetworkReply& reply); From 69a06bf1b75ebecc57d61899b509e7fbd86325da Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 13 Feb 2018 14:42:03 -0800 Subject: [PATCH 27/54] Wrong fonts file --- interface/resources/fonts/hifi-glyphs.ttf | Bin 31500 -> 32536 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/interface/resources/fonts/hifi-glyphs.ttf b/interface/resources/fonts/hifi-glyphs.ttf index 8907cf7858dd304cdad024bfa1ff4ca5cd94caf9..8db0377f88864810e7f893132449ad8e258e68cd 100644 GIT binary patch delta 1476 zcmXw3TWl0n82_O*-HyEv#{Om?#?c=y-?cjWd2_BDjG<32kZU z0)>aJHxg7(5MvC2Cf=S*R2sY_24jqXMB|I%3mOul55AC?Xm~JSX2Fx3|Cay%a{mAP z`A+;pZ``Fi2tWi+L&3(u!N-S=9DDY4VD?`C$%odi8^k3DVD<)p%!WZQ2gd(%?ap z)rrwRmtNcg9J&M0+|>T*nl*CvQDEjnK(sZQBOv{We{4r=#osU(f^+@d+qdp(cKg<= z)K90+4A7I*J$H_LTDA;>=)+(mQvn(`*?_+q>s!7})Cg)YND5)L}i3lDu*g@>^Lo3Ra(032c3rFdn4 zDrMQPx&_a-P3acAf?KfTLYmUeRXpF8o^QuRp%TObQSf}rk!9a5Sx%7d3+cw~cwkvU zbuLv`OJ-b1w^9x&Y2>|w2S?b*^k$}63m3$#gw{MSS$3isqcxXH>r0$@wz=quMe`jy zo}E8q<};moHsiMF-PuZOQzFrvUy*Mf&sp;Zh;%1r#TVK-U9NplBcj^KrmZRwF`i4R zddIdlLv20YUQfn4#Ar4vW=PF_=d=si^Vd+igWnk<-tk*UdT2`~tIqK33!SlyE52^e zH}%NqP_m0{=ZuKdR90&4;w5c5&jz0p!XO6eGrELkw4)cxu?CMcW;hEhD!8)XN|7cr zO?Ij1dxc!RQqDOk$~l(VN0wPC_EV`?DaW019~I3`*3g!)oqj48Q&fJSrBiSVOUU=q zWXEkO0^c8CzUO-lS4iOnA@6=9Mncl38#R3>r0e>S+^9)iM6V{pM!m%_T8wbgXw&sB zUH`pJ*V}cr!!%8Em@}dCCMji9Xi_LCu1LXDm1$fPn&cr><8Nt9*H}bXgeKLPuIwAu z*l;MMhc@VPScs;Z0esj<8b;Cx+ooyi`ZJ-nknaB6ka<>Db+t)I5!Hm0%G-+2nBYtZ zO-iYTxW>;jp(zoK>zW#hX=*7ZHunSh*mcwTfh?e)obz#S(M3WB&v#N(>yK|BA1Af zWU**?{K}OpR-#-28mx?QCfC@_}MwPPjRKkit? zY8||{r>l78vD#~NdhU-}f;4)OUZN9p^1`8Sc{)5gd1&u}{gV@;leKAnxH`FuA0Dk9 nkb5VmYt`}bGgptM3a3EezyoRtC>r1Qzw_gL&ibFbZr}P3tv~vd delta 456 zcmYL`ze^hd6vsdB?ivGWt%HPM4=mM1Mf4Q>MRcjgr6GbPb*Xy9=nXkNNR&$k^$&vx3S#6gf)5_=7w`MNU*3mXsb0$t0z6?CmAO>v zb-HZFZ=iAo=(E!^DSRSOIRTz$<_Cr{Utc*O3qUq!o6cs>=>RCdL0Mfhi%z3~3Y8x~ zbgfWct-r~%Kx6?5bt`YKw5AVxfIq;9W#xBFZBWiZ+JSD%F1ekTi8hc=ATJ6VIdg8@ zw%}0`M7K@X;X)Qc#sWg?rk%f-_?(4eu;V!!#nQ^lLmf)rAtIqTfoI>cf0v#n{}EFN z?CiZCZ$`zBzmrMXt4+yU>GM9ys2IUSy>~r?K$cO%Oh=RHKpRn-Slj1)-ec7eZ$|4< zJSXy{;Qil{TQ{F+p7&5{YGuv-IqP@m)jxURryGp4VfT~21*Fs3M9g2P^(lC UG`K$#yosNa2ggBt;P1!p0BG@JE&u=k From a477a3da7004f3c3d3a0b14ffb1f95536f8bccad Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 13 Feb 2018 15:04:31 -0800 Subject: [PATCH 28/54] Done with My Purchases flow for now --- .../qml/hifi/commerce/common/CommerceLightbox.qml | 4 ++++ .../qml/hifi/commerce/purchases/Purchases.qml | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml b/interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml index 8b0ec17232..b24af716ad 100644 --- a/interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml +++ b/interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml @@ -100,6 +100,10 @@ Rectangle { size: 20; verticalAlignment: Text.AlignTop; wrapMode: Text.WordWrap; + + onLinkActivated: { + sendToParent({ method: 'commerceLightboxLinkClicked', linkUrl: link }); + } } Item { diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index daa23d29c8..91fed207bc 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -147,7 +147,11 @@ Rectangle { Connections { onSendToParent: { - sendToScript(msg); + if (msg.method === 'commerceLightboxLinkClicked') { + Qt.openUrlExternally(msg.linkUrl); + } else { + sendToScript(msg); + } } } } @@ -433,7 +437,11 @@ Rectangle { lightboxPopup.visible = true; } else if (msg.method === "showReplaceContentLightbox") { lightboxPopup.titleText = "Replace Content"; - lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain."; + lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " + + "If you want to save the state of the content in this domain, create a backup before proceeding.

" + + "For more information about backing up and restoring content, " + + "" + + "click here to open info on your desktop browser."; lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = "root.visible = false;" lightboxPopup.button2text = "CONFIRM"; From 0fca843667fa1f5723849674ce3da22d4561c999 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 14 Feb 2018 10:24:34 -0800 Subject: [PATCH 29/54] Integrate 'alreadyOwned' endpoint --- .../qml/hifi/commerce/checkout/Checkout.qml | 38 ++++++++----------- interface/src/commerce/QmlCommerce.cpp | 7 ++++ interface/src/commerce/QmlCommerce.h | 3 ++ 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index c141b48d32..bd3f706004 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -28,7 +28,7 @@ Rectangle { id: root; objectName: "checkout" property string activeView: "initialize"; - property bool purchasesReceived: false; + property bool ownershipStatusReceived: false; property bool balanceReceived: false; property string itemName; property string itemId; @@ -106,14 +106,15 @@ Rectangle { } } - onInventoryResult: { + onAlreadyOwnedResult: { if (result.status !== 'success') { - console.log("Failed to get purchases", result.data.message); + console.log("Failed to get Already Owned status", result.data.message); } else { - root.purchasesReceived = true; - if (purchasesContains(result.data.assets, itemId)) { - root.alreadyOwned = true; + root.ownershipStatusReceived = true; + if (result.data.marketplace_item_id === root.itemId) { + root.alreadyOwned = result.data.already_owned; } else { + console.log("WARNING - Received 'Already Owned' status about different Marketplace ID!"); root.alreadyOwned = false; } root.setBuyText(); @@ -122,7 +123,8 @@ Rectangle { } onItemIdChanged: { - Commerce.inventory(); + root.ownershipStatusReceived = false; + Commerce.alreadyOwned(root.itemId); itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg"; } @@ -136,6 +138,7 @@ Rectangle { } else if (root.itemHref.endsWith('.js')) { root.itemType = "app"; } else { + console.log("WARNING - Item type is UNKNOWN!"); root.itemType = "entity"; } } @@ -226,7 +229,7 @@ Rectangle { color: hifi.colors.white; Component.onCompleted: { - purchasesReceived = false; + ownershipStatusReceived = false; balanceReceived = false; Commerce.getWalletStatus(); } @@ -487,7 +490,7 @@ Rectangle { // "Buy" button HifiControlsUit.Button { id: buyButton; - enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || (!root.isCertified); + enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived) || (!root.isCertified); color: hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; anchors.top: checkoutActionButtonsContainer.top; @@ -495,7 +498,7 @@ Rectangle { height: 40; anchors.left: parent.left; anchors.right: parent.right; - text: ((root.isCertified) ? ((purchasesReceived && balanceReceived) ? "Confirm Purchase" : "--") : "Get Item"); + text: ((root.isCertified) ? ((ownershipStatusReceived && balanceReceived) ? "Confirm Purchase" : "--") : "Get Item"); onClicked: { if (root.isCertified) { buyButton.enabled = false; @@ -884,7 +887,7 @@ Rectangle { buyButton.color = hifi.buttons.red; root.shouldBuyWithControlledFailure = true; } else { - buyButton.text = (root.isCertified ? ((purchasesReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item"); + buyButton.text = (root.isCertified ? ((ownershipStatusReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item"); buyButton.color = hifi.buttons.blue; root.shouldBuyWithControlledFailure = false; } @@ -924,18 +927,9 @@ Rectangle { } signal sendToScript(var message); - function purchasesContains(purchasesJson, id) { - for (var idx = 0; idx < purchasesJson.length; idx++) { - if(purchasesJson[idx].id === id) { - return true; - } - } - return false; - } - function setBuyText() { if (root.isCertified) { - if (root.purchasesReceived && root.balanceReceived) { + if (root.ownershipStatusReceived && root.balanceReceived) { if (root.balanceAfterPurchase < 0) { if (root.alreadyOwned) { buyText.text = "Your Wallet does not have sufficient funds to purchase this item again.
" + @@ -978,7 +972,7 @@ Rectangle { root.activeView = "checkoutSuccess"; } root.balanceReceived = false; - root.purchasesReceived = false; + root.ownershipStatusReceived = false; Commerce.inventory(); Commerce.balance(); } diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index ba52edba4f..5458925d55 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -30,9 +30,11 @@ QmlCommerce::QmlCommerce() { connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult); connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult); connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult); + connect(ledger.data(), &Ledger::alreadyOwnedResult, this, &QmlCommerce::alreadyOwnedResult); connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus); connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult); connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult); + connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult); auto accountManager = DependencyManager::get(); connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { @@ -176,3 +178,8 @@ void QmlCommerce::replaceContentSet(const QString& id, const QString& url) { emit contentSetChanged(id); } + +void QmlCommerce::alreadyOwned(const QString& marketplaceId) { + auto ledger = DependencyManager::get(); + ledger->alreadyOwned(marketplaceId); +} diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index aa939a439d..dc38dcad19 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -42,6 +42,7 @@ signals: void historyResult(QJsonObject result); void accountResult(QJsonObject result); void certificateInfoResult(QJsonObject result); + void alreadyOwnedResult(QJsonObject result); void updateCertificateStatus(const QString& certID, uint certStatus); @@ -70,10 +71,12 @@ protected: Q_INVOKABLE void account(); Q_INVOKABLE void certificateInfo(const QString& certificateId); + Q_INVOKABLE void alreadyOwned(const QString& marketplaceId); Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage); + Q_INVOKABLE void replaceContentSet(const QString& id, const QString& url); }; From 5a8b8d4ac84068c47d5a06d66632cb3fd21aaa4c Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 14 Feb 2018 16:44:02 -0800 Subject: [PATCH 30/54] Lots of changes --- .../qml/hifi/commerce/checkout/Checkout.qml | 132 +++++++++++++----- .../InspectionCertificate.qml | 1 + .../hifi/commerce/purchases/PurchasedItem.qml | 2 + interface/src/commerce/Ledger.cpp | 5 +- 4 files changed, 105 insertions(+), 35 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index bd3f706004..981d5c5b9a 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -40,8 +40,9 @@ Rectangle { property bool isCertified; property string itemType; property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"]; - property var buttonTextNormal: ["REZ IT", "WEAR IT", "SWAP CONTENT SET", "INSTALL IT", "WEAR IT"]; - property var buttonTextClicked: ["REZZED", "WORN", "SWAPPED", "INSTALLED", "WORN"] + property var buttonTextNormal: ["REZ IT", "WEAR IT", "REPLACE CONTENT SET", "INSTALL IT", "WEAR IT"]; + property var buttonTextClicked: ["REZZED", "WORN", "CONTENT SET REPLACED!", "INSTALLED", "WORN"] + property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar]; property bool shouldBuyWithControlledFailure: false; property bool debugCheckoutSuccess: false; property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); @@ -102,7 +103,7 @@ Rectangle { } else { root.balanceReceived = true; root.balanceAfterPurchase = result.data.balance - root.itemPrice; - root.setBuyText(); + root.refreshBuyUI(); } } @@ -117,7 +118,7 @@ Rectangle { console.log("WARNING - Received 'Already Owned' status about different Marketplace ID!"); root.alreadyOwned = false; } - root.setBuyText(); + root.refreshBuyUI(); } } } @@ -131,11 +132,11 @@ Rectangle { onItemHrefChanged: { if (root.itemHref.indexOf(".fst") > -1) { root.itemType = "avatar"; - } else if (root.itemHref.endsWith('.json.gz')) { + } else if (root.itemHref.indexOf('.json.gz') > -1) { root.itemType = "contentSet"; - } else if (root.itemHref.endsWith('.json')) { + } else if (root.itemHref.indexOf('.json') > -1) { root.itemType = "entity"; // "wearable" type handled later - } else if (root.itemHref.endsWith('.js')) { + } else if (root.itemHref.indexOf('.js') > -1) { root.itemType = "app"; } else { console.log("WARNING - Item type is UNKNOWN!"); @@ -304,6 +305,31 @@ Rectangle { anchors.left: parent.left; anchors.right: parent.right; + Rectangle { + id: loading; + z: 997; + visible: !root.ownershipStatusReceived || !root.balanceReceived; + anchors.fill: parent; + color: Qt.rgba(0.0, 0.0, 0.0, 0.7); + + // This object is always used in a popup. + // This MouseArea is used to prevent a user from being + // able to click on a button/mouseArea underneath the popup/section. + MouseArea { + anchors.fill: parent; + hoverEnabled: true; + propagateComposedEvents: false; + } + + AnimatedImage { + source: "../common/images/loader.gif" + width: 96; + height: width; + anchors.verticalCenter: parent.verticalCenter; + anchors.horizontalCenter: parent.horizontalCenter; + } + } + RalewayRegular { id: confirmPurchaseText; anchors.top: parent.top; @@ -437,7 +463,7 @@ Rectangle { Rectangle { id: buyTextContainer; visible: buyText.text !== ""; - anchors.top: cancelPurchaseButton.bottom; + anchors.top: parent.top; anchors.topMargin: 16; anchors.left: parent.left; anchors.right: parent.right; @@ -480,10 +506,23 @@ Rectangle { // Alignment horizontalAlignment: Text.AlignLeft; verticalAlignment: Text.AlignVCenter; + } + } - onLinkActivated: { - sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName}); - } + // "View in My Purchases" button + HifiControlsUit.Button { + id: viewInMyPurchasesButton; + visible: false; + color: hifi.buttons.blue; + colorScheme: hifi.colorSchemes.light; + anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top; + anchors.topMargin: 16; + height: 40; + anchors.left: parent.left; + anchors.right: parent.right; + text: "VIEW THIS ITEM IN MY PURCHASES"; + onClicked: { + sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName}); } } @@ -491,21 +530,38 @@ Rectangle { HifiControlsUit.Button { id: buyButton; enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived) || (!root.isCertified); - color: hifi.buttons.blue; + color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; - anchors.top: checkoutActionButtonsContainer.top; + anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom : + (buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top); anchors.topMargin: 16; height: 40; anchors.left: parent.left; anchors.right: parent.right; - text: ((root.isCertified) ? ((ownershipStatusReceived && balanceReceived) ? "Confirm Purchase" : "--") : "Get Item"); + text: ((root.isCertified) ? ((ownershipStatusReceived && balanceReceived) ? + (viewInMyPurchasesButton.visible ? "Buy It Again" : "Confirm Purchase") : "--") : "Get Item"); onClicked: { if (root.isCertified) { - buyButton.enabled = false; if (!root.shouldBuyWithControlledFailure) { - Commerce.buy(itemId, itemPrice); + if (root.itemType === "contentSet" && !Entities.canReplaceContent()) { + lightboxPopup.titleText = "Purchase Content Set"; + lightboxPopup.bodyText = "You will not be able to replace this domain's content with " + root.itemName + + " until the server owner gives you 'Replace Content' permissions.

Are you sure you want to purchase this content set?"; + lightboxPopup.button1text = "CANCEL"; + lightboxPopup.button1method = "root.visible = false;" + lightboxPopup.button2text = "CONFIRM"; + lightboxPopup.button2method = "Commerce.buy('" + root.itemId + "', " + root.itemPrice + ");" + + "root.visible = false; buyButton.enabled = false; loading.visible = true;"; + lightboxPopup.visible = true; + } else { + buyButton.enabled = false; + loading.visible = true; + Commerce.buy(root.itemId, root.itemPrice); + } } else { - Commerce.buy(itemId, itemPrice, true); + buyButton.enabled = false; + loading.visible = true; + Commerce.buy(root.itemId, root.itemPrice, true); } } else { if (urlHandler.canHandleUrl(itemHref)) { @@ -618,8 +674,10 @@ Rectangle { // "Rez" button HifiControlsUit.Button { id: rezNowButton; - enabled: root.canRezCertifiedItems || root.itemType === "wearable"; - buttonGlyph: hifi.glyphs.lightning; + enabled: (root.itemType === "entity" && root.canRezCertifiedItems) || + (root.itemType === "contentSet" && Entities.canReplaceContent()) || + root.itemType === "wearable"; + buttonGlyph: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; color: hifi.buttons.red; colorScheme: hifi.colorSchemes.light; anchors.top: completeText2.bottom; @@ -631,11 +689,17 @@ Rectangle { onClicked: { if (root.itemType === "contentSet") { lightboxPopup.titleText = "Replace Content"; - lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain."; + lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " + + "If you want to save the state of the content in this domain, create a backup before proceeding.

" + + "For more information about backing up and restoring content, " + + "
" + + "click here to open info on your desktop browser."; lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = "root.visible = false;" lightboxPopup.button2text = "CONFIRM"; - lightboxPopup.button2method = "sendToScript({method: 'checkout_rezClicked', itemHref: " + root.itemHref + ", itemType: " + root.itemType + "});"; + lightboxPopup.button2method = "Commerce.replaceContentSet('" + root.itemId + "', '" + root.itemHref + "');" + + "root.visible = false;rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start();" + + "UserActivityLogger.commerceEntityRezzed('" + root.itemId + "', 'checkout', '" + root.itemType + "');"; lightboxPopup.visible = true; } else { sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); @@ -919,7 +983,7 @@ Rectangle { itemHref = message.params.itemHref; referrer = message.params.referrer; itemAuthor = message.params.itemAuthor; - setBuyText(); + refreshBuyUI(); break; default: console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message)); @@ -927,13 +991,13 @@ Rectangle { } signal sendToScript(var message); - function setBuyText() { + function refreshBuyUI() { if (root.isCertified) { if (root.ownershipStatusReceived && root.balanceReceived) { if (root.balanceAfterPurchase < 0) { if (root.alreadyOwned) { - buyText.text = "Your Wallet does not have sufficient funds to purchase this item again.
" + - '
View the copy you own in My Purchases'; + buyText.text = "Your Wallet does not have sufficient funds to purchase this item again."; + viewInMyPurchasesButton.visible = true; } else { buyText.text = "Your Wallet does not have sufficient funds to purchase this item."; } @@ -943,15 +1007,19 @@ Rectangle { buyGlyph.size = 54; } else { if (root.alreadyOwned) { - buyText.text = 'You already own this item.
Purchasing it will buy another copy.
View this item in My Purchases
'; - buyTextContainer.color = "#FFD6AD"; - buyTextContainer.border.color = "#FAC07D"; - buyGlyph.text = hifi.glyphs.alert; - buyGlyph.size = 46; + viewInMyPurchasesButton.visible = true; } else { buyText.text = ""; } + + if (root.itemType === "contentSet" && !Entities.canReplaceContent()) { + buyText.text = "The domain owner must enable 'Replace Content' permissions for you in this " + + "domain's server settings before you can replace this domain's content with " + root.itemName + ""; + buyTextContainer.color = "#FFC3CD"; + buyTextContainer.border.color = "#F3808F"; + buyGlyph.text = hifi.glyphs.alert; + buyGlyph.size = 54; + } } } else { buyText.text = ""; @@ -973,7 +1041,7 @@ Rectangle { } root.balanceReceived = false; root.ownershipStatusReceived = false; - Commerce.inventory(); + Commerce.alreadyOwned(root.itemId); Commerce.balance(); } diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml index f493747c5e..a622349d00 100644 --- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml @@ -208,6 +208,7 @@ Rectangle { // able to click on a button/mouseArea underneath the popup/section. MouseArea { anchors.fill: parent; + hoverEnabled: true; propagateComposedEvents: false; } diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 9db847eada..d19a16e74e 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -209,6 +209,8 @@ Item { "You do not have 'Replace Content' permissions in this domain. Learn more"; } else if (root.itemType === "entity") { "You do not have 'Rez Certified' permissions in this domain. Learn more"; + } else { + "" } } size: 16; diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index f319881035..dff441f840 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -49,6 +49,7 @@ Handler(balance) Handler(inventory) Handler(transferHfcToNode) Handler(transferHfcToUsername) +Handler(alreadyOwned) void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) { auto accountManager = DependencyManager::get(); @@ -337,13 +338,11 @@ void Ledger::transferHfcToUsername(const QString& hfc_key, const QString& userna signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure"); } -void Ledger::alreadyOwnedSuccess(QNetworkReply& reply) { apiResponse("alreadyOwned", reply); } -void Ledger::alreadyOwnedFailure(QNetworkReply& reply) { failResponse("alreadyOwned", reply); } void Ledger::alreadyOwned(const QString& marketplaceId) { auto wallet = DependencyManager::get(); QString endpoint = "already_owned"; QJsonObject request; request["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys()); request["marketplace_item_id"] = marketplaceId; - send(endpoint, "alreadyOwnedSuccess", "alreadyOwnedFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::None, request); + send(endpoint, "alreadyOwnedSuccess", "alreadyOwnedFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, request); } From beb595266df7c23f50f6a1aa663dd353cb4468c1 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Thu, 15 Feb 2018 21:45:35 +0300 Subject: [PATCH 31/54] fix 4x 'fromQml' slots execution note: per discussion with Austion & Seth, TabletRoot should be the only entity sending 'sendToScript' signals to C++ --- libraries/qml/src/qml/OffscreenSurface.cpp | 2 +- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index 87fc8a3025..a84f3feb4d 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -331,9 +331,9 @@ void OffscreenSurface::finishQmlLoad(QQmlComponent* qmlComponent, qmlComponent->deleteLater(); onItemCreated(qmlContext, newItem); - connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant))); if (!rootCreated) { + connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant))); onRootCreated(); emit rootItemCreated(newItem); // Call this callback after rootitem is set, otherwise VrMenu wont work diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index ea34f3de76..749a60a578 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -305,7 +305,6 @@ void OffscreenQmlSurface::onItemCreated(QQmlContext* qmlContext, QQuickItem* new qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(eventBridge, qmlContext)); } - connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant))); } void OffscreenQmlSurface::onRootCreated() { From b8fb08dc74d80cd43469338640a579680637fe2e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 15 Feb 2018 11:24:22 -0800 Subject: [PATCH 32/54] Avatar support --- .../qml/hifi/commerce/checkout/Checkout.qml | 15 ++++++++++----- .../qml/hifi/commerce/purchases/PurchasedItem.qml | 2 ++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 981d5c5b9a..916e67e37f 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -40,8 +40,9 @@ Rectangle { property bool isCertified; property string itemType; property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"]; - property var buttonTextNormal: ["REZ IT", "WEAR IT", "REPLACE CONTENT SET", "INSTALL IT", "WEAR IT"]; - property var buttonTextClicked: ["REZZED", "WORN", "CONTENT SET REPLACED!", "INSTALLED", "WORN"] + property var itemTypesText: ["entity", "wearable", "content set", "app", "avatar"]; + property var buttonTextNormal: ["REZ", "WEAR", "REPLACE CONTENT SET", "INSTALL", "WEAR"]; + property var buttonTextClicked: ["REZZED!", "WORN!", "CONTENT SET REPLACED!", "INSTALLED!", "AVATAR CHANGED!"] property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar]; property bool shouldBuyWithControlledFailure: false; property bool debugCheckoutSuccess: false; @@ -529,6 +530,7 @@ Rectangle { // "Buy" button HifiControlsUit.Button { id: buyButton; + visible: !(root.itemType === "avatar" && viewInMyPurchasesButton.visible) enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived) || (!root.isCertified); color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; @@ -576,7 +578,7 @@ Rectangle { id: cancelPurchaseButton; color: hifi.buttons.noneBorderlessGray; colorScheme: hifi.colorSchemes.light; - anchors.top: buyButton.bottom; + anchors.top: buyButton.visible ? buyButton.bottom : viewInMyPurchasesButton.bottom; anchors.topMargin: 16; height: 40; anchors.left: parent.left; @@ -622,8 +624,9 @@ Rectangle { RalewaySemiBold { id: completeText2; - text: "The item " + '' + root.itemName + '' + - " has been added to your Purchases and a receipt will appear in your Wallet's transaction history."; + text: "The " + (root.itemTypesText)[itemTypesArray.indexOf(root.itemType)] + + '' + root.itemName + '' + + " has been added to your Purchases and a receipt will appear in your Wallet's transaction history."; // Text size size: 20; // Anchors @@ -701,6 +704,8 @@ Rectangle { "root.visible = false;rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start();" + "UserActivityLogger.commerceEntityRezzed('" + root.itemId + "', 'checkout', '" + root.itemType + "');"; lightboxPopup.visible = true; + } else if (root.itemType === "avatar") { + Avatar.skeletonModelURL = root.itemHref; } else { sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); rezzedNotifContainer.visible = true; diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index d19a16e74e..7b2cae5188 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -476,6 +476,8 @@ Item { onClicked: { if (root.itemType === "contentSet") { sendToPurchases({method: 'showReplaceContentLightbox', itemId: root.itemId, itemHref: root.itemHref}); + } else if (root.itemType === "avatar") { + Avatar.skeletonModelURL = root.itemHref; } else { sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); root.showConfirmation = true; From 807237282263e941235ab48b525a4079c712259d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 15 Feb 2018 13:14:56 -0800 Subject: [PATCH 33/54] Lots of changes --- .../resources/qml/controls-uit/Separator.qml | 4 +- .../qml/hifi/commerce/checkout/Checkout.qml | 69 ++++++++++--------- .../hifi/commerce/purchases/PurchasedItem.qml | 62 +++++++++++++---- .../qml/hifi/commerce/purchases/Purchases.qml | 16 +++-- interface/src/commerce/QmlCommerce.cpp | 8 +-- interface/src/commerce/QmlCommerce.h | 4 +- libraries/avatars/src/AvatarData.h | 3 +- libraries/avatars/src/ScriptAvatarData.cpp | 1 + libraries/avatars/src/ScriptAvatarData.h | 3 +- 9 files changed, 109 insertions(+), 61 deletions(-) diff --git a/interface/resources/qml/controls-uit/Separator.qml b/interface/resources/qml/controls-uit/Separator.qml index 5e2d278454..3350764ae9 100644 --- a/interface/resources/qml/controls-uit/Separator.qml +++ b/interface/resources/qml/controls-uit/Separator.qml @@ -14,8 +14,8 @@ import "../styles-uit" Item { property int colorScheme: 0; - readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray ]; - readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray ]; + readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray, "#89858C" ]; + readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray, "#89858C" ]; // Size height: colorScheme === 0 ? 2 : 1; diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 916e67e37f..08b100a64c 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -339,8 +339,8 @@ Rectangle { anchors.leftMargin: 16; width: paintedWidth; height: paintedHeight; - text: "Confirm Purchase:"; - color: hifi.colors.baseGray; + text: "Review Purchase:"; + color: hifi.colors.black; size: 28; } @@ -453,7 +453,7 @@ Rectangle { width: root.width; // Anchors anchors.top: separator2.bottom; - anchors.topMargin: 16; + anchors.topMargin: 0; anchors.left: parent.left; anchors.leftMargin: 16; anchors.right: parent.right; @@ -465,7 +465,7 @@ Rectangle { id: buyTextContainer; visible: buyText.text !== ""; anchors.top: parent.top; - anchors.topMargin: 16; + anchors.topMargin: 10; anchors.left: parent.left; anchors.right: parent.right; height: buyText.height + 30; @@ -517,8 +517,8 @@ Rectangle { color: hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top; - anchors.topMargin: 16; - height: 40; + anchors.topMargin: 10; + height: 50; anchors.left: parent.left; anchors.right: parent.right; text: "VIEW THIS ITEM IN MY PURCHASES"; @@ -536,8 +536,8 @@ Rectangle { colorScheme: hifi.colorSchemes.light; anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom : (buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top); - anchors.topMargin: 16; - height: 40; + anchors.topMargin: 10; + height: 50; anchors.left: parent.left; anchors.right: parent.right; text: ((root.isCertified) ? ((ownershipStatusReceived && balanceReceived) ? @@ -579,8 +579,8 @@ Rectangle { color: hifi.buttons.noneBorderlessGray; colorScheme: hifi.colorSchemes.light; anchors.top: buyButton.visible ? buyButton.bottom : viewInMyPurchasesButton.bottom; - anchors.topMargin: 16; - height: 40; + anchors.topMargin: 10; + height: 50; anchors.left: parent.left; anchors.right: parent.right; text: "Cancel" @@ -606,32 +606,32 @@ Rectangle { anchors.top: titleBarContainer.bottom; anchors.bottom: root.bottom; anchors.left: parent.left; - anchors.leftMargin: 16; + anchors.leftMargin: 20; anchors.right: parent.right; - anchors.rightMargin: 16; + anchors.rightMargin: 20; RalewayRegular { id: completeText; anchors.top: parent.top; - anchors.topMargin: 30; + anchors.topMargin: 18; anchors.left: parent.left; width: paintedWidth; height: paintedHeight; text: "Thank you for your order!"; color: hifi.colors.baseGray; - size: 28; + size: 36; } RalewaySemiBold { id: completeText2; text: "The " + (root.itemTypesText)[itemTypesArray.indexOf(root.itemType)] + - '' + root.itemName + '' + + ' ' + root.itemName + '' + " has been added to your Purchases and a receipt will appear in your Wallet's transaction history."; // Text size - size: 20; + size: 18; // Anchors anchors.top: completeText.bottom; - anchors.topMargin: 10; + anchors.topMargin: 15; height: paintedHeight; anchors.left: parent.left; anchors.right: parent.right; @@ -684,7 +684,7 @@ Rectangle { color: hifi.buttons.red; colorScheme: hifi.colorSchemes.light; anchors.top: completeText2.bottom; - anchors.topMargin: 30; + anchors.topMargin: 27; height: 50; anchors.left: parent.left; anchors.right: parent.right; @@ -700,12 +700,18 @@ Rectangle { lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = "root.visible = false;" lightboxPopup.button2text = "CONFIRM"; - lightboxPopup.button2method = "Commerce.replaceContentSet('" + root.itemId + "', '" + root.itemHref + "');" + + lightboxPopup.button2method = "Commerce.replaceContentSet('" + root.itemHref + "');" + "root.visible = false;rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start();" + "UserActivityLogger.commerceEntityRezzed('" + root.itemId + "', 'checkout', '" + root.itemType + "');"; lightboxPopup.visible = true; } else if (root.itemType === "avatar") { - Avatar.skeletonModelURL = root.itemHref; + lightboxPopup.titleText = "Change Avatar"; + lightboxPopup.bodyText = "This will change your current avatar to " + root.itemName + " while retaining your wearables."; + lightboxPopup.button1text = "CANCEL"; + lightboxPopup.button1method = "root.visible = false;" + lightboxPopup.button2text = "CONFIRM"; + lightboxPopup.button2method = "Avatar.skeletonModelURL('" + root.itemHref + "'); root.visible = false;"; + lightboxPopup.visible = true; } else { sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); rezzedNotifContainer.visible = true; @@ -768,9 +774,9 @@ Rectangle { RalewaySemiBold { id: myPurchasesLink; - text: 'View this item in My Purchases'; + text: 'View this item in My Purchases'; // Text size - size: 20; + size: 18; // Anchors anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom); anchors.topMargin: 40; @@ -790,12 +796,12 @@ Rectangle { RalewaySemiBold { id: walletLink; - text: 'View receipt in Wallet'; + text: 'View receipt in Wallet'; // Text size - size: 20; + size: 18; // Anchors anchors.top: myPurchasesLink.bottom; - anchors.topMargin: 20; + anchors.topMargin: 16; height: paintedHeight; anchors.left: parent.left; anchors.right: parent.right; @@ -813,12 +819,12 @@ Rectangle { RalewayRegular { id: pendingText; text: 'Your item is marked "pending" while your purchase is being confirmed. ' + - 'Learn More'; + 'Learn More'; // Text size - size: 20; + size: 18; // Anchors anchors.top: walletLink.bottom; - anchors.topMargin: 60; + anchors.topMargin: 32; height: paintedHeight; anchors.left: parent.left; anchors.right: parent.right; @@ -844,11 +850,10 @@ Rectangle { color: hifi.buttons.noneBorderlessGray; colorScheme: hifi.colorSchemes.light; anchors.bottom: parent.bottom; - anchors.bottomMargin: 20; + anchors.bottomMargin: 54; anchors.right: parent.right; - anchors.rightMargin: 14; - width: parent.width/2 - anchors.rightMargin; - height: 60; + width: 193; + height: 44; text: "Continue Shopping"; onClicked: { sendToScript({method: 'checkout_continueShopping', itemId: itemId}); diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 7b2cae5188..be460ea4ef 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -20,6 +20,7 @@ import "../../../styles-uit" import "../../../controls-uit" as HifiControlsUit import "../../../controls" as HifiControls import "../wallet" as HifiWallet +import TabletScriptingInterface 1.0 // references XXX from root context @@ -56,7 +57,17 @@ Item { target: Commerce; onContentSetChanged: { - if (contentSetMarketplaceID === root.itemId) { + if (contentSetHref === root.itemHref) { + showConfirmation = true; + } + } + } + + Connections { + target: MyAvatar; + + onSkeletonModelURLChanged: { + if (skeletonModelURL === root.itemHref) { showConfirmation = true; } } @@ -275,19 +286,19 @@ Item { anchors.bottom: parent.bottom; width: 32; // Style - color: hifi.colors.lightGray; + color: hifi.colors.black; } RalewayRegular { id: viewCertificateText; text: "VIEW CERTIFICATE"; - size: 14; + size: 13; anchors.left: certificateIcon.right; anchors.leftMargin: 4; anchors.top: parent.top; anchors.bottom: parent.bottom; anchors.right: parent.right; - color: hifi.colors.lightGray; + color: hifi.colors.black; } MouseArea { @@ -297,13 +308,13 @@ Item { sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId}); } onEntered: { - certificateIcon.color = hifi.colors.black; - viewCertificateText.color = hifi.colors.black; - } - onExited: { certificateIcon.color = hifi.colors.lightGray; viewCertificateText.color = hifi.colors.lightGray; } + onExited: { + certificateIcon.color = hifi.colors.black; + viewCertificateText.color = hifi.colors.black; + } } } @@ -317,14 +328,14 @@ Item { anchors.right: buttonContainer.left; anchors.rightMargin: 2; - FiraSansRegular { + RalewayRegular { anchors.left: parent.left; anchors.top: parent.top; anchors.bottom: parent.bottom; width: paintedWidth; text: "#" + root.itemEdition; - size: 15; - color: "#cc6a6a6a"; + size: 13; + color: hifi.colors.black; verticalAlignment: Text.AlignTop; } } @@ -471,13 +482,28 @@ Item { anchors.right: parent.right; anchors.rightMargin: 4; width: height; - enabled: root.hasPermissionToRezThis && root.purchaseStatus !== "invalidated"; + enabled: root.hasPermissionToRezThis && + root.purchaseStatus !== "invalidated" && + MyAvatar.skeletonModelURL !== root.itemHref; + + onHoveredChanged: { + if (hovered) { + Tablet.playSound(TabletEnums.ButtonHover); + } + } + + onFocusChanged: { + if (focus) { + Tablet.playSound(TabletEnums.ButtonHover); + } + } onClicked: { + Tablet.playSound(TabletEnums.ButtonClick); if (root.itemType === "contentSet") { - sendToPurchases({method: 'showReplaceContentLightbox', itemId: root.itemId, itemHref: root.itemHref}); + sendToPurchases({method: 'showReplaceContentLightbox', itemHref: root.itemHref}); } else if (root.itemType === "avatar") { - Avatar.skeletonModelURL = root.itemHref; + sendToPurchases({method: 'showChangeAvatarLightbox', itemName: root.itemName, itemHref: root.itemHref}); } else { sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); root.showConfirmation = true; @@ -547,7 +573,13 @@ Item { size: 15; verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter - text: (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)] + text: { + if (MyAvatar.skeletonModelURL === root.itemHref) { + "CURRENT"; + } else { + (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]; + } + } } } } diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 91fed207bc..df65a0a1ac 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -300,7 +300,7 @@ Rectangle { anchors.left: parent.left; anchors.leftMargin: 8; anchors.right: parent.right; - anchors.rightMargin: 12; + anchors.rightMargin: 16; anchors.top: parent.top; anchors.topMargin: 4; @@ -314,7 +314,7 @@ Rectangle { anchors.leftMargin: 16; width: paintedWidth; text: isShowingMyItems ? "My Items" : "My Purchases"; - color: hifi.colors.baseGray; + color: hifi.colors.black; size: 22; } @@ -348,7 +348,7 @@ Rectangle { HifiControlsUit.Separator { id: separator; - colorScheme: 1; + colorScheme: 2; anchors.left: parent.left; anchors.right: parent.right; anchors.top: filterBarContainer.bottom; @@ -445,7 +445,15 @@ Rectangle { lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = "root.visible = false;" lightboxPopup.button2text = "CONFIRM"; - lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemId + "', '" + msg.itemHref + "'); root.visible = false;"; + lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemHref + "'); root.visible = false;"; + lightboxPopup.visible = true; + } else if (msg.method === "showChangeAvatarLightbox") { + lightboxPopup.titleText = "Change Avatar"; + lightboxPopup.bodyText = "This will change your current avatar to " + msg.itemName + " while retaining your wearables."; + lightboxPopup.button1text = "CANCEL"; + lightboxPopup.button1method = "root.visible = false;" + lightboxPopup.button2text = "CONFIRM"; + lightboxPopup.button2method = "MyAvatar.skeletonModelURL('" + msg.itemHref + "'); root.visible = false;"; lightboxPopup.visible = true; } else if (msg.method === "showPermissionsExplanation") { if (msg.itemType === "entity") { diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 5458925d55..36c1e422c5 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -168,15 +168,15 @@ void QmlCommerce::transferHfcToUsername(const QString& username, const int& amou ledger->transferHfcToUsername(key, username, amount, optionalMessage); } -void QmlCommerce::replaceContentSet(const QString& id, const QString& url) { - qApp->replaceDomainContent(url); +void QmlCommerce::replaceContentSet(const QString& itemHref) { + qApp->replaceDomainContent(itemHref); QJsonObject messageProperties = { { "status", "SuccessfulRequestToReplaceContent" }, - { "content_set_url", url } + { "content_set_url", itemHref } }; UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); - emit contentSetChanged(id); + emit contentSetChanged(itemHref); } void QmlCommerce::alreadyOwned(const QString& marketplaceId) { diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index dc38dcad19..b621608190 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -49,7 +49,7 @@ signals: void transferHfcToNodeResult(QJsonObject result); void transferHfcToUsernameResult(QJsonObject result); - void contentSetChanged(const QString& contentSetMarketplaceID); + void contentSetChanged(const QString& contentSetHref); protected: Q_INVOKABLE void getWalletStatus(); @@ -77,7 +77,7 @@ protected: Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage); - Q_INVOKABLE void replaceContentSet(const QString& id, const QString& url); + Q_INVOKABLE void replaceContentSet(const QString& itemHref); }; #endif // hifi_QmlCommerce_h diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index f24bd51bde..6d9a13decf 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -371,7 +371,7 @@ class AvatarData : public QObject, public SpatiallyNestable { // The result is unique among all avatars present at the time. Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged) Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged) - Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript) + Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged) Q_PROPERTY(QVector attachmentData READ getAttachmentData WRITE setAttachmentData) Q_PROPERTY(QStringList jointNames READ getJointNames) @@ -697,6 +697,7 @@ public: signals: void displayNameChanged(); void sessionDisplayNameChanged(); + void skeletonModelURLChanged(); void lookAtSnappingChanged(bool enabled); void sessionUUIDChanged(); diff --git a/libraries/avatars/src/ScriptAvatarData.cpp b/libraries/avatars/src/ScriptAvatarData.cpp index 1fd001e536..8491e5368b 100644 --- a/libraries/avatars/src/ScriptAvatarData.cpp +++ b/libraries/avatars/src/ScriptAvatarData.cpp @@ -16,6 +16,7 @@ ScriptAvatarData::ScriptAvatarData(AvatarSharedPointer avatarData) : { QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged); QObject::connect(avatarData.get(), &AvatarData::sessionDisplayNameChanged, this, &ScriptAvatarData::sessionDisplayNameChanged); + QObject::connect(avatarData.get(), &AvatarData::skeletonModelURLChanged, this, &ScriptAvatarData::skeletonModelURLChanged); QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged); } diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index 68074b838d..13713ff15f 100644 --- a/libraries/avatars/src/ScriptAvatarData.h +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -51,7 +51,7 @@ class ScriptAvatarData : public QObject { // // ATTACHMENT AND JOINT PROPERTIES // - Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript) + Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged) Q_PROPERTY(QVector attachmentData READ getAttachmentData) Q_PROPERTY(QStringList jointNames READ getJointNames) @@ -132,6 +132,7 @@ public: signals: void displayNameChanged(); void sessionDisplayNameChanged(); + void skeletonModelURLChanged(); void lookAtSnappingChanged(bool enabled); public slots: From 811ecf9db8341428ecbf5bba66c7e7a87aeb61ee Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 15 Feb 2018 14:11:01 -0800 Subject: [PATCH 34/54] Fix --- .../resources/qml/hifi/commerce/checkout/Checkout.qml | 6 +++--- .../qml/hifi/commerce/purchases/PurchasedItem.qml | 5 +++-- .../resources/qml/hifi/commerce/purchases/Purchases.qml | 2 +- scripts/system/marketplaces/marketplaces.js | 8 ++++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 08b100a64c..891c8142bf 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -146,7 +146,7 @@ Rectangle { } onItemTypeChanged: { - if (root.itemType === "entity" || root.itemType === "wearable" || root.itemType === "contentSet") { + if (root.itemType === "entity" || root.itemType === "wearable" || root.itemType === "contentSet" || root.itemType === "avatar") { root.isCertified = true; } else { root.isCertified = false; @@ -679,7 +679,7 @@ Rectangle { id: rezNowButton; enabled: (root.itemType === "entity" && root.canRezCertifiedItems) || (root.itemType === "contentSet" && Entities.canReplaceContent()) || - root.itemType === "wearable"; + root.itemType === "wearable" || root.itemType === "avatar"; buttonGlyph: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; color: hifi.buttons.red; colorScheme: hifi.colorSchemes.light; @@ -710,7 +710,7 @@ Rectangle { lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = "root.visible = false;" lightboxPopup.button2text = "CONFIRM"; - lightboxPopup.button2method = "Avatar.skeletonModelURL('" + root.itemHref + "'); root.visible = false;"; + lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + root.itemHref + "'); root.visible = false;"; lightboxPopup.visible = true; } else { sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index be460ea4ef..50ac34cd51 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -151,8 +151,9 @@ Item { anchors.topMargin: 4; anchors.left: itemPreviewImage.right; anchors.leftMargin: 8; - width: root.hasPermissionToRezThis ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width) : - Math.min(itemNameTextMetrics.tightBoundingRect.width + 2, buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - noPermissionGlyph.width + 2); + width: root.hasPermissionToRezThis ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin) : + Math.min(itemNameTextMetrics.tightBoundingRect.width + 2, + buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin - noPermissionGlyph.width + 2); height: paintedHeight; // Text size size: 24; diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index df65a0a1ac..5593883e00 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -453,7 +453,7 @@ Rectangle { lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = "root.visible = false;" lightboxPopup.button2text = "CONFIRM"; - lightboxPopup.button2method = "MyAvatar.skeletonModelURL('" + msg.itemHref + "'); root.visible = false;"; + lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + msg.itemHref + "'); root.visible = false;"; lightboxPopup.visible = true; } else if (msg.method === "showPermissionsExplanation") { if (msg.itemType === "entity") { diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 95d9294063..c61272119d 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -75,10 +75,10 @@ var selectionDisplay = null; // for gridTool.js to ignore tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH); tablet.sendToQml({ method: 'updateCheckoutQML', params: { - itemId: 'e197e3d7-eafc-4aa5-9341-acee57174fe9', - itemName: 'Oasis', - itemPrice: (debugError ? 10 : 11), - itemHref: 'http://mpassets-staging.highfidelity.com/e197e3d7-eafc-4aa5-9341-acee57174fe9-v1/oasis_Aug15.json.gz', + itemId: '424611a2-73d0-4c03-9087-26a6a279257b', + itemName: '2018-02-15 Finnegon', + itemPrice: (debugError ? 10 : 3), + itemHref: 'http://devmpassets.highfidelity.com/424611a2-73d0-4c03-9087-26a6a279257b-v1/finnigon.fst', categories: ["Miscellaneous"] } }); From c4e9c762582b027553d4113e72dcabafb9cb69f5 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 15 Feb 2018 15:14:54 -0800 Subject: [PATCH 35/54] Small UIT tweaks --- interface/resources/qml/controls-uit/TextField.qml | 5 ++--- .../qml/hifi/commerce/purchases/PurchasedItem.qml | 11 ++++++----- .../qml/hifi/commerce/purchases/Purchases.qml | 10 ++++++++++ interface/resources/qml/styles-uit/HifiConstants.qml | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml index a21d1f8efd..3fc5d83129 100644 --- a/interface/resources/qml/controls-uit/TextField.qml +++ b/interface/resources/qml/controls-uit/TextField.qml @@ -34,11 +34,10 @@ TextField { placeholderText: textField.placeholderText - FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; } + FontLoader { id: firaSansRegular; source: "../../fonts/FiraSans-Regular.ttf"; } FontLoader { id: hifiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; } - font.family: firaSansSemiBold.name + font.family: firaSansRegular.name font.pixelSize: hifi.fontSizes.textFieldInput - font.italic: textField.text == "" height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered. property alias textFieldLabel: textFieldLabel diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 50ac34cd51..272c542fde 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -46,6 +46,7 @@ Item { property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar]; property bool showConfirmation: false; property bool hasPermissionToRezThis; + property bool permissionExplanationCardVisible; property string originalStatusText; property string originalStatusColor; @@ -151,7 +152,7 @@ Item { anchors.topMargin: 4; anchors.left: itemPreviewImage.right; anchors.leftMargin: 8; - width: root.hasPermissionToRezThis ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin) : + width: !noPermissionGlyph.visible ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin) : Math.min(itemNameTextMetrics.tightBoundingRect.width + 2, buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin - noPermissionGlyph.width + 2); height: paintedHeight; @@ -181,7 +182,7 @@ Item { } HiFiGlyphs { id: noPermissionGlyph; - visible: !root.hasPermissionToRezThis; + visible: true// !root.hasPermissionToRezThis; anchors.verticalCenter: itemName.verticalCenter; anchors.left: itemName.right; anchors.leftMargin: itemName.truncated ? -14 : -2; @@ -203,14 +204,14 @@ Item { noPermissionGlyph.color = hifi.colors.redAccent; } onClicked: { - permissionExplanationCard.visible = true; + root.sendToPurchases({ method: 'openPermissionExplanationCard' }); } } } Rectangle { id: permissionExplanationCard; z: 995; - visible: false; + visible: root.permissionExplanationCardVisible; anchors.fill: parent; color: hifi.colors.white; @@ -261,7 +262,7 @@ Item { parent.text = hifi.glyphs.close; } onClicked: { - permissionExplanationCard.visible = false; + root.sendToPurchases({ method: 'openPermissionExplanationCard', closeAll: true }); } } } diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 5593883e00..b01dfcfce3 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -393,6 +393,7 @@ Rectangle { numberSold: model.number_sold; limitedRun: model.limited_run; displayedItemCount: model.displayedItemCount; + permissionExplanationCardVisible: model.permissionExplanationCardVisible; itemType: { if (model.root_file_url.indexOf(".fst") > -1) { "avatar"; @@ -472,6 +473,14 @@ Rectangle { lightboxPopup.visible = true; } else if (msg.method === "setFilterText") { filterBar.text = msg.filterText; + } else if (msg.method === "openPermissionExplanationCard") { + for (var i = 0; i < filteredPurchasesModel.count; i++) { + if (i !== index || msg.closeAll) { + filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", false); + } else { + filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", true); + } + } } } } @@ -673,6 +682,7 @@ Rectangle { filteredPurchasesModel.clear(); for (var i = 0; i < tempPurchasesModel.count; i++) { filteredPurchasesModel.append(tempPurchasesModel.get(i)); + filteredPurchasesModel.setProperty(i, 'permissionExplanationCardVisible', false); } populateDisplayedItemCounts(); diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 16b74f6b54..43de8333af 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -218,7 +218,7 @@ Item { readonly property var colorStart: [ colors.white, colors.primaryHighlight, "#d42043", "#343434", Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ] readonly property var colorFinish: [ colors.lightGrayText, colors.blueAccent, "#94132e", colors.black, Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ] readonly property var hoveredColor: [ colorStart[white], colorStart[blue], colorStart[red], colorFinish[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ] - readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ] + readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colors.lightGrayText ] readonly property var focusedColor: [ colors.lightGray50, colors.blueAccent, colors.redAccent, colors.darkGray, colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ] readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight] readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow] From e5f953c103a5df5738b26affc6316ef751555e77 Mon Sep 17 00:00:00 2001 From: vladest Date: Sat, 17 Feb 2018 16:52:32 +0100 Subject: [PATCH 36/54] Make sure Flickable for GridView for TabletHome will not flick --- interface/resources/qml/hifi/tablet/TabletHome.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/hifi/tablet/TabletHome.qml b/interface/resources/qml/hifi/tablet/TabletHome.qml index cfff3a3273..1922b02f93 100644 --- a/interface/resources/qml/hifi/tablet/TabletHome.qml +++ b/interface/resources/qml/hifi/tablet/TabletHome.qml @@ -130,6 +130,7 @@ Item { flickableDirection: Flickable.AutoFlickIfNeeded keyNavigationEnabled: false highlightFollowsCurrentItem: false + interactive: false property int previousGridIndex: -1 From 65efeadf107e2a9171714d4a020c5f297338d453 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 19 Feb 2018 19:17:23 +1300 Subject: [PATCH 37/54] Fix selecting values when tabbing between entity properties fields --- scripts/system/html/js/entityProperties.js | 44 ++++------------------ 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index b27c852974..349516393a 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -497,15 +497,6 @@ function unbindAllInputs() { } } -function clearSelection() { - if (document.selection && document.selection.empty) { - document.selection.empty(); - } else if (window.getSelection) { - var sel = window.getSelection(); - sel.removeAllRanges(); - } -} - function loaded() { openEventBridge(function() { @@ -791,8 +782,10 @@ function loaded() { if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null && editor !== null) { saveJSONUserData(true); } - // the event bridge and json parsing handle our avatar id string differently. + var doSelectElement = lastEntityID === '"' + properties.id + '"'; + + // the event bridge and json parsing handle our avatar id string differently. lastEntityID = '"' + properties.id + '"'; elID.value = properties.id; @@ -1138,12 +1131,10 @@ function loaded() { } var activeElement = document.activeElement; - - if (typeof activeElement.select !== "undefined") { + if (doSelectElement && typeof activeElement.select !== "undefined") { activeElement.select(); } } - clearSelection(); } }); } @@ -1682,34 +1673,13 @@ function loaded() { }; // For input and textarea elements, select all of the text on focus - // WebKit-based browsers, such as is used with QWebView, have a quirk - // where the mouseup event comes after the focus event, causing the - // text to be deselected immediately after selecting all of the text. - // To make this work we block the first mouseup event after the elements - // received focus. If we block all mouseup events the user will not - // be able to click within the selected text. - // We also check to see if the value has changed to make sure we aren't - // blocking a mouse-up event when clicking on an input spinner. var els = document.querySelectorAll("input, textarea"); for (var i = 0; i < els.length; i++) { - var clicked = false; - var originalText; - // TODO FIXME: (JSHint) Functions declared within loops referencing - // an outer scoped variable may lead to confusing semantics. - els[i].onfocus = function(e) { - originalText = this.value; - this.select(); - clicked = false; - }; - // TODO FIXME: (JSHint) Functions declared within loops referencing - // an outer scoped variable may lead to confusing semantics. - els[i].onmouseup = function(e) { - if (!clicked && originalText === this.value) { - e.preventDefault(); - } - clicked = true; + els[i].onfocus = function (e) { + e.target.select(); }; } + bindAllNonJSONEditorElements(); }); From 11f897beb098e0dd0464370ab34bb09adcc1fc01 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 20 Feb 2018 10:39:36 -0800 Subject: [PATCH 38/54] Initial app support --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 2 +- scripts/system/marketplaces/marketplaces.js | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 891c8142bf..bf73decf9b 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -530,7 +530,7 @@ Rectangle { // "Buy" button HifiControlsUit.Button { id: buyButton; - visible: !(root.itemType === "avatar" && viewInMyPurchasesButton.visible) + visible: !((root.itemType === "avatar" || root.itemType === "app") && viewInMyPurchasesButton.visible) enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived) || (!root.isCertified); color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index c61272119d..45085b2d45 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -550,7 +550,11 @@ var selectionDisplay = null; // for gridTool.js to ignore break; case 'checkout_rezClicked': case 'purchases_rezClicked': - rezEntity(message.itemHref, message.itemType); + if (message.itemType === "app") { + + } else { + rezEntity(message.itemHref, message.itemType); + } break; case 'header_marketplaceImageClicked': case 'purchases_backClicked': From 9bde9f5a4f260d40b1af694ad86866d5451143c0 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 20 Feb 2018 12:36:11 -0800 Subject: [PATCH 39/54] Fix height of Optional Message in Send Money --- .../resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml index 7dd72b904e..9d05d3a7ef 100644 --- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml @@ -923,7 +923,7 @@ Item { anchors.leftMargin: 20; anchors.right: parent.right; anchors.rightMargin: 20; - height: 140; + height: 95; FontLoader { id: firaSansSemiBold; source: "../../../../../fonts/FiraSans-SemiBold.ttf"; } TextArea { From eb29bdf5d2530606bfd34002ea7e384a1b00e906 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 20 Feb 2018 13:06:10 -0800 Subject: [PATCH 40/54] Don't allow tabs or newlines --- .../qml/hifi/commerce/wallet/sendMoney/SendMoney.qml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml index 9d05d3a7ef..f5b7f42a3f 100644 --- a/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml +++ b/interface/resources/qml/hifi/commerce/wallet/sendMoney/SendMoney.qml @@ -947,8 +947,14 @@ Item { wrapMode: TextEdit.Wrap; activeFocusOnPress: true; activeFocusOnTab: true; - // Workaround for no max length on TextAreas onTextChanged: { + // Don't allow tabs or newlines + if ((/[\n\r\t]/g).test(text)) { + var cursor = cursorPosition; + text = text.replace(/[\n\r\t]/g, ''); + cursorPosition = cursor-1; + } + // Workaround for no max length on TextAreas if (text.length > maximumLength) { var cursor = cursorPosition; text = previousText; From fd6f4b569f2bd1b875be0ea365ecd09b68cba2d8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 20 Feb 2018 13:19:31 -0800 Subject: [PATCH 41/54] Fix active focus issue --- .../qml/hifi/commerce/wallet/PassphraseModal.qml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml index c586af9e80..f1692acb3d 100644 --- a/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml +++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml @@ -75,8 +75,6 @@ Item { // TODO: Fix this unlikely bug onVisibleChanged: { if (visible) { - passphraseField.error = false; - passphraseField.focus = true; sendSignalToParent({method: 'disableHmdPreview'}); } else { sendSignalToParent({method: 'maybeEnableHmdPreview'}); @@ -206,6 +204,14 @@ Item { placeholderText: "passphrase"; activeFocusOnPress: true; activeFocusOnTab: true; + + onVisibleChanged: { + if (visible) { + error = false; + focus = true; + forceActiveFocus(); + } + } onFocusChanged: { root.keyboardRaised = focus; From f08c66e3ac9b8538a30054cc86838806afb9f19c Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 20 Feb 2018 14:14:59 -0800 Subject: [PATCH 42/54] Remove debug code --- .../resources/qml/hifi/commerce/purchases/PurchasedItem.qml | 2 +- scripts/system/commerce/wallet.js | 2 +- scripts/system/marketplaces/marketplaces.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 272c542fde..3a414acbb5 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -182,7 +182,7 @@ Item { } HiFiGlyphs { id: noPermissionGlyph; - visible: true// !root.hasPermissionToRezThis; + visible: !root.hasPermissionToRezThis; anchors.verticalCenter: itemName.verticalCenter; anchors.left: itemName.right; anchors.leftMargin: itemName.truncated ? -14 : -2; diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 9ff7038c09..8cf5b72b9a 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -39,7 +39,7 @@ // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); } else { - tablet.loadQMLSource(MARKETPLACE_PURCHASES_QML_PATH); + tablet.loadQMLSource(WALLET_QML_SOURCE); } } diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 45085b2d45..8c41906d77 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -65,7 +65,7 @@ var selectionDisplay = null; // for gridTool.js to ignore var onMarketplaceScreen = false; var onCommerceScreen = false; - var debugCheckout = true; + var debugCheckout = false; var debugError = false; function showMarketplace() { if (!debugCheckout) { From bf73df12652955fda81749946d738e44635aeef4 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 20 Feb 2018 15:45:47 -0800 Subject: [PATCH 43/54] more logging for fogbugz 11748 --- libraries/animation/src/Rig.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 01b7dfb0de..d6791ab0b8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -434,9 +434,13 @@ void Rig::setJointRotation(int index, bool valid, const glm::quat& rotation, flo bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm::vec3 translation, glm::quat rotation) const { bool success { false }; - if (QThread::currentThread() == thread()) { + glm::vec3 originalPosition = position; + bool onOwnerThread = (QThread::currentThread() == thread()); + glm::vec3 poseSetTrans; + if (onOwnerThread) { if (isIndexValid(jointIndex)) { - position = (rotation * _internalPoseSet._absolutePoses[jointIndex].trans()) + translation; + poseSetTrans = _internalPoseSet._absolutePoses[jointIndex].trans(); + position = (rotation * poseSetTrans) + translation; success = true; } else { success = false; @@ -444,7 +448,8 @@ bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm: } else { QReadLocker readLock(&_externalPoseSetLock); if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) { - position = (rotation * _externalPoseSet._absolutePoses[jointIndex].trans()) + translation; + poseSetTrans = _externalPoseSet._absolutePoses[jointIndex].trans(); + position = (rotation * poseSetTrans) + translation; success = true; } else { success = false; @@ -452,7 +457,14 @@ bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm: } if (isNaN(position)) { - qCWarning(animation) << "Rig::getJointPositionInWorldFrame produces NaN"; + qCWarning(animation) << "Rig::getJointPositionInWorldFrame produced NaN." + << " is owner thread = " << onOwnerThread + << " position = " << originalPosition + << " translation = " << translation + << " rotation = " << rotation + << " poseSetTrans = " << poseSetTrans + << " success = " << success + << " jointIndex = " << jointIndex; success = false; position = glm::vec3(0.0f); } From 16ffcc7fe2696c10ec5429a07de14f0dcc4b3bca Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 21 Feb 2018 09:48:15 -0800 Subject: [PATCH 44/54] Add #include of Forward.h to AudioMixer.h This makes the compile by Qt MOC less dependent on order of processing. See Manuscript case 12527. --- assignment-client/src/audio/AudioMixer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index ed3a5b0541..12ae3422bc 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -18,6 +18,8 @@ #include #include +#include "Plugins/Forward.h" + #include "AudioMixerStats.h" #include "AudioMixerSlavePool.h" From 4dde178b931f04e02b2c1028dbcf17899fb48b5b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 21 Feb 2018 10:33:15 -0800 Subject: [PATCH 45/54] fix new material UI --- interface/resources/qml/hifi/tablet/NewMaterialDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/NewMaterialDialog.qml b/interface/resources/qml/hifi/tablet/NewMaterialDialog.qml index 226c17e8e2..c7fbc9d45a 100644 --- a/interface/resources/qml/hifi/tablet/NewMaterialDialog.qml +++ b/interface/resources/qml/hifi/tablet/NewMaterialDialog.qml @@ -131,7 +131,7 @@ Rectangle { spacing: 5 anchors.horizontalCenter: column3.horizontalCenter - anchors.horizontalCenterOffset: -20 + anchors.horizontalCenterOffset: 0 Button { id: button1 From 1fbc16aae224f5e9aa62a74690ec01b44e60c2b3 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 21 Feb 2018 10:52:17 -0800 Subject: [PATCH 46/54] Fix noPermissionGlyph margin --- .../resources/qml/hifi/commerce/purchases/PurchasedItem.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 3a414acbb5..5b70fdbde9 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -185,7 +185,7 @@ Item { visible: !root.hasPermissionToRezThis; anchors.verticalCenter: itemName.verticalCenter; anchors.left: itemName.right; - anchors.leftMargin: itemName.truncated ? -14 : -2; + anchors.leftMargin: itemName.truncated ? -10 : -2; text: hifi.glyphs.info; // Size size: 40; From 619901caa01d4ee3994f34563dc15a712590f58c Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 21 Feb 2018 11:12:09 -0800 Subject: [PATCH 47/54] Move up main #include for other AudioMixer* Having #include first will make more robust for MOC compile problems. Also fixes previous commit to use <> form and correct case. See Case 12527. --- assignment-client/src/audio/AudioMixer.cpp | 4 ++-- assignment-client/src/audio/AudioMixer.h | 2 +- assignment-client/src/audio/AudioMixerClientData.cpp | 4 ++-- assignment-client/src/audio/AudioMixerClientData.h | 1 + assignment-client/src/audio/AudioMixerSlave.cpp | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 7f088d8183..8af4eec934 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioMixer.h" + #include #include @@ -36,8 +38,6 @@ #include "AvatarAudioStream.h" #include "InjectedAudioStream.h" -#include "AudioMixer.h" - static const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance) static const int DISABLE_STATIC_JITTER_FRAMES = -1; static const float DEFAULT_NOISE_MUTING_THRESHOLD = 1.0f; diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 12ae3422bc..8c47893aa3 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -18,7 +18,7 @@ #include #include -#include "Plugins/Forward.h" +#include #include "AudioMixerStats.h" #include "AudioMixerSlavePool.h" diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 2560f43337..d4d4f847ee 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioMixerClientData.h" + #include #include @@ -22,8 +24,6 @@ #include "AudioLogging.h" #include "AudioHelpers.h" #include "AudioMixer.h" -#include "AudioMixerClientData.h" - AudioMixerClientData::AudioMixerClientData(const QUuid& nodeID) : NodeData(nodeID), diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index c3a31715ea..514e1c9756 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -21,6 +21,7 @@ #include #include +#include #include #include "PositionalAudioStream.h" diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index abc2f7220d..b975ba8bfe 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioMixerSlave.h" + #include #include @@ -34,8 +36,6 @@ #include "InjectedAudioStream.h" #include "AudioHelpers.h" -#include "AudioMixerSlave.h" - using AudioStreamMap = AudioMixerClientData::AudioStreamMap; // packet helpers From b548567f5acf5170c7dc6f26a136d42552a28ce5 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 21 Feb 2018 11:17:47 -0800 Subject: [PATCH 48/54] Apps protection --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 4 ++-- interface/resources/qml/hifi/commerce/purchases/Purchases.qml | 4 ++-- scripts/system/marketplaces/marketplaces.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index bf73decf9b..27acb121ca 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -135,10 +135,10 @@ Rectangle { root.itemType = "avatar"; } else if (root.itemHref.indexOf('.json.gz') > -1) { root.itemType = "contentSet"; + } else if (root.itemHref.indexOf('.app.json') > -1) { + root.itemType = "app"; } else if (root.itemHref.indexOf('.json') > -1) { root.itemType = "entity"; // "wearable" type handled later - } else if (root.itemHref.indexOf('.js') > -1) { - root.itemType = "app"; } else { console.log("WARNING - Item type is UNKNOWN!"); root.itemType = "entity"; diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index b01dfcfce3..9b333a60cd 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -401,10 +401,10 @@ Rectangle { "wearable"; } else if (model.root_file_url.endsWith('.json.gz')) { "contentSet"; + } else if (model.root_file_url.endsWith('.app.json')) { + "app"; } else if (model.root_file_url.endsWith('.json')) { "entity"; - } else if (model.root_file_url.endsWith('.js')) { - "app"; } else { "unknown"; } diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 8c41906d77..1eb16cf453 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -551,7 +551,7 @@ var selectionDisplay = null; // for gridTool.js to ignore case 'checkout_rezClicked': case 'purchases_rezClicked': if (message.itemType === "app") { - + console.log("How did you get here? You can't buy apps yet!"); } else { rezEntity(message.itemHref, message.itemType); } From 74655bde49b878f81e2707af08b871702911ff7a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 21 Feb 2018 12:12:20 -0800 Subject: [PATCH 49/54] Fix skeletonmodelURLchanged signal --- .../qml/hifi/commerce/purchases/PurchasedItem.qml | 9 ++------- interface/src/avatar/MyAvatar.cpp | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 5b70fdbde9..cc2bcd69aa 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -564,6 +564,7 @@ Item { : hifi.buttons.disabledTextColor[control.colorScheme] } RalewayBold { + id: rezIconLabel; anchors.top: rezIcon.bottom; anchors.topMargin: -4; anchors.right: parent.right; @@ -575,13 +576,7 @@ Item { size: 15; verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter - text: { - if (MyAvatar.skeletonModelURL === root.itemHref) { - "CURRENT"; - } else { - (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]; - } - } + text: MyAvatar.skeletonModelURL === root.itemHref ? "CURRENT" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]; } } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c25aaeeecd..50753724e8 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1479,7 +1479,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { }); saveAvatarUrl(); emit skeletonChanged(); - + emit skeletonModelURLChanged(); } void MyAvatar::removeAvatarEntities() { From fa1f2267cf9ad18fc87863427c753b944146575e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 22 Feb 2018 10:06:00 +1300 Subject: [PATCH 50/54] Support RC63 --- unpublishedScripts/marketplace/record/record.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unpublishedScripts/marketplace/record/record.js b/unpublishedScripts/marketplace/record/record.js index 08400dbb85..8e49589e3c 100644 --- a/unpublishedScripts/marketplace/record/record.js +++ b/unpublishedScripts/marketplace/record/record.js @@ -139,7 +139,8 @@ } function setMappingCallback(status) { - if (status !== null) { + // FIXME: "" is for RC <= 63, null is for RC > 63. Remove the former when RC63 is no longer used. + if (status !== null && status !== "") { error("Error mapping recording to " + mappingPath + " on Asset Server!", status); return; } From 68f0c0391aedaed87b64bf36230bb0410e4796e8 Mon Sep 17 00:00:00 2001 From: Liv Erickson Date: Wed, 21 Feb 2018 15:44:23 -0800 Subject: [PATCH 51/54] Initial fix - need a little style fixing --- .../resources/qml/hifi/tablet/EditTabView.qml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/interface/resources/qml/hifi/tablet/EditTabView.qml b/interface/resources/qml/hifi/tablet/EditTabView.qml index c79c05a601..9439d3fcea 100644 --- a/interface/resources/qml/hifi/tablet/EditTabView.qml +++ b/interface/resources/qml/hifi/tablet/EditTabView.qml @@ -1,5 +1,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 +import QtQuick.Controls 2.2 // Need both for short-term fix import QtWebEngine 1.1 import QtWebChannel 1.0 import QtQuick.Controls.Styles 1.4 @@ -10,6 +11,7 @@ import "../../controls-uit" as HifiControls import "../../styles-uit" + TabView { id: editTabView // anchors.fill: parent @@ -23,8 +25,25 @@ TabView { Rectangle { color: "#404040" + id: container + + Flickable { + height: parent.height + width: parent.width + + contentHeight: createEntitiesFlow.height + importButton.height + assetServerButton.height + 153 + contentWidth: width + + ScrollBar.vertical : ScrollBar { + visible: parent.contentHeight > parent.height + width: 20 + background: Rectangle { + color: hifi.colors.tableScrollBackgroundDark + } + } Text { + id: header color: "#ffffff" text: "Choose an Entity Type to Create:" font.pixelSize: 14 @@ -176,6 +195,7 @@ TabView { } HifiControls.Button { + id: importButton text: "Import Entities (.json)" color: hifi.buttons.black colorScheme: hifi.colorSchemes.dark @@ -192,6 +212,7 @@ TabView { } } } + } // Flickable } Tab { From 990e848de6bf35a5bd292b88ec4dc56e817652a5 Mon Sep 17 00:00:00 2001 From: Liv Erickson Date: Wed, 21 Feb 2018 15:54:00 -0800 Subject: [PATCH 52/54] fix typo that was breaking popup dialog --- interface/resources/qml/hifi/dialogs/TabletAssetServer.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml index 049a7faad8..bbecb9e85b 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml @@ -199,7 +199,7 @@ Rectangle { var SHAPE_TYPE_BOX = 4; var SHAPE_TYPE_SPHERE = 5; - var SHAPE_TYPES = [];ww + var SHAPE_TYPES = []; SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision"; SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model"; SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes"; From aba1cae36d1c6fe172452dd75e1af02b0818955b Mon Sep 17 00:00:00 2001 From: Liv Erickson Date: Wed, 21 Feb 2018 16:19:50 -0800 Subject: [PATCH 53/54] get rid of magic number --- interface/resources/qml/hifi/tablet/EditTabView.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/EditTabView.qml b/interface/resources/qml/hifi/tablet/EditTabView.qml index 9439d3fcea..e419b04848 100644 --- a/interface/resources/qml/hifi/tablet/EditTabView.qml +++ b/interface/resources/qml/hifi/tablet/EditTabView.qml @@ -31,7 +31,9 @@ TabView { height: parent.height width: parent.width - contentHeight: createEntitiesFlow.height + importButton.height + assetServerButton.height + 153 + contentHeight: createEntitiesFlow.height + importButton.height + assetServerButton.height + + header.anchors.topMargin + createEntitiesFlow.anchors.topMargin + + assetServerButton.anchors.topMargin + importButton.anchors.topMargin contentWidth: width ScrollBar.vertical : ScrollBar { From 3d4e6de6abb4d638d844478f68e4adba3b686cbf Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 22 Feb 2018 10:49:11 -0800 Subject: [PATCH 54/54] Quick bugfix --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 27acb121ca..ab47bb28ad 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -722,7 +722,7 @@ Rectangle { } RalewaySemiBold { id: noPermissionText; - visible: !root.canRezCertifiedItems && root.itemType !== "wearable"; + visible: !root.canRezCertifiedItems && root.itemType === "entity"; text: 'You do not have Certified Rez permissions in this domain.' // Text size size: 16;