mirror of
https://github.com/jags111/efficiency-nodes-comfyui.git
synced 2026-03-24 14:42:12 -03:00
Efficiency Nodes V2.0
This commit is contained in:
@@ -1,11 +1,18 @@
|
||||
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"
|
||||
"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
|
||||
@@ -21,11 +28,9 @@ class SeedControl {
|
||||
this.lastSeed = -1;
|
||||
this.serializedCtx = {};
|
||||
this.node = node;
|
||||
this.holdFlag = false; // Flag to track if sampler_state was set to "Hold"
|
||||
this.usedLastSeedOnHoldRelease = false; // To track if we used the lastSeed after releasing hold
|
||||
this.seedBehavior = 'randomize'; // Default behavior
|
||||
|
||||
let controlAfterGenerateIndex;
|
||||
this.samplerStateWidget = this.node.widgets.find(w => w.name === 'sampler_state');
|
||||
|
||||
for (const [i, w] of this.node.widgets.entries()) {
|
||||
if (w.name === seedName) {
|
||||
@@ -41,10 +46,24 @@ class SeedControl {
|
||||
}
|
||||
|
||||
this.lastSeedButton = this.node.addWidget("button", LAST_SEED_BUTTON_LABEL, null, () => {
|
||||
if (this.seedWidget.value != -1) {
|
||||
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 });
|
||||
|
||||
@@ -60,76 +79,167 @@ class SeedControl {
|
||||
const range = (max - min) / (this.seedWidget.options.step / 10);
|
||||
|
||||
this.seedWidget.serializeValue = async (node, index) => {
|
||||
const currentSeed = this.seedWidget.value;
|
||||
this.serializedCtx = {
|
||||
wasRandom: currentSeed == -1,
|
||||
};
|
||||
|
||||
// Check for the state transition and act accordingly.
|
||||
if (this.samplerStateWidget) {
|
||||
if (this.samplerStateWidget.value !== "Hold" && this.holdFlag && !this.usedLastSeedOnHoldRelease) {
|
||||
this.serializedCtx.seedUsed = this.lastSeed;
|
||||
this.usedLastSeedOnHoldRelease = true;
|
||||
this.holdFlag = false; // Reset flag for the next cycle
|
||||
}
|
||||
// Check if the button is disabled
|
||||
if (this.lastSeedButton.disabled) {
|
||||
return this.seedWidget.value;
|
||||
}
|
||||
|
||||
if (!this.usedLastSeedOnHoldRelease) {
|
||||
if (this.serializedCtx.wasRandom) {
|
||||
this.serializedCtx.seedUsed = Math.floor(Math.random() * range) * (this.seedWidget.options.step / 10) + min;
|
||||
} else {
|
||||
this.serializedCtx.seedUsed = 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{
|
||||
} else {
|
||||
// Update the last seed value and the button's label to show the current seed value
|
||||
this.lastSeed = this.serializedCtx.seedUsed;
|
||||
this.lastSeedButton.name = `🎲 Randomize / ♻️ ${this.lastSeed}`;
|
||||
this.updateButtonLabel();
|
||||
}
|
||||
|
||||
this.seedWidget.value = this.serializedCtx.seedUsed;
|
||||
|
||||
if (this.serializedCtx.wasRandom) {
|
||||
if (this.serializedCtx.wasSpecial) {
|
||||
this.lastSeed = this.serializedCtx.seedUsed;
|
||||
this.lastSeedButton.name = `🎲 Randomize / ♻️ ${this.lastSeed}`;
|
||||
if (this.samplerStateWidget.value === "Hold") {
|
||||
this.holdFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.usedLastSeedOnHoldRelease && this.samplerStateWidget.value !== "Hold") {
|
||||
// Reset the flag to ensure default behavior is restored
|
||||
this.usedLastSeedOnHoldRelease = false;
|
||||
this.updateButtonLabel();
|
||||
}
|
||||
|
||||
return this.serializedCtx.seedUsed;
|
||||
};
|
||||
|
||||
this.seedWidget.afterQueued = () => {
|
||||
if (this.serializedCtx.wasRandom) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Update the button's label to show the current last seed value
|
||||
this.lastSeedButton.name = `🎲 Randomize / ♻️ ${this.lastSeed}`;
|
||||
|
||||
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;
|
||||
@@ -138,4 +248,4 @@ app.registerExtension({
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user