Files
MachinePainting 3a574494eb Add short DESCRIPTION text to all 41 nodes
None of the nodes showed description text in ComfyUI because ComfyUI
reads obj_class.DESCRIPTION when it builds node_info - it does not read
the class docstring, which is what these nodes had.

Every registered node now carries a one-line DESCRIPTION, kept to
29-67 characters so it fits the limited space in ComfyUI Manager and
the node search results. Image Transform Pro's four-sentence
description is shortened to match.

Descriptions are derived from each node's existing docstring, or from
the README for the five classes that had no docstring
(ImageBlendPro, ColorMatchBlend and the three Boolean switch nodes).

README also updated for the recent changes: the New Nodes table now
lists the real "Rotate & Scale" category, the XY placement direction is
documented on both nodes (positive X right, positive Y up), and the
v2.2.0 changelog records the placement convention, the node outputs and
the MP_ImageTransform internal name.
2026-09-03 03:32:00 -07:00

110 lines
4.0 KiB
Python

import random
import time
class DynamicValueRange:
"""
Automatically cycles through a range of values on each run.
Use to create diversity in settings across multiple generations.
"""
DESCRIPTION = "Step through a range of values, one per run."
# Class variable to track current values per node instance
_state = {}
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"min_value": ("FLOAT", {"default": 0.0, "min": -10000.0, "max": 10000.0, "step": 0.1}),
"max_value": ("FLOAT", {"default": 1.0, "min": -10000.0, "max": 10000.0, "step": 0.1}),
"step": ("FLOAT", {"default": 0.1, "min": 0.001, "max": 1000.0, "step": 0.01}),
"mode": (["increment", "decrement", "random"], {"default": "increment"}),
"on_cycle_complete": (["reverse", "jump"], {"default": "reverse"}),
"output_int": ("BOOLEAN", {"default": False}),
},
"hidden": {
"unique_id": "UNIQUE_ID",
},
}
RETURN_TYPES = ("FLOAT", "INT", "STRING")
RETURN_NAMES = ("value", "value_int", "value_str")
FUNCTION = "get_value"
CATEGORY = "MachinePaintingNodes/Util"
@classmethod
def IS_CHANGED(cls, **kwargs):
# Always return a different value to force re-execution
return float("nan")
def get_value(self, min_value, max_value, step, mode, on_cycle_complete, output_int, unique_id=None):
# Use unique_id to track state per node instance
node_id = str(unique_id) if unique_id else "default"
# Initialize state if not exists
if node_id not in DynamicValueRange._state:
DynamicValueRange._state[node_id] = {
"current": min_value,
"direction": 1, # 1 = forward, -1 = backward
}
state = DynamicValueRange._state[node_id]
# Handle random mode
if mode == "random":
# Calculate number of steps
num_steps = int((max_value - min_value) / step) + 1
random_step = random.randint(0, num_steps - 1)
value = min_value + (random_step * step)
value = min(max_value, max(min_value, value))
else:
# Get current value
value = state["current"]
# Ensure value is within range (in case settings changed)
value = min(max_value, max(min_value, value))
# Calculate next value for next run
if mode == "increment":
direction = state.get("direction", 1)
else: # decrement
direction = state.get("direction", -1)
if state.get("direction") is None or state.get("direction") == 1:
state["direction"] = -1
direction = -1
next_value = value + (step * direction)
# Check if we've hit the bounds
if next_value > max_value:
if on_cycle_complete == "reverse":
state["direction"] = -1
next_value = value - step
else: # jump
next_value = min_value
elif next_value < min_value:
if on_cycle_complete == "reverse":
state["direction"] = 1
next_value = value + step
else: # jump
next_value = max_value
# Clamp next value
next_value = min(max_value, max(min_value, next_value))
# Store for next run
state["current"] = next_value
# Round to avoid floating point errors
value = round(value, 6)
# Convert outputs
value_int = int(round(value))
value_str = str(value_int if output_int else value)
if output_int:
value = float(value_int)
return (value, value_int, value_str)