ComfyUI Node

TF Level Canvas

How a 16×16 token grid becomes something you can paint on

By KorayUlusan·Created 3 days ago·Updated about 21 hours ago· 1
TF Level Canvas
  • levels
  • regions
  • highlight
  • pipeline
  • canvas
  • level
level2
view
draw_gridtrue
label_coordstrue
size512

Here's the design problem Trajectory Forcing editing hits head-on: its edits act on regions of a 16×16 token grid, and no ComfyUI mask tool knows that grid exists. You can't brush 256 latent positions with a normal paint node and expect anything sane to come back. TF Level Canvas is the bridge - it renders one level of a trajectory as a large, paintable image with the token grid drawn on it, sized so that every token is a whole number of pixels (512 default on a 16×16 grid is 32 pixels per token). You paint on that, core Painter hands you a mask, and TF Tokens From Mask converts it back down to tokens that line up exactly.

view picks what you're painting on: PCA shows the token structure the edit acts on, so you can aim at a feature region rather than guess at pixels; decoded RGB shows what that structure looks like as a real image, which is more intuitive when you want to target, say, "the dog's ear." draw_grid overlays the 16×16 lattice, and label_coords numbers rows and columns - a small thing that saves a lot of counting when you want to type a coordinate into TF Tokens From Coords instead of eyeballing it. level defaults to 2, the pack's usual editing rung (subparts).

The two optional inputs are where it becomes a real editing surface rather than a picture. Wire regions in from a TF Region Map and it draws the region boundaries, so your brush stroke can follow the cluster you actually mean to select. Wire highlight with an existing TF_TOKENS selection and it tints those tokens, which is how you check what a mask or coordinate list resolved to before committing an edit. Outputs are canvas (the IMAGE you feed to Painter) and level - an INT echoing which level you rendered, wired into the edit node to keep everything in agreement.

Two gotchas, both grounded in the README. First, the Painter node it feeds needs ComfyUI's Node 2.0 rendering; if Painter says "Node 2.0 only," go to Settings, search "Node 2.0", enable it, and reload the page. TF Level Canvas detects the setting and says so in its body rather than failing silently. Second, the canvas is designed to be painted by core Painter - this node deliberately doesn't ship a custom LiteGraph canvas - so it publishes its image as a UI preview, which is what Painter needs to show something to paint over. If Painter shows a blank square, the preview isn't reaching it.

Why go to this trouble instead of just typing coordinates? Because regions are rarely rectangles, and a brush stroke can trace the actual boundary between the background and the thing you want to edit. The mask path and the coordinate path converge on the same token selection - TF Tokens From Mask and TF Tokens From Coords both produce the same TF_TOKENS type - so pick whichever your hand is better at, and let TF Tokens Combine repair the result when a stroke was sloppy.

Install

Standard pack install: Manager → search Trajectory Forcing, or git clone https://github.com/korayulusan/ComfyUI-TrajectoryForcing into custom_nodes/. JAX-inside-ComfyUI needs its own Python 3.11 environment on CUDA 12; requirements.txt is empty on purpose and install.py either adds the JAX stack or declines with a printed reason. The README's env/setup.sh is the fallback when it declines. Health check:

cd ComfyUI/custom_nodes/ComfyUI-TrajectoryForcing
python -m tf_nodes.doctor

Remember that nothing painted yet is a legitimately useful state - the first run of a painting workflow exists to produce the canvas, and TF Tokens From Mask will stop the graph gracefully rather than error until you actually paint something.

CategoryTrajectoryForcing/select

Inputs (9)

NameTypeDefaultDescription
levelsTF_LEVELS
levelINT20–3Hierarchy level, 0 = coarsest (object/background) to 3 = finest.
viewCOMBOPCA shows the token structure the edit acts on; decoded RGB shows what that structure looks like as an image.
draw_gridBOOLEANtrue
label_coordsBOOLEANtrueNumber the rows and columns, so a coordinate for TF Tokens From Coords can be read off instead of counted.
sizeINT512128–2048Rounded so each token is a whole number of pixels.
regionsoptTF_REGIONSDraw region boundaries from a TF Region Map, so a brush stroke can follow the cluster it is meant to select.
highlightoptTF_TOKENSTint an existing selection, to check what a mask resolved to.
pipelineoptTF_PIPELINEUsually unnecessary: the trajectory carries the pipeline that made it. Wire it for a trajectory from TF Load Levels.

Outputs (2)

NameTypeDescription
canvasIMAGE
levelINT