History

Handle all the signals.

Howard Stearns committed 11 years ago

Commit b884d3c1 parent 1dd2b724 files · +69 −65Browse files

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

Unified · Split

libraries/script-engine/src/ScriptEngine.cpp+65−63
@@ -389,82 +389,84 @@ 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.392// Look up the handler associated with eventName and entityID. If found, evalute the argGenerator thunk and call the handler with those args
393QScriptValue ScriptEngine::getEntityEventHandler(const EntityItemID& entityID, const QString& eventName) {393void ScriptEngine::generalHandler(const EntityItemID& entityID, const QString& eventName, std::function<QScriptValueList()> argGenerator) {
394 if (!_registeredHandlers.contains(entityID)) return _illegal;394 if (!_registeredHandlers.contains(entityID)) return;
395 const RegisteredEventHandlers& handlersOnEntity = _registeredHandlers[entityID];395 const RegisteredEventHandlers& handlersOnEntity = _registeredHandlers[entityID];
396 if (!handlersOnEntity.contains(eventName)) return _illegal;396 if (!handlersOnEntity.contains(eventName)) return;
397 // FIXME: Need one more level of indirection. We need to allow multiple handlers per event, registered by different scripts.397 // FIXME: Need one more level of indirection. We need to allow multiple handlers per event, registered by different scripts.
398 return handlersOnEntity[eventName];398 QScriptValue handlerForEvent = handlersOnEntity[eventName];
399 if (handlerForEvent.isValid()) {
400 QScriptValueList args = argGenerator();
401 handlerForEvent.call(QScriptValue(), args);
402 }
399}403}
404// Unregister the handler for this eventName and entityID.
400void ScriptEngine::removeEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {405void ScriptEngine::removeEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {
401 // FIXME406 if (!_registeredHandlers.contains(entityID)) return;
407 RegisteredEventHandlers& handlersOnEntity = _registeredHandlers[entityID];
408 if (!handlersOnEntity.contains(eventName)) return;
409 handlersOnEntity.remove(eventName);
402}410}
403// FIXME: deletingEntity, changingEntityID411// FIXME: deletingEntity, changingEntityID
412// Register the handler.
404void ScriptEngine::addEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {413void ScriptEngine::addEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {
405 if (!_registeredHandlers.contains(entityID)) {414 if (_registeredHandlers.count() == 0) { // First time any per-entity handler has been added in this script...
406 _registeredHandlers[entityID] = RegisteredEventHandlers();415 // Connect up ALL the handlers to the global entities object's signals.
407 }416 // (We could go signal by signal, or even handler by handler, but I don't think the efficiency is worth the complexity.)
408 _registeredHandlers[entityID][eventName] = handler;417 auto entities = DependencyManager::get<EntityScriptingInterface>();
409 418 connect(entities.data(), &EntityScriptingInterface::deletingEntity, this,
410 // The rest connects the Entities signal to the handler here.419 [=](const EntityItemID& entityID) {
411 auto entities = DependencyManager::get<EntityScriptingInterface>();420 _registeredHandlers.remove(entityID);
412 421 });
413 // Given thunk that generates the arglist, evaluate that thunk only if needed, and call the handler.422 connect(entities.data(), &EntityScriptingInterface::changingEntityID, this,
414 auto generalHandler = [=](std::function<QScriptValueList()> argGenerator) {423 [=](const EntityItemID& oldEntityID, const EntityItemID& newEntityID) {
415 QScriptValue handlerForEvent = getEntityEventHandler(entityID, eventName);424 if (!_registeredHandlers.contains(oldEntityID)) return;
416 if (handlerForEvent.isValid()) {425 _registeredHandlers[newEntityID] = _registeredHandlers[oldEntityID];
417 QScriptValueList args = argGenerator();426 _registeredHandlers.remove(oldEntityID);
418 handlerForEvent.call(QScriptValue(), args);427 });
419 }428
420 };429 // Two common cases of event handler, differing only in argument signature.
421 // Two common cases of event handler, differing only in argument signature.430 auto makeSingleEntityHandler = [=](const QString& eventName) {
422 auto singleEntityHandler = [=](const EntityItemID& entityItemID) {431 return [=](const EntityItemID& entityItemID) {
423 generalHandler([=]() {432 generalHandler(entityItemID, eventName, [=]() {
424 return QScriptValueList() << entityItemID.toScriptValue(this);433 return QScriptValueList() << entityItemID.toScriptValue(this);
425 });434 });
426 };435 };
427 auto mouseHandler = [=](const EntityItemID& entityItemID, const MouseEvent& event) {436 };
428 generalHandler([=]() {437 auto makeMouseHandler = [=](const QString& eventName) {
429 return QScriptValueList() << entityItemID.toScriptValue(this) << event.toScriptValue(this);438 return [=](const EntityItemID& entityItemID, const MouseEvent& event) {
430 });439 generalHandler(entityItemID, eventName, [=]() {
431 };440 return QScriptValueList() << entityItemID.toScriptValue(this) << event.toScriptValue(this);
432 // This string comparison maze only happens when adding a handler, which isn't often, rather than during events.441 });
433 // Nonetheless, I wish it were more DRY. Variadic signals from strings? "I know reflection. I've worked with reflection. QT is no reflection."442 };
434 if (eventName == "enterEntity") {443 };
435 connect(entities.data(), &EntityScriptingInterface::enterEntity, this, singleEntityHandler);444 connect(entities.data(), &EntityScriptingInterface::enterEntity, this, makeSingleEntityHandler("enterEntity"));
436 } else if (eventName == "leaveEntity") {445 connect(entities.data(), &EntityScriptingInterface::leaveEntity, this, makeSingleEntityHandler("leaveEntity"));
437 connect(entities.data(), &EntityScriptingInterface::leaveEntity, this, singleEntityHandler);446
438 447 connect(entities.data(), &EntityScriptingInterface::mousePressOnEntity, this, makeMouseHandler("mousePressOnEntity"));
439 } else if (eventName == "mousePressOnEntity") {448 connect(entities.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, makeMouseHandler("mouseMoveOnEntity"));
440 connect(entities.data(), &EntityScriptingInterface::mousePressOnEntity, this, mouseHandler);449 connect(entities.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, makeMouseHandler("mouseReleaseOnEntity"));
441 } else if (eventName == "mouseMoveOnEntity") {450
442 connect(entities.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, mouseHandler);451 connect(entities.data(), &EntityScriptingInterface::clickDownOnEntity, this, makeMouseHandler("clickDownOnEntity"));
443 } else if (eventName == "mouseReleaseOnEntity") {452 connect(entities.data(), &EntityScriptingInterface::holdingClickOnEntity, this, makeMouseHandler("holdingClickOnEntity"));
444 connect(entities.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, mouseHandler);453 connect(entities.data(), &EntityScriptingInterface::clickReleaseOnEntity, this, makeMouseHandler("clickReleaseOnEntity"));
445 454
446 } else if (eventName == "clickDownOnEntity") {455 connect(entities.data(), &EntityScriptingInterface::hoverEnterEntity, this, makeMouseHandler("hoverEnterEntity"));
447 connect(entities.data(), &EntityScriptingInterface::clickDownOnEntity, this, mouseHandler);456 connect(entities.data(), &EntityScriptingInterface::hoverOverEntity, this, makeMouseHandler("hoverOverEntity"));
448 } else if (eventName == "holdingClickOnEntity") {457 connect(entities.data(), &EntityScriptingInterface::hoverLeaveEntity, this, makeMouseHandler("hoverLeaveEntity"));
449 connect(entities.data(), &EntityScriptingInterface::holdingClickOnEntity, this, mouseHandler);458
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,459 connect(entities.data(), &EntityScriptingInterface::collisionWithEntity, this,
462 [=](const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) {460 [=](const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) {
463 generalHandler([=]() {461 generalHandler(idA, "collisionWithEntity", [=]() {
464 return QScriptValueList () << idA.toScriptValue(this) << idB.toScriptValue(this) << collisionToScriptValue(this, collision);462 return QScriptValueList () << idA.toScriptValue(this) << idB.toScriptValue(this) << collisionToScriptValue(this, collision);
465 });463 });
466 });464 });
467 }465 }
466 if (!_registeredHandlers.contains(entityID)) {
467 _registeredHandlers[entityID] = RegisteredEventHandlers();
468 }
469 _registeredHandlers[entityID][eventName] = handler;
468}470}
469 471
470 472