- Added a button to start from scratch
woodring
Creator of
Recent community posts
https://woodring.itch.io/patternshop tutorial and playable deck
- added a button to start from scratch
https://itch.io/post/15815697 - I started it two days before that post, so it’s been 21 days.
To be fair to everyone else, I’d give myself 8 more days and submit it by the 29th without any more edits after that.
Would that be OK? This jam came at a convenient time and will force me to finish the tutorial by the 29th.
OK - it’s been redone. Hopefully this is the last one for a while.
-
no more layer buttons; order is implicit on card order
-
no more operation buttons; probably the only thing that is wanted is underpaint. over is achieved by reordering the cards.
-
everything has a hotkey and the buttons show what they are. they can be hidden.
-
UNDO! (infinite right now, but I should limit it - otherwise, you can run out of memory)
-
support for the palette card: a goto/return button, an eyedropper, copy brush and pattern from palette
-
probably a few other things
As an aside - I only just now noticed there was a WigglyPaint retrospective.
Related to that - in my attempts for making this easier to use:
-
make compositing order implicit based on the card order, since there’s already the ability to reorder cards
-
make the background automatically the composite target
-
probably all that is wanted is underpaint/masking, so I’ll probably remove operator selection. or make it less up front and center
-
I like the palette/swatch selection. so make it go directly to a “physical palette” where you can select the pattern visually with a select tool. apply your patterns in swatches like paint. kind of like how layercake can be used now to lift brushes off the palette.
this will remove all of the buttons and probably all that’s needed is a few hot keys to operate the layercake tool.
Video and tutorial card are still on their way.
I’ve made a couple of more usability passes as I’ve been trying to use it for real (the actual reason this exists).
off the top of my head:
- wipe (clear) button
- +/- buttons for incrementing and decrementing the brush and pattern on canvas layers
- other things that I don’t remember
I’ve done a pretty simple sketch of a face and torso where I sketch the rough on one layer, switch to another to outline the face by overpainting, and then switch to a third to add shading by underpainting. It works pretty well.
There will be a learning curve - but (not that this excuses it) most drawing programs with layering, that I know of, have a steep learning curve.
What needs to be added - but the last two, I don’t know if I’ll get to it. It works for my needs and the amount of work to make them functional is way over my annoyance threshold.
- the tutorial
- DONE ~don’t allow C to be activated if there are no active layers~
- DONE ~a “logical lock” - once switched to layer mode, make it ask more when switching to composite mode and vice versa - to protect drawings from being wiped.~
- (maybe, but I probably won’t) a grid widget for globally reordering layers (an overview of the composite)
- (maybe) a couple of levels of undo
I’ve made several updates. In particular, added over and under composite modes, along with several other things.
It probably operates more like people expect, now.
I plan on merging a lot of the functionality into the canvas target and layer widgets, to reduce the number of contraptions. Card target and layer contraptions will mostly remain the same. While the cards seem relatively limited compared to the canvases, they both serve a purpose: 1. being able to composite with the existing Decker drawing tools, and 2. a composited background for a canvas layer to trace over or underpaint.
https://woodring.itch.io/patternshop tutorial and deck
patternshop
a compositing tool for cards and ps canvases as layers
https://woodring.itch.io/patternshop
reload if the video is not playing

tutorial and playable deck: https://woodring.itch.io/patternshop
direct download of deck: https://codeberg.org/woodring/decker.patternshop/raw/branch/main/patternshop.deck
project and readme, which is pasted below: https://codeberg.org/woodring/decker.patternshop/src/branch/main
see https://codeberg.org/woodring for more decker things
synopsis
It’s a module and several contraptions that emulate layered drawing in other drawing tools. Or, it can be thought of as “Decker mega-underpaint mode.”
https://woodring.itch.io/patternshop
-
make at least three cards
-
put the
patternshopcontraption on each of those cards. -
switch to interactive mode.
-
press
0(zero) on each of the cards to activate the contraption. -
draw on the first card in interactive mode.
-
switch to the second card. what was drawn on the first card appears there.
-
draw on the second card.
-
switch to the third card. what was drawn on the second will be under the first.
-
et voila, layered drawing!
Why is this important? Imagine:
-
card1 has a rough sketch.
-
card2 shows card1, to trace over card1’s sketch.
-
card1 is deactivated, automatically removing the sketch, without having to manually erase it from card2.
-
card3 shows the outline of card2, to add shading without worrying about staying exactly in the lines.
layered drawing - how it works
patternshop is a contraption that combines multiple images into
one. In another PS or other drawing programs, it’s what’s called
layering. In graphics, it’s what we call compositing or
image composition.
Another analogy is that it’s like old school cel drawing, for animation, where the scene is composed of several stacked layers of transparent celluloid.
The mode of operation is to draw on the patternshop canvas,
which is a transparent drawing surface, in front of the card
background. All of the active patternshop drawing surfaces are
combined together - in a stack. Then, the combined stack is
copied onto each card background of each card that patternshop
is on. This provides the combined result on each layer - i.e.,
card.
Images are combined in card order. To change it so a drawing
appears under another, reorder the cards in the Decker menu, i.e.
File->Cards. Later cards in the stack appear under the ones
in front of it. For n layers, make n+1 cards with
patternshop on it. The final card will show everything
together, by itself.
IMPORTANT: Drawing on patternshop requires interactive
mode - not drawing mode. Decker drawing mode only works on
cards. To use the Decker drawing tools, draw on a card then use
the patternshop swap function to move the image to the
patternshop contraption. Alternatively, use ps_layercake
contraption to copy it.
When drawing on a card, with an image on the patternshop
canvas, it will be under the canvas - which is what might be
wanted for more accurate underpainting. Drawing on patternshop
only supports the freehand pencil with custom brushes and
patterns.
But, what makes patternshop different is that allows for
drawing on the canvas and simultaneously seeing the card
background underneath - to trace over it. It’s like Decker’s
built-in underpainting, but with patternshop there’s an
arbitrary number of underpainting layers.
Note: the only composite mode that patternshop supports is
under. To achieve over, move the card to the front of the
card stack. The other compositing modes that Decker likely aren’t
used in practice by most people and are not included.
usage notes
-
To save your work, save the deck. Everything is retained between sessions.
-
Reordering cards to change layer combining order is immediate, after closing the card order dialog.
-
The starting visibility of
patternshopandps_layercakeis transparent for the canvas to provide tracing over the card background, by default. They can both toggle between “solid”, “transparent”, “invert”, and “none”. -
Everything is hotkey driven - for two reasons: (1) save screen real estate, but more importantly (2) when drawing, especially with a tablet, it is common to have a hand hovering over hotkeys or program the tablet for the hotkeys. It starts with a toolbar that can be hidden with
qafter learning the hotkeys.- Buttons for
4,Z,andXonly work with hotkeys. They are visually present to show what they hotkey is.
- Buttons for
-
As noted earlier, there’s a second contraption,
ps_layercake, which is an advanced rubberband/select box that knows how to work withpatternshopcontraptions and cards. -
The
patternshopandps_layercakecontraptions can be used in any Decker project, as long as thepsmodule is copied over, too. They will not work without it. -
Switching to a card will composite (combine) all layers if there is an activate
patternshopon a card. It only updates “on view”; i.e., changing cards or having an animated widget on that card. But, having an animated widget on apatternshopcard will slow Web Decker down quite significantly. While drawing, I do not suggest having animated widgets on the cards.
controls for patternshop
patternshop home row
1: toggle canvas visibility between “solid”, “transparent”,
“invert” and “none”. starts in “transparent”. “solid” will hide
the card background and “none” will hide the canvas.
2: toggle to the last brush used. starts with brush “1”.
3: toggle to pattern 0 and back to the last pattern used.
4: eyedropper tool that picks a pattern under the cursor. picks
from the canvas first and the card second. does not change the
pattern if it is pattern 0.
5: goto a card named palette. to be used in concert with 4,
w, e, and ps_layercake’s custom brush function - to store
patterns and brushes on a card, like a real-world palette. the
palette card can contain whatever you wish - as long as it has
a patternshop contraption on it. pressing 5 when on the palette
card returns you to the previous card.
after learning the hotkeys or needing to temporarily move it
q: hide the toolbar
palette support
w: copy the brush from the palette card.
e: copy the pattern from the palette card
off patternshop home row
6: swap the image between the canvas and the card. to use
Decker drawing tools - draw on the card and then swap it to the
canvas.
7: erase the canvas.
8: set the brush. it will ask to provide a brush number or
custom brush name. 2 swaps between two brushes.
9: set the pattern. it will ask to provide a pattern number in.
for quicker pattern changing, use 4 and 5 with 3.
0: activate/deactivate the patternshop on this card. once
activated, it will show all other active patternshops combined
in card order. to remove a layer, deactivate it with 0.
IMPORTANT activating a pattershop will ERASE any
existing card background image.
undo and redo
z: infinite undo for canvases - up to available memory. no
effect for cards. TODO need to put an undo limiter in to not
accidentally run out of memory.
x: redo after undo. drawing after redoing will clear the redo
stack.
ps_layercake support
r: make a ps_layercake at 100,100
ps_layercake hotkey to support patternshop
y: remove all layercake instances from the card. IMPORTANT:
if there is more than one on a card, it will remove ALL of
them.
controls for ps_layercake
ps_layercake is a select/rubberband box companion for
patternshop. It can copy and move selections around the canvas
and card background, more selectively than the patternshop swap
(6) function.
It works in interactive mode, like patternshop. The upper-left
box moves it and the lower-right box resizes it. All of the other
controls are hotkey driven, like the rest of patternshop.
Also, it can be copy and pasted to any other card, just like any other contraption, moving the copied image between cards.
layercake to-and-from the card background
c: copy card background into layercake.
v: paste layercake onto card background.
n: merge card background into layercake. this is
different than c, because it treats pattern 0 as transparent.
m: merge layercake onto card background. like n,
this is different than v, because it also treats pattern 0 as
transparent.
layercake to-and-from the canvas
d, f, h, j: copy, paste, merge into, merge onto for the
canvas layer, instead of the card background.
other functions
t: toggle layercake visibility between “solid”,
“transparent”, “invert” and “none”.
g: erase the layercake image contents.
b: save the layercake image contents as a custom brush. it
will ask for a name.
y: remove all layercake instances from the card. IMPORTANT
if there is more than one on a card, it will remove ALL of
them.
on patternshop to support layercake
r: make a ps_layercake at 100,100
I was using it for frame timing for the bpm.
current time - last beat > bpm gap -> send a bang
so, i just hacked it by reoverflowing to positive by adding 2^31.
i just realized it’s still not 100% correct, because i’m not accounting for the timing gap (jitter) that is getting lost due to 60 Hz quantization.
update: oh, right. it wasn’t working because the “last frame” time was never initialized - so “current time” - “last frame” will always be negative, since it’s “current time” - nil (0). that’s the real reason.
so, anyways - i don’t know if negative sys.ms is supposed to be a thing, but it certainly wasn’t expected. it’s how i usually time gaps and don’t worry about initializing the first frame time for the possibility of negative time.
Here’s a version that’s a little more robust that will regenerate the card and allows for interactive updates to it:
# paste this into a card's (slide's) script (menu Card->Script...)
on view do
# boilerplate start
if card.widgets.sentinel
each k in keys card.widgets
card.remove[card.widgets[k]]
end
end
f: card.add["field" "sentinel"]
f.show: "none"
# boilerplate end
# your slide commands go here for each card
# this is different for each card (slide)
f: card.add["field" "title"]
f.pos: 30,30
f.text: "here is a title"
f.font: "menu"
f: card.add["field" "info"]
f.pos: 50,100
f.size: 200,200
f.text: "here is some information"
end
As always, it depends.
If you want something simple or a DSL (domain specific language) like Adelie, not that I know of. Though, John has made a lot of different tools and modules that could stand in for parts of it.
But, the other way is that you can is using the built in Decker commands. If I add this to a card’s script, (go to the toolbar menu, Card->Script...) I can programmatically generate the card:
removed – see my next comment for an improved version
Again, maybe not 100% of what you’re looking for, but it’s there: https://beyondloom.com/decker/decker.html#cardinterface
Also, the reason that I didn’t (aside from running out of time) was the audio feedback for a biquad filter ended up being pretty computationally expensive.
So, it probably would have required reprocessing the entire playback prior to playing it to remove audio lag.
I squeaked mine through just before the end, too.
I updated the description to the entry and game page.
Millie - I didn’t end up connecting it to your synth, but I did steal your Twinkle, Twinkle, Little Star csv from it to use in mine.
A visual data flow programming sandbox/toy/tool for Decker. Inspired by Pd (Pure Data).
Make programs by dropping boxes (nodes) and connecting them together with wires or pipes - very little to no typing.
A more “physical” way of programming that is akin to wiring diagrams or pipe flows - where you can see the results immediately and programs don’t crash.
The first card has a tutorial to explain how to use dP. Dialog boxes will pop up to explain how to use it. Click in the boxes to continue to the next.
Cards in the deck (use left-right arrows to navigate through the cards or the Decker menu):
- tutorial card for using dP
- Dialog boxes will pop up to explain - click in them to continue to the next
- demo for tracking mouse position and clicks
- demo for animating an object to move
- audio demo for a metronome
- audio demo for a tone generator with audio filters (2 cards)
- a simple one voice synthesizer that plays Milly’s Janky Tunes csv format
- the wiring for the tutorial card
- an editor that shows the dp module that drives most of dP
Made in Decker for Dec(k) Month 3 jam. Thanks to John for making Decker in the first place and Millie for the Twinkle, Twinkle, Little Star csv that I stole from her Janky Tunes sequencer.
CHANGELOG:
- 20260102 - release
- 20260103 - initialized bpm to account for negative sys.ms and fixed jitter due to 60Hz quantization
For me, I think the most appropriate metaphor is that it is the “workbench.” Or, the supercharged REPL: a computational notebook or a literate programming environment.
I’ve always gravitated towards things where I can work incrementally: Lisp, Lua, Jupyter notebooks, R-Studio markdown, etc. I’ve even gone so as far as making an environments where I can incrementally program and test C code, to emulate a notebook-like interface.
The other thing that I like, and you even mention this in the workbook section: it gives me the capability to build it as I need. That’s the Forth and Lisp creed. Or roughly, Unix creed. Do one thing and do it well - which I’ve always interpreted as, build only the thing you need.
It’s the peeve I have with other computer scientists or software engineers. They try to solve everyone’s problem, but end up either solving no one’s or doing it really badly.
So - yeah - Decker scratches the itch just right for me.
Yeah, thanks for the heads up. I was looking at the Janky code already, and had thought about it, too.
So, it’s not going to be a 1-for-1 emulation of Pd - because of that. I’m not sure Decker could handle the amount of processing. Maybe, maybe not.
But, I think a sound queue should suffice and give the appearance of realtime.
Oh, I should mention - the above picture runs in real-time already. I can type in where the 5s are, a different number, and they will automatically add up in real-time. That’s why it shows 10.
It’s just that I don’t have a visualization for the connections/wires/inputs and outputs, yet, so you can’t see them connected together. Because the output of “frame” connects to the first 5 box, the 5 box connects to the second 5 box, so the number gets copied, and then they both feed into +, and then plus outputs into the final box to show you 5+5=10.
Pd (Pure data) is a flow graph based programming environment, primarily, for real-time audio processing. It was made by Miller Puckette and also worked on Max/MSP <- (hence the name MSP).
Pd, along with Max/MSP/Jitter, are used for deejaying and veejaying, along with general audio and video processing. For instance, I have a Pd patch that I made for my computer to mix various audio sources, along with a custom equalizer, bs2b filter from scratch, etc. (I once used Max to do real-time special effects for a university play in collaboration with the theatre department and a computer graphics offshoot of the art and design college. Anyways.)
So, I want to see if I can do real-time audio processing on your sequencer. I hope I can squeeze enough cycles out of it to do something.
For the most part, dP is an experiment of mine for tinkering with data flow graph processing, because it can do more than audio - general programming. It could be something non-programmers could use for Decker. Audio engineers and deejays/veejays make their own Pd patches. Flow graph programming is frequently used in visualization tools, like VTK and ParaView, for instance.
It’s interesting to me because flow graph and graphics (my background) programming, in general, very much have a “feed-forward” view of programming - kind of like React or Unix pipes (hence, decker Pipes). It’s more procedural, event-loop, like a factory or process engineering view of programming - not a math based view of programming, which is more “call-back” or “inside-out,” in my opinion.
At least, it will be a neat toy that I hope to do some audio manipulation with your sequencer. (I’m not trying to oversell this as taking over the world, as flow graph programming has been around forever. It’s just an experiment of mine.)
Is this intended or a bug? Assigning get/set with the keystore appears to strip a level of list.
Or am I missing something?
lib: ()
lib.test: on _ do
a: (list (list (list 1,2,3)))
data.a: a
show[data.a]
data.a: data.a
show[data.a]
data.a: data.a
show[data.a]
data.a: data.a
show[data.a]
x: (list (list (list 4,5,6)))
y: (list (list 7,8,9))
z: (list 10,11,12)
w: 13,14,15
data.x: x
show[data.x]
data.y: y
show[data.y]
data.z: z
show[data.z]
data.w: w
show[data.w]
nil
end
will produce:
(((1,2,3)))
((1,2,3))
(1,2,3)
1
(((4,5,6)))
((7,8,9))
(10,11,12)
13
nil
This was run in v1.62 Decker
I’ve updated a few things related to the WebXDC stuff:
I’ve diverged from https://codeberg.org/rtn/decker-xdc such that my stuff just uses vanilla Decker.
I didn’t want to rely on a modified version of Decker for using it in WebXDC. As such, my xdc module https://codeberg.org/woodring/decker.xdc has an xdc.save_deck method to compensate for that vanilla web Decker cannot reliably save decks when running in a WebXDC environment. (rtn modified web Decker to do this, and it was his main modification).
Two, I’ve made a slimmed down version of web Decker v1.61 that originally was a modification rtn’s version https://codeberg.org/rtn/decker-xdc to bring it up to v1.60 - but since, it’s now just a packer to make WebXDC packed Deckers: https://codeberg.org/woodring/decker.decker-xdc.
My other things that used WebXDC are updated with the newer module. Technically, starter and whiteboard have a more up to date version than what is in the xdc module and card. That’s because I haven’t gotten around to documenting the changes that are in the newest version. So, it’s a bit behind.
Also, there’s a couple of new things I have made that aren’t WebXDC enabled, like Cammy: https://codeberg.org/woodring to see all of my Decker junk.
Cammy (or Leon if you prefer) - a rapid menu-less widget-making widget
Cut and paste for Cammy is here: https://codeberg.org/woodring/decker.cammy
(hit reload if the image isn’t playing, my apngs don’t loop)

Yes, you could do this through the listener, but I find this easier and faster – especially if you have a Cammy making button:
%%WGT0{"w":[{"name":"make_cammy","type":"button","size":[64,16],"pos":[432,32],"script":"on click do\n w: card.add[\"contraption\" \"cammy\"] \n w.pos: (card.size / 2) - (w.size / 2)\nend","text":"cammy"}],"d":{}}
Inspired by Pd https://puredata.info
More of my decker junk: https://codeberg.org/woodring






