If you’ve used Punctual before, you might be interested in the new features included in the recently released version 0.5. Below is a summary of the key updates.
Breaking changes
Missing Channels Default to 0
In Punctual 0.4.x, the expression circle 0 1 >> add
would produce a white circle because a one-channel signal was automatically repeated across the second and third channels.
This behavior has changed in version 0.5. Now, any missing channels default to 0, meaning that the same expression will now result in a red circle, as the green and blue channels default to 0.
This change has other implications. For instance, rect 0 0.5 >> add
is now equivalent to rect 0 [0.5, 0] >> add
, not rect 0 [0.5, 0.5] >> add
, and will produce a degenerate rectangle. Similarly, rect 0.5 [0.5, 0.5]
will now be positioned at [0.5, 0]
, not [0.5, 0.5]
as it was in version 0.4.
Output Notations
Punctual 0.5 introduces new output notations, focusing on how patterns are combined rather than on the channels used.
While the old rgb
and rgba
notations still exist, they now have slightly different meanings.
The most commonly used output notations are now add
and blend
, with add
being the equivalent of rgb
in version 0.4, and blend
equivalent to rgba
. The mul
notation completes the set of available outputs.
All deprecated output notations have been removed, including red
, green
, blue
, hue
, saturation
, value
, hsv
, alpha
, and fdbk
.
For more details, see the output notations section.
Functions with Fewer Arguments
None of the texture-creating functions (fb
, fft
, ifft
) require arguments anymore.
For example, where you previously wrote fb fxy
, you now simply write fb
. Other expressions can be adapted similarly: for example, fb frt
can be replaced with setfxy frt fb
. This update aligns these functions with img
, vid
, and cam
, which already worked this way.
The fft
function is now equivalent to the 0.4 expression fft fx
.
Removed Functions
step
: useseq
where possible, as explained below.zip
: not removed but deprecated. Use{}
instead.
Functions with Different Meanings
tile
andzoom
: see the details below.
Internal Changes
These changes may not be immediately obvious to users but have significant long-term implications for how Punctual functions and evolves.
Reimplementation in PureScript
Punctual 0.5 has been completely rewritten in PureScript, a functional programming language that compiles directly to JavaScript. Prior to version 0.5, Punctual was written in Haskell.
This switch simplifies the process of generating the final JavaScript version from Punctual’s source code, making it easier to develop new features. Additionally, it opens up possibilities for users to create their own modified versions of Punctual more easily.
Exolang
Punctual is now an exolang in Estuary. Essentially, this means that the Punctual code can be modified and these changes can be applied in Estuary without needing to alter any of Estuary’s code. As a result, bug fixes and new features can be implemented more quickly.
Since exolangs can be imported dynamically into Estuary, you can now use different versions of Punctual or even your own customized versions seamlessly. Different Estuary cells can even run different versions of Punctual simultaneously.
New Features
User-Defined Functions
You can now define your own functions and add them to Punctual!
User-defined functions are written in Punctual itself, accept arguments, and can contain any Punctual expression. The only limitation is that user functions must be written as one-liners.
For example, the user-defined pixelate
function implements a pixelation effect:
pixelate xy = setfxy $ (0.5+floor (fxy*:(xy/2)))/:(xy/2);
i << img "https://upload.wikimedia.org/wikipedia/commons/6/69/A_smiling_member_of_the_Ramnami_Samaj_%28edited%29.jpg";
pixelate [100,1000] i >> add;
External Script import
In addition to creating your own functions, you can now dynamically import Punctual code files using import
.
Any variables or functions defined in an imported file are immediately available to the rest of your Punctual code.
Files to be imported must be hosted on a CORS-enabled server, just like any other resource (such as images or videos). See Using your own images and videos for ideas on how to set this up.
Time Shifting Functions
Time functions are a new category in Punctual that allow you to control when changes in patterns occur.
This set includes four functions: slow
, fast
, late
, and early
.
Here’s an example of how they work:
l << hline (saw 0.1) 0.01;
[1,1,1]*l >> add;
[1,0,0]*slow 2 l >> add;
[0,1,0]*fast 2 l >> add;
[0,0,1]*late 2 l >> add;
[1,1,0]*early 2 l >> add;
Sequences
Punctual now allows you to create sequences of expressions using the new seq
function, which serves as a more flexible replacement for the removed step
function.
seq
overcomes the main limitation of step
, which could only handle a single number in each step.
For example:
s << seq [osc 0.2, 0];
hline s 0.001 >> add;
This will draw a horizontal line at height 0 half the time, and move it up and down according to the oscillator during the other half.
You can also use signals with different numbers of channels (all signals will be adjusted to the maximum number of channels present):
hline (seq [osc 0.3, saw [0.1,0.2,0.3]]) 0.01 >> add
By default, seq
completes one full iteration per cycle. You can control the speed and phase of the sequence using the time-shifting functions mentioned earlier.
Note, however, that this only covers cases where step was used with a saw
oscillator. For example:
l << hline 0 0.001;
s << step [0.1, 0.5, 0, 0.8, 1.3] fx;
fit 1 $ spin s l >> add;
does not have a direct equivalent with seq
.
Other Changes
Changes in Geometric Transformation Functions
In version 0.4, tile [1,4]
would repeat a pattern once on the horizontal axis and four times on the vertical axis. This behavior is now achieved using tilexy
.
In version 0.5, tile [1,4]
repeats the pattern once and four times, creating two versions of the pattern. In 0.4, this would have been written as tile [1,1,4,4]
.
There are two additional functions: tilex
, which only tiles patterns horizontally, and tiley
, which only tiles them vertically.
The same changes apply to the zoom
function, with corresponding zoomxy
, zoomx
, and zoomy
options.
New Operator {}
In Punctual 0.5, []
combines lists combinatorially, whereas {}
combines them pairwise.
In the following example, all nine circles are created by the []
expression, but only the three yellow ones appear when using {}
:
x << [-0.5, 0.2, 0.8];
y << [-0.8, 0, 0.5];
mono $ circle [x,y] 0.1 >> add;
[0,1,0]*(mono $ circle {x,y} 0.1) >> add;
In version 0.4, this result could be achieved using circle (zip x y) 0.1
.
pxy
The new pxy
shortcut has been added, which is equivalent to [px, py]
.