File size: 5,534 Bytes
b7d4bc8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
def inject(assembler, chain_definition, chain_items):
    if not chain_items:
        return

    final_settings = {}
    if chain_items and isinstance(chain_items[-1], dict) and chain_items[-1].get('is_final_settings'):
        final_settings = chain_items.pop()

    if not chain_items:
        return

    end_node_name = chain_definition.get('end')
    if not end_node_name or end_node_name not in assembler.node_map:
        print(f"Warning: Target node '{end_node_name}' for IPAdapter chain not found. Skipping chain injection.")
        return
        
    end_node_id = assembler.node_map[end_node_name]
    
    if 'model' not in assembler.workflow[end_node_id]['inputs']:
        print(f"Warning: Target node '{end_node_name}' is missing 'model' input. Skipping IPAdapter chain.")
        return
    
    current_model_connection = assembler.workflow[end_node_id]['inputs']['model']
    
    model_type = final_settings.get('model_type', 'sdxl')
    megapixels = 1.05 if model_type == 'sdxl' else 0.39

    pos_embed_outputs = []
    neg_embed_outputs = []

    for i, item_data in enumerate(chain_items):
        loader_type = 'FaceID' if 'FACEID' in item_data.get('preset', '') else 'Unified'
        
        loader_template_name = "IPAdapterUnifiedLoader"
        if loader_type == 'FaceID':
            loader_template_name = "IPAdapterUnifiedLoaderFaceID"

        image_loader_id = assembler._get_unique_id()
        image_loader_node = assembler._get_node_template("LoadImage")
        image_loader_node['inputs']['image'] = item_data['image']
        assembler.workflow[image_loader_id] = image_loader_node
        
        image_scaler_id = assembler._get_unique_id()
        image_scaler_node = assembler._get_node_template("ImageScaleToTotalPixels")
        image_scaler_node['inputs']['image'] = [image_loader_id, 0]
        image_scaler_node['inputs']['megapixels'] = megapixels
        image_scaler_node['inputs']['upscale_method'] = "lanczos"
        assembler.workflow[image_scaler_id] = image_scaler_node

        ipadapter_loader_id = assembler._get_unique_id()
        ipadapter_loader_node = assembler._get_node_template(loader_template_name)
        ipadapter_loader_node['inputs']['model'] = current_model_connection
        ipadapter_loader_node['inputs']['preset'] = item_data['preset']
        if loader_type == 'FaceID':
             ipadapter_loader_node['inputs']['lora_strength'] = item_data.get('lora_strength', 0.6)
        assembler.workflow[ipadapter_loader_id] = ipadapter_loader_node
        
        encoder_id = assembler._get_unique_id()
        encoder_node = assembler._get_node_template("IPAdapterEncoder")
        encoder_node['inputs']['weight'] = item_data['weight']
        encoder_node['inputs']['ipadapter'] = [ipadapter_loader_id, 1]
        encoder_node['inputs']['image'] = [image_scaler_id, 0]
        assembler.workflow[encoder_id] = encoder_node
        
        pos_embed_outputs.append([encoder_id, 0])
        neg_embed_outputs.append([encoder_id, 1])

    pos_combiner_id = assembler._get_unique_id()
    pos_combiner_node = assembler._get_node_template("IPAdapterCombineEmbeds")
    pos_combiner_node['inputs']['method'] = final_settings.get('final_combine_method', 'concat')
    for i, conn in enumerate(pos_embed_outputs):
        pos_combiner_node['inputs'][f'embed{i+1}'] = conn
    assembler.workflow[pos_combiner_id] = pos_combiner_node

    neg_combiner_id = assembler._get_unique_id()
    neg_combiner_node = assembler._get_node_template("IPAdapterCombineEmbeds")
    neg_combiner_node['inputs']['method'] = final_settings.get('final_combine_method', 'concat')
    for i, conn in enumerate(neg_embed_outputs):
        neg_combiner_node['inputs'][f'embed{i+1}'] = conn
    assembler.workflow[neg_combiner_id] = neg_combiner_node
    
    final_loader_type = 'FaceID' if 'FACEID' in final_settings.get('final_preset', '') else 'Unified'
    final_loader_template_name = "IPAdapterUnifiedLoader"
    if final_loader_type == 'FaceID':
        final_loader_template_name = "IPAdapterUnifiedLoaderFaceID"

    final_loader_id = assembler._get_unique_id()
    final_loader_node = assembler._get_node_template(final_loader_template_name)
    final_loader_node['inputs']['model'] = current_model_connection
    final_loader_node['inputs']['preset'] = final_settings.get('final_preset', 'STANDARD (medium strength)')
    if final_loader_type == 'FaceID':
        final_loader_node['inputs']['lora_strength'] = final_settings.get('final_lora_strength', 0.6)
    assembler.workflow[final_loader_id] = final_loader_node

    apply_embeds_id = assembler._get_unique_id()
    apply_embeds_node = assembler._get_node_template("IPAdapterEmbeds")
    apply_embeds_node['inputs']['weight'] = final_settings.get('final_weight', 1.0)
    apply_embeds_node['inputs']['embeds_scaling'] = final_settings.get('final_embeds_scaling', 'V only')
    apply_embeds_node['inputs']['model'] = [final_loader_id, 0]
    apply_embeds_node['inputs']['ipadapter'] = [final_loader_id, 1]
    apply_embeds_node['inputs']['pos_embed'] = [pos_combiner_id, 0]
    apply_embeds_node['inputs']['neg_embed'] = [neg_combiner_id, 0]
    assembler.workflow[apply_embeds_id] = apply_embeds_node

    assembler.workflow[end_node_id]['inputs']['model'] = [apply_embeds_id, 0]
    print(f"IPAdapter injector applied. Redirected '{end_node_name}' model input through {len(chain_items)} reference images.")