Switch Smart (Texturaizer)
Route a branch by matching text, not by remembering an index
- key
- input1
- input2
- input3
- input4
- input5
- input6
- input7
- input8
- input9
- input10
- selected
- index
Index-based switches are fine until the index has to mean something. Switch Smart (Texturaizer) is the one that understands meaning: you give it a key (any value), define up to ten inputs, and give each input a trigger string - then it matches the key against the triggers and selects the matching branch. And because it's lazy, only that branch ever gets computed.
Context: Texturaizer is a paid Blender addon by Luke Kratsios (LatentSpaceDirective); these nodes are its free ComfyUI companion pack. This is a genuinely useful utility - the pack's most interesting switch.
The trigger language
Each triggerN input is a string of match tokens, comma- or pipe-separated (the author's tooltip spells it out):
dog- exact match^AYS- starts-with prefixAYS*- also starts-with (the*wildcard form)re:^GITS\[coeff=- a full regex, after there:prefix
A blank trigger acts as ELSE - the first blank trigger among the ten is the fallback branch. Triggers are checked in order, so put your catch-all last.
The key input is wildcard-typed and converted to a string before matching, so you can throw a model name, a sampler name, a path, whatever at it.
Inputs and outputs
key(*) - required; the selector, converted to string.input1–input10(*) - the branches, all lazy.trigger1–trigger10(STRING) - the match rules, blank = ELSE.- Outputs:
selected(*) andindex(INT).
How it works
Mechanically it's Switch Lazy with a matcher bolted on: check_lazy_status() resolves which trigger set matches the key, then tells the executor to evaluate only that input. _token_matches() implements the four token forms (with a try/except around the regex so a bad pattern just doesn't match rather than crashing). The matching is first-hit-wins: the first trigger whose any token matches selects that branch; if nothing matches, the first blank (ELSE) trigger wins; if there's no ELSE either, input 1.
The pattern that makes it valuable
The classic Texturaizer use: route on a value that comes out of the data. Say a scene property carries the checkpoint or scheduler name - wire it into key, set trigger1 to euler, trigger2 to ^dpm, trigger3 to re:.*ancestral, and a blank on trigger4 as ELSE. The graph then routes itself based on what Blender exported, no manual re-plumbing per object. That "match the data, not the graph" move is the whole philosophy of this pack.
Install
Pack-level:
cd ComfyUI/custom_nodes
git clone https://github.com/LatentSpaceDirective/ComfyUI-Texturaizer
or ComfyUI Manager → search "Texturaizer" → Install → restart. Stock dependencies, no models.
Where people get tripped up
Regex without the re: prefix is treated as literal text - that's the #1 "why doesn't it match" mistake. Second, matching is prefix-position-sensitive: ^AYS matches "AYS SDXL" but not "SD AYS". And remember triggers and inputs are matched positionally (trigger1 ↔ input1), not by content. If the key input is an integer, it's stringified first, so 42 matches trigger 42 but not ^4... actually ^4 would match "42" as a prefix - which is a great example of why you should read the tokens as strings, because that's exactly what they are.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| key | * | Selector (any type). Converted to string and matched against triggers. | |
| input1opt | * | — | |
| input2opt | * | — | |
| input3opt | * | — | |
| input4opt | * | — | |
| input5opt | * | — | |
| input6opt | * | — | |
| input7opt | * | — | |
| input8opt | * | — | |
| input9opt | * | — | |
| input10opt | * | — | |
| trigger1opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. | |
| trigger2opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. | |
| trigger3opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. | |
| trigger4opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. | |
| trigger5opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. | |
| trigger6opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. | |
| trigger7opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. | |
| trigger8opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. | |
| trigger9opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. | |
| trigger10opt | STRING | Tokens: exact, ^prefix, prefix*, or re:<regex>. Comma or | separated. Blank = ELSE. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| selected | * | — |
| index | INT | — |