From 2bc7896dee2d94f85707958a0c76f44448a29363 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Nov 2014 13:46:48 -0800 Subject: [PATCH 1/3] first cut at preload script behavior --- examples/entityScripts/playSoundOnClick.js | 22 ++++++++++++++----- .../entityScripts/playSoundOnEnterOrLeave.js | 9 ++++++-- interface/src/entities/EntityTreeRenderer.cpp | 18 +++++++++++++++ interface/src/entities/EntityTreeRenderer.h | 2 ++ libraries/entities/src/EntityTree.cpp | 15 ++++++++++++- libraries/entities/src/EntityTree.h | 6 +++++ libraries/entities/src/EntityTreeElement.cpp | 3 ++- 7 files changed, 65 insertions(+), 10 deletions(-) diff --git a/examples/entityScripts/playSoundOnClick.js b/examples/entityScripts/playSoundOnClick.js index b261bb269a..4bc523a7aa 100644 --- a/examples/entityScripts/playSoundOnClick.js +++ b/examples/entityScripts/playSoundOnClick.js @@ -12,13 +12,23 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // (function(){ - var bird = new Sound("http://s3.amazonaws.com/hifi-public/sounds/Animals/bushtit_1.raw"); + var bird; + + function playSound(entityID) { + var options = new AudioInjectionOptions(); + var position = MyAvatar.position; + options.position = position; + options.volume = 0.5; + Audio.playSound(bird, options); + }; + + this.preload = function(entityID) { + print("preload("+entityID.id+")"); + bird = new Sound("http://s3.amazonaws.com/hifi-public/sounds/Animals/bushtit_1.raw"); + }; + this.clickDownOnEntity = function(entityID, mouseEvent) { print("clickDownOnEntity()..."); - var options = new AudioInjectionOptions(); - var position = MyAvatar.position; - options.position = position; - options.volume = 0.5; - Audio.playSound(bird, options); + playSound(); }; }) diff --git a/examples/entityScripts/playSoundOnEnterOrLeave.js b/examples/entityScripts/playSoundOnEnterOrLeave.js index 228a8a36d0..98702dcfdd 100644 --- a/examples/entityScripts/playSoundOnEnterOrLeave.js +++ b/examples/entityScripts/playSoundOnEnterOrLeave.js @@ -12,9 +12,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // (function(){ - var bird = new Sound("http://s3.amazonaws.com/hifi-public/sounds/Animals/bushtit_1.raw"); + var bird; - function playSound(entityID) { + function playSound() { var options = new AudioInjectionOptions(); var position = MyAvatar.position; options.position = position; @@ -22,6 +22,11 @@ Audio.playSound(bird, options); }; + this.preload = function(entityID) { + print("preload("+entityID.id+")"); + bird = new Sound("http://s3.amazonaws.com/hifi-public/sounds/Animals/bushtit_1.raw"); + }; + this.enterEntity = function(entityID) { playSound(); }; diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 2f8ddb1095..ae94b5f973 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -81,6 +81,8 @@ void EntityTreeRenderer::init() { _lastAvatarPosition = avatarPosition + glm::vec3(1.f, 1.f, 1.f); connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity); + connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity); + connect(entityTree, &EntityTree::changingEntityID, this, &EntityTreeRenderer::changingEntityID); } QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID) { @@ -770,3 +772,19 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { _entityScripts.remove(entityID); } +void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { + qDebug() << "addingEntity() entityID:" << entityID; + + // load the entity script if needed... + QScriptValue entityScript = loadEntityScript(entityID); + if (entityScript.property("preload").isValid()) { + QScriptValueList entityArgs = createEntityArgs(entityID); + entityScript.property("preload").call(entityScript, entityArgs); + } + +} + +void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID) { + qDebug() << "changingEntityID() oldEntityID:" << oldEntityID << "newEntityID:" << newEntityID; +} + diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index ff9066dd6d..c7068fac86 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -104,6 +104,8 @@ signals: public slots: void deletingEntity(const EntityItemID& entityID); + void addingEntity(const EntityItemID& entityID); + void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID); private: QList _releasedModels; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 199bd92030..aa7405164e 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -168,6 +168,7 @@ EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItem if (result) { // this does the actual adding of the entity addEntityItem(result); + emitAddingEntity(entityID); } return result; } @@ -184,6 +185,14 @@ void EntityTree::trackDeletedEntity(const EntityItemID& entityID) { } } +void EntityTree::emitAddingEntity(const EntityItemID& entityItemID) { + emit addingEntity(entityItemID); +} + +void EntityTree::emitEntityScriptChanging(const EntityItemID& entityItemID) { + emit entityScriptChanging(entityItemID); +} + void EntityTree::deleteEntity(const EntityItemID& entityID) { emit deletingEntity(entityID); @@ -290,6 +299,7 @@ void EntityTree::handleAddEntityResponse(const QByteArray& packet) { EntityItemID creatorTokenVersion = searchEntityID.convertToCreatorTokenVersion(); EntityItemID knownIDVersion = searchEntityID.convertToKnownIDVersion(); + // First look for and find the "viewed version" of this entity... it's possible we got // the known ID version sent to us between us creating our local version, and getting this // remapping message. If this happened, we actually want to find and delete that version of @@ -310,6 +320,10 @@ void EntityTree::handleAddEntityResponse(const QByteArray& packet) { creatorTokenContainingElement->updateEntityItemID(creatorTokenVersion, knownIDVersion); setContainingElement(creatorTokenVersion, NULL); setContainingElement(knownIDVersion, creatorTokenContainingElement); + + // because the ID of the entity is switching, we need to emit these signals for any + // listeners who care about the changing of IDs + emit changingEntityID(creatorTokenVersion, knownIDVersion); } } unlock(); @@ -981,7 +995,6 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons return processedBytes; } - EntityTreeElement* EntityTree::getContainingElement(const EntityItemID& entityItemID) /*const*/ { // TODO: do we need to make this thread safe? Or is it acceptable as is if (_entityToElementMap.contains(entityItemID)) { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 8d1acc0d01..6fe2d256c2 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -140,10 +140,16 @@ public: void trackDeletedEntity(const EntityItemID& entityID); + void emitAddingEntity(const EntityItemID& entityItemID); + void emitEntityScriptChanging(const EntityItemID& entityItemID); + QList& getMovingEntities() { return _movingEntities; } signals: void deletingEntity(const EntityItemID& entityID); + void addingEntity(const EntityItemID& entityID); + void entityScriptChanging(const EntityItemID& entityItemID); + void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID); private: diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 079fb1bba7..e419187cb6 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -726,7 +726,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int entityItemID = EntityItemID::readEntityItemIDFromBuffer(dataAt, bytesLeftToRead); entityItem = _myTree->findEntityByEntityItemID(entityItemID); } - + // If the item already exists in our tree, we want do the following... // 1) allow the existing item to read from the databuffer // 2) check to see if after reading the item, the containing element is still correct, fix it if needed @@ -762,6 +762,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int addEntityItem(entityItem); // add this new entity to this elements entities entityItemID = entityItem->getEntityItemID(); _myTree->setContainingElement(entityItemID, this); + _myTree->emitAddingEntity(entityItemID); // we just added an entity EntityItem::SimulationState newState = entityItem->getSimulationState(); _myTree->changeEntityState(entityItem, EntityItem::Static, newState); } From 8ec3f8ce991efa9c685ce9a5f91a2695f989eb49 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Nov 2014 14:21:06 -0800 Subject: [PATCH 2/3] implement support for calling preload when the script changes --- examples/entityScripts/changeColorOnHover.js | 8 ++++++++ interface/src/entities/EntityTreeRenderer.cpp | 13 ++++++++----- interface/src/entities/EntityTreeRenderer.h | 2 +- libraries/entities/src/EntityTree.cpp | 7 +++++++ libraries/entities/src/EntityTreeElement.cpp | 9 +++++++++ 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/examples/entityScripts/changeColorOnHover.js b/examples/entityScripts/changeColorOnHover.js index de3f5f3784..638c1bece4 100644 --- a/examples/entityScripts/changeColorOnHover.js +++ b/examples/entityScripts/changeColorOnHover.js @@ -22,13 +22,21 @@ this.oldColorKnown = true; print("storing old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); }; + + this.preload = function(entityID) { + print("preload"); + this.storeOldColor(entityID); + }; + this.hoverEnterEntity = function(entityID, mouseEvent) { + print("hoverEnterEntity"); if (!this.oldColorKnown) { this.storeOldColor(entityID); } Entities.editEntity(entityID, { color: { red: 0, green: 255, blue: 255} }); }; this.hoverLeaveEntity = function(entityID, mouseEvent) { + print("hoverLeaveEntity"); if (this.oldColorKnown) { print("leave restoring old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index ae94b5f973..c371c015ba 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -81,7 +81,8 @@ void EntityTreeRenderer::init() { _lastAvatarPosition = avatarPosition + glm::vec3(1.f, 1.f, 1.f); connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity); - connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity); + connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::checkAndCallPreload); + connect(entityTree, &EntityTree::entityScriptChanging, this, &EntityTreeRenderer::checkAndCallPreload); connect(entityTree, &EntityTree::changingEntityID, this, &EntityTreeRenderer::changingEntityID); } @@ -772,9 +773,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { _entityScripts.remove(entityID); } -void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { - qDebug() << "addingEntity() entityID:" << entityID; - +void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID) { // load the entity script if needed... QScriptValue entityScript = loadEntityScript(entityID); if (entityScript.property("preload").isValid()) { @@ -785,6 +784,10 @@ void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { } void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID) { - qDebug() << "changingEntityID() oldEntityID:" << oldEntityID << "newEntityID:" << newEntityID; + if (_entityScripts.contains(oldEntityID)) { + EntityScriptDetails details = _entityScripts[oldEntityID]; + _entityScripts.remove(oldEntityID); + _entityScripts[newEntityID] = details; + } } diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index c7068fac86..7c1c81b6c9 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -104,8 +104,8 @@ signals: public slots: void deletingEntity(const EntityItemID& entityID); - void addingEntity(const EntityItemID& entityID); void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID); + void checkAndCallPreload(const EntityItemID& entityID); private: QList _releasedModels; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index aa7405164e..bc2823e15c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -124,6 +124,7 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp } else { // check to see if we need to simulate this entity... EntityItem::SimulationState oldState = existingEntity->getSimulationState(); + QString entityScriptBefore = existingEntity->getScript(); UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties); recurseTreeWithOperator(&theOperator); @@ -131,6 +132,12 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp EntityItem::SimulationState newState = existingEntity->getSimulationState(); changeEntityState(existingEntity, oldState, newState); + + QString entityScriptAfter = existingEntity->getScript(); + if (entityScriptBefore != entityScriptAfter) { + emitEntityScriptChanging(entityID); // the entity script has changed + } + } containingElement = getContainingElement(entityID); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index e419187cb6..1dea2bcd85 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -734,10 +734,13 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int // TODO: Do we need to also do this? // 3) remember the old cube for the entity so we can mark it as dirty if (entityItem) { + QString entityScriptBefore = entityItem->getScript(); bool bestFitBefore = bestFitEntityBounds(entityItem); EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); EntityItem::SimulationState oldState = entityItem->getSimulationState(); + bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); + EntityItem::SimulationState newState = entityItem->getSimulationState(); if (oldState != newState) { _myTree->changeEntityState(entityItem, oldState, newState); @@ -755,6 +758,12 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int } } } + + QString entityScriptAfter = entityItem->getScript(); + if (entityScriptBefore != entityScriptAfter) { + _myTree->emitEntityScriptChanging(entityItemID); // the entity script has changed + } + } else { entityItem = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead, args); if (entityItem) { From 8975fbe1ee49ec98cb8f165e81a06a2e6887e202 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Nov 2014 14:26:45 -0800 Subject: [PATCH 3/3] removed blank line --- interface/src/entities/EntityTreeRenderer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index c371c015ba..1876b6c624 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -780,7 +780,6 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID) { QScriptValueList entityArgs = createEntityArgs(entityID); entityScript.property("preload").call(entityScript, entityArgs); } - } void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID) {