mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 17:53:32 +02:00
commit
c8c6165356
25 changed files with 499 additions and 127 deletions
|
@ -235,6 +235,11 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
// Tell our voxel edit sender about our known jurisdictions
|
||||
_voxelEditSender.setVoxelServerJurisdictions(&_voxelServerJurisdictions);
|
||||
_particleEditSender.setServerJurisdictions(&_particleServerJurisdictions);
|
||||
|
||||
// For now we're going to set the PPS for outbound packets to be super high, this is
|
||||
// probably not the right long term solution. But for now, we're going to do this to
|
||||
// allow you to move a particle around in your hand
|
||||
_particleEditSender.setPacketsPerSecond(3000); // super high!!
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
|
@ -1508,23 +1513,23 @@ void Application::shootParticle() {
|
|||
float damping = DEFAULT_DAMPING * 0.01f;
|
||||
QString updateScript("");
|
||||
|
||||
makeParticle(position / (float)TREE_SCALE, radius, color,
|
||||
velocity / (float)TREE_SCALE, gravity, damping, updateScript);
|
||||
|
||||
ParticleEditHandle* particleEditHandle = makeParticle(position / (float)TREE_SCALE, radius, color,
|
||||
velocity / (float)TREE_SCALE, gravity, damping, updateScript);
|
||||
|
||||
// If we wanted to be able to edit this particle after shooting, then we could store this value
|
||||
// and use it for editing later. But we don't care about that for "shooting" and therefore we just
|
||||
// clean up our memory now. deleting a ParticleEditHandle does not effect the underlying particle,
|
||||
// it just removes your ability to edit that particle later.
|
||||
delete particleEditHandle;
|
||||
}
|
||||
|
||||
void Application::makeParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
||||
// Caller is responsible for managing this EditableParticle
|
||||
ParticleEditHandle* Application::makeParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity, float damping, QString updateScript) {
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
ParticleDetail addParticleDetail = { position, radius, {color.red, color.green, color.blue },
|
||||
velocity, gravity, damping, updateScript };
|
||||
|
||||
// queue the packet
|
||||
_particleEditSender.queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD, 1, &addParticleDetail);
|
||||
|
||||
// release them
|
||||
_particleEditSender.releaseQueuedMessages();
|
||||
ParticleEditHandle* particleEditHandle = new ParticleEditHandle(&_particleEditSender, _particles.getTree());
|
||||
particleEditHandle->createParticle(position, radius, color, velocity, gravity, damping, updateScript);
|
||||
return particleEditHandle;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4297,6 +4302,11 @@ void* Application::networkReceive(void* args) {
|
|||
Q_ARG(QByteArray, QByteArray((char*) app->_incomingPacket, bytesReceived)));
|
||||
break;
|
||||
|
||||
case PACKET_TYPE_PARTICLE_ADD_RESPONSE:
|
||||
// look up our ParticleEditHanders....
|
||||
ParticleEditHandle::handleAddResponse(app->_incomingPacket, bytesReceived);
|
||||
break;
|
||||
|
||||
case PACKET_TYPE_PARTICLE_DATA:
|
||||
case PACKET_TYPE_VOXEL_DATA:
|
||||
case PACKET_TYPE_VOXEL_ERASE:
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "ui/RearMirrorTools.h"
|
||||
#include "ui/LodToolsDialog.h"
|
||||
#include "ParticleTreeRenderer.h"
|
||||
#include "ParticleEditHandle.h"
|
||||
|
||||
class QAction;
|
||||
class QActionGroup;
|
||||
|
@ -120,7 +121,7 @@ public:
|
|||
void wheelEvent(QWheelEvent* event);
|
||||
|
||||
void shootParticle(); // shoots a particle in the direction you're looking
|
||||
void makeParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
||||
ParticleEditHandle* makeParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity, float damping, QString updateScript);
|
||||
|
||||
void makeVoxel(glm::vec3 position,
|
||||
|
|
|
@ -34,6 +34,9 @@ public:
|
|||
virtual void renderElement(OctreeElement* element, RenderArgs* args);
|
||||
|
||||
void update();
|
||||
|
||||
ParticleTree* getTree() { return (ParticleTree*)_tree; }
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
|
|
|
@ -58,15 +58,21 @@ void VoxelPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr, uns
|
|||
|
||||
Node* voxelServer = NodeList::getInstance()->nodeWithAddress(senderSockAddr);
|
||||
if (voxelServer && *voxelServer->getActiveSocket() == senderSockAddr) {
|
||||
if (packetData[0] == PACKET_TYPE_PARTICLE_DATA) {
|
||||
//printf("VoxelPacketProcessor::processPacket().... got PACKET_TYPE_PARTICLE_DATA\n");
|
||||
app->_particles.processDatagram(QByteArray((char*) packetData, messageLength), senderSockAddr);
|
||||
} else if (packetData[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
|
||||
app->_environment.parseData(senderSockAddr, packetData, messageLength);
|
||||
} else {
|
||||
app->_voxels.setDataSourceUUID(voxelServer->getUUID());
|
||||
app->_voxels.parseData(packetData, messageLength);
|
||||
app->_voxels.setDataSourceUUID(QUuid());
|
||||
|
||||
switch(packetData[0]) {
|
||||
case PACKET_TYPE_PARTICLE_DATA: {
|
||||
app->_particles.processDatagram(QByteArray((char*) packetData, messageLength), senderSockAddr);
|
||||
} break;
|
||||
|
||||
case PACKET_TYPE_ENVIRONMENT_DATA: {
|
||||
app->_environment.parseData(senderSockAddr, packetData, messageLength);
|
||||
} break;
|
||||
|
||||
default : {
|
||||
app->_voxels.setDataSourceUUID(voxelServer->getUUID());
|
||||
app->_voxels.parseData(packetData, messageLength);
|
||||
app->_voxels.setDataSourceUUID(QUuid());
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,9 @@ using namespace std;
|
|||
const float FINGERTIP_VOXEL_SIZE = 0.05;
|
||||
const int TOY_BALL_HAND = 1;
|
||||
const float TOY_BALL_RADIUS = 0.05f;
|
||||
const glm::vec3 TOYBALL_GRAVITY (0, -1, 0);
|
||||
float TOYBALL_DAMPING = 1.f;
|
||||
const float TOY_BALL_DAMPING = 0.99f;
|
||||
const glm::vec3 TOY_BALL_GRAVITY = glm::vec3(0,-1,0);
|
||||
const QString TOY_BALL_UPDATE_SCRIPT("");
|
||||
const float PALM_COLLISION_RADIUS = 0.03f;
|
||||
|
||||
Hand::Hand(Avatar* owningAvatar) :
|
||||
|
@ -38,8 +39,10 @@ Hand::Hand(Avatar* owningAvatar) :
|
|||
_toyBallPosition(0),
|
||||
_toyBallVelocity(0),
|
||||
_toyBallInHand(false),
|
||||
_hasToyBall(false),
|
||||
_ballParticleEditHandle(NULL),
|
||||
_pitchUpdate(0)
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
void Hand::init() {
|
||||
|
@ -56,55 +59,92 @@ void Hand::reset() {
|
|||
}
|
||||
|
||||
void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) {
|
||||
if (palm.getControllerButtons() & BUTTON_FWD) {
|
||||
// If grabbing toy ball, add forces to it
|
||||
if (!_toyBallInHand) {
|
||||
// Test for whether close enough to catch and catch
|
||||
bool isCaught = true;
|
||||
if (isCaught) {
|
||||
_toyBallInHand = true;
|
||||
}
|
||||
}
|
||||
if (_toyBallInHand) {
|
||||
// Ball is in hand
|
||||
_toyBallPosition = fingerTipPosition;
|
||||
_toyBallVelocity = glm::vec3(0);
|
||||
|
||||
}
|
||||
} else {
|
||||
// If toy ball just released, add velocity to it!
|
||||
if (_toyBallInHand) {
|
||||
_toyBallInHand = false;
|
||||
glm::vec3 handVelocity = palm.getRawVelocity();
|
||||
glm::vec3 fingerTipVelocity = palm.getTipVelocity();
|
||||
glm::quat avatarRotation = _owningAvatar->getOrientation();
|
||||
//printVector(avatarRotation * handVelocity);
|
||||
_toyBallVelocity += avatarRotation * fingerTipVelocity;
|
||||
// Is the controller button being held down....
|
||||
if (palm.getControllerButtons() & BUTTON_FWD) {
|
||||
// If grabbing toy ball, add forces to it.
|
||||
|
||||
// If we don't currently have a ball in hand, then create it...
|
||||
if (!_toyBallInHand) {
|
||||
// Test for whether close enough to catch and catch....
|
||||
|
||||
// isCaught is also used as "creating" a new ball... for now, this section is the
|
||||
// create new ball portion of the code...
|
||||
bool isCaught = true;
|
||||
if (isCaught) {
|
||||
_toyBallInHand = true;
|
||||
_hasToyBall = true;
|
||||
|
||||
// create the ball, call MakeParticle, and use the resulting ParticleEditHandle to
|
||||
// manage the newly created particle.
|
||||
// Create a particle on the particle server
|
||||
xColor color = { 255, 255, 0}; // Slightly different color on server
|
||||
glm::vec3 gravity = glm::vec3(0, -1, 0);
|
||||
float damping = 0.99f;
|
||||
QString updateScript("");
|
||||
Application::getInstance()->makeParticle(fingerTipPosition / (float)TREE_SCALE,
|
||||
|
||||
_ballParticleEditHandle = Application::getInstance()->makeParticle(fingerTipPosition / (float)TREE_SCALE,
|
||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||
color,
|
||||
_toyBallVelocity / (float)TREE_SCALE,
|
||||
gravity / (float) TREE_SCALE, damping, updateScript);
|
||||
TOY_BALL_GRAVITY / (float) TREE_SCALE,
|
||||
TOY_BALL_DAMPING,
|
||||
TOY_BALL_UPDATE_SCRIPT);
|
||||
}
|
||||
}
|
||||
// Simulate toy ball
|
||||
_toyBallPosition += _toyBallVelocity * deltaTime;
|
||||
if (_toyBallInHand) {
|
||||
// Ball is in hand
|
||||
_toyBallPosition = fingerTipPosition;
|
||||
_toyBallVelocity = glm::vec3(0);
|
||||
|
||||
xColor color = { 255, 255, 0}; // Slightly different color on server
|
||||
|
||||
_ballParticleEditHandle->updateParticle(fingerTipPosition / (float)TREE_SCALE,
|
||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||
color,
|
||||
_toyBallVelocity / (float)TREE_SCALE,
|
||||
TOY_BALL_GRAVITY / (float) TREE_SCALE,
|
||||
TOY_BALL_DAMPING,
|
||||
TOY_BALL_UPDATE_SCRIPT);
|
||||
}
|
||||
} else {
|
||||
// If toy ball just released, add velocity to it!
|
||||
if (_toyBallInHand) {
|
||||
|
||||
if (!_toyBallInHand) {
|
||||
_toyBallVelocity += TOYBALL_GRAVITY * deltaTime;
|
||||
_toyBallInHand = false;
|
||||
glm::vec3 handVelocity = palm.getRawVelocity();
|
||||
glm::vec3 fingerTipVelocity = palm.getTipVelocity();
|
||||
glm::quat avatarRotation = _owningAvatar->getOrientation();
|
||||
//printVector(avatarRotation * handVelocity);
|
||||
_toyBallVelocity += avatarRotation * fingerTipVelocity;
|
||||
|
||||
xColor color = { 255, 255, 0}; // Slightly different color on server
|
||||
_ballParticleEditHandle->updateParticle(fingerTipPosition / (float)TREE_SCALE,
|
||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||
color,
|
||||
_toyBallVelocity / (float)TREE_SCALE,
|
||||
TOY_BALL_GRAVITY / (float) TREE_SCALE,
|
||||
TOY_BALL_DAMPING,
|
||||
TOY_BALL_UPDATE_SCRIPT);
|
||||
|
||||
// after releasing the ball, we free our ParticleEditHandle so we can't edit it further
|
||||
// note: deleting the edit handle doesn't effect the actual particle
|
||||
delete _ballParticleEditHandle;
|
||||
_ballParticleEditHandle = NULL;
|
||||
|
||||
}
|
||||
if (_toyBallPosition.y < 0.f) {
|
||||
_toyBallPosition.y = 0.f;
|
||||
_toyBallVelocity.y *= -1.f;
|
||||
}
|
||||
_toyBallVelocity -= (_toyBallVelocity * TOYBALL_DAMPING) * deltaTime;
|
||||
}
|
||||
// Simulate toy ball
|
||||
_toyBallPosition += _toyBallVelocity * deltaTime;
|
||||
|
||||
if (!_toyBallInHand) {
|
||||
_toyBallVelocity += TOY_BALL_GRAVITY * deltaTime;
|
||||
}
|
||||
if (_toyBallPosition.y < 0.f) {
|
||||
_toyBallPosition.y = 0.f;
|
||||
_toyBallVelocity.y *= -1.f;
|
||||
}
|
||||
|
||||
if (_hasToyBall) {
|
||||
_toyBallVelocity -= (_toyBallVelocity * TOY_BALL_DAMPING) * deltaTime;
|
||||
//printf("applying damping to TOY_BALL deltaTime=%f\n",deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
void Hand::simulate(float deltaTime, bool isMine) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <AvatarData.h>
|
||||
#include <HandData.h>
|
||||
#include <ParticleEditHandle.h>
|
||||
|
||||
#include "Balls.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
@ -26,9 +27,11 @@
|
|||
#include "devices/SerialInterface.h"
|
||||
#include "VoxelSystem.h"
|
||||
|
||||
|
||||
class Avatar;
|
||||
class ProgramObject;
|
||||
|
||||
|
||||
class Hand : public HandData {
|
||||
public:
|
||||
Hand(Avatar* owningAvatar);
|
||||
|
@ -95,7 +98,9 @@ private:
|
|||
|
||||
glm::vec3 _toyBallPosition;
|
||||
glm::vec3 _toyBallVelocity;
|
||||
bool _toyBallInHand;
|
||||
bool _toyBallInHand;
|
||||
bool _hasToyBall;
|
||||
ParticleEditHandle* _ballParticleEditHandle;
|
||||
|
||||
float _pitchUpdate;
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ void OctreeInboundPacketProcessor::resetStats() {
|
|||
void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr,
|
||||
unsigned char* packetData, ssize_t packetLength) {
|
||||
|
||||
bool debugProcessPacket = true; //_myServer->wantsVerboseDebug();
|
||||
bool debugProcessPacket = _myServer->wantsVerboseDebug();
|
||||
|
||||
if (debugProcessPacket) {
|
||||
printf("OctreeInboundPacketProcessor::processPacket() packetData=%p packetLength=%ld\n", packetData, packetLength);
|
||||
|
@ -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());
|
||||
|
|
|
@ -506,23 +506,6 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
trueBytesSent += _myServer->sendSpecialPacket(node);
|
||||
truePacketsSent++;
|
||||
packetsSentThisInterval++;
|
||||
|
||||
/**
|
||||
int numBytesPacketHeader = populateTypeAndVersion(_tempOutputBuffer, PACKET_TYPE_ENVIRONMENT_DATA);
|
||||
int envPacketLength = numBytesPacketHeader;
|
||||
int environmentsToSend = _myServer->getSendMinimalEnvironment() ? 1 : _myServer->getEnvironmentDataCount();
|
||||
|
||||
for (int i = 0; i < environmentsToSend; i++) {
|
||||
envPacketLength += _myServer->getEnvironmentData(i)->getBroadcastData(_tempOutputBuffer + envPacketLength);
|
||||
}
|
||||
|
||||
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) _tempOutputBuffer, envPacketLength,
|
||||
node->getActiveSocket()->getAddress(),
|
||||
node->getActiveSocket()->getPort());
|
||||
trueBytesSent += envPacketLength;
|
||||
truePacketsSent++;
|
||||
packetsSentThisInterval++;
|
||||
**/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -27,9 +27,6 @@ OctreeRenderer::~OctreeRenderer() {
|
|||
}
|
||||
|
||||
void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
|
||||
|
||||
|
||||
|
||||
bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
bool extraDebugging = false; // Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging)
|
||||
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails);
|
||||
|
@ -38,6 +35,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Hifi
|
|||
int packetLength = dataByteArray.size();
|
||||
|
||||
unsigned char command = *packetData;
|
||||
|
||||
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||
|
||||
PACKET_TYPE expectedType = getExpectedPacketType();
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
virtual void renderElement(OctreeElement* element, RenderArgs* args) = 0;
|
||||
|
||||
/// process incoming data
|
||||
void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
|
||||
virtual void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
|
||||
|
||||
/// initialize and GPU/rendering related resources
|
||||
void init();
|
||||
|
|
|
@ -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,36 @@ 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* node) {
|
||||
unsigned char outputBuffer[MAX_PACKET_SIZE];
|
||||
unsigned char* copyAt = outputBuffer;
|
||||
|
||||
int numBytesPacketHeader = populateTypeAndVersion(outputBuffer, PACKET_TYPE_PARTICLE_ADD_RESPONSE);
|
||||
int packetLength = numBytesPacketHeader;
|
||||
copyAt += numBytesPacketHeader;
|
||||
|
||||
// encode the creatorTokenID
|
||||
uint32_t creatorTokenID = newParticle.getCreatorTokenID();
|
||||
memcpy(copyAt, &creatorTokenID, sizeof(creatorTokenID));
|
||||
copyAt += sizeof(creatorTokenID);
|
||||
packetLength += sizeof(creatorTokenID);
|
||||
|
||||
// encode the particle ID
|
||||
uint32_t particleID = newParticle.getID();
|
||||
memcpy(copyAt, &particleID, sizeof(particleID));
|
||||
copyAt += sizeof(particleID);
|
||||
packetLength += sizeof(particleID);
|
||||
|
||||
NodeList::getInstance()->getNodeSocket().writeDatagram((char*) outputBuffer, packetLength,
|
||||
node->getActiveSocket()->getAddress(),
|
||||
node->getActiveSocket()->getPort());
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
};
|
||||
|
||||
|
|
|
@ -19,23 +19,27 @@ uint32_t Particle::_nextID = 0;
|
|||
|
||||
|
||||
Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||
float damping, glm::vec3 gravity, QString updateScript) {
|
||||
float damping, glm::vec3 gravity, QString updateScript, uint32_t id) {
|
||||
|
||||
init(position, radius, color, velocity, damping, gravity, updateScript);
|
||||
init(position, radius, color, velocity, damping, gravity, updateScript, id);
|
||||
}
|
||||
|
||||
Particle::Particle() {
|
||||
rgbColor noColor = { 0, 0, 0 };
|
||||
init(glm::vec3(0,0,0), 0, noColor, glm::vec3(0,0,0), DEFAULT_DAMPING, DEFAULT_GRAVITY, DEFAULT_SCRIPT);
|
||||
init(glm::vec3(0,0,0), 0, noColor, glm::vec3(0,0,0), DEFAULT_DAMPING, DEFAULT_GRAVITY, DEFAULT_SCRIPT, NEW_PARTICLE);
|
||||
}
|
||||
|
||||
Particle::~Particle() {
|
||||
}
|
||||
|
||||
void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||
float damping, glm::vec3 gravity, QString updateScript) {
|
||||
_id = _nextID;
|
||||
_nextID++;
|
||||
float damping, glm::vec3 gravity, QString updateScript, uint32_t id) {
|
||||
if (id == NEW_PARTICLE) {
|
||||
_id = _nextID;
|
||||
_nextID++;
|
||||
} else {
|
||||
_id = id;
|
||||
}
|
||||
_lastUpdated = usecTimestampNow();
|
||||
|
||||
_position = position;
|
||||
|
@ -146,6 +150,8 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
_updateScript = tempString;
|
||||
dataAt += scriptLength;
|
||||
bytesRead += scriptLength;
|
||||
|
||||
//printf("Particle::readParticleDataFromBuffer()... "); debugDump();
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -163,6 +169,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 +236,20 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
dataAt += scriptLength;
|
||||
processedBytes += scriptLength;
|
||||
|
||||
const bool wantDebugging = false;
|
||||
if (wantDebugging) {
|
||||
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) {
|
||||
|
@ -217,7 +260,8 @@ 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, details[i].position.z, details[i].radius);
|
||||
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);
|
||||
|
@ -233,6 +277,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 +334,14 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
memcpy(copyAt, qPrintable(details[i].updateScript), scriptLength);
|
||||
copyAt += scriptLength;
|
||||
sizeOut += scriptLength;
|
||||
|
||||
bool wantDebugging = false;
|
||||
if (wantDebugging) {
|
||||
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;
|
||||
|
@ -308,6 +378,7 @@ void Particle::update() {
|
|||
// handle damping
|
||||
glm::vec3 dampingResistance = _velocity * _damping;
|
||||
_velocity -= dampingResistance * timeElapsed;
|
||||
//printf("applying damping to Particle timeElapsed=%f\n",timeElapsed);
|
||||
|
||||
_lastUpdated = now;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -39,14 +43,15 @@ class Particle {
|
|||
public:
|
||||
Particle();
|
||||
Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||
float damping = DEFAULT_DAMPING, glm::vec3 gravity = DEFAULT_GRAVITY, QString updateScript = DEFAULT_SCRIPT);
|
||||
float damping = DEFAULT_DAMPING, glm::vec3 gravity = DEFAULT_GRAVITY, QString updateScript = DEFAULT_SCRIPT,
|
||||
uint32_t id = NEW_PARTICLE);
|
||||
|
||||
/// 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();
|
||||
virtual void init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||
float damping, glm::vec3 gravity, QString updateScript);
|
||||
float damping, glm::vec3 gravity, QString updateScript, uint32_t id);
|
||||
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
const rgbColor& getColor() const { return _color; }
|
||||
|
@ -59,6 +64,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 +80,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 +91,7 @@ public:
|
|||
|
||||
void update();
|
||||
|
||||
void debugDump() const;
|
||||
protected:
|
||||
void runScript();
|
||||
static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3);
|
||||
|
@ -101,6 +110,9 @@ protected:
|
|||
glm::vec3 _gravity;
|
||||
float _damping;
|
||||
QString _updateScript;
|
||||
|
||||
uint32_t _creatorTokenID;
|
||||
bool _newlyCreated;
|
||||
};
|
||||
|
||||
class ParticleScriptObject : public QObject {
|
||||
|
@ -115,16 +127,19 @@ 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;
|
||||
};
|
||||
|
||||
|
||||
#endif /* defined(__hifi__Particle__) */
|
103
libraries/particles/src/ParticleEditHandle.cpp
Normal file
103
libraries/particles/src/ParticleEditHandle.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// ParticleEditHandle.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/4/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
#include "Particle.h"
|
||||
#include "ParticleEditHandle.h"
|
||||
#include "ParticleEditPacketSender.h"
|
||||
#include "ParticleTree.h"
|
||||
|
||||
std::map<uint32_t,ParticleEditHandle*> ParticleEditHandle::_allHandles;
|
||||
uint32_t ParticleEditHandle::_nextCreatorTokenID = 0;
|
||||
|
||||
|
||||
ParticleEditHandle::ParticleEditHandle(ParticleEditPacketSender* packetSender, ParticleTree* localTree) {
|
||||
_creatorTokenID = _nextCreatorTokenID;
|
||||
_nextCreatorTokenID++;
|
||||
_id = NEW_PARTICLE;
|
||||
_isKnownID = false;
|
||||
_packetSender = packetSender;
|
||||
_localTree = localTree;
|
||||
|
||||
_allHandles[_creatorTokenID] = this;
|
||||
}
|
||||
|
||||
ParticleEditHandle::~ParticleEditHandle() {
|
||||
// remove us from our _allHandles map
|
||||
_allHandles.erase(_allHandles.find(_creatorTokenID));
|
||||
}
|
||||
|
||||
void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity, float damping, QString updateScript) {
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(),
|
||||
position, radius, {color.red, color.green, color.blue },
|
||||
velocity, gravity, damping, updateScript, _creatorTokenID };
|
||||
|
||||
// queue the packet
|
||||
_packetSender->queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, 1, &addParticleDetail);
|
||||
|
||||
// release them
|
||||
_packetSender->releaseQueuedMessages();
|
||||
|
||||
// if we have a local tree, also update it...
|
||||
if (_localTree) {
|
||||
// we can't really do this here, because if we create a particle locally, we'll get a ghost particle
|
||||
// because we can't really handle updating/deleting it locally
|
||||
}
|
||||
}
|
||||
|
||||
bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity, float damping, QString updateScript) {
|
||||
|
||||
if (!isKnownID()) {
|
||||
return false; // not allowed until we know the id
|
||||
}
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
ParticleDetail newParticleDetail = { _id, usecTimestampNow(),
|
||||
position, radius, {color.red, color.green, color.blue },
|
||||
velocity, gravity, damping, updateScript, _creatorTokenID };
|
||||
|
||||
// queue the packet
|
||||
_packetSender->queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, 1, &newParticleDetail);
|
||||
|
||||
// release them
|
||||
_packetSender->releaseQueuedMessages();
|
||||
|
||||
// if we have a local tree, also update it...
|
||||
if (_localTree) {
|
||||
rgbColor rcolor = {color.red, color.green, color.blue };
|
||||
Particle tempParticle(position, radius, rcolor, velocity, damping, gravity, updateScript, _id);
|
||||
_localTree->storeParticle(tempParticle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParticleEditHandle::handleAddResponse(unsigned char* packetData , int packetLength) {
|
||||
unsigned char* dataAt = packetData;
|
||||
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||
dataAt += numBytesPacketHeader;
|
||||
|
||||
uint32_t creatorTokenID;
|
||||
memcpy(&creatorTokenID, dataAt, sizeof(creatorTokenID));
|
||||
dataAt += sizeof(creatorTokenID);
|
||||
|
||||
uint32_t particleID;
|
||||
memcpy(&particleID, dataAt, sizeof(particleID));
|
||||
dataAt += sizeof(particleID);
|
||||
|
||||
// find this particle in the _allHandles map
|
||||
if (_allHandles.find(creatorTokenID) != _allHandles.end()) {
|
||||
ParticleEditHandle* theHandle = _allHandles[creatorTokenID];
|
||||
theHandle->_id = particleID;
|
||||
theHandle->_isKnownID = true;
|
||||
}
|
||||
}
|
52
libraries/particles/src/ParticleEditHandle.h
Normal file
52
libraries/particles/src/ParticleEditHandle.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// ParticleEditHandle.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/4/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __hifi__ParticleEditHandle__
|
||||
#define __hifi__ParticleEditHandle__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <OctreePacketData.h>
|
||||
|
||||
class ParticleEditPacketSender;
|
||||
class ParticleTree;
|
||||
|
||||
class ParticleEditHandle {
|
||||
public:
|
||||
ParticleEditHandle(ParticleEditPacketSender* packetSender, ParticleTree* localTree);
|
||||
~ParticleEditHandle();
|
||||
|
||||
uint32_t getCreatorTokenID() const { return _creatorTokenID; }
|
||||
uint32_t getID() const { return _id; }
|
||||
|
||||
bool isKnownID() const { return _isKnownID; }
|
||||
|
||||
void createParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity, float damping, QString updateScript);
|
||||
|
||||
bool updateParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
||||
glm::vec3 gravity, float damping, QString updateScript);
|
||||
|
||||
static void handleAddResponse(unsigned char* packetData , int packetLength);
|
||||
private:
|
||||
uint32_t _creatorTokenID;
|
||||
uint32_t _id;
|
||||
bool _isKnownID;
|
||||
static uint32_t _nextCreatorTokenID;
|
||||
static std::map<uint32_t,ParticleEditHandle*> _allHandles;
|
||||
ParticleEditPacketSender* _packetSender;
|
||||
ParticleTree* _localTree;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__ParticleEditHandle__) */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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,17 +65,19 @@ 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: {
|
||||
processedBytes = 0;
|
||||
} break;
|
||||
|
@ -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);
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue