The preview now attaches to ShaderNoiseKSamplerDirect as well. That node already exposes every shader control as a real input, so instead of adding a second, unconnected copy of each widget, the preview mirrors the node's own inputs into the properties its WebGL uniforms read, and follows them as they change. Its four preview-only widgets (Show Shader, Show Tooltips, Animation Speed, Pixel Resolution) are marked serialize: false there. Saved workflows map widget values by position, so serializing them would shift every stored input when an older workflow loads. The deprecated display node keeps its own widgets and behaviour unchanged. Also adds vitest coverage for the sampling-mode migration helpers. Typecheck clean, 91 web tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
/**
|
|
* Workflows saved before 2.0 must keep sampling the way they were tuned.
|
|
*
|
|
* 2.0 changes what a seed produces (stages became segments of one run, denoise
|
|
* and custom sigmas take effect, blended noise keeps its distribution), so a
|
|
* node loaded without the snk_version marker is switched to "legacy".
|
|
*/
|
|
import { describe, it, expect } from 'vitest';
|
|
|
|
import { needsLegacySampling, setSamplingMode } from '../src/sampling_mode_migration.js';
|
|
|
|
interface TestWidget {
|
|
name?: string;
|
|
value?: unknown;
|
|
}
|
|
|
|
function nodeWithWidgets(widgets: TestWidget[]): any {
|
|
return { properties: {}, widgets };
|
|
}
|
|
|
|
describe('sampling mode migration', () => {
|
|
describe('needsLegacySampling', () => {
|
|
it('treats a node saved before 2.0 as legacy', () => {
|
|
expect(needsLegacySampling({ properties: { 'Node name for S&R': 'ShaderNoiseKSamplerDirect' } })).toBe(true);
|
|
});
|
|
|
|
it('treats missing or empty serialized data as legacy', () => {
|
|
expect(needsLegacySampling(undefined)).toBe(true);
|
|
expect(needsLegacySampling(null)).toBe(true);
|
|
expect(needsLegacySampling({})).toBe(true);
|
|
expect(needsLegacySampling({ properties: {} })).toBe(true);
|
|
});
|
|
|
|
it('leaves a node saved by 2.0 alone', () => {
|
|
expect(needsLegacySampling({ properties: { snk_version: 2 } })).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('setSamplingMode', () => {
|
|
it('sets the sampling_mode widget', () => {
|
|
const node = nodeWithWidgets([
|
|
{ name: 'seed', value: 8888 },
|
|
{ name: 'sampling_mode', value: 'standard' },
|
|
]);
|
|
|
|
setSamplingMode(node, 'legacy');
|
|
|
|
expect(node.widgets[1].value).toBe('legacy');
|
|
expect(node.widgets[0].value).toBe(8888);
|
|
});
|
|
|
|
it('does nothing when the widget is absent', () => {
|
|
const node = nodeWithWidgets([{ name: 'seed', value: 8888 }]);
|
|
expect(() => setSamplingMode(node, 'legacy')).not.toThrow();
|
|
});
|
|
|
|
it('does nothing when the node has no widgets', () => {
|
|
expect(() => setSamplingMode({ properties: {} } as any, 'legacy')).not.toThrow();
|
|
});
|
|
});
|
|
});
|