Four things people ran into while picking a mask:
- Ctrl-click on a part of a picked thing could take the whole thing
away. With only a sweater picked, a Ctrl-click on the face offered
the person, which holds the sweater, and the pick was gone. From a
spot that is not picked, a piece that holds a whole pick is no longer
offered; the picture says nothing is picked there.
- A name could only be taken away while Erase was chosen. The name
field now has a + / - button, and a name typed with a minus in front
("-face") is taken away whichever tool is chosen.
- SAM 3 answers at the size of the picture it is given, so a look at a
3840 px picture took 53 s and an 8192 px one ran a 32 GB card out of
memory. A picture with a long side over 2048 px is now asked about on
a smaller copy, and the answer comes back at the picture's own size:
31 s and 33 s. Pictures up to 2048 px are asked about as before.
- Each change on the loader in front of the node sent one more look and
left the earlier ones waiting. The node's own waiting looks are now
taken out of the queue before a new one is sent.
The button that pauses the look now says Pause or Look on, and an out
of memory stop says so in plain words.
65 lines
2.9 KiB
JavaScript
65 lines
2.9 KiB
JavaScript
// A stopped run's message on Mask by Touch goes once the next result comes in.
|
|
//
|
|
// When a run stops at Mask by Touch (nothing picked, picks made on another
|
|
// picture), its message goes on the node's face and stays there, so the
|
|
// person can read it. It used to stay after the next run from the Run button
|
|
// had worked, until something else on the face was said. The face's own
|
|
// runs cleared it; a workflow run's result did not.
|
|
//
|
|
// touch_stage.mjs imports ComfyUI's api, so it cannot be loaded here. This
|
|
// file runs its setNote for real and holds the stop and the result to the
|
|
// lines that clear the message. The live proof is a stopped run followed by
|
|
// a good one on a real canvas.
|
|
|
|
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { readFileSync } from "node:fs";
|
|
|
|
const SOURCE = readFileSync(new URL("../js/shared/touch_stage.mjs", import.meta.url), "utf-8");
|
|
|
|
function functionSource(name) {
|
|
const start = SOURCE.indexOf(`function ${name}(`);
|
|
assert.ok(start >= 0, `touch_stage.mjs has no function ${name}`);
|
|
const end = SOURCE.indexOf("\n}\n", start);
|
|
return SOURCE.slice(start, end + 2);
|
|
}
|
|
|
|
// The face's note, with setNote as touch_stage.mjs has it.
|
|
function noteFace() {
|
|
const setNote = new Function(`${functionSource("setNote")}\nreturn setNote;`)();
|
|
const classes = new Set();
|
|
const face = {
|
|
noteTimer: 0,
|
|
noteEl: { textContent: "", classList: { toggle: (name, on) => (on ? classes.add(name) : classes.delete(name)) } },
|
|
};
|
|
return { face, setNote, shown: () => (classes.has("on") ? face.noteEl.textContent : "") };
|
|
}
|
|
|
|
test("a stopped run's message stays up until the next result, then goes", () => {
|
|
const { face, setNote, shown } = noteFace();
|
|
const stopped = SOURCE.match(/face\.stopped = \(message\) => \{([\s\S]*?)\n {2}\};/)?.[1];
|
|
assert.ok(stopped, "touch_stage.mjs has no face.stopped");
|
|
assert.match(stopped, /setNote\(face, stopMessage\(message\)\);\s*(?:\/\/[^\n]*\n\s*)*face\.stopNote = true;/,
|
|
"a stop marks its message as a stop message, after it is set");
|
|
// What face.stopped does to the note.
|
|
setNote(face, "Mask by Touch: nothing is picked.");
|
|
face.stopNote = true;
|
|
assert.equal(shown(), "Mask by Touch: nothing is picked.");
|
|
|
|
// The next result clears it, as the head of show() does.
|
|
const head = functionSource("show").split("\n").slice(0, 6).join("\n");
|
|
assert.match(head, /if \(face\.stopNote && !interim && !restored\) setNote\(face, ""\);/,
|
|
"show() clears a stop message when a result comes in");
|
|
if (face.stopNote) setNote(face, "");
|
|
assert.equal(shown(), "");
|
|
});
|
|
|
|
test("any other message ends the stop message's hold", () => {
|
|
const { face, setNote } = noteFace();
|
|
setNote(face, "Mask by Touch: nothing is picked.");
|
|
face.stopNote = true;
|
|
setNote(face, "Nothing found there.", { life: 1 });
|
|
clearTimeout(face.noteTimer);
|
|
assert.equal(face.stopNote, false, "a note said since is not cleared by the next result");
|
|
});
|