3v324v23's picture
lfs
1e3b872
import { app } from "../../scripts/app.js";
import { addMenuHandler } from "./node_options/common/utils.js";
const LAST_SEED_BUTTON_LABEL = '🎲 Randomize / ♻️ Last Queued Seed';
const SEED_BEHAVIOR_RANDOMIZE = 'Randomize';
const SEED_BEHAVIOR_INCREMENT = 'Increment';
const SEED_BEHAVIOR_DECREMENT = 'Decrement';
const NODE_WIDGET_MAP = {
"KSampler (Efficient)": "seed",
"KSampler Adv. (Efficient)": "noise_seed",
"KSampler SDXL (Eff.)": "noise_seed",
"Noise Control Script": "seed",
"HighRes-Fix Script": "seed",
"Tiled Upscaler Script": "seed"
};
const SPECIFIC_WIDTH = 325; // Set to desired width
function setNodeWidthForMappedTitles(node) {
if (NODE_WIDGET_MAP[node.comfyClass]) {
node.setSize([SPECIFIC_WIDTH, node.size[1]]);
}
}
class SeedControl {
constructor(node, seedName) {
this.lastSeed = -1;
this.serializedCtx = {};
this.node = node;
this.seedBehavior = 'randomize'; // Default behavior
let controlAfterGenerateIndex;
for (const [i, w] of this.node.widgets.entries()) {
if (w.name === seedName) {
this.seedWidget = w;
} else if (w.name === 'control_after_generate') {
controlAfterGenerateIndex = i;
this.node.widgets.splice(i, 1);
}
}
if (!this.seedWidget) {
throw new Error('Something\'s wrong; expected seed widget');
}
this.lastSeedButton = this.node.addWidget("button", LAST_SEED_BUTTON_LABEL, null, () => {
const isValidValue = Number.isInteger(this.seedWidget.value) && this.seedWidget.value >= min && this.seedWidget.value <= max;
// Special case: if the current label is the default and seed value is -1
if (this.lastSeedButton.name === LAST_SEED_BUTTON_LABEL && this.seedWidget.value == -1) {
return; // Do nothing and return early
}
if (isValidValue && this.seedWidget.value != -1) {
this.lastSeed = this.seedWidget.value;
this.seedWidget.value = -1;
} else if (this.lastSeed !== -1) {
this.seedWidget.value = this.lastSeed;
} else {
this.seedWidget.value = -1; // Set to -1 if the label didn't update due to a seed value issue
}
if (isValidValue) {
this.updateButtonLabel(); // Update the button label to reflect the change
}
}, { width: 50, serialize: false });
setNodeWidthForMappedTitles(node);
if (controlAfterGenerateIndex !== undefined) {
const addedWidget = this.node.widgets.pop();
this.node.widgets.splice(controlAfterGenerateIndex, 0, addedWidget);
setNodeWidthForMappedTitles(node);
}
const max = Math.min(1125899906842624, this.seedWidget.options.max);
const min = Math.max(-1125899906842624, this.seedWidget.options.min);
const range = (max - min) / (this.seedWidget.options.step / 10);
this.seedWidget.serializeValue = async (node, index) => {
// Check if the button is disabled
if (this.lastSeedButton.disabled) {
return this.seedWidget.value;
}
const currentSeed = this.seedWidget.value;
this.serializedCtx = {
wasSpecial: currentSeed == -1,
};
if (this.serializedCtx.wasSpecial) {
switch (this.seedBehavior) {
case 'increment':
this.serializedCtx.seedUsed = this.lastSeed + 1;
break;
case 'decrement':
this.serializedCtx.seedUsed = this.lastSeed - 1;
break;
default:
this.serializedCtx.seedUsed = Math.floor(Math.random() * range) * (this.seedWidget.options.step / 10) + min;
break;
}
// Ensure the seed value is an integer and remains within the accepted range
this.serializedCtx.seedUsed = Number.isInteger(this.serializedCtx.seedUsed) ? Math.min(Math.max(this.serializedCtx.seedUsed, min), max) : this.seedWidget.value;
} else {
this.serializedCtx.seedUsed = this.seedWidget.value;
}
if (node && node.widgets_values) {
node.widgets_values[index] = this.serializedCtx.seedUsed;
} else {
// Update the last seed value and the button's label to show the current seed value
this.lastSeed = this.serializedCtx.seedUsed;
this.updateButtonLabel();
}
this.seedWidget.value = this.serializedCtx.seedUsed;
if (this.serializedCtx.wasSpecial) {
this.lastSeed = this.serializedCtx.seedUsed;
this.updateButtonLabel();
}
return this.serializedCtx.seedUsed;
};
this.seedWidget.afterQueued = () => {
// Check if the button is disabled
if (this.lastSeedButton.disabled) {
return; // Exit the function immediately
}
if (this.serializedCtx.wasSpecial) {
this.seedWidget.value = -1;
}
// Check if seed has changed to a non -1 value, and if so, update lastSeed
if (this.seedWidget.value !== -1) {
this.lastSeed = this.seedWidget.value;
}
this.updateButtonLabel();
this.serializedCtx = {};
};
}
setBehavior(behavior) {
this.seedBehavior = behavior;
// Capture the current seed value as lastSeed and then set the seed widget value to -1
if (this.seedWidget.value != -1) {
this.lastSeed = this.seedWidget.value;
this.seedWidget.value = -1;
}
this.updateButtonLabel();
}
updateButtonLabel() {
switch (this.seedBehavior) {
case 'increment':
this.lastSeedButton.name = `➕ Increment / ♻️ ${this.lastSeed === -1 ? "Last Queued Seed" : this.lastSeed}`;
break;
case 'decrement':
this.lastSeedButton.name = `➖ Decrement / ♻️ ${this.lastSeed === -1 ? "Last Queued Seed" : this.lastSeed}`;
break;
default:
this.lastSeedButton.name = `🎲 Randomize / ♻️ ${this.lastSeed === -1 ? "Last Queued Seed" : this.lastSeed}`;
break;
}
}
}
function showSeedBehaviorMenu(value, options, e, menu, node) {
const behaviorOptions = [
{
content: "🎲 Randomize",
callback: () => {
node.seedControl.setBehavior('randomize');
}
},
{
content: "➕ Increment",
callback: () => {
node.seedControl.setBehavior('increment');
}
},
{
content: "➖ Decrement",
callback: () => {
node.seedControl.setBehavior('decrement');
}
}
];
new LiteGraph.ContextMenu(behaviorOptions, {
event: e,
callback: null,
parentMenu: menu,
node: node
});
return false; // This ensures the original context menu doesn't proceed
}
// Extension Definition
app.registerExtension({
name: "efficiency.seedcontrol",
async beforeRegisterNodeDef(nodeType, nodeData, _app) {
if (NODE_WIDGET_MAP[nodeData.name]) {
addMenuHandler(nodeType, function (insertOption) {
// Check conditions before showing the seed behavior option
let showSeedOption = true;
if (nodeData.name === "Noise Control Script") {
// Check for 'add_seed_noise' widget being false
const addSeedNoiseWidget = this.widgets.find(w => w.name === 'add_seed_noise');
if (addSeedNoiseWidget && !addSeedNoiseWidget.value) {
showSeedOption = false;
}
} else if (nodeData.name === "HighRes-Fix Script") {
// Check for 'use_same_seed' widget being true
const useSameSeedWidget = this.widgets.find(w => w.name === 'use_same_seed');
if (useSameSeedWidget && useSameSeedWidget.value) {
showSeedOption = false;
}
}
if (showSeedOption) {
insertOption({
content: "🌱 Seed behavior...",
has_submenu: true,
callback: showSeedBehaviorMenu
});
}
});
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function () {
onNodeCreated ? onNodeCreated.apply(this, []) : undefined;
this.seedControl = new SeedControl(this, NODE_WIDGET_MAP[nodeData.name]);
this.seedControl.seedWidget.value = -1;
};
}
},
});