diff --git a/interface/resources/images/address-bar.svg b/interface/resources/images/address-bar.svg index dd907aa6c9..56dc4f028c 100644 --- a/interface/resources/images/address-bar.svg +++ b/interface/resources/images/address-bar.svg @@ -15,7 +15,7 @@ viewBox="0 0 1440 200" id="svg4136" inkscape:version="0.91 r13725" - sodipodi:docname="address-bar.002.svg"> + sodipodi:docname="address-bar.svg"> @@ -39,16 +39,16 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="1835" - inkscape:window-height="1057" + inkscape:window-width="1536" + inkscape:window-height="687" id="namedview4140" showgrid="false" inkscape:zoom="0.61319416" - inkscape:cx="132.58366" + inkscape:cx="670.06567" inkscape:cy="52.468468" - inkscape:window-x="77" - inkscape:window-y="-8" - inkscape:window-maximized="1" + inkscape:window-x="105" + inkscape:window-y="0" + inkscape:window-maximized="0" inkscape:current-layer="svg4136" /> + width="328.72031" + height="139.64169" + x="150.33546" + y="30.179144" + rx="18.876532" + ry="20.609974" /> - diff --git a/interface/resources/images/home-button.svg b/interface/resources/images/home-button.svg new file mode 100644 index 0000000000..c7f9bfd607 --- /dev/null +++ b/interface/resources/images/home-button.svg @@ -0,0 +1,48 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index c5712c11d2..7f107e44e9 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -55,15 +55,35 @@ Window { property int inputAreaHeight: 56.0 * root.scale // Height of the background's input area property int inputAreaStep: (height - inputAreaHeight) / 2 + Image { + id: homeButton + source: "../images/home-button.svg" + width: 29 + height: 26 + anchors { + left: parent.left + leftMargin: parent.height + 2 * hifi.layout.spacing + verticalCenter: parent.verticalCenter + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton + onClicked: { + addressBarDialog.loadHome() + } + } + } + Image { id: backArrow source: addressBarDialog.backEnabled ? "../images/left-arrow.svg" : "../images/left-arrow-disabled.svg" + width: 22 + height: 26 anchors { - fill: parent - leftMargin: parent.height + hifi.layout.spacing + 6 - rightMargin: parent.height + hifi.layout.spacing * 60 - topMargin: parent.inputAreaStep + parent.inputAreaStep + hifi.layout.spacing - bottomMargin: parent.inputAreaStep + parent.inputAreaStep + hifi.layout.spacing + left: homeButton.right + leftMargin: 2 * hifi.layout.spacing + verticalCenter: parent.verticalCenter } MouseArea { @@ -78,12 +98,12 @@ Window { Image { id: forwardArrow source: addressBarDialog.forwardEnabled ? "../images/right-arrow.svg" : "../images/right-arrow-disabled.svg" + width: 22 + height: 26 anchors { - fill: parent - leftMargin: parent.height + hifi.layout.spacing * 9 - rightMargin: parent.height + hifi.layout.spacing * 53 - topMargin: parent.inputAreaStep + parent.inputAreaStep + hifi.layout.spacing - bottomMargin: parent.inputAreaStep + parent.inputAreaStep + hifi.layout.spacing + left: backArrow.right + leftMargin: 2 * hifi.layout.spacing + verticalCenter: parent.verticalCenter } MouseArea { @@ -101,7 +121,7 @@ Window { focus: true anchors { fill: parent - leftMargin: parent.height + parent.height + hifi.layout.spacing * 5 + leftMargin: parent.height + parent.height + hifi.layout.spacing * 7 rightMargin: hifi.layout.spacing * 2 topMargin: parent.inputAreaStep + hifi.layout.spacing bottomMargin: parent.inputAreaStep + hifi.layout.spacing diff --git a/interface/resources/qml/InfoView.qml b/interface/resources/qml/InfoView.qml index 2e93c401d4..c5dba7e1f3 100644 --- a/interface/resources/qml/InfoView.qml +++ b/interface/resources/qml/InfoView.qml @@ -1,8 +1,18 @@ +// +// InfoView.qml +// +// Created by Bradley Austin Davis on 27 Apr 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + import QtQuick 2.5 import Hifi 1.0 as Hifi -import "controls" -import "windows" as Windows +import "controls-uit" +import "windows-uit" as Windows Windows.Window { id: root @@ -12,16 +22,16 @@ Windows.Window { Hifi.InfoView { id: infoView - // Fill the client area - anchors.fill: parent - + width: pane.contentWidth + implicitHeight: pane.scrollHeight + WebView { id: webview objectName: "WebView" anchors.fill: parent url: infoView.url } - } + } Component.onCompleted: { centerWindow(root); diff --git a/interface/resources/qml/QmlWebWindow.qml b/interface/resources/qml/QmlWebWindow.qml index 70c8afd298..ae052879db 100644 --- a/interface/resources/qml/QmlWebWindow.qml +++ b/interface/resources/qml/QmlWebWindow.qml @@ -1,11 +1,21 @@ -import QtQuick 2.3 -import QtQuick.Controls 1.2 +// +// QmlWebWindow.qml +// +// Created by Bradley Austin Davis on 17 Dec 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 import QtWebEngine 1.1 import QtWebChannel 1.0 -import "windows" as Windows -import "controls" as Controls -import "styles" +import "windows-uit" as Windows +import "controls-uit" as Controls +import "styles-uit" Windows.Window { id: root @@ -29,11 +39,16 @@ Windows.Window { // missing signal signal sendToScript(var message); - Controls.WebView { - id: webview - url: "about:blank" - anchors.fill: parent - focus: true - webChannel.registeredObjects: [eventBridgeWrapper] + Item { + width: pane.contentWidth + implicitHeight: pane.scrollHeight + + Controls.WebView { + id: webview + url: "about:blank" + anchors.fill: parent + focus: true + webChannel.registeredObjects: [eventBridgeWrapper] + } } -} // dialog +} diff --git a/interface/resources/qml/controls-uit/WebView.qml b/interface/resources/qml/controls-uit/WebView.qml index 5ea4b22baf..e6005d5dcf 100644 --- a/interface/resources/qml/controls-uit/WebView.qml +++ b/interface/resources/qml/controls-uit/WebView.qml @@ -15,6 +15,8 @@ WebEngineView { id: root property var newUrl; + profile.httpUserAgent: "Mozilla/5.0 Chrome (HighFidelityInterface)" + Component.onCompleted: { console.log("Connecting JS messaging to Hifi Logging") // Ensure the JS from the web-engine makes it to our logging diff --git a/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml b/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml index cdeddb5886..e5bc9b80ef 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml @@ -1,10 +1,20 @@ +// +// AvatarBrowser.qml +// +// Created by Bradley Austin Davis on 30 Aug 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + import QtQuick 2.5 import QtQuick.Controls 1.4 import QtWebEngine 1.1 -import "../../windows" as Windows -import "../../controls" as Controls -import "../../styles" +import "../../windows-uit" as Windows +import "../../controls-uit" as Controls +import "../../styles-uit" Windows.Window { id: root @@ -14,20 +24,14 @@ Windows.Window { modality: Qt.ApplicationModal Item { - anchors.fill: parent + width: pane.contentWidth + implicitHeight: pane.scrollHeight Controls.WebView { id: webview - anchors { top: parent.top; left: parent.left; right: parent.right; bottom: closeButton.top; margins: 8 } + anchors.fill: parent url: "https://metaverse.highfidelity.com/marketplace?category=avatars" focus: true } - - Button { - id: closeButton - anchors { bottom: parent.bottom; right: parent.right; margins: 8 } - text: "Close" - onClicked: root.destroy(); - } } } diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index 0e7941a5a4..476925a0c5 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -29,6 +29,10 @@ #include "Bookmarks.h" #include + +const QString Bookmarks::HOME_BOOKMARK = "Home"; + + Bookmarks::Bookmarks() { _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + BOOKMARKS_FILENAME; readFromFile(); @@ -60,6 +64,10 @@ bool Bookmarks::contains(const QString& name) const { return _bookmarks.contains(name); } +QString Bookmarks::addressForBookmark(const QString& name) const { + return _bookmarks.value(name).toString(); +} + void Bookmarks::readFromFile() { QFile loadFile(_bookmarksFilename); @@ -95,6 +103,8 @@ void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { // Add menus/actions auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation); QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(bookmarkLocation()), Qt::QueuedConnection); + auto setHomeAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::SetHomeLocation); + QObject::connect(setHomeAction, SIGNAL(triggered()), this, SLOT(setHomeLocation()), Qt::QueuedConnection); _bookmarksMenu = menu->addMenu(MenuOption::Bookmarks); _deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark); QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection); @@ -146,6 +156,18 @@ void Bookmarks::bookmarkLocation() { enableMenuItems(true); } +void Bookmarks::setHomeLocation() { + Menu* menubar = Menu::getInstance(); + QString bookmarkName = HOME_BOOKMARK; + auto addressManager = DependencyManager::get(); + QString bookmarkAddress = addressManager->currentAddress().toString(); + + addLocationToMenu(menubar, bookmarkName, bookmarkAddress); + insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. + + enableMenuItems(true); +} + void Bookmarks::teleportToBookmark() { QAction* action = qobject_cast(sender()); QString address = action->data().toString(); diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h index 7ff9d48e8a..fd9598b7db 100644 --- a/interface/src/Bookmarks.h +++ b/interface/src/Bookmarks.h @@ -29,8 +29,13 @@ public: void setupMenus(Menu* menubar, MenuWrapper* menu); + QString addressForBookmark(const QString& name) const; + + static const QString HOME_BOOKMARK; + private slots: void bookmarkLocation(); + void setHomeLocation(); void teleportToBookmark(); void deleteBookmark(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b1bcf91e10..5796575780 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -170,6 +170,7 @@ namespace MenuOption { const QString RunTimingTests = "Run Timing Tests"; const QString ScriptEditor = "Script Editor..."; const QString ScriptedMotorControl = "Enable Scripted Motor Control"; + const QString SetHomeLocation = "Set Home Location"; const QString ShowDSConnectTable = "Show Domain Connection Timing"; const QString ShowBordersEntityNodes = "Show Entity Nodes"; const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats"; diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index bedd089c93..94a66782f2 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -78,11 +78,11 @@ private: void simulateAvatarFades(float deltaTime); // virtual overrides - virtual AvatarSharedPointer newSharedAvatar(); - virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer); + virtual AvatarSharedPointer newSharedAvatar() override; + virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer) override; - virtual void removeAvatar(const QUuid& sessionUUID); - virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar); + virtual void removeAvatar(const QUuid& sessionUUID) override; + virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) override; QVector _avatarFades; std::shared_ptr _myAvatar; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 614f7bd9fe..bad60643ec 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -663,14 +663,6 @@ void MyAvatar::restoreRoleAnimation(const QString& role) { _rig->restoreRoleAnimation(role); } -void MyAvatar::prefetchAnimation(const QString& url) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "prefetchAnimation", Q_ARG(const QString&, url)); - return; - } - _rig->prefetchAnimation(url); -} - void MyAvatar::saveData() { Settings settings; settings.beginGroup("Avatar"); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e320c0e3de..fee1a9add3 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -143,9 +143,6 @@ public: // remove an animation role override and return to the standard animation. Q_INVOKABLE void restoreRoleAnimation(const QString& role); - // prefetch animation - Q_INVOKABLE void prefetchAnimation(const QString& url); - // Adds handler(animStateDictionaryIn) => animStateDictionaryOut, which will be invoked just before each animGraph state update. // The handler will be called with an animStateDictionaryIn that has all those properties specified by the (possibly empty) // propertiesList argument. However for debugging, if the properties argument is null, all internal animGraph state is provided. diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 7019944f3b..0fe1a59bb2 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -85,12 +85,23 @@ Rig::CharacterControllerState convertCharacterControllerState(CharacterControlle }; } + // Called within Model::simulate call, below. void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { const FBXGeometry& geometry = getFBXGeometry(); Head* head = _owningAvatar->getHead(); + + // make sure lookAt is not too close to face (avoid crosseyes) + glm::vec3 lookAt = _owningAvatar->isMyAvatar() ? head->getLookAtPosition() : head->getCorrectedLookAtPosition(); + glm::vec3 focusOffset = lookAt - _owningAvatar->getHead()->getEyePosition(); + float focusDistance = glm::length(focusOffset); + const float MIN_LOOK_AT_FOCUS_DISTANCE = 1.0f; + if (focusDistance < MIN_LOOK_AT_FOCUS_DISTANCE && focusDistance > EPSILON) { + lookAt = _owningAvatar->getHead()->getEyePosition() + (MIN_LOOK_AT_FOCUS_DISTANCE / focusDistance) * focusOffset; + } + if (_owningAvatar->isMyAvatar()) { MyAvatar* myAvatar = static_cast(_owningAvatar); @@ -164,7 +175,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::EyeParameters eyeParams; eyeParams.worldHeadOrientation = headParams.worldHeadOrientation; - eyeParams.eyeLookAt = head->getLookAtPosition(); + eyeParams.eyeLookAt = lookAt; eyeParams.eyeSaccade = head->getSaccade(); eyeParams.modelRotation = getRotation(); eyeParams.modelTranslation = getTranslation(); @@ -196,8 +207,8 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::EyeParameters eyeParams; eyeParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame(); - eyeParams.eyeLookAt = head->getCorrectedLookAtPosition(); - eyeParams.eyeSaccade = glm::vec3(); + eyeParams.eyeLookAt = lookAt; + eyeParams.eyeSaccade = glm::vec3(0.0f); eyeParams.modelRotation = getRotation(); eyeParams.modelTranslation = getTranslation(); eyeParams.leftEyeJointIndex = geometry.leftEyeJointIndex; diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index 9718aafd14..b483160552 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -10,6 +10,7 @@ // #include "AddressBarDialog.h" +#include "Application.h" #include @@ -50,6 +51,16 @@ void AddressBarDialog::loadAddress(const QString& address) { } } +void AddressBarDialog::loadHome() { + qDebug() << "Called LoadHome"; + QString homeLocation = qApp->getBookmarks()->addressForBookmark(Bookmarks::HOME_BOOKMARK); + const QString DEFAULT_HOME_LOCATION = "localhost"; + if (homeLocation == "") { + homeLocation = DEFAULT_HOME_LOCATION; + } + DependencyManager::get()->handleLookupString(homeLocation); +} + void AddressBarDialog::loadBack() { qDebug() << "Called LoadBack"; DependencyManager::get()->goBack(); diff --git a/interface/src/ui/AddressBarDialog.h b/interface/src/ui/AddressBarDialog.h index 811e2f5b12..eab1ebae69 100644 --- a/interface/src/ui/AddressBarDialog.h +++ b/interface/src/ui/AddressBarDialog.h @@ -36,6 +36,7 @@ protected: void hide(); Q_INVOKABLE void loadAddress(const QString& address); + Q_INVOKABLE void loadHome(); Q_INVOKABLE void loadBack(); Q_INVOKABLE void loadForward(); diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index c001d39f69..41e7e517b7 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -23,7 +23,7 @@ public: Base3DOverlay(const Base3DOverlay* base3DOverlay); // getters - virtual bool is3D() const { return true; } + virtual bool is3D() const override { return true; } const glm::vec3& getPosition() const { return _transform.getTranslation(); } const glm::quat& getRotation() const { return _transform.getRotation(); } const glm::vec3& getScale() const { return _transform.getScale(); } @@ -50,7 +50,7 @@ public: void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } void setDrawInFront(bool value) { _drawInFront = value; } - virtual AABox getBounds() const = 0; + virtual AABox getBounds() const override = 0; void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; diff --git a/interface/src/ui/overlays/Billboard3DOverlay.h b/interface/src/ui/overlays/Billboard3DOverlay.h index 1d4d60bf5b..d256a92afe 100644 --- a/interface/src/ui/overlays/Billboard3DOverlay.h +++ b/interface/src/ui/overlays/Billboard3DOverlay.h @@ -27,7 +27,7 @@ public: QVariant getProperty(const QString& property) override; protected: - virtual void applyTransformTo(Transform& transform, bool force = false); + virtual void applyTransformTo(Transform& transform, bool force = false) override; }; #endif // hifi_Billboard3DOverlay_h diff --git a/interface/src/ui/overlays/Circle3DOverlay.h b/interface/src/ui/overlays/Circle3DOverlay.h index f0bc49c313..c0e84ef1c6 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.h +++ b/interface/src/ui/overlays/Circle3DOverlay.h @@ -19,12 +19,12 @@ class Circle3DOverlay : public Planar3DOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } Circle3DOverlay(); Circle3DOverlay(const Circle3DOverlay* circle3DOverlay); - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; virtual const render::ShapeKey getShapeKey() override; void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -54,9 +54,9 @@ public: void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; } virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal); + BoxFace& face, glm::vec3& surfaceNormal) override; - virtual Circle3DOverlay* createClone() const; + virtual Circle3DOverlay* createClone() const override; protected: float _startAt; diff --git a/interface/src/ui/overlays/Cube3DOverlay.h b/interface/src/ui/overlays/Cube3DOverlay.h index 93ea46db4d..78b8b06582 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.h +++ b/interface/src/ui/overlays/Cube3DOverlay.h @@ -18,15 +18,15 @@ class Cube3DOverlay : public Volume3DOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } Cube3DOverlay() {} Cube3DOverlay(const Cube3DOverlay* cube3DOverlay); - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; virtual const render::ShapeKey getShapeKey() override; - virtual Cube3DOverlay* createClone() const; + virtual Cube3DOverlay* createClone() const override; float getBorderSize() const { return _borderSize; } diff --git a/interface/src/ui/overlays/Grid3DOverlay.h b/interface/src/ui/overlays/Grid3DOverlay.h index aa372436de..90e3083dba 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.h +++ b/interface/src/ui/overlays/Grid3DOverlay.h @@ -19,22 +19,22 @@ class Grid3DOverlay : public Planar3DOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } Grid3DOverlay(); Grid3DOverlay(const Grid3DOverlay* grid3DOverlay); - virtual AABox getBounds() const; + virtual AABox getBounds() const override; - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; virtual const render::ShapeKey getShapeKey() override; void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; - virtual Grid3DOverlay* createClone() const; + virtual Grid3DOverlay* createClone() const override; // Grids are UI tools, and may not be intersected (pickable) - virtual bool findRayIntersection(const glm::vec3&, const glm::vec3&, float&, BoxFace&, glm::vec3&) { return false; } + virtual bool findRayIntersection(const glm::vec3&, const glm::vec3&, float&, BoxFace&, glm::vec3&) override { return false; } private: void updateGrid(); diff --git a/interface/src/ui/overlays/Image3DOverlay.h b/interface/src/ui/overlays/Image3DOverlay.h index 2bdc58709a..159c6b4ccb 100644 --- a/interface/src/ui/overlays/Image3DOverlay.h +++ b/interface/src/ui/overlays/Image3DOverlay.h @@ -22,14 +22,14 @@ class Image3DOverlay : public Billboard3DOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } Image3DOverlay(); Image3DOverlay(const Image3DOverlay* image3DOverlay); - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; - virtual void update(float deltatime); + virtual void update(float deltatime) override; virtual const render::ShapeKey getShapeKey() override; @@ -41,9 +41,9 @@ public: QVariant getProperty(const QString& property) override; virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal); + BoxFace& face, glm::vec3& surfaceNormal) override; - virtual Image3DOverlay* createClone() const; + virtual Image3DOverlay* createClone() const override; private: QString _url; diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index 8ff38859a2..db50d11276 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -18,14 +18,14 @@ class Line3DOverlay : public Base3DOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } Line3DOverlay(); Line3DOverlay(const Line3DOverlay* line3DOverlay); ~Line3DOverlay(); - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; virtual const render::ShapeKey getShapeKey() override; - virtual AABox getBounds() const; + virtual AABox getBounds() const override; // getters const glm::vec3& getStart() const { return _start; } @@ -38,7 +38,7 @@ public: void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; - virtual Line3DOverlay* createClone() const; + virtual Line3DOverlay* createClone() const override; protected: glm::vec3 _start; diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 36ff75cb6a..dc4b4a853b 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -20,24 +20,24 @@ class ModelOverlay : public Volume3DOverlay { Q_OBJECT public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } ModelOverlay(); ModelOverlay(const ModelOverlay* modelOverlay); - virtual void update(float deltatime); - virtual void render(RenderArgs* args); + virtual void update(float deltatime) override; + virtual void render(RenderArgs* args) override; void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal); - virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, QString& extraInfo); + BoxFace& face, glm::vec3& surfaceNormal) override; + virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, QString& extraInfo) override; - virtual ModelOverlay* createClone() const; + virtual ModelOverlay* createClone() const override; - virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); - virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; + virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; private: diff --git a/interface/src/ui/overlays/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h index 3fd11f79f0..a1efe8a6de 100644 --- a/interface/src/ui/overlays/Overlay2D.h +++ b/interface/src/ui/overlays/Overlay2D.h @@ -22,9 +22,9 @@ public: Overlay2D() {} Overlay2D(const Overlay2D* overlay2D); - virtual AABox getBounds() const; + virtual AABox getBounds() const override; - virtual bool is3D() const { return false; } + virtual bool is3D() const override { return false; } // getters int getX() const { return _bounds.x(); } diff --git a/interface/src/ui/overlays/Planar3DOverlay.h b/interface/src/ui/overlays/Planar3DOverlay.h index ef391e61e4..9c502ab75e 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.h +++ b/interface/src/ui/overlays/Planar3DOverlay.h @@ -20,7 +20,7 @@ public: Planar3DOverlay(); Planar3DOverlay(const Planar3DOverlay* planar3DOverlay); - virtual AABox getBounds() const; + virtual AABox getBounds() const override; glm::vec2 getDimensions() const { return _dimensions; } void setDimensions(float value) { _dimensions = glm::vec2(value); } @@ -30,7 +30,7 @@ public: QVariant getProperty(const QString& property) override; virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal); + BoxFace& face, glm::vec3& surfaceNormal) override; protected: glm::vec2 _dimensions; diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.h b/interface/src/ui/overlays/Rectangle3DOverlay.h index 31ccac45a3..525224ef29 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.h +++ b/interface/src/ui/overlays/Rectangle3DOverlay.h @@ -18,16 +18,16 @@ class Rectangle3DOverlay : public Planar3DOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } Rectangle3DOverlay(); Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay); ~Rectangle3DOverlay(); - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; virtual const render::ShapeKey getShapeKey() override; void setProperties(const QVariantMap& properties) override; - virtual Rectangle3DOverlay* createClone() const; + virtual Rectangle3DOverlay* createClone() const override; private: int _geometryCacheID; glm::vec2 _previousHalfDimensions; diff --git a/interface/src/ui/overlays/Sphere3DOverlay.h b/interface/src/ui/overlays/Sphere3DOverlay.h index ec2efa9f04..991b2ab51e 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.h +++ b/interface/src/ui/overlays/Sphere3DOverlay.h @@ -18,15 +18,15 @@ class Sphere3DOverlay : public Volume3DOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } Sphere3DOverlay() {} Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay); - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; virtual const render::ShapeKey getShapeKey() override; - virtual Sphere3DOverlay* createClone() const; + virtual Sphere3DOverlay* createClone() const override; }; diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index 181e9d526c..b7756d0400 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -22,14 +22,14 @@ class Text3DOverlay : public Billboard3DOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } Text3DOverlay(); Text3DOverlay(const Text3DOverlay* text3DOverlay); ~Text3DOverlay(); - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; - virtual void update(float deltatime); + virtual void update(float deltatime) override; virtual const render::ShapeKey getShapeKey() override; @@ -59,9 +59,9 @@ public: QSizeF textSize(const QString& test) const; // Meters virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal); + BoxFace& face, glm::vec3& surfaceNormal) override; - virtual Text3DOverlay* createClone() const; + virtual Text3DOverlay* createClone() const override; private: TextRenderer3D* _textRenderer = nullptr; diff --git a/interface/src/ui/overlays/Volume3DOverlay.h b/interface/src/ui/overlays/Volume3DOverlay.h index 42b3d439d6..4d087615d2 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.h +++ b/interface/src/ui/overlays/Volume3DOverlay.h @@ -20,7 +20,7 @@ public: Volume3DOverlay() {} Volume3DOverlay(const Volume3DOverlay* volume3DOverlay); - virtual AABox getBounds() const; + virtual AABox getBounds() const override; const glm::vec3& getDimensions() const { return _localBoundingBox.getDimensions(); } void setDimensions(float value) { _localBoundingBox.setBox(glm::vec3(-value / 2.0f), value); } @@ -30,7 +30,7 @@ public: QVariant getProperty(const QString& property) override; virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal); + BoxFace& face, glm::vec3& surfaceNormal) override; protected: // Centered local bounding box diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 062cff61d6..a828626715 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -18,16 +18,16 @@ class Web3DOverlay : public Billboard3DOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } Web3DOverlay(); Web3DOverlay(const Web3DOverlay* Web3DOverlay); virtual ~Web3DOverlay(); - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; virtual const render::ShapeKey getShapeKey() override; - virtual void update(float deltatime); + virtual void update(float deltatime) override; // setters void setURL(const QString& url); @@ -36,9 +36,9 @@ public: QVariant getProperty(const QString& property) override; virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal); + BoxFace& face, glm::vec3& surfaceNormal) override; - virtual Web3DOverlay* createClone() const; + virtual Web3DOverlay* createClone() const override; private: OffscreenQmlSurface* _webSurface{ nullptr }; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index b3f5e30d40..a7115199a2 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -152,14 +152,6 @@ void Rig::restoreRoleAnimation(const QString& role) { } } -void Rig::prefetchAnimation(const QString& url) { - - // This will begin loading the NetworkGeometry for the given URL. - // which should speed us up if we request it later via overrideAnimation. - auto clipNode = std::make_shared("prefetch", url, 0, 0, 1.0, false, false); - _prefetchedAnimations.push_back(clipNode); -} - void Rig::destroyAnimGraph() { _animSkeleton.reset(); _animLoader.reset(); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 897fa358e8..363006d48c 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -94,7 +94,6 @@ public: QStringList getAnimationRoles() const; void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void restoreRoleAnimation(const QString& role); - void prefetchAnimation(const QString& url); void initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset); void reset(const FBXGeometry& geometry); @@ -203,8 +202,6 @@ public: // rig space bool getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const; - const glm::vec3& getEyesInRootFrame() const { return _eyesInRootFrame; } - // rig space AnimPose getAbsoluteDefaultPose(int index) const; @@ -275,7 +272,6 @@ protected: glm::vec3 _lastFront; glm::vec3 _lastPosition; glm::vec3 _lastVelocity; - glm::vec3 _eyesInRootFrame { Vectors::ZERO }; QUrl _animGraphURL; std::shared_ptr _animNode; @@ -322,7 +318,6 @@ protected: SimpleMovingAverage _averageLateralSpeed { 10 }; std::map _origRoleAnimations; - std::vector _prefetchedAnimations; bool _lastEnableInverseKinematics { true }; bool _enableInverseKinematics { true }; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 8e46521bfc..013385a169 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -380,7 +380,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetTexture(zone->getKeyLightProperties().getAmbientURL(), CUBE_TEXTURE); + _ambientTexture = textureCache->getTexture(zone->getKeyLightProperties().getAmbientURL(), NetworkTexture::CUBE_TEXTURE); _pendingAmbientTexture = true; if (_ambientTexture && _ambientTexture->isLoaded()) { @@ -410,7 +410,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetTexture(zone->getSkyboxProperties().getURL(), CUBE_TEXTURE); + _skyboxTexture = textureCache->getTexture(zone->getSkyboxProperties().getURL(), NetworkTexture::CUBE_TEXTURE); _pendingSkyboxTexture = true; if (_skyboxTexture && _skyboxTexture->isLoaded()) { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 49a55b6b27..4125be61dd 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -33,7 +33,7 @@ public: QObject* getEventHandler(); void update(const quint64& now) override; - bool needsToCallUpdate() const { return _webSurface != nullptr; } + bool needsToCallUpdate() const override { return _webSurface != nullptr; } SIMPLE_RENDERABLE(); diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index 241a066341..58aa951e64 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -27,19 +27,19 @@ public: _needsInitialSimulation(true) { } - virtual bool setProperties(const EntityItemProperties& properties); + virtual bool setProperties(const EntityItemProperties& properties) override; virtual void somethingChangedNotification() override; virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, - bool& somethingChanged); + bool& somethingChanged) override; - virtual void render(RenderArgs* args); - virtual bool contains(const glm::vec3& point) const; + virtual void render(RenderArgs* args) override; + virtual bool contains(const glm::vec3& point) const override; - virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); - virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; + virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; private: virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); } diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index ba59d66cf4..c634326a31 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -54,6 +54,9 @@ public: virtual bool lifetimeIsOver() { return false; } virtual quint64 getExpires() { return 0; } + virtual bool isMine() { return _isMine; } + virtual void setIsMine(bool value) { _isMine = value; } + bool locallyAddedButNotYetReceived = false; virtual bool shouldSuppressLocationEdits() { return false; } @@ -89,6 +92,7 @@ protected: QUuid _id; EntityActionType _type; bool _active { false }; + bool _isMine { false }; // did this interface create / edit this action? }; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 2d1bbf2f88..dc017f81e6 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -658,6 +658,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef if (_simulationOwner.set(newSimOwner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; somethingChanged = true; + // recompute weOwnSimulation so that if this is the packet that tells use we are the owner, + // we ignore the physics changes from this packet. + weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); } } { // When we own the simulation we don't accept updates to the entity's transform/velocities @@ -1702,6 +1705,7 @@ bool EntityItem::updateAction(EntitySimulation* simulation, const QUuid& actionI success = action->updateArguments(arguments); if (success) { + action->setIsMine(true); serializeActions(success, _allActionsDataCache); _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; } else { @@ -1808,7 +1812,9 @@ void EntityItem::deserializeActionsInternal() { EntityActionPointer action = _objectActions[actionID]; // TODO: make sure types match? there isn't currently a way to // change the type of an existing action. - action->deserialize(serializedAction); + if (!action->isMine()) { + action->deserialize(serializedAction); + } action->locallyAddedButNotYetReceived = false; updated << actionID; } else { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b3689b9b56..742ab337d0 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -361,7 +361,7 @@ public: void setPhysicsInfo(void* data) { _physicsInfo = data; } EntityTreeElementPointer getElement() const { return _element; } EntityTreePointer getTree() const; - virtual SpatialParentTree* getParentTree() const; + virtual SpatialParentTree* getParentTree() const override; bool wantTerseEditLogging() const; glm::mat4 getEntityToWorldMatrix() const; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 8213316b7b..9a4539ea9f 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -830,6 +830,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, if (!action) { return false; } + action->setIsMine(true); success = entity->addAction(simulation, action); entity->grabSimulationOwnership(); return false; // Physics will cause a packet to be sent, so don't send from here. diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 1937bf6daf..54e516d01d 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -127,7 +127,7 @@ public: EntityItemPointer findClosestEntity(glm::vec3 position, float targetRadius); EntityItemPointer findEntityByID(const QUuid& id); EntityItemPointer findEntityByEntityItemID(const EntityItemID& entityID); - virtual SpatiallyNestablePointer findByID(const QUuid& id) { return findEntityByID(id); } + virtual SpatiallyNestablePointer findByID(const QUuid& id) override { return findEntityByID(id); } EntityItemID assignEntityID(const EntityItemID& entityItemID); /// Assigns a known ID for a creator token ID diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index ba6f32b51f..4538a1bb43 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -49,7 +49,7 @@ public: const rgbColor& getColor() const { return _color; } xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } - glm::vec3 getColorRGB() const { return ColorUtils::toLinearVec3(toGlm(getXColor())); } + glm::vec3 getColorRGB() const { return ColorUtils::sRGBToLinearVec3(toGlm(getXColor())); } static const xColor DEFAULT_COLOR; void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } @@ -62,17 +62,17 @@ public: bool _isColorStartInitialized = false; void setColorStart(const xColor& colorStart) { _colorStart = colorStart; _isColorStartInitialized = true; } xColor getColorStart() const { return _isColorStartInitialized ? _colorStart : getXColor(); } - glm::vec3 getColorStartRGB() const { return _isColorStartInitialized ? ColorUtils::toLinearVec3(toGlm(_colorStart)) : getColorRGB(); } + glm::vec3 getColorStartRGB() const { return _isColorStartInitialized ? ColorUtils::sRGBToLinearVec3(toGlm(_colorStart)) : getColorRGB(); } bool _isColorFinishInitialized = false; void setColorFinish(const xColor& colorFinish) { _colorFinish = colorFinish; _isColorFinishInitialized = true; } xColor getColorFinish() const { return _isColorFinishInitialized ? _colorFinish : getXColor(); } - glm::vec3 getColorFinishRGB() const { return _isColorStartInitialized ? ColorUtils::toLinearVec3(toGlm(_colorFinish)) : getColorRGB(); } + glm::vec3 getColorFinishRGB() const { return _isColorStartInitialized ? ColorUtils::sRGBToLinearVec3(toGlm(_colorFinish)) : getColorRGB(); } static const xColor DEFAULT_COLOR_SPREAD; void setColorSpread(const xColor& colorSpread) { _colorSpread = colorSpread; } xColor getColorSpread() const { return _colorSpread; } - glm::vec3 getColorSpreadRGB() const { return ColorUtils::toLinearVec3(toGlm(_colorSpread)); } + glm::vec3 getColorSpreadRGB() const { return ColorUtils::sRGBToLinearVec3(toGlm(_colorSpread)); } static const float MAXIMUM_ALPHA; static const float MINIMUM_ALPHA; diff --git a/libraries/gpu/src/gpu/Color.slh b/libraries/gpu/src/gpu/Color.slh index d4d9ba7b81..4330b34b90 100644 --- a/libraries/gpu/src/gpu/Color.slh +++ b/libraries/gpu/src/gpu/Color.slh @@ -11,9 +11,14 @@ <@if not GPU_COLOR_SLH@> <@def GPU_COLOR_SLH@> +float sRGBFloatToLinear(float value) { + const float SRGB_ELBOW = 0.04045; + + return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4); +} + vec3 colorToLinearRGB(vec3 srgb) { - const float GAMMA_22 = 2.2; - return pow(srgb, vec3(GAMMA_22)); + return vec3(sRGBFloatToLinear(srgb.r), sRGBFloatToLinear(srgb.g), sRGBFloatToLinear(srgb.b)); } vec4 colorToLinearRGBA(vec4 srgba) { diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index 7c603919fd..b7a8380f78 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -11,6 +11,7 @@ using namespace gpu; const Element Element::COLOR_RGBA_32{ VEC4, NUINT8, RGBA }; +const Element Element::COLOR_SRGBA_32{ VEC4, NUINT8, SRGBA }; const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA }; const Element Element::VEC2F_UV{ VEC2, FLOAT, UV }; const Element Element::VEC2F_XY{ VEC2, FLOAT, XY }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 9c08e45bec..6b2bc4b93e 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -245,6 +245,7 @@ public: } static const Element COLOR_RGBA_32; + static const Element COLOR_SRGBA_32; static const Element VEC4F_COLOR_RGBA; static const Element VEC2F_UV; static const Element VEC2F_XY; diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 9f10f2e2b6..2362926c84 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -18,6 +18,8 @@ #include "GPULogging.h" #include "Context.h" +#include "ColorUtils.h" + using namespace gpu; static int TexturePointerMetaTypeId = qRegisterMetaType(); @@ -637,18 +639,6 @@ void SphericalHarmonics::assignPreset(int p) { } } - - -glm::vec3 sRGBToLinear(glm::vec3& color) { - const float GAMMA_CORRECTION = 2.2f; - return glm::pow(color, glm::vec3(GAMMA_CORRECTION)); -} - -glm::vec3 linearTosRGB(glm::vec3& color) { - const float GAMMA_CORRECTION_INV = 1.0f / 2.2f; - return glm::pow(color, glm::vec3(GAMMA_CORRECTION_INV)); -} - // Originial code for the Spherical Harmonics taken from "Sun and Black Cat- Igor Dykhta (igor dykhta email) � 2007-2014 " void sphericalHarmonicsAdd(float * result, int order, const float * inputA, const float * inputB) { const int numCoeff = order * order; @@ -803,7 +793,7 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector< float(data[pixOffsetIndex+2]) * UCHAR_TO_FLOAT); // Gamma correct - clr = sRGBToLinear(clr); + clr = ColorUtils::sRGBToLinearVec3(clr); // scale color and add to previously accumulated coefficients sphericalHarmonicsScale(shBuffB.data(), order, diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 6dd1d97d7f..e4fb5c97f8 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -237,13 +237,14 @@ ModelCache::ModelCache() { QSharedPointer ModelCache::createResource(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, const void* extra) { - const GeometryExtra* geometryExtra = static_cast(extra); - Resource* resource = nullptr; if (url.path().toLower().endsWith(".fst")) { resource = new GeometryMappingResource(url); } else { - resource = new GeometryDefinitionResource(url, geometryExtra->mapping, geometryExtra->textureBaseUrl); + const GeometryExtra* geometryExtra = static_cast(extra); + auto mapping = geometryExtra ? geometryExtra->mapping : QVariantHash(); + auto textureBaseUrl = geometryExtra ? geometryExtra->textureBaseUrl : QUrl(); + resource = new GeometryDefinitionResource(url, mapping, textureBaseUrl); } return QSharedPointer(resource, &Resource::deleter); @@ -424,7 +425,7 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur { _textures = Textures(MapChannel::NUM_MAP_CHANNELS); if (!material.albedoTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, NetworkTexture::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); _albedoTransform = material.albedoTexture.transform; map->setTextureTransform(_albedoTransform); @@ -441,39 +442,39 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur if (!material.normalTexture.filename.isEmpty()) { - auto type = (material.normalTexture.isBumpmap ? BUMP_TEXTURE : NORMAL_TEXTURE); + auto type = (material.normalTexture.isBumpmap ? NetworkTexture::BUMP_TEXTURE : NetworkTexture::NORMAL_TEXTURE); auto map = fetchTextureMap(textureBaseUrl, material.normalTexture, type, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } if (!material.roughnessTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, NetworkTexture::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); setTextureMap(MapChannel::ROUGHNESS_MAP, map); } else if (!material.glossTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, NetworkTexture::GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP); setTextureMap(MapChannel::ROUGHNESS_MAP, map); } if (!material.metallicTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, NetworkTexture::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); setTextureMap(MapChannel::METALLIC_MAP, map); } else if (!material.specularTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, SPECULAR_TEXTURE, MapChannel::METALLIC_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, NetworkTexture::SPECULAR_TEXTURE, MapChannel::METALLIC_MAP); setTextureMap(MapChannel::METALLIC_MAP, map); } if (!material.occlusionTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, NetworkTexture::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); setTextureMap(MapChannel::OCCLUSION_MAP, map); } if (!material.emissiveTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, NetworkTexture::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); setTextureMap(MapChannel::EMISSIVE_MAP, map); } if (!material.lightmapTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, NetworkTexture::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); _lightmapTransform = material.lightmapTexture.transform; _lightmapParams = material.lightmapParams; map->setTextureTransform(_lightmapTransform); @@ -495,7 +496,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!albedoName.isEmpty()) { auto url = textureMap.contains(albedoName) ? textureMap[albedoName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(url, NetworkTexture::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); map->setTextureTransform(_albedoTransform); // when reassigning the albedo texture we also check for the alpha channel used as opacity map->setUseAlphaChannel(true); @@ -504,39 +505,39 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!normalName.isEmpty()) { auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, NORMAL_TEXTURE, MapChannel::NORMAL_MAP); + auto map = fetchTextureMap(url, NetworkTexture::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } if (!roughnessName.isEmpty()) { auto url = textureMap.contains(roughnessName) ? textureMap[roughnessName].toUrl() : QUrl(); // FIXME: If passing a gloss map instead of a roughmap how do we know? - auto map = fetchTextureMap(url, ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + auto map = fetchTextureMap(url, NetworkTexture::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); setTextureMap(MapChannel::ROUGHNESS_MAP, map); } if (!metallicName.isEmpty()) { auto url = textureMap.contains(metallicName) ? textureMap[metallicName].toUrl() : QUrl(); // FIXME: If passing a specular map instead of a metallic how do we know? - auto map = fetchTextureMap(url, METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + auto map = fetchTextureMap(url, NetworkTexture::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); setTextureMap(MapChannel::METALLIC_MAP, map); } if (!occlusionName.isEmpty()) { auto url = textureMap.contains(occlusionName) ? textureMap[occlusionName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + auto map = fetchTextureMap(url, NetworkTexture::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); setTextureMap(MapChannel::OCCLUSION_MAP, map); } if (!emissiveName.isEmpty()) { auto url = textureMap.contains(emissiveName) ? textureMap[emissiveName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + auto map = fetchTextureMap(url, NetworkTexture::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); setTextureMap(MapChannel::EMISSIVE_MAP, map); } if (!lightmapName.isEmpty()) { auto url = textureMap.contains(lightmapName) ? textureMap[lightmapName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + auto map = fetchTextureMap(url, NetworkTexture::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); map->setTextureTransform(_lightmapTransform); map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); setTextureMap(MapChannel::LIGHTMAP_MAP, map); diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index f479dc9ce2..bf47f293e8 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -98,7 +98,7 @@ public: GeometryResource(const QUrl& url, const QUrl& textureBaseUrl = QUrl()) : Resource(url), _textureBaseUrl(textureBaseUrl) {} - virtual bool areTexturesLoaded() const { return isLoaded() && Geometry::areTexturesLoaded(); } + virtual bool areTexturesLoaded() const override { return isLoaded() && Geometry::areTexturesLoaded(); } virtual void deleter() override; @@ -170,6 +170,8 @@ protected: const bool& isOriginal() const { return _isOriginal; } private: + using TextureType = NetworkTexture::Type; + // Helpers for the ctors QUrl getTextureUrl(const QUrl& baseUrl, const FBXTexture& fbxTexture); model::TextureMapPointer fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture, diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 7d18151f2c..2aaddace88 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -35,6 +35,16 @@ TextureCache::TextureCache() { const qint64 TEXTURE_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; setUnusedResourceCacheSize(TEXTURE_DEFAULT_UNUSED_MAX_SIZE); setObjectName("TextureCache"); + + // Expose enum Type to JS/QML via properties + // Despite being one-off, this should be fine, because TextureCache is a SINGLETON_DEPENDENCY + QObject* type = new QObject(this); + type->setObjectName("TextureType"); + setProperty("Type", QVariant::fromValue(type)); + auto metaEnum = QMetaEnum::fromType(); + for (int i = 0; i < metaEnum.keyCount(); ++i) { + type->setProperty(metaEnum.key(i), metaEnum.value(i)); + } } TextureCache::~TextureCache() { @@ -145,60 +155,68 @@ const gpu::TexturePointer& TextureCache::getNormalFittingTexture() { /// Extra data for creating textures. class TextureExtra { public: - TextureType type; + NetworkTexture::Type type; const QByteArray& content; }; -NetworkTexturePointer TextureCache::getTexture(const QUrl& url, TextureType type, const QByteArray& content) { +ScriptableResource* TextureCache::prefetch(const QUrl& url, int type) { + auto byteArray = QByteArray(); + TextureExtra extra = { (Type)type, byteArray }; + return ResourceCache::prefetch(url, &extra); +} + +NetworkTexturePointer TextureCache::getTexture(const QUrl& url, Type type, const QByteArray& content) { TextureExtra extra = { type, content }; return ResourceCache::getResource(url, QUrl(), content.isEmpty(), &extra).staticCast(); } -TextureCache::TextureLoaderFunc getTextureLoaderForType(TextureType type) { +NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type type) { + using Type = NetworkTexture; + switch (type) { - case ALBEDO_TEXTURE: { + case Type::ALBEDO_TEXTURE: { return model::TextureUsage::createAlbedoTextureFromImage; break; } - case EMISSIVE_TEXTURE: { + case Type::EMISSIVE_TEXTURE: { return model::TextureUsage::createEmissiveTextureFromImage; break; } - case LIGHTMAP_TEXTURE: { + case Type::LIGHTMAP_TEXTURE: { return model::TextureUsage::createLightmapTextureFromImage; break; } - case CUBE_TEXTURE: { + case Type::CUBE_TEXTURE: { return model::TextureUsage::createCubeTextureFromImage; break; } - case BUMP_TEXTURE: { + case Type::BUMP_TEXTURE: { return model::TextureUsage::createNormalTextureFromBumpImage; break; } - case NORMAL_TEXTURE: { + case Type::NORMAL_TEXTURE: { return model::TextureUsage::createNormalTextureFromNormalImage; break; } - case ROUGHNESS_TEXTURE: { + case Type::ROUGHNESS_TEXTURE: { return model::TextureUsage::createRoughnessTextureFromImage; break; } - case GLOSS_TEXTURE: { + case Type::GLOSS_TEXTURE: { return model::TextureUsage::createRoughnessTextureFromGlossImage; break; } - case SPECULAR_TEXTURE: { + case Type::SPECULAR_TEXTURE: { return model::TextureUsage::createMetallicTextureFromImage; break; } - case CUSTOM_TEXTURE: { + case Type::CUSTOM_TEXTURE: { Q_ASSERT(false); - return TextureCache::TextureLoaderFunc(); + return NetworkTexture::TextureLoaderFunc(); break; } - case DEFAULT_TEXTURE: + case Type::DEFAULT_TEXTURE: default: { return model::TextureUsage::create2DTextureFromImage; break; @@ -207,7 +225,7 @@ TextureCache::TextureLoaderFunc getTextureLoaderForType(TextureType type) { } /// Returns a texture version of an image file -gpu::TexturePointer TextureCache::getImageTexture(const QString& path, TextureType type) { +gpu::TexturePointer TextureCache::getImageTexture(const QString& path, Type type) { QImage image = QImage(path); auto loader = getTextureLoaderForType(type); return gpu::TexturePointer(loader(image, QUrl::fromLocalFile(path).fileName().toStdString())); @@ -216,11 +234,13 @@ gpu::TexturePointer TextureCache::getImageTexture(const QString& path, TextureTy QSharedPointer TextureCache::createResource(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, const void* extra) { const TextureExtra* textureExtra = static_cast(extra); - return QSharedPointer(new NetworkTexture(url, textureExtra->type, textureExtra->content), + auto type = textureExtra ? textureExtra->type : Type::DEFAULT_TEXTURE; + auto content = textureExtra ? textureExtra->content : QByteArray(); + return QSharedPointer(new NetworkTexture(url, type, content), &Resource::deleter); } -NetworkTexture::NetworkTexture(const QUrl& url, TextureType type, const QByteArray& content) : +NetworkTexture::NetworkTexture(const QUrl& url, Type type, const QByteArray& content) : Resource(url, !content.isEmpty()), _type(type) { diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index c614a7ceb3..8fd0b12369 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -25,79 +26,6 @@ namespace gpu { class Batch; } -class NetworkTexture; - -typedef QSharedPointer NetworkTexturePointer; - -enum TextureType { - DEFAULT_TEXTURE, - ALBEDO_TEXTURE, - NORMAL_TEXTURE, - BUMP_TEXTURE, - SPECULAR_TEXTURE, - METALLIC_TEXTURE = SPECULAR_TEXTURE, // for now spec and metallic texture are the same, converted to grey - ROUGHNESS_TEXTURE, - GLOSS_TEXTURE, - EMISSIVE_TEXTURE, - CUBE_TEXTURE, - OCCLUSION_TEXTURE, - LIGHTMAP_TEXTURE, - CUSTOM_TEXTURE -}; - -/// Stores cached textures, including render-to-texture targets. -class TextureCache : public ResourceCache, public Dependency { - Q_OBJECT - SINGLETON_DEPENDENCY - -public: - /// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture - /// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and - /// the second, a set of random unit vectors to be used as noise gradients. - const gpu::TexturePointer& getPermutationNormalTexture(); - - /// Returns an opaque white texture (useful for a default). - const gpu::TexturePointer& getWhiteTexture(); - - /// Returns an opaque gray texture (useful for a default). - const gpu::TexturePointer& getGrayTexture(); - - /// Returns the a pale blue texture (useful for a normal map). - const gpu::TexturePointer& getBlueTexture(); - - /// Returns the a black texture (useful for a default). - const gpu::TexturePointer& getBlackTexture(); - - // Returns a map used to compress the normals through a fitting scale algorithm - const gpu::TexturePointer& getNormalFittingTexture(); - - /// Returns a texture version of an image file - static gpu::TexturePointer getImageTexture(const QString& path, TextureType type = DEFAULT_TEXTURE); - - /// Loads a texture from the specified URL. - NetworkTexturePointer getTexture(const QUrl& url, TextureType type = DEFAULT_TEXTURE, - const QByteArray& content = QByteArray()); - - typedef gpu::Texture* TextureLoader(const QImage& image, const std::string& srcImageName); - - typedef std::function TextureLoaderFunc; -protected: - - virtual QSharedPointer createResource(const QUrl& url, - const QSharedPointer& fallback, bool delayLoad, const void* extra); - -private: - TextureCache(); - virtual ~TextureCache(); - friend class DilatableNetworkTexture; - - gpu::TexturePointer _permutationNormalTexture; - gpu::TexturePointer _whiteTexture; - gpu::TexturePointer _grayTexture; - gpu::TexturePointer _blueTexture; - gpu::TexturePointer _blackTexture; - gpu::TexturePointer _normalFittingTexture; -}; /// A simple object wrapper for an OpenGL texture. class Texture { @@ -107,15 +35,31 @@ public: }; /// A texture loaded from the network. - class NetworkTexture : public Resource, public Texture { Q_OBJECT public: - - typedef TextureCache::TextureLoaderFunc TextureLoaderFunc; - - NetworkTexture(const QUrl& url, TextureType type, const QByteArray& content); + enum Type { + DEFAULT_TEXTURE, + ALBEDO_TEXTURE, + NORMAL_TEXTURE, + BUMP_TEXTURE, + SPECULAR_TEXTURE, + METALLIC_TEXTURE = SPECULAR_TEXTURE, // for now spec and metallic texture are the same, converted to grey + ROUGHNESS_TEXTURE, + GLOSS_TEXTURE, + EMISSIVE_TEXTURE, + CUBE_TEXTURE, + OCCLUSION_TEXTURE, + LIGHTMAP_TEXTURE, + CUSTOM_TEXTURE + }; + Q_ENUM(Type) + + typedef gpu::Texture* TextureLoader(const QImage& image, const std::string& srcImageName); + using TextureLoaderFunc = std::function; + + NetworkTexture(const QUrl& url, Type type, const QByteArray& content); NetworkTexture(const QUrl& url, const TextureLoaderFunc& textureLoader, const QByteArray& content); int getOriginalWidth() const { return _originalWidth; } @@ -138,12 +82,69 @@ protected: Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight); private: - TextureType _type; - TextureLoaderFunc _textureLoader; + Type _type; + TextureLoaderFunc _textureLoader { [](const QImage&, const std::string&){ return nullptr; } }; int _originalWidth { 0 }; int _originalHeight { 0 }; int _width { 0 }; int _height { 0 }; }; +using NetworkTexturePointer = QSharedPointer; + +/// Stores cached textures, including render-to-texture targets. +class TextureCache : public ResourceCache, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY + + using Type = NetworkTexture::Type; + +public: + /// Returns the ID of the permutation/normal texture used for Perlin noise shader programs. This texture + /// has two lines: the first, a set of random numbers in [0, 255] to be used as permutation offsets, and + /// the second, a set of random unit vectors to be used as noise gradients. + const gpu::TexturePointer& getPermutationNormalTexture(); + + /// Returns an opaque white texture (useful for a default). + const gpu::TexturePointer& getWhiteTexture(); + + /// Returns an opaque gray texture (useful for a default). + const gpu::TexturePointer& getGrayTexture(); + + /// Returns the a pale blue texture (useful for a normal map). + const gpu::TexturePointer& getBlueTexture(); + + /// Returns the a black texture (useful for a default). + const gpu::TexturePointer& getBlackTexture(); + + // Returns a map used to compress the normals through a fitting scale algorithm + const gpu::TexturePointer& getNormalFittingTexture(); + + /// Returns a texture version of an image file + static gpu::TexturePointer getImageTexture(const QString& path, Type type = Type::DEFAULT_TEXTURE); + + /// Loads a texture from the specified URL. + NetworkTexturePointer getTexture(const QUrl& url, Type type = Type::DEFAULT_TEXTURE, + const QByteArray& content = QByteArray()); + +protected: + // Overload ResourceCache::prefetch to allow specifying texture type for loads + Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type); + + virtual QSharedPointer createResource(const QUrl& url, + const QSharedPointer& fallback, bool delayLoad, const void* extra); + +private: + TextureCache(); + virtual ~TextureCache(); + friend class DilatableNetworkTexture; + + gpu::TexturePointer _permutationNormalTexture; + gpu::TexturePointer _whiteTexture; + gpu::TexturePointer _grayTexture; + gpu::TexturePointer _blueTexture; + gpu::TexturePointer _blackTexture; + gpu::TexturePointer _normalFittingTexture; +}; + #endif // hifi_TextureCache_h diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index 1ea407122f..d700a191c4 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -65,7 +65,7 @@ Material::~Material() { void Material::setEmissive(const Color& emissive, bool isSRGB) { _key.setEmissive(glm::any(glm::greaterThan(emissive, Color(0.0f)))); _schemaBuffer.edit()._key = (uint32) _key._flags.to_ulong(); - _schemaBuffer.edit()._emissive = (isSRGB ? ColorUtils::toLinearVec3(emissive) : emissive); + _schemaBuffer.edit()._emissive = (isSRGB ? ColorUtils::sRGBToLinearVec3(emissive) : emissive); } void Material::setOpacity(float opacity) { @@ -77,7 +77,7 @@ void Material::setOpacity(float opacity) { void Material::setAlbedo(const Color& albedo, bool isSRGB) { _key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f)))); _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); - _schemaBuffer.edit()._albedo = (isSRGB ? ColorUtils::toLinearVec3(albedo) : albedo); + _schemaBuffer.edit()._albedo = (isSRGB ? ColorUtils::sRGBToLinearVec3(albedo) : albedo); } void Material::setRoughness(float roughness) { @@ -89,7 +89,7 @@ void Material::setRoughness(float roughness) { void Material::setFresnel(const Color& fresnel, bool isSRGB) { //_key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f)))); - _schemaBuffer.edit()._fresnel = (isSRGB ? ColorUtils::toLinearVec3(fresnel) : fresnel); + _schemaBuffer.edit()._fresnel = (isSRGB ? ColorUtils::sRGBToLinearVec3(fresnel) : fresnel); } void Material::setMetallic(float metallic) { diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index 4cfb2120ee..cf6b48f257 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -245,16 +245,16 @@ public: const MaterialKey& getKey() const { return _key; } void setEmissive(const Color& emissive, bool isSRGB = true); - Color getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._emissive) : _schemaBuffer.get()._emissive); } + Color getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_schemaBuffer.get()._emissive) : _schemaBuffer.get()._emissive); } void setOpacity(float opacity); float getOpacity() const { return _schemaBuffer.get()._opacity; } void setAlbedo(const Color& albedo, bool isSRGB = true); - Color getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._albedo) : _schemaBuffer.get()._albedo); } + Color getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_schemaBuffer.get()._albedo) : _schemaBuffer.get()._albedo); } void setFresnel(const Color& fresnel, bool isSRGB = true); - Color getFresnel(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._fresnel) : _schemaBuffer.get()._fresnel); } + Color getFresnel(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_schemaBuffer.get()._fresnel) : _schemaBuffer.get()._fresnel); } void setMetallic(float metallic); float getMetallic() const { return _schemaBuffer.get()._metallic; } diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index c0382a5748..4cc8b1d4f0 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -119,6 +119,92 @@ QSharedPointer ResourceCacheSharedItems::getHighestPendingRequest() { return highestResource; } +ScriptableResource::ScriptableResource(const QUrl& url) : + QObject(nullptr), + _url(url) { } + +void ScriptableResource::release() { + disconnectHelper(); + _resource.reset(); +} + +bool ScriptableResource::isInScript() const { + return _resource && _resource->isInScript(); +} + +void ScriptableResource::setInScript(bool isInScript) { + if (_resource) { + _resource->setInScript(isInScript); + } +} + +void ScriptableResource::loadingChanged() { + emit stateChanged(LOADING); +} + +void ScriptableResource::loadedChanged() { + emit stateChanged(LOADED); +} + +void ScriptableResource::finished(bool success) { + disconnectHelper(); + + emit stateChanged(success ? FINISHED : FAILED); +} + +void ScriptableResource::disconnectHelper() { + if (_progressConnection) { + disconnect(_progressConnection); + } + if (_loadingConnection) { + disconnect(_loadingConnection); + } + if (_loadedConnection) { + disconnect(_loadedConnection); + } + if (_finishedConnection) { + disconnect(_finishedConnection); + } +} + +ScriptableResource* ResourceCache::prefetch(const QUrl& url, void* extra) { + ScriptableResource* result = nullptr; + + if (QThread::currentThread() != thread()) { + // Must be called in thread to ensure getResource returns a valid pointer + QMetaObject::invokeMethod(this, "prefetch", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(ScriptableResource*, result), + Q_ARG(QUrl, url), Q_ARG(void*, extra)); + return result; + } + + result = new ScriptableResource(url); + + auto resource = getResource(url, QUrl(), false, extra); + result->_resource = resource; + result->setObjectName(url.toString()); + + result->_resource = resource; + if (resource->isLoaded()) { + result->finished(!resource->_failedToLoad); + } else { + result->_progressConnection = connect( + resource.data(), &Resource::onProgress, + result, &ScriptableResource::progressChanged); + result->_loadingConnection = connect( + resource.data(), &Resource::loading, + result, &ScriptableResource::loadingChanged); + result->_loadedConnection = connect( + resource.data(), &Resource::loaded, + result, &ScriptableResource::loadedChanged); + result->_finishedConnection = connect( + resource.data(), &Resource::finished, + result, &ScriptableResource::finished); + } + + return result; +} + ResourceCache::ResourceCache(QObject* parent) : QObject(parent) { auto nodeList = DependencyManager::get(); if (nodeList) { @@ -219,7 +305,7 @@ QVariantList ResourceCache::getResourceList() { return list; } - + void ResourceCache::setRequestLimit(int limit) { _requestLimit = limit; @@ -272,6 +358,7 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& getResource(fallback, QUrl(), true) : QSharedPointer(), delayLoad, extra); resource->setSelf(resource); resource->setCache(this); + connect(resource.data(), &Resource::updateSize, this, &ResourceCache::updateTotalSize); { QWriteLocker locker(&_resourcesLock); _resources.insert(url, resource); @@ -357,8 +444,13 @@ void ResourceCache::removeResource(const QUrl& url, qint64 size) { _totalResourcesSize -= size; } -void ResourceCache::updateTotalSize(const qint64& oldSize, const qint64& newSize) { - _totalResourcesSize += (newSize - oldSize); +void ResourceCache::updateTotalSize(const qint64& deltaSize) { + _totalResourcesSize += deltaSize; + + // Sanity checks + assert(_totalResourcesSize >= 0); + assert(_totalResourcesSize < (1024 * BYTES_PER_GIGABYTES)); + emit dirty(); } @@ -543,7 +635,7 @@ void Resource::finishedLoading(bool success) { } void Resource::setSize(const qint64& bytes) { - QMetaObject::invokeMethod(_cache.data(), "updateTotalSize", Q_ARG(qint64, _bytes), Q_ARG(qint64, bytes)); + emit updateSize(bytes - _bytes); _bytes = bytes; } @@ -569,8 +661,11 @@ void Resource::makeRequest() { } qCDebug(networking).noquote() << "Starting request for:" << _url.toDisplayString(); + emit loading(); + + connect(_request, &ResourceRequest::progress, this, &Resource::onProgress); + connect(this, &Resource::onProgress, this, &Resource::handleDownloadProgress); - connect(_request, &ResourceRequest::progress, this, &Resource::handleDownloadProgress); connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished); _bytesReceived = _bytesTotal = _bytes = 0; diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index ed3dbf69b6..b81c69c079 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -24,9 +24,12 @@ #include #include #include + #include #include +#include + #include #include "ResourceManager.h" @@ -50,7 +53,7 @@ static const qint64 DEFAULT_UNUSED_MAX_SIZE = 100 * BYTES_PER_MEGABYTES; static const qint64 DEFAULT_UNUSED_MAX_SIZE = 1024 * BYTES_PER_MEGABYTES; #endif static const qint64 MIN_UNUSED_MAX_SIZE = 0; -static const qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES; +static const qint64 MAX_UNUSED_MAX_SIZE = MAXIMUM_CACHE_SIZE; // We need to make sure that these items are available for all instances of // ResourceCache derived classes. Since we can't count on the ordering of @@ -78,6 +81,61 @@ private: QList> _loadingRequests; }; +/// Wrapper to expose resources to JS/QML +class ScriptableResource : public QObject { + Q_OBJECT + Q_PROPERTY(QUrl url READ getUrl) + Q_PROPERTY(int state READ getState NOTIFY stateChanged) + +public: + enum State { + QUEUED, + LOADING, + LOADED, + FINISHED, + FAILED, + }; + Q_ENUM(State) + + ScriptableResource(const QUrl& url); + virtual ~ScriptableResource() = default; + + Q_INVOKABLE void release(); + + const QUrl& getUrl() const { return _url; } + int getState() const { return (int)_state; } + const QSharedPointer& getResource() const { return _resource; } + + bool isInScript() const; + void setInScript(bool isInScript); + +signals: + void progressChanged(uint64_t bytesReceived, uint64_t bytesTotal); + void stateChanged(int state); + +private slots: + void loadingChanged(); + void loadedChanged(); + void finished(bool success); + +private: + void disconnectHelper(); + + friend class ResourceCache; + + // Holds a ref to the resource to keep it in scope + QSharedPointer _resource; + + QMetaObject::Connection _progressConnection; + QMetaObject::Connection _loadingConnection; + QMetaObject::Connection _loadedConnection; + QMetaObject::Connection _finishedConnection; + + QUrl _url; + State _state{ QUEUED }; +}; + +Q_DECLARE_METATYPE(ScriptableResource*); /// Base class for resource caches. class ResourceCache : public QObject { @@ -121,12 +179,23 @@ public slots: void checkAsynchronousGets(); protected slots: - void updateTotalSize(const qint64& oldSize, const qint64& newSize); + void updateTotalSize(const qint64& deltaSize); + + // Prefetches a resource to be held by the QScriptEngine. + // Left as a protected member so subclasses can overload prefetch + // and delegate to it (see TextureCache::prefetch(const QUrl&, int). + ScriptableResource* prefetch(const QUrl& url, void* extra); private slots: void clearATPAssets(); protected: + // Prefetches a resource to be held by the QScriptEngine. + // Pointers created through this method should be owned by the caller, + // which should be a QScriptEngine with ScriptableResource registered, so that + // the QScriptEngine will delete the pointer when it is garbage collected. + Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr); } + /// Loads a resource from the specified URL. /// \param fallback a fallback URL to load if the desired one is unavailable /// \param delayLoad if true, don't load the resource immediately; wait until load is first requested @@ -231,6 +300,9 @@ public: const QUrl& getURL() const { return _url; } signals: + /// Fired when the resource begins downloading. + void loading(); + /// Fired when the resource has been downloaded. /// This can be used instead of downloadFinished to access data before it is processed. void loaded(const QByteArray request); @@ -244,6 +316,12 @@ signals: /// Fired when the resource is refreshed. void onRefresh(); + /// Fired on progress updates. + void onProgress(uint64_t bytesReceived, uint64_t bytesTotal); + + /// Fired when the size changes (through setSize). + void updateSize(qint64 deltaSize); + protected slots: void attemptRequest(); @@ -280,21 +358,26 @@ private slots: void handleReplyFinished(); private: + friend class ResourceCache; + friend class ScriptableResource; + void setLRUKey(int lruKey) { _lruKey = lruKey; } void makeRequest(); void retry(); void reinsert(); + + bool isInScript() const { return _isInScript; } + void setInScript(bool isInScript) { _isInScript = isInScript; } - friend class ResourceCache; - - ResourceRequest* _request = nullptr; - int _lruKey = 0; - QTimer* _replyTimer = nullptr; - qint64 _bytesReceived = 0; - qint64 _bytesTotal = 0; - qint64 _bytes = 0; - int _attempts = 0; + ResourceRequest* _request{ nullptr }; + int _lruKey{ 0 }; + QTimer* _replyTimer{ nullptr }; + qint64 _bytesReceived{ 0 }; + qint64 _bytesTotal{ 0 }; + qint64 _bytes{ 0 }; + int _attempts{ 0 }; + bool _isInScript{ false }; }; uint qHash(const QPointer& value, uint seed = 0); diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index 2b8f2327a0..b38e481317 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -26,7 +26,7 @@ public: virtual void clear() override; - virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; + virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const override; static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); protected: diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index e7604544bd..3607aa5803 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -363,7 +363,7 @@ void Font::drawString(gpu::Batch& batch, float x, float y, const QString& str, c batch._glUniform1i(_outlineLoc, (effectType == OUTLINE_EFFECT)); // need the gamma corrected color here - glm::vec4 lrgba = glm::vec4(ColorUtils::toLinearVec3(glm::vec3(*color)), color->a); + glm::vec4 lrgba = ColorUtils::sRGBToLinearVec4(*color); batch._glUniform4fv(_colorLoc, 1, (const float*)&lrgba); batch.setInputFormat(_format); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 2f0d81db3f..58b3a50e54 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -105,6 +105,9 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons for (auto& pipelineKey : sortedPipelines) { auto& bucket = sortedShapes[pipelineKey]; args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); + if (!args->_pipeline) { + continue; + } for (auto& item : bucket) { item.render(args); } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 15f3ebb985..20a2bbe2dd 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -140,6 +140,8 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { hadUncaughtExceptions(*this, _fileNameString); }); + + setProcessEventsInterval(MSECS_PER_SECOND); } ScriptEngine::~ScriptEngine() { @@ -170,7 +172,7 @@ void ScriptEngine::runInThread() { } _isThreaded = true; - QThread* workerThread = new QThread(); // thread is not owned, so we need to manage the delete + QThread* workerThread = new QThread(this); // thread is not owned, so we need to manage the delete QString scriptEngineName = QString("Script Thread:") + getFilename(); workerThread->setObjectName(scriptEngineName); @@ -184,9 +186,6 @@ void ScriptEngine::runInThread() { // tell the thread to stop when the script engine is done connect(this, &ScriptEngine::doneRunning, workerThread, &QThread::quit); - // when the thread is finished, add thread to the deleteLater queue - connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater); - moveToThread(workerThread); // Starts an event loop, and emits workerThread->started() @@ -199,11 +198,30 @@ void ScriptEngine::waitTillDoneRunning() { // NOTE: waitTillDoneRunning() will be called on the main Application thread, inside of stopAllScripts() // we want the application thread to continue to process events, because the scripts will likely need to - // marshall messages across to the main thread. For example if they access Settings or Meny in any of their + // marshall messages across to the main thread. For example if they access Settings or Menu in any of their // shutdown code. + QString scriptName = getFilename(); + + auto startedWaiting = usecTimestampNow(); while (thread()->isRunning()) { // process events for the main application thread, allowing invokeMethod calls to pass between threads QCoreApplication::processEvents(); + auto stillWaiting = usecTimestampNow(); + auto elapsedUsecs = stillWaiting - startedWaiting; + + // if we've been waiting a second or more, then tell the script engine to stop evaluating + static const auto MAX_SCRIPT_EVALUATION_TIME = USECS_PER_SECOND; + static const auto WAITING_TOO_LONG = MAX_SCRIPT_EVALUATION_TIME * 5; + + // if we've been waiting for more than 5 seconds then we should be more aggessive about stopping + if (elapsedUsecs > WAITING_TOO_LONG) { + qCDebug(scriptengine) << "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] quitting."; + thread()->quit(); + break; + } else if (elapsedUsecs > MAX_SCRIPT_EVALUATION_TIME) { + qCDebug(scriptengine) << "Script " << scriptName << " has been running too long [" << elapsedUsecs << " usecs] aborting evaluation."; + QMetaObject::invokeMethod(this, "abortEvaluation"); + } } } } @@ -270,6 +288,48 @@ static void resultHandlerFromScriptValue(const QScriptValue& value, AnimVariantR assert(false); } +// Templated qScriptRegisterMetaType fails to compile with raw pointers +using ScriptableResourceRawPtr = ScriptableResource*; + +static QScriptValue scriptableResourceToScriptValue(QScriptEngine* engine, const ScriptableResourceRawPtr& resource) { + // The first script to encounter this resource will track its memory. + // In this way, it will be more likely to GC. + // This fails in the case that the resource is used across many scripts, but + // in that case it would be too difficult to tell which one should track the memory, and + // this serves the common case (use in a single script). + auto data = resource->getResource(); + if (data && !resource->isInScript()) { + resource->setInScript(true); + QObject::connect(data.data(), SIGNAL(updateSize(qint64)), engine, SLOT(updateMemoryCost(qint64))); + } + + auto object = engine->newQObject( + const_cast(resource), + QScriptEngine::ScriptOwnership); + return object; +} + +static void scriptableResourceFromScriptValue(const QScriptValue& value, ScriptableResourceRawPtr& resource) { + resource = static_cast(value.toQObject()); +} + +static QScriptValue createScriptableResourcePrototype(QScriptEngine* engine) { + auto prototype = engine->newObject(); + + // Expose enum State to JS/QML via properties + QObject* state = new QObject(engine); + state->setObjectName("ResourceState"); + auto metaEnum = QMetaEnum::fromType(); + for (int i = 0; i < metaEnum.keyCount(); ++i) { + state->setProperty(metaEnum.key(i), metaEnum.value(i)); + } + + auto prototypeState = engine->newQObject(state, QScriptEngine::QtOwnership, QScriptEngine::ExcludeSlots | QScriptEngine::ExcludeSuperClassMethods); + prototype.setProperty("State", prototypeState); + + return prototype; +} + void ScriptEngine::init() { if (_isInitialized) { return; // only initialize once @@ -327,11 +387,16 @@ void ScriptEngine::init() { registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Mat4", &_mat4Library); registerGlobalObject("Uuid", &_uuidLibrary); - registerGlobalObject("AnimationCache", DependencyManager::get().data()); registerGlobalObject("Messages", DependencyManager::get().data()); qScriptRegisterMetaType(this, animVarMapToScriptValue, animVarMapFromScriptValue); qScriptRegisterMetaType(this, resultHandlerToScriptValue, resultHandlerFromScriptValue); + // Scriptable cache access + auto resourcePrototype = createScriptableResourcePrototype(this); + globalObject().setProperty("Resource", resourcePrototype); + setDefaultPrototype(qMetaTypeId(), resourcePrototype); + qScriptRegisterMetaType(this, scriptableResourceToScriptValue, scriptableResourceFromScriptValue); + // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); @@ -367,7 +432,6 @@ void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) { if (partsToGo > 0) { //QObject *object = new QObject; QScriptValue partValue = newArray(); //newQObject(object, QScriptEngine::ScriptOwnership); - qDebug() << "partValue[" << pathPart<<"].isArray() :" << partValue.isArray(); partObject.setProperty(pathPart, partValue); } else { partObject.setProperty(pathPart, value); @@ -793,6 +857,12 @@ void ScriptEngine::callAnimationStateHandler(QScriptValue callback, AnimVariantM } } +void ScriptEngine::updateMemoryCost(const qint64& deltaSize) { + if (deltaSize > 0) { + reportAdditionalMemoryCost(deltaSize); + } +} + void ScriptEngine::timerFired() { QTimer* callingTimer = reinterpret_cast(sender()); CallbackData timerData = _timerFunctionMap.value(callingTimer); @@ -1060,11 +1130,6 @@ void ScriptEngine::loadEntityScript(QWeakPointer theEngine, const << QThread::currentThread() << "] expected thread [" << strongEngine->thread() << "]"; #endif strongEngine->entityScriptContentAvailable(entityID, scriptOrURL, contents, isURL, success); - } else { - // FIXME - I'm leaving this in for testing, so that QA can confirm that sometimes the script contents - // returns after the ScriptEngine has been deleted, we can remove this after QA verifies the - // repro case. - qDebug() << "ScriptCache::getScriptContents() returned after our ScriptEngine was deleted... script:" << scriptOrURL; } }, forceRedownload); } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index e8ce00c66c..175a3f1f1c 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -131,6 +131,8 @@ public: Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const MouseEvent& event); Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision); + Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts Q_INVOKABLE void stop(); @@ -156,6 +158,7 @@ public: public slots: void callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler); + void updateMemoryCost(const qint64&); signals: void scriptLoaded(const QString& scriptFilename); diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index eeca49ff84..8fea7e4653 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -129,20 +129,7 @@ void ScriptEngines::shutdownScripting() { // "entities sandbox" which is only used to evaluate entities scripts to test their validity before using // them. We don't need to stop scripts that aren't running. if (scriptEngine->isRunning()) { - - // If the script is running, but still evaluating then we need to wait for its evaluation step to - // complete. After that we can handle the stop process appropriately - if (scriptEngine->evaluatePending()) { - while (scriptEngine->evaluatePending()) { - - // This event loop allows any started, but not yet finished evaluate() calls to complete - // we need to let these complete so that we can be guaranteed that the script engine isn't - // in a partially setup state, which can confuse our shutdown unwinding. - QEventLoop loop; - QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit); - loop.exec(); - } - } + qCDebug(scriptengine) << "about to shutdown script:" << scriptName; // We disconnect any script engine signals from the application because we don't want to do any // extra stopScript/loadScript processing that the Application normally does when scripts start diff --git a/libraries/shared/src/ColorUtils.h b/libraries/shared/src/ColorUtils.h index b47e7c3a98..5ee9254bc9 100644 --- a/libraries/shared/src/ColorUtils.h +++ b/libraries/shared/src/ColorUtils.h @@ -21,9 +21,19 @@ class ColorUtils { public: inline static glm::vec3 toVec3(const xColor& color); - // Convert from gamma 2.2 space to linear - inline static glm::vec3 toLinearVec3(const glm::vec3& srgb); + // Convert to gamma 2.2 space from linear inline static glm::vec3 toGamma22Vec3(const glm::vec3& linear); + + // Convert from sRGB gamma space to linear. + // This is pretty different from converting from 2.2. + inline static glm::vec3 sRGBToLinearVec3(const glm::vec3& srgb); + inline static glm::vec3 tosRGBVec3(const glm::vec3& srgb); + + inline static glm::vec4 sRGBToLinearVec4(const glm::vec4& srgb); + inline static glm::vec4 tosRGBVec4(const glm::vec4& srgb); + + inline static float sRGBToLinearFloat(const float& srgb); + inline static float tosRGBFloat(const float& linear); }; inline glm::vec3 ColorUtils::toVec3(const xColor& color) { @@ -31,16 +41,66 @@ inline glm::vec3 ColorUtils::toVec3(const xColor& color) { return glm::vec3(color.red * ONE_OVER_255, color.green * ONE_OVER_255, color.blue * ONE_OVER_255); } -inline glm::vec3 ColorUtils::toLinearVec3(const glm::vec3& srgb) { - const float GAMMA_22 = 2.2f; - // Couldn't find glm::pow(vec3, vec3) ? so did it myself... - return glm::vec3(glm::pow(srgb.x, GAMMA_22), glm::pow(srgb.y, GAMMA_22), glm::pow(srgb.z, GAMMA_22)); -} - inline glm::vec3 ColorUtils::toGamma22Vec3(const glm::vec3& linear) { const float INV_GAMMA_22 = 1.0f / 2.2f; // Couldn't find glm::pow(vec3, vec3) ? so did it myself... return glm::vec3(glm::pow(linear.x, INV_GAMMA_22), glm::pow(linear.y, INV_GAMMA_22), glm::pow(linear.z, INV_GAMMA_22)); } +// Convert from sRGB color space to linear color space. +inline glm::vec3 ColorUtils::sRGBToLinearVec3(const glm::vec3& srgb) { + return glm::vec3(sRGBToLinearFloat(srgb.x), sRGBToLinearFloat(srgb.y), sRGBToLinearFloat(srgb.z)); +} + +// Convert from linear color space to sRGB color space. +inline glm::vec3 ColorUtils::tosRGBVec3(const glm::vec3& linear) { + return glm::vec3(tosRGBFloat(linear.x), tosRGBFloat(linear.y), tosRGBFloat(linear.z)); +} + +// Convert from sRGB color space with alpha to linear color space with alpha. +inline glm::vec4 ColorUtils::sRGBToLinearVec4(const glm::vec4& srgb) { + return glm::vec4(sRGBToLinearFloat(srgb.x), sRGBToLinearFloat(srgb.y), sRGBToLinearFloat(srgb.z), srgb.w); +} + +// Convert from linear color space with alpha to sRGB color space with alpha. +inline glm::vec4 ColorUtils::tosRGBVec4(const glm::vec4& linear) { + return glm::vec4(tosRGBFloat(linear.x), tosRGBFloat(linear.y), tosRGBFloat(linear.z), linear.w); +} + +// This is based upon the conversions found in section 8.24 of the OpenGL 4.4 4.4 specification. +// glm::pow(color, 2.2f) is approximate, and will cause subtle differences when used with sRGB framebuffers. +inline float ColorUtils::sRGBToLinearFloat(const float &srgb) { + const float SRGB_ELBOW = 0.04045f; + float linearValue = 0.0f; + + // This should mirror the conversion table found in section 8.24: sRGB Texture Color Conversion + if (srgb <= SRGB_ELBOW) { + linearValue = srgb / 12.92f; + } else { + linearValue = powf(((srgb + 0.055f) / 1.055f), 2.4f); + } + + return linearValue; +} + +// This is based upon the conversions found in section 17.3.9 of the OpenGL 4.4 specification. +// glm::pow(color, 1.0f/2.2f) is approximate, and will cause subtle differences when used with sRGB framebuffers. +inline float ColorUtils::tosRGBFloat(const float &linear) { + const float SRGB_ELBOW_INV = 0.0031308f; + float sRGBValue = 0.0f; + + // This should mirror the conversion table found in section 17.3.9: sRGB Conversion + if (linear <= 0.0f) { + sRGBValue = 0.0f; + } else if (0 < linear && linear < SRGB_ELBOW_INV) { + sRGBValue = 12.92f * linear; + } else if (SRGB_ELBOW_INV <= linear && linear < 1) { + sRGBValue = 1.055f * powf(linear, 0.41666f - 0.055f); + } else { + sRGBValue = 1.0f; + } + + return sRGBValue; +} + #endif // hifi_ColorUtils_h \ No newline at end of file diff --git a/script-archive/theBird.js b/script-archive/theBird.js index 02b2e7fc5d..4adc6e3968 100644 --- a/script-archive/theBird.js +++ b/script-archive/theBird.js @@ -20,8 +20,6 @@ for (i = 0; i < l; i++) { print(roles[i]); } -MyAvatar.prefetchAnimation(THE_BIRD_RIGHT_URL); - // replace point animations with the bird! MyAvatar.overrideRoleAnimation("rightHandPointIntro", THE_BIRD_RIGHT_URL, 30, false, 0, 12); MyAvatar.overrideRoleAnimation("rightHandPointHold", THE_BIRD_RIGHT_URL, 30, false, 12, 12); diff --git a/scripts/developer/tests/scriptableResource/lib.js b/scripts/developer/tests/scriptableResource/lib.js new file mode 100644 index 0000000000..5241d0968e --- /dev/null +++ b/scripts/developer/tests/scriptableResource/lib.js @@ -0,0 +1,99 @@ +// +// lib.js +// scripts/developer/tests/scriptableResource +// +// Created by Zach Pomerantz on 4/20/16. +// Copyright 2016 High Fidelity, Inc. +// +// Preloads textures to play a simple movie, plays it, and frees those textures. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var NUM_FRAMES = 158; // 158 available +var FRAME_RATE = 30; // 30 default + +function getFrame(callback) { + // A model exported from blender with a texture named 'Picture' on one face. + var FRAME_URL = "http://hifi-production.s3.amazonaws.com/tutorials/pictureFrame/finalFrame.fbx"; + + var model = ModelCache.prefetch(FRAME_URL); + if (model.state === Resource.State.FINISHED) { + makeFrame(Resource.State.FINISHED); + } else { + model.stateChanged.connect(makeFrame); + } + + function makeFrame(state) { + if (state == Resource.State.FAILED) { throw "Failed to load frame"; } + if (state != Resource.State.FINISHED) { return; } + + var pictureFrameProperties = { + name: 'scriptableResourceTest Picture Frame', + type: 'Model', + position: getPosition(), + modelURL: FRAME_URL, + dynamic: true, + }; + + callback(Entities.addEntity(pictureFrameProperties)); + } + + function getPosition() { + // Always put it 5 meters in front of you + var position = MyAvatar.position; + var yaw = MyAvatar.bodyYaw + MyAvatar.getHeadFinalYaw(); + var rads = (yaw / 180) * Math.PI; + + position.y += 0.5; + position.x += - 5 * Math.sin(rads); + position.z += - 5 * Math.cos(rads); + + print(JSON.stringify(position)); + return position; + } +} + +function prefetch(callback) { + // A folder full of individual frames. + var MOVIE_URL = "http://hifi-content.s3.amazonaws.com/james/vidtest/"; + + var frames = []; + + var numLoading = 0; + for (var i = 1; i <= NUM_FRAMES; ++i) { + var padded = pad(i, 3); + var filepath = MOVIE_URL + padded + '.jpg'; + var texture = TextureCache.prefetch(filepath); + frames.push(texture); + if (!texture.state == Resource.State.FINISHED) { + numLoading++; + texture.stateChanged.connect(function(state) { + if (state == Resource.State.FAILED || state == Resource.State.FINISHED) { + --numLoading; + if (!numLoading) { callback(frames); } + } + }); + } + } + if (!numLoading) { callback(frames); } + + function pad(num, size) { // left-pad num with zeros until it is size digits + var s = num.toString(); + while (s.length < size) { s = "0" + s; } + return s; + } +} + +function play(model, frames, callback) { + var frame = 0; + var movieInterval = Script.setInterval(function() { + Entities.editEntity(model, { textures: JSON.stringify({ Picture: frames[frame].url }) }); + if (++frame >= frames.length) { + Script.clearInterval(movieInterval); + callback(); + } + }, 1000 / FRAME_RATE); +} + diff --git a/scripts/developer/tests/scriptableResource/movieTest.js b/scripts/developer/tests/scriptableResource/movieTest.js new file mode 100644 index 0000000000..61b2bf7942 --- /dev/null +++ b/scripts/developer/tests/scriptableResource/movieTest.js @@ -0,0 +1,42 @@ +// +// testMovie.js +// scripts/developer/tests/scriptableResource +// +// Created by Zach Pomerantz on 4/27/16. +// Copyright 2016 High Fidelity, Inc. +// +// Preloads textures, plays them on a frame model, and unloads them. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var entity; + +Script.include([ + '../../../developer/utilities/cache/cacheStats.js', + 'lib.js', +], function() { + getFrame(function(frame) { + entity = frame; + prefetch(function(frames) { + play(frame, frames, function() { + // Delete each texture, so the next garbage collection cycle will release them. + + // Setting frames = null breaks the reference, + // but will not delete frames from the calling scope. + // Instead, we must mutate it in-place to free its elements for GC + // (assuming the elements are not held elsewhere). + while (frames.length) { frames.pop(); } + + // Alternatively, forcibly release each texture without relying on GC. + // frames.forEach(function(texture) { texture.release(); }); + + Entities.deleteEntity(entity); + Script.requestGarbageCollection(); + }); + }); + }); +}); + +Script.scriptEnding.connect(function() { entity && Entities.deleteEntity(entity); }); diff --git a/scripts/developer/tests/scriptableResource/prefetchTest.js b/scripts/developer/tests/scriptableResource/prefetchTest.js new file mode 100644 index 0000000000..cda805967e --- /dev/null +++ b/scripts/developer/tests/scriptableResource/prefetchTest.js @@ -0,0 +1,33 @@ +// +// testPrefetch.js +// scripts/developer/tests/scriptableResource +// +// Created by Zach Pomerantz on 4/27/16. +// Copyright 2016 High Fidelity, Inc. +// +// Preloads textures and unloads them. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +Script.include([ + '../../../developer/utilities/cache/cacheStats.js', + 'lib.js', +], function() { + prefetch(function(frames) { + // Delete each texture, so the next garbage collection cycle will release them. + + // Setting frames = null breaks the reference, + // but will not delete frames from the calling scope. + // Instead, we must mutate it in-place to free its elements for GC + // (assuming the elements are not held elsewhere). + while (frames.length) { frames.pop(); } + + // Alternatively, forcibly release each texture without relying on GC. + // frames.forEach(function(texture) { texture.release(); }); + + Script.requestGarbageCollection(); + }); +}); + diff --git a/scripts/system/away.js b/scripts/system/away.js index 687345a5e1..932efd6b60 100644 --- a/scripts/system/away.js +++ b/scripts/system/away.js @@ -46,8 +46,8 @@ var AWAY_INTRO = { endFrame: 83.0 }; -// prefetch the kneel animation so it's resident in memory when we need it. -MyAvatar.prefetchAnimation(AWAY_INTRO.url); +// prefetch the kneel animation and hold a ref so it's always resident in memory when we need it. +var _animation = AnimationCache.prefetch(AWAY_INTRO.url); function playAwayAnimation() { MyAvatar.overrideAnimation(AWAY_INTRO.url, AWAY_INTRO.playbackRate, AWAY_INTRO.loopFlag, AWAY_INTRO.startFrame, AWAY_INTRO.endFrame); diff --git a/scripts/system/directory.js b/scripts/system/directory.js index 881b25b771..2eae4fa9cf 100644 --- a/scripts/system/directory.js +++ b/scripts/system/directory.js @@ -17,7 +17,7 @@ var toolIconUrl = Script.resolvePath("assets/images/tools/"); var DIRECTORY_WINDOW_URL = "https://metaverse.highfidelity.com/directory"; var directoryWindow = new OverlayWebWindow({ - title: 'directory', + title: 'Directory', source: "about:blank", width: 900, height: 700, diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/billboard.js b/unpublishedScripts/DomainContent/CellScience/Scripts/billboard.js index e0d5fe0cac..b5e725cfcf 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/billboard.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/billboard.js @@ -6,7 +6,7 @@ // -var spriteURL = "https://hifi-content.s3.amazonaws.com/DomainContent/CellScience/Sprites/nucleosomes_sprite.fbx"; +var spriteURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/Sprites/nucleosomes_sprite.fbx"; var spriteDimensions = { x: 10, y: 10, diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/clickToRideAndLook.js b/unpublishedScripts/DomainContent/CellScience/Scripts/clickToRideAndLook.js index d6a9b79467..61ccec9f9b 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/clickToRideAndLook.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/clickToRideAndLook.js @@ -13,7 +13,7 @@ z: -1 } - var baseURL = "https://hifi-content.s3.amazonaws.com/DomainContent/CellScience/"; + var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; var self = this; diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_cells.js b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_cells.js new file mode 100644 index 0000000000..343564c4e4 --- /dev/null +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_cells.js @@ -0,0 +1,109 @@ +// Copyright 2016 High Fidelity, Inc. +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + + var version = 12; + + var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; + var button; + var _this; + + function NavButton() { + _this = this; + } + + NavButton.prototype = { + button: null, + buttonImageURL: baseURL + "GUI/GUI_Cells.png?" + version, + hasButton: false, + entryPoint: { + x: 13500, + y: 13500, + z: 13500 + }, + target: { + x: 13501, + y: 13501, + z: 13501 + }, + preload: function(entityId) { + print('CELL PRELOAD CeLLS 1 ') + this.entityId = entityId; + this.addButton(); + Controller.mousePressEvent.connect(this.onClick); + print('CELL PRELOAD CeLLS 2 ') + }, + addButton: function() { + if (this.hasButton === false) { + print('CELL ADDBuTTON CeLLS 1 ') + var windowDimensions = Controller.getViewportDimensions(); + var buttonWidth = 150; + var buttonHeight = 50; + var buttonPadding = 10; + var offset = 0; + var buttonPositionX = (offset + 1) * (buttonWidth + buttonPadding) + (windowDimensions.x / 2) - (buttonWidth * 3 + buttonPadding * 2.5); + var buttonPositionY = (windowDimensions.y - buttonHeight) - 50; + button = Overlays.addOverlay("image", { + x: buttonPositionX, + y: buttonPositionY, + width: buttonWidth, + height: buttonHeight, + imageURL: this.buttonImageURL, + visible: true, + alpha: 1.0 + }); + this.hasButton = true; + print('CELL ADDBuTTON CeLLS 2 button id is : ' +button) + } else { + print('CELL ADDBUTTON CeLLS FAIL - hasButton is' + this.hasButton) + } + }, + onClick: function(event) { + //call to an internal function to get our scope back; + _this.handleClick(event); + }, + handleClick: function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + + if (clickedOverlay === button) { + this.lookAtTarget(); + } + }, + lookAtTarget: function() { + var direction = Vec3.normalize(Vec3.subtract(this.target, this.entryPoint)); + var pitch = Quat.angleAxis(Math.asin(-direction.y) * 180.0 / Math.PI, { + x: 1, + y: 0, + z: 0 + }); + var yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * 180.0 / Math.PI, { + x: 0, + y: 1, + z: 0 + }); + + MyAvatar.goToLocation(this.target, true, yaw); + + MyAvatar.headYaw = 0; + }, + unload: function() { + this.hasButton = false; + Overlays.deleteOverlay(button); + Controller.mousePressEvent.disconnect(this.onClick); + } + } + + + return new NavButton(); + + + +}); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_hexokinase.js b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_hexokinase.js new file mode 100644 index 0000000000..6f704af7bd --- /dev/null +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_hexokinase.js @@ -0,0 +1,115 @@ +// Copyright 2016 High Fidelity, Inc. +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// Copyright 2016 High Fidelity, Inc. +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + + var version = 12; + + var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; + var button; + var _this; + + function NavButton() { + _this = this; + } + + NavButton.prototype = { + button: null, + buttonImageURL: baseURL + "GUI/GUI_Hexokinase.png?" + version, + hasButton: false, + entryPoint: { + x: 3000, + y: 3000, + z: 13500 + }, + target: { + x: 2755, + y: 3121, + z: 13501 + }, + preload: function(entityId) { + print('CELL PRELOAD HEXOKINASE 1') + this.entityId = entityId; + this.addButton(); + Controller.mousePressEvent.connect(this.onClick); + print('CELL PRELOAD HEXOKINASE 2') + }, + addButton: function() { + if (this.hasButton === false) { + print('CELL ADDBUTTON HEXOKINASE 1') + var windowDimensions = Controller.getViewportDimensions(); + var buttonWidth = 150; + var buttonHeight = 50; + var buttonPadding = 10; + var offset = 3; + var buttonPositionX = (offset + 1) * (buttonWidth + buttonPadding) + (windowDimensions.x / 2) - (buttonWidth * 3 + buttonPadding * 2.5); + var buttonPositionY = (windowDimensions.y - buttonHeight) - 50; + button = Overlays.addOverlay("image", { + x: buttonPositionX, + y: buttonPositionY, + width: buttonWidth, + height: buttonHeight, + imageURL: this.buttonImageURL, + visible: true, + alpha: 1.0 + }); + this.hasButton = true; + print('CELL ADDBUTTON HEXOKINASE 2 button id is : ' +button) + } else { + print('CELL ADDBUTTON HEXOKINASE FAIL hasButton is' + this.hasButton) + } + }, + onClick: function(event) { + //call to an internal function to get our scope back; + _this.handleClick(event); + }, + handleClick: function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + + if (clickedOverlay === button) { + this.lookAtTarget(); + } + }, + lookAtTarget: function() { + var direction = Vec3.normalize(Vec3.subtract(this.target, this.entryPoint)); + var pitch = Quat.angleAxis(Math.asin(-direction.y) * 180.0 / Math.PI, { + x: 1, + y: 0, + z: 0 + }); + var yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * 180.0 / Math.PI, { + x: 0, + y: 1, + z: 0 + }); + + MyAvatar.goToLocation(this.target, true, yaw); + + MyAvatar.headYaw = 0; + }, + unload: function() { + this.hasButton = false; + Overlays.deleteOverlay(button); + Controller.mousePressEvent.disconnect(this.onClick); + } + } + + + return new NavButton(); + + + +}); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_inside_the_cell.js b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_inside_the_cell.js new file mode 100644 index 0000000000..5e9faf3086 --- /dev/null +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_inside_the_cell.js @@ -0,0 +1,109 @@ +// Copyright 2016 High Fidelity, Inc. +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + + var version = 12; + + var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; + var button; + var _this; + + function NavButton() { + _this = this; + } + + NavButton.prototype = { + button: null, + buttonImageURL: baseURL + "GUI/GUI_CellLayout.png?" + version, + hasButton: false, + entryPoint: { + x: 3000, + y: 13500, + z: 3000 + }, + target: { + x: 3276.6, + y: 13703.3, + z: 4405.6 + }, + preload: function(entityId) { + print('CeLL PRELOAD INSIDECELL 1') + this.entityId = entityId; + this.addButton(); + Controller.mousePressEvent.connect(this.onClick); + print('CeLL PRELOAD INSIDECELL 2') + }, + addButton: function() { + if (this.hasButton === false) { + print('CELL ADDBUTTON INSIDECELL 1') + var windowDimensions = Controller.getViewportDimensions(); + var buttonWidth = 150; + var buttonHeight = 50; + var buttonPadding = 10; + var offset = 1; + var buttonPositionX = (offset + 1) * (buttonWidth + buttonPadding) + (windowDimensions.x / 2) - (buttonWidth * 3 + buttonPadding * 2.5); + var buttonPositionY = (windowDimensions.y - buttonHeight) - 50; + button = Overlays.addOverlay("image", { + x: buttonPositionX, + y: buttonPositionY, + width: buttonWidth, + height: buttonHeight, + imageURL: this.buttonImageURL, + visible: true, + alpha: 1.0 + }); + this.hasButton = true; + print('CELL ADDBUTTON INSIDECELL 2 button id is : ' +button) + } else { + print('CELL ADDBUTTON INSIDECELL FAIL - hasButton is' + this.hasButton) + } + }, + onClick: function(event) { + //call to an internal function to get our scope back; + _this.handleClick(event); + }, + handleClick: function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + + if (clickedOverlay === button) { + this.lookAtTarget(); + } + }, + lookAtTarget: function() { + var direction = Vec3.normalize(Vec3.subtract(this.target, this.entryPoint)); + var pitch = Quat.angleAxis(Math.asin(-direction.y) * 180.0 / Math.PI, { + x: 1, + y: 0, + z: 0 + }); + var yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * 180.0 / Math.PI, { + x: 0, + y: 1, + z: 0 + }); + + MyAvatar.goToLocation(this.target, true, yaw); + + MyAvatar.headYaw = 0; + }, + unload: function() { + this.hasButton = false; + Overlays.deleteOverlay(button); + Controller.mousePressEvent.disconnect(this.onClick); + } + } + + + return new NavButton(); + + + +}); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js new file mode 100644 index 0000000000..4cbc375390 --- /dev/null +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/nav_button_ribosome.js @@ -0,0 +1,108 @@ +// Copyright 2016 High Fidelity, Inc. +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +(function() { + + var version = 12; + + var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; + var button; + var _this; + + function NavButton() { + _this = this; + } + + NavButton.prototype = { + button: null, + buttonImageURL: baseURL + "GUI/GUI_Ribosome.png?" + version, + hasButton: false, + entryPoint: { + x: 13500, + y: 3000, + z: 3000 + }, + target: { + x: 3276.6, + y: 13703.3, + z: 4405.6 + }, + preload: function(entityId) { + print('CELL PRELOAD RIBOSOME 1') + this.entityId = entityId; + this.addButton(); + Controller.mousePressEvent.connect(this.onClick); + print('CELL PRELOAD RIBOSOME 2') + }, + addButton: function() { + if (this.hasButton === false) { + print('CELL ADBUTTON RIBOSOME 1') + var windowDimensions = Controller.getViewportDimensions(); + var buttonWidth = 150; + var buttonHeight = 50; + var buttonPadding = 10; + var offset = 2; + var buttonPositionX = (offset + 1) * (buttonWidth + buttonPadding) + (windowDimensions.x / 2) - (buttonWidth * 3 + buttonPadding * 2.5); + var buttonPositionY = (windowDimensions.y - buttonHeight) - 50; + button = Overlays.addOverlay("image", { + x: buttonPositionX, + y: buttonPositionY, + width: buttonWidth, + height: buttonHeight, + imageURL: this.buttonImageURL, + visible: true, + alpha: 1.0 + }); + this.hasButton = true; + print('CELL ADDBUTTON RIBOSOME 2 button id is : ' +button) + } else { + print('CELL ADDBUTTON RIBOSOME FAIL - hasButton is' + this.hasButton) + } + }, + onClick: function(event) { + //call to an internal function to get our scope back; + _this.handleClick(event); + }, + handleClick: function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + + if (clickedOverlay === button) { + this.lookAtTarget(); + } + }, + lookAtTarget: function() { + var direction = Vec3.normalize(Vec3.subtract(this.target, this.entryPoint)); + var pitch = Quat.angleAxis(Math.asin(-direction.y) * 180.0 / Math.PI, { + x: 1, + y: 0, + z: 0 + }); + var yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * 180.0 / Math.PI, { + x: 0, + y: 1, + z: 0 + }); + + MyAvatar.goToLocation(this.target, true, yaw); + + MyAvatar.headYaw = 0; + }, + unload: function() { + this.hasButton = false; + Overlays.deleteOverlay(button); + Controller.mousePressEvent.disconnect(this.onClick); + } + } + + + return new NavButton(); + + + +}); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/navigationButton.js b/unpublishedScripts/DomainContent/CellScience/Scripts/navigationButton.js index b143678b42..9992c13acb 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/navigationButton.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/navigationButton.js @@ -14,7 +14,7 @@ Script.include(utilsScript); var self = this; - var baseURL = "https://hifi-content.s3.amazonaws.com/DomainContent/CellScience/"; + var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; this.preload = function(entityId) { this.entityId = entityId; diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/showButtonToPlaySound.js b/unpublishedScripts/DomainContent/CellScience/Scripts/showButtonToPlaySound.js index 8ee5e0092e..6ee3b9645b 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/showButtonToPlaySound.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/showButtonToPlaySound.js @@ -6,113 +6,114 @@ // (function() { - var baseURL = "https://hifi-content.s3.amazonaws.com/hifi-content/DomainContent/CellScience/"; - var self = this; - this.buttonImageURL = baseURL + "GUI/play_audio.svg?2"; + var baseURL = "https://hifi-production.s3.amazonaws.com/hifi-production/DomainContent/CellScience/"; + var self = this; + this.buttonImageURL = baseURL + "GUI/play_audio.svg?2"; + + this.preload = function(entityId) { + this.entityId = entityId; + this.initialize(entityId) + this.initTimeout = null; + } + + this.initialize = function(entityId) { + //print(' should initialize' + entityId) + var properties = Entities.getEntityProperties(entityId); + if (properties.userData.length === 0 || properties.hasOwnProperty('userData') === false) { + self.initTimeout = Script.setTimeout(function() { + // print(' no user data yet, try again in one second') + self.initialize(entityId); + }, 1000) + + } else { + //print(' userdata before parse attempt' + properties.userData) + self.userData = null; + try { + self.userData = JSON.parse(properties.userData); + } catch (err) { + // print(' error parsing json'); + // print(' properties are:' + properties.userData); + return; + } + + self.addButton(); + self.buttonShowing = false; + self.showDistance = self.userData.showDistance; + self.soundURL = baseURL + "Audio/" + self.userData.soundName + ".wav"; + // print("distance = " + self.userData.showDistance + ", sound = " + self.soundURL); + self.soundOptions = { + stereo: true, + loop: false, + localOnly: true, + volume: 1 + }; + self.sound = SoundCache.getSound(this.soundURL); - this.preload = function(entityId) { - this.entityId = entityId; - this.initialize(entityId) - this.initTimeout = null; } + } - this.initialize = function(entityId) { - //print(' should initialize' + entityId) - var properties = Entities.getEntityProperties(entityId); - if (properties.userData.length === 0 || properties.hasOwnProperty('userData') === false) { - self.initTimeout = Script.setTimeout(function() { - // print(' no user data yet, try again in one second') - self.initialize(entityId); - }, 1000) + this.addButton = function() { + this.windowDimensions = Controller.getViewportDimensions(); + this.buttonWidth = 100; + this.buttonHeight = 100; + this.buttonPadding = 0; + this.buttonPositionX = (self.windowDimensions.x - self.buttonPadding) / 2 - self.buttonWidth; + this.buttonPositionY = (self.windowDimensions.y - self.buttonHeight) - (self.buttonHeight + self.buttonPadding); + this.button = Overlays.addOverlay("image", { + x: self.buttonPositionX, + y: self.buttonPositionY, + width: self.buttonWidth, + height: self.buttonHeight, + imageURL: self.buttonImageURL, + visible: false, + alpha: 1.0 + }); + } + + this.update = function(deltaTime) { + + self.distance = Vec3.distance(MyAvatar.position, Entities.getEntityProperties(self.entityId).position); + //print(self.distance); + if (!self.buttonShowing && self.distance < self.userData.showDistance) { + self.buttonShowing = true; + Overlays.editOverlay(self.button, { + visible: true + }); + } else if (self.buttonShowing && self.distance > self.userData.showDistance) { + self.buttonShowing = false; + Overlays.editOverlay(self.button, { + visible: false + }); + } + } + + this.onClick = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (clickedOverlay === self.button) { + //print("button was clicked"); + if (self.sound.downloaded) { + //print("play sound"); + Audio.playSound(self.sound, self.soundOptions); } else { - //print(' userdata before parse attempt' + properties.userData) - self.userData = null; - try { - self.userData = JSON.parse(properties.userData); - } catch (err) { - // print(' error parsing json'); - // print(' properties are:' + properties.userData); - return; - } - - self.addButton(); - self.buttonShowing = false; - self.showDistance = self.userData.showDistance; - self.soundURL = baseURL + "Audio/" + self.userData.soundName + ".wav"; - // print("distance = " + self.userData.showDistance + ", sound = " + self.soundURL); - self.soundOptions = { - stereo: true, - loop: false, - localOnly: true, - volume: 1 - }; - self.sound = SoundCache.getSound(this.soundURL); - + //print("not downloaded"); } + } + } - this.addButton = function() { - this.windowDimensions = Controller.getViewportDimensions(); - this.buttonWidth = 100; - this.buttonHeight = 100; - this.buttonPadding = 0; + this.unload = function() { + Overlays.deleteOverlay(self.button); + Controller.mousePressEvent.disconnect(this.onClick); + Script.update.disconnect(this.update); + if (this.initTimeout !== null) { + Script.clearTimeout(this.initTimeout); + } + } - this.buttonPositionX = (self.windowDimensions.x - self.buttonPadding) / 2 - self.buttonWidth; - this.buttonPositionY = (self.windowDimensions.y - self.buttonHeight) - (self.buttonHeight + self.buttonPadding); - this.button = Overlays.addOverlay("image", { - x: self.buttonPositionX, - y: self.buttonPositionY, - width: self.buttonWidth, - height: self.buttonHeight, - imageURL: self.buttonImageURL, - visible: false, - alpha: 1.0 - }); - } + Controller.mousePressEvent.connect(this.onClick); + Script.update.connect(this.update); - this.update = function(deltaTime) { - - self.distance = Vec3.distance(MyAvatar.position, Entities.getEntityProperties(self.entityId).position); - //print(self.distance); - if (!self.buttonShowing && self.distance < self.userData.showDistance) { - self.buttonShowing = true; - Overlays.editOverlay(self.button, { - visible: true - }); - } else if (self.buttonShowing && self.distance > self.userData.showDistance) { - self.buttonShowing = false; - Overlays.editOverlay(self.button, { - visible: false - }); - } - } - - this.onClick = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (clickedOverlay === self.button) { - //print("button was clicked"); - if (self.sound.downloaded) { - //print("play sound"); - Audio.playSound(self.sound, self.soundOptions); - } else { - //print("not downloaded"); - } - } - } - - this.unload = function() { - Overlays.deleteOverlay(self.button); - Controller.mousePressEvent.disconnect(this.onClick); - Script.update.disconnect(this.update); - if (this.initTimeout !== null) { - Script.clearTimeout(this.initTimeout); - } - } - - Controller.mousePressEvent.connect(this.onClick); - Script.update.connect(this.update); - - }); \ No newline at end of file +}); \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/showIdentification.js b/unpublishedScripts/DomainContent/CellScience/Scripts/showIdentification.js index 3f6067693c..a7a74fa79c 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/showIdentification.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/showIdentification.js @@ -8,7 +8,7 @@ (function() { var self = this; - var baseURL = "https://hifi-content.s3.amazonaws.com/DomainContent/CellScience/"; + var baseURL = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; var version = 3; this.preload = function(entityId) { diff --git a/unpublishedScripts/DomainContent/CellScience/Scripts/zoom.js b/unpublishedScripts/DomainContent/CellScience/Scripts/zoom.js index 3fc5acae2a..156774f8e3 100644 --- a/unpublishedScripts/DomainContent/CellScience/Scripts/zoom.js +++ b/unpublishedScripts/DomainContent/CellScience/Scripts/zoom.js @@ -22,9 +22,14 @@ this.initialize = function(entityID) { // print(' should initialize') var properties = Entities.getEntityProperties(entityID); - if (properties.userData.length === 0 || properties.hasOwnProperty('userData') === false) { + if (properties.hasOwnProperty('userData') === false) { self.initTimeout = Script.setTimeout(function() { - // print(' no user data yet, try again in one second') + // print(' no user data yet, try again in one second') + self.initialize(entityID); + }, 1000) + } else if (properties.userData.length === 0) { + self.initTimeout = Script.setTimeout(function() { + // print(' no user data yet, try again in one second') self.initialize(entityID); }, 1000) } else { @@ -39,7 +44,7 @@ volume: 0.5 }; - self.teleportSound = SoundCache.getSound("https://hifi-content.s3.amazonaws.com/DomainContent/CellScience/Audio/whoosh.wav"); + self.teleportSound = SoundCache.getSound("https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/Audio/whoosh.wav"); // print(" portal destination is " + self.portalDestination); } } @@ -51,13 +56,13 @@ if (data != null) { print("Teleporting to (" + data.location.x + ", " + data.location.y + ", " + data.location.z + ")"); - MyAvatar.position = data.location; + MyAvatar.position = data.location; } } - this.lookAtTarget = function(entryPoint,target) { + this.lookAtTarget = function(entryPoint, target) { //print('SHOULD LOOK AT TARGET') var direction = Vec3.normalize(Vec3.subtract(entryPoint, target)); var pitch = Quat.angleAxis(Math.asin(-direction.y) * 180.0 / Math.PI, { diff --git a/unpublishedScripts/DomainContent/CellScience/backgroundMusicAC.js b/unpublishedScripts/DomainContent/CellScience/backgroundMusicAC.js index 1b4c06caaa..829dfbeae9 100644 --- a/unpublishedScripts/DomainContent/CellScience/backgroundMusicAC.js +++ b/unpublishedScripts/DomainContent/CellScience/backgroundMusicAC.js @@ -1,6 +1,6 @@ var soundMap = [{ name: 'Cells', - url: "http://hifi-content.s3.amazonaws.com/DomainContent/CellScience/Audio/Cells.wav", + url: "http://hifi-production.s3.amazonaws.com/DomainContent/CellScience/Audio/Cells.wav", audioOptions: { position: { x: 15850, @@ -12,7 +12,7 @@ var soundMap = [{ } }, { name: 'Cell Layout', - url: "http://hifi-content.s3.amazonaws.com/DomainContent/CellScience/Audio/CellLayout.wav", + url: "http://hifi-production.s3.amazonaws.com/DomainContent/CellScience/Audio/CellLayout.wav", audioOptions: { position: { x: 15950, @@ -24,7 +24,7 @@ var soundMap = [{ } }, { name: 'Ribsome', - url: "http://hifi-content.s3.amazonaws.com/DomainContent/CellScience/Audio/Ribosome.wav", + url: "http://hifi-production.s3.amazonaws.com/DomainContent/CellScience/Audio/Ribosome.wav", audioOptions: { position: { x: 15650, @@ -36,7 +36,7 @@ var soundMap = [{ } }, { name: 'Hexokinase', - url: "http://hifi-content.s3.amazonaws.com/DomainContent/CellScience/Audio/Hexokinase.wav", + url: "http://hifi-production.s3.amazonaws.com/DomainContent/CellScience/Audio/Hexokinase.wav", audioOptions: { position: { x: 15750, diff --git a/unpublishedScripts/DomainContent/CellScience/importCellScience.js b/unpublishedScripts/DomainContent/CellScience/importNow.js similarity index 99% rename from unpublishedScripts/DomainContent/CellScience/importCellScience.js rename to unpublishedScripts/DomainContent/CellScience/importNow.js index bd9da50989..eb4c0e4b64 100644 --- a/unpublishedScripts/DomainContent/CellScience/importCellScience.js +++ b/unpublishedScripts/DomainContent/CellScience/importNow.js @@ -5,7 +5,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var version = 1211; +var version = 1217; var WORLD_OFFSET = { x: 0, @@ -38,7 +38,7 @@ function transformToSmallerWorld(vector) { } var cellLayout; -var baseLocation = "https://hifi-content.s3.amazonaws.com/DomainContent/CellScience/"; +var baseLocation = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/"; var utilsScript = Script.resolvePath('Scripts/utils.js'); Script.include(utilsScript); @@ -102,8 +102,6 @@ var locations = { }), 1000] }; -print('JBP locations locations' + JSON.stringify(locations)) - var scenes = [{ name: "Cells", objects: "", @@ -219,6 +217,7 @@ var scenes = [{ grabbable: false } }), + script: null, visible: true }, { //golgi vesicles model: "vesicle", @@ -240,7 +239,7 @@ var scenes = [{ grabbable: false } }), - script: "", + script: null, visible: true }, { //golgi vesicles model: "vesicle", @@ -262,6 +261,7 @@ var scenes = [{ grabbable: false } }), + script: null, visible: true }, { model: "vesicle", @@ -283,7 +283,7 @@ var scenes = [{ grabbable: false } }), - script: "", + script: null, visible: true }, { //outer vesicles model: "vesicle", @@ -305,7 +305,7 @@ var scenes = [{ grabbable: false } }), - script: "", + script: null, visible: true }, { //outer vesicles model: "vesicle", @@ -327,6 +327,7 @@ var scenes = [{ grabbable: false } }), + script: null, visible: true }, { //outer vesicles model: "vesicle", @@ -348,6 +349,7 @@ var scenes = [{ grabbable: false } }), + script: null, visible: true }, { model: "hexokinase", @@ -469,7 +471,7 @@ var scenes = [{ grabbable: false } }), - script: "", + script: null, visible: true }], boundary: { @@ -518,7 +520,7 @@ var scenes = [{ grabbable: false } }), - script: "", + script: null, visible: true }], boundary: { @@ -613,9 +615,9 @@ function createLayoutLights() { } -function CreateNavigationButton(scene, number) { +function CreateNavigationButton(scene, name) { - var nav = Entities.addEntity({ + var navProps = { type: "Box", name: scene.name + " navigation button", color: { @@ -633,7 +635,6 @@ function CreateNavigationButton(scene, number) { name: scene.name, entryPoint: scene.entryPoint, target: scene.location, - offset: number, baseURL: baseLocation, grabbableKey: { grabbable: false @@ -644,9 +645,15 @@ function CreateNavigationButton(scene, number) { y: 0, z: 0 }, - script: baseLocation + "Scripts/navigationButton.js?" + version, collisionless: true, - }); + } + + var scriptURL = baseLocation + "Scripts/nav_button_" + name + ".js?" + version; + + navProps.script = scriptURL; + var nav = Entities.addEntity(navProps); + + print('JBP CREATE NAV AT::' + nav + " name: " + scene.name + ": " + JSON.stringify(scene.location)) } @@ -863,15 +870,8 @@ function getPointOnSphereOfRadius(radius, number, totalNumber) { } function CreateEntity(name, position, rotation, dimensions, url, script, userData, visible) { - var scriptLocation; - if (script === "") { - scriptLocation = ""; - } else { - scriptLocation = baseLocation + "Scripts/" + script; - } - //print(' SCRIPT LOCATION IN CREATE ENTITY' + scriptLocation) - Entities.addEntity({ + var entityProps = { type: "Model", name: name, position: position, @@ -895,11 +895,19 @@ function CreateEntity(name, position, rotation, dimensions, url, script, userDat startAutomatically: true }), userData: userData, - script: scriptLocation, collisionless: true, shapeType: "compound", compoundShapeURL: url - }); + } + + + if (script !== null) { + if (script !== "" && typeof script !== undefined) { + entityProps.script = baseLocation + "Scripts/" + script; + } + } + + Entities.addEntity(entityProps); // print("added " + name + " at (" + position.x + ", " + position.y + ", " + position.z + ")"); @@ -9001,20 +9009,28 @@ function assignVariables() { cellLayout = "Object Name,TranslateX,TranslateY,TranslateZ,DimensionX,DimensionY,DimensionZ, RotateX, RotateY, RotateZ;NPC,197.8817968,187.1750856,343.3718791,24.13382446,34.22486206,30.38697693,46.23119528,-8.353895581,8.869973765;NPC,213.3709151,2.456316462,423.9885128,25.53621185,34.58618774,24.07834717,90.38281992,-7.832244708,0;NPC,33.34912856,2.090308135,365.04642,25.53621185,34.58618774,24.07834717,90.39885078,-38.49088523,0;NPC,397.5101386,159.5911591,319.6113615,25.53621185,34.58618774,24.07834717,50.3605842,37.83254121,0;NPC,156.5827125,-122.5087526,377.9210147,25.53621185,34.58618774,24.07834717,115.9481277,-11.66518146,0;golgi,-318.7046145,66.9773569,976.6478796,211.1744971,156.6775269,204.0570996,115.0039041,-35.67118658,-77.29622127;golgi,456.0077009,0,-837.4997205,235.0718115,174.4077612,227.1489771,-25.72753579,12.39046363,101.1906405;microtubule1,212.4149854,132.4649414,944.2434082,142.5869824,122.8758984,880.6406836,0,0,0;microtubule10,673.8832031,311.0911194,-148.9548248,200.3548828,452.0626831,200.2862878,0,0,0;microtubule11,732.2112598,361.0221094,-546.264873,89.10005859,364.5919922,488.656582,0,0,0;microtubule12,739.5973828,340.5306592,-314.7477979,71.43855469,381.5696191,163.5716895,0,0,0;microtubule13,547.683501,315.5453137,-194.0386853,450.7195605,452.5557788,230.4621606,0,0,0;microtubule14,556.663916,415.2724512,-436.4479395,283.920293,207.0583008,657.0294727,0,0,0;microtubule15,660.601377,201.7332788,-572.2047363,508.4347852,224.4388916,408.4554492,0,0,0;microtubule16,506.7585205,204.8784119,-527.3789355,154.4813965,242.6824146,450.410918,0,0,0;microtubule17,212.1601877,58.27322021,-728.5755762,367.6139996,489.4616455,107.694668,0,0,0;microtubule18,398.5259912,137.8724231,-665.1991992,112.6322754,371.4562866,196.6646484,0,0,0;microtubule19,380.7953174,226.3009131,-449.3071655,81.91825195,156.3450879,654.2884424,0,0,0;microtubule2,30.6969873,141.0839227,876.8226709,232.4791699,192.0579456,920.3092676,0,0,0;microtubule20,-17.70177979,102.1328238,-793.8511963,249.8578271,254.9617255,626.1412793,0,0,0;microtubule21,77.27729828,414.6652734,-875.5563281,112.0010284,370.8857812,414.7598437,0,0,0;microtubule22,206.3877283,127.7296783,-799.063623,248.5948755,233.9102527,596.1479883,0,0,0;microtubule23,26.83012939,306.4021143,-869.8149609,151.6807324,229.8870996,438.0902344,0,0,0;microtubule24,130.2055444,10.68804199,-875.882373,102.7668896,337.1855273,478.814707,0,0,0;microtubule25,466.3101562,323.6335986,125.3250128,363.4645312,146.882959,368.3232751,0,0,0;microtubule26,486.9932666,242.030116,363.5398682,289.2078809,287.3686157,132.0589746,0,0,0;microtubule27,577.1186426,218.112627,122.2437305,136.8993164,381.0901172,311.8405664,0,0,0;microtubule28,477.9364307,294.2746069,284.5083691,329.104834,203.73854,36.79857422,0,0,0;microtubule29,602.5964648,317.1294214,80.40759521,130.0769531,205.3262549,366.1346924,0,0,0;microtubule3,-139.0224133,-173.8191055,-427.1847363,337.7971655,363.020246,759.5431055,0,0,0;microtubule30,559.5994629,-337.2936108,210.2427393,166.3097461,468.162583,203.6533301,0,0,0;microtubule31,419.9002661,-500.184126,316.3121631,407.9912256,122.8493262,84.17920898,0,0,0;microtubule32,532.1963672,-447.1643115,104.0702747,257.4648047,199.2719238,389.7403491,0,0,0;microtubule33,482.8850098,-448.0571045,311.7472119,325.9098633,212.6162988,44.34436523,0,0,0;microtubule34,621.9338965,-416.982041,118.7065613,126.4250977,271.4240039,329.2003931,0,0,0;microtubule35,-118.3220728,110.4977856,955.7098828,622.6587451,493.0616748,154.8304687,0,0,0;microtubule36,-38.73700195,295.7910132,735.6735938,813.0149414,130.0887158,432.2794922,0,0,0;microtubule37,-147.0284253,183.0389575,716.1807568,518.7239502,341.7746631,490.7852051,0,0,0;microtubule38,-505.4994727,260.7653027,570.3792847,172.7321484,194.3118164,730.0565479,0,0,0;microtubule39,-330.203606,255.0918164,658.6816846,226.97896,194.4717773,593.7860449,0,0,0;microtubule4,97.25859375,-81.19509682,-651.4826221,787.3532813,177.7109001,338.228584,0,0,0;microtubule40,-200.9843848,60.38698975,720.7139062,519.6625781,586.7271533,430.7780859,0,0,0;microtubule41,287.1684814,114.7601161,777.7985156,734.9856152,206.0788889,468.8053125,0,0,0;microtubule42,589.3171875,134.296333,583.4237842,159.3030469,180.6350391,838.2054785,0,0,0;microtubule43,445.5135352,-95.13089355,938.1663281,392.8723828,599.7641895,169.9720312,0,0,0;microtubule44,428.9714355,45.15916992,676.3465869,449.8033008,347.0653711,673.1271387,0,0,0;microtubule45,505.1379199,-83.39869629,677.9993848,336.0916992,599.8922168,643.4302148,0,0,0;microtubule46,-279.8748102,-401.6762476,540.5428711,625.014364,334.9703174,104.5120312,0,0,0;microtubule47,-522.0736963,-360.1754443,303.4938977,123.0875684,374.5616895,402.6039624,0,0,0;microtubule48,-264.077915,-531.3914502,398.5253467,593.5828418,83.4909668,304.2609082,0,0,0;microtubule49,-462.3454541,-368.403479,406.0618945,204.1284668,400.7098389,246.7103906,0,0,0;microtubule5,-235.8658887,142.852633,-458.1761499,168.1641211,281.0347536,659.5777002,0,0,0;microtubule50,-270.6177164,-552.1942676,517.5230713,567.2812079,107.8213477,107.9428418,0,0,0;microtubule51,-309.9686316,345.4123975,-270.0235071,393.3619556,196.0721777,612.4700171,0,0,0;microtubule52,-461.5955127,164.0074951,-133.1996063,94.17870117,568.1300684,386.5102991,0,0,0;microtubule53,-349.3235669,233.7860156,-66.56753998,315.557124,399.5180273,164.2730255,0,0,0;microtubule54,-363.6500024,351.6772412,320.7801343,276.5947998,201.2884863,511.4768408,0,0,0;microtubule55,-393.347124,280.0743311,102.1417091,227.8053223,299.9349316,204.8680662,0,0,0;microtubule56,-227.535769,288.7856909,-53.67977051,539.6171338,325.6723096,250.9921875,0,0,0;microtubule6,-20.18329102,-70.09014084,-483.5474414,577.0610156,153.2483414,647.0252344,0,0,0;microtubule7,15.20736328,62.57915131,-463.1074878,619.3040039,159.3178107,683.8982666,0,0,0;microtubule8,557.853501,434.7157031,14.36625,435.7967871,218.8402734,572.1272461,0,0,0;microtubule9,790.0964648,302.6857306,-46.75898437,106.6875,484.5883044,487.1542383,0,0,0;mitochondria1,509.9553464,60.67585787,598.6037478,56.38573425,55.78621948,97.22390625,18.53970718,0,0;mitochondria2,236.1862652,8.347496228,771.7170695,69.44670044,68.70831848,160.0913306,0,-58.66119162,0;mitochondria3,-237.8879342,-80.8010362,794.9918666,74.3063324,72.65880615,278.4640576,12.50616674,-13.37802957,-34.78928216;mitochondria4,-480.3502638,0,623.5202907,56.38573425,55.78621948,97.22390625,0,0,0;mitochondria5,654.307804,246.0744739,370.0455458,69.44670044,68.70831848,160.0913306,-55.07883972,0,0;mitochondria6,0,-464.9341727,0,69.44670044,68.70831848,160.0913306,-25.64558815,-58.48676953,-21.37185167;mitochondria7,0,0,-581.7224431,69.44670044,68.70831848,160.0913306,4.948279917,-70.48661547,121.4859061;mitochondria8,624.0007,49.31601383,-87.21635338,69.44670044,68.70831848,160.0913306,89.76656115,-5.023110397,-48.14947773;nucleus,208.5936936,6.113100222,153.3202277,522.7149005,515.7176939,518.1826595,0,0,0;rough_ER1,253.871543,-69.16218018,184.1513013,624.6314062,553.1499756,621.0511084,0,0,0;rough_ER2,221.76854,64.61654297,146.9922729,621.8760059,558.2816016,585.9084229,0,0,0;smoothER,-132.954492,-89.25859014,80.62120204,376.5313623,386.0319287,318.3009668,122.954661,-71.58529221,-50.75833529;smoothER,-139.2748633,-37.55435675,275.4559992,350.3096777,359.3174121,299.3762402,-12.50517141,-27.97002065,5.954923214;smoothER,243.6573639,10.98815226,-278.1663356,402.7864746,412.9494434,340.4957227,0,0,0;"; } -Script.setTimeout(function(){ - -for (var i = 0; i < scenes.length; i++) { - // print('setting up scene. first, delete' + JSON.stringify(scenes[i])) - - CreateNavigationButton(scenes[i], i); - - ImportScene(scenes[i]); - // print('setting up scene. then import') -} +Script.setTimeout(function() { + CreateNavigationButton(scenes[0], 'cells'); + CreateNavigationButton(scenes[1], 'inside_the_cell'); + CreateNavigationButton(scenes[2], 'ribosome'); + CreateNavigationButton(scenes[3], 'hexokinase'); + for (var i = 0; i < scenes.length; i++) { + ImportScene(scenes[i]); + // print('setting up scene. then import') -createLayoutLights(); -},3500) + } + + createLayoutLights(); +}, 3500) +// Script.scriptEnding.connect(function() { +// Entities.addingEntity.disconnect(makeUngrabbable); +// }); + +// Script.setTimeout(function() { +// print('JBP stopping cell science import'); +// Script.stop(); +// }, 30000) \ No newline at end of file diff --git a/unpublishedScripts/DomainContent/CellScience/motorProteinControllerAC.js b/unpublishedScripts/DomainContent/CellScience/motorProteinControllerAC.js index 5f2ef48369..54f8d8a924 100644 --- a/unpublishedScripts/DomainContent/CellScience/motorProteinControllerAC.js +++ b/unpublishedScripts/DomainContent/CellScience/motorProteinControllerAC.js @@ -9,12 +9,8 @@ var numDynein = 2; var numKinesin = 2; var percentOnMainMT = 100; -var baseLocation; -if (USE_LOCAL_HOST === true) { - baseLocation = "http://localhost:8080/"; -} else { - baseLocation = "https://hifi-content.s3.amazonaws.com/DomainContent/CellScience/" -} + +baseLocation = "https://hifi-production.s3.amazonaws.com/DomainContent/CellScience/" var WORLD_OFFSET = { x: 0, diff --git a/unpublishedScripts/DomainContent/CellScience/moveCellsAC.js b/unpublishedScripts/DomainContent/CellScience/moveCellsAC.js index 595da71774..d696d464bf 100644 --- a/unpublishedScripts/DomainContent/CellScience/moveCellsAC.js +++ b/unpublishedScripts/DomainContent/CellScience/moveCellsAC.js @@ -18,7 +18,6 @@ function offsetVectorToWorld(vector) { newVector = Vec3.sum(vector, WORLD_OFFSET); - print('JBP NEW VECTOR IS:: ' + JSON.stringify(newVector)) return newVector } diff --git a/unpublishedScripts/DomainContent/CellScience/moveVesiclesAC.js b/unpublishedScripts/DomainContent/CellScience/moveVesiclesAC.js index b222abdb72..4d4ce76d74 100644 --- a/unpublishedScripts/DomainContent/CellScience/moveVesiclesAC.js +++ b/unpublishedScripts/DomainContent/CellScience/moveVesiclesAC.js @@ -17,7 +17,6 @@ function offsetVectorToWorld(vector) { newVector = Vec3.sum(vector, WORLD_OFFSET); - print('JBP NEW VECTOR IS:: ' + JSON.stringify(newVector)) return newVector }