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 <UUID.h>
#include <VoxelConstants.h>
#include <ParticlesScriptingInterface.h>
#include "Agent.h"

View file

@ -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); " );

View file

@ -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...

View file

@ -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;

View file

@ -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();
}
}
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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;