### New: EvaluateStringMultiline [m9] (`utilities/primitive`)
A multiline string primitive, like the stock String (Multiline), that also:
- resolves `{ a | b }` choices, using the same rules as StepReplace
- takes a `seed_optional`, the same as StepReplace: `0` re-rolls every run, any other seed repeats its result
- has a `random_line` output that picks one line of the resolved text. Blank lines are never picked, and a single line is always returned
### Changed: StepReplace [m9] picks each choice once
Every `{choice}` is now resolved before any search/replace runs: the incoming text first, then each `replace` field. A placeholder used several times now gets the same pick everywhere. For example, `[EYE_COLOR]` replaced with `{ blue | green }` gives all blue or all green, never a mix. Later steps can still match text an earlier step inserted.
49 lines
1.8 KiB
Python
49 lines
1.8 KiB
Python
from .m_evalstring import evaluate_string
|
|
|
|
|
|
class EvaluateStringMultiline_m9:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
# Modeled on the stock PrimitiveStringMultiline: one multiline `value` widget.
|
|
# seed_optional works exactly as it does on StepReplace [m9].
|
|
return {"required": {"value": ("STRING", {"default": "", "multiline": True}),
|
|
},
|
|
"optional": {"seed_optional": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
}}
|
|
|
|
RETURN_TYPES = ("STRING", "STRING", )
|
|
RETURN_NAMES = ("text", "random_line", )
|
|
|
|
FUNCTION = "evaluate"
|
|
|
|
# utilities/primitive is where the stock PrimitiveStringMultiline lives (it was
|
|
# utils/primitive on older builds), so this sits directly beside the node it extends.
|
|
CATEGORY = "utilities/primitive"
|
|
|
|
@classmethod
|
|
def IS_CHANGED(s, seed_optional=0, **kwargs):
|
|
# Same convention as StepReplace [m9]: a seed of 0 means "re-roll every run".
|
|
# NaN never compares equal to itself, so ComfyUI re-executes the node each queue
|
|
# instead of serving one cached roll forever. Any other seed is returned as-is.
|
|
if not seed_optional:
|
|
return float("nan")
|
|
return seed_optional
|
|
|
|
def evaluate(self, value, seed_optional=0):
|
|
# 0 is what an unconnected widget sends, and it means "no seed given" --
|
|
# random.Random(None) then seeds from entropy.
|
|
seed = None if not seed_optional else seed_optional
|
|
return evaluate_string(value, inSeed=seed)
|
|
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"EvaluateStringMultiline_m9": EvaluateStringMultiline_m9
|
|
}
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"EvaluateStringMultiline_m9": "EvaluateStringMultiline [m9]"
|
|
}
|