RioShiina commited on
Commit
0765997
·
verified ·
1 Parent(s): ee9859c

Add Reference Latent Chains

Browse files
chain_injectors/reference_latent_injector.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def inject(assembler, chain_definition, chain_items):
2
+ if not chain_items:
3
+ return
4
+
5
+ ksampler_name = chain_definition.get('ksampler_node', 'ksampler')
6
+ flux_guidance_name = chain_definition.get('flux_guidance_node')
7
+ vae_node_name = chain_definition.get('vae_node', 'vae_loader')
8
+
9
+ if ksampler_name not in assembler.node_map:
10
+ print(f"Warning: [ReferenceLatent] KSampler node '{ksampler_name}' not found. Skipping.")
11
+ return
12
+ if vae_node_name not in assembler.node_map:
13
+ print(f"Warning: [ReferenceLatent] VAE loader node '{vae_node_name}' not found. Skipping.")
14
+ return
15
+
16
+ ksampler_id = assembler.node_map[ksampler_name]
17
+ vae_node_id = assembler.node_map[vae_node_name]
18
+
19
+ pos_target_node_id = None
20
+ pos_target_input_name = None
21
+ if flux_guidance_name and flux_guidance_name in assembler.node_map:
22
+ flux_guidance_id = assembler.node_map[flux_guidance_name]
23
+ if 'conditioning' in assembler.workflow[flux_guidance_id]['inputs']:
24
+ pos_target_node_id = flux_guidance_id
25
+ pos_target_input_name = 'conditioning'
26
+ print(f"ReferenceLatent injector targeting FluxGuidance node '{flux_guidance_name}'.")
27
+
28
+ if not pos_target_node_id:
29
+ if 'positive' in assembler.workflow[ksampler_id]['inputs']:
30
+ pos_target_node_id = ksampler_id
31
+ pos_target_input_name = 'positive'
32
+ print(f"ReferenceLatent injector targeting KSampler node '{ksampler_name}'.")
33
+ else:
34
+ print(f"Warning: [ReferenceLatent] Could not find a valid positive injection point. Skipping.")
35
+ return
36
+
37
+ current_pos_conditioning = assembler.workflow[pos_target_node_id]['inputs'][pos_target_input_name]
38
+
39
+ for i, img_filename in enumerate(chain_items):
40
+ if not img_filename or not isinstance(img_filename, str):
41
+ continue
42
+
43
+ load_id = assembler._get_unique_id()
44
+ load_node = assembler._get_node_template("LoadImage")
45
+ load_node['inputs']['image'] = img_filename
46
+ assembler.workflow[load_id] = load_node
47
+
48
+ vae_encode_id = assembler._get_unique_id()
49
+ vae_encode_node = assembler._get_node_template("VAEEncode")
50
+ vae_encode_node['inputs']['pixels'] = [load_id, 0]
51
+ vae_encode_node['inputs']['vae'] = [vae_node_id, 0]
52
+ assembler.workflow[vae_encode_id] = vae_encode_node
53
+
54
+ latent_conn = [vae_encode_id, 0]
55
+
56
+ ref_latent_id = assembler._get_unique_id()
57
+ ref_latent_node = assembler._get_node_template("ReferenceLatent")
58
+ ref_latent_node['inputs']['conditioning'] = current_pos_conditioning
59
+ ref_latent_node['inputs']['latent'] = latent_conn
60
+ assembler.workflow[ref_latent_id] = ref_latent_node
61
+
62
+ current_pos_conditioning = [ref_latent_id, 0]
63
+
64
+ assembler.workflow[pos_target_node_id]['inputs'][pos_target_input_name] = current_pos_conditioning
65
+
66
+ print(f"ReferenceLatent injector applied. Re-routed inputs through {len(chain_items)} reference image(s).")
core/pipelines/sd_image_pipeline.py CHANGED
@@ -312,6 +312,16 @@ class SdImagePipeline(BasePipeline):
312
  "strength": float(strengths[i])
313
  })
314
 
 
 
 
 
 
 
 
 
 
 
315
  loras_string = f"LoRAs: [{', '.join(active_loras_for_meta)}]" if active_loras_for_meta else ""
316
 
317
  progress(0.8, desc="Assembling workflow...")
@@ -346,6 +356,7 @@ class SdImagePipeline(BasePipeline):
346
  "clip_name": components['clip'],
347
  "vae_name": ui_inputs.get('vae_name', components['vae']),
348
  "conditioning_chain": active_conditioning,
 
349
  }
350
 
351
  if task_type == 'txt2img':
 
312
  "strength": float(strengths[i])
313
  })
314
 
315
+ reference_latent_data = ui_inputs.get('reference_latent_data', [])
316
+ active_reference_latents = []
317
+ if reference_latent_data:
318
+ for img_pil in reference_latent_data:
319
+ if img_pil is not None:
320
+ temp_file_path = os.path.join(INPUT_DIR, f"temp_ref_{random.randint(1000, 9999)}.png")
321
+ img_pil.save(temp_file_path, "PNG")
322
+ active_reference_latents.append(os.path.basename(temp_file_path))
323
+ temp_files_to_clean.append(temp_file_path)
324
+
325
  loras_string = f"LoRAs: [{', '.join(active_loras_for_meta)}]" if active_loras_for_meta else ""
326
 
327
  progress(0.8, desc="Assembling workflow...")
 
356
  "clip_name": components['clip'],
357
  "vae_name": ui_inputs.get('vae_name', components['vae']),
358
  "conditioning_chain": active_conditioning,
359
+ "reference_latent_chain": active_reference_latents,
360
  }
361
 
362
  if task_type == 'txt2img':
core/pipelines/workflow_recipes/_partials/conditioning/flux2.yaml CHANGED
@@ -43,6 +43,11 @@ dynamic_conditioning_chains:
43
  ksampler_node: "ksampler"
44
  clip_source: "clip_loader:0"
45
 
 
 
 
 
 
46
  ui_map:
47
  unet_name: "unet_loader:unet_name"
48
  clip_name: "clip_loader:clip_name"
 
43
  ksampler_node: "ksampler"
44
  clip_source: "clip_loader:0"
45
 
46
+ dynamic_reference_latent_chains:
47
+ reference_latent_chain:
48
+ ksampler_node: "ksampler"
49
+ vae_node: "vae_loader"
50
+
51
  ui_map:
52
  unet_name: "unet_loader:unet_name"
53
  clip_name: "clip_loader:clip_name"
core/settings.py CHANGED
@@ -111,11 +111,13 @@ try:
111
  MAX_EMBEDDINGS = _constants.get('MAX_EMBEDDINGS', 5)
112
  MAX_CONDITIONINGS = _constants.get('MAX_CONDITIONINGS', 10)
113
  MAX_CONTROLNETS = _constants.get('MAX_CONTROLNETS', 5)
 
114
  LORA_SOURCE_CHOICES = _constants.get('LORA_SOURCE_CHOICES', ["Civitai", "File"])
115
  RESOLUTION_MAP = _constants.get('RESOLUTION_MAP', {})
116
  except Exception as e:
117
  print(f"FATAL: Could not load constants from YAML. Error: {e}")
118
  MAX_LORAS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_CONTROLNETS = 5, 5, 10, 5
 
119
  LORA_SOURCE_CHOICES = ["Civitai", "File"]
120
  RESOLUTION_MAP = {}
121
 
 
111
  MAX_EMBEDDINGS = _constants.get('MAX_EMBEDDINGS', 5)
112
  MAX_CONDITIONINGS = _constants.get('MAX_CONDITIONINGS', 10)
113
  MAX_CONTROLNETS = _constants.get('MAX_CONTROLNETS', 5)
114
+ MAX_REFERENCE_LATENTS = _constants.get('MAX_REFERENCE_LATENTS', 10)
115
  LORA_SOURCE_CHOICES = _constants.get('LORA_SOURCE_CHOICES', ["Civitai", "File"])
116
  RESOLUTION_MAP = _constants.get('RESOLUTION_MAP', {})
117
  except Exception as e:
118
  print(f"FATAL: Could not load constants from YAML. Error: {e}")
119
  MAX_LORAS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_CONTROLNETS = 5, 5, 10, 5
120
+ MAX_REFERENCE_LATENTS = 10
121
  LORA_SOURCE_CHOICES = ["Civitai", "File"]
122
  RESOLUTION_MAP = {}
123
 
ui/events.py CHANGED
@@ -10,7 +10,7 @@ from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
10
 
11
  from core.pipelines.controlnet_preprocessor import CPU_ONLY_PREPROCESSORS
12
  from utils.app_utils import PREPROCESSOR_MODEL_MAP, PREPROCESSOR_PARAMETER_MAP, save_uploaded_file_with_hash
13
- from ui.shared.ui_components import RESOLUTION_MAP, MAX_CONTROLNETS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_LORAS
14
 
15
 
16
  def on_model_change(model_display_name):
@@ -253,6 +253,36 @@ def attach_event_handlers(ui_components, demo):
253
  del_outputs = [count_state, add_button, del_button] + rows + prompts
254
  add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
255
  del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
257
 
258
  def on_vae_upload(file_obj):
@@ -318,7 +348,7 @@ def attach_event_handlers(ui_components, demo):
318
 
319
  input_keys = list(run_inputs_map.keys())
320
  input_list_flat = [v for v in run_inputs_map.values() if v is not None]
321
- input_list_flat += lora_data_components + embedding_data_components + conditioning_data_components
322
 
323
  def create_ui_inputs_dict(*args):
324
  valid_keys = [k for k in input_keys if run_inputs_map[k] is not None]
@@ -331,6 +361,8 @@ def attach_event_handlers(ui_components, demo):
331
  arg_idx += len(embedding_data_components)
332
  ui_dict['conditioning_data'] = list(args[arg_idx : arg_idx + len(conditioning_data_components)])
333
  arg_idx += len(conditioning_data_components)
 
 
334
 
335
  return ui_dict
336
 
@@ -383,7 +415,9 @@ def attach_event_handlers(ui_components, demo):
383
  outputs=[emb_ids[i], emb_sources[i], emb_files[i]],
384
  show_progress=False
385
  )
386
- if f'add_conditioning_button_{prefix}' in ui_components: create_conditioning_event_handlers(prefix) if f'vae_source_{prefix}' in ui_components:
 
 
387
  upload_button = ui_components.get(f'vae_upload_button_{prefix}')
388
  if upload_button:
389
  upload_button.upload(
 
10
 
11
  from core.pipelines.controlnet_preprocessor import CPU_ONLY_PREPROCESSORS
12
  from utils.app_utils import PREPROCESSOR_MODEL_MAP, PREPROCESSOR_PARAMETER_MAP, save_uploaded_file_with_hash
13
+ from ui.shared.ui_components import RESOLUTION_MAP, MAX_CONTROLNETS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_LORAS, MAX_REFERENCE_LATENTS
14
 
15
 
16
  def on_model_change(model_display_name):
 
253
  del_outputs = [count_state, add_button, del_button] + rows + prompts
254
  add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
255
  del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
256
+
257
+ def create_reference_latent_event_handlers(prefix):
258
+ rows = ui_components[f'reference_latent_rows_{prefix}']
259
+ images = ui_components[f'reference_latent_images_{prefix}']
260
+ count_state = ui_components[f'reference_latent_count_state_{prefix}']
261
+ add_button = ui_components[f'add_reference_latent_button_{prefix}']
262
+ del_button = ui_components[f'delete_reference_latent_button_{prefix}']
263
+
264
+ def add_row(c):
265
+ c += 1
266
+ return {
267
+ count_state: c,
268
+ rows[c - 1]: gr.update(visible=True),
269
+ add_button: gr.update(visible=c < MAX_REFERENCE_LATENTS),
270
+ del_button: gr.update(visible=True),
271
+ }
272
+
273
+ def del_row(c):
274
+ c -= 1
275
+ return {
276
+ count_state: c,
277
+ rows[c]: gr.update(visible=False),
278
+ images[c]: None,
279
+ add_button: gr.update(visible=True),
280
+ del_button: gr.update(visible=c > 0),
281
+ }
282
+
283
+ add_outputs = [count_state, add_button, del_button] + rows
284
+ del_outputs = [count_state, add_button, del_button] + rows + images
285
+ add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False)
286
  del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)
287
 
288
  def on_vae_upload(file_obj):
 
348
 
349
  input_keys = list(run_inputs_map.keys())
350
  input_list_flat = [v for v in run_inputs_map.values() if v is not None]
351
+ input_list_flat += lora_data_components + embedding_data_components + conditioning_data_components + reference_latent_components
352
 
353
  def create_ui_inputs_dict(*args):
354
  valid_keys = [k for k in input_keys if run_inputs_map[k] is not None]
 
361
  arg_idx += len(embedding_data_components)
362
  ui_dict['conditioning_data'] = list(args[arg_idx : arg_idx + len(conditioning_data_components)])
363
  arg_idx += len(conditioning_data_components)
364
+ ui_dict['reference_latent_data'] = list(args[arg_idx : arg_idx + len(reference_latent_components)])
365
+
366
 
367
  return ui_dict
368
 
 
415
  outputs=[emb_ids[i], emb_sources[i], emb_files[i]],
416
  show_progress=False
417
  )
418
+ if f'add_conditioning_button_{prefix}' in ui_components: create_conditioning_event_handlers(prefix)
419
+ if f'add_reference_latent_button_{prefix}' in ui_components: create_reference_latent_event_handlers(prefix)
420
+ if f'vae_source_{prefix}' in ui_components:
421
  upload_button = ui_components.get(f'vae_upload_button_{prefix}')
422
  if upload_button:
423
  upload_button.upload(
ui/shared/hires_fix_ui.py CHANGED
@@ -4,7 +4,8 @@ from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
  create_embedding_ui,
7
- create_conditioning_ui, create_vae_override_ui, create_api_key_ui
 
8
  )
9
 
10
  def create_ui():
@@ -68,7 +69,7 @@ def create_ui():
68
  # components.update(create_diffsynth_controlnet_ui(prefix))
69
  # components.update(create_controlnet_ui(prefix))
70
  # components.update(create_embedding_ui(prefix))
71
- components.update((prefix))
72
  components.update(create_conditioning_ui(prefix))
73
  # components.update(create_vae_override_ui(prefix))
74
 
 
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
  create_embedding_ui,
7
+ create_conditioning_ui, create_vae_override_ui, create_api_key_ui,
8
+ create_reference_latent_ui
9
  )
10
 
11
  def create_ui():
 
69
  # components.update(create_diffsynth_controlnet_ui(prefix))
70
  # components.update(create_controlnet_ui(prefix))
71
  # components.update(create_embedding_ui(prefix))
72
+ components.update(create_reference_latent_ui(prefix))
73
  components.update(create_conditioning_ui(prefix))
74
  # components.update(create_vae_override_ui(prefix))
75
 
ui/shared/img2img_ui.py CHANGED
@@ -4,7 +4,8 @@ from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
  create_embedding_ui,
7
- create_conditioning_ui, create_vae_override_ui, create_api_key_ui
 
8
  )
9
 
10
  def create_ui():
@@ -51,7 +52,7 @@ def create_ui():
51
  # components.update(create_diffsynth_controlnet_ui(prefix))
52
  # components.update(create_controlnet_ui(prefix))
53
  # components.update(create_embedding_ui(prefix))
54
- components.update((prefix))
55
  components.update(create_conditioning_ui(prefix))
56
  # components.update(create_vae_override_ui(prefix))
57
 
 
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
  create_embedding_ui,
7
+ create_conditioning_ui, create_vae_override_ui, create_api_key_ui,
8
+ create_reference_latent_ui
9
  )
10
 
11
  def create_ui():
 
52
  # components.update(create_diffsynth_controlnet_ui(prefix))
53
  # components.update(create_controlnet_ui(prefix))
54
  # components.update(create_embedding_ui(prefix))
55
+ components.update(create_reference_latent_ui(prefix))
56
  components.update(create_conditioning_ui(prefix))
57
  # components.update(create_vae_override_ui(prefix))
58
 
ui/shared/inpaint_ui.py CHANGED
@@ -3,7 +3,8 @@ from core.settings import MODEL_MAP_CHECKPOINT
3
  from .ui_components import (
4
  create_base_parameter_ui, create_lora_settings_ui,
5
  create_embedding_ui,
6
- create_conditioning_ui, create_vae_override_ui, create_api_key_ui
 
7
  )
8
 
9
  def create_ui():
@@ -74,7 +75,7 @@ def create_ui():
74
  # components.update(create_diffsynth_controlnet_ui(prefix))
75
  # components.update(create_controlnet_ui(prefix))
76
  # components.update(create_embedding_ui(prefix))
77
- components.update((prefix))
78
  components.update(create_conditioning_ui(prefix))
79
  # components.update(create_vae_override_ui(prefix))
80
  components[f'accordion_wrapper_{prefix}'] = accordion_wrapper
 
3
  from .ui_components import (
4
  create_base_parameter_ui, create_lora_settings_ui,
5
  create_embedding_ui,
6
+ create_conditioning_ui, create_vae_override_ui, create_api_key_ui,
7
+ create_reference_latent_ui
8
  )
9
 
10
  def create_ui():
 
75
  # components.update(create_diffsynth_controlnet_ui(prefix))
76
  # components.update(create_controlnet_ui(prefix))
77
  # components.update(create_embedding_ui(prefix))
78
+ components.update(create_reference_latent_ui(prefix))
79
  components.update(create_conditioning_ui(prefix))
80
  # components.update(create_vae_override_ui(prefix))
81
  components[f'accordion_wrapper_{prefix}'] = accordion_wrapper
ui/shared/outpaint_ui.py CHANGED
@@ -4,7 +4,8 @@ from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
  create_embedding_ui,
7
- create_conditioning_ui, create_vae_override_ui, create_api_key_ui
 
8
  )
9
 
10
  def create_ui():
@@ -62,7 +63,7 @@ def create_ui():
62
  # components.update(create_diffsynth_controlnet_ui(prefix))
63
  # components.update(create_controlnet_ui(prefix))
64
  # components.update(create_embedding_ui(prefix))
65
- components.update((prefix))
66
  components.update(create_conditioning_ui(prefix))
67
  # components.update(create_vae_override_ui(prefix))
68
 
 
4
  from .ui_components import (
5
  create_lora_settings_ui,
6
  create_embedding_ui,
7
+ create_conditioning_ui, create_vae_override_ui, create_api_key_ui,
8
+ create_reference_latent_ui
9
  )
10
 
11
  def create_ui():
 
63
  # components.update(create_diffsynth_controlnet_ui(prefix))
64
  # components.update(create_controlnet_ui(prefix))
65
  # components.update(create_embedding_ui(prefix))
66
+ components.update(create_reference_latent_ui(prefix))
67
  components.update(create_conditioning_ui(prefix))
68
  # components.update(create_vae_override_ui(prefix))
69
 
ui/shared/txt2img_ui.py CHANGED
@@ -3,7 +3,8 @@ from core.settings import MODEL_MAP_CHECKPOINT
3
  from .ui_components import (
4
  create_base_parameter_ui, create_lora_settings_ui,
5
  create_embedding_ui,
6
- create_conditioning_ui, create_vae_override_ui, create_api_key_ui
 
7
  )
8
 
9
  def create_ui():
@@ -32,7 +33,7 @@ def create_ui():
32
  # components.update(create_diffsynth_controlnet_ui(prefix))
33
  # components.update(create_controlnet_ui(prefix))
34
  # components.update(create_embedding_ui(prefix))
35
- components.update((prefix))
36
  components.update(create_conditioning_ui(prefix))
37
  # components.update(create_vae_override_ui(prefix))
38
 
 
3
  from .ui_components import (
4
  create_base_parameter_ui, create_lora_settings_ui,
5
  create_embedding_ui,
6
+ create_conditioning_ui, create_vae_override_ui, create_api_key_ui,
7
+ create_reference_latent_ui
8
  )
9
 
10
  def create_ui():
 
33
  # components.update(create_diffsynth_controlnet_ui(prefix))
34
  # components.update(create_controlnet_ui(prefix))
35
  # components.update(create_embedding_ui(prefix))
36
+ components.update(create_reference_latent_ui(prefix))
37
  components.update(create_conditioning_ui(prefix))
38
  # components.update(create_vae_override_ui(prefix))
39
 
ui/shared/ui_components.py CHANGED
@@ -2,7 +2,7 @@ import gradio as gr
2
  from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
3
  from core.settings import (
4
  MAX_LORAS, LORA_SOURCE_CHOICES, MAX_EMBEDDINGS, MAX_CONDITIONINGS,
5
- MAX_CONTROLNETS, RESOLUTION_MAP
6
  )
7
  import yaml
8
  import os
@@ -172,6 +172,35 @@ def create_conditioning_ui(prefix: str):
172
  components[key('all_conditioning_components_flat')] = all_cond_components_flat
173
 
174
  return components
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
  def create_vae_override_ui(prefix: str):
177
  components = {}
 
2
  from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
3
  from core.settings import (
4
  MAX_LORAS, LORA_SOURCE_CHOICES, MAX_EMBEDDINGS, MAX_CONDITIONINGS,
5
+ MAX_CONTROLNETS, RESOLUTION_MAP, MAX_REFERENCE_LATENTS
6
  )
7
  import yaml
8
  import os
 
172
  components[key('all_conditioning_components_flat')] = all_cond_components_flat
173
 
174
  return components
175
+
176
+ def create_reference_latent_ui(prefix: str):
177
+ components = {}
178
+ key = lambda name: f"{name}_{prefix}"
179
+
180
+ with gr.Accordion("Reference Edit", open=False) as accordion:
181
+ components[key('reference_latent_accordion')] = accordion
182
+ gr.Markdown("💡 **Tip:** For multimodal models (like FLUX.2), this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an **Image Edit**, while adding multiple images performs an **Image Combine**.")
183
+
184
+ ref_rows, ref_images = [], []
185
+ components.update({
186
+ key('reference_latent_rows'): ref_rows,
187
+ key('reference_latent_images'): ref_images,
188
+ })
189
+
190
+ with gr.Row():
191
+ for i in range(MAX_REFERENCE_LATENTS):
192
+ with gr.Column(visible=(i < 1), min_width=160) as row_wrapper:
193
+ ref_images.append(gr.Image(type="pil", label=f"Reference {i+1}", sources=["upload"], height=150))
194
+ ref_rows.append(row_wrapper)
195
+
196
+ with gr.Row():
197
+ components[key('add_reference_latent_button')] = gr.Button("✚ Add Reference Image")
198
+ components[key('delete_reference_latent_button')] = gr.Button("➖ Delete Reference Image", visible=False)
199
+ components[key('reference_latent_count_state')] = gr.State(1)
200
+
201
+ components[key('all_reference_latent_components_flat')] = ref_images
202
+
203
+ return components
204
 
205
  def create_vae_override_ui(prefix: str):
206
  components = {}
yaml/constants.yaml CHANGED
@@ -2,6 +2,7 @@ MAX_LORAS: 5
2
  MAX_CONTROLNETS: 5
3
  MAX_EMBEDDINGS: 5
4
  MAX_CONDITIONINGS: 10
 
5
  LORA_SOURCE_CHOICES: ["Civitai", "File"]
6
 
7
  RESOLUTION_MAP:
 
2
  MAX_CONTROLNETS: 5
3
  MAX_EMBEDDINGS: 5
4
  MAX_CONDITIONINGS: 10
5
+ MAX_REFERENCE_LATENTS: 10
6
  LORA_SOURCE_CHOICES: ["Civitai", "File"]
7
 
8
  RESOLUTION_MAP:
yaml/injectors.yaml CHANGED
@@ -1,6 +1,9 @@
1
  injector_definitions:
2
  dynamic_conditioning_chains:
3
  module: "chain_injectors.conditioning_injector"
 
 
4
 
5
  injector_order:
 
6
  - dynamic_conditioning_chains
 
1
  injector_definitions:
2
  dynamic_conditioning_chains:
3
  module: "chain_injectors.conditioning_injector"
4
+ dynamic_reference_latent_chains:
5
+ module: "chain_injectors.reference_latent_injector"
6
 
7
  injector_order:
8
+ - dynamic_reference_latent_chains
9
  - dynamic_conditioning_chains