|
import { app } from "../../scripts/app.js"; |
|
import { ComfyWidgets } from "../../scripts/widgets.js"; |
|
import { RgthreeBaseServerNode } from "./base_node.js"; |
|
import { rgthree } from "./rgthree.js"; |
|
import { addConnectionLayoutSupport } from "./utils.js"; |
|
import { NodeTypesString } from "./constants.js"; |
|
const LAST_SEED_BUTTON_LABEL = "♻️ (Use Last Queued Seed)"; |
|
const SPECIAL_SEED_RANDOM = -1; |
|
const SPECIAL_SEED_INCREMENT = -2; |
|
const SPECIAL_SEED_DECREMENT = -3; |
|
const SPECIAL_SEEDS = [SPECIAL_SEED_RANDOM, SPECIAL_SEED_INCREMENT, SPECIAL_SEED_DECREMENT]; |
|
class RgthreeSeed extends RgthreeBaseServerNode { |
|
constructor(title = RgthreeSeed.title) { |
|
super(title); |
|
this.serialize_widgets = true; |
|
this.logger = rgthree.newLogSession(`[Seed]`); |
|
this.lastSeed = undefined; |
|
this.serializedCtx = {}; |
|
this.lastSeedValue = null; |
|
this.randMax = 1125899906842624; |
|
this.randMin = 0; |
|
this.randomRange = 1125899906842624; |
|
this.handleApiHijackingBound = this.handleApiHijacking.bind(this); |
|
rgthree.addEventListener("comfy-api-queue-prompt-before", this.handleApiHijackingBound); |
|
} |
|
onRemoved() { |
|
rgthree.addEventListener("comfy-api-queue-prompt-before", this.handleApiHijackingBound); |
|
} |
|
configure(info) { |
|
var _a; |
|
super.configure(info); |
|
if ((_a = this.properties) === null || _a === void 0 ? void 0 : _a["showLastSeed"]) { |
|
this.addLastSeedValue(); |
|
} |
|
} |
|
async handleAction(action) { |
|
if (action === "Randomize Each Time") { |
|
this.seedWidget.value = SPECIAL_SEED_RANDOM; |
|
} |
|
else if (action === "Use Last Queued Seed") { |
|
this.seedWidget.value = this.lastSeed != null ? this.lastSeed : this.seedWidget.value; |
|
this.lastSeedButton.name = LAST_SEED_BUTTON_LABEL; |
|
this.lastSeedButton.disabled = true; |
|
} |
|
} |
|
onNodeCreated() { |
|
var _a; |
|
(_a = super.onNodeCreated) === null || _a === void 0 ? void 0 : _a.call(this); |
|
for (const [i, w] of this.widgets.entries()) { |
|
if (w.name === "seed") { |
|
this.seedWidget = w; |
|
this.seedWidget.value = SPECIAL_SEED_RANDOM; |
|
} |
|
else if (w.name === "control_after_generate") { |
|
this.widgets.splice(i, 1); |
|
} |
|
} |
|
let step = this.seedWidget.options.step || 1; |
|
this.randMax = Math.min(1125899906842624, this.seedWidget.options.max); |
|
this.randMin = Math.max(0, this.seedWidget.options.min); |
|
this.randomRange = (this.randMax - Math.max(0, this.randMin)) / (step / 10); |
|
this.addWidget("button", "🎲 Randomize Each Time", null, () => { |
|
this.seedWidget.value = SPECIAL_SEED_RANDOM; |
|
}, { serialize: false }); |
|
this.addWidget("button", "🎲 New Fixed Random", null, () => { |
|
this.seedWidget.value = |
|
Math.floor(Math.random() * this.randomRange) * (step / 10) + this.randMin; |
|
}, { serialize: false }); |
|
this.lastSeedButton = this.addWidget("button", LAST_SEED_BUTTON_LABEL, null, () => { |
|
this.seedWidget.value = this.lastSeed != null ? this.lastSeed : this.seedWidget.value; |
|
this.lastSeedButton.name = LAST_SEED_BUTTON_LABEL; |
|
this.lastSeedButton.disabled = true; |
|
}, { width: 50, serialize: false }); |
|
this.lastSeedButton.disabled = true; |
|
} |
|
getExtraMenuOptions(canvas, options) { |
|
var _a; |
|
(_a = super.getExtraMenuOptions) === null || _a === void 0 ? void 0 : _a.apply(this, [...arguments]); |
|
options.splice(options.length - 1, 0, { |
|
content: "Show/Hide Last Seed Value", |
|
callback: (_value, _options, _event, _parentMenu, _node) => { |
|
this.properties["showLastSeed"] = !this.properties["showLastSeed"]; |
|
if (this.properties["showLastSeed"]) { |
|
this.addLastSeedValue(); |
|
} |
|
else { |
|
this.removeLastSeedValue(); |
|
} |
|
}, |
|
}); |
|
} |
|
addLastSeedValue() { |
|
if (this.lastSeedValue) |
|
return; |
|
this.lastSeedValue = ComfyWidgets["STRING"](this, "last_seed", ["STRING", { multiline: true }], app).widget; |
|
this.lastSeedValue.inputEl.readOnly = true; |
|
this.lastSeedValue.inputEl.style.fontSize = "0.75rem"; |
|
this.lastSeedValue.inputEl.style.textAlign = "center"; |
|
this.computeSize(); |
|
} |
|
removeLastSeedValue() { |
|
if (!this.lastSeedValue) |
|
return; |
|
this.lastSeedValue.inputEl.remove(); |
|
this.widgets.splice(this.widgets.indexOf(this.lastSeedValue), 1); |
|
this.lastSeedValue = null; |
|
this.computeSize(); |
|
} |
|
handleApiHijacking(e) { |
|
var _a, _b, _c, _d; |
|
if (this.mode === LiteGraph.NEVER || this.mode === 4) { |
|
return; |
|
} |
|
const workflow = e.detail.workflow; |
|
const output = e.detail.output; |
|
let workflowNode = (_b = (_a = workflow === null || workflow === void 0 ? void 0 : workflow.nodes) === null || _a === void 0 ? void 0 : _a.find((n) => n.id === this.id)) !== null && _b !== void 0 ? _b : null; |
|
let outputInputs = (_c = output === null || output === void 0 ? void 0 : output[this.id]) === null || _c === void 0 ? void 0 : _c.inputs; |
|
if (!workflowNode || |
|
!outputInputs || |
|
outputInputs[this.seedWidget.name || "seed"] === undefined) { |
|
const [n, v] = this.logger.warnParts(`Node ${this.id} not found in prompt data sent to server. This may be fine if only ` + |
|
`queuing part of the workflow. If not, then this could be a bug.`); |
|
(_d = console[n]) === null || _d === void 0 ? void 0 : _d.call(console, ...v); |
|
return; |
|
} |
|
const seedToUse = this.getSeedToUse(); |
|
const seedWidgetndex = this.widgets.indexOf(this.seedWidget); |
|
workflowNode.widgets_values[seedWidgetndex] = seedToUse; |
|
outputInputs[this.seedWidget.name || "seed"] = seedToUse; |
|
this.lastSeed = seedToUse; |
|
if (seedToUse != this.seedWidget.value) { |
|
this.lastSeedButton.name = `♻️ ${this.lastSeed}`; |
|
this.lastSeedButton.disabled = false; |
|
} |
|
else { |
|
this.lastSeedButton.name = LAST_SEED_BUTTON_LABEL; |
|
this.lastSeedButton.disabled = true; |
|
} |
|
if (this.lastSeedValue) { |
|
this.lastSeedValue.value = `Last Seed: ${this.lastSeed}`; |
|
} |
|
} |
|
getSeedToUse() { |
|
const inputSeed = this.seedWidget.value; |
|
let seedToUse = null; |
|
if (SPECIAL_SEEDS.includes(inputSeed)) { |
|
if (typeof this.lastSeed === "number" && !SPECIAL_SEEDS.includes(this.lastSeed)) { |
|
if (inputSeed === SPECIAL_SEED_INCREMENT) { |
|
seedToUse = this.lastSeed + 1; |
|
} |
|
else if (inputSeed === SPECIAL_SEED_DECREMENT) { |
|
seedToUse = this.lastSeed - 1; |
|
} |
|
} |
|
if (seedToUse == null || SPECIAL_SEEDS.includes(seedToUse)) { |
|
seedToUse = |
|
Math.floor(Math.random() * this.randomRange) * |
|
((this.seedWidget.options.step || 1) / 10) + |
|
this.randMin; |
|
} |
|
} |
|
return seedToUse !== null && seedToUse !== void 0 ? seedToUse : inputSeed; |
|
} |
|
static setUp(comfyClass, nodeData) { |
|
RgthreeBaseServerNode.registerForOverride(comfyClass, nodeData, RgthreeSeed); |
|
} |
|
static onRegisteredForOverride(comfyClass, ctxClass) { |
|
addConnectionLayoutSupport(RgthreeSeed, app, [ |
|
["Left", "Right"], |
|
["Right", "Left"], |
|
]); |
|
setTimeout(() => { |
|
RgthreeSeed.category = comfyClass.category; |
|
}); |
|
} |
|
} |
|
RgthreeSeed.title = NodeTypesString.SEED; |
|
RgthreeSeed.type = NodeTypesString.SEED; |
|
RgthreeSeed.comfyClass = NodeTypesString.SEED; |
|
RgthreeSeed.exposedActions = ["Randomize Each Time", "Use Last Queued Seed"]; |
|
app.registerExtension({ |
|
name: "rgthree.Seed", |
|
async beforeRegisterNodeDef(nodeType, nodeData) { |
|
if (nodeData.name === RgthreeSeed.type) { |
|
RgthreeSeed.setUp(nodeType, nodeData); |
|
} |
|
}, |
|
}); |
|
|