File size: 4,443 Bytes
7c2113f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""Write the instruction board into the Starter workflow, in place.

Idempotent: cards are identified by `properties.htc_card`, so re-running
replaces the board rather than stacking a second copy beside it. Operates on the
shipped `.json` itself rather than rebuilding from a private source workflow, so
anyone with the pack can run it.

It also strips `widgets_values_named` from every node. Both shipped workflows
carried a stale copy inherited from the dev workflow they were cloned out of --
`chains: 3`, `duration: 10 s`, `control_after_generate: randomize`, and a legacy
`ref_plan` naming pictures that do not ship, 25 entries against a 28-widget node.
It is dormant while `Comfy.Workflow.NamedValuesRestore` stays off (experimental,
default false), but anyone who turns that on would load a Starter that randomizes
its seed and dies on a missing reference. The frontend re-emits the block
correctly on the next save.
"""
import io
import json
import os
import shutil
import sys

HERE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

import notes  # noqa: E402

WF = os.path.join(HERE, "workflows", "HandTieClips_Starter.json")
# The board is Starter-only, but the stale-named-values bug is in both shipped
# workflows, so the strip runs over both.
ALSO_STRIP = [os.path.join(HERE, "workflows", "HandTieClips_Showcase.json")]
MARKER = "htc_card"
FIRST_ID = 20


def strip_named(path):
    """Drop `widgets_values_named`, and refresh the Showcase's plain Note.

    The Showcase carries one `Note` rather than the card board; its text lives
    in `notes.SHOWCASE_NOTE` so there is still a single source for it.
    """
    wf = json.load(io.open(path, encoding="utf-8"))
    n = sum(1 for node in wf["nodes"]
            if node.pop("widgets_values_named", None) is not None)
    for node in wf["nodes"]:
        if node["type"] == "Note" and node.get("widgets_values") != [notes.SHOWCASE_NOTE]:
            node["widgets_values"] = [notes.SHOWCASE_NOTE]
            # The dependency block pushed it past what 400x700 shows without
            # scrolling.
            node["size"] = [440, 900]
            n += 1
    if n:
        bak = path + ".bak-notes"
        if not os.path.exists(bak):
            shutil.copyfile(path, bak)
        io.open(path, "w", encoding="utf-8", newline="\n").write(
            json.dumps(wf, indent=2) + "\n")
    return n


def main():
    wf = json.load(io.open(WF, encoding="utf-8"))

    bak = WF + ".bak-notes"
    if not os.path.exists(bak):
        shutil.copyfile(WF, bak)

    # Out with the old board, and with the single legacy `Note` whose text the
    # cards now carry between them.
    before = len(wf["nodes"])
    wf["nodes"] = [n for n in wf["nodes"]
                   if MARKER not in (n.get("properties") or {})
                   and n["type"] != "Note"]
    dropped = before - len(wf["nodes"])

    order = max((n.get("order", 0) for n in wf["nodes"]), default=0)
    for i, (key, title, pos, size, colour, text) in enumerate(notes.CARDS):
        order += 1
        wf["nodes"].append({
            "id": FIRST_ID + i,
            "type": "MarkdownNote",
            "pos": list(pos),
            "size": list(size),
            "flags": {},
            "order": order,
            "mode": 0,
            "inputs": [],
            "outputs": [],
            "title": title,
            "properties": {MARKER: key},
            "widgets_values": [text],
            "color": colour[0],
            "bgcolor": colour[1],
        })

    wf["groups"] = [dict(notes.GROUP)]
    wf["extra"]["ds"] = dict(notes.DS)
    wf["last_node_id"] = max(wf["last_node_id"], FIRST_ID + len(notes.CARDS) - 1)

    stripped = 0
    for n in wf["nodes"]:
        if n.pop("widgets_values_named", None) is not None:
            stripped += 1

    io.open(WF, "w", encoding="utf-8", newline="\n").write(
        json.dumps(wf, indent=2) + "\n")

    print("%s\n  dropped %d old note/card node(s), wrote %d card(s)"
          % (os.path.basename(WF), dropped, len(notes.CARDS)))
    print("  stripped widgets_values_named from %d node(s)" % stripped)
    print("  %d nodes, %d bytes" % (len(wf["nodes"]), os.path.getsize(WF)))

    for path in ALSO_STRIP:
        print("%s\n  stripped widgets_values_named from %d node(s)"
              % (os.path.basename(path), strip_named(path)))


if __name__ == "__main__":
    main()