mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-05 22:14:27 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into 19483
This commit is contained in:
commit
11bf9b8a50
10 changed files with 928 additions and 876 deletions
|
@ -18,6 +18,7 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelConstants.h>
|
||||
#include <ParticlesScriptingInterface.h>
|
||||
|
||||
#include "Agent.h"
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <OctalCode.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <PairingHandler.h>
|
||||
#include <ParticlesScriptingInterface.h>
|
||||
#include <PerfStat.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelSceneStats.h>
|
||||
|
@ -239,6 +240,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_voxelEditSender.setVoxelServerJurisdictions(&_voxelServerJurisdictions);
|
||||
_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
|
||||
// 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
|
||||
|
@ -1555,6 +1559,10 @@ void Application::shootParticle() {
|
|||
" var myColor = Particle.getColor();"
|
||||
" print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); "
|
||||
" 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); " );
|
||||
|
||||
|
|
|
@ -129,7 +129,8 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in
|
|||
_totalPackets++;
|
||||
if (debug) {
|
||||
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";
|
||||
}
|
||||
|
||||
|
@ -211,6 +212,7 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in
|
|||
|
||||
/// Version of voxel distributor that sends the deepest LOD level at once
|
||||
int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, bool viewFrustumChanged) {
|
||||
bool forceDebugging = false;
|
||||
|
||||
int truePacketsSent = 0;
|
||||
int trueBytesSent = 0;
|
||||
|
@ -231,16 +233,19 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
// then let's just send that waiting packet.
|
||||
if (!nodeData->getCurrentPacketFormatMatches()) {
|
||||
if (nodeData->isPacketWaiting()) {
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
printf("wantColor=%s wantCompression=%s SENDING PARTIAL PACKET! currentPacketIsColor=%s currentPacketIsCompressed=%s\n",
|
||||
if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
|
||||
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(nodeData->getCurrentPacketIsColor()),
|
||||
debug::valueOf(nodeData->getCurrentPacketIsCompressed()) );
|
||||
}
|
||||
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
} else {
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
printf("wantColor=%s wantCompression=%s FIXING HEADER! currentPacketIsColor=%s currentPacketIsCompressed=%s\n",
|
||||
if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
|
||||
qDebug("wantColor=%s wantCompression=%s FIXING HEADER! currentPacketIsColor=%s currentPacketIsCompressed=%s\n",
|
||||
debug::valueOf(wantColor), debug::valueOf(wantCompression),
|
||||
debug::valueOf(nodeData->getCurrentPacketIsColor()),
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -260,7 +265,7 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
}
|
||||
|
||||
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(wantCompression), debug::valueOf(nodeData->getCurrentPacketIsCompressed()),
|
||||
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;
|
||||
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
printf("packetDistributor() viewFrustumChanged=%s, nodeBag.isEmpty=%s, viewSent=%s\n",
|
||||
if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
|
||||
qDebug("packetDistributor() viewFrustumChanged=%s, nodeBag.isEmpty=%s, viewSent=%s\n",
|
||||
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()),
|
||||
debug::valueOf(nodeData->getViewSent())
|
||||
);
|
||||
|
@ -279,17 +284,17 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
// the current view frustum for things to send.
|
||||
if (viewFrustumChanged || nodeData->nodeBag.isEmpty()) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
printf("(viewFrustumChanged=%s || nodeData->nodeBag.isEmpty() =%s)...\n",
|
||||
if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
|
||||
qDebug("(viewFrustumChanged=%s || nodeData->nodeBag.isEmpty() =%s)...\n",
|
||||
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()));
|
||||
if (nodeData->getLastTimeBagEmpty() > 0) {
|
||||
float elapsedSceneSend = (now - nodeData->getLastTimeBagEmpty()) / 1000000.0f;
|
||||
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 {
|
||||
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(wantColor));
|
||||
}
|
||||
|
@ -316,9 +321,17 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
|
||||
unsigned long encodeTime = nodeData->stats.getTotalEncodeTime();
|
||||
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()
|
||||
<< "encodeTime:" << encodeTime
|
||||
<< " sleepTime:" << sleepTime
|
||||
|
@ -337,7 +350,7 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
nodeData->nodeBag.deleteAll();
|
||||
}
|
||||
|
||||
if (_myServer->wantsDebugSending()) {
|
||||
if (forceDebugging || _myServer->wantsDebugSending()) {
|
||||
qDebug() << "Scene started at " << usecTimestampNow()
|
||||
<< " Packets:" << _totalPackets
|
||||
<< " Bytes:" << _totalBytes
|
||||
|
@ -369,15 +382,16 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
||||
|
||||
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(),
|
||||
nodeData->getMaxOctreePacketsPerSecond(), clientMaxPacketsPerInterval);
|
||||
}
|
||||
|
||||
int extraPackingAttempts = 0;
|
||||
bool completedScene = false;
|
||||
while (somethingToSend && packetsSentThisInterval < maxPacketsPerInterval) {
|
||||
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(),
|
||||
nodeData->getMaxOctreePacketsPerSecond(), clientMaxPacketsPerInterval);
|
||||
}
|
||||
|
@ -409,6 +423,11 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
nodeData->stats.encodeStarted();
|
||||
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 (_packetData.getTargetSize() == MAX_OCTREE_PACKET_DATA_SIZE) {
|
||||
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
|
||||
// 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
|
||||
// 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.
|
||||
if (lastNodeDidntFit) {
|
||||
if (completedScene || lastNodeDidntFit) {
|
||||
if (_packetData.hasContent()) {
|
||||
// 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
|
||||
|
@ -449,15 +469,16 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
|
||||
|
||||
if (writtenSize > nodeData->getAvailable()) {
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
printf("writtenSize[%d] > available[%d] too big, sending packet as is.\n",
|
||||
writtenSize, nodeData->getAvailable());
|
||||
if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
|
||||
qDebug("about to call handlePacketSend() .... line: %d -- "
|
||||
"writtenSize[%d] > available[%d] too big, sending packet as is.\n",
|
||||
__LINE__, writtenSize, nodeData->getAvailable());
|
||||
}
|
||||
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
}
|
||||
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
printf("calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%d\n",
|
||||
if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
|
||||
qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%d\n",
|
||||
nodeData->getAvailable(), _packetData.getFinalizedSize(),
|
||||
_packetData.getUncompressedSize(), _packetData.getTargetSize());
|
||||
}
|
||||
|
@ -465,7 +486,7 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
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...
|
||||
bool sendNow = true;
|
||||
|
||||
|
@ -477,6 +498,9 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
|
||||
int targetSize = MAX_OCTREE_PACKET_DATA_SIZE;
|
||||
if (sendNow) {
|
||||
if (forceDebugging) {
|
||||
qDebug("about to call handlePacketSend() .... line: %d -- sendNow = TRUE\n", __LINE__);
|
||||
}
|
||||
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
if (wantCompression) {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
_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 > 1000) {
|
||||
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",
|
||||
elapsedsec, elapsedCompressTimeMsecs, elapsedCompressCalls, trueBytesSent, truePacketsSent, nodeData->nodeBag.count());
|
||||
qDebug("WARNING! packetLoop() took %d seconds [%d milliseconds %d calls in compress] "
|
||||
"to generate %d bytes in %d packets %d nodes still to send\n",
|
||||
elapsedsec, elapsedCompressTimeMsecs, elapsedCompressCalls,
|
||||
trueBytesSent, truePacketsSent, nodeData->nodeBag.count());
|
||||
} 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",
|
||||
elapsedmsec, elapsedCompressTimeMsecs, elapsedCompressCalls, trueBytesSent, truePacketsSent, nodeData->nodeBag.count());
|
||||
qDebug("WARNING! packetLoop() took %d milliseconds [%d milliseconds %d calls in compress] "
|
||||
"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()) {
|
||||
printf("packetLoop() took %d milliseconds [%d milliseconds %d calls in compress] to generate %d bytes in %d packets, %d nodes still to send\n",
|
||||
elapsedmsec, elapsedCompressTimeMsecs, elapsedCompressCalls, trueBytesSent, truePacketsSent, nodeData->nodeBag.count());
|
||||
qDebug("packetLoop() took %d milliseconds [%d milliseconds %d calls in compress] "
|
||||
"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
|
||||
|
@ -544,9 +574,11 @@ int OctreeSendThread::packetDistributor(Node* node, OctreeQueryNode* nodeData, b
|
|||
}
|
||||
|
||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
|
||||
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
|
||||
nodeData->getMaxOctreePacketsPerSecond(), clientMaxPacketsPerInterval);
|
||||
qDebug("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d "
|
||||
"server PPI=%d nodePPS=%d nodePPI=%d\n",
|
||||
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval,
|
||||
_myServer->getPacketsPerClientPerInterval(), nodeData->getMaxOctreePacketsPerSecond(),
|
||||
clientMaxPacketsPerInterval);
|
||||
}
|
||||
|
||||
} // end if bag wasn't empty, and so we sent stuff...
|
||||
|
|
|
@ -1133,12 +1133,16 @@ bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCoun
|
|||
if (!childToDelete->isLeaf()) {
|
||||
// delete all it's children
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
if (childToDelete->getChildAtIndex(i)) {
|
||||
deleteApproved = childToDelete->safeDeepDeleteChildAtIndex(i,recursionCount+1);
|
||||
if (!deleteApproved) {
|
||||
break; // no point in continuing...
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
deleteApproved = true; // because we got here after checking that delete was approved
|
||||
}
|
||||
if (deleteApproved) {
|
||||
deleteChildAtIndex(childIndex);
|
||||
_isDirty = true;
|
||||
|
|
|
@ -7,21 +7,25 @@
|
|||
//
|
||||
//
|
||||
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <Octree.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h> // usecTimestampNow()
|
||||
#include <Octree.h>
|
||||
|
||||
#include <VoxelsScriptingInterface.h>
|
||||
#include "ParticlesScriptingInterface.h"
|
||||
|
||||
// This is not ideal, but adding script-engine as a linked library, will cause a circular reference
|
||||
// I'm open to other potential solutions. Could we change cmake to allow libraries to reference each others
|
||||
// headers, but not link to each other, this is essentially what this construct is doing, but would be
|
||||
// better to add includes to the include path, but not link
|
||||
#include "../../script-engine/src/ScriptEngine.h"
|
||||
|
||||
#include "ParticlesScriptingInterface.h"
|
||||
#include "Particle.h"
|
||||
|
||||
uint32_t Particle::_nextID = 0;
|
||||
VoxelsScriptingInterface* Particle::_voxelsScriptingInterface = NULL;
|
||||
ParticlesScriptingInterface* Particle::_particlesScriptingInterface = NULL;
|
||||
VoxelEditPacketSender* Particle::_voxelEditSender = NULL;
|
||||
ParticleEditPacketSender* Particle::_particleEditSender = NULL;
|
||||
|
||||
|
||||
Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity,
|
||||
|
@ -505,72 +509,59 @@ void Particle::update() {
|
|||
|
||||
void Particle::runUpdateScript() {
|
||||
if (!_script.isEmpty()) {
|
||||
ScriptEngine engine(_script); // no menu or controller interface...
|
||||
|
||||
QScriptEngine engine;
|
||||
|
||||
// register meta-type for glm::vec3 and rgbColor conversions
|
||||
registerMetaTypes(&engine);
|
||||
if (_voxelEditSender) {
|
||||
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
|
||||
}
|
||||
|
||||
// Add the Particle object
|
||||
ParticleScriptObject particleScriptable(this);
|
||||
QScriptValue particleValue = engine.newQObject(&particleScriptable);
|
||||
engine.globalObject().setProperty("Particle", particleValue);
|
||||
engine.registerGlobalObject("Particle", &particleScriptable);
|
||||
|
||||
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
||||
engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE);
|
||||
|
||||
QScriptValue result = engine.evaluate(_script);
|
||||
// init and evaluate the script, but return so we can emit the collision
|
||||
engine.evaluate();
|
||||
|
||||
particleScriptable.emitUpdate();
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
if (_voxelEditSender) {
|
||||
_voxelEditSender->releaseQueuedMessages();
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
_particleEditSender->releaseQueuedMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Particle::collisionWithParticle(Particle* other) {
|
||||
if (!_script.isEmpty()) {
|
||||
ScriptEngine engine(_script); // no menu or controller interface...
|
||||
|
||||
QScriptEngine engine;
|
||||
|
||||
// register meta-type for glm::vec3 and rgbColor conversions
|
||||
registerMetaTypes(&engine);
|
||||
if (_voxelEditSender) {
|
||||
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
|
||||
}
|
||||
|
||||
// Add the Particle object
|
||||
ParticleScriptObject particleScriptable(this);
|
||||
QScriptValue particleValue = engine.newQObject(&particleScriptable);
|
||||
engine.globalObject().setProperty("Particle", particleValue);
|
||||
engine.registerGlobalObject("Particle", &particleScriptable);
|
||||
|
||||
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
||||
engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE);
|
||||
|
||||
|
||||
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);
|
||||
// init and evaluate the script, but return so we can emit the collision
|
||||
engine.evaluate();
|
||||
|
||||
ParticleScriptObject otherParticleScriptable(other);
|
||||
particleScriptable.emitCollisionWithParticle(&otherParticleScriptable);
|
||||
|
||||
if (getVoxelsScriptingInterface()) {
|
||||
getVoxelsScriptingInterface()->getPacketSender()->releaseQueuedMessages();
|
||||
if (_voxelEditSender) {
|
||||
_voxelEditSender->releaseQueuedMessages();
|
||||
}
|
||||
|
||||
if (getParticlesScriptingInterface()) {
|
||||
getParticlesScriptingInterface()->getPacketSender()->releaseQueuedMessages();
|
||||
}
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
if (_particleEditSender) {
|
||||
_particleEditSender->releaseQueuedMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -578,45 +569,32 @@ void Particle::collisionWithParticle(Particle* other) {
|
|||
void Particle::collisionWithVoxel(VoxelDetail* voxelDetails) {
|
||||
if (!_script.isEmpty()) {
|
||||
|
||||
QScriptEngine engine;
|
||||
ScriptEngine engine(_script); // no menu or controller interface...
|
||||
|
||||
// register meta-type for glm::vec3 and rgbColor conversions
|
||||
registerMetaTypes(&engine);
|
||||
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
||||
// we can use the same ones as our context.
|
||||
if (_voxelEditSender) {
|
||||
engine.getVoxelsScriptingInterface()->setPacketSender(_voxelEditSender);
|
||||
}
|
||||
if (_particleEditSender) {
|
||||
engine.getParticlesScriptingInterface()->setPacketSender(_particleEditSender);
|
||||
}
|
||||
|
||||
// Add the Particle object
|
||||
ParticleScriptObject particleScriptable(this);
|
||||
QScriptValue particleValue = engine.newQObject(&particleScriptable);
|
||||
engine.globalObject().setProperty("Particle", particleValue);
|
||||
engine.registerGlobalObject("Particle", &particleScriptable);
|
||||
|
||||
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
||||
engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE);
|
||||
|
||||
|
||||
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);
|
||||
// init and evaluate the script, but return so we can emit the collision
|
||||
engine.evaluate();
|
||||
|
||||
VoxelDetailScriptObject voxelDetailsScriptable(voxelDetails);
|
||||
particleScriptable.emitCollisionWithVoxel(&voxelDetailsScriptable);
|
||||
|
||||
if (getVoxelsScriptingInterface()) {
|
||||
getVoxelsScriptingInterface()->getPacketSender()->releaseQueuedMessages();
|
||||
if (_voxelEditSender) {
|
||||
_voxelEditSender->releaseQueuedMessages();
|
||||
}
|
||||
|
||||
if (getParticlesScriptingInterface()) {
|
||||
getParticlesScriptingInterface()->getPacketSender()->releaseQueuedMessages();
|
||||
}
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
if (_particleEditSender) {
|
||||
_particleEditSender->releaseQueuedMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
class VoxelsScriptingInterface;
|
||||
class ParticlesScriptingInterface;
|
||||
class VoxelEditPacketSender;
|
||||
class ParticleEditPacketSender;
|
||||
|
||||
|
||||
const uint32_t NEW_PARTICLE = 0xFFFFFFFF;
|
||||
|
@ -122,18 +124,19 @@ public:
|
|||
// similar to assignment/copy, but it handles keeping lifetime accurate
|
||||
void copyChangedProperties(const Particle& other);
|
||||
|
||||
static VoxelsScriptingInterface* getVoxelsScriptingInterface() { return _voxelsScriptingInterface; }
|
||||
static ParticlesScriptingInterface* getParticlesScriptingInterface() { return _particlesScriptingInterface; }
|
||||
static VoxelEditPacketSender* getVoxelEditPacketSender() { return _voxelEditSender; }
|
||||
static ParticleEditPacketSender* getParticleEditPacketSender() { return _particleEditSender; }
|
||||
|
||||
static void setVoxelsScriptingInterface(VoxelsScriptingInterface* interface)
|
||||
{ _voxelsScriptingInterface = interface; }
|
||||
static void setVoxelEditPacketSender(VoxelEditPacketSender* interface)
|
||||
{ _voxelEditSender = interface; }
|
||||
|
||||
static void setParticleEditPacketSender(ParticleEditPacketSender* interface)
|
||||
{ _particleEditSender = interface; }
|
||||
|
||||
static void setParticlesScriptingInterface(ParticlesScriptingInterface* interface)
|
||||
{ _particlesScriptingInterface = interface; }
|
||||
|
||||
protected:
|
||||
static VoxelsScriptingInterface* _voxelsScriptingInterface;
|
||||
static ParticlesScriptingInterface* _particlesScriptingInterface;
|
||||
static VoxelEditPacketSender* _voxelEditSender;
|
||||
static ParticleEditPacketSender* _particleEditSender;
|
||||
|
||||
void runUpdateScript();
|
||||
static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3);
|
||||
|
|
|
@ -19,11 +19,14 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <UUID.h>
|
||||
#include <VoxelConstants.h>
|
||||
#include <ParticlesScriptingInterface.h>
|
||||
|
||||
#include <Sound.h>
|
||||
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
|
||||
|
||||
int ScriptEngine::_scriptNumber = 1;
|
||||
VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface;
|
||||
ParticlesScriptingInterface ScriptEngine::_particlesScriptingInterface;
|
||||
|
@ -41,6 +44,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
|
|||
_scriptContents = scriptContents;
|
||||
_isFinished = false;
|
||||
_isRunning = false;
|
||||
_isInitialized = false;
|
||||
|
||||
// some clients will use these menu features
|
||||
_wantMenuItems = wantMenuItems;
|
||||
|
@ -54,15 +58,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems,
|
|||
}
|
||||
_menu = menu;
|
||||
_controllerScriptingInterface = controllerScriptingInterface;
|
||||
|
||||
// hook up our interfaces
|
||||
if (!Particle::getVoxelsScriptingInterface()) {
|
||||
Particle::setVoxelsScriptingInterface(getVoxelsScriptingInterface());
|
||||
}
|
||||
|
||||
if (!Particle::getParticlesScriptingInterface()) {
|
||||
Particle::setParticlesScriptingInterface(getParticlesScriptingInterface());
|
||||
}
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine() {
|
||||
|
@ -92,57 +87,83 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents) {
|
|||
|
||||
Q_SCRIPT_DECLARE_QMETAOBJECT(AudioInjectorOptions, QObject*)
|
||||
|
||||
void ScriptEngine::run() {
|
||||
_isRunning = true;
|
||||
QScriptEngine engine;
|
||||
void ScriptEngine::init() {
|
||||
if (_isInitialized) {
|
||||
return; // only initialize once
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
|
||||
_voxelsScriptingInterface.init();
|
||||
_particlesScriptingInterface.init();
|
||||
|
||||
// register meta-type for glm::vec3 conversions
|
||||
registerMetaTypes(&engine);
|
||||
registerMetaTypes(&_engine);
|
||||
|
||||
QScriptValue agentValue = engine.newQObject(this);
|
||||
engine.globalObject().setProperty("Agent", agentValue);
|
||||
QScriptValue agentValue = _engine.newQObject(this);
|
||||
_engine.globalObject().setProperty("Agent", agentValue);
|
||||
|
||||
QScriptValue voxelScripterValue = engine.newQObject(&_voxelsScriptingInterface);
|
||||
engine.globalObject().setProperty("Voxels", voxelScripterValue);
|
||||
QScriptValue voxelScripterValue = _engine.newQObject(&_voxelsScriptingInterface);
|
||||
_engine.globalObject().setProperty("Voxels", voxelScripterValue);
|
||||
|
||||
QScriptValue particleScripterValue = engine.newQObject(&_particlesScriptingInterface);
|
||||
engine.globalObject().setProperty("Particles", particleScripterValue);
|
||||
QScriptValue particleScripterValue = _engine.newQObject(&_particlesScriptingInterface);
|
||||
_engine.globalObject().setProperty("Particles", particleScripterValue);
|
||||
|
||||
QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor);
|
||||
QScriptValue soundMetaObject = _engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
||||
_engine.globalObject().setProperty("Sound", soundMetaObject);
|
||||
|
||||
QScriptValue soundConstructorValue = engine.newFunction(soundConstructor);
|
||||
QScriptValue soundMetaObject = engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
||||
engine.globalObject().setProperty("Sound", soundMetaObject);
|
||||
QScriptValue injectionOptionValue = _engine.scriptValueFromQMetaObject<AudioInjectorOptions>();
|
||||
_engine.globalObject().setProperty("AudioInjectionOptions", injectionOptionValue);
|
||||
|
||||
QScriptValue injectionOptionValue = engine.scriptValueFromQMetaObject<AudioInjectorOptions>();
|
||||
engine.globalObject().setProperty("AudioInjectionOptions", injectionOptionValue);
|
||||
|
||||
QScriptValue audioScriptingInterfaceValue = engine.newQObject(&_audioScriptingInterface);
|
||||
engine.globalObject().setProperty("Audio", audioScriptingInterfaceValue);
|
||||
QScriptValue audioScriptingInterfaceValue = _engine.newQObject(&_audioScriptingInterface);
|
||||
_engine.globalObject().setProperty("Audio", audioScriptingInterfaceValue);
|
||||
|
||||
if (_controllerScriptingInterface) {
|
||||
QScriptValue controllerScripterValue = engine.newQObject(_controllerScriptingInterface);
|
||||
engine.globalObject().setProperty("Controller", controllerScripterValue);
|
||||
QScriptValue controllerScripterValue = _engine.newQObject(_controllerScriptingInterface);
|
||||
_engine.globalObject().setProperty("Controller", controllerScripterValue);
|
||||
}
|
||||
|
||||
QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE));
|
||||
engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
||||
|
||||
const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000;
|
||||
QScriptValue treeScaleValue = _engine.newVariant(QVariant(TREE_SCALE));
|
||||
_engine.globalObject().setProperty("TREE_SCALE", treeScaleValue);
|
||||
|
||||
// let the VoxelPacketSender know how frequently we plan to call it
|
||||
_voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
|
||||
_particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS);
|
||||
|
||||
//qDebug() << "Script:\n" << _scriptContents << "\n";
|
||||
}
|
||||
|
||||
QScriptValue result = engine.evaluate(_scriptContents);
|
||||
void ScriptEngine::registerGlobalObject(const QString& name, QObject* object) {
|
||||
QScriptValue value = _engine.newQObject(object);
|
||||
_engine.globalObject().setProperty(name, value);
|
||||
}
|
||||
|
||||
void ScriptEngine::evaluate() {
|
||||
if (!_isInitialized) {
|
||||
init();
|
||||
}
|
||||
|
||||
QScriptValue result = _engine.evaluate(_scriptContents);
|
||||
qDebug() << "Evaluated script.\n";
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::run() {
|
||||
if (!_isInitialized) {
|
||||
init();
|
||||
}
|
||||
_isRunning = true;
|
||||
|
||||
QScriptValue result = _engine.evaluate(_scriptContents);
|
||||
qDebug() << "Evaluated script.\n";
|
||||
|
||||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n";
|
||||
}
|
||||
|
||||
|
@ -198,9 +219,9 @@ void ScriptEngine::run() {
|
|||
emit willSendVisualDataCallback();
|
||||
}
|
||||
|
||||
if (engine.hasUncaughtException()) {
|
||||
int line = engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << engine.uncaughtException().toString() << "\n";
|
||||
if (_engine.hasUncaughtException()) {
|
||||
int line = _engine.uncaughtExceptionLineNumber();
|
||||
qDebug() << "Uncaught exception at line" << line << ":" << _engine.uncaughtException().toString() << "\n";
|
||||
}
|
||||
}
|
||||
cleanMenuItems();
|
||||
|
@ -213,7 +234,6 @@ void ScriptEngine::run() {
|
|||
emit finished();
|
||||
_isRunning = false;
|
||||
}
|
||||
|
||||
void ScriptEngine::stop() {
|
||||
_isFinished = true;
|
||||
}
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
|
||||
#include <AbstractMenuInterface.h>
|
||||
#include <AudioScriptingInterface.h>
|
||||
#include <ParticlesScriptingInterface.h>
|
||||
#include <VoxelsScriptingInterface.h>
|
||||
|
||||
class ParticlesScriptingInterface;
|
||||
|
||||
#include "AbstractControllerScriptingInterface.h"
|
||||
|
||||
const QString NO_SCRIPT("");
|
||||
|
@ -45,9 +46,13 @@ public:
|
|||
void setupMenuItems();
|
||||
void cleanMenuItems();
|
||||
|
||||
void registerGlobalObject(const QString& name, QObject* object); /// registers a global object by name
|
||||
|
||||
public slots:
|
||||
void run();
|
||||
void init();
|
||||
void run(); /// runs continuously until Agent.stop() is called
|
||||
void stop();
|
||||
void evaluate(); /// initializes the engine, and evaluates the script, but then returns control to caller
|
||||
|
||||
signals:
|
||||
void willSendAudioDataCallback();
|
||||
|
@ -57,7 +62,8 @@ protected:
|
|||
QString _scriptContents;
|
||||
bool _isFinished;
|
||||
bool _isRunning;
|
||||
|
||||
bool _isInitialized;
|
||||
QScriptEngine _engine;
|
||||
|
||||
private:
|
||||
static VoxelsScriptingInterface _voxelsScriptingInterface;
|
||||
|
|
Loading…
Reference in a new issue