How can I set priority of event handlers?

These days I am trying to solve priority of event handlers.
My scene is similar to playcanvas’s online editor. There are objects and user can move them when selected.
It is implemented by two scripts mainly:

  • Picker.js
Picker.prototype.initialize = function() {
  this.app.mouse.on('mousedown', this.onMouseDown, this);
}
  • Movement.js
Movement.prototype.initialize = function() {
  this.on('enable', this.onEnable);
  this.on('disable', this.onDisable);
  this.onEnable();
};

Movement.prototype.onEnable = function() {
  this.app.mouse.on('mousedown', this.onMouseDown, this);
};

Movement.prototype.onDisable = function() {
  this.app.mouse.off('mousedown', this.onMouseDown, this);
};

Picker will attach on camera entity. It is always enabled.
Movement will be attach on other entities. Only when the entity is clicked, the Movement script is enabled, other it is disabled.

I hope when Movement script is enabled, its event handler’s priority can be higher than the picker’s, so that I can control the execute order of mousedown event handlers.

hi dude, you should prefer “privilege” to “priority”, it fires a discussion in my office. :laughing:

1 Like

My general approach would not to have multiple event handlers for the same event in different scripts.

With the Movement.js, on enable/disable, I would register the entity or script to Picker.js so it can handle the priority logic of what should receive the mouse down/up event.

1 Like

Do you mean ?

Picker.prototype.initialize = function() {
  this.movement = null;
  this.app.mouse.on('mousedown', this.onMouseDown, this);
};

Picker.prototype.onMouseDown = function(e) {
  if (this.movement) {
    this.movement.onMouseDown(e);
  }
  // rest...
};

Movement.prototype.initialize = function() {
  this.picker = pc.app.root.findByName('Camera').script.picker;
  this.on('enable', this.onEnable);
  this.on('disable', this.onDisable);
  this.onEnable();
};

Movement.prototype.onEnable = function() {
  this.picker = this;
};

Movement.prototype.onDisable = function() {
  this.picker = null;
};

This untested code but should give you the gist:

Movement.prototype.initialize = function() {
  this.on('enable', this.onEnable);
  this.on('disable', this.onDisable);
  this.onEnable();
};

Movement.prototype.onEnable = function() {
  this.app.fire('picker:register', this);
};

Movement.prototype.onDisable = function() {
  this.app.fire('picker:remove', this);
};
Picker.prototype.initialize = function() {
  this.app.mouse.on('mousedown', this.onMouseDown, this);
  this.app.on('picker:register', this.onRegister, this);
  this.app.on('picker:remove', this.onRemove, this);
  this.movementScripts = [];
};

Picker.prototype.onRegister= function(movementScript) {
 // Add to this.movementScripts;
}

Picker.prototype.onRemove= function(movementScript) {
 // Remove from this.movementScripts;
}

Picker.prototype.onMouseDown= function(e) {
  // Now you have the ability to prioritise what you want to do. You have all 
  // the movementScripts in the array to process and work out what you want to do
}
1 Like

It is more like a MouseEventManager…
My aim is to create isolate script, so that it can be more general. :anguished:

I think here is a more general implementation (not tested):

Movement.prototype.onEnable = function() {
  this.app.mouse.on('mousedown', this.onMouseDown, this);

  var callbacks = this.app.mouse. _callbacks.mousedown;
  var index = callbacks.indexOf(this.onMouseDown);

  callbacks.splice(index, 1);
  callbacks.unshift(this.onMouseDown);
};

You may want to expand it further so that the priority of the event is stored in the callbacks somehow. This allows for more flexibility to add other scripts that also want to handle the mouse down event.

I still think registering the script to Picker.js or a separate manager script is the way to go over individual instances of scripts registering the mousedown event directly.

2 Likes