History

Simpler and more uniform version that handles all the standard entity-script events.

Howard Stearns committed 11 years ago

Commit 1dd2b721 parent 277f5ef5 files · +83 −39Browse files

Showing the changes to libraries/script-engine/src/ScriptEngine.cpp (1 of 5 files). Show all

Unified · Split

libraries/script-engine/src/ScriptEngine.cpp+71−16
@@ -389,30 +389,85 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func · 388 unmodified lines
389 }389 }
390}390}
391 391
392// Answer the previously registered handler for the given entityID/eventName, else an invalid QScriptValue.
393QScriptValue ScriptEngine::getEntityEventHandler(const EntityItemID& entityID, const QString& eventName) {
394 if (!_registeredHandlers.contains(entityID)) return _illegal;
395 const RegisteredEventHandlers& handlersOnEntity = _registeredHandlers[entityID];
396 if (!handlersOnEntity.contains(eventName)) return _illegal;
397 // FIXME: Need one more level of indirection. We need to allow multiple handlers per event, registered by different scripts.
398 return handlersOnEntity[eventName];
399}
400void ScriptEngine::removeEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {
401 // FIXME
402}
403// FIXME: deletingEntity, changingEntityID
392void ScriptEngine::addEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {404void ScriptEngine::addEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {
393 auto entities = DependencyManager::get<EntityScriptingInterface>();
394 if (!_registeredHandlers.contains(entityID)) {405 if (!_registeredHandlers.contains(entityID)) {
395 _registeredHandlers[entityID] = RegisteredEventHandlers();406 _registeredHandlers[entityID] = RegisteredEventHandlers();
396 }407 }
397 _registeredHandlers[entityID][eventName] = handler;408 _registeredHandlers[entityID][eventName] = handler;
398 if (eventName == "collisionWithEntity") {409
399 connect(entities.data(), &EntityScriptingInterface::collisionWithEntity, this, &ScriptEngine::collisionWithEntity);410 // The rest connects the Entities signal to the handler here.
411 auto entities = DependencyManager::get<EntityScriptingInterface>();
412
413 // Given thunk that generates the arglist, evaluate that thunk only if needed, and call the handler.
414 auto generalHandler = [=](std::function<QScriptValueList()> argGenerator) {
415 QScriptValue handlerForEvent = getEntityEventHandler(entityID, eventName);
416 if (handlerForEvent.isValid()) {
417 QScriptValueList args = argGenerator();
418 handlerForEvent.call(QScriptValue(), args);
419 }
420 };
421 // Two common cases of event handler, differing only in argument signature.
422 auto singleEntityHandler = [=](const EntityItemID& entityItemID) {
423 generalHandler([=]() {
424 return QScriptValueList() << entityItemID.toScriptValue(this);
425 });
426 };
427 auto mouseHandler = [=](const EntityItemID& entityItemID, const MouseEvent& event) {
428 generalHandler([=]() {
429 return QScriptValueList() << entityItemID.toScriptValue(this) << event.toScriptValue(this);
430 });
431 };
432 // This string comparison maze only happens when adding a handler, which isn't often, rather than during events.
433 // Nonetheless, I wish it were more DRY. Variadic signals from strings? "I know reflection. I've worked with reflection. QT is no reflection."
434 if (eventName == "enterEntity") {
435 connect(entities.data(), &EntityScriptingInterface::enterEntity, this, singleEntityHandler);
436 } else if (eventName == "leaveEntity") {
437 connect(entities.data(), &EntityScriptingInterface::leaveEntity, this, singleEntityHandler);
438
439 } else if (eventName == "mousePressOnEntity") {
440 connect(entities.data(), &EntityScriptingInterface::mousePressOnEntity, this, mouseHandler);
441 } else if (eventName == "mouseMoveOnEntity") {
442 connect(entities.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, mouseHandler);
443 } else if (eventName == "mouseReleaseOnEntity") {
444 connect(entities.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, mouseHandler);
445
446 } else if (eventName == "clickDownOnEntity") {
447 connect(entities.data(), &EntityScriptingInterface::clickDownOnEntity, this, mouseHandler);
448 } else if (eventName == "holdingClickOnEntity") {
449 connect(entities.data(), &EntityScriptingInterface::holdingClickOnEntity, this, mouseHandler);
450 } else if (eventName == "clickReleaseOnEntity") {
451 connect(entities.data(), &EntityScriptingInterface::clickReleaseOnEntity, this, mouseHandler);
452
453 } else if (eventName == "hoverEnterEntity") {
454 connect(entities.data(), &EntityScriptingInterface::hoverEnterEntity, this, mouseHandler);
455 } else if (eventName == "hoverOverEntity") {
456 connect(entities.data(), &EntityScriptingInterface::hoverOverEntity, this, mouseHandler);
457 } else if (eventName == "hoverLeaveEntity") {
458 connect(entities.data(), &EntityScriptingInterface::hoverLeaveEntity, this, mouseHandler);
459
460 } else if (eventName == "collisionWithEntity") {
461 connect(entities.data(), &EntityScriptingInterface::collisionWithEntity, this,
462 [=](const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) {
463 generalHandler([=]() {
464 return QScriptValueList () << idA.toScriptValue(this) << idB.toScriptValue(this) << collisionToScriptValue(this, collision);
465 });
466 });
400 }467 }
401 // FIXME: deletingEntity, changingEntityID
402}
403void ScriptEngine::removeEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {
404 // FIXME
405}
406void ScriptEngine::collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) {
407 if (!_registeredHandlers.contains(idA)) return;
408 const RegisteredEventHandlers& handlersOnEntity = _registeredHandlers[idA];
409 if (!handlersOnEntity.contains("collisionWithEntity")) return;
410 // FIXME: Need one more level of indirection. We need to allow multiple handlers per event, registered by different scripts.
411 QScriptValue handlerForEvent = handlersOnEntity["collisionWithEntity"];
412 QScriptValueList args = QScriptValueList () << idA.toScriptValue(this) << idB.toScriptValue(this) << collisionToScriptValue(this, collision);
413 handlerForEvent.call(QScriptValue(), args);
414}468}
415 469
470
416void ScriptEngine::evaluate() {471void ScriptEngine::evaluate() {
417 if (_stoppingAllScripts) {472 if (_stoppingAllScripts) {
418 return; // bail early473 return; // bail early