diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index e534c7b418..4f29b829f5 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -145,6 +145,7 @@ public: }; Q_DECLARE_METATYPE(ParticleID); +Q_DECLARE_METATYPE(QVector); QScriptValue ParticleIDtoScriptValue(QScriptEngine* engine, const ParticleID& properties); void ParticleIDfromScriptValue(const QScriptValue &object, ParticleID& properties); diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index 73e8dd6711..015c34ce12 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -160,6 +160,42 @@ const Particle* ParticleTree::findClosestParticle(glm::vec3 position, float targ return args.closestParticle; } +class FindAllNearPointArgs { +public: + glm::vec3 position; + float targetRadius; + QVector particles; +}; + + +bool ParticleTree::findInSphereOperation(OctreeElement* element, void* extraData) { + FindAllNearPointArgs* args = static_cast(extraData); + ParticleTreeElement* particleTreeElement = static_cast(element); + + glm::vec3 penetration; + bool sphereIntersection = particleTreeElement->getAABox().findSpherePenetration(args->position, + args->targetRadius, penetration); + + // If this particleTreeElement contains the point, then search it... + if (sphereIntersection) { + QVector moreParticles = particleTreeElement->getParticles(args->position, args->targetRadius); + args->particles << moreParticles; + return true; // keep searching in case children have closer particles + } + + // if this element doesn't contain the point, then none of it's children can contain the point, so stop searching + return false; +} + +QVector ParticleTree::findParticles(const glm::vec3& center, float radius) { + QVector result; + FindAllNearPointArgs args = { center, radius }; + lockForRead(); + recurseTreeWithOperation(findInSphereOperation, &args); + unlock(); + return args.particles; +} + class FindByIDArgs { public: uint32_t id; diff --git a/libraries/particles/src/ParticleTree.h b/libraries/particles/src/ParticleTree.h index 33e5d5fe75..b8089a1a0e 100644 --- a/libraries/particles/src/ParticleTree.h +++ b/libraries/particles/src/ParticleTree.h @@ -42,6 +42,7 @@ public: void storeParticle(const Particle& particle, Node* senderNode = NULL); const Particle* findClosestParticle(glm::vec3 position, float targetRadius); const Particle* findParticleByID(uint32_t id, bool alreadyLocked = false); + QVector findParticles(const glm::vec3& center, float radius); void addNewlyCreatedHook(NewlyCreatedParticleHook* hook); void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook); @@ -58,6 +59,7 @@ private: static bool updateOperation(OctreeElement* element, void* extraData); static bool findAndUpdateOperation(OctreeElement* element, void* extraData); static bool findNearPointOperation(OctreeElement* element, void* extraData); + static bool findInSphereOperation(OctreeElement* element, void* extraData); static bool pruneOperation(OctreeElement* element, void* extraData); static bool findByIDOperation(OctreeElement* element, void* extraData); static bool findAndDeleteOperation(OctreeElement* element, void* extraData); diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index 7994909004..fd52eb07ee 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -185,6 +185,23 @@ const Particle* ParticleTreeElement::getClosestParticle(glm::vec3 position) cons return closestParticle; } +QVector ParticleTreeElement::getParticles(glm::vec3 searchPosition, float searchRadius) const { + QVector results; + uint16_t numberOfParticles = _particles->size(); + for (uint16_t i = 0; i < numberOfParticles; i++) { + const Particle* particle = &(*_particles)[i]; + glm::vec3 particlePosition = particle->getPosition(); + float particleRadius = particle->getRadius(); + glm::vec3 penetration; + + // check to see that the particle (penetrator) penetrates the search area + if (findSphereSpherePenetration(particlePosition, particleRadius, searchPosition, searchRadius, penetration)) { + results << particle; + } + } + return results; +} + const Particle* ParticleTreeElement::getParticleWithID(uint32_t id) const { // NOTE: this lookup is O(N) but maybe we don't care? (guaranteed that num particles per elemen is small?) const Particle* foundParticle = NULL; diff --git a/libraries/particles/src/ParticleTreeElement.h b/libraries/particles/src/ParticleTreeElement.h index 8493d59bb8..7318f115c1 100644 --- a/libraries/particles/src/ParticleTreeElement.h +++ b/libraries/particles/src/ParticleTreeElement.h @@ -89,6 +89,7 @@ public: bool containsParticle(const Particle& particle) const; bool updateParticle(const Particle& particle); const Particle* getClosestParticle(glm::vec3 position) const; + QVector getParticles(glm::vec3 position, float radius) const; const Particle* getParticleWithID(uint32_t id) const; bool removeParticleWithID(uint32_t id); diff --git a/libraries/particles/src/ParticlesScriptingInterface.cpp b/libraries/particles/src/ParticlesScriptingInterface.cpp index 14388b6ac4..a494cc2dab 100644 --- a/libraries/particles/src/ParticlesScriptingInterface.cpp +++ b/libraries/particles/src/ParticlesScriptingInterface.cpp @@ -34,15 +34,28 @@ ParticleID ParticlesScriptingInterface::addParticle(const ParticleProperties& pr return id; } -void ParticlesScriptingInterface::editParticle(ParticleID particleID, const ParticleProperties& properties) { +ParticleID ParticlesScriptingInterface::identifyParticle(ParticleID particleID) { uint32_t actualID = particleID.id; if (!particleID.isKnownID) { actualID = Particle::getIDfromCreatorTokenID(particleID.creatorTokenID); - // hmmm... we kind of want to bail if someone attempts to edit an unknown if (actualID == UNKNOWN_PARTICLE_ID) { - //qDebug() << "ParticlesScriptingInterface::editParticle()... BAILING!!! particleID.creatorTokenID=" - // << particleID.creatorTokenID; - return; // bailing early + return particleID; // bailing early + } + + // found it! + particleID.id = actualID; + particleID.isKnownID = true; + } + return particleID; +} + + +ParticleID ParticlesScriptingInterface::editParticle(ParticleID particleID, const ParticleProperties& properties) { + uint32_t actualID = particleID.id; + if (!particleID.isKnownID) { + actualID = Particle::getIDfromCreatorTokenID(particleID.creatorTokenID); + if (actualID == UNKNOWN_PARTICLE_ID) { + return particleID; // bailing early } } @@ -71,6 +84,7 @@ void ParticlesScriptingInterface::editParticle(ParticleID particleID, const Part } } queueParticleMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, particleID, properties); + return particleID; } @@ -116,3 +130,17 @@ ParticleID ParticlesScriptingInterface::findClosestParticle(const glm::vec3& cen return result; } + +QVector ParticlesScriptingInterface::findParticles(const glm::vec3& center, float radius) const { + QVector result; + if (_particleTree) { + QVector particles = _particleTree->findParticles(center/(float)TREE_SCALE, radius/(float)TREE_SCALE); + + foreach (const Particle* particle, particles) { + ParticleID thisParticleID(particle->getID(), UNKNOWN_TOKEN, true); + result << thisParticleID; + } + } + return result; +} + diff --git a/libraries/particles/src/ParticlesScriptingInterface.h b/libraries/particles/src/ParticlesScriptingInterface.h index d61f8289f4..2ba7c509e0 100644 --- a/libraries/particles/src/ParticlesScriptingInterface.h +++ b/libraries/particles/src/ParticlesScriptingInterface.h @@ -28,11 +28,29 @@ public: ParticleTree* getParticleTree(ParticleTree*) { return _particleTree; } public slots: + /// adds a particle with the specific properties ParticleID addParticle(const ParticleProperties& properties); - void editParticle(ParticleID particleID, const ParticleProperties& properties); + + /// identify a recently created particle to determine its true ID + ParticleID identifyParticle(ParticleID particleID); + + /// edits a particle updating only the included properties, will return the identified ParticleID in case of + /// successful edit, if the input particleID is for an unknown particle this function will have no effect + ParticleID editParticle(ParticleID particleID, const ParticleProperties& properties); + + /// deletes a particle void deleteParticle(ParticleID particleID); + + /// finds the closest particle to the center point, within the radius + /// will return a ParticleID.isKnownID = false if no particles are in the radius + /// this function will not find any particles in script engine contexts which don't have access to particles ParticleID findClosestParticle(const glm::vec3& center, float radius) const; + /// finds particles within the search sphere specified by the center point and radius + /// this function will not find any particles in script engine contexts which don't have access to particles + QVector findParticles(const glm::vec3& center, float radius) const; + + private: void queueParticleMessage(PACKET_TYPE packetType, ParticleID particleID, const ParticleProperties& properties); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index f77b428764..1bf8dbf696 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -118,6 +118,7 @@ void ScriptEngine::init() { registerMetaTypes(&_engine); qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue); qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue); + qScriptRegisterSequenceMetaType >(&_engine); QScriptValue agentValue = _engine.newQObject(this); _engine.globalObject().setProperty("Agent", agentValue);