From d320f5b6f4e2f616501107c627cc3081300e035e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Oct 2015 14:40:12 -0700 Subject: [PATCH 01/20] remember uuid of deleted actions for 20 seconds and don't re-add them --- libraries/entities/src/EntityItem.cpp | 20 +++++++++++++++++--- libraries/entities/src/EntityItem.h | 3 +++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ce719ee976..161d2c9005 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -34,7 +34,7 @@ bool EntityItem::_sendPhysicsUpdates = true; int EntityItem::_maxActionsDataSize = 800; - +quint64 EntityItem::_rememberDeletedActionTime = 20; // seconds EntityItem::EntityItem(const EntityItemID& entityItemID) : _type(EntityTypes::Unknown), _id(entityItemID), @@ -1618,6 +1618,8 @@ void EntityItem::deserializeActions() { void EntityItem::deserializeActionsInternal() { assertWriteLocked(); + quint64 now = usecTimestampNow(); + if (!_element) { return; } @@ -1643,6 +1645,10 @@ void EntityItem::deserializeActionsInternal() { QUuid actionID; serializedActionStream >> actionType; serializedActionStream >> actionID; + if (_previouslyDeletedActions.contains(actionID)) { + continue; + } + updated << actionID; if (_objectActions.contains(actionID)) { @@ -1652,8 +1658,6 @@ void EntityItem::deserializeActionsInternal() { action->deserialize(serializedAction); } else { auto actionFactory = DependencyManager::get(); - - // EntityItemPointer entity = entityTree->findEntityByEntityItemID(_id, false); EntityItemPointer entity = shared_from_this(); EntityActionPointer action = actionFactory->factoryBA(entity, serializedAction); if (action) { @@ -1668,10 +1672,20 @@ void EntityItem::deserializeActionsInternal() { QUuid id = i.key(); if (!updated.contains(id)) { _actionsToRemove << id; + _previouslyDeletedActions.insert(id, now); } i++; } + // trim down _previouslyDeletedActions + QMutableHashIterator _previouslyDeletedIter(_previouslyDeletedActions); + while (_previouslyDeletedIter.hasNext()) { + _previouslyDeletedIter.next(); + if (_previouslyDeletedIter.value() - now > _rememberDeletedActionTime) { + _previouslyDeletedActions.remove(_previouslyDeletedIter.key()); + } + } + return; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 62b436b498..7f760bcf33 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -519,6 +519,9 @@ protected: void checkWaitingToRemove(EntitySimulation* simulation = nullptr); mutable QSet _actionsToRemove; mutable bool _actionDataDirty = false; + // _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag + static quint64 _rememberDeletedActionTime; + mutable QHash _previouslyDeletedActions; }; #endif // hifi_EntityItem_h From 56b50b5fb302d5d889e6b4317b615c70e7ac9d51 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Oct 2015 14:45:10 -0700 Subject: [PATCH 02/20] also add action to _previouslyDeletedActions if the local interface deletes the action --- libraries/entities/src/EntityItem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 161d2c9005..acd2e7d316 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1566,6 +1566,7 @@ bool EntityItem::removeAction(EntitySimulation* simulation, const QUuid& actionI bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* simulation) { assertWriteLocked(); + _previouslyDeletedActions.insert(actionID, usecTimestampNow()); if (_objectActions.contains(actionID)) { if (!simulation) { EntityTreePointer entityTree = _element ? _element->getTree() : nullptr; From fa7a5f1a615e599f6f7e7e8cbe9878a67b5c464c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Oct 2015 14:51:33 -0700 Subject: [PATCH 03/20] formatting, fix a bug --- libraries/entities/src/EntityItem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index acd2e7d316..1ecaf238b2 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -35,6 +35,7 @@ bool EntityItem::_sendPhysicsUpdates = true; int EntityItem::_maxActionsDataSize = 800; quint64 EntityItem::_rememberDeletedActionTime = 20; // seconds + EntityItem::EntityItem(const EntityItemID& entityItemID) : _type(EntityTypes::Unknown), _id(entityItemID), @@ -1682,7 +1683,7 @@ void EntityItem::deserializeActionsInternal() { QMutableHashIterator _previouslyDeletedIter(_previouslyDeletedActions); while (_previouslyDeletedIter.hasNext()) { _previouslyDeletedIter.next(); - if (_previouslyDeletedIter.value() - now > _rememberDeletedActionTime) { + if (now - _previouslyDeletedIter.value() > _rememberDeletedActionTime) { _previouslyDeletedActions.remove(_previouslyDeletedIter.key()); } } From f2ebba9863a077cff9a008eb98082e470be41c79 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Oct 2015 16:16:23 -0700 Subject: [PATCH 04/20] separate out the inbound and outbound caches of serialized action data --- libraries/entities/src/EntityItem.cpp | 28 ++++++++++++++++----------- libraries/entities/src/EntityItem.h | 4 +++- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1ecaf238b2..1bb70be205 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -34,7 +34,7 @@ bool EntityItem::_sendPhysicsUpdates = true; int EntityItem::_maxActionsDataSize = 800; -quint64 EntityItem::_rememberDeletedActionTime = 20; // seconds +quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; EntityItem::EntityItem(const EntityItemID& entityItemID) : _type(EntityTypes::Unknown), @@ -1528,7 +1528,7 @@ bool EntityItem::addActionInternal(EntitySimulation* simulation, EntityActionPoi bool success; QByteArray newDataCache = serializeActions(success); if (success) { - _allActionsDataCache = newDataCache; + _allActionsDataCacheOut = newDataCache; _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; } return success; @@ -1547,7 +1547,7 @@ bool EntityItem::updateAction(EntitySimulation* simulation, const QUuid& actionI success = action->updateArguments(arguments); if (success) { - _allActionsDataCache = serializeActions(success); + _allActionsDataCacheOut = serializeActions(success); _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; } else { qDebug() << "EntityItem::updateAction failed"; @@ -1583,7 +1583,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s } bool success = true; - _allActionsDataCache = serializeActions(success); + _allActionsDataCacheOut = serializeActions(success); _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; return success; } @@ -1602,8 +1602,10 @@ bool EntityItem::clearActions(EntitySimulation* simulation) { } // empty _serializedActions means no actions for the EntityItem _actionsToRemove.clear(); - _allActionsDataCache.clear(); + _allActionsDataCacheIn.clear(); + _allActionsDataCacheOut.clear(); _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; + _actionDataDirty = true; }); return true; } @@ -1634,8 +1636,8 @@ void EntityItem::deserializeActionsInternal() { assert(simulation); QVector serializedActions; - if (_allActionsDataCache.size() > 0) { - QDataStream serializedActionsStream(_allActionsDataCache); + if (_allActionsDataCacheIn.size() > 0) { + QDataStream serializedActionsStream(_allActionsDataCacheIn); serializedActionsStream >> serializedActions; } @@ -1688,6 +1690,8 @@ void EntityItem::deserializeActionsInternal() { } } + _actionDataDirty = true; + return; } @@ -1709,8 +1713,10 @@ void EntityItem::setActionData(QByteArray actionData) { void EntityItem::setActionDataInternal(QByteArray actionData) { assertWriteLocked(); checkWaitingToRemove(); - _allActionsDataCache = actionData; - deserializeActionsInternal(); + if (_allActionsDataCacheIn != actionData) { + _allActionsDataCacheIn = actionData; + deserializeActionsInternal(); + } } QByteArray EntityItem::serializeActions(bool& success) const { @@ -1749,11 +1755,11 @@ const QByteArray EntityItem::getActionDataInternal() const { bool success; QByteArray newDataCache = serializeActions(success); if (success) { - _allActionsDataCache = newDataCache; + _allActionsDataCacheOut = newDataCache; } _actionDataDirty = false; } - return _allActionsDataCache; + return _allActionsDataCacheOut; } const QByteArray EntityItem::getActionData() const { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 7f760bcf33..b48da7cdff 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -512,7 +512,9 @@ protected: QHash _objectActions; static int _maxActionsDataSize; - mutable QByteArray _allActionsDataCache; + mutable QByteArray _allActionsDataCacheIn; + mutable QByteArray _allActionsDataCacheOut; + // when an entity-server starts up, EntityItem::setActionData is called before the entity-tree is // ready. This means we can't find our EntityItemPointer or add the action to the simulation. These // are used to keep track of and work around this situation. From e90b156b7bd7c8456e6a6376cdf0db8f861a6c2f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Oct 2015 17:02:02 -0700 Subject: [PATCH 05/20] avoid: add an action, immediately receive an update to that entities action, delete the just-added action because it wasn't in the packet --- libraries/entities/src/EntityActionInterface.h | 2 ++ libraries/entities/src/EntityItem.cpp | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index e61019c98c..4432b26a6a 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -48,6 +48,8 @@ public: virtual bool lifetimeIsOver() { return false; } + bool locallyAddedButNotYetReceived = false; + protected: virtual glm::vec3 getPosition() = 0; virtual void setPosition(glm::vec3 position) = 0; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1bb70be205..5bcb61963c 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1506,6 +1506,8 @@ bool EntityItem::addAction(EntitySimulation* simulation, EntityActionPointer act result = addActionInternal(simulation, action); if (!result) { removeActionInternal(action->getID()); + } else { + action->locallyAddedButNotYetReceived = true; } }); @@ -1665,6 +1667,7 @@ void EntityItem::deserializeActionsInternal() { EntityItemPointer entity = shared_from_this(); EntityActionPointer action = actionFactory->factoryBA(entity, serializedAction); if (action) { + action->locallyAddedButNotYetReceived = false; entity->addActionInternal(simulation, action); } } @@ -1675,8 +1678,12 @@ void EntityItem::deserializeActionsInternal() { while (i != _objectActions.end()) { QUuid id = i.key(); if (!updated.contains(id)) { - _actionsToRemove << id; - _previouslyDeletedActions.insert(id, now); + EntityActionPointer action = i.value(); + // if we've just added this action, don't remove it due to lack of mention in an incoming packet. + if (! action->locallyAddedButNotYetReceived) { + _actionsToRemove << id; + _previouslyDeletedActions.insert(id, now); + } } i++; } From 40c5103d2fba7b3cbd2cc047cd002086651d6a1c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Oct 2015 17:15:20 -0700 Subject: [PATCH 06/20] back out change where actino data caches were split into in/out --- libraries/entities/src/EntityItem.cpp | 21 ++++++++++----------- libraries/entities/src/EntityItem.h | 3 +-- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5bcb61963c..2c18ac5cfd 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1530,7 +1530,7 @@ bool EntityItem::addActionInternal(EntitySimulation* simulation, EntityActionPoi bool success; QByteArray newDataCache = serializeActions(success); if (success) { - _allActionsDataCacheOut = newDataCache; + _allActionsDataCache = newDataCache; _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; } return success; @@ -1549,7 +1549,7 @@ bool EntityItem::updateAction(EntitySimulation* simulation, const QUuid& actionI success = action->updateArguments(arguments); if (success) { - _allActionsDataCacheOut = serializeActions(success); + _allActionsDataCache = serializeActions(success); _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; } else { qDebug() << "EntityItem::updateAction failed"; @@ -1585,7 +1585,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s } bool success = true; - _allActionsDataCacheOut = serializeActions(success); + _allActionsDataCache = serializeActions(success); _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; return success; } @@ -1604,8 +1604,7 @@ bool EntityItem::clearActions(EntitySimulation* simulation) { } // empty _serializedActions means no actions for the EntityItem _actionsToRemove.clear(); - _allActionsDataCacheIn.clear(); - _allActionsDataCacheOut.clear(); + _allActionsDataCache.clear(); _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; _actionDataDirty = true; }); @@ -1638,8 +1637,8 @@ void EntityItem::deserializeActionsInternal() { assert(simulation); QVector serializedActions; - if (_allActionsDataCacheIn.size() > 0) { - QDataStream serializedActionsStream(_allActionsDataCacheIn); + if (_allActionsDataCache.size() > 0) { + QDataStream serializedActionsStream(_allActionsDataCache); serializedActionsStream >> serializedActions; } @@ -1720,8 +1719,8 @@ void EntityItem::setActionData(QByteArray actionData) { void EntityItem::setActionDataInternal(QByteArray actionData) { assertWriteLocked(); checkWaitingToRemove(); - if (_allActionsDataCacheIn != actionData) { - _allActionsDataCacheIn = actionData; + if (_allActionsDataCache != actionData) { + _allActionsDataCache = actionData; deserializeActionsInternal(); } } @@ -1762,11 +1761,11 @@ const QByteArray EntityItem::getActionDataInternal() const { bool success; QByteArray newDataCache = serializeActions(success); if (success) { - _allActionsDataCacheOut = newDataCache; + _allActionsDataCache = newDataCache; } _actionDataDirty = false; } - return _allActionsDataCacheOut; + return _allActionsDataCache; } const QByteArray EntityItem::getActionData() const { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b48da7cdff..c856794322 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -512,8 +512,7 @@ protected: QHash _objectActions; static int _maxActionsDataSize; - mutable QByteArray _allActionsDataCacheIn; - mutable QByteArray _allActionsDataCacheOut; + mutable QByteArray _allActionsDataCache; // when an entity-server starts up, EntityItem::setActionData is called before the entity-tree is // ready. This means we can't find our EntityItemPointer or add the action to the simulation. These From 9f27e5ff1fb260bc313fd8c9c08775ab8eae47f9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Oct 2015 18:21:53 -0700 Subject: [PATCH 07/20] back out a couple other unneeded changes --- libraries/entities/src/EntityItem.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 2c18ac5cfd..87967629dd 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1606,7 +1606,6 @@ bool EntityItem::clearActions(EntitySimulation* simulation) { _actionsToRemove.clear(); _allActionsDataCache.clear(); _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; - _actionDataDirty = true; }); return true; } @@ -1719,10 +1718,8 @@ void EntityItem::setActionData(QByteArray actionData) { void EntityItem::setActionDataInternal(QByteArray actionData) { assertWriteLocked(); checkWaitingToRemove(); - if (_allActionsDataCache != actionData) { - _allActionsDataCache = actionData; - deserializeActionsInternal(); - } + _allActionsDataCache = actionData; + deserializeActionsInternal(); } QByteArray EntityItem::serializeActions(bool& success) const { From 5b970e6b1af1a3d06efd73ce868e53d0d65ea96e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Oct 2015 11:43:19 -0700 Subject: [PATCH 08/20] try to fix double-distance-grabbing lockout --- examples/controllers/handControllerGrab.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 5705bd4498..9822f90670 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -87,15 +87,18 @@ function getTag() { } function entityIsGrabbedByOther(entityID) { + // by convention, a distance grab sets the tag of its action to be grab-*owner-session-id*. var actionIDs = Entities.getActionIDs(entityID); for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { var actionID = actionIDs[actionIndex]; var actionArguments = Entities.getActionArguments(entityID, actionID); var tag = actionArguments["tag"]; if (tag == getTag()) { + // we see a grab-*uuid* shaped tag, but it's our tag, so that's okay. continue; } if (tag.slice(0, 5) == "grab-") { + // we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. return true; } } @@ -259,6 +262,7 @@ function MyController(hand, triggerAction) { } else { if (entityIsGrabbedByOther(intersection.entityID)) { // don't allow two people to distance grab the same object + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); return; } // the hand is far from the intersected object. go into distance-holding mode From 880d92ee64d6cd369731c9b2449df4ab6ee214fd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Oct 2015 11:46:48 -0700 Subject: [PATCH 09/20] try to fix double-distance-grabbing lockout --- examples/grab.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/examples/grab.js b/examples/grab.js index 03a227931d..1e0adf9f1b 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -45,26 +45,25 @@ var IDENTITY_QUAT = { z: 0, w: 0 }; -var ACTION_LIFETIME = 120; // 2 minutes +var ACTION_LIFETIME = 10; // seconds function getTag() { return "grab-" + MyAvatar.sessionUUID; } function entityIsGrabbedByOther(entityID) { + // by convention, a distance grab sets the tag of its action to be grab-*owner-session-id*. var actionIDs = Entities.getActionIDs(entityID); - var actionIndex; - var actionID; - var actionArguments; - var tag; - for (actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { - actionID = actionIDs[actionIndex]; - actionArguments = Entities.getActionArguments(entityID, actionID); - tag = actionArguments.tag; - if (tag === getTag()) { + for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { + var actionID = actionIDs[actionIndex]; + var actionArguments = Entities.getActionArguments(entityID, actionID); + var tag = actionArguments["tag"]; + if (tag == getTag()) { + // we see a grab-*uuid* shaped tag, but it's our tag, so that's okay. continue; } - if (tag.slice(0, 5) === "grab-") { + if (tag.slice(0, 5) == "grab-") { + // we see a grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. return true; } } @@ -530,4 +529,4 @@ Controller.mousePressEvent.connect(pressEvent); Controller.mouseMoveEvent.connect(moveEvent); Controller.mouseReleaseEvent.connect(releaseEvent); Controller.keyPressEvent.connect(keyPressEvent); -Controller.keyReleaseEvent.connect(keyReleaseEvent); \ No newline at end of file +Controller.keyReleaseEvent.connect(keyReleaseEvent); From c0e8b02a2fddc5768c1b6bc97d225523f47ce44b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Oct 2015 12:25:34 -0700 Subject: [PATCH 10/20] fix what happens when a distance grab is blocked because someone else already has it --- examples/controllers/handControllerGrab.js | 54 ++++++++++++---------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 9822f90670..f4a6d1790d 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -167,6 +167,12 @@ function MyController(hand, triggerAction) { } }; + this.setState = function(newState) { + // print("STATE: " + this.state + " --> " + newState); + this.state = newState; + } + + this.lineOn = function(closePoint, farPoint, color) { // draw a line if (this.pointer === null) { @@ -220,14 +226,14 @@ function MyController(hand, triggerAction) { this.off = function() { if (this.triggerSmoothedSqueezed()) { - this.state = STATE_SEARCHING; + this.setState(STATE_SEARCHING); return; } } this.search = function() { if (this.triggerSmoothedReleased()) { - this.state = STATE_RELEASE; + this.setState(STATE_RELEASE); return; } @@ -238,6 +244,8 @@ function MyController(hand, triggerAction) { direction: Quat.getUp(this.getHandRotation()) }; + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + var defaultGrabbableData = { grabbable: true }; @@ -253,21 +261,20 @@ function MyController(hand, triggerAction) { var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, intersection.entityID, defaultGrabbableData); if (grabbableData.grabbable === false) { + this.grabbedEntity = null; return; } if (intersectionDistance < NEAR_PICK_MAX_DISTANCE) { // the hand is very close to the intersected object. go into close-grabbing mode. - this.state = STATE_NEAR_GRABBING; - + this.setState(STATE_NEAR_GRABBING); } else { + // don't allow two people to distance grab the same object if (entityIsGrabbedByOther(intersection.entityID)) { - // don't allow two people to distance grab the same object - this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); - return; + this.grabbedEntity = null; + } else { + // the hand is far from the intersected object. go into distance-holding mode + this.setState(STATE_DISTANCE_HOLDING); } - // the hand is far from the intersected object. go into distance-holding mode - this.state = STATE_DISTANCE_HOLDING; - this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); } } else { // forward ray test failed, try sphere test. @@ -291,15 +298,14 @@ function MyController(hand, triggerAction) { } } if (this.grabbedEntity === null) { - this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + // this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); } else if (props.locked === 0 && props.collisionsWillMove === 1) { - this.state = STATE_NEAR_GRABBING; + this.setState(STATE_NEAR_GRABBING); } else if (props.collisionsWillMove === 0) { // We have grabbed a non-physical object, so we want to trigger a non-colliding event as opposed to a grab event - this.state = STATE_NEAR_GRABBING_NON_COLLIDING; + this.setState(STATE_NEAR_GRABBING_NON_COLLIDING); } } - }; this.distanceHolding = function() { @@ -329,7 +335,7 @@ function MyController(hand, triggerAction) { } if (this.actionID !== null) { - this.state = STATE_CONTINUE_DISTANCE_HOLDING; + this.setState(STATE_CONTINUE_DISTANCE_HOLDING); this.activateEntity(this.grabbedEntity); if (this.hand === RIGHT_HAND) { Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); @@ -346,7 +352,7 @@ function MyController(hand, triggerAction) { this.continueDistanceHolding = function() { if (this.triggerSmoothedReleased()) { - this.state = STATE_RELEASE; + this.setState(STATE_RELEASE); return; } @@ -404,7 +410,7 @@ function MyController(hand, triggerAction) { var now = Date.now(); var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds this.computeReleaseVelocity(deltaPosition, deltaTime, false); - + this.currentObjectPosition = newObjectPosition; this.currentObjectTime = now; @@ -427,7 +433,7 @@ function MyController(hand, triggerAction) { this.nearGrabbing = function() { if (this.triggerSmoothedReleased()) { - this.state = STATE_RELEASE; + this.setState(STATE_RELEASE); return; } @@ -458,7 +464,7 @@ function MyController(hand, triggerAction) { if (this.actionID === NULL_ACTION_ID) { this.actionID = null; } else { - this.state = STATE_CONTINUE_NEAR_GRABBING; + this.setState(STATE_CONTINUE_NEAR_GRABBING); if (this.hand === RIGHT_HAND) { Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); } else { @@ -475,7 +481,7 @@ function MyController(hand, triggerAction) { this.continueNearGrabbing = function() { if (this.triggerSmoothedReleased()) { - this.state = STATE_RELEASE; + this.setState(STATE_RELEASE); return; } @@ -502,7 +508,7 @@ function MyController(hand, triggerAction) { this.nearGrabbingNonColliding = function() { if (this.triggerSmoothedReleased()) { - this.state = STATE_RELEASE; + this.setState(STATE_RELEASE); return; } if (this.hand === RIGHT_HAND) { @@ -511,12 +517,12 @@ function MyController(hand, triggerAction) { Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); } Entities.callEntityMethod(this.grabbedEntity, "startNearGrabNonColliding"); - this.state = STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING; + this.setState(STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING); }; this.continueNearGrabbingNonColliding = function() { if (this.triggerSmoothedReleased()) { - this.state = STATE_RELEASE; + this.setState(STATE_RELEASE); return; } Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabbingNonColliding"); @@ -627,7 +633,7 @@ function MyController(hand, triggerAction) { this.grabbedVelocity = ZERO_VEC; this.grabbedEntity = null; this.actionID = null; - this.state = STATE_OFF; + this.setState(STATE_OFF); }; this.cleanup = function() { From 67cc944afc27ce9182b716a9b7c4ab07547901e6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Oct 2015 13:27:45 -0700 Subject: [PATCH 11/20] fix double free problem --- libraries/entities/src/EntityItem.cpp | 22 +++++++++++----------- libraries/entities/src/EntityItem.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 87967629dd..a031fbb196 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1528,7 +1528,8 @@ bool EntityItem::addActionInternal(EntitySimulation* simulation, EntityActionPoi simulation->addAction(action); bool success; - QByteArray newDataCache = serializeActions(success); + QByteArray newDataCache; + serializeActions(success, newDataCache); if (success) { _allActionsDataCache = newDataCache; _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; @@ -1549,7 +1550,7 @@ bool EntityItem::updateAction(EntitySimulation* simulation, const QUuid& actionI success = action->updateArguments(arguments); if (success) { - _allActionsDataCache = serializeActions(success); + serializeActions(success, _allActionsDataCache); _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; } else { qDebug() << "EntityItem::updateAction failed"; @@ -1585,7 +1586,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s } bool success = true; - _allActionsDataCache = serializeActions(success); + serializeActions(success, _allActionsDataCache); _dirtyFlags |= EntityItem::DIRTY_PHYSICS_ACTIVATION; return success; } @@ -1722,13 +1723,13 @@ void EntityItem::setActionDataInternal(QByteArray actionData) { deserializeActionsInternal(); } -QByteArray EntityItem::serializeActions(bool& success) const { +void EntityItem::serializeActions(bool& success, QByteArray& result) const { assertLocked(); - QByteArray result; if (_objectActions.size() == 0) { success = true; - return QByteArray(); + result.clear(); + return; } QVector serializedActions; @@ -1746,21 +1747,20 @@ QByteArray EntityItem::serializeActions(bool& success) const { if (result.size() >= _maxActionsDataSize) { success = false; - return result; + return; } success = true; - return result; + return; } const QByteArray EntityItem::getActionDataInternal() const { if (_actionDataDirty) { bool success; - QByteArray newDataCache = serializeActions(success); + serializeActions(success, _allActionsDataCache); if (success) { - _allActionsDataCache = newDataCache; + _actionDataDirty = false; } - _actionDataDirty = false; } return _allActionsDataCache; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index c856794322..7b1537bbc3 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -508,7 +508,7 @@ protected: bool addActionInternal(EntitySimulation* simulation, EntityActionPointer action); bool removeActionInternal(const QUuid& actionID, EntitySimulation* simulation = nullptr); void deserializeActionsInternal(); - QByteArray serializeActions(bool& success) const; + void serializeActions(bool& success, QByteArray& result) const; QHash _objectActions; static int _maxActionsDataSize; From b6b57de1c6b870cbd026ad21fa22e01bf622643e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 2 Oct 2015 16:42:50 -0700 Subject: [PATCH 12/20] animation lib warning fixes --- libraries/animation/src/AnimClip.cpp | 2 +- libraries/animation/src/AnimInverseKinematics.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index c432b3b9ac..0d181f8e47 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -159,7 +159,7 @@ void AnimClip::copyFromNetworkAnim() { // used to adjust translation offsets, so large translation animatons on the reference skeleton // will be adjusted when played on a skeleton with short limbs. - float limbLengthScale = fabs(glm::length(fbxZeroTrans)) <= 0.0001f ? 1.0f : (glm::length(relBindPose.trans) / glm::length(fbxZeroTrans)); + float limbLengthScale = (float)fabs(glm::length(fbxZeroTrans)) <= 0.0001f ? 1.0f : (glm::length(relBindPose.trans) / glm::length(fbxZeroTrans)); AnimPose& pose = _anim[frame][skeletonJoint]; const FBXAnimationFrame& fbxAnimFrame = geom.animationFrames[frame]; diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index 2eb0d9b08e..171bcc11d8 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -52,7 +52,7 @@ protected: void computeTargets(const AnimVariantMap& animVars, std::vector& targets, const AnimPoseVec& underPoses); void solveWithCyclicCoordinateDescent(const std::vector& targets); - virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton); + virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) override; // for AnimDebugDraw rendering virtual const AnimPoseVec& getPosesInternal() const override { return _relativePoses; } From 67a497cda33ed3e31197215c98d0fa3d002d4160 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 2 Oct 2015 17:37:59 -0700 Subject: [PATCH 13/20] Sanitize particle properties and their use Excluding animationSetings because it's unused and will be removed. --- .../entities/src/ParticleEffectEntityItem.cpp | 113 +++++++++++++++--- .../entities/src/ParticleEffectEntityItem.h | 58 ++++++--- 2 files changed, 140 insertions(+), 31 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 40d3853c39..3a823ae2e8 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -52,24 +52,48 @@ const float ParticleEffectEntityItem::DEFAULT_ALPHA = 1.0f; const float ParticleEffectEntityItem::DEFAULT_ALPHA_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_ALPHA_START = DEFAULT_ALPHA; const float ParticleEffectEntityItem::DEFAULT_ALPHA_FINISH = DEFAULT_ALPHA; +const float ParticleEffectEntityItem::MINIMUM_ALPHA = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_ALPHA = 1.0f; const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f; const bool ParticleEffectEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false; const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f; const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; +const quint32 ParticleEffectEntityItem::MINIMUM_MAX_PARTICLES = 1; +const quint32 ParticleEffectEntityItem::MAXIMUM_MAX_PARTICLES = 10000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; +const float ParticleEffectEntityItem::MINIMUM_LIFESPAN = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_LIFESPAN = 86400.0f; // 1 day const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; +const float ParticleEffectEntityItem::MINIMUM_EMIT_RATE = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_EMIT_RATE = 1000.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_SPEED = 5.0f; +const float ParticleEffectEntityItem::MINIMUM_EMIT_SPEED = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_EMIT_SPEED = 343.2f; // Speed of sound const float ParticleEffectEntityItem::DEFAULT_SPEED_SPREAD = 1.0f; const glm::quat ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, X_AXIS); // Vertical const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS = glm::vec3(0.0f, 0.0f, 0.0f); // Emit from point +const float ParticleEffectEntityItem::MINIMUM_EMIT_DIMENSION = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_EMIT_DIMENSION = (float)TREE_SCALE; const float ParticleEffectEntityItem::DEFAULT_EMIT_RADIUS_START = 1.0f; // Emit from surface (when emitDimensions > 0) +const float ParticleEffectEntityItem::MINIMUM_EMIT_RADIUS_START = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_EMIT_RADIUS_START = 1.0f; +const float ParticleEffectEntityItem::MINIMUM_POLAR = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_POLAR = PI; const float ParticleEffectEntityItem::DEFAULT_POLAR_START = 0.0f; // Emit along z-axis const float ParticleEffectEntityItem::DEFAULT_POLAR_FINISH = 0.0f; // "" +const float ParticleEffectEntityItem::MINIMUM_AZIMUTH = -PI; +const float ParticleEffectEntityItem::MAXIMUM_AZIMUTH = PI; const float ParticleEffectEntityItem::DEFAULT_AZIMUTH_START = -PI; // Emit full circumference (when polarFinish > 0) const float ParticleEffectEntityItem::DEFAULT_AZIMUTH_FINISH = PI; // "" const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, -9.8f, 0.0f); +const float ParticleEffectEntityItem::MINIMUM_EMIT_ACCELERATION = -100.0f; // ~ 10g +const float ParticleEffectEntityItem::MAXIMUM_EMIT_ACCELERATION = 100.0f; const glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f); +const float ParticleEffectEntityItem::MINIMUM_ACCELERATION_SPREAD = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_ACCELERATION_SPREAD = 100.0f; const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; +const float ParticleEffectEntityItem::MINIMUM_PARTICLE_RADIUS = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_PARTICLE_RADIUS = (float)TREE_SCALE; const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS; const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS; @@ -114,37 +138,82 @@ ParticleEffectEntityItem::~ParticleEffectEntityItem() { } +void ParticleEffectEntityItem::setAlphaStart(float alphaStart) { + _alphaStart = glm::clamp(alphaStart, MINIMUM_ALPHA, MAXIMUM_ALPHA); + _isAlphaStartInitialized = true; +} + +void ParticleEffectEntityItem::setAlphaFinish(float alphaFinish) { + _alphaFinish = glm::clamp(alphaFinish, MINIMUM_ALPHA, MAXIMUM_ALPHA); + _isAlphaFinishInitialized = true; +} + void ParticleEffectEntityItem::setEmitSpeed(float emitSpeed) { - _emitSpeed = emitSpeed; + _emitSpeed = glm::clamp(emitSpeed, MINIMUM_EMIT_SPEED, MAXIMUM_EMIT_SPEED); computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setSpeedSpread(float speedSpread) { - _speedSpread = speedSpread; + _speedSpread = glm::clamp(speedSpread, MINIMUM_EMIT_SPEED, MAXIMUM_EMIT_SPEED); computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setEmitOrientation(const glm::quat& emitOrientation) { - _emitOrientation = emitOrientation; + _emitOrientation = glm::normalize(emitOrientation); computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setEmitDimensions(const glm::vec3& emitDimensions) { - _emitDimensions = emitDimensions; + _emitDimensions = glm::vec3( + glm::clamp(emitDimensions.x, MINIMUM_EMIT_DIMENSION, MAXIMUM_EMIT_DIMENSION), + glm::clamp(emitDimensions.y, MINIMUM_EMIT_DIMENSION, MAXIMUM_EMIT_DIMENSION), + glm::clamp(emitDimensions.z, MINIMUM_EMIT_DIMENSION, MAXIMUM_EMIT_DIMENSION) + ); computeAndUpdateDimensions(); } +void ParticleEffectEntityItem::setEmitRadiusStart(float emitRadiusStart) { + _emitRadiusStart = glm::clamp(emitRadiusStart, MINIMUM_EMIT_RADIUS_START, MAXIMUM_EMIT_RADIUS_START); +} + void ParticleEffectEntityItem::setEmitAcceleration(const glm::vec3& emitAcceleration) { - _emitAcceleration = emitAcceleration; + _emitAcceleration = glm::vec3( + glm::clamp(emitAcceleration.x, MINIMUM_EMIT_ACCELERATION, MAXIMUM_EMIT_ACCELERATION), + glm::clamp(emitAcceleration.x, MINIMUM_EMIT_ACCELERATION, MAXIMUM_EMIT_ACCELERATION), + glm::clamp(emitAcceleration.y, MINIMUM_EMIT_ACCELERATION, MAXIMUM_EMIT_ACCELERATION) + ); computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setAccelerationSpread(const glm::vec3& accelerationSpread){ - _accelerationSpread = accelerationSpread; + _accelerationSpread = glm::vec3( + glm::clamp(accelerationSpread.x, MINIMUM_ACCELERATION_SPREAD, MAXIMUM_ACCELERATION_SPREAD), + glm::clamp(accelerationSpread.x, MINIMUM_ACCELERATION_SPREAD, MAXIMUM_ACCELERATION_SPREAD), + glm::clamp(accelerationSpread.y, MINIMUM_ACCELERATION_SPREAD, MAXIMUM_ACCELERATION_SPREAD) + ); computeAndUpdateDimensions(); } +void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { + _particleRadius = glm::clamp(particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); +} + +void ParticleEffectEntityItem::setRadiusStart(float radiusStart) { + _radiusStart = glm::clamp(radiusStart, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + _isRadiusStartInitialized = true; +} + +void ParticleEffectEntityItem::setRadiusFinish(float radiusFinish) { + _radiusFinish = glm::clamp(radiusFinish, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + _isRadiusFinishInitialized = true; +} + +void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) { + _radiusSpread = glm::clamp(radiusSpread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); +} + + void ParticleEffectEntityItem::computeAndUpdateDimensions() { const float time = _lifespan * 1.1f; // add 10% extra time to account for incremental timer accumulation error @@ -639,12 +708,12 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particleLifetimes[i] -= deltaTime; // if particle has died. - if (_particleLifetimes[i] <= 0.0f) { + if (_particleLifetimes[i] <= 0.0f || _lifespan == 0.0f) { // move head forward _particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles; } else { - float age = (1.0f - _particleLifetimes[i] / _lifespan); // 0.0 .. 1.0 + float age = 1.0f - _particleLifetimes[i] / _lifespan; // 0.0 .. 1.0 updateRadius(i, age); updateColor(i, age); updateAlpha(i, age); @@ -654,7 +723,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } // emit new particles, but only if animation is playing - if (getAnimationIsPlaying()) { + if (getAnimationIsPlaying() && _emitRate > 0.0f && _lifespan > 0.0f && _polarStart <= _polarFinish) { float timeLeftInFrame = deltaTime; while (_timeUntilNextEmit < timeLeftInFrame) { @@ -672,10 +741,18 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _radiusMiddles[i] =_particleRadius; _radiusFinishes[i] = getRadiusFinish(); } else { - float spreadMultiplier = 1.0f + (2.0f * randFloat() - 1.0f) * _radiusSpread / _particleRadius; - _radiusStarts[i] = spreadMultiplier * getRadiusStart(); - _radiusMiddles[i] = spreadMultiplier * _particleRadius; - _radiusFinishes[i] = spreadMultiplier * getRadiusFinish(); + float spreadMultiplier; + if (_particleRadius > 0.0f) { + spreadMultiplier = 1.0f + (2.0f * randFloat() - 1.0f) * _radiusSpread / _particleRadius; + } else { + spreadMultiplier = 0.0f; + } + _radiusStarts[i] = + glm::clamp(spreadMultiplier * getRadiusStart(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + _radiusMiddles[i] = + glm::clamp(spreadMultiplier * _particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + _radiusFinishes[i] = + glm::clamp(spreadMultiplier * getRadiusFinish(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); } updateRadius(i, 0.0f); @@ -753,9 +830,12 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { xColor finishColor = getColorFinish(); float spread = 2.0f * randFloat() - 1.0f; - float spreadMultiplierRed = 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red; - float spreadMultiplierGreen = 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green; - float spreadMultiplierBlue = 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue; + float spreadMultiplierRed = + middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; + float spreadMultiplierGreen = + middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green :1.0f; + float spreadMultiplierBlue = + middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; _colorStarts[i].red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); _colorStarts[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); @@ -799,6 +879,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { + maxParticles = glm::clamp(maxParticles, MINIMUM_MAX_PARTICLES, MAXIMUM_MAX_PARTICLES); if (_maxParticles != maxParticles) { _maxParticles = maxParticles; diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 74d39aa4af..d54cfb2250 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -12,6 +12,7 @@ #define hifi_ParticleEffectEntityItem_h #include + #include "EntityItem.h" class ParticleEffectEntityItem : public EntityItem { @@ -68,22 +69,25 @@ public: void setColorSpread(const xColor& colorSpread) { _colorSpread = colorSpread; } xColor getColorSpread() const { return _colorSpread; } + static const float MAXIMUM_ALPHA; + static const float MINIMUM_ALPHA; + static const float DEFAULT_ALPHA; - void setAlpha(float alpha) { _alpha = alpha; } + void setAlpha(float alpha) { _alpha = glm::clamp(alpha, MINIMUM_ALPHA, MAXIMUM_ALPHA); } float getAlpha() const { return _alpha; } static const float DEFAULT_ALPHA_START; bool _isAlphaStartInitialized = false; - void setAlphaStart(float alphaStart) { _alphaStart = alphaStart; _isAlphaStartInitialized = true; } + void setAlphaStart(float alphaStart); float getAlphaStart() const { return _isAlphaStartInitialized ? _alphaStart : _alpha; } static const float DEFAULT_ALPHA_FINISH; bool _isAlphaFinishInitialized = false; - void setAlphaFinish(float alphaFinish) { _alphaFinish = alphaFinish; _isAlphaFinishInitialized = true; } + void setAlphaFinish(float alphaFinish); float getAlphaFinish() const { return _isAlphaFinishInitialized ? _alphaFinish : _alpha; } static const float DEFAULT_ALPHA_SPREAD; - void setAlphaSpread(float alphaSpread) { _alphaSpread = alphaSpread; } + void setAlphaSpread(float alphaSpread) { _alphaSpread = glm::clamp(alphaSpread, MINIMUM_ALPHA, MAXIMUM_ALPHA); } float getAlphaSpread() const { return _alphaSpread; } void updateShapeType(ShapeType type); @@ -117,18 +121,26 @@ public: float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } static const quint32 DEFAULT_MAX_PARTICLES; + static const quint32 MINIMUM_MAX_PARTICLES; + static const quint32 MAXIMUM_MAX_PARTICLES; void setMaxParticles(quint32 maxParticles); quint32 getMaxParticles() const { return _maxParticles; } static const float DEFAULT_LIFESPAN; - void setLifespan(float lifespan) { _lifespan = lifespan; } + static const float MINIMUM_LIFESPAN; + static const float MAXIMUM_LIFESPAN; + void setLifespan(float lifespan) { _lifespan = glm::clamp(lifespan, MINIMUM_LIFESPAN, MAXIMUM_LIFESPAN); } float getLifespan() const { return _lifespan; } static const float DEFAULT_EMIT_RATE; - void setEmitRate(float emitRate) { _emitRate = emitRate; } + static const float MINIMUM_EMIT_RATE; + static const float MAXIMUM_EMIT_RATE; + void setEmitRate(float emitRate) { _emitRate = glm::clamp(emitRate, MINIMUM_EMIT_RATE, MAXIMUM_EMIT_RATE); } float getEmitRate() const { return _emitRate; } static const float DEFAULT_EMIT_SPEED; + static const float MINIMUM_EMIT_SPEED; + static const float MAXIMUM_EMIT_SPEED; void setEmitSpeed(float emitSpeed); float getEmitSpeed() const { return _emitSpeed; } @@ -141,53 +153,69 @@ public: const glm::quat& getEmitOrientation() const { return _emitOrientation; } static const glm::vec3 DEFAULT_EMIT_DIMENSIONS; + static const float MINIMUM_EMIT_DIMENSION; + static const float MAXIMUM_EMIT_DIMENSION; void setEmitDimensions(const glm::vec3& emitDimensions); const glm::vec3& getEmitDimensions() const { return _emitDimensions; } static const float DEFAULT_EMIT_RADIUS_START; - void setEmitRadiusStart(float emitRadiusStart) { _emitRadiusStart = emitRadiusStart; } + static const float MINIMUM_EMIT_RADIUS_START; + static const float MAXIMUM_EMIT_RADIUS_START; + void setEmitRadiusStart(float emitRadiusStart); float getEmitRadiusStart() const { return _emitRadiusStart; } + static const float MINIMUM_POLAR; + static const float MAXIMUM_POLAR; + static const float DEFAULT_POLAR_START; - void setPolarStart(float polarStart) { _polarStart = polarStart; } + void setPolarStart(float polarStart) { _polarStart = glm::clamp(polarStart, MINIMUM_POLAR, MAXIMUM_POLAR); } float getPolarStart() const { return _polarStart; } static const float DEFAULT_POLAR_FINISH; - void setPolarFinish(float polarFinish) { _polarFinish = polarFinish; } + void setPolarFinish(float polarFinish) { _polarFinish = glm::clamp(polarFinish, MINIMUM_POLAR, MAXIMUM_POLAR); } float getPolarFinish() const { return _polarFinish; } + static const float MINIMUM_AZIMUTH; + static const float MAXIMUM_AZIMUTH; + static const float DEFAULT_AZIMUTH_START; - void setAzimuthStart(float azimuthStart) { _azimuthStart = azimuthStart; } + void setAzimuthStart(float azimuthStart) { _azimuthStart = glm::clamp(azimuthStart, MINIMUM_AZIMUTH, MAXIMUM_AZIMUTH); } float getAzimuthStart() const { return _azimuthStart; } static const float DEFAULT_AZIMUTH_FINISH; - void setAzimuthFinish(float azimuthFinish) { _azimuthFinish = azimuthFinish; } + void setAzimuthFinish(float azimuthFinish) { _azimuthFinish = glm::clamp(azimuthFinish, MINIMUM_AZIMUTH, MAXIMUM_AZIMUTH); } float getAzimuthFinish() const { return _azimuthFinish; } static const glm::vec3 DEFAULT_EMIT_ACCELERATION; + static const float MINIMUM_EMIT_ACCELERATION; + static const float MAXIMUM_EMIT_ACCELERATION; void setEmitAcceleration(const glm::vec3& emitAcceleration); const glm::vec3& getEmitAcceleration() const { return _emitAcceleration; } static const glm::vec3 DEFAULT_ACCELERATION_SPREAD; + static const float MINIMUM_ACCELERATION_SPREAD; + static const float MAXIMUM_ACCELERATION_SPREAD; void setAccelerationSpread(const glm::vec3& accelerationSpread); const glm::vec3& getAccelerationSpread() const { return _accelerationSpread; } static const float DEFAULT_PARTICLE_RADIUS; - void setParticleRadius(float particleRadius) { _particleRadius = particleRadius; } + static const float MINIMUM_PARTICLE_RADIUS; + static const float MAXIMUM_PARTICLE_RADIUS; + void setParticleRadius(float particleRadius); float getParticleRadius() const { return _particleRadius; } static const float DEFAULT_RADIUS_START; bool _isRadiusStartInitialized; - void setRadiusStart(float radiusStart) { _radiusStart = radiusStart; _isRadiusStartInitialized = true; } + void setRadiusStart(float radiusStart); float getRadiusStart() const { return _isRadiusStartInitialized ? _radiusStart : _particleRadius; } static const float DEFAULT_RADIUS_FINISH; bool _isRadiusFinishInitialized; - void setRadiusFinish(float radiusFinish) { _radiusFinish = radiusFinish; _isRadiusFinishInitialized = true; } + void setRadiusFinish(float radiusFinish); float getRadiusFinish() const { return _isRadiusFinishInitialized ? _radiusFinish : _particleRadius; } static const float DEFAULT_RADIUS_SPREAD; - void setRadiusSpread(float radiusSpread) { _radiusSpread = radiusSpread; } + void setRadiusSpread(float radiusSpread); float getRadiusSpread() const { return _radiusSpread; } void computeAndUpdateDimensions(); From 510065fe5c98a09892ccd9115eaec348f5d4a94e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 3 Oct 2015 09:16:07 -0700 Subject: [PATCH 14/20] Fix particle property maxParticles not being able to be set properly --- libraries/entities/src/EntityItemProperties.cpp | 2 +- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/ParticleEffectEntityItem.cpp | 10 +++++----- libraries/entities/src/ParticleEffectEntityItem.h | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 61e369cf96..37e61ec0de 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -851,7 +851,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_TEXT_COLOR, TextColor, textColor, xColor); ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); ADD_PROPERTY_TO_MAP(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); - ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); + ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, float); ADD_PROPERTY_TO_MAP(PROP_LIFESPAN, Lifespan, lifespan, float); ADD_PROPERTY_TO_MAP(PROP_EMIT_RATE, EmitRate, emitRate, float); ADD_PROPERTY_TO_MAP(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, glm::vec3); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 55be145d85..e5aa40abc5 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -138,7 +138,7 @@ public: DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor); DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); - DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); + DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, float); DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float); DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); DEFINE_PROPERTY(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, float); diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 3a823ae2e8..ddff80b1b5 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -354,7 +354,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch } READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); - READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); + READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, float, setMaxParticles); READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); if (args.bitstreamVersion < VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER) { @@ -878,10 +878,10 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } } -void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { - maxParticles = glm::clamp(maxParticles, MINIMUM_MAX_PARTICLES, MAXIMUM_MAX_PARTICLES); - if (_maxParticles != maxParticles) { - _maxParticles = maxParticles; +void ParticleEffectEntityItem::setMaxParticles(float maxParticles) { + maxParticles = glm::clamp(maxParticles, (float)MINIMUM_MAX_PARTICLES, (float)MAXIMUM_MAX_PARTICLES); + if (_maxParticles != (quint32)maxParticles) { + _maxParticles = (quint32)maxParticles; // TODO: try to do something smart here and preserve the state of existing particles. diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 30f899aac4..14b60ce4e2 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -123,8 +123,8 @@ public: static const quint32 DEFAULT_MAX_PARTICLES; static const quint32 MINIMUM_MAX_PARTICLES; static const quint32 MAXIMUM_MAX_PARTICLES; - void setMaxParticles(quint32 maxParticles); - quint32 getMaxParticles() const { return _maxParticles; } + void setMaxParticles(float maxParticles); + float getMaxParticles() const { return (float)_maxParticles; } static const float DEFAULT_LIFESPAN; static const float MINIMUM_LIFESPAN; From 53e85e8566f02e59249a473274fd05db1eca5006 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 3 Oct 2015 09:59:33 -0700 Subject: [PATCH 15/20] Tidying --- libraries/entities/src/ParticleEffectEntityItem.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index ddff80b1b5..0c187cfd1c 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -1,4 +1,3 @@ - // // ParticleEffectEntityItem.cpp // libraries/entities/src @@ -31,8 +30,6 @@ #include #include -#include - #include #include #include @@ -68,7 +65,7 @@ const float ParticleEffectEntityItem::MINIMUM_EMIT_RATE = 0.0f; const float ParticleEffectEntityItem::MAXIMUM_EMIT_RATE = 1000.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_SPEED = 5.0f; const float ParticleEffectEntityItem::MINIMUM_EMIT_SPEED = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_EMIT_SPEED = 343.2f; // Speed of sound +const float ParticleEffectEntityItem::MAXIMUM_EMIT_SPEED = 1000.0f; // Approx mach 3 const float ParticleEffectEntityItem::DEFAULT_SPEED_SPREAD = 1.0f; const glm::quat ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, X_AXIS); // Vertical const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS = glm::vec3(0.0f, 0.0f, 0.0f); // Emit from point From 993111d22f6249b788c4ca37f51dce9ca85d63ee Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 5 Oct 2015 11:28:59 -0700 Subject: [PATCH 16/20] code review --- interface/src/InterfaceActionFactory.cpp | 6 +++--- libraries/entities/src/EntityItem.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/InterfaceActionFactory.cpp b/interface/src/InterfaceActionFactory.cpp index 2879c19eaa..cf5dad8fa5 100644 --- a/interface/src/InterfaceActionFactory.cpp +++ b/interface/src/InterfaceActionFactory.cpp @@ -65,9 +65,9 @@ EntityActionPointer InterfaceActionFactory::factoryBA(EntityItemPointer ownerEnt if (action) { action->deserialize(data); - } - if (action->lifetimeIsOver()) { - return nullptr; + if (action->lifetimeIsOver()) { + return nullptr; + } } return action; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a031fbb196..c4f5ad0061 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1661,13 +1661,14 @@ void EntityItem::deserializeActionsInternal() { // TODO: make sure types match? there isn't currently a way to // change the type of an existing action. action->deserialize(serializedAction); + action->locallyAddedButNotYetReceived = false; } else { auto actionFactory = DependencyManager::get(); EntityItemPointer entity = shared_from_this(); EntityActionPointer action = actionFactory->factoryBA(entity, serializedAction); if (action) { - action->locallyAddedButNotYetReceived = false; entity->addActionInternal(simulation, action); + action->locallyAddedButNotYetReceived = false; } } } From 75849db86729f7cd4382e149a60940df9314737a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 5 Oct 2015 12:00:02 -0700 Subject: [PATCH 17/20] Changed (float)fabs() to fabsf() --- libraries/animation/src/AnimClip.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 0d181f8e47..251cb0047a 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -159,7 +159,7 @@ void AnimClip::copyFromNetworkAnim() { // used to adjust translation offsets, so large translation animatons on the reference skeleton // will be adjusted when played on a skeleton with short limbs. - float limbLengthScale = (float)fabs(glm::length(fbxZeroTrans)) <= 0.0001f ? 1.0f : (glm::length(relBindPose.trans) / glm::length(fbxZeroTrans)); + float limbLengthScale = fabsf(glm::length(fbxZeroTrans)) <= 0.0001f ? 1.0f : (glm::length(relBindPose.trans) / glm::length(fbxZeroTrans)); AnimPose& pose = _anim[frame][skeletonJoint]; const FBXAnimationFrame& fbxAnimFrame = geom.animationFrames[frame]; From 844270e3060048b54ad419a9ea3cbdfb97813bdb Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 5 Oct 2015 12:44:22 -0700 Subject: [PATCH 18/20] Reset (as though by apostrophe key) whenever we calibrate the hydra. --- interface/src/PluginContainerProxy.cpp | 4 ++++ interface/src/PluginContainerProxy.h | 1 + libraries/input-plugins/src/input-plugins/SixenseManager.cpp | 1 + libraries/plugins/src/plugins/PluginContainer.h | 1 + 4 files changed, 7 insertions(+) diff --git a/interface/src/PluginContainerProxy.cpp b/interface/src/PluginContainerProxy.cpp index 4ef755bd1b..469e7f7c77 100644 --- a/interface/src/PluginContainerProxy.cpp +++ b/interface/src/PluginContainerProxy.cpp @@ -139,6 +139,10 @@ void PluginContainerProxy::unsetFullscreen(const QScreen* avoid) { #endif } +void PluginContainerProxy::requestReset() { + // We could signal qApp to sequence this, but it turns out that requestReset is only used from within the main thread anyway. + qApp->resetSensors(); +} void PluginContainerProxy::showDisplayPluginsTools() { DependencyManager::get()->hmdTools(true); diff --git a/interface/src/PluginContainerProxy.h b/interface/src/PluginContainerProxy.h index e01cabc3b8..6910dbcd47 100644 --- a/interface/src/PluginContainerProxy.h +++ b/interface/src/PluginContainerProxy.h @@ -20,6 +20,7 @@ class PluginContainerProxy : public QObject, PluginContainer { virtual void setFullscreen(const QScreen* targetScreen, bool hideMenu = true) override; virtual void unsetFullscreen(const QScreen* avoidScreen = nullptr) override; virtual void showDisplayPluginsTools() override; + virtual void requestReset() override; virtual QGLWidget* getPrimarySurface() override; virtual bool isForeground() override; QRect _savedGeometry{ 10, 120, 800, 600 }; diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index aa04c49adb..e900e8779e 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -285,6 +285,7 @@ void SixenseManager::updateCalibration(void* controllersX) { _avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis))); const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f; _avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR; + CONTAINER->requestReset(); qCDebug(inputplugins, "succeess: sixense calibration"); } break; diff --git a/libraries/plugins/src/plugins/PluginContainer.h b/libraries/plugins/src/plugins/PluginContainer.h index c2cba23392..f938758161 100644 --- a/libraries/plugins/src/plugins/PluginContainer.h +++ b/libraries/plugins/src/plugins/PluginContainer.h @@ -26,6 +26,7 @@ public: virtual void setFullscreen(const QScreen* targetScreen, bool hideMenu = false) = 0; virtual void unsetFullscreen(const QScreen* avoidScreen = nullptr) = 0; virtual void showDisplayPluginsTools() = 0; + virtual void requestReset() = 0; virtual QGLWidget* getPrimarySurface() = 0; virtual bool isForeground() = 0; }; From c72c87b59c3be8ae4af9618d6c2e3fe42d347d5f Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Mon, 5 Oct 2015 13:35:58 -0700 Subject: [PATCH 19/20] Revert "QA for 20699 - Sanitize particle property values when set" --- .../entities/src/EntityItemProperties.cpp | 2 +- libraries/entities/src/EntityItemProperties.h | 2 +- .../entities/src/ParticleEffectEntityItem.cpp | 124 ++++-------------- .../entities/src/ParticleEffectEntityItem.h | 62 +++------ 4 files changed, 42 insertions(+), 148 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 37e61ec0de..61e369cf96 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -851,7 +851,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_TEXT_COLOR, TextColor, textColor, xColor); ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); ADD_PROPERTY_TO_MAP(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); - ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, float); + ADD_PROPERTY_TO_MAP(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); ADD_PROPERTY_TO_MAP(PROP_LIFESPAN, Lifespan, lifespan, float); ADD_PROPERTY_TO_MAP(PROP_EMIT_RATE, EmitRate, emitRate, float); ADD_PROPERTY_TO_MAP(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, glm::vec3); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index e5aa40abc5..55be145d85 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -138,7 +138,7 @@ public: DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor); DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); - DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, float); + DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float); DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); DEFINE_PROPERTY(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, float); diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 0c187cfd1c..40d3853c39 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -1,3 +1,4 @@ + // // ParticleEffectEntityItem.cpp // libraries/entities/src @@ -30,6 +31,8 @@ #include #include +#include + #include #include #include @@ -49,48 +52,24 @@ const float ParticleEffectEntityItem::DEFAULT_ALPHA = 1.0f; const float ParticleEffectEntityItem::DEFAULT_ALPHA_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_ALPHA_START = DEFAULT_ALPHA; const float ParticleEffectEntityItem::DEFAULT_ALPHA_FINISH = DEFAULT_ALPHA; -const float ParticleEffectEntityItem::MINIMUM_ALPHA = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_ALPHA = 1.0f; const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f; const bool ParticleEffectEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false; const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f; const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; -const quint32 ParticleEffectEntityItem::MINIMUM_MAX_PARTICLES = 1; -const quint32 ParticleEffectEntityItem::MAXIMUM_MAX_PARTICLES = 10000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; -const float ParticleEffectEntityItem::MINIMUM_LIFESPAN = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_LIFESPAN = 86400.0f; // 1 day const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; -const float ParticleEffectEntityItem::MINIMUM_EMIT_RATE = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_EMIT_RATE = 1000.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_SPEED = 5.0f; -const float ParticleEffectEntityItem::MINIMUM_EMIT_SPEED = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_EMIT_SPEED = 1000.0f; // Approx mach 3 const float ParticleEffectEntityItem::DEFAULT_SPEED_SPREAD = 1.0f; const glm::quat ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, X_AXIS); // Vertical const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS = glm::vec3(0.0f, 0.0f, 0.0f); // Emit from point -const float ParticleEffectEntityItem::MINIMUM_EMIT_DIMENSION = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_EMIT_DIMENSION = (float)TREE_SCALE; const float ParticleEffectEntityItem::DEFAULT_EMIT_RADIUS_START = 1.0f; // Emit from surface (when emitDimensions > 0) -const float ParticleEffectEntityItem::MINIMUM_EMIT_RADIUS_START = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_EMIT_RADIUS_START = 1.0f; -const float ParticleEffectEntityItem::MINIMUM_POLAR = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_POLAR = PI; const float ParticleEffectEntityItem::DEFAULT_POLAR_START = 0.0f; // Emit along z-axis const float ParticleEffectEntityItem::DEFAULT_POLAR_FINISH = 0.0f; // "" -const float ParticleEffectEntityItem::MINIMUM_AZIMUTH = -PI; -const float ParticleEffectEntityItem::MAXIMUM_AZIMUTH = PI; const float ParticleEffectEntityItem::DEFAULT_AZIMUTH_START = -PI; // Emit full circumference (when polarFinish > 0) const float ParticleEffectEntityItem::DEFAULT_AZIMUTH_FINISH = PI; // "" const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, -9.8f, 0.0f); -const float ParticleEffectEntityItem::MINIMUM_EMIT_ACCELERATION = -100.0f; // ~ 10g -const float ParticleEffectEntityItem::MAXIMUM_EMIT_ACCELERATION = 100.0f; const glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f); -const float ParticleEffectEntityItem::MINIMUM_ACCELERATION_SPREAD = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_ACCELERATION_SPREAD = 100.0f; const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; -const float ParticleEffectEntityItem::MINIMUM_PARTICLE_RADIUS = 0.0f; -const float ParticleEffectEntityItem::MAXIMUM_PARTICLE_RADIUS = (float)TREE_SCALE; const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS; const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS; @@ -135,82 +114,37 @@ ParticleEffectEntityItem::~ParticleEffectEntityItem() { } -void ParticleEffectEntityItem::setAlphaStart(float alphaStart) { - _alphaStart = glm::clamp(alphaStart, MINIMUM_ALPHA, MAXIMUM_ALPHA); - _isAlphaStartInitialized = true; -} - -void ParticleEffectEntityItem::setAlphaFinish(float alphaFinish) { - _alphaFinish = glm::clamp(alphaFinish, MINIMUM_ALPHA, MAXIMUM_ALPHA); - _isAlphaFinishInitialized = true; -} - void ParticleEffectEntityItem::setEmitSpeed(float emitSpeed) { - _emitSpeed = glm::clamp(emitSpeed, MINIMUM_EMIT_SPEED, MAXIMUM_EMIT_SPEED); + _emitSpeed = emitSpeed; computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setSpeedSpread(float speedSpread) { - _speedSpread = glm::clamp(speedSpread, MINIMUM_EMIT_SPEED, MAXIMUM_EMIT_SPEED); + _speedSpread = speedSpread; computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setEmitOrientation(const glm::quat& emitOrientation) { - _emitOrientation = glm::normalize(emitOrientation); + _emitOrientation = emitOrientation; computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setEmitDimensions(const glm::vec3& emitDimensions) { - _emitDimensions = glm::vec3( - glm::clamp(emitDimensions.x, MINIMUM_EMIT_DIMENSION, MAXIMUM_EMIT_DIMENSION), - glm::clamp(emitDimensions.y, MINIMUM_EMIT_DIMENSION, MAXIMUM_EMIT_DIMENSION), - glm::clamp(emitDimensions.z, MINIMUM_EMIT_DIMENSION, MAXIMUM_EMIT_DIMENSION) - ); + _emitDimensions = emitDimensions; computeAndUpdateDimensions(); } -void ParticleEffectEntityItem::setEmitRadiusStart(float emitRadiusStart) { - _emitRadiusStart = glm::clamp(emitRadiusStart, MINIMUM_EMIT_RADIUS_START, MAXIMUM_EMIT_RADIUS_START); -} - void ParticleEffectEntityItem::setEmitAcceleration(const glm::vec3& emitAcceleration) { - _emitAcceleration = glm::vec3( - glm::clamp(emitAcceleration.x, MINIMUM_EMIT_ACCELERATION, MAXIMUM_EMIT_ACCELERATION), - glm::clamp(emitAcceleration.x, MINIMUM_EMIT_ACCELERATION, MAXIMUM_EMIT_ACCELERATION), - glm::clamp(emitAcceleration.y, MINIMUM_EMIT_ACCELERATION, MAXIMUM_EMIT_ACCELERATION) - ); + _emitAcceleration = emitAcceleration; computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setAccelerationSpread(const glm::vec3& accelerationSpread){ - _accelerationSpread = glm::vec3( - glm::clamp(accelerationSpread.x, MINIMUM_ACCELERATION_SPREAD, MAXIMUM_ACCELERATION_SPREAD), - glm::clamp(accelerationSpread.x, MINIMUM_ACCELERATION_SPREAD, MAXIMUM_ACCELERATION_SPREAD), - glm::clamp(accelerationSpread.y, MINIMUM_ACCELERATION_SPREAD, MAXIMUM_ACCELERATION_SPREAD) - ); + _accelerationSpread = accelerationSpread; computeAndUpdateDimensions(); } -void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { - _particleRadius = glm::clamp(particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); -} - -void ParticleEffectEntityItem::setRadiusStart(float radiusStart) { - _radiusStart = glm::clamp(radiusStart, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - _isRadiusStartInitialized = true; -} - -void ParticleEffectEntityItem::setRadiusFinish(float radiusFinish) { - _radiusFinish = glm::clamp(radiusFinish, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - _isRadiusFinishInitialized = true; -} - -void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) { - _radiusSpread = glm::clamp(radiusSpread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); -} - - void ParticleEffectEntityItem::computeAndUpdateDimensions() { const float time = _lifespan * 1.1f; // add 10% extra time to account for incremental timer accumulation error @@ -351,7 +285,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch } READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); - READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, float, setMaxParticles); + READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); if (args.bitstreamVersion < VERSION_ENTITIES_PARTICLE_ELLIPSOID_EMITTER) { @@ -705,12 +639,12 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particleLifetimes[i] -= deltaTime; // if particle has died. - if (_particleLifetimes[i] <= 0.0f || _lifespan == 0.0f) { + if (_particleLifetimes[i] <= 0.0f) { // move head forward _particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles; } else { - float age = 1.0f - _particleLifetimes[i] / _lifespan; // 0.0 .. 1.0 + float age = (1.0f - _particleLifetimes[i] / _lifespan); // 0.0 .. 1.0 updateRadius(i, age); updateColor(i, age); updateAlpha(i, age); @@ -720,7 +654,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } // emit new particles, but only if animation is playing - if (getAnimationIsPlaying() && _emitRate > 0.0f && _lifespan > 0.0f && _polarStart <= _polarFinish) { + if (getAnimationIsPlaying()) { float timeLeftInFrame = deltaTime; while (_timeUntilNextEmit < timeLeftInFrame) { @@ -738,18 +672,10 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _radiusMiddles[i] =_particleRadius; _radiusFinishes[i] = getRadiusFinish(); } else { - float spreadMultiplier; - if (_particleRadius > 0.0f) { - spreadMultiplier = 1.0f + (2.0f * randFloat() - 1.0f) * _radiusSpread / _particleRadius; - } else { - spreadMultiplier = 0.0f; - } - _radiusStarts[i] = - glm::clamp(spreadMultiplier * getRadiusStart(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - _radiusMiddles[i] = - glm::clamp(spreadMultiplier * _particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - _radiusFinishes[i] = - glm::clamp(spreadMultiplier * getRadiusFinish(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + float spreadMultiplier = 1.0f + (2.0f * randFloat() - 1.0f) * _radiusSpread / _particleRadius; + _radiusStarts[i] = spreadMultiplier * getRadiusStart(); + _radiusMiddles[i] = spreadMultiplier * _particleRadius; + _radiusFinishes[i] = spreadMultiplier * getRadiusFinish(); } updateRadius(i, 0.0f); @@ -827,12 +753,9 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { xColor finishColor = getColorFinish(); float spread = 2.0f * randFloat() - 1.0f; - float spreadMultiplierRed = - middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; - float spreadMultiplierGreen = - middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green :1.0f; - float spreadMultiplierBlue = - middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; + float spreadMultiplierRed = 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red; + float spreadMultiplierGreen = 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green; + float spreadMultiplierBlue = 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue; _colorStarts[i].red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); _colorStarts[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); @@ -875,10 +798,9 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } } -void ParticleEffectEntityItem::setMaxParticles(float maxParticles) { - maxParticles = glm::clamp(maxParticles, (float)MINIMUM_MAX_PARTICLES, (float)MAXIMUM_MAX_PARTICLES); - if (_maxParticles != (quint32)maxParticles) { - _maxParticles = (quint32)maxParticles; +void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { + if (_maxParticles != maxParticles) { + _maxParticles = maxParticles; // TODO: try to do something smart here and preserve the state of existing particles. diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 14b60ce4e2..6d5b8761b0 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -12,7 +12,6 @@ #define hifi_ParticleEffectEntityItem_h #include - #include "EntityItem.h" class ParticleEffectEntityItem : public EntityItem { @@ -69,25 +68,22 @@ public: void setColorSpread(const xColor& colorSpread) { _colorSpread = colorSpread; } xColor getColorSpread() const { return _colorSpread; } - static const float MAXIMUM_ALPHA; - static const float MINIMUM_ALPHA; - static const float DEFAULT_ALPHA; - void setAlpha(float alpha) { _alpha = glm::clamp(alpha, MINIMUM_ALPHA, MAXIMUM_ALPHA); } + void setAlpha(float alpha) { _alpha = alpha; } float getAlpha() const { return _alpha; } static const float DEFAULT_ALPHA_START; bool _isAlphaStartInitialized = false; - void setAlphaStart(float alphaStart); + void setAlphaStart(float alphaStart) { _alphaStart = alphaStart; _isAlphaStartInitialized = true; } float getAlphaStart() const { return _isAlphaStartInitialized ? _alphaStart : _alpha; } static const float DEFAULT_ALPHA_FINISH; bool _isAlphaFinishInitialized = false; - void setAlphaFinish(float alphaFinish); + void setAlphaFinish(float alphaFinish) { _alphaFinish = alphaFinish; _isAlphaFinishInitialized = true; } float getAlphaFinish() const { return _isAlphaFinishInitialized ? _alphaFinish : _alpha; } static const float DEFAULT_ALPHA_SPREAD; - void setAlphaSpread(float alphaSpread) { _alphaSpread = glm::clamp(alphaSpread, MINIMUM_ALPHA, MAXIMUM_ALPHA); } + void setAlphaSpread(float alphaSpread) { _alphaSpread = alphaSpread; } float getAlphaSpread() const { return _alphaSpread; } void updateShapeType(ShapeType type); @@ -121,26 +117,18 @@ public: float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } static const quint32 DEFAULT_MAX_PARTICLES; - static const quint32 MINIMUM_MAX_PARTICLES; - static const quint32 MAXIMUM_MAX_PARTICLES; - void setMaxParticles(float maxParticles); - float getMaxParticles() const { return (float)_maxParticles; } + void setMaxParticles(quint32 maxParticles); + quint32 getMaxParticles() const { return _maxParticles; } static const float DEFAULT_LIFESPAN; - static const float MINIMUM_LIFESPAN; - static const float MAXIMUM_LIFESPAN; - void setLifespan(float lifespan) { _lifespan = glm::clamp(lifespan, MINIMUM_LIFESPAN, MAXIMUM_LIFESPAN); } + void setLifespan(float lifespan) { _lifespan = lifespan; } float getLifespan() const { return _lifespan; } static const float DEFAULT_EMIT_RATE; - static const float MINIMUM_EMIT_RATE; - static const float MAXIMUM_EMIT_RATE; - void setEmitRate(float emitRate) { _emitRate = glm::clamp(emitRate, MINIMUM_EMIT_RATE, MAXIMUM_EMIT_RATE); } + void setEmitRate(float emitRate) { _emitRate = emitRate; } float getEmitRate() const { return _emitRate; } static const float DEFAULT_EMIT_SPEED; - static const float MINIMUM_EMIT_SPEED; - static const float MAXIMUM_EMIT_SPEED; void setEmitSpeed(float emitSpeed); float getEmitSpeed() const { return _emitSpeed; } @@ -153,69 +141,53 @@ public: const glm::quat& getEmitOrientation() const { return _emitOrientation; } static const glm::vec3 DEFAULT_EMIT_DIMENSIONS; - static const float MINIMUM_EMIT_DIMENSION; - static const float MAXIMUM_EMIT_DIMENSION; void setEmitDimensions(const glm::vec3& emitDimensions); const glm::vec3& getEmitDimensions() const { return _emitDimensions; } static const float DEFAULT_EMIT_RADIUS_START; - static const float MINIMUM_EMIT_RADIUS_START; - static const float MAXIMUM_EMIT_RADIUS_START; - void setEmitRadiusStart(float emitRadiusStart); + void setEmitRadiusStart(float emitRadiusStart) { _emitRadiusStart = emitRadiusStart; } float getEmitRadiusStart() const { return _emitRadiusStart; } - static const float MINIMUM_POLAR; - static const float MAXIMUM_POLAR; - static const float DEFAULT_POLAR_START; - void setPolarStart(float polarStart) { _polarStart = glm::clamp(polarStart, MINIMUM_POLAR, MAXIMUM_POLAR); } + void setPolarStart(float polarStart) { _polarStart = polarStart; } float getPolarStart() const { return _polarStart; } static const float DEFAULT_POLAR_FINISH; - void setPolarFinish(float polarFinish) { _polarFinish = glm::clamp(polarFinish, MINIMUM_POLAR, MAXIMUM_POLAR); } + void setPolarFinish(float polarFinish) { _polarFinish = polarFinish; } float getPolarFinish() const { return _polarFinish; } - static const float MINIMUM_AZIMUTH; - static const float MAXIMUM_AZIMUTH; - static const float DEFAULT_AZIMUTH_START; - void setAzimuthStart(float azimuthStart) { _azimuthStart = glm::clamp(azimuthStart, MINIMUM_AZIMUTH, MAXIMUM_AZIMUTH); } + void setAzimuthStart(float azimuthStart) { _azimuthStart = azimuthStart; } float getAzimuthStart() const { return _azimuthStart; } static const float DEFAULT_AZIMUTH_FINISH; - void setAzimuthFinish(float azimuthFinish) { _azimuthFinish = glm::clamp(azimuthFinish, MINIMUM_AZIMUTH, MAXIMUM_AZIMUTH); } + void setAzimuthFinish(float azimuthFinish) { _azimuthFinish = azimuthFinish; } float getAzimuthFinish() const { return _azimuthFinish; } static const glm::vec3 DEFAULT_EMIT_ACCELERATION; - static const float MINIMUM_EMIT_ACCELERATION; - static const float MAXIMUM_EMIT_ACCELERATION; void setEmitAcceleration(const glm::vec3& emitAcceleration); const glm::vec3& getEmitAcceleration() const { return _emitAcceleration; } static const glm::vec3 DEFAULT_ACCELERATION_SPREAD; - static const float MINIMUM_ACCELERATION_SPREAD; - static const float MAXIMUM_ACCELERATION_SPREAD; void setAccelerationSpread(const glm::vec3& accelerationSpread); const glm::vec3& getAccelerationSpread() const { return _accelerationSpread; } static const float DEFAULT_PARTICLE_RADIUS; - static const float MINIMUM_PARTICLE_RADIUS; - static const float MAXIMUM_PARTICLE_RADIUS; - void setParticleRadius(float particleRadius); + void setParticleRadius(float particleRadius) { _particleRadius = particleRadius; } float getParticleRadius() const { return _particleRadius; } static const float DEFAULT_RADIUS_START; bool _isRadiusStartInitialized = false; - void setRadiusStart(float radiusStart); + void setRadiusStart(float radiusStart) { _radiusStart = radiusStart; _isRadiusStartInitialized = true; } float getRadiusStart() const { return _isRadiusStartInitialized ? _radiusStart : _particleRadius; } static const float DEFAULT_RADIUS_FINISH; bool _isRadiusFinishInitialized = false; - void setRadiusFinish(float radiusFinish); + void setRadiusFinish(float radiusFinish) { _radiusFinish = radiusFinish; _isRadiusFinishInitialized = true; } float getRadiusFinish() const { return _isRadiusFinishInitialized ? _radiusFinish : _particleRadius; } static const float DEFAULT_RADIUS_SPREAD; - void setRadiusSpread(float radiusSpread); + void setRadiusSpread(float radiusSpread) { _radiusSpread = radiusSpread; } float getRadiusSpread() const { return _radiusSpread; } void computeAndUpdateDimensions(); From 598aab884eef819467c71a65635732e06ca4a72b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 5 Oct 2015 14:59:28 -0700 Subject: [PATCH 20/20] Make log more readable --- libraries/shared/src/LogHandler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index d1f23531cb..22ea12c1b3 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -120,11 +120,11 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont } // log prefix is in the following format - // [DEBUG] [TIMESTAMP] [PID] [TARGET] logged string + // [TIMESTAMP] [DEBUG] [PID] [TARGET] logged string - QString prefixString = QString("[%1]").arg(stringForLogType(type)); + QString prefixString = QString("[%1]").arg(QDateTime::currentDateTime().toString(DATE_STRING_FORMAT)); - prefixString.append(QString(" [%1]").arg(QDateTime::currentDateTime().toString(DATE_STRING_FORMAT))); + prefixString.append(QString(" [%1]").arg(stringForLogType(type))); if (_shouldOutputPID) { prefixString.append(QString(" [%1]").arg(QCoreApplication::instance()->applicationPid()));