Fix live preview media refresh
This commit is contained in:
@@ -623,7 +623,7 @@ All nodes process batches natively:
|
||||
|
||||
**Author**: Majoor
|
||||
**Category**: `image/imageops`
|
||||
**Version**: 0.1.2
|
||||
**Version**: 0.1.4
|
||||
|
||||
---
|
||||
|
||||
|
||||
+18
-2
@@ -70,6 +70,18 @@ def _field_factory(kind: str):
|
||||
return getattr(_node20_io, fallback_map.get(kind, "String"), None)
|
||||
|
||||
|
||||
def _custom_field_factory(type_name: str):
|
||||
if _node20_io is None:
|
||||
return None
|
||||
custom = getattr(_node20_io, "Custom", None)
|
||||
if callable(custom):
|
||||
try:
|
||||
return custom(type_name)
|
||||
except Exception:
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
def _make_schema_input(name: str, spec, optional: bool = False):
|
||||
if _node20_io is None:
|
||||
return None
|
||||
@@ -104,7 +116,9 @@ def _make_schema_input(name: str, spec, optional: bool = False):
|
||||
return factory.Input(name, options=list(raw_type), **kwargs)
|
||||
|
||||
type_name = str(raw_type or "STRING").upper()
|
||||
if type_name == "COLOR" or ("COLOR" in name.lower() and type_name == "STRING"):
|
||||
if "," in type_name or type_name == "VIDEO":
|
||||
factory = _custom_field_factory(type_name) or _field_factory("Image")
|
||||
elif type_name == "COLOR" or ("COLOR" in name.lower() and type_name == "STRING"):
|
||||
factory = _field_factory("Color")
|
||||
elif type_name in {"BOOLEAN", "BOOL"}:
|
||||
factory = _field_factory("Boolean")
|
||||
@@ -144,7 +158,9 @@ def _make_schema_output(name: str, output_type: str):
|
||||
if _node20_io is None:
|
||||
return None
|
||||
kind = str(output_type or "STRING").upper()
|
||||
if kind == "MASK":
|
||||
if "," in kind or kind == "VIDEO":
|
||||
factory = _custom_field_factory(kind) or _field_factory("Image")
|
||||
elif kind == "MASK":
|
||||
factory = _field_factory("Mask")
|
||||
elif "IMAGE" in kind or "VIDEO" in kind:
|
||||
factory = _field_factory("Image")
|
||||
|
||||
+37
-1
@@ -417,6 +417,18 @@ function registerImageOpsLivePreview() {
|
||||
startLoopIfVideo(n);
|
||||
}
|
||||
}
|
||||
function refreshDependentsSoon(changedNode) {
|
||||
refreshDependents(changedNode);
|
||||
for (const delayMs of [50, 250]) {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
refreshDependents(changedNode);
|
||||
} catch (e) {
|
||||
console.warn("[ImageOps] delayed refreshDependents threw", e);
|
||||
}
|
||||
}, delayMs);
|
||||
}
|
||||
}
|
||||
function hookNode(node) {
|
||||
if (!IMAGEOPS_CLASSES.has(node.comfyClass)) {
|
||||
if (node.__imageops_hooked_ext) return;
|
||||
@@ -430,12 +442,36 @@ function registerImageOpsLivePreview() {
|
||||
console.warn("[ImageOps] upstream onExecuted threw", e);
|
||||
}
|
||||
try {
|
||||
refreshDependents(node);
|
||||
refreshDependentsSoon(node);
|
||||
} catch (e) {
|
||||
console.warn("[ImageOps] refreshDependents threw", e);
|
||||
}
|
||||
return r;
|
||||
};
|
||||
for (const w of node.widgets ?? []) {
|
||||
if (typeof w.callback !== "function" && typeof w.callback !== "undefined") continue;
|
||||
const orig = w.callback;
|
||||
w.callback = function() {
|
||||
const r = orig?.apply(this, arguments);
|
||||
try {
|
||||
refreshDependentsSoon(node);
|
||||
} catch (e) {
|
||||
console.warn("[ImageOps] widget refreshDependents threw", e);
|
||||
}
|
||||
return r;
|
||||
};
|
||||
const element = w.element;
|
||||
if (element && !w.__imageops_dom_refresh_hooked) {
|
||||
w.__imageops_dom_refresh_hooked = true;
|
||||
element.addEventListener?.("change", () => {
|
||||
try {
|
||||
refreshDependentsSoon(node);
|
||||
} catch (e) {
|
||||
console.warn("[ImageOps] widget change refreshDependents threw", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
const st = ensureState(node);
|
||||
|
||||
+9
-1
@@ -41,6 +41,14 @@ class ImageOpsChannel:
|
||||
return build_node_preview_result(source, (source, output_mask), prefix="imageops_channel")
|
||||
|
||||
extracted = _extract_channel_mask(source, channel)
|
||||
result = _channel_mask_to_image(extracted, source)
|
||||
if str(_scalar(channel, str)).strip().lower() == "alpha":
|
||||
result = source.clone()
|
||||
if result.shape[-1] < 4:
|
||||
result = _channel_mask_to_image(extracted, source)
|
||||
else:
|
||||
result[..., :3] = 1.0
|
||||
result[..., 3] = extracted.to(device=result.device, dtype=result.dtype)
|
||||
else:
|
||||
result = _channel_mask_to_image(extracted, source)
|
||||
progress.finish()
|
||||
return build_node_preview_result(result, (result, extracted), prefix="imageops_channel")
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "comfyui-majoor-imageops",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.4",
|
||||
"description": "WORK IN PROGRESS",
|
||||
"scripts": {
|
||||
"build": "node esbuild.mjs",
|
||||
|
||||
+26
-1
@@ -473,6 +473,15 @@ export function registerImageOpsLivePreview(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function refreshDependentsSoon(changedNode: ComfyNode): void {
|
||||
refreshDependents(changedNode);
|
||||
for (const delayMs of [50, 250]) {
|
||||
setTimeout(() => {
|
||||
try { refreshDependents(changedNode); } catch (e) { console.warn("[ImageOps] delayed refreshDependents threw", e); }
|
||||
}, delayMs);
|
||||
}
|
||||
}
|
||||
|
||||
function hookNode(node: ComfyNode): void {
|
||||
// Non-ImageOps nodes: only hook onExecuted to refresh downstream ImageOps nodes.
|
||||
// Avoid creating heavy state objects or wrapping widgets on every node in the graph.
|
||||
@@ -483,9 +492,25 @@ export function registerImageOpsLivePreview(): void {
|
||||
node.onExecuted = function (this: any, message: any) {
|
||||
let r: any;
|
||||
try { r = origOnExecuted0?.apply(this, arguments as any); } catch (e) { console.warn("[ImageOps] upstream onExecuted threw", e); }
|
||||
try { refreshDependents(node); } catch (e) { console.warn("[ImageOps] refreshDependents threw", e); }
|
||||
try { refreshDependentsSoon(node); } catch (e) { console.warn("[ImageOps] refreshDependents threw", e); }
|
||||
return r;
|
||||
};
|
||||
for (const w of (node.widgets ?? [])) {
|
||||
if (typeof w.callback !== "function" && typeof w.callback !== "undefined") continue;
|
||||
const orig = w.callback;
|
||||
w.callback = function (this: any) {
|
||||
const r = orig?.apply(this, arguments as any);
|
||||
try { refreshDependentsSoon(node); } catch (e) { console.warn("[ImageOps] widget refreshDependents threw", e); }
|
||||
return r;
|
||||
};
|
||||
const element = w.element as HTMLElement | null | undefined;
|
||||
if (element && !(w as any).__imageops_dom_refresh_hooked) {
|
||||
(w as any).__imageops_dom_refresh_hooked = true;
|
||||
element.addEventListener?.("change", () => {
|
||||
try { refreshDependentsSoon(node); } catch (e) { console.warn("[ImageOps] widget change refreshDependents threw", e); }
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user