mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-15 21:18:06 +02:00
use ScriptEngine in Particle::collideWithXXX() methods so that we get all script interfaces
This commit is contained in:
parent
3efc1ea410
commit
0df02618ee
5 changed files with 670 additions and 657 deletions
File diff suppressed because it is too large
Load diff
|
@ -7,39 +7,43 @@
|
|||
//
|
||||
//
|
||||
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <Octree.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h> // usecTimestampNow()
|
||||
#include <Octree.h>
|
||||
|
||||
#include <VoxelsScriptingInterface.h>
|
||||
#include "ParticlesScriptingInterface.h"
|
||||
|
||||
// This is not ideal, but adding script-engine as a linked library, will cause a circular reference
|
||||
// I'm open to other potential solutions. Could we change cmake to allow libraries to reference each others
|
||||
// headers, but not link to each other, this is essentially what this construct is doing, but would be
|
||||
// better to add includes to the include path, but not link
|
||||
#include "../../script-engine/src/ScriptEngine.h"
|
||||
|
||||
#include "ParticlesScriptingInterface.h"
|
||||
#include "Particle.h"
|
||||
|
||||
uint32_t Particle::_nextID = 0;
|
||||
VoxelsScriptingInterface* Particle::_voxelsScriptingInterface = NULL;
|
||||
ParticlesScriptingInterface* Particle::_particlesScriptingInterface = NULL;
|
||||
VoxelEditPacketSender* Particle::_voxelEditSender = NULL;
|
||||
ParticleEditPacketSender* Particle::_particleEditSender = NULL;
|
||||
|
||||
|
||||
Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity,
|
||||
Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity,
|
||||
float damping, bool inHand, QString updateScript, uint32_t id) {
|
||||
|
||||
|
||||
init(position, radius, color, velocity, gravity, damping, inHand, updateScript, id);
|
||||
}
|
||||
|
||||
Particle::Particle() {
|
||||
rgbColor noColor = { 0, 0, 0 };
|
||||
init(glm::vec3(0,0,0), 0, noColor, glm::vec3(0,0,0),
|
||||
init(glm::vec3(0,0,0), 0, noColor, glm::vec3(0,0,0),
|
||||
DEFAULT_GRAVITY, DEFAULT_DAMPING, NOT_IN_HAND, DEFAULT_SCRIPT, NEW_PARTICLE);
|
||||
}
|
||||
|
||||
Particle::~Particle() {
|
||||
}
|
||||
|
||||
void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity,
|
||||
void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity,
|
||||
float damping, bool inHand, QString updateScript, uint32_t id) {
|
||||
if (id == NEW_PARTICLE) {
|
||||
_id = _nextID;
|
||||
|
@ -51,7 +55,7 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3
|
|||
_lastEdited = now;
|
||||
_lastUpdated = now;
|
||||
_created = now; // will get updated as appropriate in setLifetime()
|
||||
|
||||
|
||||
_position = position;
|
||||
_radius = radius;
|
||||
memcpy(_color, color, sizeof(_color));
|
||||
|
@ -215,7 +219,7 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
_script = tempString;
|
||||
dataAt += scriptLength;
|
||||
bytesRead += scriptLength;
|
||||
|
||||
|
||||
//printf("Particle::readParticleDataFromBuffer()... "); debugDump();
|
||||
}
|
||||
return bytesRead;
|
||||
|
@ -227,11 +231,11 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
unsigned char* dataAt = data;
|
||||
processedBytes = 0;
|
||||
|
||||
// the first part of the data is our octcode...
|
||||
// the first part of the data is our octcode...
|
||||
int octets = numberOfThreeBitSectionsInCode(data);
|
||||
int lengthOfOctcode = bytesRequiredForCodeLength(octets);
|
||||
|
||||
// we don't actually do anything with this octcode...
|
||||
|
||||
// we don't actually do anything with this octcode...
|
||||
dataAt += lengthOfOctcode;
|
||||
processedBytes += lengthOfOctcode;
|
||||
|
||||
|
@ -240,7 +244,7 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
memcpy(&editID, dataAt, sizeof(editID));
|
||||
dataAt += sizeof(editID);
|
||||
processedBytes += sizeof(editID);
|
||||
|
||||
|
||||
// special case for handling "new" particles
|
||||
if (editID == NEW_PARTICLE) {
|
||||
// If this is a NEW_PARTICLE, then we assume that there's an additional uint32_t creatorToken, that
|
||||
|
@ -251,19 +255,19 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
processedBytes += sizeof(creatorTokenID);
|
||||
newParticle.setCreatorTokenID(creatorTokenID);
|
||||
newParticle._newlyCreated = true;
|
||||
|
||||
|
||||
newParticle.setLifetime(0); // this guy is new!
|
||||
|
||||
} else {
|
||||
newParticle._id = editID;
|
||||
newParticle._newlyCreated = false;
|
||||
}
|
||||
}
|
||||
|
||||
// lastEdited
|
||||
memcpy(&newParticle._lastEdited, dataAt, sizeof(newParticle._lastEdited));
|
||||
dataAt += sizeof(newParticle._lastEdited);
|
||||
processedBytes += sizeof(newParticle._lastEdited);
|
||||
|
||||
|
||||
// radius
|
||||
memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius));
|
||||
dataAt += sizeof(newParticle._radius);
|
||||
|
@ -283,12 +287,12 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
memcpy(&newParticle._velocity, dataAt, sizeof(newParticle._velocity));
|
||||
dataAt += sizeof(newParticle._velocity);
|
||||
processedBytes += sizeof(newParticle._velocity);
|
||||
|
||||
|
||||
// gravity
|
||||
memcpy(&newParticle._gravity, dataAt, sizeof(newParticle._gravity));
|
||||
dataAt += sizeof(newParticle._gravity);
|
||||
processedBytes += sizeof(newParticle._gravity);
|
||||
|
||||
|
||||
// damping
|
||||
memcpy(&newParticle._damping, dataAt, sizeof(newParticle._damping));
|
||||
dataAt += sizeof(newParticle._damping);
|
||||
|
@ -311,11 +315,11 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
|
||||
const bool wantDebugging = false;
|
||||
if (wantDebugging) {
|
||||
printf("Particle::fromEditPacket()...\n");
|
||||
printf("Particle::fromEditPacket()...\n");
|
||||
printf(" Particle id in packet:%u\n", editID);
|
||||
newParticle.debugDump();
|
||||
}
|
||||
|
||||
|
||||
return newParticle;
|
||||
}
|
||||
|
||||
|
@ -329,7 +333,7 @@ void Particle::debugDump() const {
|
|||
printf(" color:%d,%d,%d\n", _color[0], _color[1], _color[2]);
|
||||
}
|
||||
|
||||
bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, const ParticleDetail* details,
|
||||
bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, const ParticleDetail* details,
|
||||
unsigned char* bufferOut, int sizeIn, int& sizeOut) {
|
||||
|
||||
bool success = true; // assume the best
|
||||
|
@ -338,13 +342,13 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
|
||||
for (int i = 0; i < count && success; i++) {
|
||||
// get the octal code for the particle
|
||||
unsigned char* octcode = pointToOctalCode(details[i].position.x, details[i].position.y,
|
||||
unsigned char* octcode = pointToOctalCode(details[i].position.x, details[i].position.y,
|
||||
details[i].position.z, details[i].radius);
|
||||
|
||||
int octets = numberOfThreeBitSectionsInCode(octcode);
|
||||
int lengthOfOctcode = bytesRequiredForCodeLength(octets);
|
||||
int lenfthOfEditData = lengthOfOctcode + expectedEditMessageBytes();
|
||||
|
||||
|
||||
// make sure we have room to copy this particle
|
||||
if (sizeOut + lenfthOfEditData > sizeIn) {
|
||||
success = false;
|
||||
|
@ -353,9 +357,9 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
memcpy(copyAt, octcode, lengthOfOctcode);
|
||||
copyAt += lengthOfOctcode;
|
||||
sizeOut += lengthOfOctcode;
|
||||
|
||||
|
||||
// Now add our edit content details...
|
||||
|
||||
|
||||
// id
|
||||
memcpy(copyAt, &details[i].id, sizeof(details[i].id));
|
||||
copyAt += sizeof(details[i].id);
|
||||
|
@ -419,7 +423,7 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
sizeOut += scriptLength;
|
||||
|
||||
bool wantDebugging = false;
|
||||
if (wantDebugging) {
|
||||
if (wantDebugging) {
|
||||
printf("encodeParticleEditMessageDetails()....\n");
|
||||
printf("Particle id :%u\n", details[i].id);
|
||||
printf(" nextID:%u\n", _nextID);
|
||||
|
@ -433,7 +437,7 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
}
|
||||
|
||||
// adjust any internal timestamps to fix clock skew for this server
|
||||
void Particle::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew) {
|
||||
void Particle::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew) {
|
||||
unsigned char* dataAt = codeColorBuffer;
|
||||
int octets = numberOfThreeBitSectionsInCode(dataAt);
|
||||
int lengthOfOctcode = bytesRequiredForCodeLength(octets);
|
||||
|
@ -456,7 +460,7 @@ void Particle::adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssiz
|
|||
uint64_t lastEditedInServerTime = lastEditedInLocalTime + clockSkew;
|
||||
memcpy(dataAt, &lastEditedInServerTime, sizeof(lastEditedInServerTime));
|
||||
const bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
if (wantDebug) {
|
||||
qDebug("Particle::adjustEditPacketForClockSkew()...\n");
|
||||
qDebug() << " lastEditedInLocalTime: " << lastEditedInLocalTime << "\n";
|
||||
qDebug() << " clockSkew: " << clockSkew << "\n";
|
||||
|
@ -470,7 +474,7 @@ void Particle::update() {
|
|||
float elapsed = static_cast<float>(now - _lastUpdated);
|
||||
_lastUpdated = now;
|
||||
float timeElapsed = elapsed / static_cast<float>(USECS_PER_SECOND);
|
||||
|
||||
|
||||
// calculate our default shouldDie state... then allow script to change it if it wants...
|
||||
float velocityScalar = glm::length(getVelocity());
|
||||
const float STILL_MOVING = 0.05f / static_cast<float>(TREE_SCALE);
|
||||
|
@ -480,13 +484,13 @@ void Particle::update() {
|
|||
bool isInHand = getInHand();
|
||||
bool shouldDie = getShouldDie() || (!isInHand && !isStillMoving && isReallyOld);
|
||||
setShouldDie(shouldDie);
|
||||
|
||||
|
||||
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) {
|
||||
_position += _velocity * timeElapsed;
|
||||
|
||||
|
||||
// handle bounces off the ground...
|
||||
if (_position.y <= 0) {
|
||||
_velocity = _velocity * glm::vec3(1,-1,1);
|
||||
|
@ -507,21 +511,21 @@ void Particle::runUpdateScript() {
|
|||
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.emitUpdate();
|
||||
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
|
@ -532,45 +536,30 @@ void Particle::runUpdateScript() {
|
|||
void Particle::collisionWithParticle(Particle* other) {
|
||||
if (!_script.isEmpty()) {
|
||||
|
||||
QScriptEngine engine;
|
||||
|
||||
// register meta-type for glm::vec3 and rgbColor conversions
|
||||
registerMetaTypes(&engine);
|
||||
|
||||
ScriptEngine engine(_script); // no menu or controller interface...
|
||||
|
||||
if (_voxelEditSender) {
|
||||
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
|
||||
}
|
||||
|
||||
// Add the Particle object
|
||||
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);
|
||||
engine.registerGlobalObject("Particle", &particleScriptable);
|
||||
|
||||
// init and evaluate the script, but return so we can emit the collision
|
||||
engine.evaluate();
|
||||
|
||||
if (getVoxelsScriptingInterface()) {
|
||||
QScriptValue voxelScripterValue = engine.newQObject(getVoxelsScriptingInterface());
|
||||
engine.globalObject().setProperty("Voxels", voxelScripterValue);
|
||||
}
|
||||
|
||||
if (getParticlesScriptingInterface()) {
|
||||
QScriptValue particleScripterValue = engine.newQObject(getParticlesScriptingInterface());
|
||||
engine.globalObject().setProperty("Particles", particleScripterValue);
|
||||
}
|
||||
|
||||
QScriptValue result = engine.evaluate(_script);
|
||||
|
||||
ParticleScriptObject otherParticleScriptable(other);
|
||||
particleScriptable.emitCollisionWithParticle(&otherParticleScriptable);
|
||||
|
||||
if (getVoxelsScriptingInterface()) {
|
||||
getVoxelsScriptingInterface()->getPacketSender()->releaseQueuedMessages();
|
||||
if (_voxelEditSender) {
|
||||
_voxelEditSender->releaseQueuedMessages();
|
||||
}
|
||||
|
||||
if (getParticlesScriptingInterface()) {
|
||||
getParticlesScriptingInterface()->getPacketSender()->releaseQueuedMessages();
|
||||
}
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
if (_particleEditSender) {
|
||||
_particleEditSender->releaseQueuedMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -578,45 +567,32 @@ void Particle::collisionWithParticle(Particle* other) {
|
|||
void Particle::collisionWithVoxel(VoxelDetail* voxelDetails) {
|
||||
if (!_script.isEmpty()) {
|
||||
|
||||
QScriptEngine engine;
|
||||
|
||||
// register meta-type for glm::vec3 and rgbColor conversions
|
||||
registerMetaTypes(&engine);
|
||||
|
||||
ScriptEngine engine(_script); // no menu or controller interface...
|
||||
|
||||
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
||||
// we can use the same ones as our context.
|
||||
if (_voxelEditSender) {
|
||||
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
|
||||
}
|
||||
|
||||
// Add the Particle object
|
||||
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);
|
||||
engine.registerGlobalObject("Particle", &particleScriptable);
|
||||
|
||||
// init and evaluate the script, but return so we can emit the collision
|
||||
engine.evaluate();
|
||||
|
||||
if (getVoxelsScriptingInterface()) {
|
||||
QScriptValue voxelScripterValue = engine.newQObject(getVoxelsScriptingInterface());
|
||||
engine.globalObject().setProperty("Voxels", voxelScripterValue);
|
||||
}
|
||||
|
||||
if (getParticlesScriptingInterface()) {
|
||||
QScriptValue particleScripterValue = engine.newQObject(getParticlesScriptingInterface());
|
||||
engine.globalObject().setProperty("Particles", particleScripterValue);
|
||||
}
|
||||
|
||||
QScriptValue result = engine.evaluate(_script);
|
||||
|
||||
VoxelDetailScriptObject voxelDetailsScriptable(voxelDetails);
|
||||
particleScriptable.emitCollisionWithVoxel(&voxelDetailsScriptable);
|
||||
|
||||
if (getVoxelsScriptingInterface()) {
|
||||
getVoxelsScriptingInterface()->getPacketSender()->releaseQueuedMessages();
|
||||
if (_voxelEditSender) {
|
||||
_voxelEditSender->releaseQueuedMessages();
|
||||
}
|
||||
|
||||
if (getParticlesScriptingInterface()) {
|
||||
getParticlesScriptingInterface()->getPacketSender()->releaseQueuedMessages();
|
||||
}
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
if (_particleEditSender) {
|
||||
_particleEditSender->releaseQueuedMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -625,7 +601,7 @@ void Particle::collisionWithVoxel(VoxelDetail* voxelDetails) {
|
|||
|
||||
void Particle::setLifetime(float lifetime) {
|
||||
uint64_t lifetimeInUsecs = lifetime * USECS_PER_SECOND;
|
||||
_created = usecTimestampNow() - lifetimeInUsecs;
|
||||
_created = usecTimestampNow() - lifetimeInUsecs;
|
||||
}
|
||||
|
||||
void Particle::copyChangedProperties(const Particle& other) {
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
class VoxelsScriptingInterface;
|
||||
class ParticlesScriptingInterface;
|
||||
class VoxelEditPacketSender;
|
||||
class ParticleEditPacketSender;
|
||||
|
||||
|
||||
const uint32_t NEW_PARTICLE = 0xFFFFFFFF;
|
||||
|
@ -48,19 +50,19 @@ const bool IN_HAND = true; // it's in a hand
|
|||
const bool NOT_IN_HAND = !IN_HAND; // it's not in a hand
|
||||
|
||||
class Particle {
|
||||
|
||||
|
||||
public:
|
||||
Particle();
|
||||
Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity = DEFAULT_GRAVITY, float damping = DEFAULT_DAMPING, bool inHand = NOT_IN_HAND,
|
||||
Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity = DEFAULT_GRAVITY, float damping = DEFAULT_DAMPING, bool inHand = NOT_IN_HAND,
|
||||
QString updateScript = DEFAULT_SCRIPT, uint32_t id = NEW_PARTICLE);
|
||||
|
||||
|
||||
/// creates an NEW particle from an PACKET_TYPE_PARTICLE_ADD_OR_EDIT edit data buffer
|
||||
static Particle fromEditPacket(unsigned char* data, int length, int& processedBytes);
|
||||
|
||||
static Particle fromEditPacket(unsigned char* data, int length, int& processedBytes);
|
||||
|
||||
virtual ~Particle();
|
||||
virtual void init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity = DEFAULT_GRAVITY, float damping = DEFAULT_DAMPING, bool inHand = NOT_IN_HAND,
|
||||
virtual void init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity = DEFAULT_GRAVITY, float damping = DEFAULT_DAMPING, bool inHand = NOT_IN_HAND,
|
||||
QString updateScript = DEFAULT_SCRIPT, uint32_t id = NEW_PARTICLE);
|
||||
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
|
@ -71,7 +73,7 @@ public:
|
|||
const glm::vec3& getGravity() const { return _gravity; }
|
||||
bool getInHand() const { return _inHand; }
|
||||
float getDamping() const { return _damping; }
|
||||
|
||||
|
||||
/// The last updated/simulated time of this particle from the time perspective of the authoritative server/source
|
||||
uint64_t getLastUpdated() const { return _lastUpdated; }
|
||||
|
||||
|
@ -91,9 +93,9 @@ public:
|
|||
void setVelocity(const glm::vec3& value) { _velocity = value; }
|
||||
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
|
||||
void setColor(const xColor& value) {
|
||||
_color[RED_INDEX] = value.red;
|
||||
_color[GREEN_INDEX] = value.green;
|
||||
_color[BLUE_INDEX] = value.blue;
|
||||
_color[RED_INDEX] = value.red;
|
||||
_color[GREEN_INDEX] = value.green;
|
||||
_color[BLUE_INDEX] = value.blue;
|
||||
}
|
||||
void setRadius(float value) { _radius = value; }
|
||||
void setGravity(const glm::vec3& value) { _gravity = value; }
|
||||
|
@ -102,15 +104,15 @@ public:
|
|||
void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; }
|
||||
void setScript(QString updateScript) { _script = updateScript; }
|
||||
void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; }
|
||||
|
||||
|
||||
bool appendParticleData(OctreePacketData* packetData) const;
|
||||
int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
|
||||
static int expectedBytes();
|
||||
static int expectedEditMessageBytes();
|
||||
|
||||
static bool encodeParticleEditMessageDetails(PACKET_TYPE command, int count, const ParticleDetail* details,
|
||||
static bool encodeParticleEditMessageDetails(PACKET_TYPE command, int count, const ParticleDetail* details,
|
||||
unsigned char* bufferOut, int sizeIn, int& sizeOut);
|
||||
|
||||
|
||||
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew);
|
||||
|
||||
void update();
|
||||
|
@ -118,22 +120,23 @@ public:
|
|||
void collisionWithVoxel(VoxelDetail* voxel);
|
||||
|
||||
void debugDump() const;
|
||||
|
||||
|
||||
// similar to assignment/copy, but it handles keeping lifetime accurate
|
||||
void copyChangedProperties(const Particle& other);
|
||||
|
||||
static VoxelsScriptingInterface* getVoxelsScriptingInterface() { return _voxelsScriptingInterface; }
|
||||
static ParticlesScriptingInterface* getParticlesScriptingInterface() { return _particlesScriptingInterface; }
|
||||
|
||||
static void setVoxelsScriptingInterface(VoxelsScriptingInterface* interface)
|
||||
{ _voxelsScriptingInterface = interface; }
|
||||
|
||||
static void setParticlesScriptingInterface(ParticlesScriptingInterface* interface)
|
||||
{ _particlesScriptingInterface = interface; }
|
||||
|
||||
static VoxelEditPacketSender* getVoxelEditPacketSender() { return _voxelEditSender; }
|
||||
static ParticleEditPacketSender* getParticleEditPacketSender() { return _particleEditSender; }
|
||||
|
||||
static void setVoxelEditPacketSender(VoxelEditPacketSender* interface)
|
||||
{ _voxelEditSender = interface; }
|
||||
|
||||
static void setParticleEditPacketSender(ParticleEditPacketSender* interface)
|
||||
{ _particleEditSender = interface; }
|
||||
|
||||
|
||||
protected:
|
||||
static VoxelsScriptingInterface* _voxelsScriptingInterface;
|
||||
static ParticlesScriptingInterface* _particlesScriptingInterface;
|
||||
static VoxelEditPacketSender* _voxelEditSender;
|
||||
static ParticleEditPacketSender* _particleEditSender;
|
||||
|
||||
void runUpdateScript();
|
||||
static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3);
|
||||
|
@ -141,8 +144,8 @@ protected:
|
|||
static QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color);
|
||||
static void xColorFromScriptValue(const QScriptValue &object, xColor& color);
|
||||
|
||||
void setLifetime(float lifetime);
|
||||
|
||||
void setLifetime(float lifetime);
|
||||
|
||||
glm::vec3 _position;
|
||||
rgbColor _color;
|
||||
float _radius;
|
||||
|
@ -184,7 +187,7 @@ public slots:
|
|||
float getRadius() const { return _particle->getRadius(); }
|
||||
bool getShouldDie() { return _particle->getShouldDie(); }
|
||||
float getLifetime() const { return _particle->getLifetime(); }
|
||||
|
||||
|
||||
void setPosition(glm::vec3 value) { _particle->setPosition(value); }
|
||||
void setVelocity(glm::vec3 value) { _particle->setVelocity(value); }
|
||||
void setGravity(glm::vec3 value) { _particle->setGravity(value); }
|
||||
|
|
|
@ -19,11 +19,14 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelConstants.h>
|
||||
#include <ParticlesScriptingInterface.h>
|
||||
|
||||
#include <Sound.h>
|
||||
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
|
||||
|
||||
int ScriptEngine::_scriptNumber = 1;
|
||||
VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface;
|
||||
ParticlesScriptingInterface ScriptEngine::_particlesScriptingInterface;
|
||||
|
@ -31,7 +34,7 @@ ParticlesScriptingInterface ScriptEngine::_particlesScriptingInterface;
|
|||
static QScriptValue soundConstructor(QScriptContext* context, QScriptEngine* engine) {
|
||||
QUrl soundURL = QUrl(context->argument(0).toString());
|
||||
QScriptValue soundScriptValue = engine->newQObject(new Sound(soundURL), QScriptEngine::ScriptOwnership);
|
||||
|
||||
|
||||
return soundScriptValue;
|
||||
}
|
||||
|
||||
|
@ -41,7 +44,8 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
|
|||
_scriptContents = scriptContents;
|
||||
_isFinished = false;
|
||||
_isRunning = false;
|
||||
|
||||
_isInitialized = false;
|
||||
|
||||
// some clients will use these menu features
|
||||
_wantMenuItems = wantMenuItems;
|
||||
if (scriptMenuName) {
|
||||
|
@ -54,15 +58,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
|
|||
}
|
||||
_menu = menu;
|
||||
_controllerScriptingInterface = controllerScriptingInterface;
|
||||
|
||||
// hook up our interfaces
|
||||
if (!Particle::getVoxelsScriptingInterface()) {
|
||||
Particle::setVoxelsScriptingInterface(getVoxelsScriptingInterface());
|
||||
}
|
||||
|
||||
if (!Particle::getParticlesScriptingInterface()) {
|
||||
Particle::setParticlesScriptingInterface(getParticlesScriptingInterface());
|
||||
}
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine() {
|
||||
|
@ -92,63 +87,89 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents) {
|
|||
|
||||
Q_SCRIPT_DECLARE_QMETAOBJECT(AudioInjectorOptions, QObject*)
|
||||
|
||||
void ScriptEngine::run() {
|
||||
_isRunning = true;
|
||||
QScriptEngine engine;
|
||||
|
||||
void ScriptEngine::init() {
|
||||
if (_isInitialized) {
|
||||
return; // only initialize once
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
|
||||
_voxelsScriptingInterface.init();
|
||||
_particlesScriptingInterface.init();
|
||||
|
||||
// register meta-type for glm::vec3 conversions
|
||||
registerMetaTypes(&engine);
|
||||
|
||||
QScriptValue agentValue = engine.newQObject(this);
|
||||
engine.globalObject().setProperty("Agent", agentValue);
|
||||
|
||||
QScriptValue voxelScripterValue = engine.newQObject(&_voxelsScriptingInterface);
|
||||
engine.globalObject().setProperty("Voxels", voxelScripterValue);
|
||||
|
||||
QScriptValue particleScripterValue = engine.newQObject(&_particlesScriptingInterface);
|
||||
engine.globalObject().setProperty("Particles", particleScripterValue);
|
||||
|
||||
|
||||
QScriptValue soundConstructorValue = engine.newFunction(soundConstructor);
|
||||
QScriptValue soundMetaObject = engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
||||
engine.globalObject().setProperty("Sound", soundMetaObject);
|
||||
|
||||
QScriptValue injectionOptionValue = engine.scriptValueFromQMetaObject<AudioInjectorOptions>();
|
||||
engine.globalObject().setProperty("AudioInjectionOptions", injectionOptionValue);
|
||||
|
||||
QScriptValue audioScriptingInterfaceValue = engine.newQObject(&_audioScriptingInterface);
|
||||
engine.globalObject().setProperty("Audio", audioScriptingInterfaceValue);
|
||||
|
||||
// register meta-type for glm::vec3 conversions
|
||||
registerMetaTypes(&_engine);
|
||||
|
||||
QScriptValue agentValue = _engine.newQObject(this);
|
||||
_engine.globalObject().setProperty("Agent", agentValue);
|
||||
|
||||
QScriptValue voxelScripterValue = _engine.newQObject(&_voxelsScriptingInterface);
|
||||
_engine.globalObject().setProperty("Voxels", voxelScripterValue);
|
||||
|
||||
QScriptValue particleScripterValue = _engine.newQObject(&_particlesScriptingInterface);
|
||||
_engine.globalObject().setProperty("Particles", particleScripterValue);
|
||||
|
||||
QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor);
|
||||
QScriptValue soundMetaObject = _engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
||||
_engine.globalObject().setProperty("Sound", soundMetaObject);
|
||||
|
||||
QScriptValue injectionOptionValue = _engine.scriptValueFromQMetaObject<AudioInjectorOptions>();
|
||||
_engine.globalObject().setProperty("AudioInjectionOptions", injectionOptionValue);
|
||||
|
||||
QScriptValue audioScriptingInterfaceValue = _engine.newQObject(&_audioScriptingInterface);
|
||||
_engine.globalObject().setProperty("Audio", audioScriptingInterfaceValue);
|
||||
|
||||
if (_controllerScriptingInterface) {
|
||||
QScriptValue controllerScripterValue = engine.newQObject(_controllerScriptingInterface);
|
||||
engine.globalObject().setProperty("Controller", controllerScripterValue);
|
||||
QScriptValue controllerScripterValue = _engine.newQObject(_controllerScriptingInterface);
|
||||
_engine.globalObject().setProperty("Controller", controllerScripterValue);
|
||||
}
|
||||
|
||||
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
||||
engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
||||
|
||||
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
|
||||
|
||||
|
||||
QScriptValue treeScaleValue = _engine.newVariant(QVariant(TREE_SCALE));
|
||||
_engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
||||
|
||||
// let the VoxelPacketSender know how frequently we plan to call it
|
||||
_voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
|
||||
_particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
|
||||
|
||||
//qDebug() << "Script:\n" << _scriptContents << "\n";
|
||||
|
||||
QScriptValue result = engine.evaluate(_scriptContents);
|
||||
}
|
||||
|
||||
void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) {
|
||||
QScriptValue value = _engine.newQObject(object);
|
||||
_engine.globalObject().setProperty(name, value);
|
||||
}
|
||||
|
||||
void ScriptEngine::evaluate() {
|
||||
if (!_isInitialized) {
|
||||
init();
|
||||
}
|
||||
|
||||
QScriptValue result = _engine.evaluate(_scriptContents);
|
||||
qDebug() << "Evaluated script.\n";
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
|
||||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ScriptEngine::run() {
|
||||
if (!_isInitialized) {
|
||||
init();
|
||||
}
|
||||
_isRunning = true;
|
||||
|
||||
QScriptValue result = _engine.evaluate(_scriptContents);
|
||||
qDebug() << "Evaluated script.\n";
|
||||
|
||||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
}
|
||||
|
||||
timeval startTime;
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
|
||||
int thisFrame = 0;
|
||||
|
||||
while (!_isFinished) {
|
||||
|
@ -166,15 +187,15 @@ void ScriptEngine::run() {
|
|||
if (_isFinished) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
bool willSendVisualDataCallBack = false;
|
||||
if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) {
|
||||
if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) {
|
||||
// allow the scripter's call back to setup visual data
|
||||
willSendVisualDataCallBack = true;
|
||||
|
||||
|
||||
// release the queue of edit voxel messages.
|
||||
_voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages();
|
||||
|
||||
|
||||
// since we're in non-threaded mode, call process so that the packets are sent
|
||||
if (!_voxelsScriptingInterface.getVoxelPacketSender()->isThreaded()) {
|
||||
_voxelsScriptingInterface.getVoxelPacketSender()->process();
|
||||
|
@ -184,23 +205,23 @@ void ScriptEngine::run() {
|
|||
if (_particlesScriptingInterface.getParticlePacketSender()->serversExist()) {
|
||||
// allow the scripter's call back to setup visual data
|
||||
willSendVisualDataCallBack = true;
|
||||
|
||||
|
||||
// release the queue of edit voxel messages.
|
||||
_particlesScriptingInterface.getParticlePacketSender()->releaseQueuedMessages();
|
||||
|
||||
|
||||
// since we're in non-threaded mode, call process so that the packets are sent
|
||||
if (!_particlesScriptingInterface.getParticlePacketSender()->isThreaded()) {
|
||||
_particlesScriptingInterface.getParticlePacketSender()->process();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (willSendVisualDataCallBack) {
|
||||
emit willSendVisualDataCallback();
|
||||
}
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
|
||||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << _engine.uncaughtException().toString() << "\n";
|
||||
}
|
||||
}
|
||||
cleanMenuItems();
|
||||
|
@ -213,9 +234,8 @@ void ScriptEngine::run() {
|
|||
emit finished();
|
||||
_isRunning = false;
|
||||
}
|
||||
|
||||
void ScriptEngine::stop() {
|
||||
_isFinished = true;
|
||||
void ScriptEngine::stop() {
|
||||
_isFinished = true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
|
||||
#include <AbstractMenuInterface.h>
|
||||
#include <AudioScriptingInterface.h>
|
||||
#include <ParticlesScriptingInterface.h>
|
||||
#include <VoxelsScriptingInterface.h>
|
||||
|
||||
class ParticlesScriptingInterface;
|
||||
|
||||
#include "AbstractControllerScriptingInterface.h"
|
||||
|
||||
const QString NO_SCRIPT("");
|
||||
|
@ -27,12 +28,12 @@ const QString NO_SCRIPT("");
|
|||
class ScriptEngine : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptEngine(const QString& scriptContents = NO_SCRIPT, bool wantMenuItems = false,
|
||||
ScriptEngine(const QString& scriptContents = NO_SCRIPT, bool wantMenuItems = false,
|
||||
const char* scriptMenuName = NULL, AbstractMenuInterface* menu = NULL,
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface = NULL);
|
||||
|
||||
~ScriptEngine();
|
||||
|
||||
|
||||
/// Access the VoxelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
||||
VoxelsScriptingInterface* getVoxelsScriptingInterface() { return &_voxelsScriptingInterface; }
|
||||
|
||||
|
@ -44,11 +45,15 @@ public:
|
|||
|
||||
void setupMenuItems();
|
||||
void cleanMenuItems();
|
||||
|
||||
|
||||
void registerGlobalObject(const QString& name, QObject* object); /// registers a global object by name
|
||||
|
||||
public slots:
|
||||
void run();
|
||||
void init();
|
||||
void run(); /// runs continuously until Agent.stop() is called
|
||||
void stop();
|
||||
|
||||
void evaluate(); /// initializes the engine, and evaluates the script, but then returns control to caller
|
||||
|
||||
signals:
|
||||
void willSendAudioDataCallback();
|
||||
void willSendVisualDataCallback();
|
||||
|
@ -57,7 +62,8 @@ protected:
|
|||
QString _scriptContents;
|
||||
bool _isFinished;
|
||||
bool _isRunning;
|
||||
|
||||
bool _isInitialized;
|
||||
QScriptEngine _engine;
|
||||
|
||||
private:
|
||||
static VoxelsScriptingInterface _voxelsScriptingInterface;
|
||||
|
|
Loading…
Reference in a new issue