From f4b28041fa6c5906923999029fb8131a40eedf20 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 30 Dec 2013 14:59:00 -0800 Subject: [PATCH] first cut at running scripts on particle collisions --- libraries/particles/src/Particle.cpp | 56 ++++++++++++++----- libraries/particles/src/Particle.h | 19 +++++-- .../particles/src/ParticleCollisionSystem.cpp | 5 ++ 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index f2ee1c1fb4..9f5af61042 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -53,8 +53,9 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 _velocity = velocity; _damping = damping; _gravity = gravity; - _updateScript = updateScript; + _script = updateScript; _inHand = inHand; + _shouldDie = false; } @@ -95,10 +96,10 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { success = packetData->appendValue(getInHand()); } if (success) { - uint16_t scriptLength = _updateScript.size() + 1; // include NULL + uint16_t scriptLength = _script.size() + 1; // include NULL success = packetData->appendValue(scriptLength); if (success) { - success = packetData->appendRawData((const unsigned char*)qPrintable(_updateScript), scriptLength); + success = packetData->appendRawData((const unsigned char*)qPrintable(_script), scriptLength); } } return success; @@ -206,7 +207,7 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += sizeof(scriptLength); bytesRead += sizeof(scriptLength); QString tempString((const char*)dataAt); - _updateScript = tempString; + _script = tempString; dataAt += scriptLength; bytesRead += scriptLength; @@ -299,7 +300,7 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe dataAt += sizeof(scriptLength); processedBytes += sizeof(scriptLength); QString tempString((const char*)dataAt); - newParticle._updateScript = tempString; + newParticle._script = tempString; dataAt += scriptLength; processedBytes += scriptLength; @@ -472,7 +473,7 @@ void Particle::update() { const float REALLY_OLD = 30.0f; // 30 seconds bool isReallyOld = (getLifetime() > REALLY_OLD); bool isInHand = getInHand(); - bool shouldDie = !isInHand && !isStillMoving && isReallyOld; + bool shouldDie = getShouldDie() || (!isInHand && !isStillMoving && isReallyOld); setShouldDie(shouldDie); const bool wantDebug = false; @@ -483,7 +484,7 @@ void Particle::update() { debug::valueOf(isReallyOld), debug::valueOf(shouldDie)); } - runScript(); // allow the javascript to alter our state + runUpdateScript(); // allow the javascript to alter our state // If the ball is in hand, it doesn't move or have gravity effect it if (!isInHand) { @@ -507,11 +508,9 @@ void Particle::update() { _lastUpdated = now; } -void Particle::runScript() { - if (!_updateScript.isEmpty()) { - - //qDebug() << "Script: " << _updateScript << "\n"; - +void Particle::runUpdateScript() { + if (!_script.isEmpty()) { + QScriptEngine engine; // register meta-type for glm::vec3 and rgbColor conversions @@ -524,9 +523,9 @@ void Particle::runScript() { QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); - //qDebug() << "Downloaded script:" << _updateScript << "\n"; - QScriptValue result = engine.evaluate(_updateScript); - //qDebug() << "Evaluated script.\n"; + QScriptValue result = engine.evaluate(_script); + + particleScriptable.emitUpdate(); if (engine.hasUncaughtException()) { int line = engine.uncaughtExceptionLineNumber(); @@ -535,6 +534,33 @@ void Particle::runScript() { } } +void Particle::collisionWithParticle(unsigned int otherID) { + if (!_script.isEmpty()) { + + QScriptEngine engine; + + // register meta-type for glm::vec3 and rgbColor conversions + registerMetaTypes(&engine); + + ParticleScriptObject particleScriptable(this); + QScriptValue particleValue = engine.newQObject(&particleScriptable); + engine.globalObject().setProperty("Particle", particleValue); + + QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); + engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); + + QScriptValue result = engine.evaluate(_script); + + particleScriptable.emitCollisionWithParticle(otherID); + + if (engine.hasUncaughtException()) { + int line = engine.uncaughtExceptionLineNumber(); + qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n"; + } + } +} + + void Particle::setLifetime(float lifetime) { uint64_t lifetimeInUsecs = lifetime * USECS_PER_SECOND; _created = usecTimestampNow() - lifetimeInUsecs; diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 0d50413b4f..51d7cd4a30 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -79,7 +79,7 @@ public: float getEditedAgo() const { return (float)(usecTimestampNow() - _lastEdited) / (float)USECS_PER_SECOND; } uint32_t getID() const { return _id; } bool getShouldDie() const { return _shouldDie; } - QString getUpdateScript() const { return _updateScript; } + QString getUpdateScript() const { return _script; } uint32_t getCreatorTokenID() const { return _creatorTokenID; } bool isNewlyCreated() const { return _newlyCreated; } @@ -96,7 +96,7 @@ public: void setInHand(bool inHand) { _inHand = inHand; } void setDamping(float value) { _damping = value; } void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; } - void setUpdateScript(QString updateScript) { _updateScript = updateScript; } + void setUpdateScript(QString updateScript) { _script = updateScript; } void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; } bool appendParticleData(OctreePacketData* packetData) const; @@ -110,6 +110,7 @@ public: static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew); void update(); + void collisionWithParticle(unsigned int otherID); void debugDump() const; @@ -117,7 +118,7 @@ public: void copyChangedProperties(const Particle& other); protected: - void runScript(); + void runUpdateScript(); static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3); static void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3); static QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color); @@ -134,7 +135,7 @@ protected: bool _shouldDie; glm::vec3 _gravity; float _damping; - QString _updateScript; + QString _script; bool _inHand; uint32_t _creatorTokenID; @@ -152,7 +153,12 @@ class ParticleScriptObject : public QObject { public: ParticleScriptObject(Particle* particle) { _particle = particle; } + void emitUpdate() { emit update(); } + void emitCollisionWithParticle(uint32_t otherID) { emit collisionWithParticle(otherID); } + void emitCollisionWithVoxel() { emit collisionWithVoxel(); } + public slots: + unsigned int getID() const { return _particle->getID(); } glm::vec3 getPosition() const { return _particle->getPosition(); } glm::vec3 getVelocity() const { return _particle->getVelocity(); } xColor getColor() const { return _particle->getXColor(); } @@ -170,6 +176,11 @@ public slots: void setRadius(float value) { _particle->setRadius(value); } void setShouldDie(bool value) { _particle->setShouldDie(value); } +signals: + void update(); + void collisionWithVoxel(); + void collisionWithParticle(unsigned int otherID); + private: Particle* _particle; }; diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index b3ad9a9740..c477804325 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -90,6 +90,11 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { glm::vec3 penetration; Particle* penetratedParticle; if (_particles->findSpherePenetration(center, radius, penetration, (void**)&penetratedParticle)) { + + // let the particles run their collision scripts if they have them + particle->collisionWithParticle(penetratedParticle->getID()); + penetratedParticle->collisionWithParticle(particle->getID()); + penetration /= (float)TREE_SCALE; updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); // apply a hard collision to both particles of half the penetration each