joeygambino commited on
Commit
74098bd
·
verified ·
1 Parent(s): b45b3cc

v2.1: clear Studio LoRA defaults; RiftCast fallback widgets hide when a Style node is wired

Browse files
Files changed (1) hide show
  1. web/js/riftcast_style_shadow.js +109 -0
web/js/riftcast_style_shadow.js ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // RiftCast: hide the Designer's fallback appearance widgets when a Style node
2
+ // is wired.
3
+ //
4
+ // THE PROBLEM. hair_color / hair_style / wardrobe / distinguishing exist on BOTH
5
+ // RiftCast_CharacterDesigner and RiftCast_Style + Wardrobe. When style_block is
6
+ // connected the Designer's four are discarded outright (riftcast_generator.py
7
+ // builds `appearance` from the style payload and never reads them) - so you set
8
+ // hair colour on the Designer, nothing happens, and nothing on screen says why.
9
+ // Two identical-looking dropdowns on two nodes, only one of which is live.
10
+ //
11
+ // WHY NOT JUST DELETE THEM. They are a real fallback: the Designer is used with
12
+ // NO Style node in JoyEcho_Multishot_Workflow_PUBLIC.json and in
13
+ // RiftCast_Character_Foundry.json. Removing them would break both, and make the
14
+ // Style node mandatory for everyone who installed the patch.
15
+ //
16
+ // WHY NOT JUST A TOOLTIP. A tooltip only helps someone who hovers BEFORE they
17
+ // are confused, and the widget labels stay identical either way. The console
18
+ // warning in design() fires after the render, which is too late and unseen by
19
+ // most users.
20
+ //
21
+ // THE FIX. Wire a Style node -> the four vanish from the Designer. Unwire it ->
22
+ // they come back with their values intact. Nothing is removed from node.widgets,
23
+ // so ComfyUI's positional widgets_values serialization is untouched and saved
24
+ // workflows keep loading exactly as before.
25
+ //
26
+ // Everything is wrapped defensively: if a future frontend changes the widget
27
+ // API, the worst case is the widgets stay visible (today's behaviour), never a
28
+ // broken node.
29
+
30
+ import { app } from "../../scripts/app.js";
31
+
32
+ const NODE = "RiftCast_CharacterDesigner";
33
+ const INPUT = "style_block";
34
+ const SHADOWED = ["hair_color", "hair_style", "wardrobe", "distinguishing"];
35
+
36
+ function setShown(w, shown) {
37
+ try {
38
+ if (shown) {
39
+ if (w._rcType !== undefined) { w.type = w._rcType; delete w._rcType; }
40
+ if (w._rcSize !== undefined) { w.computeSize = w._rcSize; delete w._rcSize; }
41
+ w.hidden = false;
42
+ } else {
43
+ if (w._rcType === undefined) {
44
+ w._rcType = w.type;
45
+ w._rcSize = w.computeSize;
46
+ }
47
+ // belt and braces: `hidden` is honoured by the current frontend, the
48
+ // zero computeSize collapses the row on older ones.
49
+ w.hidden = true;
50
+ w.computeSize = () => [0, -4];
51
+ }
52
+ } catch (e) {
53
+ console.warn("[RiftCast] widget toggle skipped:", e);
54
+ }
55
+ }
56
+
57
+ function styleWired(node) {
58
+ const i = node.inputs?.find((x) => x?.name === INPUT);
59
+ return !!(i && i.link != null);
60
+ }
61
+
62
+ function apply(node) {
63
+ if (!node?.widgets) return;
64
+ const hide = styleWired(node);
65
+ let changed = false;
66
+ for (const w of node.widgets) {
67
+ if (!SHADOWED.includes(w.name)) continue;
68
+ const already = !!w.hidden;
69
+ if (already !== hide) { setShown(w, !hide); changed = true; }
70
+ }
71
+ if (changed) {
72
+ try {
73
+ const s = node.computeSize();
74
+ node.setSize([Math.max(node.size[0], s[0]), s[1]]);
75
+ node.setDirtyCanvas(true, true);
76
+ } catch (e) { /* sizing is cosmetic - never fail the node over it */ }
77
+ }
78
+ }
79
+
80
+ app.registerExtension({
81
+ name: "riftcast.styleShadow",
82
+ beforeRegisterNodeDef(nodeType, nodeData) {
83
+ if (nodeData?.name !== NODE) return;
84
+
85
+ const origCreated = nodeType.prototype.onNodeCreated;
86
+ nodeType.prototype.onNodeCreated = function () {
87
+ const r = origCreated?.apply(this, arguments);
88
+ apply(this);
89
+ return r;
90
+ };
91
+
92
+ const origConn = nodeType.prototype.onConnectionsChange;
93
+ nodeType.prototype.onConnectionsChange = function () {
94
+ const r = origConn?.apply(this, arguments);
95
+ apply(this);
96
+ return r;
97
+ };
98
+
99
+ // Loading a saved workflow: links resolve after onConfigure returns, so
100
+ // read the connection state on the next tick or style_block still looks
101
+ // unwired and the widgets flash back in.
102
+ const origConfigure = nodeType.prototype.onConfigure;
103
+ nodeType.prototype.onConfigure = function () {
104
+ const r = origConfigure?.apply(this, arguments);
105
+ setTimeout(() => apply(this), 0);
106
+ return r;
107
+ };
108
+ },
109
+ });