What's New in Punctual 0.5

A summary of all the changes between Punctual 0.4 and 0.5.

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: use seq where possible, as explained below.
  • zip: not removed but deprecated. Use {} instead.

Functions with Different Meanings

  • tile and zoom: 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].