first cut at creatorTokenIDs for creating particles

This commit is contained in:
ZappoMan 2013-12-11 15:38:52 -08:00
parent ee2fda1412
commit 03c72134cb
16 changed files with 179 additions and 34 deletions

View file

@ -139,7 +139,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_recentMaxPackets(0),
_resetRecentMaxPacketsSoon(true),
_swatch(NULL),
_pasteMode(false)
_pasteMode(false),
_nextCreatorTokenID(0)
{
_applicationStartupTime = startup_time;
_window->setWindowTitle("Interface");
@ -1515,13 +1516,18 @@ void Application::shootParticle() {
void Application::makeParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
glm::vec3 gravity, float damping, QString updateScript) {
// The application will keep track of creatorTokenID
uint32_t creatorTokenID = _nextCreatorTokenID;
_nextCreatorTokenID++;
// setup a ParticleDetail struct with the data
ParticleDetail addParticleDetail = { position, radius, {color.red, color.green, color.blue },
velocity, gravity, damping, updateScript };
ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(),
position, radius, {color.red, color.green, color.blue },
velocity, gravity, damping, updateScript, creatorTokenID };
// queue the packet
_particleEditSender.queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD, 1, &addParticleDetail);
_particleEditSender.queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, 1, &addParticleDetail);
// release them
_particleEditSender.releaseQueuedMessages();

View file

@ -490,6 +490,8 @@ private:
std::vector<VoxelFade> _voxelFades;
std::vector<Avatar*> _avatarFades;
uint32_t _nextCreatorTokenID;
};
#endif /* defined(__interface__Application__) */

View file

@ -56,6 +56,8 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA
if (_myServer->getOctree()->handlesEditPacketType(packetType)) {
PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE",debugProcessPacket);
_receivedPacketCount++;
Node* senderNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
unsigned short int sequence = (*((unsigned short int*)(packetData + numBytesPacketHeader)));
uint64_t sentAt = (*((uint64_t*)(packetData + numBytesPacketHeader + sizeof(sequence))));
@ -85,7 +87,7 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA
_myServer->getOctree()->lockForWrite();
uint64_t startProcess = usecTimestampNow();
int editDataBytesRead = _myServer->getOctree()->processEditPacketData(packetType,
packetData, packetLength, editData, maxSize);
packetData, packetLength, editData, maxSize, senderNode);
_myServer->getOctree()->unlock();
uint64_t endProcess = usecTimestampNow();
@ -107,7 +109,6 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA
}
// Make sure our Node and NodeList knows we've heard from this node.
Node* senderNode = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
QUuid& nodeUUID = DEFAULT_NODE_ID_REF;
if (senderNode) {
senderNode->setLastHeardMicrostamp(usecTimestampNow());

View file

@ -185,7 +185,7 @@ public:
// own definition. Implement these to allow your octree based server to support editing
virtual bool handlesEditPacketType(PACKET_TYPE packetType) const { return false; }
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
unsigned char* editData, int maxLength) { return 0; }
unsigned char* editData, int maxLength, Node* senderNode) { return 0; }
virtual void update() { }; // nothing to do by default

View file

@ -21,7 +21,8 @@ ParticleServer::ParticleServer(const unsigned char* dataBuffer, int numBytes) :
}
ParticleServer::~ParticleServer() {
// nothing special to do here...
ParticleTree* tree = (ParticleTree*)_tree;
tree->removeNewlyCreatedHook(this);
}
OctreeQueryNode* ParticleServer::createOctreeQueryNode(Node* newNode) {
@ -29,9 +30,15 @@ OctreeQueryNode* ParticleServer::createOctreeQueryNode(Node* newNode) {
}
Octree* ParticleServer::createTree() {
return new ParticleTree(true);
ParticleTree* tree = new ParticleTree(true);
tree->addNewlyCreatedHook(this);
return tree;
}
void ParticleServer::beforeRun() {
// nothing special to do...
}
void ParticleServer::particleCreated(const Particle& newParticle, Node* senderNode) {
printf("ParticleServer::particleCreated(newParticle.creatorTokenID=%u, senderNode)\n",newParticle.getCreatorTokenID());
}

View file

@ -12,10 +12,12 @@
#include <OctreeServer.h>
#include "Particle.h"
#include "ParticleServerConsts.h"
#include "ParticleTree.h"
/// Handles assignments of type ParticleServer - sending particles to various clients.
class ParticleServer : public OctreeServer {
class ParticleServer : public OctreeServer, public NewlyCreatedParticleHook {
public:
ParticleServer(const unsigned char* dataBuffer, int numBytes);
~ParticleServer();
@ -32,6 +34,8 @@ public:
// subclass may implement these method
virtual void beforeRun();
virtual void particleCreated(const Particle& newParticle, Node* senderNode);
private:
};

View file

@ -146,6 +146,8 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef
_updateScript = tempString;
dataAt += scriptLength;
bytesRead += scriptLength;
printf("Particle::readParticleDataFromBuffer()... "); debugDump();
}
return bytesRead;
}
@ -163,6 +165,32 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
// we don't actually do anything with this octcode...
dataAt += lengthOfOctcode;
processedBytes += lengthOfOctcode;
// id
uint32_t editID;
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
// we want to send back to the creator as an map to the actual id
uint32_t creatorTokenID;
memcpy(&creatorTokenID, dataAt, sizeof(creatorTokenID));
dataAt += sizeof(creatorTokenID);
processedBytes += sizeof(creatorTokenID);
newParticle.setCreatorTokenID(creatorTokenID);
newParticle._newlyCreated = true;
} else {
newParticle._id = editID;
newParticle._newlyCreated = false;
}
// lastUpdated
memcpy(&newParticle._lastUpdated, dataAt, sizeof(newParticle._lastUpdated));
dataAt += sizeof(newParticle._lastUpdated);
processedBytes += sizeof(newParticle._lastUpdated);
// radius
memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius));
@ -204,9 +232,17 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
dataAt += scriptLength;
processedBytes += scriptLength;
printf("Particle::fromEditPacket()...\n");
printf(" Particle id in packet:%u\n", editID);
newParticle.debugDump();
return newParticle;
}
void Particle::debugDump() const {
printf("Particle id :%u\n", _id);
printf(" last updated:%llu\n", _lastUpdated);
}
bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, const ParticleDetail* details,
unsigned char* bufferOut, int sizeIn, int& sizeOut) {
@ -233,6 +269,24 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
sizeOut += lengthOfOctcode;
// Now add our edit content details...
// id
memcpy(copyAt, &details[i].id, sizeof(details[i].id));
copyAt += sizeof(details[i].id);
sizeOut += sizeof(details[i].id);
// special case for handling "new" particles
if (details[i].id == NEW_PARTICLE) {
// If this is a NEW_PARTICLE, then we assume that there's an additional uint32_t creatorToken, that
// we want to send back to the creator as an map to the actual id
memcpy(copyAt, &details[i].creatorTokenID, sizeof(details[i].creatorTokenID));
copyAt += sizeof(details[i].creatorTokenID);
sizeOut += sizeof(details[i].creatorTokenID);
}
// lastUpdated
memcpy(copyAt, &details[i].lastUpdated, sizeof(details[i].lastUpdated));
copyAt += sizeof(details[i].lastUpdated);
sizeOut += sizeof(details[i].lastUpdated);
// radius
memcpy(copyAt, &details[i].radius, sizeof(details[i].radius));
@ -272,6 +326,12 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
memcpy(copyAt, qPrintable(details[i].updateScript), scriptLength);
copyAt += scriptLength;
sizeOut += scriptLength;
printf("encodeParticleEditMessageDetails()....\n");
printf("Particle id :%u\n", details[i].id);
printf(" last updated:%llu\n", details[i].lastUpdated);
printf(" nextID:%u\n", _nextID);
}
// cleanup
delete[] octcode;

View file

@ -19,8 +19,11 @@
#include <SharedUtil.h>
#include <OctreePacketData.h>
const uint32_t NEW_PARTICLE = 0xFFFFFFFF;
class ParticleDetail {
public:
uint32_t id;
uint64_t lastUpdated;
glm::vec3 position;
float radius;
rgbColor color;
@ -28,6 +31,7 @@ public:
glm::vec3 gravity;
float damping;
QString updateScript;
uint32_t creatorTokenID;
};
const float DEFAULT_DAMPING = 0.99f;
@ -41,7 +45,7 @@ public:
Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
float damping = DEFAULT_DAMPING, glm::vec3 gravity = DEFAULT_GRAVITY, QString updateScript = DEFAULT_SCRIPT);
/// creates an NEW particle from an PACKET_TYPE_PARTICLE_ADD edit data buffer
/// 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);
virtual ~Particle();
@ -59,6 +63,8 @@ public:
uint32_t getID() const { return _id; }
bool getShouldDie() const { return _shouldDie; }
QString getUpdateScript() const { return _updateScript; }
uint32_t getCreatorTokenID() const { return _creatorTokenID; }
bool isNewlyCreated() const { return _newlyCreated; }
void setPosition(const glm::vec3& value) { _position = value; }
void setVelocity(const glm::vec3& value) { _velocity = value; }
@ -73,6 +79,7 @@ public:
void setDamping(float value) { _damping = value; }
void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; }
void setUpdateScript(QString updateScript) { _updateScript = updateScript; }
void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; }
bool appendParticleData(OctreePacketData* packetData) const;
int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
@ -83,6 +90,7 @@ public:
void update();
void debugDump() const;
protected:
void runScript();
static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3);
@ -101,6 +109,9 @@ protected:
glm::vec3 _gravity;
float _damping;
QString _updateScript;
uint32_t _creatorTokenID;
bool _newlyCreated;
};
class ParticleScriptObject : public QObject {
@ -115,13 +126,15 @@ public slots:
glm::vec3 getGravity() const { return _particle->getGravity(); }
float getDamping() const { return _particle->getDamping(); }
float getRadius() const { return _particle->getRadius(); }
bool setShouldDie() { return _particle->getShouldDie(); }
void setPosition(glm::vec3 value) { return _particle->setPosition(value); }
void setVelocity(glm::vec3 value) { return _particle->setVelocity(value); }
void setGravity(glm::vec3 value) { return _particle->setGravity(value); }
void setDamping(float value) { return _particle->setDamping(value); }
void setColor(xColor value) { return _particle->setColor(value); }
void setRadius(float value) { return _particle->setRadius(value); }
void setPosition(glm::vec3 value) { _particle->setPosition(value); }
void setVelocity(glm::vec3 value) { _particle->setVelocity(value); }
void setGravity(glm::vec3 value) { _particle->setGravity(value); }
void setDamping(float value) { _particle->setDamping(value); }
void setColor(xColor value) { _particle->setColor(value); }
void setRadius(float value) { _particle->setRadius(value); }
void setShouldDie(bool value) { _particle->setShouldDie(value); }
private:
Particle* _particle;

View file

@ -9,7 +9,8 @@
#include "ParticleScriptingInterface.h"
ParticleScriptingInterface::ParticleScriptingInterface() :
_jurisdictionListener(NODE_TYPE_PARTICLE_SERVER)
_jurisdictionListener(NODE_TYPE_PARTICLE_SERVER),
_nextCreatorTokenID(0)
{
_jurisdictionListener.initialize(true);
_particlePacketSender.setServerJurisdictions(_jurisdictionListener.getJurisdictions());
@ -19,12 +20,20 @@ void ParticleScriptingInterface::queueParticleAdd(PACKET_TYPE addPacketType, Par
_particlePacketSender.queueParticleEditMessages(addPacketType, 1, &addParticleDetails);
}
void ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, float radius,
uint32_t ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, float radius,
xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, QString updateScript) {
// The application will keep track of creatorTokenID
uint32_t creatorTokenID = _nextCreatorTokenID;
_nextCreatorTokenID++;
// setup a ParticleDetail struct with the data
ParticleDetail addParticleDetail = { position, radius, {color.red, color.green, color.blue }, velocity, gravity, damping, updateScript };
ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(),
position, radius, {color.red, color.green, color.blue }, velocity,
gravity, damping, updateScript, creatorTokenID };
// queue the packet
queueParticleAdd(PACKET_TYPE_PARTICLE_ADD, addParticleDetail);
queueParticleAdd(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, addParticleDetail);
return creatorTokenID;
}

View file

@ -24,7 +24,8 @@ public:
JurisdictionListener* getJurisdictionListener() { return &_jurisdictionListener; }
public slots:
/// queues the creation of a Particle which will be sent by calling process on the PacketSender
void queueParticleAdd(glm::vec3 position, float radius,
/// returns the creatorTokenID for the newly created particle
uint32_t queueParticleAdd(glm::vec3 position, float radius,
xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, QString updateScript);
/// Set the desired max packet size in bytes that should be created
@ -84,6 +85,8 @@ private:
JurisdictionListener _jurisdictionListener;
void queueParticleAdd(PACKET_TYPE addPacketType, ParticleDetail& addParticleDetails);
uint32_t _nextCreatorTokenID;
};
#endif /* defined(__hifi__ParticleScriptingInterface__) */

View file

@ -22,7 +22,7 @@ ParticleTreeElement* ParticleTree::createNewElement(unsigned char * octalCode) c
bool ParticleTree::handlesEditPacketType(PACKET_TYPE packetType) const {
// we handle these types of "edit" packets
switch (packetType) {
case PACKET_TYPE_PARTICLE_ADD:
case PACKET_TYPE_PARTICLE_ADD_OR_EDIT:
case PACKET_TYPE_PARTICLE_ERASE:
return true;
}
@ -65,15 +65,17 @@ void ParticleTree::storeParticle(const Particle& particle) {
}
int ParticleTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
unsigned char* editData, int maxLength) {
unsigned char* editData, int maxLength, Node* senderNode) {
int processedBytes = 0;
// we handle these types of "edit" packets
switch (packetType) {
case PACKET_TYPE_PARTICLE_ADD: {
case PACKET_TYPE_PARTICLE_ADD_OR_EDIT: {
Particle newParticle = Particle::fromEditPacket(editData, maxLength, processedBytes);
storeParticle(newParticle);
// It seems like we need some way to send the ID back to the creator??
if (newParticle.isNewlyCreated()) {
notifyNewlyCreatedParticle(newParticle, senderNode);
}
} break;
case PACKET_TYPE_PARTICLE_ERASE: {
@ -83,6 +85,31 @@ int ParticleTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* p
return processedBytes;
}
void ParticleTree::notifyNewlyCreatedParticle(const Particle& newParticle, Node* senderNode) {
_newlyCreatedHooksLock.lockForRead();
for (int i = 0; i < _newlyCreatedHooks.size(); i++) {
_newlyCreatedHooks[i]->particleCreated(newParticle, senderNode);
}
_newlyCreatedHooksLock.unlock();
}
void ParticleTree::addNewlyCreatedHook(NewlyCreatedParticleHook* hook) {
_newlyCreatedHooksLock.lockForWrite();
_newlyCreatedHooks.push_back(hook);
_newlyCreatedHooksLock.unlock();
}
void ParticleTree::removeNewlyCreatedHook(NewlyCreatedParticleHook* hook) {
_newlyCreatedHooksLock.lockForWrite();
for (int i = 0; i < _newlyCreatedHooks.size(); i++) {
if (_newlyCreatedHooks[i] == hook) {
_newlyCreatedHooks.erase(_newlyCreatedHooks.begin() + i);
break;
}
}
_newlyCreatedHooksLock.unlock();
}
bool ParticleTree::updateOperation(OctreeElement* element, void* extraData) {
ParticleTreeUpdateArgs* args = static_cast<ParticleTreeUpdateArgs*>(extraData);

View file

@ -17,7 +17,10 @@ public:
std::vector<Particle> _movingParticles;
};
class NewlyCreatedParticleHook {
public:
virtual void particleCreated(const Particle& newParticle, Node* senderNode) = 0;
};
class ParticleTree : public Octree {
Q_OBJECT
@ -35,18 +38,24 @@ public:
// own definition. Implement these to allow your octree based server to support editing
virtual bool handlesEditPacketType(PACKET_TYPE packetType) const;
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
unsigned char* editData, int maxLength);
unsigned char* editData, int maxLength, Node* senderNode);
virtual void update();
void storeParticle(const Particle& particle);
void addNewlyCreatedHook(NewlyCreatedParticleHook* hook);
void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook);
private:
static bool updateOperation(OctreeElement* element, void* extraData);
static bool findAndUpdateOperation(OctreeElement* element, void* extraData);
void notifyNewlyCreatedParticle(const Particle& newParticle, Node* senderNode);
QReadWriteLock _newlyCreatedHooksLock;
std::vector<NewlyCreatedParticleHook*> _newlyCreatedHooks;
};
#endif /* defined(__hifi__ParticleTree__) */

View file

@ -49,6 +49,9 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
case PACKET_TYPE_JURISDICTION:
return 1;
case PACKET_TYPE_PARTICLE_ADD_OR_EDIT:
return 1;
default:
return 0;

View file

@ -48,8 +48,9 @@ const PACKET_TYPE PACKET_TYPE_JURISDICTION = 'J';
const PACKET_TYPE PACKET_TYPE_JURISDICTION_REQUEST = 'j';
const PACKET_TYPE PACKET_TYPE_PARTICLE_QUERY = 'Q';
const PACKET_TYPE PACKET_TYPE_PARTICLE_DATA = 'v';
const PACKET_TYPE PACKET_TYPE_PARTICLE_ADD = 'a';
const PACKET_TYPE PACKET_TYPE_PARTICLE_ADD_OR_EDIT = 'a';
const PACKET_TYPE PACKET_TYPE_PARTICLE_ERASE = 'x';
const PACKET_TYPE PACKET_TYPE_PARTICLE_ADD_RESPONSE = 'b';
typedef char PACKET_VERSION;

View file

@ -651,7 +651,7 @@ bool VoxelTree::handlesEditPacketType(PACKET_TYPE packetType) const {
}
int VoxelTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
unsigned char* editData, int maxLength) {
unsigned char* editData, int maxLength, Node* senderNode) {
int processedBytes = 0;
// we handle these types of "edit" packets

View file

@ -55,7 +55,7 @@ public:
virtual bool handlesEditPacketType(PACKET_TYPE packetType) const;
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
unsigned char* editData, int maxLength);
unsigned char* editData, int maxLength, Node* senderNode);
void processSetVoxelsBitstream(const unsigned char* bitstream, int bufferSizeBytes);
/**