It is possible to make these types of modifications, but it will require moderately involved scripting and familiarity with Decker's features. I strongly recommend starting by reading through All About Brushes, which explains how to extend and enhance Decker's native drawing tools. WigglyPaint takes advantage of these features for some of its wiggly drawing tools!
As of WigglyPaint v1.6, changing drawing tools is done via the changetool[] function in the Card-level script of the card "main". The PopOut contraption "pen" has a script that calls changetool[] like so:
on click do changetool[me me.name] end
This in turn writes to the ".brush" attribute of "target", the main drawing area of WigglyPaint.
Drawing is directly carried out by the Wiggler prototype's prototype-level script: In Widgets mode, double-click the main drawing area to get the "Wiggler Properties" modal, then click "Prototype...", and then within the prototype editor choose "Prototype -> Script..." from the menu.
Within this script, we first see get_ and set_ functions used by WigglyPaint to configure the shape of the "highlighters", the eraser, the brush style, mirroring modes, and others. The draw[] function handles actually drawing lines and brush splats, and the drag[] function handles mirroring, playing appropriate brush sound effects, and doing some bookkeeping for the draw[] function.
Let's look at a simplified skeleton of the draw[] function:
on draw x o frames do if "eraser"~br.text # ... elseif "hi"~2 take br.text # ... elseif "pen"~br.text # ... elseif "pencil"~br.text # ... else # ... end end
The arguments to this function are "x" (a position on the canvas), "o" (the previous location on the canvas in the current stroke), and "frames" (a list of three images comprising the wiggly animation), and the script also frequently references "br" (a field within the wiggler which tracks the name of the active brush) and "c" (the canvas widget that accounts for the visual appearance of the wiggler and is also used as a temporary drawing surface for brushstrokes). Based on the brush selected, we use the drawing coordinates we're supplied to update the frames of the animation!
The simplest tool is that last "default" option:
c.brush:br.text each f in frames c.paste[f] c.line[wiggle[o] wiggle[x]] f.paste[c.copy[]] end
All this does is choose a custom Decker brush by name and then draw lines on each frame, randomly offsetting the start and end coordinates each time. This means that without modifying the wiggler at all, we could use the information in All About Brushes to define a new brush, and then make a button or popout widget which selects that tool by name with changetool[].
The built-in custom brushes WigglyPaint uses are defined in a module called "pens". If you want to see and edit their innards, presently the easiest way is to save wigglypaint as a .deck or .html file, open it in a text editor and search for "{module:pens}". Here's one of the functional brushes you'll find inside:
# 4x4 stipples: t:image@"\n"split 1 drop" %%IMG0AAQABAAwMAA= %%IMG0AAQABMDAAAA= %%IMG0AAQABAAAYGA= %%IMG0AAQABADAwAA= %%IMG0AAQABIAAAIA= %%IMG0AAQABAAgAEA= %%IMG0AAQABEAAEAA= %%IMG0AAQABAAAgBA=" brush[on StippleTiny do random[t] end]
This corresponds to the PopOut contraption in WigglyPaint which is also named "StippleTiny". It selects from a small set of pixel masks every time it "splats" itself along a line. Copying and pasting these "%%IMG..." strings into Decker (without quotes!) will let you see and edit the masks. It's a little tedious, but not as scary as it might initially seem!
The "highlighters" use the end of their names to specify one of Decker's pattern indices to draw in. Their implementation is more complex than a generic drawing tool because they work by compositing their brush shape onto the wiggler's canvas (c) while preserving "black" lines (pattern 1). Here "sh" is another internal field which stores an encoded brush shape image that we need to center at the drawing coordinates:
pat:0+2 drop br.text img:image[sh.text] s:img.size y:x-s/2 each f in frames w:wiggle[y] f.paste[img.copy[].merge[f.copy[w s].map[1 dict 1 pat]] w 1] end
If you didn't want to leave black lines alone, this could become simpler; we just need to map pattern 0 of the brush shape to our highlighter's pattern index, and everything else to pattern 0 (transparent) up-front:
pat:0+2 drop br.text img:image[sh.text].map[0 dict pat 0] s:img.size y:x-s/2 each f in frames f.paste[img wiggle[y] 1] end
Wiring this change up to a UI in wigglypaint- a checkbox, togglebutton, etc- is left as an exercise to the reader; you can reference the surrounding code and widgets for how all the other properties of the wiggler work.
Does any of that help?