Releases: eaviles/Ollin
Releases · eaviles/Ollin
Release list
Ollin 0.4.0
Added
- The API reference is generated from the source as well as written by hand. Every public symbol of the twenty-two library modules now has a page built by DocC, and the core's four hundred and seventy top-level names are grouped on one landing page rather than sorted by kind. A
.spi.ymlfile tells the Swift Package Index which modules to build that documentation for, andScripts/api-docs.shbuilds the same thing locally. It fails on a documentation warning, which is how forty stale doc comments came to light: links pointing at symbols that had been renamed away, and parameters documented under names their signatures no longer carry. It also refuses to pass if a library module of the package is missing from that file, so a new satellite cannot ship with no reference at all. - The site can be read by a machine, not just rendered for a person. Every page now has a markdown twin at the same address with
.mdin place of.html, holding what was actually written rather than navigation and styling wrapped around it, and/llms.txtis a curated index of the whole site pointing at those twins. Each page also says where its own twin is. This follows thellms.txtconvention, which is what an agent with a browsing tool looks for; nothing fetches it automatically.
Changed
- The front page's sketches are a band you page through, and a phone gets them too. Hello, circle now leads a row of sketches you move between with the dots under it, each running beside the whole program that draws it, starting with the circle the README opens on. The separate band of three below it is gone. Moving between them is the browser's own scrolling, so a swipe, a trackpad, and the arrow keys work with no script running, and only the sketch on screen plays: the rest are not fetched until you page to them, which is a megabyte and a half nobody pays for on arrival. One sketch at a time is what puts the band back on a phone, where three of them stacked was a wall of code and the whole thing had to be hidden. The command under Run it names whichever sketch you are looking at, so what you copy runs what you see.
Fixed
- The Syphon satellite works from a package dependency again. Any project that pulled Ollin in by version, which is what
ollin new --remotewrites, could not useOllinSyphonat all: the build stopped at resolution withthe target 'CSyphon' in product 'OllinSyphon' contains unsafe build flags. The vendored engine needed a prefix header forced into every file, which SwiftPM can only pass as an unsafe flag. Each file now imports that prefix itself, so the flag is gone and nothing about the running code changed. - The site's favicon no longer sits in a white box in Safari's tabs. Safari draws a light plate behind an icon whose own tone reads too close to the bar it sits on, which is what an icon carrying a near-black tile gets on a dark tab bar. The mark is drawn on nothing now, in near-black for a light bar and paper for a dark one, and the page picks between the two files: Safari ignores a color-scheme media query written inside an SVG favicon, so the drawing cannot change its own ink.
Ollin 0.3.0
Added
- Every example can show what it does, not just what it says.
Scripts/media.shrenders a clip and a still for a sketch and puts them where the site reads them, and the example's own page on the website plays the clip with the still as its poster. A sketch that declares a loop records exactly one lap; everything else records ten seconds, which is what a clip needs to answer what the sketch does before a reader moves on, and an example whose arc wants longer says so in its own row. The clips are H.264 at 4:2:0 tagged for a browser, which is the combination an iPhone plays inline, and they carry no sound. The files live outside the repository behind one addressExamples/media.jsonnames once, so moving the host is one edit. Three hundred and fifty-three examples have theirs; the rest are written down with the reason they do not, being a sketch that waits on hardware, one that waits on a hand, or one measured as barely moving. - Four vision examples work with no camera plugged in. The mirror that grows Turing patterns on you takes the bundled dancer, the object tracker the wrestler, the depth contours the street, and the contour tracer is told which way round its contrast runs, which is why it had been finding nothing in the bundled film. Each reads the picture its own technique reads best, the way the rest of that folder already did. Two are unchanged and honest about it: the barcode reader has no bundled code to read, and the trajectory tracker draws its own synthetic ball.
- The guide and the README open on the work. The guide's first picture is now the sketch each of its thirty-two chapters builds, one per cell, in chapter order, and the README's is thirty-two example sketches from every area of the framework. On the website both play. The markdown carries the still, which is what GitHub and a plain clone can show, and a reader who blocks video or has asked for less motion sees exactly that.
- Every examples listing opens on a grid of its sketches. Each picture links to the sketch and carries its name, so a folder shows what it holds before it says it. On the website the grid is a gallery that reflows to the screen, and resting the pointer on a cell swaps its still for a short clip that plays there; nothing is fetched until then, and a screen with no pointer or a reader who has asked for less motion keeps the still. The examples front page and the 3D and recreations indexes show one picture per group instead, chosen per group and written down. The 3D folder became ten pages on the way, one per topic, since a hundred and thirty-seven sketches in one listing could not take a grid.
- Thirteen figures stopped faking what they teach. The Guide's optical-flow, slit-scan, contour, saliency and detector figures used to author their subject in code: a dancer made of two hash-speckled discs, a clip made of sine stripes, a printed card rasterized from glyph outlines. They read the bundled film and the bundled photographs now, so what a reader sees is what the technique does to a real picture. Motion paints from the film's own frames, the arrows gather on the arms that swing and thin to nothing across the rest of him, the slit scan turns a swung arm into a comb of sleeves, the two detectors read a real desk and print the five lines they found, saliency lands on a face while the classifier puts
marigoldunder its own floor, and the contour tracer comes back with both palms and their creases. The melt, the triplanar skin, the surface grain, the two live-feed environments, the design filters and the print separations took photographs too. Three swaps were tried, rendered, and put back: a spectrum, a dither and a seamless clone all teach better on the drawn source, and the reasons are written down. VideoPlayer.snapshot()works offline. Under a headless export it reads the same virtual playhead the frame does, soseek(to:)and thensnapshot()hands back exactly the moment asked for. A still-imagedetect(in:)over a clip now works where a live tracker reads nothing, which is what lets a figure measure optical flow between two frames of a film and render the same picture on any machine.- A sketch that reads the world still runs when the world is not plugged in.
Camera.orStill(_:)gives back a running camera where the Mac has one and a still picture where it does not, and everything downstream takes either, since both are a feed. Fourteen of the vision examples now fall back to a bundled photograph instead of showing a notice, each to the one its own technique reads best: a body to find, hands to find, a face, a scene to name.--photoon launch takes the picture even where a camera would have worked, which is how a still of a live sketch is made. StillFrames. The feed underneath: one picture published as both aVideoFeedand aFrameSource, so it stands wherever a camera or a video player would. It republishes a few times a second rather than once, because an analyzer drops frames it cannot keep up with and a single frame could be the one dropped.- A photograph in the color-vision check.
Color/ColorVisionand the Guide's figure now show a picture beside the palettes, seen the same four ways: the woven blankets, where red sits beside green oftener than in any other bundled photograph, so the two commonest kinds flatten the weave to one olive band while the blues hold. A palette is still checked color by color, a picture by filtering the layer. The example'spreviewparameter now draws every column in its true colors first, so the one filter over the finished canvas is the only thing simulating anything, which is what that mode always claimed to do. - A pair of hands worth tracking.
SamplePhoto.handsjoins the bundled set, two open palms against a dark ground with every finger separated, andVision/HandTrackingreads it instead of the breakdancer. Both hands come back with all twenty-one joints, so the sketch draws ten finger chains running out to ten separated fingertips; the breakdancer's hands are planted and half closed, which gives the tracker something to find and the drawing almost nothing to show. - A short film, for what a still cannot show.
SampleClip.dancejoins the bundled set: thirty seconds of a dancer on a plain studio ground, 960 square, silent, 1.5 MB, with the camera locked off so that nearly two thirds of the frame never changes. Optical flow, a contour tracer, a skeleton and a matte all want motion rather than a picture, andVision/OpticalFlowandVision/ContourTracenow read the film where there is no camera, having shown nothing at all before. It is vended as a URL rather than as a player, so opening it stays withOllinVideo. - The optical-flow overlay reads any source. Its arrows were scaled against a fixed number of pixels, which suits a hand waved at a webcam and drew almost nothing for a dancer moving a few pixels a frame. Length and color now read against that frame's own fastest motion, so the field is legible whatever it is pointed at.
- A page under uneven light, and two surfaces to wrap a form in.
SamplePhoto.page,.talaveraand.stonejoin the bundled set: a book held open with shadow falling across it, a panel of Mexican talavera tilework, and a dry-stone wall. The page is what adaptive thresholding exists for, and the Guide'sLocalAveragesfigure now shows it losing whole bands of text to one global cut and getting all of them back from a local one;Vision/TextScanreads it too, sixty lines where the desk gave five. The talavera is the one bundled picture that repeats seamlessly, cut to two whole periods of its motif, which is what3D/Materials/Triplanarneeds, since a triplanar projection tiles whatever it is given whatever the wrap says. The stone carries real relief, so3D/Materials/Parallaxreads one photograph as both its color and its height map. The two surfaces are 1024-pixel squares rather than 1600 on the long side, the size a GPU mips evenly. - Two landscapes at dusk, and the first wide pictures in the set.
SamplePhoto.headlandand.boatsjoin the bundled photographs: a headland over the water at Loreto with cacti in silhouette, and small boats off Cozumel under a pink sky. Everything bundled before them was a square or an upright, so a sketch that wanted a landscape had to crop one and throw away the photographer's frame. These two are three to two and share one shape, so either drops into the same box.Effects/SeamlessClonenow clones its slab onto the Cozumel picture instead of a painted wash, which is the honest demonstration of a compositing technique: it was picked because its brightness stays in a narrow band while its color runs from grey-violet to pink, which is the ground a clone needs. - Four streets, for the techniques that want a whole scene.
SamplePhoto.alley,.street,.textiles, and.cityjoin the bundled set: a Guanajuato alley of pastel walls under a wide sky, a San Miguel de Allende street strung with papel picado, woven blankets hung side by side at Teotitlán del Valle, and rooftops running back to the hills. Each is the largest square its original held, so two of the photographer's own edges are untouched. Pixel sorting and seam carving now run on the alley, where half the frame is sky for the carver to eat; the frequency domain runs on the weave, whose spectrum carries bands rather than a plain blob; and the picture-fit example and figure run on the city, whose round dome is the fastest way to see a stretch. Image.cropped(x:y:width:height:)andImage.cropped(toAspect:). The companion toresized: that one changes how big a picture is, these change what is in it. The rectangle form is clamped to the picture, so a crop that runs off an edge comes back smaller rather than empty; the aspect form takes the largest centered piece of a given shape, which is what a square photograph needs before it can stand in for a w...
Ollin 0.2.0
Added
- Newton's basins.
generate(.newton(roots:))runs Newton's method from every pixel over the polynomial with the roots you place (up to eight) and colors each pixel by the root it lands on, shaded by how many steps it took, with the palette spread around the roots andphaseturning it.relaxationscales the step so the basins swell, spiral, and shed islands, and a pixel the method never brings home is paintedtrapped. TheEffects/NewtonBasinsexample, a Guide section in Chapter 18 with the NewtonBasins figure, and thenewton-basinssnapshot. - A homage after Frieder Nake.
Examples/Recreations/FriederNake/HommageAPaulKleedraws the drawing usually called Hommage à Paul Klee (13/9/65 Nr. 2, 1965) from Nake's own list of its chance decisions: horizontal bands of rolled width whose edges buckle across the sheet without crossing, every quadrilateral left empty or filled with vertical lines or triangles, and circles thrown over the whole. A seed is a sheet, and--export-svggives the plotter drawing back. - A board with no firmware of your own.
FirmataBoardinOllinSerialspeaks Firmata over a serial port, so a board running the StandardFirmata sketch every Arduino IDE ships answers pin by pin:analog(0)anddigital(2, pullUp: true)read,write(13, true),write(9, 0.5), andwrite(10, angle: 90)drive a digital pin, a PWM duty, and a servo,bind(analog:to:)puts a pin on a@Param, andmessages()drains every decoded message. Asking a pin is what turns it on, and a board that resets is told everything again. TheIntegration/Firmataexample. - The public API, written down.
API/holds one generated listing per library product (every public type and member with its types, defaults, and deprecation), andScripts/api-surface.shfails preflight whenever the build and the listings disagree, so a change to the public surface is recorded on purpose and reads as a diff in review. This is the ground the 1.0 deprecation discipline stands on. - Deriving one easing curve from another.
Easing.reversed()runs a curve from its other end, so an ease-in becomes its ease-out, andmirrored()puts the curve on the first half of a trip and its reverse on the second, the way the catalog builds its ease-in-outs. Where the catalog already holds the result the helper hands back the built-in (.easeInQuad.reversed() == .easeOutQuad), so it still reads by name on a menu; mirroring an ease-out gives the out-in curve the catalog lacks. ExampleMotion/DerivedCurves, a Guide chapter 3 figure, and the Animation page. - The performance host on a controller. OllinLiveCoding answers OSC at fixed addresses under
/ollin/(evaluate, evaluate fresh, hide the code, the code's backdrop and size, record) once a port is set in the inspector's new Controls card, and learns a MIDI pad, button, or fader for any of them: press Learn, move the control, done. A host preference, never the sketch's; the map holds across launches. Checked headless by--controltest.OllinInspector.Paletteis public, so a host's own card can sit beside the shipped ones. - A room of your own: convolution reverb.
Reverb(impulse, mix:, preDelay:)plays an instrument through anImpulseResponse: a recording (.load,.resource), fading noise (.decay(seconds:damping:)), or a room drawn from a rule (ImpulseResponse(seconds:) { time, noise in }), and.reversed()runs any of them backward. It sits in the chain like the built-in rooms,synth.reverbstill reaches it, it reaches an export exactly, and turningmixnever cuts a tail that is sounding.Examples/Audio/Roomsdraws five rooms from rules.Effect.Kindgains.convolution, the kind a reverb carrying a room reads as. - Timecode: a sketch that chases a timeline.
TimecodeClock(from: midi)follows MIDI Time Code, the position a video deck, a show controller, a lighting desk, or a DAW locked to picture sends as hours, minutes, seconds, and frames, intotimecode,seconds(gliding between frames),frameRate,isPlaying, andisReversed. TheTimecodevalue does the drop-frame arithmetic and both wire forms,MIDIOutput.send(timecode:)andsend(sysEx:)cover the other direction, and the Timecode example plays the deck itself. MIDI - Sharp features from a field: dual contouring.
isosurface(at:in:resolution:method: .dualContouring)meshes a field with one vertex per cube placed where the field's own normals meet, so a block's corners land on the corners and a bored hole keeps its rim, at any resolution, where marching cubes (still the default, unchanged) rounds every edge off to the size of a cell. A cube on a crease carries one vertex per side, so the faces shade flat to the edge while a sphere still shades smooth. Isosurfaces - A homage after Josef Albers.
Examples/Recreations/JosefAlbers/Homageputs the Homage to the Square format on the canvas, squares of ten, eight, six, and four units on a ten-unit grid, each set half a unit lower than the one around it, in the four arrangements he used, and rolls a new set of colors onto it every few seconds from five palette rules of its own (a ramp, a glow, near-value hues, grays around one color, warm against cool), built in OKLCH and crossfaded in OKLab, withcontrastanddriftscaling the sheet's steps live and--export-gridprinting a wall of them. Recreations - Search on the website. Every page
ollin sitewrites now carries a search: the button in the bar,/, or ⌘K opens it, and it looks through the Guide, the reference, and the examples one section at a time, a page's title counting most and the words of its prose least, with a prefix reaching a word (kuwafinds brushwork), a typo in a longer word forgiven, and the words that matched marked. The index is built with the site; the matching is MiniSearch (MIT), loaded from a content network on the first search and pinned to one release by its hash. - Embroidery, a frame as stitches.
--export-embroidery leaf.dstwrites the frame as the stitches an embroidery machine sews, in the Tajima.dstfile nearly every machine reads: strokes as a running stitch whose every corner is a penetration, fills as connected rows (or as outlines), and each color as its own thread in draw order.Embroidery(width:)takes the hoop's real millimeters, andEmbroidery.stitches(_:in:)plans your own contours, so a sketch can draw the stitches before anything sews. - Brushwork, the picture as paint.
layer.filtered(.brushwork())lays the layer on as paint patches that follow the picture's own flow: each pixel takes the average of the flattest of eight sectors of a brush around it, so detail flattens while edges stay crisp, and the brush stretches along whatever edge runs through the pixel, so the patches read as strokes along the contours rather than the square dabs of.oilPaint.radiusis the brush size,stretchhow far an edge can draw it out, andsharpnesshow decisively the flattest sector wins. - Lighter, darker, and the complement of a color.
ink.lighter(),ink.darker(by: 0.25), andink.complementderive a color from one you hold: the first two step its perceived lightness in OKLab units while its hue and chroma stay put, the third is the opposite hue at the same lightness and chroma. A vivid color pushed to the top ends at white, a gray is its own complement, and alpha rides along. - Gabor noise, a noise whose spectrum you design.
generate(.gaborNoise())fills a layer with sparse Gabor convolution: small Gaussian blobs each carrying a cosine wave, scattered and summed, so the field has onewavelength(in pixels), a bandbandwidthwide around it, and one direction (angle, withspread0) or every direction (spreadπ). Brushed metal, wood grain, silk, and rippled water at a turn of the parameters, with the long interference patterns a narrow band makes.impulsesis the quality,phaseslides the waves (periodic over 2π),seedpicks the field, and the kernels are filtered for the pixel footprint so a wavelength near the pixel grid fades instead of aliasing. The same field on the CPU isgaborNoise(x, y, ...)and theGaborNoisevalue type, computing at a pixel what the generator paints there, and in a shader of your own it is the library'sgaborNoise(p, ...).Examples/Effects/GaborNoise. - XDoG, the picture as pen and ink.
layer.filtered(.xdog())draws a line wherever the layer has an edge, solid ink where it is dark, and paper everywhere else, the lines following each edge's own direction so they run continuous rather than breaking into speckle.radiusis the line scale,sharpeninghow far the edges are pushed over the tone,thresholdandsoftnessthe cut and its ramp (0 is a two-tone print),flowhow far along an edge the response is gathered, andforeground/backgroundthe ink and the paper. Empty space on a transparent layer reads as paper.Examples/Effects/InkDrawing. - Hobby's spline.
drawCurve(points, spline: .hobby)threads a curve through points the way a practiced hand does: every gap becomes a Bézier whose control points are solved together, so the bend flows evenly instead of flattening between far-apart points and swelling between close ones..hobby(tension:curl:)tunes it,Contour(curveThrough:spline:)andShape(curveThrough:spline:)take the same choice, andHobbySpline(through:)is the typed form with the Béziers themselves. The default spline is unchanged. - The drag on the performance stage. Under OllinLiveCoding, hold Command over the stage and the shape under the pointer is outlined through the code. Dr...
Ollin 0.1.0
The first tagged release. Ollin grew in one repository from May 2026 to this tag, and that history is not itemized here. This entry says what the release contains, area by area, with a link to the reference for each. The README carries the fuller catalog, and the Guide teaches it in order. Read this entry as a table of contents rather than a list of changes.
The framework
- Drawing. A p5-style API over a Metal core:
setup()anddraw(), and bare calls likedrawCircleandbackground.draw()runs at the display's refresh rate from the first line, so motion is the default. Some thirty analytic shapes, curved paths, concave and holed fills, variable-width strokes, marks that follow the hand, shape booleans and offsets, gradients, blend modes, clipping, accumulation, and retained batches. Every frame composites in linear light with HDR tone mapping and analytic anti-aliasing. Drawing. - Text and color. Bitmap, outline, and single-line plotter fonts through one
drawText, in any script, in columns, justified, along a path, or as vector shapes. OKLab mixing, spectral paint mixing, palettes and colormaps, color vision simulation, and wide-gamut and HDR output. Text, Color. - Shapes that merge. SDF combinators in 2D and in raymarched 3D: smooth union, subtraction, morphing, domain mirror, tile, and radial repeat, and a clay-like
sculpt { }block. Combinators. - Generative technique. Sixty-six classic techniques as first-class helpers, from Poisson-disk scatter and L-systems to Wave Function Collapse, strange attractors, marching cubes, paper marbling, and terrain erosion. Generators.
- Layers, effects, and shaders. Off-screen layers with fifty-plus GPU filters, two-layer combines, feedback, simulation fields, and a compose DSL. Measured distance fields, light with shadows in a flat sketch, the frequency domain, and summed-area averages. Your own
shade(uv, info)fragment function, inline or in a hot-reloading.metalfile, with errors reported at your own line numbers. ChainableVisuals when you would rather skip the Metal. Effects, Shaders. - Motion and parameters. Frame-rate-independent easing and springs, keyframe timelines, seeded variations, and record and replay.
@Paramproperties become typed inspector controls, persist across reloads, and can follow a curve or a formula. Sketch, Automation, Variations. - GPU compute and simulation. Compute kernels with a million particles a frame, and a neighbor-search primitive under artificial life and SPH fluids. Ping-pong texture simulations, steering crowds at GPU scale, populations that evolve, and chaotic systems. Compute, Simulation.
- Physics. A stepped
Worldwith Verlet particles and springs, Box2D bodies and joints in 2D, and Jolt-backed 3D bodies, joints, characters, vehicles, ragdolls, cloth, ropes, and water. Physics, Physics in 3D. - 3D, opt-in. Cameras and imported scenes (OBJ, glTF, USD), instanced meshes and GPU-culled worlds, grass and an ocean, physically based materials with the full map set, glass with dispersion, area lights, image-based lighting and a procedural sky. Shadows, ray-traced reflections, caustics, global illumination, atmosphere, temporal anti-aliasing, motion blur, and lens flare. A 2D sketch never pays for any of it. 3D.
- The world as input. Nineteen on-device Vision trackers over the camera or any video, depth from a video model, screen and window capture, and video playback. CSV, JSON, and SVG import, live and pushed data feeds, game controllers, and an iPhone over USB as a LiDAR, motion, body, face, and hand sensor. Vision, Data, The phone.
- Sound. FFT analysis with beat detection, listening for words and named sounds, and a synthesizer the sketch plays. Voice presets, physical models, sampled instruments, wavetables, a patchable graph, effects chains, a place in the 3D scene, and algorithmic composition, all carried into an exported video. Audio, Synthesis.
- Integration. MIDI, OSC, a network tempo session, serial, Bluetooth Low Energy, DMX and LED mapping, and show lasers. Syphon out and in, a virtual camera, haptics, a remote surface for a phone, and a room several machines join to draw one piece on one clock. Integration.
- Output. Headless stills and deterministic sequences, MP4 and GIF with slow motion, SVG and PDF with hatched fills, G-code, and print separations with press proofing. STL, OBJ, and 3MF for printing, USDZ and spatial video, a path-traced export, live recording with sound, and an accessibility layer for color vision and motion. Export.
- Running in the system. A finished piece as a signed Mac app, a screen saver, the desktop wallpaper, a menu-bar strip, or an installation that stays up for a week. A sketch as an app, Installation.
The tools
- The
ollincommand. One loose.swiftfile is a whole sketch, run from any directory.ollin newwrites a starter,ollin installputs the command on PATH, andollin checkcompiles a shader on this machine's GPU.ollin docsandollin examplesread the reference and the examples in the terminal. Single-file sketches, The reference offline. - OllinLive. Save the file and the running window hot-swaps the sketch, with the clock carried across.
@Paramproperties appear as typed inspector controls, a timeline records their automation, and Command-drag moves, resizes, or turns a shape by editing the source.⌘]and⌘[put it in front of or behind its neighbor. The parameter timeline, Dragging a shape. - OllinLiveCoding. The performance host: the sketch fills the window, the code rides over it as translucent text, and Command-Return recompiles the buffer mid-motion. Live coding.
- The project generator.
ollin newandollin generatewrite a ready-to-run project from ten templates or from any example. They also bring a GLSL fragment shader or a glTF or USD scene over as source, and scaffold an extension library other sketches import. Project generator. - The examples. 494 example sketches in their own package, browsable in one gallery window, including twelve recreations after eight artists. Examples.
The documentation
- The reference under Docs/, about two hundred pages, with a short concept page for each idea the reference assumes.
- The Guide, thirty-two chapters and four appendices: a practical introduction to creative coding taught through Ollin.
- For contributors, CAPABILITIES.md inventories every capability's invariants, ARCHITECTURE.md explains the internals, and ATTRIBUTION.md credits the influences and the techniques.
Requirements
- macOS 26 or later, a Metal-capable GPU, and a Swift 6 toolchain. Apple platforms only, by design: iOS and visionOS are future targets, and Linux, Windows, and the web are out of scope.
Versioning from here
- Tags begin at 0.1.0. A breaking change or a new feature bumps the minor, a fix bumps the patch, and each release names its breaking renames in this file. Deprecation shims and a settled surface arrive at 1.0. Until then, pin
.upToNextMinor(from: "0.1.0").