Tools

A tool appears in the toolbox and is told what the pointer does on the picture.

A tool that paints

With paints on, the tool paints on a layer (the selected painted one, or a new one). The event carries that layer's pen, and a whole stroke is one step to undo.

tools: [{
  key: 'speckle', name: 'Speckle', icon: 'Brush', paints: true,
  about: 'Dots scattered round the pointer, in the color in hand',
  fields: [{ key: 'density', label: 'Density', low: 1, high: 80, step: 1, usual: 20 }],
  on(event) {
    if (event.kind === 'release' || !event.pen) return;
    const reach = Math.max(3, event.size * 3);
    event.pen.fillStyle = event.color;
    for (let n = 0; n < event.settings.density; n++) {
      const angle = Math.random() * Math.PI * 2, far = reach * Math.sqrt(Math.random());
      event.pen.fillRect(Math.round(event.x + far * Math.cos(angle)), Math.round(event.y + far * Math.sin(angle)), 2, 2);
    }
  },
}],
import math
import random

from rassam import slider


@plugin.tool('Speckle', icon='Brush', paints=True, about='Dots scattered round the pointer, in the color in hand',
             fields=[slider('density', 'Density', 1, 80, 20)])
def speckle(event):
    if event.kind == 'release':
        return
    pen, reach = event.pen, max(3, event.size * 3)
    pen.fillStyle = event.color
    for _ in range(int(event.settings.density)):
        angle, far = random.uniform(0, math.tau), reach * math.sqrt(random.random())
        pen.fillRect(round(event.x + far * math.cos(angle)), round(event.y + far * math.sin(angle)), 2, 2)

A tool that works with layers

Without paints, the tool is given no pen. It works with the project instead.

tools: [{
  key: 'dots', name: 'Dots', icon: 'Ellipse', about: 'Click to put a dot there: a shape of its own',
  fields: [{ key: 'size', label: 'Size', low: 4, high: 400, step: 1, usual: 48 }],
  on(event) {
    if (event.kind !== 'press') return;
    const { w, h } = event.api.size(), size = event.settings.size;
    // A layer's x and y are how far its middle is from the image's.
    event.api.project.add({ kind: 'shape', name: 'Dot', shape: 'Ellipse', w: size, h: size, color: event.color, radius: 0, stroke: 0,
                            x: Math.round(event.x - w / 2), y: Math.round(event.y - h / 2) });
  },
}],
@plugin.tool('Dots', icon='Ellipse', about='Click to put a dot there: a shape of its own',
             fields=[slider('size', 'Size', 4, 400, 48)])
def dots(event):
    if event.kind != 'press':
        return
    w, h = event.app.size
    size = int(event.settings.size)
    # A layer's x and y are how far its middle is from the image's.
    event.app.add(kind='shape', name='Dot', shape='Ellipse', w=size, h=size, color=event.color, radius=0, stroke=0,
                  x=round(event.x - w / 2), y=round(event.y - h / 2))

The event

On the eventWhat it is
kind'press' (the button went down), 'drag' (the pointer moved with it down) or 'release'.
x, yWhere the pointer is, in the picture's pixels.
fromX, fromYWhere the button went down. In Python: event.start.
shift, ctrl, altThe keys held.
color, color2, sizeThe colors in hand and the brush's size.
settingsThe tool's own settings.
penThe layer's canvas context, when the tool paints. It draws as a web page's canvas is drawn on. In Python, event.picture gives the layer's pixels too.
apiThe API. In Python: event.app.