πΎ Dynamic Value Range
Batch diversity without a random node in sight
- value
- value_int
- value_str
When you want a batch of variations, a random node gives you chaos: you can't reproduce which value hit when, and you can't guarantee you covered the range evenly. Dynamic Value Range is the opposite philosophy - it advances through a value range one step per run, in a predictable order, and hands you the current value as FLOAT, INT, and STRING simultaneously. Plug it into your CFG, denoise, or seed offset and each generation in a queue gets a different setting, systematically.
How it works
You set min_value, max_value, and step. Each time the workflow runs, the node returns the current value and advances for next time. Three modes:
- increment - steps up from the min.
- decrement - steps down from the max.
- random - jumps to a random step in the range (the one mode that's not deterministic).
When it hits the end of the range, on_cycle_complete decides the fate: reverse (bounce back the way it came) or jump (teleport to the other end and start over). That's your ping-pong vs. sawtooth choice, and it matters for how "smooth" the progression feels across a long queue.
The state is tracked per node instance in memory (keyed by the node's unique ID), so each Dynamic Value Range node in your graph has its own independent counter. It always re-executes (IS_CHANGED is NaN) - that's how it knows to advance - so don't expect it to sit still in a cached graph.
Inputs and outputs
The required inputs are the obvious four: min_value, max_value, step, mode, plus on_cycle_complete and output_int (toggle: emit integers instead of floats, and the STRING output follows suit). Outputs are value (FLOAT), value_int (INT), and value_str (STRING) - same number, three formats, so it plugs into anything. That triple output is a small touch that saves a conversion node every time.
Where it shines
Batch diversity without randomness. Queue five renders with the node driving CFG from 4 to 8 in 1.0 steps and you get a clean sweep - no repeats, no gaps, and you know exactly what value produced which frame. It's also a quiet debugging tool: sweep a single parameter to see how sensitive a workflow is to it, then set the mode to random when you actually want the chaos back.
Install
MachinePainting Nodes pack:
cd ComfyUI/custom_nodes
git clone https://github.com/machinepainting/ComfyUI-MachinePaintingNodes.git
pip install -r requirements.txt
or ComfyUI Manager β "MachinePaintingNodes" β install β restart.
Gotchas
State is in memory and per-process: restart ComfyUI and every counter resets to min_value. So "where did my progression go?" usually means "the app restarted." Also, step ranges are computed by count ((maxβmin)/step + 1), so a step that doesn't divide the range evenly will clamp at the bounds rather than walk off the end - pick steps that divide your range for clean behavior. And in random mode, reproducibility goes out the window by design; if you need the queue reproducible, use increment/decrement.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| min_value | FLOAT | 0.0-10000β10000 | β |
| max_value | FLOAT | 1.0-10000β10000 | β |
| step | FLOAT | 0.100.001β1000 | β |
| mode | COMBO | increment | 3 options: increment, decrement, random |
| on_cycle_complete | COMBO | reverse | 2 options: reverse, jump |
| output_int | BOOLEAN | false | β |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| value | FLOAT | β |
| value_int | INT | β |
| value_str | STRING | β |