romainberger / voxel-painter-core

Extract the core module from maxogden/voxel-painter
https://github.com/maxogden/voxel-painter
BSD 2-Clause "Simplified" License
3 stars 0 forks source link

Plugin management #3

Open romainberger opened 10 years ago

romainberger commented 10 years ago

The point of releasing this module and extracting it from the website is to allow the creation of plugins. I'm alone here but I've never worked on a module that would allow plugin so I'll dump ideas on how this could work hoping someone with more experience can review this

Here is a first idea of how this could work:

var voxelPainter = require('voxel-painter-core')
  , plugin = require('voxel-plugin-to-do-stuff')

var painter = voxelPainter({container: '#container'})

// load the plugin in the voxel-painter instance
painter.loadPlugin(plugin)

The core module would then provide hooks (pre and post) on most methods. The plugin could for example try to do something after a voxel has been added:

// plugin snippet
module.exports = function() {
  var nbrOfVoxel

  this.postAddVoxel = function() {
    nbrOfVoxel++
    // do something interesting here
  }
}

So the core module loadPlugin method would store the plugin, then on every hook iterate on the plugins registered. If they have a method corresponding to the hook, run it.

The hook could provides informations and variables. For example for a hook called before adding a voxel:

// plugin module snippet
function preAddVoxel(x, y, z, c) {
  // x, y, z and c would be the infos given by the core module 
  // on the position and color of the voxel to be add
}

The issue could be that if the plugin can modify these values they need to be returned.

romainberger commented 10 years ago

Other solution with streams (Gist: https://gist.github.com/romainberger/9117621)

Basically the core module would load the plugins and everything would use streams to emit / watch events.

// Core module
var Stream = require('stream')
  , pluginStream = new Stream()

// [...]

  /**
   * Load a plugin
   */
  exports.loadPlugin = function(plugin) {
    plugins.push(plugin)
    return plugin(pluginStream)
  }

   // [...]
   // then in the methods, emit events from the stream
   function addVoxel(x, y, z, c) {
     pluginStream.emit('addVoxel', [x, y, z, c])
     // [...]
   }

In the module, watch the stream given

var Stream = require('stream')
  , stream = new Stream()
  , numberVoxel = 0

var voxelCount = function(studio) {
  studio.on('addVoxel', function() {
    numberVoxel++
    stream.emit('addVoxel', numberVoxel)
  })

  return stream
}

module.exports = voxelCount

then load the plugin, in this example the module also returns a stream to trigger stuffs

voxelCount = studio.loadPlugin(voxelCount)
voxelCount.on('addVoxel', function(number) {
  console.log(number+' voxels in the canvas')
})