π BV LUT Loop Job Resolver
The node that tells you what this loop iteration is for
- loop_state
- current_image
- lut
- mask
- strength
- job_info
Inside a LUT loop, every iteration is different: job 1 might be a global "Dustfire" pass, job 2 a masked "Cool Graphite" pass, job 3 an inverted grade on the background. The loop state knows all of that, but nothing downstream can read a BV_LUT_LOOP_STATE - it's a typed internal object. BV LUT Loop Job Resolver is the translator: it takes the loop state and unpacks the current job into ordinary, wire-able values your Apply node can actually consume.
Think of it as the loop's window into the present. It sits inside the loop body between BV LUT Loop Start and BV Apply LUT, and it's the node that makes a loop feel like a list comprehension instead of a pile of repeated nodes.
How it works
Given a loop_state, it looks up the job at the current index and materializes everything that job needs:
- If the plan is a regional LUT plan, it composes the job's mask from the regional document's region masks (union, intersection, or subtract as configured), and if the job carries a detector binding it runs the Impact detector on the current image and intersects that with the region mask.
- If the plan is a manual prototype plan, it just normalizes the job's stored mask.
mask_invertis applied last, so an inverted job comes out already flipped.
So by the time the resolver emits the values, the tricky parts - regional composition, detector intersection, inversion - are already done. Your Apply node doesn't need to know where its mask came from.
The inputs and outputs that matter
One input: loop_state from Loop Start. Five outputs, and the author's tooltips are worth quoting because they're the actual instructions:
current_image- "Current accumulated image for this job." Feed it to Apply LUT's image input.lut- "Resolved LUT for this job."mask- "Resolved regional and detector mask for this job."strength- "Connect this output to BV Apply LUT strength; an unconnected Apply node uses its own widget value." This is the line that saves you an hour of "why is every iteration the same strength." Wire it.job_info- a string like2/3: Cool Graphite(index/total plus LUT title). Perfect for a text/display node so you can see which job is running, or for logging.
How to install
Part of BV Node Pack:
cd ComfyUI/custom_nodes
git clone https://github.com/BlackVortexAI/bv_nodepack.git
Restart ComfyUI and hard-refresh, or install via ComfyUI Manager β "BV Node Pack". No model downloads.
Common issues
- Every iteration uses the same strength - you left Apply LUT's
strengthwidget connected (or at its widget value) instead of wiring the resolver's strength output. The tooltip exists because this is the #1 gotcha. - Mask is missing or all-ones - a global-scope job or a plan whose mask never materialized; check the plan's job definitions on BV Regional LUT Plan or the Job nodes.
- "loop_state must be a version 1 BV LUT prototype loop state" - you fed it something that isn't a valid loop state, usually a stale or disconnected wire from a re-run workflow.
If you're building a loop by hand, this is the node that turns "a loop" into "a loop that does something different each time." Wire its strength, and it just works.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| loop_state | BV_LUT_LOOP_STATE | β |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| current_image | IMAGE | Current accumulated image for this job. |
| lut | BV_LUT_PROTOTYPE | Resolved LUT for this job. |
| mask | MASK | Resolved regional and detector mask for this job. |
| strength | FLOAT | Connect this output to BV Apply LUT strength; an unconnected Apply node uses its own widget value. |
| job_info | STRING | Current job index and LUT title. |