Merge branch 'master' of https://github.com/worklist/hifi into 19483

This commit is contained in:
stojce 2014-01-05 23:45:37 +01:00
commit 11bf9b8a50
10 changed files with 928 additions and 876 deletions

View file

@ -18,6 +18,7 @@
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <UUID.h> #include <UUID.h>
#include <VoxelConstants.h> #include <VoxelConstants.h>
#include <ParticlesScriptingInterface.h>
#include "Agent.h" #include "Agent.h"

View file

@ -44,6 +44,7 @@
#include <OctalCode.h> #include <OctalCode.h>
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <PairingHandler.h> #include <PairingHandler.h>
#include <ParticlesScriptingInterface.h>
#include <PerfStat.h> #include <PerfStat.h>
#include <UUID.h> #include <UUID.h>
#include <VoxelSceneStats.h> #include <VoxelSceneStats.h>
@ -239,6 +240,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_voxelEditSender.setVoxelServerJurisdictions(&_voxelServerJurisdictions); _voxelEditSender.setVoxelServerJurisdictions(&_voxelServerJurisdictions);
_particleEditSender.setServerJurisdictions(&_particleServerJurisdictions); _particleEditSender.setServerJurisdictions(&_particleServerJurisdictions);
Particle::setVoxelEditPacketSender(&_voxelEditSender);
Particle::setParticleEditPacketSender(&_particleEditSender);
// For now we're going to set the PPS for outbound packets to be super high, this is // 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 // 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 // allow you to move a particle around in your hand
@ -1555,6 +1559,10 @@ void Application::shootParticle() {
" var myColor = Particle.getColor();" " var myColor = Particle.getColor();"
" print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " " print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); "
" Particle.setColor(voxelColor); " " Particle.setColor(voxelColor); "
" var voxelAt = voxel.getPosition();"
" var voxelScale = voxel.getScale();"
" Voxels.queueVoxelDelete(voxelAt.x, voxelAt.y, voxelAt.z, voxelScale); "
" print('Voxels.queueVoxelDelete(' + voxelAt.x + ', ' + voxelAt.y + ', ' + voxelAt.z + ', ' + voxelScale + ')... \\n'); "
" } " " } "
" Particle.collisionWithVoxel.connect(collisionWithVoxel); " ); " Particle.collisionWithVoxel.connect(collisionWithVoxel); " );

View file

@ -129,7 +129,8 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in
_totalPackets++; _totalPackets++;
if (debug) { if (debug) {
qDebug() << "Adding stats to packet at " << now << " [" << _totalPackets <<"]: sequence: " << sequence << qDebug() << "Adding stats to packet at " << now << " [" << _totalPackets <<"]: sequence: " << sequence <<
" size: " << nodeData->getPacketLength() << " [" << _totalBytes << " statsMessageLength: " << statsMessageLength <<
" original size: " << nodeData->getPacketLength() << " [" << _totalBytes <<
"] wasted bytes:" << thisWastedBytes << " [" << _totalWastedBytes << "]\n"; "] wasted bytes:" << thisWastedBytes << " [" << _totalWastedBytes << "]\n";
} }
@ -211,6 +212,7 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in
/// Version of voxel distributor that sends the deepest LOD level at once /// Version of voxel distributor that sends the deepest LOD level at once
int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, bool viewFrustumChanged) { int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, bool viewFrustumChanged) {
bool forceDebugging = false;
int truePacketsSent = 0; int truePacketsSent = 0;
int trueBytesSent = 0; int trueBytesSent = 0;
@ -231,16 +233,19 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
// then let's just send that waiting packet. // then let's just send that waiting packet.
if (!nodeData->getCurrentPacketFormatMatches()) { if (!nodeData->getCurrentPacketFormatMatches()) {
if (nodeData->isPacketWaiting()) { if (nodeData->isPacketWaiting()) {
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
printf("wantColor=%s wantCompression=%s SENDING PARTIAL PACKET! currentPacketIsColor=%s currentPacketIsCompressed=%s\n", qDebug("about to call handlePacketSend() .... line: %d -- format change "
"wantColor=%s wantCompression=%s SENDING PARTIAL PACKET! currentPacketIsColor=%s "
"currentPacketIsCompressed=%s\n",
__LINE__,
debug::valueOf(wantColor), debug::valueOf(wantCompression), debug::valueOf(wantColor), debug::valueOf(wantCompression),
debug::valueOf(nodeData->getCurrentPacketIsColor()), debug::valueOf(nodeData->getCurrentPacketIsColor()),
debug::valueOf(nodeData->getCurrentPacketIsCompressed()) ); debug::valueOf(nodeData->getCurrentPacketIsCompressed()) );
} }
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent); packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
} else { } else {
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
printf("wantColor=%s wantCompression=%s FIXING HEADER! currentPacketIsColor=%s currentPacketIsCompressed=%s\n", qDebug("wantColor=%s wantCompression=%s FIXING HEADER! currentPacketIsColor=%s currentPacketIsCompressed=%s\n",
debug::valueOf(wantColor), debug::valueOf(wantCompression), debug::valueOf(wantColor), debug::valueOf(wantCompression),
debug::valueOf(nodeData->getCurrentPacketIsColor()), debug::valueOf(nodeData->getCurrentPacketIsColor()),
debug::valueOf(nodeData->getCurrentPacketIsCompressed()) ); debug::valueOf(nodeData->getCurrentPacketIsCompressed()) );
@ -252,7 +257,7 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE); targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
} }
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
printf("line:%d _packetData.changeSettings() wantCompression=%s targetSize=%d\n",__LINE__, qDebug("line:%d _packetData.changeSettings() wantCompression=%s targetSize=%d\n", __LINE__,
debug::valueOf(wantCompression), targetSize); debug::valueOf(wantCompression), targetSize);
} }
@ -260,7 +265,7 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
} }
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
printf("wantColor/isColor=%s/%s wantCompression/isCompressed=%s/%s viewFrustumChanged=%s, getWantLowResMoving()=%s\n", qDebug("wantColor/isColor=%s/%s wantCompression/isCompressed=%s/%s viewFrustumChanged=%s, getWantLowResMoving()=%s\n",
debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()), debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()),
debug::valueOf(wantCompression), debug::valueOf(nodeData->getCurrentPacketIsCompressed()), debug::valueOf(wantCompression), debug::valueOf(nodeData->getCurrentPacketIsCompressed()),
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->getWantLowResMoving())); debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->getWantLowResMoving()));
@ -268,8 +273,8 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
const ViewFrustum* lastViewFrustum = wantDelta ? &nodeData->getLastKnownViewFrustum() : NULL; const ViewFrustum* lastViewFrustum = wantDelta ? &nodeData->getLastKnownViewFrustum() : NULL;
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
printf("packetDistributor() viewFrustumChanged=%s, nodeBag.isEmpty=%s, viewSent=%s\n", qDebug("packetDistributor() viewFrustumChanged=%s, nodeBag.isEmpty=%s, viewSent=%s\n",
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()), debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()),
debug::valueOf(nodeData->getViewSent()) debug::valueOf(nodeData->getViewSent())
); );
@ -279,17 +284,17 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
// the current view frustum for things to send. // the current view frustum for things to send.
if (viewFrustumChanged || nodeData->nodeBag.isEmpty()) { if (viewFrustumChanged || nodeData->nodeBag.isEmpty()) {
uint64_t now = usecTimestampNow(); uint64_t now = usecTimestampNow();
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
printf("(viewFrustumChanged=%s || nodeData->nodeBag.isEmpty() =%s)...\n", qDebug("(viewFrustumChanged=%s || nodeData->nodeBag.isEmpty() =%s)...\n",
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty())); debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()));
if (nodeData->getLastTimeBagEmpty() > 0) { if (nodeData->getLastTimeBagEmpty() > 0) {
float elapsedSceneSend = (now - nodeData->getLastTimeBagEmpty()) / 1000000.0f; float elapsedSceneSend = (now - nodeData->getLastTimeBagEmpty()) / 1000000.0f;
if (viewFrustumChanged) { if (viewFrustumChanged) {
printf("viewFrustumChanged resetting after elapsed time to send scene = %f seconds", elapsedSceneSend); qDebug("viewFrustumChanged resetting after elapsed time to send scene = %f seconds", elapsedSceneSend);
} else { } else {
printf("elapsed time to send scene = %f seconds", elapsedSceneSend); qDebug("elapsed time to send scene = %f seconds", elapsedSceneSend);
} }
printf(" [occlusionCulling:%s, wantDelta:%s, wantColor:%s ]\n", qDebug(" [occlusionCulling:%s, wantDelta:%s, wantColor:%s ]\n",
debug::valueOf(nodeData->getWantOcclusionCulling()), debug::valueOf(wantDelta), debug::valueOf(nodeData->getWantOcclusionCulling()), debug::valueOf(wantDelta),
debug::valueOf(wantColor)); debug::valueOf(wantColor));
} }
@ -316,9 +321,17 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
unsigned long encodeTime = nodeData->stats.getTotalEncodeTime(); unsigned long encodeTime = nodeData->stats.getTotalEncodeTime();
unsigned long elapsedTime = nodeData->stats.getElapsedTime(); unsigned long elapsedTime = nodeData->stats.getElapsedTime();
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
if (_myServer->wantsDebugSending()) { if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
qDebug("about to call handlePacketSend() .... line: %d -- completed scene \n", __LINE__ );
}
int packetsJustSent = handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
packetsSentThisInterval += packetsJustSent;
if (forceDebugging) {
qDebug("packetsJustSent=%d packetsSentThisInterval=%d\n", packetsJustSent, packetsSentThisInterval);
}
if (forceDebugging || _myServer->wantsDebugSending()) {
qDebug() << "Scene completed at " << usecTimestampNow() qDebug() << "Scene completed at " << usecTimestampNow()
<< "encodeTime:" << encodeTime << "encodeTime:" << encodeTime
<< " sleepTime:" << sleepTime << " sleepTime:" << sleepTime
@ -337,7 +350,7 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
nodeData->nodeBag.deleteAll(); nodeData->nodeBag.deleteAll();
} }
if (_myServer->wantsDebugSending()) { if (forceDebugging || _myServer->wantsDebugSending()) {
qDebug() << "Scene started at " << usecTimestampNow() qDebug() << "Scene started at " << usecTimestampNow()
<< " Packets:" << _totalPackets << " Packets:" << _totalPackets
<< " Bytes:" << _totalBytes << " Bytes:" << _totalBytes
@ -369,15 +382,16 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval()); int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n", qDebug("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(), truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
nodeData->getMaxOctreePacketsPerSecond(), clientMaxPacketsPerInterval); nodeData->getMaxOctreePacketsPerSecond(), clientMaxPacketsPerInterval);
} }
int extraPackingAttempts = 0; int extraPackingAttempts = 0;
bool completedScene = false;
while (somethingToSend && packetsSentThisInterval < maxPacketsPerInterval) { while (somethingToSend && packetsSentThisInterval < maxPacketsPerInterval) {
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n", qDebug("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(), truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
nodeData->getMaxOctreePacketsPerSecond(), clientMaxPacketsPerInterval); nodeData->getMaxOctreePacketsPerSecond(), clientMaxPacketsPerInterval);
} }
@ -409,6 +423,11 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
nodeData->stats.encodeStarted(); nodeData->stats.encodeStarted();
bytesWritten = _myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->nodeBag, params); bytesWritten = _myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->nodeBag, params);
// If after calling encodeTreeBitstream() there are no nodes left to send, then we know we've
// sent the entire scene. We want to know this below so we'll actually write this content into
// the packet and send it
completedScene = nodeData->nodeBag.isEmpty();
// if we're trying to fill a full size packet, then we use this logic to determine if we have a DIDNT_FIT case. // if we're trying to fill a full size packet, then we use this logic to determine if we have a DIDNT_FIT case.
if (_packetData.getTargetSize() == MAX_OCTREE_PACKET_DATA_SIZE) { if (_packetData.getTargetSize() == MAX_OCTREE_PACKET_DATA_SIZE) {
if (_packetData.hasContent() && bytesWritten == 0 && if (_packetData.hasContent() && bytesWritten == 0 &&
@ -434,12 +453,13 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
} }
// If the last node didn't fit, but we're in compressed mode, then we actually want to see if we can fit a // If the last node didn't fit, but we're in compressed mode, then we actually want to see if we can fit a
// little bit more in this packet. To do this we // little bit more in this packet. To do this we write into the packet, but don't send it yet, we'll
// keep attempting to write in compressed mode to add more compressed segments
// We only consider sending anything if there is something in the _packetData to send... But // We only consider sending anything if there is something in the _packetData to send... But
// if bytesWritten == 0 it means either the subTree couldn't fit or we had an empty bag... Both cases // if bytesWritten == 0 it means either the subTree couldn't fit or we had an empty bag... Both cases
// mean we should send the previous packet contents and reset it. // mean we should send the previous packet contents and reset it.
if (lastNodeDidntFit) { if (completedScene || lastNodeDidntFit) {
if (_packetData.hasContent()) { if (_packetData.hasContent()) {
// if for some reason the finalized size is greater than our available size, then probably the "compressed" // if for some reason the finalized size is greater than our available size, then probably the "compressed"
// form actually inflated beyond our padding, and in this case we will send the current packet, then // form actually inflated beyond our padding, and in this case we will send the current packet, then
@ -449,15 +469,16 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
if (writtenSize > nodeData->getAvailable()) { if (writtenSize > nodeData->getAvailable()) {
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
printf("writtenSize[%d] > available[%d] too big, sending packet as is.\n", qDebug("about to call handlePacketSend() .... line: %d -- "
writtenSize, nodeData->getAvailable()); "writtenSize[%d] > available[%d] too big, sending packet as is.\n",
__LINE__, writtenSize, nodeData->getAvailable());
} }
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent); packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
} }
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
printf("calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%d\n", qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%d\n",
nodeData->getAvailable(), _packetData.getFinalizedSize(), nodeData->getAvailable(), _packetData.getFinalizedSize(),
_packetData.getUncompressedSize(), _packetData.getTargetSize()); _packetData.getUncompressedSize(), _packetData.getTargetSize());
} }
@ -465,7 +486,7 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
extraPackingAttempts = 0; extraPackingAttempts = 0;
} }
// If we're not running compressed, the we know we can just send now. Or if we're running compressed, but // If we're not running compressed, then we know we can just send now. Or if we're running compressed, but
// the packet doesn't have enough space to bother attempting to pack more... // the packet doesn't have enough space to bother attempting to pack more...
bool sendNow = true; bool sendNow = true;
@ -477,6 +498,9 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
int targetSize = MAX_OCTREE_PACKET_DATA_SIZE; int targetSize = MAX_OCTREE_PACKET_DATA_SIZE;
if (sendNow) { if (sendNow) {
if (forceDebugging) {
qDebug("about to call handlePacketSend() .... line: %d -- sendNow = TRUE\n", __LINE__);
}
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent); packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
if (wantCompression) { if (wantCompression) {
targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE); targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
@ -491,7 +515,7 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) - COMPRESS_PADDING; targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) - COMPRESS_PADDING;
} }
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
printf("line:%d _packetData.changeSettings() wantCompression=%s targetSize=%d\n",__LINE__, qDebug("line:%d _packetData.changeSettings() wantCompression=%s targetSize=%d\n",__LINE__,
debug::valueOf(nodeData->getWantCompression()), targetSize); debug::valueOf(nodeData->getWantCompression()), targetSize);
} }
_packetData.changeSettings(nodeData->getWantCompression(), targetSize); // will do reset _packetData.changeSettings(nodeData->getWantCompression(), targetSize); // will do reset
@ -521,15 +545,21 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
if (elapsedmsec > 100) { if (elapsedmsec > 100) {
if (elapsedmsec > 1000) { if (elapsedmsec > 1000) {
int elapsedsec = (end - start)/1000000; int elapsedsec = (end - start)/1000000;
printf("WARNING! packetLoop() took %d seconds [%d milliseconds %d calls in compress] to generate %d bytes in %d packets %d nodes still to send\n", qDebug("WARNING! packetLoop() took %d seconds [%d milliseconds %d calls in compress] "
elapsedsec, elapsedCompressTimeMsecs, elapsedCompressCalls, trueBytesSent, truePacketsSent, nodeData->nodeBag.count()); "to generate %d bytes in %d packets %d nodes still to send\n",
elapsedsec, elapsedCompressTimeMsecs, elapsedCompressCalls,
trueBytesSent, truePacketsSent, nodeData->nodeBag.count());
} else { } else {
printf("WARNING! packetLoop() took %d milliseconds [%d milliseconds %d calls in compress] to generate %d bytes in %d packets, %d nodes still to send\n", qDebug("WARNING! packetLoop() took %d milliseconds [%d milliseconds %d calls in compress] "
elapsedmsec, elapsedCompressTimeMsecs, elapsedCompressCalls, trueBytesSent, truePacketsSent, nodeData->nodeBag.count()); "to generate %d bytes in %d packets, %d nodes still to send\n",
elapsedmsec, elapsedCompressTimeMsecs, elapsedCompressCalls,
trueBytesSent, truePacketsSent, nodeData->nodeBag.count());
} }
} else if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { } else if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
printf("packetLoop() took %d milliseconds [%d milliseconds %d calls in compress] to generate %d bytes in %d packets, %d nodes still to send\n", qDebug("packetLoop() took %d milliseconds [%d milliseconds %d calls in compress] "
elapsedmsec, elapsedCompressTimeMsecs, elapsedCompressCalls, trueBytesSent, truePacketsSent, nodeData->nodeBag.count()); "to generate %d bytes in %d packets, %d nodes still to send\n",
elapsedmsec, elapsedCompressTimeMsecs, elapsedCompressCalls,
trueBytesSent, truePacketsSent, nodeData->nodeBag.count());
} }
// if after sending packets we've emptied our bag, then we want to remember that we've sent all // if after sending packets we've emptied our bag, then we want to remember that we've sent all
@ -544,9 +574,11 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
} }
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n", qDebug("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d "
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(), "server PPI=%d nodePPS=%d nodePPI=%d\n",
nodeData->getMaxOctreePacketsPerSecond(), clientMaxPacketsPerInterval); truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval,
_myServer->getPacketsPerClientPerInterval(), nodeData->getMaxOctreePacketsPerSecond(),
clientMaxPacketsPerInterval);
} }
} // end if bag wasn't empty, and so we sent stuff... } // end if bag wasn't empty, and so we sent stuff...

View file

@ -1133,12 +1133,16 @@ bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCoun
if (!childToDelete->isLeaf()) { if (!childToDelete->isLeaf()) {
// delete all it's children // delete all it's children
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (childToDelete->getChildAtIndex(i)) {
deleteApproved = childToDelete->safeDeepDeleteChildAtIndex(i,recursionCount+1); deleteApproved = childToDelete->safeDeepDeleteChildAtIndex(i,recursionCount+1);
if (!deleteApproved) { if (!deleteApproved) {
break; // no point in continuing... break; // no point in continuing...
} }
} }
} }
} else {
deleteApproved = true; // because we got here after checking that delete was approved
}
if (deleteApproved) { if (deleteApproved) {
deleteChildAtIndex(childIndex); deleteChildAtIndex(childIndex);
_isDirty = true; _isDirty = true;

View file

@ -7,21 +7,25 @@
// //
// //
#include <QtScript/QScriptEngine>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <Octree.h>
#include <RegisteredMetaTypes.h> #include <RegisteredMetaTypes.h>
#include <SharedUtil.h> // usecTimestampNow() #include <SharedUtil.h> // usecTimestampNow()
#include <Octree.h>
#include <VoxelsScriptingInterface.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" #include "Particle.h"
uint32_t Particle::_nextID = 0; uint32_t Particle::_nextID = 0;
VoxelsScriptingInterface* Particle::_voxelsScriptingInterface = NULL; VoxelEditPacketSender* Particle::_voxelEditSender = NULL;
ParticlesScriptingInterface* Particle::_particlesScriptingInterface = 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,
@ -505,72 +509,59 @@ void Particle::update() {
void Particle::runUpdateScript() { void Particle::runUpdateScript() {
if (!_script.isEmpty()) { if (!_script.isEmpty()) {
ScriptEngine engine(_script); // no menu or controller interface...
QScriptEngine engine; if (_voxelEditSender) {
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
// register meta-type for glm::vec3 and rgbColor conversions }
registerMetaTypes(&engine); if (_particleEditSender) {
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
}
// Add the Particle object
ParticleScriptObject particleScriptable(this); ParticleScriptObject particleScriptable(this);
QScriptValue particleValue = engine.newQObject(&particleScriptable); engine.registerGlobalObject("Particle", &particleScriptable);
engine.globalObject().setProperty("Particle", particleValue);
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); // init and evaluate the script, but return so we can emit the collision
engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); engine.evaluate();
QScriptValue result = engine.evaluate(_script);
particleScriptable.emitUpdate(); particleScriptable.emitUpdate();
if (engine.hasUncaughtException()) { if (_voxelEditSender) {
int line = engine.uncaughtExceptionLineNumber(); _voxelEditSender->releaseQueuedMessages();
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n"; }
if (_particleEditSender) {
_particleEditSender->releaseQueuedMessages();
} }
} }
} }
void Particle::collisionWithParticle(Particle* other) { void Particle::collisionWithParticle(Particle* other) {
if (!_script.isEmpty()) { if (!_script.isEmpty()) {
ScriptEngine engine(_script); // no menu or controller interface...
QScriptEngine engine; if (_voxelEditSender) {
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
// register meta-type for glm::vec3 and rgbColor conversions }
registerMetaTypes(&engine); if (_particleEditSender) {
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
}
// Add the Particle object
ParticleScriptObject particleScriptable(this); ParticleScriptObject particleScriptable(this);
QScriptValue particleValue = engine.newQObject(&particleScriptable); engine.registerGlobalObject("Particle", &particleScriptable);
engine.globalObject().setProperty("Particle", particleValue);
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); // init and evaluate the script, but return so we can emit the collision
engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); 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); ParticleScriptObject otherParticleScriptable(other);
particleScriptable.emitCollisionWithParticle(&otherParticleScriptable); particleScriptable.emitCollisionWithParticle(&otherParticleScriptable);
if (getVoxelsScriptingInterface()) { if (_voxelEditSender) {
getVoxelsScriptingInterface()->getPacketSender()->releaseQueuedMessages(); _voxelEditSender->releaseQueuedMessages();
} }
if (_particleEditSender) {
if (getParticlesScriptingInterface()) { _particleEditSender->releaseQueuedMessages();
getParticlesScriptingInterface()->getPacketSender()->releaseQueuedMessages();
}
if (engine.hasUncaughtException()) {
int line = engine.uncaughtExceptionLineNumber();
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
} }
} }
} }
@ -578,45 +569,32 @@ void Particle::collisionWithParticle(Particle* other) {
void Particle::collisionWithVoxel(VoxelDetail* voxelDetails) { void Particle::collisionWithVoxel(VoxelDetail* voxelDetails) {
if (!_script.isEmpty()) { if (!_script.isEmpty()) {
QScriptEngine engine; ScriptEngine engine(_script); // no menu or controller interface...
// register meta-type for glm::vec3 and rgbColor conversions // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
registerMetaTypes(&engine); // 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); ParticleScriptObject particleScriptable(this);
QScriptValue particleValue = engine.newQObject(&particleScriptable); engine.registerGlobalObject("Particle", &particleScriptable);
engine.globalObject().setProperty("Particle", particleValue);
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); // init and evaluate the script, but return so we can emit the collision
engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); 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); VoxelDetailScriptObject voxelDetailsScriptable(voxelDetails);
particleScriptable.emitCollisionWithVoxel(&voxelDetailsScriptable); particleScriptable.emitCollisionWithVoxel(&voxelDetailsScriptable);
if (getVoxelsScriptingInterface()) { if (_voxelEditSender) {
getVoxelsScriptingInterface()->getPacketSender()->releaseQueuedMessages(); _voxelEditSender->releaseQueuedMessages();
} }
if (_particleEditSender) {
if (getParticlesScriptingInterface()) { _particleEditSender->releaseQueuedMessages();
getParticlesScriptingInterface()->getPacketSender()->releaseQueuedMessages();
}
if (engine.hasUncaughtException()) {
int line = engine.uncaughtExceptionLineNumber();
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
} }
} }
} }

View file

@ -21,6 +21,8 @@
class VoxelsScriptingInterface; class VoxelsScriptingInterface;
class ParticlesScriptingInterface; class ParticlesScriptingInterface;
class VoxelEditPacketSender;
class ParticleEditPacketSender;
const uint32_t NEW_PARTICLE = 0xFFFFFFFF; const uint32_t NEW_PARTICLE = 0xFFFFFFFF;
@ -122,18 +124,19 @@ public:
// similar to assignment/copy, but it handles keeping lifetime accurate // similar to assignment/copy, but it handles keeping lifetime accurate
void copyChangedProperties(const Particle& other); void copyChangedProperties(const Particle& other);
static VoxelsScriptingInterface* getVoxelsScriptingInterface() { return _voxelsScriptingInterface; } static VoxelEditPacketSender* getVoxelEditPacketSender() { return _voxelEditSender; }
static ParticlesScriptingInterface* getParticlesScriptingInterface() { return _particlesScriptingInterface; } static ParticleEditPacketSender* getParticleEditPacketSender() { return _particleEditSender; }
static void setVoxelsScriptingInterface(VoxelsScriptingInterface* interface) static void setVoxelEditPacketSender(VoxelEditPacketSender* interface)
{ _voxelsScriptingInterface = interface; } { _voxelEditSender = interface; }
static void setParticleEditPacketSender(ParticleEditPacketSender* interface)
{ _particleEditSender = interface; }
static void setParticlesScriptingInterface(ParticlesScriptingInterface* interface)
{ _particlesScriptingInterface = interface; }
protected: protected:
static VoxelsScriptingInterface* _voxelsScriptingInterface; static VoxelEditPacketSender* _voxelEditSender;
static ParticlesScriptingInterface* _particlesScriptingInterface; static ParticleEditPacketSender* _particleEditSender;
void runUpdateScript(); void runUpdateScript();
static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3); static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3);

View file

@ -19,11 +19,14 @@
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <UUID.h> #include <UUID.h>
#include <VoxelConstants.h> #include <VoxelConstants.h>
#include <ParticlesScriptingInterface.h>
#include <Sound.h> #include <Sound.h>
#include "ScriptEngine.h" #include "ScriptEngine.h"
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
int ScriptEngine::_scriptNumber = 1; int ScriptEngine::_scriptNumber = 1;
VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface; VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface;
ParticlesScriptingInterface ScriptEngine::_particlesScriptingInterface; ParticlesScriptingInterface ScriptEngine::_particlesScriptingInterface;
@ -41,6 +44,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
_scriptContents = scriptContents; _scriptContents = scriptContents;
_isFinished = false; _isFinished = false;
_isRunning = false; _isRunning = false;
_isInitialized = false;
// some clients will use these menu features // some clients will use these menu features
_wantMenuItems = wantMenuItems; _wantMenuItems = wantMenuItems;
@ -54,15 +58,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
} }
_menu = menu; _menu = menu;
_controllerScriptingInterface = controllerScriptingInterface; _controllerScriptingInterface = controllerScriptingInterface;
// hook up our interfaces
if (!Particle::getVoxelsScriptingInterface()) {
Particle::setVoxelsScriptingInterface(getVoxelsScriptingInterface());
}
if (!Particle::getParticlesScriptingInterface()) {
Particle::setParticlesScriptingInterface(getParticlesScriptingInterface());
}
} }
ScriptEngine::~ScriptEngine() { ScriptEngine::~ScriptEngine() {
@ -92,57 +87,83 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents) {
Q_SCRIPT_DECLARE_QMETAOBJECT(AudioInjectorOptions, QObject*) Q_SCRIPT_DECLARE_QMETAOBJECT(AudioInjectorOptions, QObject*)
void ScriptEngine::run() { void ScriptEngine::init() {
_isRunning = true; if (_isInitialized) {
QScriptEngine engine; return; // only initialize once
}
_isInitialized = true;
_voxelsScriptingInterface.init(); _voxelsScriptingInterface.init();
_particlesScriptingInterface.init(); _particlesScriptingInterface.init();
// register meta-type for glm::vec3 conversions // register meta-type for glm::vec3 conversions
registerMetaTypes(&engine); registerMetaTypes(&_engine);
QScriptValue agentValue = engine.newQObject(this); QScriptValue agentValue = _engine.newQObject(this);
engine.globalObject().setProperty("Agent", agentValue); _engine.globalObject().setProperty("Agent", agentValue);
QScriptValue voxelScripterValue = engine.newQObject(&_voxelsScriptingInterface); QScriptValue voxelScripterValue = _engine.newQObject(&_voxelsScriptingInterface);
engine.globalObject().setProperty("Voxels", voxelScripterValue); _engine.globalObject().setProperty("Voxels", voxelScripterValue);
QScriptValue particleScripterValue = engine.newQObject(&_particlesScriptingInterface); QScriptValue particleScripterValue = _engine.newQObject(&_particlesScriptingInterface);
engine.globalObject().setProperty("Particles", particleScripterValue); _engine.globalObject().setProperty("Particles", particleScripterValue);
QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor);
QScriptValue soundMetaObject = _engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
_engine.globalObject().setProperty("Sound", soundMetaObject);
QScriptValue soundConstructorValue = engine.newFunction(soundConstructor); QScriptValue injectionOptionValue = _engine.scriptValueFromQMetaObject<AudioInjectorOptions>();
QScriptValue soundMetaObject = engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue); _engine.globalObject().setProperty("AudioInjectionOptions", injectionOptionValue);
engine.globalObject().setProperty("Sound", soundMetaObject);
QScriptValue injectionOptionValue = engine.scriptValueFromQMetaObject<AudioInjectorOptions>(); QScriptValue audioScriptingInterfaceValue = _engine.newQObject(&_audioScriptingInterface);
engine.globalObject().setProperty("AudioInjectionOptions", injectionOptionValue); _engine.globalObject().setProperty("Audio", audioScriptingInterfaceValue);
QScriptValue audioScriptingInterfaceValue = engine.newQObject(&_audioScriptingInterface);
engine.globalObject().setProperty("Audio", audioScriptingInterfaceValue);
if (_controllerScriptingInterface) { if (_controllerScriptingInterface) {
QScriptValue controllerScripterValue = engine.newQObject(_controllerScriptingInterface); QScriptValue controllerScripterValue = _engine.newQObject(_controllerScriptingInterface);
engine.globalObject().setProperty("Controller", controllerScripterValue); _engine.globalObject().setProperty("Controller", controllerScripterValue);
} }
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); QScriptValue treeScaleValue = _engine.newVariant(QVariant(TREE_SCALE));
engine.globalObject().setProperty("TREE_SCALE", treeScaleValue); _engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
// let the VoxelPacketSender know how frequently we plan to call it // let the VoxelPacketSender know how frequently we plan to call it
_voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS); _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
_particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS); _particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
//qDebug() << "Script:\n" << _scriptContents << "\n"; //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"; qDebug() << "Evaluated script.\n";
if (engine.hasUncaughtException()) { if (_engine.hasUncaughtException()) {
int line = engine.uncaughtExceptionLineNumber(); 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"; qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
} }
@ -198,9 +219,9 @@ void ScriptEngine::run() {
emit willSendVisualDataCallback(); emit willSendVisualDataCallback();
} }
if (engine.hasUncaughtException()) { if (_engine.hasUncaughtException()) {
int line = engine.uncaughtExceptionLineNumber(); int line = _engine.uncaughtExceptionLineNumber();
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n"; qDebug() << "Uncaught exception at line" << line << ":" << _engine.uncaughtException().toString() << "\n";
} }
} }
cleanMenuItems(); cleanMenuItems();
@ -213,7 +234,6 @@ void ScriptEngine::run() {
emit finished(); emit finished();
_isRunning = false; _isRunning = false;
} }
void ScriptEngine::stop() { void ScriptEngine::stop() {
_isFinished = true; _isFinished = true;
} }

View file

@ -17,9 +17,10 @@
#include <AbstractMenuInterface.h> #include <AbstractMenuInterface.h>
#include <AudioScriptingInterface.h> #include <AudioScriptingInterface.h>
#include <ParticlesScriptingInterface.h>
#include <VoxelsScriptingInterface.h> #include <VoxelsScriptingInterface.h>
class ParticlesScriptingInterface;
#include "AbstractControllerScriptingInterface.h" #include "AbstractControllerScriptingInterface.h"
const QString NO_SCRIPT(""); const QString NO_SCRIPT("");
@ -45,9 +46,13 @@ public:
void setupMenuItems(); void setupMenuItems();
void cleanMenuItems(); void cleanMenuItems();
void registerGlobalObject(const QString& name, QObject* object); /// registers a global object by name
public slots: public slots:
void run(); void init();
void run(); /// runs continuously until Agent.stop() is called
void stop(); void stop();
void evaluate(); /// initializes the engine, and evaluates the script, but then returns control to caller
signals: signals:
void willSendAudioDataCallback(); void willSendAudioDataCallback();
@ -57,7 +62,8 @@ protected:
QString _scriptContents; QString _scriptContents;
bool _isFinished; bool _isFinished;
bool _isRunning; bool _isRunning;
bool _isInitialized;
QScriptEngine _engine;
private: private:
static VoxelsScriptingInterface _voxelsScriptingInterface; static VoxelsScriptingInterface _voxelsScriptingInterface;