Commit Graph
24 Commits
Author SHA1 Message Date
simonandClaude Opus 5.5 3c8c5bed8c Make Tile swap slow at a low Swap rate, on a curved slider
A tile has to come back to the cut it started with for the clip to
loop, so every tile swapped at least twice a clip, and below that
rounding left every tile still: the bottom of the slider was either
frozen or busy. Swap rate is now the average per tile: below two swaps
a clip only a share of the tiles swap (twice each), fewer the lower it
goes, and above it each tile rounds up or down by its own draw.

ParamSpec::slider() takes an optional curve: the scale runs over the
slider's travel and sliderValue/sliderPosition map it onto the number
as position^curve. Swap rate uses a curve of 3, so the low end gets
most of the slider; the command line and project file are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 01:11:28 +02:00
simonandClaude Opus 5.5 ef8f728126 Show Tile swap's Swap rate as a slider, and let it go slower
A new ParamSpec::slider() marks an Int or Double param to be shown in
the interface as a Gtk::Scale with its minimum and maximum marked under
the ends, rather than a spin button; the command line and the project
file are unchanged. Swap rate uses it, and now runs from 0 to 5 in
steps of 0.01 (was 0 to 30 in steps of 0.1): with every tile swapping
on its own, even 0.1 swapped the canvas many times a second.

Version 0.8.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:44:27 +02:00
SiandClaude Opus 5.5 5402a50742 Add undo and redo to the interface
Ctrl+Z undoes, Ctrl+Y and Ctrl+Shift+Z redo, caught in the capture
phase so a focused entry or spin never undoes only its own text; both
are in the header-bar menu too. The history keeps whole snapshots of
the project (currentProject() plus the immutable source list itself,
so stepping back never decodes again), compared by their JSON.
requestRender() notes every edit, and a step is committed once the
controls have been still for half a second. New and Open start the
history over once the project's images are in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 23:15:03 +02:00
SiandClaude Opus 5.5 f9fe6e0fa5 Pick the text stage's font with a font chooser
A new Font param type (ParamSpec::makeFont) is a font family as the
machine names it. The interface shows it as a family-only
FontDialogButton; the command line and the project file treat it as a
plain string, as they did the Text param it replaces, so existing
projects and --font-family keep working. A family the machine lacks is
kept as written. Bumps the version to 0.8.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 22:58:44 +02:00
SiandClaude Opus 5.5 8acf85ddb8 Show progress while loading reads the image sizes
Before decoding, loadImages reads every header to size the batch against
the free memory. That pass was serial, silent and could not be cancelled,
so the loading window sat at "0 of N". LoadProgress gains onSized, the
headers are read in parallel on the same cursor-driven workers as the
decodes, and a cancel stops the pass. The window's bar runs twice,
"Checking sizes" then "Decoding", and the CLI prints a sizing line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 22:42:30 +02:00
SiandClaude Opus 5.5 cfaa773cf7 Give the video effects more room in the Add effect menu
With eight video effects their list filled its 110-pixel cap, and the menu's
headings take more than the 120 pixels the height test allowed for them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 20:49:10 +02:00
SiandClaude Opus 5.5 53dca6b4b8 Add Focus pull, a video effect that pulls Blur in and out of focus
Blur's box blur moves to effects/box_blur.hpp so both share it; Blur renders
exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 20:45:46 +02:00
SiandClaude Opus 5.5 4b407281e2 Add Strip roll, a video effect that rolls the picture in Scanlines' strips
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 20:43:47 +02:00
SiandClaude Opus 5.5 a7cb2505d7 Add Datamosh, a video effect whose Corrupt blocks break and heal over the clip
Corrupt's block damage moves to effects/corrupt_blocks.hpp so both share it;
Corrupt renders exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 20:41:52 +02:00
SiandClaude Opus 5.5 ce0207c41f Add Film gate, a video effect of film running through a projector
Film grain's field moves to effects/grain_field.hpp so both share it; Film
grain renders exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 20:39:57 +02:00
SiandClaude Opus 5.5 37c02a8a7b Add Sort sweep, a video effect that sweeps Pixel sort's window over the brightness
The run sorting moves to effects/sort_runs.hpp so both share it; Pixel sort
renders exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 20:37:30 +02:00
SiandClaude Opus 5.5 0377cd4abb Add Warp flow, a video effect that sets Warp's noise field drifting
Warp's noise field moves to effects/noise_field.hpp so both share it; Warp
renders exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 20:34:55 +02:00
SiandClaude Opus 5.5 370d3e550e Add Echo tunnel, a video effect that flies through Feedback's nested echoes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 20:32:49 +02:00
SiandClaude Opus 5.5 8537a3cf0a Open Save in the project folder and offer the last name with a number counted on
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 20:24:10 +02:00
SiandClaude Opus 5.5 ac8b62208c Render the video preview draft first: every third frame, then the rest
The preview plays a draft of every third frame, each held for three, as
soon as those are in, and fills in the frames between while it plays.
renderFrames takes an optional frame order (draftFirstOrder builds this
one); a frame is the same whatever order it is rendered in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 19:49:59 +02:00
SiandClaude Opus 5.5 6df4bcb079 Add a video export quality choice: Small file, Standard or High
A Quality dropdown under Video on Setup, --video-quality on the command
line, and "quality" in a project's video settings (written only when it is
not Standard). One table, videoQualities(), holds the ffmpeg settings per
codec; Standard is what every video was written with before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 19:41:00 +02:00
SiandClaude Opus 5.5 1b30a079e6 Add Tile swap, a video effect built from the source images
Tile swap lays tiles cut from the photographs over the canvas as Tiles
does, in a grid, in bricks or scattered, and swaps each one for another
cut at a moment of its own, so the mosaic keeps changing piece by piece.
The layout stays put for the whole clip; what a tile shows depends only
on the tile and how many times it has swapped, counted round the clip, so
it holds still between swaps and the clip loops without a jump. On the
command line it is -e tileswap with --tileswap-rate and the rest.

VideoEffect learns a second kind: an effect that answers needsSources()
writes compose() instead of animate(), and the base then takes no crop,
only the one seed, so it sees the photographs when it leads the chain and
the stage before it otherwise. Transforms render exactly as before. The
tile cutting and painting move out of tiles.cpp into tile_plan.hpp for
both effects to share; Tiles renders byte for byte as before. Version
0.8.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 19:22:26 +02:00
SiandClaude Opus 5.5 cdaadffc89 Split effects into image and video effects, with VHS tracking as the first video effect
Effect::video() says which kind an effect is. The Add effect menu lists the
two kinds in sections of their own, each scrolling on its own, and offers
video effects only in a video project; a video stage carries a film icon in
the chain and, in a still, is dimmed and skipped like a stage switched off.
enabledStages takes whether the render is a video and is the one place that
leaves video stages out of a still. --help groups the video effects under a
heading of their own, --list-effects marks them, and a video effect given
for a still is skipped with a warning.

VideoEffect is the base every video effect builds on, and keeps the rules a
moving stage has to follow: it takes one value from the shared rng, the same
on every frame, and hands the effect steady and per-frame generators and
loop-rounded time through a Moment, so a subclass writes only animate().
VHS tracking is the first, and the one to copy: the colour planes sway and
shake and a tracking bar rolls down the picture.

That motion moves out of channel split, which is an image effect again and
renders stills exactly as before; forVideo() goes with it. Version 0.7.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 19:03:39 +02:00
SiandClaude Opus 5.5 ea59db5acd Refuse loads and renders that would not fit in memory
Opening a project of ninety 17 MP photos got Effector killed by the
kernel's OOM killer: 4.6 GB of decoded RGB on a machine with 3.6 GB free,
and no core dump to show for it. Bulk allocations are now sized first and
refused with an OutOfMemoryError past three quarters of the free memory
(MemAvailable, or less under a cgroup memory.max). loadImages sizes the
batch from the file headers and refuses it before decoding anything, and
holds the decodes in flight to what is left; renderChain and renderFrames
refuse a canvas at 24 bytes a pixel, plus any picture a Path param loads.
The interface keeps a refused batch's paths, so saving the project never
drops them. Version 0.6.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 18:31:53 +02:00
SiandClaude Opus 5.5 385617781e Make video projects, with a moving channel split as the first video effect
A project can now be a clip: Setup has a Video switch with a length, a
frame rate and presets that set the canvas too (Instagram story, reel and
feed video, TikTok / YouTube Short, Square loop, Full HD clip). The preview
renders the whole clip, shrunk to a memory budget, and loops it with
play/pause and a scale; Save As... renders it again at full size and pipes
the frames into ffmpeg as .mp4, .mov, .mkv, .webm or .gif, with a progress
window that can cancel. --duration, --fps and --video-preset do the same
from the command line.

Effects learn about time through FrameTime and Effect::renderFrame, which
falls back to render, so nothing that holds still changes. Channel split
now sways, shakes and rolls a tracking bar down the picture in a video; its
motion params are marked forVideo() and hidden in a still project, and a
still renders byte for byte as before. renderFrames starts every frame
from the same seed and renders the still stages ahead of the first moving
one only once. The version moves to 0.6.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:22:01 +02:00
SiandClaude Opus 5.5 c069de3566 Give Effector its own icon
An E split into its colour channels, with two slices slipped sideways,
replaces the generic applications-graphics icon in the desktop entry and
About Effector, with a one-colour symbolic version for panels. Both are
installed into the hicolor theme; a build run straight from the build tree
falls back to the copy in the sources. The version moves to 0.5.3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:38:49 +02:00
SiandClaude Opus 5.5 708b6bdb1b License Effector under the GPL, version 3 or later
LICENSE holds the text, the README and About Effector state it, and the
Arch package declares it. The version moves to 0.5.2 for the release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:26:28 +02:00
SiandClaude Opus 5.5 520c7c45fb Package Effector for Arch and give it a desktop entry
packaging/arch/PKGBUILD builds the tagged release from this repository
and installs it with pacman; the version test keeps its pkgver in step
with CMakeLists.txt. A desktop entry puts the interface in the app menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:22:18 +02:00
SiandClaude Opus 5.5 b9f905e04c Give Effector a version and a changelog, shown from the menu
The version is the project() line of CMakeLists.txt and nowhere else:
CMake writes it, with the text of CHANGELOG.md, into a generated
core/version.hpp, so the number and the release notes the binary shows
are the ones it was built from. effector --version (-V) prints it, and
the header-bar menu gains a section with Changelog, a window laying the
Markdown out as headings and bullets, and About Effector.

The core tests hold the newest changelog entry to the current version,
so a bump cannot go in without its notes. Releases are tagged vX.Y.Z;
this is 0.5.0, and the changelog reconstructs 0.1.0-0.4.0 from the
history.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:14:43 +02:00