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