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
389389 }
390390 }
391391
392−// Answer the previously registered handler for the given entityID/eventName, else an invalid QScriptValue.
393−QScriptValue ScriptEngine::getEntityEventHandler(const EntityItemID& entityID, const QString& eventName) {
394− if (!_registeredHandlers.contains(entityID)) return _illegal;
392+// Look up the handler associated with eventName and entityID. If found, evalute the argGenerator thunk and call the handler with those args
393+void ScriptEngine::generalHandler(const EntityItemID& entityID, const QString& eventName, std::function<QScriptValueList()> argGenerator) {
394+ if (!_registeredHandlers.contains(entityID)) return;
395395 const RegisteredEventHandlers& handlersOnEntity = _registeredHandlers[entityID];
396− if (!handlersOnEntity.contains(eventName)) return _illegal;
396+ if (!handlersOnEntity.contains(eventName)) return;
397397 // 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+ }
399403 }
404+// Unregister the handler for this eventName and entityID.
400405 void ScriptEngine::removeEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {
401− // FIXME
406+ if (!_registeredHandlers.contains(entityID)) return;
407+ RegisteredEventHandlers& handlersOnEntity = _registeredHandlers[entityID];
408+ if (!handlersOnEntity.contains(eventName)) return;
409+ handlersOnEntity.remove(eventName);
402410 }
403411 // FIXME: deletingEntity, changingEntityID
412+// Register the handler.
404413 void ScriptEngine::addEntityEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler) {
405− if (!_registeredHandlers.contains(entityID)) {
406− _registeredHandlers[entityID] = RegisteredEventHandlers();
407− }
408− _registeredHandlers[entityID][eventName] = handler;
409−
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") {
414+ if (_registeredHandlers.count() == 0) { // First time any per-entity handler has been added in this script...
415+ // Connect up ALL the handlers to the global entities object's signals.
416+ // (We could go signal by signal, or even handler by handler, but I don't think the efficiency is worth the complexity.)
417+ auto entities = DependencyManager::get<EntityScriptingInterface>();
418+ connect(entities.data(), &EntityScriptingInterface::deletingEntity, this,
419+ [=](const EntityItemID& entityID) {
420+ _registeredHandlers.remove(entityID);
421+ });
422+ connect(entities.data(), &EntityScriptingInterface::changingEntityID, this,
423+ [=](const EntityItemID& oldEntityID, const EntityItemID& newEntityID) {
424+ if (!_registeredHandlers.contains(oldEntityID)) return;
425+ _registeredHandlers[newEntityID] = _registeredHandlers[oldEntityID];
426+ _registeredHandlers.remove(oldEntityID);
427+ });
428+
429+ // Two common cases of event handler, differing only in argument signature.
430+ auto makeSingleEntityHandler = [=](const QString& eventName) {
431+ return [=](const EntityItemID& entityItemID) {
432+ generalHandler(entityItemID, eventName, [=]() {
433+ return QScriptValueList() << entityItemID.toScriptValue(this);
434+ });
435+ };
436+ };
437+ auto makeMouseHandler = [=](const QString& eventName) {
438+ return [=](const EntityItemID& entityItemID, const MouseEvent& event) {
439+ generalHandler(entityItemID, eventName, [=]() {
440+ return QScriptValueList() << entityItemID.toScriptValue(this) << event.toScriptValue(this);
441+ });
442+ };
443+ };
444+ connect(entities.data(), &EntityScriptingInterface::enterEntity, this, makeSingleEntityHandler("enterEntity"));
445+ connect(entities.data(), &EntityScriptingInterface::leaveEntity, this, makeSingleEntityHandler("leaveEntity"));
446+
447+ connect(entities.data(), &EntityScriptingInterface::mousePressOnEntity, this, makeMouseHandler("mousePressOnEntity"));
448+ connect(entities.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, makeMouseHandler("mouseMoveOnEntity"));
449+ connect(entities.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, makeMouseHandler("mouseReleaseOnEntity"));
450+
451+ connect(entities.data(), &EntityScriptingInterface::clickDownOnEntity, this, makeMouseHandler("clickDownOnEntity"));
452+ connect(entities.data(), &EntityScriptingInterface::holdingClickOnEntity, this, makeMouseHandler("holdingClickOnEntity"));
453+ connect(entities.data(), &EntityScriptingInterface::clickReleaseOnEntity, this, makeMouseHandler("clickReleaseOnEntity"));
454+
455+ connect(entities.data(), &EntityScriptingInterface::hoverEnterEntity, this, makeMouseHandler("hoverEnterEntity"));
456+ connect(entities.data(), &EntityScriptingInterface::hoverOverEntity, this, makeMouseHandler("hoverOverEntity"));
457+ connect(entities.data(), &EntityScriptingInterface::hoverLeaveEntity, this, makeMouseHandler("hoverLeaveEntity"));
458+
461459 connect(entities.data(), &EntityScriptingInterface::collisionWithEntity, this,
462460 [=](const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) {
463− generalHandler([=]() {
461+ generalHandler(idA, "collisionWithEntity", [=]() {
464462 return QScriptValueList () << idA.toScriptValue(this) << idB.toScriptValue(this) << collisionToScriptValue(this, collision);
465463 });
466464 });
467465 }
466+ if (!_registeredHandlers.contains(entityID)) {
467+ _registeredHandlers[entityID] = RegisteredEventHandlers();
468+ }
469+ _registeredHandlers[entityID][eventName] = handler;
468470 }
469471
470472