mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-06 05:45:09 +02:00
first cut at shutting down scripts ahead of other cleanup
This commit is contained in:
parent
70400f7f8c
commit
0b607fa390
5 changed files with 270 additions and 148 deletions
|
@ -527,12 +527,22 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
}
|
||||
|
||||
void Application::aboutToQuit() {
|
||||
qDebug() << "Application::aboutToQuit()";
|
||||
_aboutToQuit = true;
|
||||
|
||||
cleanupBeforeQuit();
|
||||
}
|
||||
|
||||
void Application::cleanupBeforeQuit() {
|
||||
qDebug() << "Application::cleanupBeforeQuit() ------------ START -----------------";
|
||||
|
||||
// stop entities running scripts
|
||||
_entities.shutdown();
|
||||
|
||||
// stop all running scripts
|
||||
ScriptEngine::gracefullyStopAllScripts();
|
||||
|
||||
|
||||
// first stop all timers directly or by invokeMethod
|
||||
// depending on what thread they run in
|
||||
locationUpdateTimer->stop();
|
||||
|
@ -572,6 +582,8 @@ void Application::cleanupBeforeQuit() {
|
|||
|
||||
// destroy the AudioClient so it and its thread have a chance to go down safely
|
||||
DependencyManager::destroy<AudioClient>();
|
||||
|
||||
qDebug() << "Application::cleanupBeforeQuit() ------------ DONE -----------------";
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
|
@ -3432,6 +3444,7 @@ void Application::clearScriptsBeforeRunning() {
|
|||
}
|
||||
|
||||
void Application::saveScripts() {
|
||||
qDebug() << "Application::saveScripts()";
|
||||
// Saves all currently running user-loaded scripts
|
||||
Settings settings;
|
||||
settings.beginWriteArray(SETTINGS_KEY);
|
||||
|
@ -3525,7 +3538,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
#endif
|
||||
|
||||
QThread* workerThread = new QThread(this);
|
||||
workerThread->setObjectName("Script Engine Thread");
|
||||
QString scriptEngineName = QString("Script Thread:") + scriptEngine->getFilename();
|
||||
workerThread->setObjectName(scriptEngineName);
|
||||
|
||||
// when the worker thread is started, call our engine's run..
|
||||
connect(workerThread, &QThread::started, scriptEngine, &ScriptEngine::run);
|
||||
|
@ -3599,6 +3613,7 @@ void Application::handleScriptLoadError(const QString& scriptFilename) {
|
|||
}
|
||||
|
||||
void Application::scriptFinished(const QString& scriptName) {
|
||||
qDebug() << "Application::scriptFinished(), scriptName:" << scriptName;
|
||||
const QString& scriptURLString = QUrl(scriptName).toString();
|
||||
QHash<QString, ScriptEngine*>::iterator it = _scriptEnginesHash.find(scriptURLString);
|
||||
if (it != _scriptEnginesHash.end()) {
|
||||
|
@ -3609,6 +3624,7 @@ void Application::scriptFinished(const QString& scriptName) {
|
|||
}
|
||||
|
||||
void Application::stopAllScripts(bool restart) {
|
||||
qDebug() << "Application::stopAllScripts()... restart:" << restart;
|
||||
// stops all current running scripts
|
||||
for (QHash<QString, ScriptEngine*>::const_iterator it = _scriptEnginesHash.constBegin();
|
||||
it != _scriptEnginesHash.constEnd(); it++) {
|
||||
|
|
|
@ -97,6 +97,27 @@ void EntityTreeRenderer::init() {
|
|||
connect(entityTree, &EntityTree::changingEntityID, this, &EntityTreeRenderer::changingEntityID);
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::shutdown() {
|
||||
_shuttingDown = true;
|
||||
|
||||
/*
|
||||
if (_entitiesScriptEngine) {
|
||||
_entitiesScriptEngine->stop();
|
||||
|
||||
QEventLoop loop;
|
||||
QObject::connect(_entitiesScriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit);
|
||||
|
||||
_entitiesScriptEngine->stop();
|
||||
|
||||
qDebug() << "waiting on Entities sandbox script to stop... ";
|
||||
loop.exec();
|
||||
qDebug() << "done waiting... ";
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID) {
|
||||
EntityItem* entity = static_cast<EntityTree*>(_tree)->findEntityByEntityItemID(entityItemID);
|
||||
return loadEntityScript(entity);
|
||||
|
@ -156,6 +177,10 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe
|
|||
|
||||
|
||||
QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) {
|
||||
if (_shuttingDown) {
|
||||
return QScriptValue(); // no entity...
|
||||
}
|
||||
|
||||
if (!entity) {
|
||||
return QScriptValue(); // no entity...
|
||||
}
|
||||
|
@ -235,7 +260,7 @@ void EntityTreeRenderer::setTree(Octree* newTree) {
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::update() {
|
||||
if (_tree) {
|
||||
if (_tree && !_shuttingDown) {
|
||||
EntityTree* tree = static_cast<EntityTree*>(_tree);
|
||||
tree->update();
|
||||
|
||||
|
@ -258,7 +283,7 @@ void EntityTreeRenderer::update() {
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||
if (_tree) {
|
||||
if (_tree && !_shuttingDown) {
|
||||
_tree->lockForWrite(); // so that our scripts can do edits if they want
|
||||
glm::vec3 avatarPosition = _viewState->getAvatarPosition() / (float) TREE_SCALE;
|
||||
|
||||
|
@ -309,7 +334,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() {
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::leaveAllEntities() {
|
||||
if (_tree) {
|
||||
if (_tree && !_shuttingDown) {
|
||||
_tree->lockForWrite(); // so that our scripts can do edits if they want
|
||||
|
||||
// for all of our previous containing entities, if they are no longer containing then send them a leave event
|
||||
|
@ -330,7 +355,7 @@ void EntityTreeRenderer::leaveAllEntities() {
|
|||
}
|
||||
}
|
||||
void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) {
|
||||
if (_tree) {
|
||||
if (_tree && !_shuttingDown) {
|
||||
Model::startScene(renderSide);
|
||||
RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
@ -700,179 +725,193 @@ QScriptValueList EntityTreeRenderer::createEntityArgs(const EntityItemID& entity
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
if (_tree && !_shuttingDown) {
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
|
||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
//qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID;
|
||||
emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
//qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID;
|
||||
emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
|
||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
|
||||
if (entityScript.property("mousePressOnEntity").isValid()) {
|
||||
entityScript.property("mousePressOnEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
|
||||
if (entityScript.property("mousePressOnEntity").isValid()) {
|
||||
entityScript.property("mousePressOnEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
|
||||
_currentClickingOnEntityID = rayPickResult.entityID;
|
||||
emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
|
||||
if (entityScript.property("clickDownOnEntity").isValid()) {
|
||||
entityScript.property("clickDownOnEntity").call(entityScript, entityScriptArgs);
|
||||
_currentClickingOnEntityID = rayPickResult.entityID;
|
||||
emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
|
||||
if (entityScript.property("clickDownOnEntity").isValid()) {
|
||||
entityScript.property("clickDownOnEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
}
|
||||
_lastMouseEvent = MouseEvent(*event, deviceID);
|
||||
_lastMouseEventValid = true;
|
||||
}
|
||||
_lastMouseEvent = MouseEvent(*event, deviceID);
|
||||
_lastMouseEventValid = true;
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
//qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
|
||||
emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
if (_tree && !_shuttingDown) {
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
//qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
|
||||
emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
|
||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
|
||||
if (entityScript.property("mouseReleaseOnEntity").isValid()) {
|
||||
entityScript.property("mouseReleaseOnEntity").call(entityScript, entityScriptArgs);
|
||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
|
||||
if (entityScript.property("mouseReleaseOnEntity").isValid()) {
|
||||
entityScript.property("mouseReleaseOnEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Even if we're no longer intersecting with an entity, if we started clicking on it, and now
|
||||
// we're releasing the button, then this is considered a clickOn event
|
||||
if (!_currentClickingOnEntityID.isInvalidID()) {
|
||||
emit clickReleaseOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
|
||||
// Even if we're no longer intersecting with an entity, if we started clicking on it, and now
|
||||
// we're releasing the button, then this is considered a clickOn event
|
||||
if (!_currentClickingOnEntityID.isInvalidID()) {
|
||||
emit clickReleaseOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
|
||||
|
||||
QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID);
|
||||
QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID);
|
||||
if (currentClickingEntity.property("clickReleaseOnEntity").isValid()) {
|
||||
currentClickingEntity.property("clickReleaseOnEntity").call(currentClickingEntity, currentClickingEntityArgs);
|
||||
QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID);
|
||||
QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID);
|
||||
if (currentClickingEntity.property("clickReleaseOnEntity").isValid()) {
|
||||
currentClickingEntity.property("clickReleaseOnEntity").call(currentClickingEntity, currentClickingEntityArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// makes it the unknown ID, we just released so we can't be clicking on anything
|
||||
_currentClickingOnEntityID = EntityItemID::createInvalidEntityID();
|
||||
_lastMouseEvent = MouseEvent(*event, deviceID);
|
||||
_lastMouseEventValid = true;
|
||||
// makes it the unknown ID, we just released so we can't be clicking on anything
|
||||
_currentClickingOnEntityID = EntityItemID::createInvalidEntityID();
|
||||
_lastMouseEvent = MouseEvent(*event, deviceID);
|
||||
_lastMouseEventValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
|
||||
if (_tree && !_shuttingDown) {
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
|
||||
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
|
||||
bool precisionPicking = false; // for mouse moves we do not do precision picking
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||
bool precisionPicking = false; // for mouse moves we do not do precision picking
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
|
||||
|
||||
// load the entity script if needed...
|
||||
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
|
||||
if (entityScript.property("mouseMoveEvent").isValid()) {
|
||||
entityScript.property("mouseMoveEvent").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
// load the entity script if needed...
|
||||
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
|
||||
if (entityScript.property("mouseMoveEvent").isValid()) {
|
||||
entityScript.property("mouseMoveEvent").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
|
||||
//qDebug() << "mouseMoveEvent over entity:" << rayPickResult.entityID;
|
||||
emit mouseMoveOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
if (entityScript.property("mouseMoveOnEntity").isValid()) {
|
||||
entityScript.property("mouseMoveOnEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
//qDebug() << "mouseMoveEvent over entity:" << rayPickResult.entityID;
|
||||
emit mouseMoveOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
if (entityScript.property("mouseMoveOnEntity").isValid()) {
|
||||
entityScript.property("mouseMoveOnEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
|
||||
// handle the hover logic...
|
||||
// handle the hover logic...
|
||||
|
||||
// if we were previously hovering over an entity, and this new entity is not the same as our previous entity
|
||||
// then we need to send the hover leave.
|
||||
if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) {
|
||||
emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID));
|
||||
// if we were previously hovering over an entity, and this new entity is not the same as our previous entity
|
||||
// then we need to send the hover leave.
|
||||
if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) {
|
||||
emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID));
|
||||
|
||||
QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID);
|
||||
QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID);
|
||||
|
||||
QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID);
|
||||
if (currentHoverEntity.property("hoverLeaveEntity").isValid()) {
|
||||
currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
// If the new hover entity does not match the previous hover entity then we are entering the new one
|
||||
// this is true if the _currentHoverOverEntityID is known or unknown
|
||||
if (rayPickResult.entityID != _currentHoverOverEntityID) {
|
||||
emit hoverEnterEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
if (entityScript.property("hoverEnterEntity").isValid()) {
|
||||
entityScript.property("hoverEnterEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
}
|
||||
|
||||
// and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and
|
||||
// we should send our hover over event
|
||||
emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
if (entityScript.property("hoverOverEntity").isValid()) {
|
||||
entityScript.property("hoverOverEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
|
||||
// remember what we're hovering over
|
||||
_currentHoverOverEntityID = rayPickResult.entityID;
|
||||
|
||||
} else {
|
||||
// handle the hover logic...
|
||||
// if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to
|
||||
// send the hover leave for our previous entity
|
||||
if (!_currentHoverOverEntityID.isInvalidID()) {
|
||||
emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID));
|
||||
|
||||
QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID);
|
||||
|
||||
QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID);
|
||||
if (currentHoverEntity.property("hoverLeaveEntity").isValid()) {
|
||||
currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs);
|
||||
QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID);
|
||||
if (currentHoverEntity.property("hoverLeaveEntity").isValid()) {
|
||||
currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs);
|
||||
}
|
||||
}
|
||||
|
||||
_currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID
|
||||
// If the new hover entity does not match the previous hover entity then we are entering the new one
|
||||
// this is true if the _currentHoverOverEntityID is known or unknown
|
||||
if (rayPickResult.entityID != _currentHoverOverEntityID) {
|
||||
emit hoverEnterEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
if (entityScript.property("hoverEnterEntity").isValid()) {
|
||||
entityScript.property("hoverEnterEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
}
|
||||
|
||||
// and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and
|
||||
// we should send our hover over event
|
||||
emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
if (entityScript.property("hoverOverEntity").isValid()) {
|
||||
entityScript.property("hoverOverEntity").call(entityScript, entityScriptArgs);
|
||||
}
|
||||
|
||||
// remember what we're hovering over
|
||||
_currentHoverOverEntityID = rayPickResult.entityID;
|
||||
|
||||
} else {
|
||||
// handle the hover logic...
|
||||
// if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to
|
||||
// send the hover leave for our previous entity
|
||||
if (!_currentHoverOverEntityID.isInvalidID()) {
|
||||
emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID));
|
||||
|
||||
QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID);
|
||||
|
||||
QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID);
|
||||
if (currentHoverEntity.property("hoverLeaveEntity").isValid()) {
|
||||
currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs);
|
||||
}
|
||||
|
||||
_currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have
|
||||
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
||||
if (!_currentClickingOnEntityID.isInvalidID()) {
|
||||
emit holdingClickOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
|
||||
// Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have
|
||||
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
||||
if (!_currentClickingOnEntityID.isInvalidID()) {
|
||||
emit holdingClickOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
|
||||
|
||||
QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID);
|
||||
QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID);
|
||||
|
||||
QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID);
|
||||
if (currentClickingEntity.property("holdingClickOnEntity").isValid()) {
|
||||
currentClickingEntity.property("holdingClickOnEntity").call(currentClickingEntity, currentClickingEntityArgs);
|
||||
QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID);
|
||||
if (currentClickingEntity.property("holdingClickOnEntity").isValid()) {
|
||||
currentClickingEntity.property("holdingClickOnEntity").call(currentClickingEntity, currentClickingEntityArgs);
|
||||
}
|
||||
}
|
||||
_lastMouseEvent = MouseEvent(*event, deviceID);
|
||||
_lastMouseEventValid = true;
|
||||
}
|
||||
_lastMouseEvent = MouseEvent(*event, deviceID);
|
||||
_lastMouseEventValid = true;
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
|
||||
checkAndCallUnload(entityID);
|
||||
if (_tree && !_shuttingDown) {
|
||||
checkAndCallUnload(entityID);
|
||||
}
|
||||
_entityScripts.remove(entityID);
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) {
|
||||
checkAndCallUnload(entityID);
|
||||
if (_tree && !_shuttingDown) {
|
||||
checkAndCallUnload(entityID);
|
||||
}
|
||||
checkAndCallPreload(entityID);
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID) {
|
||||
// load the entity script if needed...
|
||||
QScriptValue entityScript = loadEntityScript(entityID);
|
||||
if (entityScript.property("preload").isValid()) {
|
||||
QScriptValueList entityArgs = createEntityArgs(entityID);
|
||||
entityScript.property("preload").call(entityScript, entityArgs);
|
||||
if (_tree && !_shuttingDown) {
|
||||
// load the entity script if needed...
|
||||
QScriptValue entityScript = loadEntityScript(entityID);
|
||||
if (entityScript.property("preload").isValid()) {
|
||||
QScriptValueList entityArgs = createEntityArgs(entityID);
|
||||
entityScript.property("preload").call(entityScript, entityArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::checkAndCallUnload(const EntityItemID& entityID) {
|
||||
QScriptValue entityScript = getPreviouslyLoadedEntityScript(entityID);
|
||||
if (entityScript.property("unload").isValid()) {
|
||||
QScriptValueList entityArgs = createEntityArgs(entityID);
|
||||
entityScript.property("unload").call(entityScript, entityArgs);
|
||||
if (_tree && !_shuttingDown) {
|
||||
QScriptValue entityScript = getPreviouslyLoadedEntityScript(entityID);
|
||||
if (entityScript.property("unload").isValid()) {
|
||||
QScriptValueList entityArgs = createEntityArgs(entityID);
|
||||
entityScript.property("unload").call(entityScript, entityArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -887,22 +926,24 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const
|
|||
|
||||
void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB,
|
||||
const Collision& collision) {
|
||||
QScriptValue entityScriptA = loadEntityScript(idA);
|
||||
if (entityScriptA.property("collisionWithEntity").isValid()) {
|
||||
QScriptValueList args;
|
||||
args << idA.toScriptValue(_entitiesScriptEngine);
|
||||
args << idB.toScriptValue(_entitiesScriptEngine);
|
||||
args << collisionToScriptValue(_entitiesScriptEngine, collision);
|
||||
entityScriptA.property("collisionWithEntity").call(entityScriptA, args);
|
||||
}
|
||||
if (_tree && !_shuttingDown) {
|
||||
QScriptValue entityScriptA = loadEntityScript(idA);
|
||||
if (entityScriptA.property("collisionWithEntity").isValid()) {
|
||||
QScriptValueList args;
|
||||
args << idA.toScriptValue(_entitiesScriptEngine);
|
||||
args << idB.toScriptValue(_entitiesScriptEngine);
|
||||
args << collisionToScriptValue(_entitiesScriptEngine, collision);
|
||||
entityScriptA.property("collisionWithEntity").call(entityScriptA, args);
|
||||
}
|
||||
|
||||
QScriptValue entityScriptB = loadEntityScript(idB);
|
||||
if (entityScriptB.property("collisionWithEntity").isValid()) {
|
||||
QScriptValueList args;
|
||||
args << idB.toScriptValue(_entitiesScriptEngine);
|
||||
args << idA.toScriptValue(_entitiesScriptEngine);
|
||||
args << collisionToScriptValue(_entitiesScriptEngine, collision);
|
||||
entityScriptB.property("collisionWithEntity").call(entityScriptA, args);
|
||||
QScriptValue entityScriptB = loadEntityScript(idB);
|
||||
if (entityScriptB.property("collisionWithEntity").isValid()) {
|
||||
QScriptValueList args;
|
||||
args << idB.toScriptValue(_entitiesScriptEngine);
|
||||
args << idA.toScriptValue(_entitiesScriptEngine);
|
||||
args << collisionToScriptValue(_entitiesScriptEngine, collision);
|
||||
entityScriptB.property("collisionWithEntity").call(entityScriptA, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
virtual int getBoundaryLevelAdjust() const;
|
||||
virtual void setTree(Octree* newTree);
|
||||
|
||||
void shutdown();
|
||||
void update();
|
||||
|
||||
EntityTree* getTree() { return static_cast<EntityTree*>(_tree); }
|
||||
|
@ -154,6 +155,8 @@ private:
|
|||
bool _displayModelElementProxy;
|
||||
bool _dontDoPrecisionPicking;
|
||||
|
||||
bool _shuttingDown = false;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_EntityTreeRenderer_h
|
||||
|
|
|
@ -94,8 +94,45 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
|
|||
_isUserLoaded(false),
|
||||
_arrayBufferClass(new ArrayBufferClass(this))
|
||||
{
|
||||
_allKnownScriptEngines.insert(this);
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine() {
|
||||
qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::~ScriptEngine() " << getFilename();
|
||||
_allKnownScriptEngines.remove(this);
|
||||
}
|
||||
|
||||
QSet<ScriptEngine*> ScriptEngine::_allKnownScriptEngines;
|
||||
|
||||
void ScriptEngine::gracefullyStopAllScripts() {
|
||||
qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- START ------------------";
|
||||
foreach(ScriptEngine* scriptEngine, _allKnownScriptEngines) {
|
||||
if (scriptEngine->isRunning()) {
|
||||
qDebug() << "scriptEngine still alive:" << scriptEngine->getFilename() << "[" << scriptEngine << "]";
|
||||
|
||||
QEventLoop loop;
|
||||
QObject::connect(scriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit);
|
||||
|
||||
scriptEngine->stop();
|
||||
|
||||
qDebug() << "waiting on script to stop... ";
|
||||
loop.exec();
|
||||
qDebug() << "done waiting... ";
|
||||
}
|
||||
}
|
||||
qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- DONE ------------------";
|
||||
}
|
||||
|
||||
QString ScriptEngine::getFilename() const {
|
||||
QStringList fileNameParts = _fileNameString.split("/");
|
||||
QString lastPart;
|
||||
if (!fileNameParts.isEmpty()) {
|
||||
lastPart = fileNameParts.last();
|
||||
}
|
||||
return lastPart;
|
||||
}
|
||||
|
||||
|
||||
void ScriptEngine::setIsAvatar(bool isAvatar) {
|
||||
_isAvatar = isAvatar;
|
||||
|
||||
|
@ -364,16 +401,18 @@ void ScriptEngine::run() {
|
|||
}
|
||||
|
||||
if (_isFinished) {
|
||||
qDebug() << "ScriptEngine::run()... while() about to break " << getFilename();
|
||||
break;
|
||||
}
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
if (_isFinished) {
|
||||
qDebug() << "ScriptEngine::run()... while() about to break " << getFilename();
|
||||
break;
|
||||
}
|
||||
|
||||
if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) {
|
||||
if (!_isFinished && _entityScriptingInterface.getEntityPacketSender()->serversExist()) {
|
||||
// release the queue of edit entity messages.
|
||||
_entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages();
|
||||
|
||||
|
@ -383,7 +422,7 @@ void ScriptEngine::run() {
|
|||
}
|
||||
}
|
||||
|
||||
if (_isAvatar && _avatarData) {
|
||||
if (!_isFinished && _isAvatar && _avatarData) {
|
||||
|
||||
const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * AudioConstants::SAMPLE_RATE)
|
||||
/ (1000 * 1000)) + 0.5);
|
||||
|
@ -493,9 +532,13 @@ void ScriptEngine::run() {
|
|||
clearExceptions();
|
||||
}
|
||||
|
||||
emit update(deltaTime);
|
||||
if (!_isFinished) {
|
||||
//qDebug() << "ScriptEngine::run()... about to emit update() _scriptName:" << _scriptName << "_fileNameString:" << _fileNameString << "_isFinished:" << _isFinished;
|
||||
emit update(deltaTime);
|
||||
}
|
||||
lastUpdate = now;
|
||||
}
|
||||
qDebug() << "ScriptEngine::run()... about to emit scriptEnding() " << getFilename();
|
||||
emit scriptEnding();
|
||||
|
||||
// kill the avatar identity timer
|
||||
|
@ -513,16 +556,25 @@ void ScriptEngine::run() {
|
|||
|
||||
// If we were on a thread, then wait till it's done
|
||||
if (thread()) {
|
||||
qDebug() << "ScriptEngine::run()... about to call thread()->quit() " << getFilename();
|
||||
thread()->quit();
|
||||
}
|
||||
|
||||
qDebug() << "ScriptEngine::run()... about to emit finished() " << getFilename();
|
||||
emit finished(_fileNameString);
|
||||
|
||||
_isRunning = false;
|
||||
|
||||
qDebug() << "ScriptEngine::run()... about to emit runningStateChanged() " << getFilename();
|
||||
emit runningStateChanged();
|
||||
|
||||
qDebug() << "ScriptEngine::run()... about to emit doneRunning() " << getFilename();
|
||||
emit doneRunning();
|
||||
qDebug() << "ScriptEngine::run()... DONE WITH run()... " << getFilename();
|
||||
}
|
||||
|
||||
void ScriptEngine::stop() {
|
||||
qDebug() << "ScriptEngine::stop()... " << getFilename();
|
||||
_isFinished = true;
|
||||
emit runningStateChanged();
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ public:
|
|||
const QString& fileNameString = QString(""),
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface = NULL);
|
||||
|
||||
~ScriptEngine();
|
||||
|
||||
/// Access the EntityScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener
|
||||
static EntityScriptingInterface* getEntityScriptingInterface() { return &_entityScriptingInterface; }
|
||||
|
||||
|
@ -88,6 +90,10 @@ public:
|
|||
bool isUserLoaded() const { return _isUserLoaded; }
|
||||
|
||||
void setParentURL(const QString& parentURL) { _parentURL = parentURL; }
|
||||
|
||||
QString getFilename() const;
|
||||
|
||||
static void gracefullyStopAllScripts();
|
||||
|
||||
public slots:
|
||||
void loadURL(const QUrl& scriptURL);
|
||||
|
@ -118,6 +124,7 @@ signals:
|
|||
void runningStateChanged();
|
||||
void evaluationFinished(QScriptValue result, bool isException);
|
||||
void loadScript(const QString& scriptName, bool isUserLoaded);
|
||||
void doneRunning();
|
||||
|
||||
protected:
|
||||
QString _scriptContents;
|
||||
|
@ -156,6 +163,9 @@ private:
|
|||
QHash<QUuid, quint16> _outgoingScriptAudioSequenceNumbers;
|
||||
private slots:
|
||||
void handleScriptDownload();
|
||||
|
||||
private:
|
||||
static QSet<ScriptEngine*> _allKnownScriptEngines;
|
||||
};
|
||||
|
||||
#endif // hifi_ScriptEngine_h
|
||||
|
|
Loading…
Reference in a new issue