The Direct node now dispatches: "standard" (default) runs the new pipeline, "legacy" runs the frozen pre-2.0 one. Measured through the node with a recording sampler, 20 steps: standard, 1 stage 1 call x 20 steps, from sigma 14.61 standard, 2 stages 2 calls x 10 steps, from 14.61 then 1.48 standard, denoise 0.6 1 call x 20 steps, from 2.23 standard, 3 injections 4 calls x 5 steps, 14.61 / 3.87 / 1.48 / 0.60 legacy, 2 stages 2 calls, each rebuilding a full schedule The 1.48 is the fix: stages continue one trajectory instead of restarting at maximum noise, where flow models discard the previous stage entirely. The 2.23 is denoise finally reaching the schedule. Also on the node: - sequential_distribution, injection_distribution and fast_high_channel_noise become real optional inputs. As V1 `hidden` tuple inputs ComfyUI never delivered them, so they were stuck at their defaults. - the debug/visualisation hidden inputs are gone; they drove stub no-ops. - IS_CHANGED is removed: it only restated widget values that are already part of the cache key, and would have rejected the new input. - new widgets are appended last, so saved workflows keep their widget order. web/src/sampling_mode_migration.ts switches nodes loaded from pre-2.0 workflows to "legacy", recognising them by the absence of the snk_version property, so existing seeds keep reproducing. 186 Python tests and 85 web tests pass; the 11 legacy goldens now exercise the legacy branch through this dispatch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
49 lines
2.0 KiB
JavaScript
49 lines
2.0 KiB
JavaScript
// Import app from ComfyUI at runtime (this import is resolved by the browser)
|
|
// @ts-ignore - ComfyUI provides this at runtime
|
|
import { app } from '../../scripts/app.js';
|
|
const NODE_NAME = 'ShaderNoiseKSamplerDirect';
|
|
const SAMPLING_MODE_WIDGET = 'sampling_mode';
|
|
const VERSION_PROPERTY = 'snk_version';
|
|
const CURRENT_VERSION = 2;
|
|
/** True when this serialized node predates the sampling modes. */
|
|
export function needsLegacySampling(info) {
|
|
const properties = info?.properties;
|
|
return properties?.[VERSION_PROPERTY] === undefined;
|
|
}
|
|
/** Set the sampling_mode widget, if the node has one. */
|
|
export function setSamplingMode(node, mode) {
|
|
const widget = node.widgets?.find((w) => w.name === SAMPLING_MODE_WIDGET);
|
|
if (widget)
|
|
widget.value = mode;
|
|
}
|
|
/** Record that this node was written by a version that understands sampling modes. */
|
|
function stampVersion(node) {
|
|
node.properties = node.properties || {};
|
|
node.properties[VERSION_PROPERTY] = CURRENT_VERSION;
|
|
}
|
|
const extension = {
|
|
name: 'ShaderNoiseKSampler.SamplingModeMigration',
|
|
async beforeRegisterNodeDef(nodeType, nodeData, _app) {
|
|
if (nodeData.name !== NODE_NAME)
|
|
return;
|
|
const origOnNodeCreated = nodeType.prototype.onNodeCreated;
|
|
nodeType.prototype.onNodeCreated = function () {
|
|
if (origOnNodeCreated)
|
|
origOnNodeCreated.call(this);
|
|
stampVersion(this);
|
|
};
|
|
const origOnConfigure = nodeType.prototype.onConfigure;
|
|
nodeType.prototype.onConfigure = function (info) {
|
|
if (origOnConfigure)
|
|
origOnConfigure.call(this, info);
|
|
// Read the marker from the saved data, not from this.properties:
|
|
// onNodeCreated has already stamped the live node by this point.
|
|
if (needsLegacySampling(info)) {
|
|
setSamplingMode(this, 'legacy');
|
|
}
|
|
stampVersion(this);
|
|
};
|
|
},
|
|
};
|
|
app.registerExtension(extension);
|
|
//# sourceMappingURL=sampling_mode_migration.js.map
|