Registering new inks in extensions

My proposition is to provide a simple API to allow for implementing custom inks in extensions, a mock extension code could look as follows:

function init(plugin)
    plugin:newInkGroup{
        id = "custom-ink-group",
        title = "Custom Inks"
    }

    plugin:newInk{
        id = "custom-ink",
        title = "Custom Ink",
        group = "custom-ink-group",
        onclick = function(pixel, color) -- Modeled after `image:pixels()`
            local pixelValue = pixel() -- get pixel
            pixel(color.rgbaPixel) -- set pixel
            print(pixel.x, pixel.y) -- get pixel x,y coordinates
        end
    }
end

function exit(plugin) end

plugin:newInkGroup - would allow for registering a group in the ink menu so inks can be organized.

plugin:newInk - would allow for registering a new ink in the ink menu, with parameters:

  • id - for reference and identification
  • title - title displayed in the ink menu
  • group - if provided it would assign the ink to one of the custom ink groups, if nil then the ink would be assigned to an additional unnamed group to differentiate it from the core inks
  • onclick - simple function for processing pixels, modeled after image:pixels(), it would provide two parameters:
    • pixel - with x and y coordinates of the pixel (both immutable), if called with no argument it would return the pixel value of the pixel being processed, if called with a parameter - this parameter would be treated as a new value for the pixel (accepting either Color or raw color value)
    • color - depending on user input and editor preferences it would be either the active foreground color or background color, immutable

And a mock extended ink menu could look like this:

image

Hi @thkwznk thanks for your post! Actually the original issue for script in extensions #1949 included this item: Script in extensions · Issue #1949 · aseprite/aseprite · GitHub

I like the general design. Still not sure what callback/events should be offered (not sure if onclick or other simple formats). For example:

plugin:newInk{
  id = "custom-ink",
  title = "Custom Ink",
  group = "custom-ink-group",
  filterPixel = function(color)
    return newColor
  end
}

Anyway this limit the possibility to use the xy coordinate or use a sub-region of the pixel. We could offer some options like:

filterPixel = function(color)
  return newColor
end
area = { size=Size(3, 3), center=Point(1, 1) },
filterArea = function(data)
  -- data.centerPixel
  -- data.pixels[1...3*3]
  -- data.width = 3
  -- data.height = 3
  -- data.center.x = 1
  -- data.center.y = 1
  -- etc.?
  return newColor
end
3 Likes

I completely missed that you already had it planned, my bad. :sweat_smile:

I’m not completely sure about the area and filterArea interface you suggested, I might have not understood it correctly but it feels to me like it disregards the selected brush and/or dynamics.

But to be honest I completely forgot about the brush in my suggestion and I think it should be included, ideally with pre-applied properties that would be the result of dynamics settings so that they don’t need to be applied in every custom ink. :thinking: