Extract MSR characters into reusable nodes
This commit is contained in:
@@ -788,13 +788,8 @@ function parseInitial(jsonStr) {
|
||||
reference_mode: "OFF",
|
||||
analyzeProvider: "ollama",
|
||||
analyzeBaseUrl: "",
|
||||
analyzeModel: "",
|
||||
characters: [
|
||||
{ images: [], description: "" },
|
||||
{ images: [], description: "" },
|
||||
{ images: [], description: "" }
|
||||
]
|
||||
};
|
||||
analyzeModel: ""
|
||||
};
|
||||
try {
|
||||
if (jsonStr) {
|
||||
const p = JSON.parse(jsonStr);
|
||||
@@ -819,16 +814,7 @@ function parseInitial(jsonStr) {
|
||||
if (p.reference_mode !== undefined) parsed.reference_mode = p.reference_mode;
|
||||
if (p.analyzeProvider !== undefined) parsed.analyzeProvider = p.analyzeProvider;
|
||||
if (p.analyzeBaseUrl !== undefined) parsed.analyzeBaseUrl = p.analyzeBaseUrl;
|
||||
if (p.analyzeModel !== undefined) parsed.analyzeModel = p.analyzeModel;
|
||||
if (Array.isArray(p.characters)) {
|
||||
parsed.characters = p.characters.map(c => ({
|
||||
images: Array.isArray(c.images) ? c.images : [],
|
||||
description: c.description || ""
|
||||
}));
|
||||
while (parsed.characters.length < 3) {
|
||||
parsed.characters.push({ images: [], description: "" });
|
||||
}
|
||||
}
|
||||
if (p.analyzeModel !== undefined) parsed.analyzeModel = p.analyzeModel;
|
||||
if (Array.isArray(p.segments)) {
|
||||
parsed.segments = p.segments.map(stripImageSegmentTransient);
|
||||
}
|
||||
@@ -4055,10 +4041,7 @@ class TimelineEditor {
|
||||
this.wrapper.appendChild(propContainer);
|
||||
this.wrapper.appendChild(this.globalPropContainer);
|
||||
|
||||
// --- Character reference slots (3 @char panels) at the bottom of the editor ---
|
||||
this.createCharacterSlots(this.wrapper);
|
||||
|
||||
// --- @char autocomplete on both prompt fields ---
|
||||
// --- @char autocomplete on both prompt fields ---
|
||||
if (this.globalPromptInput) this.setupAutocomplete(this.globalPromptInput);
|
||||
if (this.promptInput) this.setupAutocomplete(this.promptInput);
|
||||
|
||||
@@ -9336,11 +9319,14 @@ class TimelineEditor {
|
||||
if (!this._autocompleteMenus) this._autocompleteMenus = [];
|
||||
this._autocompleteMenus.push(menu);
|
||||
|
||||
const suggestions = [
|
||||
{ tag: "@char1", label: "Character 1" },
|
||||
{ tag: "@char2", label: "Character 2" },
|
||||
{ tag: "@char3", label: "Character 3" }
|
||||
];
|
||||
const suggestions = [
|
||||
{ tag: "@char1", label: "Character 1" },
|
||||
{ tag: "@char2", label: "Character 2" },
|
||||
{ tag: "@char3", label: "Character 3" },
|
||||
{ tag: "@char4", label: "Character 4" },
|
||||
{ tag: "@char5", label: "Character 5" },
|
||||
{ tag: "@char6", label: "Character 6" }
|
||||
];
|
||||
|
||||
let activeIndex = 0;
|
||||
let showMenu = false;
|
||||
@@ -9554,15 +9540,11 @@ class TimelineEditor {
|
||||
fileSize: this.timeline.retakeVideo.fileSize,
|
||||
} : null,
|
||||
normalStartFrame: this.timeline.normalStartFrame,
|
||||
normalDurationFrames: this.timeline.normalDurationFrames,
|
||||
normalDurationFrames: this.timeline.normalDurationFrames,
|
||||
reference_mode: this.timeline.reference_mode || "OFF",
|
||||
analyzeProvider: this.timeline.analyzeProvider || "ollama",
|
||||
analyzeBaseUrl: this.timeline.analyzeBaseUrl || "",
|
||||
analyzeModel: this.timeline.analyzeModel || "",
|
||||
characters: (this.timeline.characters || []).map(c => ({
|
||||
images: (c.images || []).map(img => img.b64 ? { b64: img.b64, name: img.name } : { name: img.name }),
|
||||
description: c.description || ""
|
||||
})),
|
||||
analyzeModel: this.timeline.analyzeModel || "",
|
||||
segments: sortedSegments.map(stripImageSegmentTransient),
|
||||
motionSegments: (this.timeline.motionSegments || []).map(stripMotionSegmentTransient),
|
||||
audioSegments: (this.timeline.audioSegments || []).map(stripAudioSegmentTransient)
|
||||
@@ -12225,12 +12207,9 @@ app.registerExtension({
|
||||
const canvasH = self._timelineEditor ? self._timelineEditor.canvasHeight : CANVAS_HEIGHT;
|
||||
const propH = self._timelineEditor ? (self._timelineEditor.propHeight || 90) : 90;
|
||||
const globalPropH = self._timelineEditor ? (self._timelineEditor.globalPropHeight || 60) : 60;
|
||||
// Reserve room for the @char reference panel at the bottom so the node doesn't
|
||||
// collapse and crop it whenever ComfyUI recomputes the node height.
|
||||
const charPanelH = self._timelineEditor ? (self._timelineEditor.charPanelHeight || 150) : 150;
|
||||
const nodeWidth = self.size?.[0] || width || 1375;
|
||||
return [Math.max(10, nodeWidth - 30), canvasH + propH + globalPropH + charPanelH + 160];
|
||||
};
|
||||
const nodeWidth = self.size?.[0] || width || 1375;
|
||||
return [Math.max(10, nodeWidth - 30), canvasH + propH + globalPropH + 160];
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user