var Circle = require('../geom/circle/Circle'); var CircleContains = require('../geom/circle/Contains'); var Class = require('../utils/Class'); var CreateInteractiveObject = require('./CreateInteractiveObject'); var CreatePixelPerfectHandler = require('./CreatePixelPerfectHandler'); var DistanceBetween = require('../math/distance/DistanceBetween'); var Ellipse = require('../geom/ellipse/Ellipse'); var EllipseContains = require('../geom/ellipse/Contains'); var EventEmitter = require('eventemitter3'); var GetFastValue = require('../utils/object/GetFastValue'); var InputPluginCache = require('./InputPluginCache'); var IsPlainObject = require('../utils/object/IsPlainObject'); var PluginCache = require('../plugins/PluginCache'); var Rectangle = require('../geom/rectangle/Rectangle'); var RectangleContains = require('../geom/rectangle/Contains'); var Triangle = require('../geom/triangle/Triangle'); var TriangleContains = require('../geom/triangle/Contains'); var InputPlugin = new Class({ Extends: EventEmitter, initialize: function InputPlugin(scene){ EventEmitter.call(this); this.scene = scene; this.systems = scene.sys; this.settings = scene.sys.settings; this.manager = scene.sys.game.input; this.pluginEvents = new EventEmitter(); this.enabled = true ; this.displayList; this.cameras; InputPluginCache.install(this); this.mouse = this.manager.mouse; this.topOnly = true ; this.pollRate = -1; this._pollTimer = 0; var _eventData = { cancelled: false } ; this._eventContainer = { stopPropagation: function (){ _eventData.cancelled = true ; } } ; this._eventData = _eventData; this.dragDistanceThreshold = 0; this.dragTimeThreshold = 0; this._temp = [] ; this._tempZones = [] ; this._list = [] ; this._pendingInsertion = [] ; this._pendingRemoval = [] ; this._draggable = [] ; this._drag = { 0: [] , 1: [] , 2: [] , 3: [] , 4: [] , 5: [] , 6: [] , 7: [] , 8: [] , 9: [] , 10: [] } ; this._over = { 0: [] , 1: [] , 2: [] , 3: [] , 4: [] , 5: [] , 6: [] , 7: [] , 8: [] , 9: [] , 10: [] } ; this._validTypes = ['onDown', 'onUp', 'onOver', 'onOut', 'onMove', 'onDragStart', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragLeave', 'onDragOver', 'onDrop'] ; scene.sys.events.once('boot', this.boot, this); scene.sys.events.on('start', this.start, this); } , boot: function (){ this.cameras = this.systems.cameras; this.displayList = this.systems.displayList; this.systems.events.once('destroy', this.destroy, this); this.pluginEvents.emit('boot'); } , start: function (){ var eventEmitter = this.systems.events; eventEmitter.on('transitionstart', this.transitionIn, this); eventEmitter.on('transitionout', this.transitionOut, this); eventEmitter.on('transitioncomplete', this.transitionComplete, this); eventEmitter.on('preupdate', this.preUpdate, this); eventEmitter.on('update', this.update, this); eventEmitter.once('shutdown', this.shutdown, this); this.enabled = true ; this.pluginEvents.emit('start'); } , preUpdate: function (){ this.pluginEvents.emit('preUpdate'); var removeList = this._pendingRemoval; var insertList = this._pendingInsertion; var toRemove = _AN_Read_length('length', removeList); var toInsert = _AN_Read_length('length', insertList); if (toRemove === 0 && toInsert === 0) { return ; } var current = this._list; for (var i = 0; i < toRemove; i++ ){ var gameObject = removeList[i]; var index = current.indexOf(gameObject); if (index > -1) { current.splice(index, 1); _AN_Call_clear('clear', this, gameObject); } } removeList.length = 0; this._pendingRemoval.length = 0; this._list = current.concat(insertList.splice(0)); } , isActive: function (){ return (this.enabled && this.scene.sys.isActive()); } , update: function (time, delta){ if (!this.isActive()) { return ; } this.pluginEvents.emit('update', time, delta); var manager = this.manager; if (manager.globalTopOnly && manager.ignoreEvents) { return ; } var runUpdate = (manager.dirty || this.pollRate === 0); if (this.pollRate > -1) { this._pollTimer -= delta; if (this._pollTimer < 0) { runUpdate = true ; this._pollTimer = this.pollRate; } } if (!runUpdate) { return ; } var pointers = this.manager.pointers; for (var i = 0; i < this.manager.pointersTotal; i++ ){ var pointer = pointers[i]; this._tempZones = [] ; this._temp = this.hitTestPointer(pointer); this.sortGameObjects(this._temp); this.sortGameObjects(this._tempZones); if (this.topOnly) { if (this._temp.length) { this._temp.splice(1); } if (this._tempZones.length) { this._tempZones.splice(1); } } var total = this.processDragEvents(pointer, time); if (!pointer.wasTouch) { total += this.processOverOutEvents(pointer); } if (pointer.justDown) { total += this.processDownEvents(pointer); } if (pointer.justUp) { total += this.processUpEvents(pointer); } if (pointer.justMoved) { total += this.processMoveEvents(pointer); } if (total > 0 && manager.globalTopOnly) { manager.ignoreEvents = true ; } } } , clear: function (gameObject){ var input = gameObject.input; if (!input) { return ; } this.queueForRemoval(gameObject); input.gameObject = undefined; _AN_Write_target('target', input, false , undefined); input.hitArea = undefined; input.hitAreaCallback = undefined; input.callbackContext = undefined; this.manager.resetCursor(input); gameObject.input = null ; var index = this._draggable.indexOf(gameObject); if (index > -1) { this._draggable.splice(index, 1); } index = this._drag[0].indexOf(gameObject); if (index > -1) { this._drag[0].splice(index, 1); } index = this._over[0].indexOf(gameObject); if (index > -1) { this._over[0].splice(index, 1); } return gameObject; } , disable: function (gameObject){ gameObject.input.enabled = false ; } , enable: function (gameObject, shape, callback, dropZone){ if (dropZone === undefined) { dropZone = false ; } if (gameObject.input) { gameObject.input.enabled = true ; } else { this.setHitArea(gameObject, shape, callback); } if (gameObject.input && dropZone && !gameObject.input.dropZone) { gameObject.input.dropZone = dropZone; } return this; } , hitTestPointer: function (pointer){ var cameras = this.cameras.getCamerasBelowPointer(pointer); for (var c = 0; c < (_AN_Read_length('length', cameras)); c++ ){ var camera = cameras[c]; var over = this.manager.hitTest(pointer, this._list, camera); for (var i = 0; i < (_AN_Read_length('length', over)); i++ ){ var obj = over[i]; if (obj.input.dropZone) { this._tempZones.push(obj); } } if ((_AN_Read_length('length', over)) > 0) { pointer.camera = camera; return over; } } pointer.camera = cameras[0]; return [] ; } , processDownEvents: function (pointer){ var total = 0; var currentlyOver = this._temp; var _eventData = this._eventData; var _eventContainer = this._eventContainer; _eventData.cancelled = false ; var aborted = false ; for (var i = 0; i < (_AN_Read_length('length', currentlyOver)); i++ ){ var gameObject = currentlyOver[i]; if (!gameObject.input) { continue ; } total++ ; gameObject.emit('pointerdown', pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); if (_eventData.cancelled) { aborted = true ; break ; } this.emit('gameobjectdown', pointer, gameObject, _eventContainer); if (_eventData.cancelled) { aborted = true ; break ; } } if (!aborted) { this.emit('pointerdown', pointer, currentlyOver); } return total; } , processDragEvents: function (pointer, time){ if ((_AN_Read_length('length', this._draggable)) === 0) { return 0; } var i; var gameObject; var list; var input; var currentlyOver = this._temp; if (pointer.dragState === 0 && pointer.primaryDown && pointer.justDown && (_AN_Read_length('length', currentlyOver)) > 0) { pointer.dragState = 1; } else if (pointer.dragState > 0 && !pointer.primaryDown && pointer.justUp) { pointer.dragState = 5; } if (pointer.dragState === 1) { var draglist = [] ; for (i = 0; i < (_AN_Read_length('length', currentlyOver)); i++ ){ gameObject = currentlyOver[i]; if (gameObject.input.draggable && (gameObject.input.dragState === 0)) { draglist.push(gameObject); } } if ((_AN_Read_length('length', draglist)) === 0) { pointer.dragState = 0; return 0; } else if ((_AN_Read_length('length', draglist)) > 1) { this.sortGameObjects(draglist); if (this.topOnly) { draglist.splice(1); } } this._drag[pointer.id] = draglist; if (this.dragDistanceThreshold === 0 && this.dragTimeThreshold === 0) { pointer.dragState = 3; } else { pointer.dragState = 2; } } if (pointer.dragState === 2) { if (this.dragDistanceThreshold > 0 && DistanceBetween(pointer.x, pointer.y, pointer.downX, pointer.downY) >= this.dragDistanceThreshold) { pointer.dragState = 3; } if (this.dragTimeThreshold > 0 && (time >= pointer.downTime + this.dragTimeThreshold)) { pointer.dragState = 3; } } if (pointer.dragState === 3) { list = this._drag[pointer.id]; for (i = 0; i < (_AN_Read_length('length', list)); i++ ){ gameObject = list[i]; input = gameObject.input; input.dragState = 2; input.dragX = pointer.x - gameObject.x; input.dragY = pointer.y - gameObject.y; input.dragStartX = gameObject.x; input.dragStartY = gameObject.y; gameObject.emit('dragstart', pointer, input.dragX, input.dragY); this.emit('dragstart', pointer, gameObject); } pointer.dragState = 4; return (_AN_Read_length('length', list)); } if (pointer.dragState === 4 && pointer.justMoved && !pointer.justUp) { var dropZones = this._tempZones; list = this._drag[pointer.id]; for (i = 0; i < (_AN_Read_length('length', list)); i++ ){ gameObject = list[i]; input = gameObject.input; if (input.target) { var index = dropZones.indexOf(_AN_Read_target('target', input)); if (index === 0) { gameObject.emit('dragover', pointer, _AN_Read_target('target', input)); this.emit('dragover', pointer, gameObject, _AN_Read_target('target', input)); } else if (index > 0) { gameObject.emit('dragleave', pointer, _AN_Read_target('target', input)); this.emit('dragleave', pointer, gameObject, _AN_Read_target('target', input)); _AN_Write_target('target', input, false , dropZones[0]); gameObject.emit('dragenter', pointer, _AN_Read_target('target', input)); this.emit('dragenter', pointer, gameObject, _AN_Read_target('target', input)); } else { gameObject.emit('dragleave', pointer, _AN_Read_target('target', input)); this.emit('dragleave', pointer, gameObject, _AN_Read_target('target', input)); if (dropZones[0]) { _AN_Write_target('target', input, false , dropZones[0]); gameObject.emit('dragenter', pointer, _AN_Read_target('target', input)); this.emit('dragenter', pointer, gameObject, _AN_Read_target('target', input)); } else { _AN_Write_target('target', input, false , null ); } } } else if (!(_AN_Read_target('target', input)) && dropZones[0]) { _AN_Write_target('target', input, false , dropZones[0]); gameObject.emit('dragenter', pointer, _AN_Read_target('target', input)); this.emit('dragenter', pointer, gameObject, _AN_Read_target('target', input)); } var dragX = pointer.x - gameObject.input.dragX; var dragY = pointer.y - gameObject.input.dragY; gameObject.emit('drag', pointer, dragX, dragY); this.emit('drag', pointer, gameObject, dragX, dragY); } return (_AN_Read_length('length', list)); } if (pointer.dragState === 5) { list = this._drag[pointer.id]; for (i = 0; i < (_AN_Read_length('length', list)); i++ ){ gameObject = list[i]; input = gameObject.input; if (input.dragState === 2) { input.dragState = 0; input.dragX = input.localX - gameObject.displayOriginX; input.dragY = input.localY - gameObject.displayOriginY; var dropped = false ; if (input.target) { gameObject.emit('drop', pointer, _AN_Read_target('target', input)); this.emit('drop', pointer, gameObject, _AN_Read_target('target', input)); _AN_Write_target('target', input, false , null ); dropped = true ; } gameObject.emit('dragend', pointer, input.dragX, input.dragY, dropped); this.emit('dragend', pointer, gameObject, dropped); } } pointer.dragState = 0; list.splice(0); } return 0; } , processMoveEvents: function (pointer){ var total = 0; var currentlyOver = this._temp; var _eventData = this._eventData; var _eventContainer = this._eventContainer; _eventData.cancelled = false ; var aborted = false ; for (var i = 0; i < (_AN_Read_length('length', currentlyOver)); i++ ){ var gameObject = currentlyOver[i]; if (!gameObject.input) { continue ; } total++ ; gameObject.emit('pointermove', pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); if (_eventData.cancelled) { aborted = true ; break ; } this.emit('gameobjectmove', pointer, gameObject, _eventContainer); if (_eventData.cancelled) { aborted = true ; break ; } if (this.topOnly) { break ; } } if (!aborted) { this.emit('pointermove', pointer, currentlyOver); } return total; } , processOverOutEvents: function (pointer){ var currentlyOver = this._temp; var i; var gameObject; var justOut = [] ; var justOver = [] ; var stillOver = [] ; var previouslyOver = this._over[pointer.id]; var currentlyDragging = this._drag[pointer.id]; var manager = this.manager; for (i = 0; i < (_AN_Read_length('length', previouslyOver)); i++ ){ gameObject = previouslyOver[i]; if (currentlyOver.indexOf(gameObject) === -1 && currentlyDragging.indexOf(gameObject) === -1) { justOut.push(gameObject); } else { stillOver.push(gameObject); } } for (i = 0; i < (_AN_Read_length('length', currentlyOver)); i++ ){ gameObject = currentlyOver[i]; if (previouslyOver.indexOf(gameObject) === -1) { justOver.push(gameObject); } } var total = _AN_Read_length('length', justOut); var totalInteracted = 0; var _eventData = this._eventData; var _eventContainer = this._eventContainer; _eventData.cancelled = false ; var aborted = false ; if (total > 0) { this.sortGameObjects(justOut); for (i = 0; i < total; i++ ){ gameObject = justOut[i]; if (!gameObject.input) { continue ; } gameObject.emit('pointerout', pointer, _eventContainer); manager.resetCursor(gameObject.input); totalInteracted++ ; if (_eventData.cancelled) { aborted = true ; break ; } this.emit('gameobjectout', pointer, gameObject, _eventContainer); if (_eventData.cancelled) { aborted = true ; break ; } } if (!aborted) { this.emit('pointerout', pointer, justOut); } } total = _AN_Read_length('length', justOver); _eventData.cancelled = false ; aborted = false ; if (total > 0) { this.sortGameObjects(justOver); for (i = 0; i < total; i++ ){ gameObject = justOver[i]; if (!gameObject.input) { continue ; } gameObject.emit('pointerover', pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); manager.setCursor(gameObject.input); totalInteracted++ ; if (_eventData.cancelled) { aborted = true ; break ; } this.emit('gameobjectover', pointer, gameObject, _eventContainer); if (_eventData.cancelled) { aborted = true ; break ; } } if (!aborted) { this.emit('pointerover', pointer, justOver); } } previouslyOver = stillOver.concat(justOver); this._over[pointer.id] = this.sortGameObjects(previouslyOver); return totalInteracted; } , processUpEvents: function (pointer){ var currentlyOver = this._temp; var _eventData = this._eventData; var _eventContainer = this._eventContainer; _eventData.cancelled = false ; var aborted = false ; for (var i = 0; i < (_AN_Read_length('length', currentlyOver)); i++ ){ var gameObject = currentlyOver[i]; if (!gameObject.input) { continue ; } gameObject.emit('pointerup', pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer); if (_eventData.cancelled) { aborted = true ; break ; } this.emit('gameobjectup', pointer, gameObject, _eventContainer); if (_eventData.cancelled) { aborted = true ; break ; } } if (!aborted) { this.emit('pointerup', pointer, currentlyOver); } return (_AN_Read_length('length', currentlyOver)); } , queueForInsertion: function (child){ if (this._pendingInsertion.indexOf(child) === -1 && this._list.indexOf(child) === -1) { this._pendingInsertion.push(child); } return this; } , queueForRemoval: function (child){ this._pendingRemoval.push(child); return this; } , setDraggable: function (gameObjects, value){ if (value === undefined) { value = true ; } if (!Array.isArray(gameObjects)) { gameObjects = [gameObjects] ; } for (var i = 0; i < (_AN_Read_length('length', gameObjects)); i++ ){ var gameObject = gameObjects[i]; gameObject.input.draggable = value; var index = this._draggable.indexOf(gameObject); if (value && index === -1) { this._draggable.push(gameObject); } else if (!value && index > -1) { this._draggable.splice(index, 1); } } return this; } , makePixelPerfect: function (alphaTolerance){ if (alphaTolerance === undefined) { alphaTolerance = 1; } var textureManager = this.systems.textures; return CreatePixelPerfectHandler(textureManager, alphaTolerance); } , setHitArea: function (gameObjects, shape, callback){ if (shape === undefined) { return this.setHitAreaFromTexture(gameObjects); } if (!Array.isArray(gameObjects)) { gameObjects = [gameObjects] ; } var draggable = false ; var dropZone = false ; var cursor = false ; var useHandCursor = false ; if (IsPlainObject(shape)) { var config = shape; shape = GetFastValue(config, 'hitArea', null ); callback = GetFastValue(config, 'hitAreaCallback', null ); draggable = GetFastValue(config, 'draggable', false ); dropZone = GetFastValue(config, 'dropZone', false ); cursor = GetFastValue(config, 'cursor', false ); useHandCursor = GetFastValue(config, 'useHandCursor', false ); var pixelPerfect = GetFastValue(config, 'pixelPerfect', false ); var alphaTolerance = GetFastValue(config, 'alphaTolerance', 1); if (pixelPerfect) { shape = { } ; callback = this.makePixelPerfect(alphaTolerance); } if (!shape || !callback) { this.setHitAreaFromTexture(gameObjects); } } else if (typeof shape === 'function' && !callback) { callback = shape; shape = { } ; } for (var i = 0; i < (_AN_Read_length('length', gameObjects)); i++ ){ var gameObject = gameObjects[i]; var io = (!gameObject.input)? CreateInteractiveObject(gameObject, shape, callback): gameObject.input; io.dropZone = dropZone; _AN_Write_cursor('cursor', io, false , (useHandCursor)? 'pointer': cursor); gameObject.input = io; if (draggable) { this.setDraggable(gameObject); } this.queueForInsertion(gameObject); } return this; } , setHitAreaCircle: function (gameObjects, x, y, radius, callback){ if (callback === undefined) { callback = CircleContains; } var shape = new Circle(x, y, radius); return this.setHitArea(gameObjects, shape, callback); } , setHitAreaEllipse: function (gameObjects, x, y, width, height, callback){ if (callback === undefined) { callback = EllipseContains; } var shape = new Ellipse(x, y, width, height); return this.setHitArea(gameObjects, shape, callback); } , setHitAreaFromTexture: function (gameObjects, callback){ if (callback === undefined) { callback = RectangleContains; } if (!Array.isArray(gameObjects)) { gameObjects = [gameObjects] ; } for (var i = 0; i < (_AN_Read_length('length', gameObjects)); i++ ){ var gameObject = gameObjects[i]; var frame = gameObject.frame; var width = 0; var height = 0; if (frame) { width = frame.realWidth; height = frame.realHeight; } else if (gameObject.width) { width = gameObject.width; height = gameObject.height; } if (gameObject.type === 'Container' && (width === 0 || height === 0)) { console.warn('Container.setInteractive() must specify a Shape or call setSize() first'); continue ; } if (width !== 0 && height !== 0) { gameObject.input = CreateInteractiveObject(gameObject, new Rectangle(0, 0, width, height), callback); this.queueForInsertion(gameObject); } } return this; } , setHitAreaRectangle: function (gameObjects, x, y, width, height, callback){ if (callback === undefined) { callback = RectangleContains; } var shape = new Rectangle(x, y, width, height); return this.setHitArea(gameObjects, shape, callback); } , setHitAreaTriangle: function (gameObjects, x1, y1, x2, y2, x3, y3, callback){ if (callback === undefined) { callback = TriangleContains; } var shape = new Triangle(x1, y1, x2, y2, x3, y3); return this.setHitArea(gameObjects, shape, callback); } , setPollAlways: function (){ this.pollRate = 0; this._pollTimer = 0; return this; } , setPollOnMove: function (){ this.pollRate = -1; this._pollTimer = 0; return this; } , setPollRate: function (value){ this.pollRate = value; this._pollTimer = 0; return this; } , setGlobalTopOnly: function (value){ this.manager.globalTopOnly = value; return this; } , setTopOnly: function (value){ this.topOnly = value; return this; } , sortGameObjects: function (gameObjects){ if ((_AN_Read_length('length', gameObjects)) < 2) { return gameObjects; } this.scene.sys.depthSort(); return gameObjects.sort(this.sortHandlerGO.bind(this)); } , sortHandlerGO: function (childA, childB){ if (!childA.parentContainer && !childB.parentContainer) { return this.displayList.getIndex(childB) - this.displayList.getIndex(childA); } else if (childA.parentContainer === childB.parentContainer) { return childB.parentContainer.getIndex(childB) - childA.parentContainer.getIndex(childA); } else if (childA.parentContainer === childB) { return -1; } else if (childB.parentContainer === childA) { return 1; } else { var listA = childA.getIndexList(); var listB = childB.getIndexList(); var len = Math.min(_AN_Read_length('length', listA), _AN_Read_length('length', listB)); for (var i = 0; i < len; i++ ){ var indexA = listA[i]; var indexB = listB[i]; if (indexA === indexB) { continue ; } else { return indexB - indexA; } } } return 0; } , stopPropagation: function (){ if (this.manager.globalTopOnly) { this.manager.ignoreEvents = true ; } return this; } , addUpCallback: function (callback, isOnce){ this.manager.addUpCallback(callback, isOnce); return this; } , addDownCallback: function (callback, isOnce){ this.manager.addDownCallback(callback, isOnce); return this; } , addMoveCallback: function (callback, isOnce){ this.manager.addMoveCallback(callback, isOnce); return this; } , addPointer: function (quantity){ return this.manager.addPointer(quantity); } , setDefaultCursor: function (cursor){ this.manager.setDefaultCursor(cursor); return this; } , transitionIn: function (){ this.enabled = this.settings.transitionAllowInput; } , transitionComplete: function (){ if (!this.settings.transitionAllowInput) { this.enabled = true ; } } , transitionOut: function (){ this.enabled = this.settings.transitionAllowInput; } , shutdown: function (){ this.pluginEvents.emit('shutdown'); this._temp.length = 0; this._list.length = 0; this._draggable.length = 0; this._pendingRemoval.length = 0; this._pendingInsertion.length = 0; for (var i = 0; i < 10; i++ ){ this._drag[i] = [] ; this._over[i] = [] ; } this.removeAllListeners(); var eventEmitter = this.systems.events; eventEmitter.off('transitionstart', this.transitionIn, this); eventEmitter.off('transitionout', this.transitionOut, this); eventEmitter.off('transitioncomplete', this.transitionComplete, this); eventEmitter.off('preupdate', this.preUpdate, this); eventEmitter.off('update', this.update, this); eventEmitter.off('shutdown', this.shutdown, this); } , destroy: function (){ this.shutdown(); this.pluginEvents.emit('destroy'); this.pluginEvents.removeAllListeners(); this.scene.sys.events.off('start', this.start, this); this.scene = null ; this.cameras = null ; this.manager = null ; this.events = null ; this.mouse = null ; } , x: { get: function (){ return this.manager.activePointer.x; } } , y: { get: function (){ return this.manager.activePointer.y; } } , mousePointer: { get: function (){ return this.manager.mousePointer; } } , activePointer: { get: function (){ return this.manager.activePointer; } } , pointer1: { get: function (){ return this.manager.pointers[1]; } } , pointer2: { get: function (){ return this.manager.pointers[2]; } } , pointer3: { get: function (){ return this.manager.pointers[3]; } } , pointer4: { get: function (){ return this.manager.pointers[4]; } } , pointer5: { get: function (){ return this.manager.pointers[5]; } } , pointer6: { get: function (){ return this.manager.pointers[6]; } } , pointer7: { get: function (){ return this.manager.pointers[7]; } } , pointer8: { get: function (){ return this.manager.pointers[8]; } } , pointer9: { get: function (){ return this.manager.pointers[9]; } } , pointer10: { get: function (){ return this.manager.pointers[10]; } } } ); PluginCache.register('InputPlugin', InputPlugin, 'input'); module.exports = InputPlugin;