From f88433b7bb25c1ad3862d1e302f4507dc32e9e45 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Jan 2017 11:23:17 -0800 Subject: [PATCH 1/9] Add tealight.js entity server script --- .../marketplace/teaLight/teaLight.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 unpublishedScripts/marketplace/teaLight/teaLight.js diff --git a/unpublishedScripts/marketplace/teaLight/teaLight.js b/unpublishedScripts/marketplace/teaLight/teaLight.js new file mode 100644 index 0000000000..85b0a3c310 --- /dev/null +++ b/unpublishedScripts/marketplace/teaLight/teaLight.js @@ -0,0 +1,21 @@ +(function() { + var MINIMUM_LIGHT_INTENSITY = 100.0; + var MAXIMUM_LIGHT_INTENSITY = 125.0; + + // Return a random number between `low` (inclusive) and `high` (exclusive) + function randFloat(low, high) { + return low + Math.random() * (high - low); + } + + var self = this; + this.preload = function(entityID) { + self.intervalID = Script.setInterval(function() { + Entities.editEntity(entityID, { + intensity: randFloat(MINIMUM_LIGHT_INTENSITY, MAXIMUM_LIGHT_INTENSITY) + }); + }, 100); + }; + this.unload = function() { + Script.clearInterval(self.intervalID); + } +}); From c3f9663ab0addb14ed9e3c6d64fe249d7f255b9f Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 31 Jan 2017 01:25:59 +0100 Subject: [PATCH 2/9] - Fix for simulation owned entities moving to 0,0,0 after cache reload - Fix for simulation priority, use SCRIPT_GRAB_SIMULATION_PRIORITY in EntityItem::grabSimulationOwnership() --- libraries/entities/src/EntityItem.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 64bc9fbd5a..52dad5e976 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -688,6 +688,14 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef somethingChanged = true; _simulationOwner.clearCurrentOwner(); } + } else if (newSimOwner.matchesValidID(myNodeID) && !(_dirtyFlags & Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE) + && !(_dirtyFlags & Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB)) { + // entity-server tells us that we have simulation ownership while we never requested this for this EntityItem, + // this could happen when the user reloads the cache and entity tree. + _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + somethingChanged = true; + _simulationOwner.clearCurrentOwner(); + weOwnSimulation = false; } else if (_simulationOwner.set(newSimOwner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; somethingChanged = true; @@ -1278,7 +1286,7 @@ void EntityItem::grabSimulationOwnership() { auto nodeList = DependencyManager::get(); if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { // we already own it - _simulationOwner.promotePriority(SCRIPT_POKE_SIMULATION_PRIORITY); + _simulationOwner.promotePriority(SCRIPT_GRAB_SIMULATION_PRIORITY); } else { // we don't own it yet _simulationOwner.setPendingPriority(SCRIPT_GRAB_SIMULATION_PRIORITY, usecTimestampNow()); From 360899887775ae01049d57ab552f4cc83e6f479a Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 31 Jan 2017 21:01:03 +0100 Subject: [PATCH 3/9] use dedicated bool rather than unreliable dirtyFlags to determine if the entityItem had ever bid for simulation ownership --- libraries/entities/src/EntityItem.cpp | 15 +++++++++++++-- libraries/entities/src/EntityItem.h | 7 ++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d77fac131d..61f082c9b6 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -688,8 +688,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef somethingChanged = true; _simulationOwner.clearCurrentOwner(); } - } else if (newSimOwner.matchesValidID(myNodeID) && !(_dirtyFlags & Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE) - && !(_dirtyFlags & Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB)) { + } else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) { // entity-server tells us that we have simulation ownership while we never requested this for this EntityItem, // this could happen when the user reloads the cache and entity tree. _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; @@ -1279,6 +1278,7 @@ void EntityItem::pokeSimulationOwnership() { // we don't own it yet _simulationOwner.setPendingPriority(SCRIPT_POKE_SIMULATION_PRIORITY, usecTimestampNow()); } + checkForFirstSimulationBid(_simulationOwner); } void EntityItem::grabSimulationOwnership() { @@ -1291,6 +1291,7 @@ void EntityItem::grabSimulationOwnership() { // we don't own it yet _simulationOwner.setPendingPriority(SCRIPT_GRAB_SIMULATION_PRIORITY, usecTimestampNow()); } + checkForFirstSimulationBid(_simulationOwner); } bool EntityItem::setProperties(const EntityItemProperties& properties) { @@ -1861,6 +1862,7 @@ void EntityItem::setSimulationOwner(const QUuid& id, quint8 priority) { qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id << priority; } _simulationOwner.set(id, priority); + checkForFirstSimulationBid(_simulationOwner); } void EntityItem::setSimulationOwner(const SimulationOwner& owner) { @@ -1869,6 +1871,7 @@ void EntityItem::setSimulationOwner(const SimulationOwner& owner) { } _simulationOwner.set(owner); + checkForFirstSimulationBid(_simulationOwner); } void EntityItem::updateSimulationOwner(const SimulationOwner& owner) { @@ -1879,6 +1882,7 @@ void EntityItem::updateSimulationOwner(const SimulationOwner& owner) { if (_simulationOwner.set(owner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; } + checkForFirstSimulationBid(_simulationOwner); } void EntityItem::clearSimulationOwnership() { @@ -1895,6 +1899,7 @@ void EntityItem::clearSimulationOwnership() { void EntityItem::setPendingOwnershipPriority(quint8 priority, const quint64& timestamp) { _simulationOwner.setPendingPriority(priority, timestamp); + checkForFirstSimulationBid(_simulationOwner); } QString EntityItem::actionsToDebugString() { @@ -2152,6 +2157,12 @@ void EntityItem::setActionDataInternal(QByteArray actionData) { checkWaitingToRemove(); } +void EntityItem::checkForFirstSimulationBid(const SimulationOwner& simulationOwner) const { + if (!_hasBidOnSimulation && simulationOwner.matchesValidID(DependencyManager::get()->getSessionUUID())) { + _hasBidOnSimulation = true; + } +} + void EntityItem::serializeActions(bool& success, QByteArray& result) const { if (_objectActions.size() == 0) { success = true; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b203de203b..98a2a1e268 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -478,6 +478,8 @@ protected: const QByteArray getActionDataInternal() const; void setActionDataInternal(QByteArray actionData); + void checkForFirstSimulationBid(const SimulationOwner& simulationOwner) const; + virtual void locationChanged(bool tellPhysics = true) override; virtual void dimensionsChanged() override; @@ -586,6 +588,9 @@ protected: static quint64 _rememberDeletedActionTime; mutable QHash _previouslyDeletedActions; + // per entity keep state if it ever bid on simulation, so that we can ignore false simulation ownership + mutable bool _hasBidOnSimulation = false; + QUuid _sourceUUID; /// the server node UUID we came from bool _clientOnly { false }; @@ -594,7 +599,7 @@ protected: // physics related changes from the network to suppress any duplicates and make // sure redundant applications are idempotent glm::vec3 _lastUpdatedPositionValue; - glm::quat _lastUpdatedRotationValue; + glm::quat _lastUpdatedRotationValue; glm::vec3 _lastUpdatedVelocityValue; glm::vec3 _lastUpdatedAngularVelocityValue; glm::vec3 _lastUpdatedAccelerationValue; From 174a7ad5bdadc72f14875281889b26fb7706ac2b Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 31 Jan 2017 22:54:58 +0100 Subject: [PATCH 4/9] Optimizations and style fixes from code review --- libraries/entities/src/EntityItem.cpp | 16 +++-------- libraries/entities/src/EntityItem.h | 27 +++++++++---------- .../entities/src/EntityScriptingInterface.cpp | 2 ++ libraries/physics/src/EntityMotionState.cpp | 2 ++ 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 61f082c9b6..3c10d0382c 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1278,7 +1278,6 @@ void EntityItem::pokeSimulationOwnership() { // we don't own it yet _simulationOwner.setPendingPriority(SCRIPT_POKE_SIMULATION_PRIORITY, usecTimestampNow()); } - checkForFirstSimulationBid(_simulationOwner); } void EntityItem::grabSimulationOwnership() { @@ -1291,7 +1290,6 @@ void EntityItem::grabSimulationOwnership() { // we don't own it yet _simulationOwner.setPendingPriority(SCRIPT_GRAB_SIMULATION_PRIORITY, usecTimestampNow()); } - checkForFirstSimulationBid(_simulationOwner); } bool EntityItem::setProperties(const EntityItemProperties& properties) { @@ -1862,7 +1860,6 @@ void EntityItem::setSimulationOwner(const QUuid& id, quint8 priority) { qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id << priority; } _simulationOwner.set(id, priority); - checkForFirstSimulationBid(_simulationOwner); } void EntityItem::setSimulationOwner(const SimulationOwner& owner) { @@ -1871,7 +1868,6 @@ void EntityItem::setSimulationOwner(const SimulationOwner& owner) { } _simulationOwner.set(owner); - checkForFirstSimulationBid(_simulationOwner); } void EntityItem::updateSimulationOwner(const SimulationOwner& owner) { @@ -1882,7 +1878,6 @@ void EntityItem::updateSimulationOwner(const SimulationOwner& owner) { if (_simulationOwner.set(owner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; } - checkForFirstSimulationBid(_simulationOwner); } void EntityItem::clearSimulationOwnership() { @@ -1899,7 +1894,10 @@ void EntityItem::clearSimulationOwnership() { void EntityItem::setPendingOwnershipPriority(quint8 priority, const quint64& timestamp) { _simulationOwner.setPendingPriority(priority, timestamp); - checkForFirstSimulationBid(_simulationOwner); +} + +void EntityItem::rememberHasSimulationOwnershipBid() const { + _hasBidOnSimulation = true; } QString EntityItem::actionsToDebugString() { @@ -2157,12 +2155,6 @@ void EntityItem::setActionDataInternal(QByteArray actionData) { checkWaitingToRemove(); } -void EntityItem::checkForFirstSimulationBid(const SimulationOwner& simulationOwner) const { - if (!_hasBidOnSimulation && simulationOwner.matchesValidID(DependencyManager::get()->getSessionUUID())) { - _hasBidOnSimulation = true; - } -} - void EntityItem::serializeActions(bool& success, QByteArray& result) const { if (_objectActions.size() == 0) { success = true; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 98a2a1e268..e69195d53d 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -321,6 +321,7 @@ public: void updateSimulationOwner(const SimulationOwner& owner); void clearSimulationOwnership(); void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp); + void rememberHasSimulationOwnershipBid() const; const QString& getMarketplaceID() const { return _marketplaceID; } void setMarketplaceID(const QString& value) { _marketplaceID = value; } @@ -478,8 +479,6 @@ protected: const QByteArray getActionDataInternal() const; void setActionDataInternal(QByteArray actionData); - void checkForFirstSimulationBid(const SimulationOwner& simulationOwner) const; - virtual void locationChanged(bool tellPhysics = true) override; virtual void dimensionsChanged() override; @@ -499,16 +498,16 @@ protected: mutable AABox _cachedAABox; mutable AACube _maxAACube; mutable AACube _minAACube; - mutable bool _recalcAABox = true; - mutable bool _recalcMinAACube = true; - mutable bool _recalcMaxAACube = true; + mutable bool _recalcAABox { true }; + mutable bool _recalcMinAACube { true }; + mutable bool _recalcMaxAACube { true }; float _localRenderAlpha; - float _density = ENTITY_ITEM_DEFAULT_DENSITY; // kg/m^3 + float _density { ENTITY_ITEM_DEFAULT_DENSITY }; // kg/m^3 // NOTE: _volumeMultiplier is used to allow some mass properties code exist in the EntityItem base class // rather than in all of the derived classes. If we ever collapse these classes to one we could do it a // different way. - float _volumeMultiplier = 1.0f; + float _volumeMultiplier { 1.0f }; glm::vec3 _gravity; glm::vec3 _acceleration; float _damping; @@ -518,7 +517,7 @@ protected: QString _script; /// the value of the script property QString _loadedScript; /// the value of _script when the last preload signal was sent - quint64 _scriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the script loaded property used for forced reload + quint64 _scriptTimestamp { ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP }; /// the script loaded property used for forced reload QString _serverScripts; /// keep track of time when _serverScripts property was last changed @@ -526,7 +525,7 @@ protected: /// the value of _scriptTimestamp when the last preload signal was sent // NOTE: on construction we want this to be different from _scriptTimestamp so we intentionally bump it - quint64 _loadedScriptTimestamp{ ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP + 1 }; + quint64 _loadedScriptTimestamp { ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP + 1 }; QString _collisionSoundURL; SharedSoundPointer _collisionSound; @@ -564,8 +563,8 @@ protected: uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation // these backpointers are only ever set/cleared by friends: - EntityTreeElementPointer _element = nullptr; // set by EntityTreeElement - void* _physicsInfo = nullptr; // set by EntitySimulation + EntityTreeElementPointer _element { nullptr }; // set by EntityTreeElement + void* _physicsInfo { nullptr }; // set by EntitySimulation bool _simulated; // set by EntitySimulation bool addActionInternal(EntitySimulationPointer simulation, EntityActionPointer action); @@ -582,14 +581,14 @@ protected: // are used to keep track of and work around this situation. void checkWaitingToRemove(EntitySimulationPointer simulation = nullptr); mutable QSet _actionsToRemove; - mutable bool _actionDataDirty = false; - mutable bool _actionDataNeedsTransmit = false; + mutable bool _actionDataDirty { false }; + mutable bool _actionDataNeedsTransmit { false }; // _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag static quint64 _rememberDeletedActionTime; mutable QHash _previouslyDeletedActions; // per entity keep state if it ever bid on simulation, so that we can ignore false simulation ownership - mutable bool _hasBidOnSimulation = false; + mutable bool _hasBidOnSimulation { false }; QUuid _sourceUUID; /// the server node UUID we came from diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 6fb5d14329..85c3fc74f6 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -231,6 +231,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties // and make note of it now, so we can act on it right away. propertiesWithSimID.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); entity->setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); + entity->rememberHasSimulationOwnershipBid(); } entity->setLastBroadcast(usecTimestampNow()); @@ -444,6 +445,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& // we make a bid for simulation ownership properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); entity->pokeSimulationOwnership(); + entity->rememberHasSimulationOwnershipBid(); } } if (properties.parentRelatedPropertyChanged() && entity->computePuffedQueryAACube()) { diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index b0bdc34b52..02cee9a03a 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -582,6 +582,8 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ _nextOwnershipBid = now + USECS_BETWEEN_OWNERSHIP_BIDS; // copy _outgoingPriority into pendingPriority... _entity->setPendingOwnershipPriority(_outgoingPriority, now); + // don't forget to remember that we have made a bid + _entity->rememberHasSimulationOwnershipBid(); // ...then reset _outgoingPriority in preparation for the next frame _outgoingPriority = 0; } else if (_outgoingPriority != _entity->getSimulationPriority()) { From 8f362861eb19a8fd636c1c6d52b252615877f77d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 31 Jan 2017 16:53:25 -0800 Subject: [PATCH 5/9] tablet-ui: button icon images now work with http urls. --- interface/resources/qml/hifi/tablet/TabletButton.qml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletButton.qml b/interface/resources/qml/hifi/tablet/TabletButton.qml index 9ad8d1476c..c6c810d25e 100644 --- a/interface/resources/qml/hifi/tablet/TabletButton.qml +++ b/interface/resources/qml/hifi/tablet/TabletButton.qml @@ -75,6 +75,14 @@ Item { source: buttonOutline } + function urlHelper(src) { + if (src.match(/\bhttp/)) { + return src; + } else { + return "../../../" + src; + } + } + Image { id: icon width: 50 @@ -84,7 +92,7 @@ Item { anchors.bottomMargin: 5 anchors.horizontalCenter: parent.horizontalCenter fillMode: Image.Stretch - source: "../../../" + tabletButton.icon + source: tabletButton.urlHelper(tabletButton.icon) } ColorOverlay { @@ -185,7 +193,7 @@ Item { PropertyChanges { target: icon - source: "../../../" + tabletButton.activeIcon + source: tabletButton.urlHelper(tabletButton.activeIcon) } }, State { From cf855391af34d47a44e0ca5e46a7b9da534701c2 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 31 Jan 2017 16:54:15 -0800 Subject: [PATCH 6/9] Added jsdocs for all button properties --- .../script-engine/src/TabletScriptingInterface.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index b0b2d00e0f..0b7829c7fb 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -119,7 +119,7 @@ public: * @param msg {object|string} */ Q_INVOKABLE void emitScriptEvent(QVariant msg); - + Q_INVOKABLE bool onHomeScreen(); QObject* getTabletSurface(); @@ -170,14 +170,14 @@ public: /**jsdoc * Returns the current value of this button's properties * @function TabletButtonProxy#getProperties - * @returns {object} + * @returns {ButtonProperties} */ Q_INVOKABLE QVariantMap getProperties() const; /**jsdoc * Replace the values of some of this button's properties * @function TabletButtonProxy#editProperties - * @param properties {object} set of properties to change + * @param {ButtonProperties} properties - set of properties to change */ Q_INVOKABLE void editProperties(QVariantMap properties); @@ -199,4 +199,13 @@ protected: QVariantMap _properties; }; +/**jsdoc + * @typedef TabletButtonProxy.ButtonProperties + * @property {string} text - button caption + * @property {string} icon - url to button icon. (50 x 50) + * @property {string} activeText - button caption when button is active + * @property {string} activeIcon - url to button icon used when button is active. (50 x 50) + * @property {string} isActive - true when button is active. + */ + #endif // hifi_TabletScriptingInterface_h From c147b9bec0672aa9253c406ab0a2f75005906adc Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 31 Jan 2017 18:00:18 -0800 Subject: [PATCH 7/9] Fix for tablets in third-person HMD mode. --- scripts/system/libraries/WebTablet.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 65551b2140..edb637d9a2 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -198,6 +198,11 @@ WebTablet = function (url, width, dpi, hand, clientOnly) { _this.geometryChanged(geometry); }; Window.geometryChanged.connect(this.myGeometryChanged); + + this.myCameraModeChanged = function(newMode) { + _this.cameraModeChanged(newMode); + }; + Camera.modeUpdated.connect(this.myCameraModeChanged); }; WebTablet.prototype.setHomeButtonTexture = function() { @@ -228,6 +233,7 @@ WebTablet.prototype.destroy = function () { Controller.mouseReleaseEvent.disconnect(this.myMouseReleaseEvent); Window.geometryChanged.disconnect(this.myGeometryChanged); + Camera.modeUpdated.disconnect(this.myCameraModeChanged); }; WebTablet.prototype.geometryChanged = function (geometry) { @@ -370,6 +376,19 @@ WebTablet.prototype.mousePressEvent = function (event) { } }; +WebTablet.prototype.cameraModeChanged = function (newMode) { + // reposition the tablet, after a small delay. + // This allows HMD.position to reflect the new camera mode. + var self = this; + Script.setTimeout(function () { + var NO_HANDS = -1; + var tabletProperties = {}; + // compute position, rotation & parentJointIndex of the tablet + self.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties); + Entities.editEntity(self.tabletEntityID, tabletProperties); + }, 10); +}; + function rayIntersectPlane(planePosition, planeNormal, rayStart, rayDirection) { var rayDirectionDotPlaneNormal = Vec3.dot(rayDirection, planeNormal); if (rayDirectionDotPlaneNormal > 0.00001 || rayDirectionDotPlaneNormal < -0.00001) { From 008a58f9d708e00ce4d8de9de1d9ff70805bb903 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 31 Jan 2017 18:03:48 -0800 Subject: [PATCH 8/9] Only reposition the tablet when camera mode changes, in HMD mode. --- scripts/system/libraries/WebTablet.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index edb637d9a2..52912337a1 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -379,14 +379,16 @@ WebTablet.prototype.mousePressEvent = function (event) { WebTablet.prototype.cameraModeChanged = function (newMode) { // reposition the tablet, after a small delay. // This allows HMD.position to reflect the new camera mode. - var self = this; - Script.setTimeout(function () { - var NO_HANDS = -1; - var tabletProperties = {}; - // compute position, rotation & parentJointIndex of the tablet - self.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties); - Entities.editEntity(self.tabletEntityID, tabletProperties); - }, 10); + if (HMD.active) { + var self = this; + Script.setTimeout(function () { + var NO_HANDS = -1; + var tabletProperties = {}; + // compute position, rotation & parentJointIndex of the tablet + self.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties); + Entities.editEntity(self.tabletEntityID, tabletProperties); + }, 10); + } }; function rayIntersectPlane(planePosition, planeNormal, rayStart, rayDirection) { From 3c04f54e7509b08c36eff7311f16a3f6b636c391 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 31 Jan 2017 18:22:38 -0800 Subject: [PATCH 9/9] more fixes to third person tablet usage. --- scripts/system/libraries/WebTablet.js | 31 +++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 52912337a1..75ca2e514f 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -24,6 +24,7 @@ var CAMERA_MATRIX = -7; var ROT_Y_180 = {x: 0, y: 1, z: 0, w: 0}; var TABLET_TEXTURE_RESOLUTION = { x: 480, y: 706 }; var INCHES_TO_METERS = 1 / 39.3701; +var NO_HANDS = -1; var TABLET_URL = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx"; @@ -35,18 +36,21 @@ var TABLET_MODEL_PATH = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-wi // * position - position in front of the user // * rotation - rotation of entity so it faces the user. function calcSpawnInfo(hand, height) { - var noHands = -1; var finalPosition; - if (HMD.active && hand !== noHands) { + + var headPos = (HMD.active && Camera.mode === "first person") ? HMD.position : Camera.position; + var headRot = (HMD.active && Camera.mode === "first person") ? HMD.orientation : Camera.orientation; + + if (HMD.active && hand !== NO_HANDS) { var handController = getControllerWorldLocation(hand, true); var controllerPosition = handController.position; // compute the angle of the chord with length (height / 2) - var theta = Math.asin(height / (2 * Vec3.distance(HMD.position, controllerPosition))); + var theta = Math.asin(height / (2 * Vec3.distance(headPos, controllerPosition))); // then we can use this angle to rotate the vector between the HMD position and the center of the tablet. // this vector, u, will become our new look at direction. - var d = Vec3.normalize(Vec3.subtract(HMD.position, controllerPosition)); + var d = Vec3.normalize(Vec3.subtract(headPos, controllerPosition)); var w = Vec3.normalize(Vec3.cross(Y_AXIS, d)); var q = Quat.angleAxis(theta * (180 / Math.PI), w); var u = Vec3.multiplyQbyV(q, d); @@ -64,8 +68,8 @@ function calcSpawnInfo(hand, height) { rotation: lookAtRot }; } else { - var front = Quat.getFront(Camera.orientation); - finalPosition = Vec3.sum(Camera.position, Vec3.multiply(0.6, front)); + var front = Quat.getFront(headRot); + finalPosition = Vec3.sum(headPos, Vec3.multiply(0.6, front)); var orientation = Quat.lookAt({x: 0, y: 0, z: 0}, front, {x: 0, y: 1, z: 0}); return { position: finalPosition, @@ -238,7 +242,6 @@ WebTablet.prototype.destroy = function () { WebTablet.prototype.geometryChanged = function (geometry) { if (!HMD.active) { - var NO_HANDS = -1; var tabletProperties = {}; // compute position, rotation & parentJointIndex of the tablet this.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties); @@ -294,7 +297,6 @@ WebTablet.prototype.onHmdChanged = function () { Controller.mouseReleaseEvent.connect(this.myMouseReleaseEvent); } - var NO_HANDS = -1; var tabletProperties = {}; // compute position, rotation & parentJointIndex of the tablet this.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties); @@ -377,17 +379,14 @@ WebTablet.prototype.mousePressEvent = function (event) { }; WebTablet.prototype.cameraModeChanged = function (newMode) { - // reposition the tablet, after a small delay. + // reposition the tablet. // This allows HMD.position to reflect the new camera mode. if (HMD.active) { var self = this; - Script.setTimeout(function () { - var NO_HANDS = -1; - var tabletProperties = {}; - // compute position, rotation & parentJointIndex of the tablet - self.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties); - Entities.editEntity(self.tabletEntityID, tabletProperties); - }, 10); + var tabletProperties = {}; + // compute position, rotation & parentJointIndex of the tablet + self.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties); + Entities.editEntity(self.tabletEntityID, tabletProperties); } };