Fix native 'queue selected nodes'; add random seed range in node properties; fix groups collecting nodes when moving; and other small fixes. Fixes #578 #536 #551 #576
This commit is contained in:
@@ -9,6 +9,7 @@ class RgthreeImageComparer(PreviewImage):
|
||||
NAME = get_name('Image Comparer')
|
||||
CATEGORY = get_category()
|
||||
FUNCTION = "compare_images"
|
||||
DESCRIPTION = "Compares two images with a hover slider, or click from properties."
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring
|
||||
|
||||
+26
-12
@@ -1,7 +1,6 @@
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import requests
|
||||
|
||||
from .utils import set_dict_value
|
||||
|
||||
@@ -45,14 +44,29 @@ LOGO_URL: str = _DATA['tool']['comfy']['Icon']
|
||||
if not LOGO_URL.endswith('.svg'):
|
||||
raise ValueError('Bad logo url.')
|
||||
|
||||
# Fetch the logo so we have any updated markup.
|
||||
try:
|
||||
LOGO_SVG = requests.get(
|
||||
LOGO_URL,
|
||||
headers={"user-agent": f"rgthree-comfy/{VERSION}"},
|
||||
timeout=10
|
||||
).text
|
||||
LOGO_SVG = re.sub(r'(id="bg".*fill=)"[^\"]+"', r'\1"{bg}"', LOGO_SVG)
|
||||
LOGO_SVG = re.sub(r'(id="fg".*fill=)"[^\"]+"', r'\1"{fg}"', LOGO_SVG)
|
||||
except Exception:
|
||||
LOGO_SVG = '<svg></svg>'
|
||||
LOGO_SVG = None
|
||||
async def get_logo_svg():
|
||||
import aiohttp
|
||||
global LOGO_SVG
|
||||
if LOGO_SVG is not None:
|
||||
return LOGO_SVG
|
||||
# Fetch the logo so we have any updated markup.
|
||||
try:
|
||||
async with aiohttp.ClientSession(
|
||||
trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=True)
|
||||
) as session:
|
||||
headers = {
|
||||
"user-agent": f"rgthree-comfy/{VERSION}",
|
||||
'Cache-Control': 'no-cache',
|
||||
'Pragma': 'no-cache',
|
||||
'Expires': '0'
|
||||
}
|
||||
async with session.get(LOGO_URL, headers=headers) as resp:
|
||||
LOGO_SVG = await resp.text()
|
||||
LOGO_SVG = '<svg></svg>'
|
||||
LOGO_SVG = re.sub(r'(id="bg".*fill=)"[^\"]+"', r'\1"{bg}"', LOGO_SVG)
|
||||
LOGO_SVG = re.sub(r'(id="fg".*fill=)"[^\"]+"', r'\1"{fg}"', LOGO_SVG)
|
||||
except Exception:
|
||||
LOGO_SVG = '<svg></svg>'
|
||||
print(LOGO_SVG)
|
||||
return LOGO_SVG
|
||||
|
||||
@@ -4,12 +4,13 @@ from aiohttp import web
|
||||
|
||||
from server import PromptServer
|
||||
|
||||
from ..pyproject import LOGO_SVG
|
||||
from ..pyproject import get_logo_svg
|
||||
from .utils_server import is_param_truthy, get_param
|
||||
from ..config import get_config, set_user_config, refresh_config
|
||||
|
||||
routes = PromptServer.instance.routes
|
||||
|
||||
|
||||
@routes.get('/rgthree/config.js')
|
||||
def api_get_user_config_file(request):
|
||||
""" Returns the user configuration as a javascript file. """
|
||||
@@ -36,9 +37,29 @@ async def api_set_user_config(request):
|
||||
|
||||
|
||||
@routes.get('/rgthree/logo.svg')
|
||||
async def get_logo(request):
|
||||
async def get_logo(request, as_markup=False):
|
||||
""" Returns the rgthree logo with color config. """
|
||||
bg = get_param(request, 'bg', 'transparent')
|
||||
fg = get_param(request, 'fg', '#111111')
|
||||
resp = LOGO_SVG.format(bg=bg, fg=fg)
|
||||
w = get_param(request, 'w')
|
||||
h = get_param(request, 'h')
|
||||
css_class = get_param(request, 'cssClass')
|
||||
svg = await get_logo_svg()
|
||||
resp = svg.format(bg=bg, fg=fg)
|
||||
if w is not None:
|
||||
resp = re.sub(r'(<svg[^\>]*?)width="[^\"]+"', r'\1', resp)
|
||||
resp = re.sub(r'<svg', f'<svg width="{w}"', resp)
|
||||
if h is not None:
|
||||
resp = re.sub(r'(<svg[^\>]*?)height="[^\"]+"', r'\1', resp)
|
||||
resp = re.sub(r'<svg', f'<svg height="{h}"', resp)
|
||||
if css_class is not None:
|
||||
resp = re.sub(r'<svg', f'<svg class="{css_class}"', resp)
|
||||
if as_markup:
|
||||
resp = re.sub(r'^.*?<svg', r'<svg', resp, flags=re.DOTALL)
|
||||
return web.Response(text=resp, content_type='image/svg+xml')
|
||||
|
||||
|
||||
@routes.get('/rgthree/logo_markup.svg')
|
||||
async def get_logo_markup(request):
|
||||
""" Returns the rgthree logo svg markup (no doctype) with options. """
|
||||
return await get_logo(request, as_markup=True)
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "rgthree-comfy"
|
||||
description = "Making ComfyUI more comfortable."
|
||||
version = "1.0.2508241658"
|
||||
version = "1.0.2509062212"
|
||||
license = { file = "LICENSE" }
|
||||
dependencies = []
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {app} from "scripts/app.js";
|
||||
import { ComfyButtonGroup } from "scripts/ui/components/buttonGroup.js";
|
||||
import { ComfyButton } from "scripts/ui/components/button.js";
|
||||
import { iconGear, iconStarFilled, logoRgthree } from "rgthree/common/media/svgs.js";
|
||||
import { createElement, empty, query } from "rgthree/common/utils_dom.js";
|
||||
import { SERVICE as BOOKMARKS_SERVICE } from "./services/bookmarks_services.js";
|
||||
import { SERVICE as CONFIG_SERVICE } from "./services/config_service.js";
|
||||
import { ComfyPopup } from "scripts/ui/components/popup.js";
|
||||
import { RgthreeConfigDialog } from "./config.js";
|
||||
import {ComfyButtonGroup} from "scripts/ui/components/buttonGroup.js";
|
||||
import {ComfyButton} from "scripts/ui/components/button.js";
|
||||
import {iconGear, iconStarFilled, logoRgthreeAsync} from "rgthree/common/media/svgs.js";
|
||||
import {createElement, empty, query} from "rgthree/common/utils_dom.js";
|
||||
import {SERVICE as BOOKMARKS_SERVICE} from "./services/bookmarks_services.js";
|
||||
import {SERVICE as CONFIG_SERVICE} from "./services/config_service.js";
|
||||
import {ComfyPopup} from "scripts/ui/components/popup.js";
|
||||
import {RgthreeConfigDialog} from "./config.js";
|
||||
|
||||
let rgthreeButtonGroup: ComfyButtonGroup | null = null;
|
||||
|
||||
@@ -33,10 +33,10 @@ function addRgthreeTopBarButtons() {
|
||||
});
|
||||
buttons.push(rgthreeButton);
|
||||
rgthreeButton.iconElement.style.width = "1.2rem";
|
||||
rgthreeButton.iconElement.innerHTML = logoRgthree;
|
||||
logoRgthreeAsync().then((t) => { rgthreeButton.iconElement.innerHTML = t;});
|
||||
rgthreeButton.withPopup(
|
||||
new ComfyPopup(
|
||||
{ target: rgthreeButton.element, classList: "rgthree-top-menu" },
|
||||
{target: rgthreeButton.element, classList: "rgthree-top-menu"},
|
||||
createElement("menu", {
|
||||
children: [
|
||||
createElement("li", {
|
||||
@@ -61,7 +61,7 @@ function addRgthreeTopBarButtons() {
|
||||
const bookmarksListEl = createElement("menu");
|
||||
bookmarksListEl.appendChild(
|
||||
createElement("li.rgthree-message", {
|
||||
child: createElement("span", { text: "No bookmarks in current workflow." }),
|
||||
child: createElement("span", {text: "No bookmarks in current workflow."}),
|
||||
}),
|
||||
);
|
||||
const bookmarksButton = new ComfyButton({
|
||||
@@ -70,7 +70,7 @@ function addRgthreeTopBarButtons() {
|
||||
app,
|
||||
});
|
||||
const bookmarksPopup = new ComfyPopup(
|
||||
{ target: bookmarksButton.element, classList: "rgthree-top-menu" },
|
||||
{target: bookmarksButton.element, classList: "rgthree-top-menu"},
|
||||
bookmarksListEl,
|
||||
);
|
||||
bookmarksPopup.addEventListener("open", () => {
|
||||
@@ -92,7 +92,7 @@ function addRgthreeTopBarButtons() {
|
||||
} else {
|
||||
bookmarksListEl.appendChild(
|
||||
createElement("li.rgthree-message", {
|
||||
child: createElement("span", { text: "No bookmarks in current workflow." }),
|
||||
child: createElement("span", {text: "No bookmarks in current workflow."}),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ app.registerExtension({
|
||||
message: "No output nodes for group!",
|
||||
});
|
||||
} else {
|
||||
rgthree.queueOutputNodes(outputNodes.map((n) => n.id));
|
||||
rgthree.queueOutputNodes(outputNodes);
|
||||
}
|
||||
} else {
|
||||
const toggleMode = TOGGLE_TO_MODE.get(toggleAction);
|
||||
|
||||
@@ -21,7 +21,7 @@ function showQueueNodesMenuIfOutputNodesAreSelected(
|
||||
content: `Queue Selected Output Nodes (rgthree) `,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: () => {
|
||||
rgthree.queueOutputNodes(outputNodes.map((n) => n.id));
|
||||
rgthree.queueOutputNodes(outputNodes);
|
||||
},
|
||||
disabled: !outputNodes.length,
|
||||
};
|
||||
@@ -50,7 +50,7 @@ function showQueueGroupNodesMenuIfGroupIsSelected(
|
||||
content: `Queue Group Output Nodes (rgthree) `,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: () => {
|
||||
outputNodes && rgthree.queueOutputNodes(outputNodes.map((n) => n.id));
|
||||
outputNodes && rgthree.queueOutputNodes(outputNodes);
|
||||
},
|
||||
disabled: !outputNodes?.length,
|
||||
};
|
||||
|
||||
@@ -255,6 +255,8 @@ class Rgthree extends EventTarget {
|
||||
// Comfy/LiteGraph states so nodes and tell what the hell is going on.
|
||||
canvasCurrentlyCopyingToClipboard = false;
|
||||
canvasCurrentlyCopyingToClipboardWithMultipleNodes = false;
|
||||
canvasCurrentlyPastingFromClipboard = false;
|
||||
canvasCurrentlyPastingFromClipboardWithMultipleNodes = false;
|
||||
initialGraphToPromptSerializedWorkflowBecauseComfyUIBrokeStuff: any = null;
|
||||
|
||||
private readonly isMac: boolean = !!(
|
||||
@@ -419,6 +421,14 @@ class Rgthree extends EventTarget {
|
||||
rgthree.canvasCurrentlyCopyingToClipboardWithMultipleNodes = false;
|
||||
};
|
||||
|
||||
// [🤮] Pasting from clipboard.
|
||||
const pasteFromClipboard = LGraphCanvas.prototype.pasteFromClipboard;
|
||||
LGraphCanvas.prototype.pasteFromClipboard = function (...args: any[]) {
|
||||
rgthree.canvasCurrentlyPastingFromClipboard = true;
|
||||
pasteFromClipboard.apply(this, [...arguments] as any);
|
||||
rgthree.canvasCurrentlyPastingFromClipboard = false;
|
||||
};
|
||||
|
||||
// [⭐] Make it so when we add a group, we get to name it immediately.
|
||||
const onGroupAdd = LGraphCanvas.onGroupAdd;
|
||||
LGraphCanvas.onGroupAdd = function (...args: any[]) {
|
||||
@@ -648,7 +658,13 @@ class Rgthree extends EventTarget {
|
||||
* Wraps an `app.queuePrompt` call setting a specific node id that we will inspect and change the
|
||||
* serialized graph right before being sent (below, in our `api.queuePrompt` override).
|
||||
*/
|
||||
async queueOutputNodes(nodeIds: NodeId[]) {
|
||||
async queueOutputNodes(nodes: LGraphNode[]) {
|
||||
// We can use just these next two lines when
|
||||
// https://github.com/ltdrdata/ComfyUI-Inspire-Pack/pull/258 is pulled. Until then, we'll keep
|
||||
// our custom logic as ComfyUI-Inspire-Pack would cause it not to work.
|
||||
// app.canvas.selectItems(nodes);
|
||||
// app.extensionManager.command.execute('Comfy.QueueSelectedOutputNodes');
|
||||
const nodeIds = nodes.map(n => n.id);
|
||||
try {
|
||||
this.queueNodeIds = nodeIds;
|
||||
await app.queuePrompt(0);
|
||||
@@ -729,7 +745,7 @@ class Rgthree extends EventTarget {
|
||||
// then we only want to queue those nodes, by rewriting the api format (prompt 'output' field)
|
||||
// so only those are evaluated.
|
||||
const apiQueuePrompt = api.queuePrompt as Function;
|
||||
api.queuePrompt = async function (index: number, prompt: ComfyApiPrompt) {
|
||||
api.queuePrompt = async function (index: number, prompt: ComfyApiPrompt, ...args: any[]) {
|
||||
if (rgthree.queueNodeIds?.length && prompt.output) {
|
||||
const oldOutput = prompt.output;
|
||||
let newOutput = {};
|
||||
@@ -742,7 +758,7 @@ class Rgthree extends EventTarget {
|
||||
workflow: prompt.workflow,
|
||||
output: prompt.output,
|
||||
});
|
||||
const response = apiQueuePrompt.apply(app, [index, prompt]);
|
||||
const response = apiQueuePrompt.apply(app, [index, prompt, ...args]);
|
||||
rgthree.dispatchCustomEvent("comfy-api-queue-prompt-end");
|
||||
return response;
|
||||
};
|
||||
|
||||
+31
-21
@@ -41,30 +41,40 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
|
||||
static override exposedActions = ["Randomize Each Time", "Use Last Queued Seed"];
|
||||
|
||||
static "@randomMax" = {type: "number"};
|
||||
static "@randomMin" = {type: "number"};
|
||||
|
||||
lastSeed?: number = undefined;
|
||||
serializedCtx: SeedSerializedCtx = {};
|
||||
seedWidget!: IWidget;
|
||||
lastSeedButton!: IWidget;
|
||||
lastSeedValue: IWidget | null = null;
|
||||
|
||||
randMax = 1125899906842624;
|
||||
// We can have a full range of seeds, including negative. But, for the randomRange we'll
|
||||
// only generate positives, since that's what folks assume.
|
||||
// const min = Math.max(-1125899906842624, this.seedWidget.options.min);
|
||||
randMin = 0;
|
||||
randomRange = 1125899906842624;
|
||||
|
||||
private handleApiHijackingBound = this.handleApiHijacking.bind(this);
|
||||
|
||||
constructor(title = RgthreeSeed.title) {
|
||||
super(title);
|
||||
|
||||
this.properties["randomMax"] = 1125899906842624;
|
||||
// We can have a full range of seeds, including negative. But, for the randomRange we'll
|
||||
// only generate positives, since that's what folks assume.
|
||||
this.properties["randomMin"] = 0;
|
||||
|
||||
rgthree.addEventListener(
|
||||
"comfy-api-queue-prompt-before",
|
||||
this.handleApiHijackingBound as EventListener,
|
||||
);
|
||||
}
|
||||
|
||||
override onPropertyChanged(prop: string, value: unknown, prevValue?: unknown): boolean {
|
||||
if (prop === 'randomMax') {
|
||||
this.properties["randomMax"] = Math.min(1125899906842624, Number(value as number));
|
||||
} else if (prop === 'randomMin') {
|
||||
this.properties["randomMin"] = Math.max(-1125899906842624, Number(value as number));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override onRemoved() {
|
||||
rgthree.addEventListener(
|
||||
"comfy-api-queue-prompt-before",
|
||||
@@ -101,14 +111,6 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
}
|
||||
}
|
||||
|
||||
// Update random values in case seed comes down with different options.
|
||||
let step = this.seedWidget.options.step || 1;
|
||||
this.randMax = Math.min(1125899906842624, this.seedWidget.options.max ?? 0);
|
||||
// We can have a full range of seeds, including negative. But, for the randomRange we'll
|
||||
// only generate positives, since that's what folks assume.
|
||||
this.randMin = Math.max(0, this.seedWidget.options.min ?? 0);
|
||||
this.randomRange = (this.randMax - Math.max(0, this.randMin)) / (step / 10);
|
||||
|
||||
this.addWidget(
|
||||
"button",
|
||||
"🎲 Randomize Each Time",
|
||||
@@ -124,8 +126,7 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
"🎲 New Fixed Random",
|
||||
"",
|
||||
() => {
|
||||
this.seedWidget.value =
|
||||
Math.floor(Math.random() * this.randomRange) * (step / 10) + this.randMin;
|
||||
this.seedWidget.value = this.generateRandomSeed();
|
||||
},
|
||||
{serialize: false},
|
||||
);
|
||||
@@ -144,6 +145,18 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
this.lastSeedButton.disabled = true;
|
||||
}
|
||||
|
||||
generateRandomSeed() {
|
||||
let step = this.seedWidget.options.step || 1;
|
||||
const randomMin = Number(this.properties['randomMin'] || 0);
|
||||
const randomMax = Number(this.properties['randomMax'] || 1125899906842624);
|
||||
const randomRange = (randomMax - randomMin) / (step / 10);
|
||||
let seed = Math.floor(Math.random() * randomRange) * (step / 10) + randomMin;
|
||||
if (SPECIAL_SEEDS.includes(seed)) {
|
||||
seed = 0;
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
|
||||
override getExtraMenuOptions(canvas: LGraphCanvas, options: IContextMenuValue[]) {
|
||||
super.getExtraMenuOptions?.apply(this, [...arguments] as any);
|
||||
options.splice(options.length - 1, 0, {
|
||||
@@ -263,10 +276,7 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
// If we don't have a seed to use, or it's special seed (like we incremented into one), then
|
||||
// we randomize.
|
||||
if (seedToUse == null || SPECIAL_SEEDS.includes(seedToUse)) {
|
||||
seedToUse =
|
||||
Math.floor(Math.random() * this.randomRange) *
|
||||
((this.seedWidget.options.step || 1) / 10) +
|
||||
this.randMin;
|
||||
seedToUse = this.generateRandomSeed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type {LGraphGroup} from "@comfyorg/frontend";
|
||||
import type {LGraphGroup as TLGraphGroup} from "@comfyorg/frontend";
|
||||
import type {BaseFastGroupsModeChanger} from "../fast_groups_muter.js";
|
||||
|
||||
import {app} from "scripts/app.js";
|
||||
@@ -6,6 +6,8 @@ import {getGraphDependantNodeKey, getGroupNodes, reduceNodesDepthFirst} from "..
|
||||
|
||||
type Vector4 = [number, number, number, number];
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A service that keeps global state that can be shared by multiple FastGroupsMuter or
|
||||
* FastGroupsBypasser nodes rather than calculate it on it's own.
|
||||
@@ -16,9 +18,9 @@ class FastGroupsService {
|
||||
private msLastAlpha = 0;
|
||||
private msLastPosition = 0;
|
||||
|
||||
private groupsUnsorted: LGraphGroup[] = [];
|
||||
private groupsSortedAlpha: LGraphGroup[] = [];
|
||||
private groupsSortedPosition: LGraphGroup[] = [];
|
||||
private groupsUnsorted: TLGraphGroup[] = [];
|
||||
private groupsSortedAlpha: TLGraphGroup[] = [];
|
||||
private groupsSortedPosition: TLGraphGroup[] = [];
|
||||
|
||||
private readonly fastGroupNodes: BaseFastGroupsModeChanger[] = [];
|
||||
|
||||
@@ -118,10 +120,13 @@ class FastGroupsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* This overrides `LGraphGroup.prototype.recomputeInsideNodes` to be much more efficient when
|
||||
* This overrides `TLGraphGroup.prototype.recomputeInsideNodes` to be much more efficient when
|
||||
* calculating for many groups at once (only compute all nodes once in `getBoundingsForAllNodes`).
|
||||
*/
|
||||
recomputeInsideNodesForGroup(group: LGraphGroup) {
|
||||
recomputeInsideNodesForGroup(group: TLGraphGroup) {
|
||||
// If the canvas is currently being dragged (includes if a group is being dragged around) then
|
||||
// don't recompute anything.
|
||||
if (app.canvas.isDragging) return;
|
||||
const cachedBoundings = this.getBoundingsForAllNodes();
|
||||
const nodes = group.graph!.nodes;
|
||||
group._children.clear();
|
||||
|
||||
@@ -1,13 +1,37 @@
|
||||
import { createElement as $el } from "../utils_dom.js";
|
||||
import {createElement as $el} from "../utils_dom.js";
|
||||
|
||||
// Some svg repo : https://www.svgrepo.com/svg/326731/open-outline
|
||||
|
||||
export const logoRgthree = `<svg viewBox="0 0 256 256" fill="currentColor" class="rgthree-logo">
|
||||
<path d="M88.503,158.997 L152.731,196.103 L152.738,196.092 L152.762,196.103 L152.769,196.106 L152.771,196.103 L183.922,142.084 L174.153,136.437 L148.611,180.676 L101.512,153.484 L132.193,30.415 L156.124,71.869 L165.896,66.225 L128.002,0.59 "></path>
|
||||
<path d="M55.586,148.581l13.44,47.521l0.014,0.051l0.168-0.051l10.689-3.022l-6.589-23.313l45.609,26.335l0.087,0.051l0.027-0.051 l5.617-9.718l-42.648-24.622l35.771-143.45L33.232,164.729l9.77,5.645L55.586,148.581z M87.394,93.484l-16.708,67.018l-5.018-17.747 l-8.028,2.27L87.394,93.484z"></path>
|
||||
<path d="M189.85,107.717 L137.892,137.718 L143.532,147.49 L185.723,123.133 L231.109,201.746 L24.895,201.746 L37.363,180.146 L27.592,174.505 L5.347,213.03 L250.653,213.03 "></path>
|
||||
<path d="M5.347,247.299v8.111h245.307v-8.111l-41.94-0.003c-1.336,0-2.404-1.065-2.441-2.396v-12.14 c0.037-1.315,1.089-2.368,2.41-2.385h41.972v-8.11H5.347v8.11h41.951c1.338,0.017,2.427,1.104,2.427,2.449v12.01 c0,1.365-1.105,2.462-2.457,2.462L5.347,247.299z M139.438,247.296c-1.334,0-2.406-1.065-2.439-2.396v-12.14 c0.033-1.315,1.085-2.368,2.41-2.385h46.415c1.335,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.459,2.462H139.438z M70.193,247.296c-1.339,0-2.408-1.065-2.441-2.396v-12.14c0.033-1.315,1.086-2.368,2.407-2.385h46.418 c1.336,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.458,2.462H70.193z"></path>
|
||||
</svg>`;
|
||||
export let logoRgthree: string = "";
|
||||
|
||||
export async function logoRgthreeAsync(): Promise<string> {
|
||||
if (logoRgthree) return logoRgthree;
|
||||
let baseUrl = null;
|
||||
if (window.location.pathname.includes("/rgthree/")) {
|
||||
// Try to find how many relatives paths we need to go back to hit ./rgthree/api
|
||||
const parts = window.location.pathname.split("/rgthree/")[1]?.split("/");
|
||||
if (parts && parts.length) {
|
||||
baseUrl = parts.map(() => "../").join("") + "rgthree";
|
||||
}
|
||||
}
|
||||
baseUrl = baseUrl || "./rgthree";
|
||||
return fetch(`${baseUrl}/logo_markup.svg?fg=currentColor&cssClass=rgthree-logo&w=auto&h=auto`)
|
||||
.then((r) => r.text())
|
||||
.then((t) => {
|
||||
if (t.length < 100) {
|
||||
t = `<svg viewBox="0 0 256 256" fill="currentColor" class="rgthree-logo">
|
||||
<path d="M88.503,158.997 L152.731,196.103 L152.738,196.092 L152.762,196.103 L152.769,196.106 L152.771,196.103 L183.922,142.084 L174.153,136.437 L148.611,180.676 L101.512,153.484 L132.193,30.415 L156.124,71.869 L165.896,66.225 L128.002,0.59 "></path>
|
||||
<path d="M55.586,148.581l13.44,47.521l0.014,0.051l0.168-0.051l10.689-3.022l-6.589-23.313l45.609,26.335l0.087,0.051l0.027-0.051 l5.617-9.718l-42.648-24.622l35.771-143.45L33.232,164.729l9.77,5.645L55.586,148.581z M87.394,93.484l-16.708,67.018l-5.018-17.747 l-8.028,2.27L87.394,93.484z"></path>
|
||||
<path d="M189.85,107.717 L137.892,137.718 L143.532,147.49 L185.723,123.133 L231.109,201.746 L24.895,201.746 L37.363,180.146 L27.592,174.505 L5.347,213.03 L250.653,213.03 "></path>
|
||||
<path d="M5.347,247.299v8.111h245.307v-8.111l-41.94-0.003c-1.336,0-2.404-1.065-2.441-2.396v-12.14 c0.037-1.315,1.089-2.368,2.41-2.385h41.972v-8.11H5.347v8.11h41.951c1.338,0.017,2.427,1.104,2.427,2.449v12.01 c0,1.365-1.105,2.462-2.457,2.462L5.347,247.299z M139.438,247.296c-1.334,0-2.406-1.065-2.439-2.396v-12.14 c0.033-1.315,1.085-2.368,2.41-2.385h46.415c1.335,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.459,2.462H139.438z M70.193,247.296c-1.339,0-2.408-1.065-2.441-2.396v-12.14c0.033-1.315,1.086-2.368,2.407-2.385h46.418 c1.336,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.458,2.462H70.193z"></path>
|
||||
</svg>`;
|
||||
}
|
||||
logoRgthree = t;
|
||||
return t;
|
||||
});
|
||||
}
|
||||
// Kick it off to cache upfront.
|
||||
logoRgthreeAsync();
|
||||
|
||||
export const github = `<svg viewBox="0 0 16 16" fill="currentColor" class="github-logo">
|
||||
<path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"></path>
|
||||
@@ -178,7 +202,7 @@ export const gearColored = `<svg viewBox="0 0 128 128" preserveAspectRatio="xMid
|
||||
<path d="M25.24 65.87c-.01-22.03 15.9-40.19 38.13-41.05c.68-.03 2.45 0 3.55.99c1.01.91 1.38 2.51.79 3.82c-.95 2.11-2.85 2.07-3.36 2.09c-18.51.66-34.18 15.73-34.19 33.95c0 .29-.05.58-.15.84l-.1.25c-.76 1.98-3.52 2.09-4.43.18c-.15-.34-.24-.7-.24-1.07z" fill="#94d1e0"></path>
|
||||
</svg>`;
|
||||
|
||||
export function $svg(markup: string, attrs: { [key: string]: string }) {
|
||||
export function $svg(markup: string, attrs: {[key: string]: string}) {
|
||||
if (!markup.match(/^\s*<svg/)) {
|
||||
throw new Error("Cannot call $svg with non-svg markup.");
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ class PromptService extends EventTarget {
|
||||
|
||||
// Patch the queuePrompt method so we can capture new data going through.
|
||||
const queuePrompt = api.queuePrompt;
|
||||
api.queuePrompt = async function (num: number, prompt: ComfyApiPrompt) {
|
||||
api.queuePrompt = async function (num: number, prompt: ComfyApiPrompt, ...args: any[]) {
|
||||
let response;
|
||||
try {
|
||||
response = await queuePrompt.apply(api, [...arguments]);
|
||||
|
||||
@@ -254,7 +254,7 @@ export function areDataViewsEqual(a: DataView, b: DataView) {
|
||||
* A cheap check if the source looks like base64.
|
||||
*/
|
||||
function looksLikeBase64(source: string) {
|
||||
return source.length > 500 || source.startsWith("data:");
|
||||
return source.length > 500 || source.startsWith("data:") || source.includes(";base64,");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,18 +267,40 @@ export function areArrayBuffersEqual(a?: ArrayBuffer | null, b?: ArrayBuffer | n
|
||||
return areDataViewsEqual(new DataView(a), new DataView(b));
|
||||
}
|
||||
|
||||
export function newCanvas(
|
||||
widthOrPtOrImage: number | {width: number; height: number} | HTMLImageElement,
|
||||
height?: number,
|
||||
) {
|
||||
let width: number;
|
||||
if (typeof widthOrPtOrImage !== "number") {
|
||||
width = widthOrPtOrImage.width;
|
||||
height = widthOrPtOrImage.height;
|
||||
} else {
|
||||
width = widthOrPtOrImage;
|
||||
height = height;
|
||||
}
|
||||
if (height == null) {
|
||||
throw new Error("Invalid height supplied when creating new canvas object.");
|
||||
}
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
if (widthOrPtOrImage instanceof HTMLImageElement) {
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
ctx.drawImage(widthOrPtOrImage, 0, 0, width, height);
|
||||
}
|
||||
return canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns canvas image data for an HTML Image.
|
||||
*/
|
||||
export function getCanvasImageData(
|
||||
image: HTMLImageElement,
|
||||
): [HTMLCanvasElement, CanvasRenderingContext2D, ImageData] {
|
||||
const canvas = document.createElement("canvas");
|
||||
const canvas = newCanvas(image);
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
ctx.drawImage(image, 0, 0);
|
||||
const imageData = ctx.getImageData(0, 0, image.width, image.height);
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
return [canvas, ctx, imageData];
|
||||
}
|
||||
|
||||
@@ -301,6 +323,9 @@ export async function convertToBase64(
|
||||
return convertToBase64(await loadImage(source));
|
||||
}
|
||||
if (source instanceof HTMLImageElement) {
|
||||
if (looksLikeBase64(source.src)) {
|
||||
return source.src;
|
||||
}
|
||||
const [canvas, ctx, imageData] = getCanvasImageData(source);
|
||||
return convertToBase64(canvas);
|
||||
}
|
||||
|
||||
@@ -356,6 +356,18 @@ export function empty(element: HTMLElement) {
|
||||
return element;
|
||||
}
|
||||
|
||||
export function remove(element: HTMLElement) {
|
||||
while (element.parentElement) {
|
||||
element.parentElement.removeChild(element);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
export function replaceChild(oldChildNode: Node, newNode: Node) {
|
||||
oldChildNode.parentNode!.replaceChild(newNode, oldChildNode);
|
||||
return newNode;
|
||||
}
|
||||
|
||||
type ChildType = HTMLElement | DocumentFragment | Text | string | null;
|
||||
export function appendChildren(el: HTMLElement, children: ChildType | ChildType[]) {
|
||||
children = !Array.isArray(children) ? [children] : children;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { ComfyButtonGroup } from "../../scripts/ui/components/buttonGroup.js";
|
||||
import { ComfyButton } from "../../scripts/ui/components/button.js";
|
||||
import { iconGear, iconStarFilled, logoRgthree } from "../../rgthree/common/media/svgs.js";
|
||||
import { iconGear, iconStarFilled, logoRgthreeAsync } from "../../rgthree/common/media/svgs.js";
|
||||
import { createElement, empty } from "../../rgthree/common/utils_dom.js";
|
||||
import { SERVICE as BOOKMARKS_SERVICE } from "./services/bookmarks_services.js";
|
||||
import { SERVICE as CONFIG_SERVICE } from "./services/config_service.js";
|
||||
@@ -30,7 +30,7 @@ function addRgthreeTopBarButtons() {
|
||||
});
|
||||
buttons.push(rgthreeButton);
|
||||
rgthreeButton.iconElement.style.width = "1.2rem";
|
||||
rgthreeButton.iconElement.innerHTML = logoRgthree;
|
||||
logoRgthreeAsync().then((t) => { rgthreeButton.iconElement.innerHTML = t; });
|
||||
rgthreeButton.withPopup(new ComfyPopup({ target: rgthreeButton.element, classList: "rgthree-top-menu" }, createElement("menu", {
|
||||
children: [
|
||||
createElement("li", {
|
||||
|
||||
@@ -57,7 +57,7 @@ app.registerExtension({
|
||||
});
|
||||
}
|
||||
else {
|
||||
rgthree.queueOutputNodes(outputNodes.map((n) => n.id));
|
||||
rgthree.queueOutputNodes(outputNodes);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -11,7 +11,7 @@ function showQueueNodesMenuIfOutputNodesAreSelected(existingOptions) {
|
||||
content: `Queue Selected Output Nodes (rgthree) `,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: () => {
|
||||
rgthree.queueOutputNodes(outputNodes.map((n) => n.id));
|
||||
rgthree.queueOutputNodes(outputNodes);
|
||||
},
|
||||
disabled: !outputNodes.length,
|
||||
};
|
||||
@@ -31,7 +31,7 @@ function showQueueGroupNodesMenuIfGroupIsSelected(existingOptions) {
|
||||
content: `Queue Group Output Nodes (rgthree) `,
|
||||
className: "rgthree-contextmenu-item",
|
||||
callback: () => {
|
||||
outputNodes && rgthree.queueOutputNodes(outputNodes.map((n) => n.id));
|
||||
outputNodes && rgthree.queueOutputNodes(outputNodes);
|
||||
},
|
||||
disabled: !(outputNodes === null || outputNodes === void 0 ? void 0 : outputNodes.length),
|
||||
};
|
||||
|
||||
+12
-3
@@ -143,6 +143,8 @@ class Rgthree extends EventTarget {
|
||||
this.lastCanvasMouseEvent = null;
|
||||
this.canvasCurrentlyCopyingToClipboard = false;
|
||||
this.canvasCurrentlyCopyingToClipboardWithMultipleNodes = false;
|
||||
this.canvasCurrentlyPastingFromClipboard = false;
|
||||
this.canvasCurrentlyPastingFromClipboardWithMultipleNodes = false;
|
||||
this.initialGraphToPromptSerializedWorkflowBecauseComfyUIBrokeStuff = null;
|
||||
this.isMac = !!(((_a = navigator.platform) === null || _a === void 0 ? void 0 : _a.toLocaleUpperCase().startsWith("MAC")) ||
|
||||
((_c = (_b = navigator.userAgentData) === null || _b === void 0 ? void 0 : _b.platform) === null || _c === void 0 ? void 0 : _c.toLocaleUpperCase().startsWith("MAC")));
|
||||
@@ -262,6 +264,12 @@ class Rgthree extends EventTarget {
|
||||
rgthree.canvasCurrentlyCopyingToClipboard = false;
|
||||
rgthree.canvasCurrentlyCopyingToClipboardWithMultipleNodes = false;
|
||||
};
|
||||
const pasteFromClipboard = LGraphCanvas.prototype.pasteFromClipboard;
|
||||
LGraphCanvas.prototype.pasteFromClipboard = function (...args) {
|
||||
rgthree.canvasCurrentlyPastingFromClipboard = true;
|
||||
pasteFromClipboard.apply(this, [...arguments]);
|
||||
rgthree.canvasCurrentlyPastingFromClipboard = false;
|
||||
};
|
||||
const onGroupAdd = LGraphCanvas.onGroupAdd;
|
||||
LGraphCanvas.onGroupAdd = function (...args) {
|
||||
const graph = app.canvas.getCurrentGraph();
|
||||
@@ -431,8 +439,9 @@ class Rgthree extends EventTarget {
|
||||
},
|
||||
];
|
||||
}
|
||||
async queueOutputNodes(nodeIds) {
|
||||
async queueOutputNodes(nodes) {
|
||||
var _a;
|
||||
const nodeIds = nodes.map(n => n.id);
|
||||
try {
|
||||
this.queueNodeIds = nodeIds;
|
||||
await app.queuePrompt(0);
|
||||
@@ -491,7 +500,7 @@ class Rgthree extends EventTarget {
|
||||
return promise;
|
||||
};
|
||||
const apiQueuePrompt = api.queuePrompt;
|
||||
api.queuePrompt = async function (index, prompt) {
|
||||
api.queuePrompt = async function (index, prompt, ...args) {
|
||||
var _a;
|
||||
if (((_a = rgthree.queueNodeIds) === null || _a === void 0 ? void 0 : _a.length) && prompt.output) {
|
||||
const oldOutput = prompt.output;
|
||||
@@ -505,7 +514,7 @@ class Rgthree extends EventTarget {
|
||||
workflow: prompt.workflow,
|
||||
output: prompt.output,
|
||||
});
|
||||
const response = apiQueuePrompt.apply(app, [index, prompt]);
|
||||
const response = apiQueuePrompt.apply(app, [index, prompt, ...args]);
|
||||
rgthree.dispatchCustomEvent("comfy-api-queue-prompt-end");
|
||||
return response;
|
||||
};
|
||||
|
||||
+27
-14
@@ -17,12 +17,20 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
this.lastSeed = undefined;
|
||||
this.serializedCtx = {};
|
||||
this.lastSeedValue = null;
|
||||
this.randMax = 1125899906842624;
|
||||
this.randMin = 0;
|
||||
this.randomRange = 1125899906842624;
|
||||
this.handleApiHijackingBound = this.handleApiHijacking.bind(this);
|
||||
this.properties["randomMax"] = 1125899906842624;
|
||||
this.properties["randomMin"] = 0;
|
||||
rgthree.addEventListener("comfy-api-queue-prompt-before", this.handleApiHijackingBound);
|
||||
}
|
||||
onPropertyChanged(prop, value, prevValue) {
|
||||
if (prop === 'randomMax') {
|
||||
this.properties["randomMax"] = Math.min(1125899906842624, Number(value));
|
||||
}
|
||||
else if (prop === 'randomMin') {
|
||||
this.properties["randomMin"] = Math.max(-1125899906842624, Number(value));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
onRemoved() {
|
||||
rgthree.addEventListener("comfy-api-queue-prompt-before", this.handleApiHijackingBound);
|
||||
}
|
||||
@@ -44,7 +52,7 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
}
|
||||
}
|
||||
onNodeCreated() {
|
||||
var _a, _b, _c;
|
||||
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") {
|
||||
@@ -55,16 +63,11 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
this.widgets.splice(i, 1);
|
||||
}
|
||||
}
|
||||
let step = this.seedWidget.options.step || 1;
|
||||
this.randMax = Math.min(1125899906842624, (_b = this.seedWidget.options.max) !== null && _b !== void 0 ? _b : 0);
|
||||
this.randMin = Math.max(0, (_c = this.seedWidget.options.min) !== null && _c !== void 0 ? _c : 0);
|
||||
this.randomRange = (this.randMax - Math.max(0, this.randMin)) / (step / 10);
|
||||
this.addWidget("button", "🎲 Randomize Each Time", "", () => {
|
||||
this.seedWidget.value = SPECIAL_SEED_RANDOM;
|
||||
}, { serialize: false });
|
||||
this.addWidget("button", "🎲 New Fixed Random", "", () => {
|
||||
this.seedWidget.value =
|
||||
Math.floor(Math.random() * this.randomRange) * (step / 10) + this.randMin;
|
||||
this.seedWidget.value = this.generateRandomSeed();
|
||||
}, { serialize: false });
|
||||
this.lastSeedButton = this.addWidget("button", LAST_SEED_BUTTON_LABEL, "", () => {
|
||||
this.seedWidget.value = this.lastSeed != null ? this.lastSeed : this.seedWidget.value;
|
||||
@@ -73,6 +76,17 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
}, { width: 50, serialize: false });
|
||||
this.lastSeedButton.disabled = true;
|
||||
}
|
||||
generateRandomSeed() {
|
||||
let step = this.seedWidget.options.step || 1;
|
||||
const randomMin = Number(this.properties['randomMin'] || 0);
|
||||
const randomMax = Number(this.properties['randomMax'] || 1125899906842624);
|
||||
const randomRange = (randomMax - randomMin) / (step / 10);
|
||||
let seed = Math.floor(Math.random() * randomRange) * (step / 10) + randomMin;
|
||||
if (SPECIAL_SEEDS.includes(seed)) {
|
||||
seed = 0;
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
getExtraMenuOptions(canvas, options) {
|
||||
var _a;
|
||||
(_a = super.getExtraMenuOptions) === null || _a === void 0 ? void 0 : _a.apply(this, [...arguments]);
|
||||
@@ -154,10 +168,7 @@ class RgthreeSeed extends RgthreeBaseServerNode {
|
||||
}
|
||||
}
|
||||
if (seedToUse == null || SPECIAL_SEEDS.includes(seedToUse)) {
|
||||
seedToUse =
|
||||
Math.floor(Math.random() * this.randomRange) *
|
||||
((this.seedWidget.options.step || 1) / 10) +
|
||||
this.randMin;
|
||||
seedToUse = this.generateRandomSeed();
|
||||
}
|
||||
}
|
||||
return seedToUse !== null && seedToUse !== void 0 ? seedToUse : inputSeed;
|
||||
@@ -179,6 +190,8 @@ RgthreeSeed.title = NodeTypesString.SEED;
|
||||
RgthreeSeed.type = NodeTypesString.SEED;
|
||||
RgthreeSeed.comfyClass = NodeTypesString.SEED;
|
||||
RgthreeSeed.exposedActions = ["Randomize Each Time", "Use Last Queued Seed"];
|
||||
RgthreeSeed["@randomMax"] = { type: "number" };
|
||||
RgthreeSeed["@randomMin"] = { type: "number" };
|
||||
app.registerExtension({
|
||||
name: "rgthree.Seed",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData) {
|
||||
|
||||
@@ -81,6 +81,8 @@ class FastGroupsService {
|
||||
return this.cachedNodeBoundings;
|
||||
}
|
||||
recomputeInsideNodesForGroup(group) {
|
||||
if (app.canvas.isDragging)
|
||||
return;
|
||||
const cachedBoundings = this.getBoundingsForAllNodes();
|
||||
const nodes = group.graph.nodes;
|
||||
group._children.clear();
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
import { createElement as $el } from "../utils_dom.js";
|
||||
export const logoRgthree = `<svg viewBox="0 0 256 256" fill="currentColor" class="rgthree-logo">
|
||||
<path d="M88.503,158.997 L152.731,196.103 L152.738,196.092 L152.762,196.103 L152.769,196.106 L152.771,196.103 L183.922,142.084 L174.153,136.437 L148.611,180.676 L101.512,153.484 L132.193,30.415 L156.124,71.869 L165.896,66.225 L128.002,0.59 "></path>
|
||||
<path d="M55.586,148.581l13.44,47.521l0.014,0.051l0.168-0.051l10.689-3.022l-6.589-23.313l45.609,26.335l0.087,0.051l0.027-0.051 l5.617-9.718l-42.648-24.622l35.771-143.45L33.232,164.729l9.77,5.645L55.586,148.581z M87.394,93.484l-16.708,67.018l-5.018-17.747 l-8.028,2.27L87.394,93.484z"></path>
|
||||
<path d="M189.85,107.717 L137.892,137.718 L143.532,147.49 L185.723,123.133 L231.109,201.746 L24.895,201.746 L37.363,180.146 L27.592,174.505 L5.347,213.03 L250.653,213.03 "></path>
|
||||
<path d="M5.347,247.299v8.111h245.307v-8.111l-41.94-0.003c-1.336,0-2.404-1.065-2.441-2.396v-12.14 c0.037-1.315,1.089-2.368,2.41-2.385h41.972v-8.11H5.347v8.11h41.951c1.338,0.017,2.427,1.104,2.427,2.449v12.01 c0,1.365-1.105,2.462-2.457,2.462L5.347,247.299z M139.438,247.296c-1.334,0-2.406-1.065-2.439-2.396v-12.14 c0.033-1.315,1.085-2.368,2.41-2.385h46.415c1.335,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.459,2.462H139.438z M70.193,247.296c-1.339,0-2.408-1.065-2.441-2.396v-12.14c0.033-1.315,1.086-2.368,2.407-2.385h46.418 c1.336,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.458,2.462H70.193z"></path>
|
||||
</svg>`;
|
||||
export let logoRgthree = "";
|
||||
export async function logoRgthreeAsync() {
|
||||
var _a;
|
||||
if (logoRgthree)
|
||||
return logoRgthree;
|
||||
let baseUrl = null;
|
||||
if (window.location.pathname.includes("/rgthree/")) {
|
||||
const parts = (_a = window.location.pathname.split("/rgthree/")[1]) === null || _a === void 0 ? void 0 : _a.split("/");
|
||||
if (parts && parts.length) {
|
||||
baseUrl = parts.map(() => "../").join("") + "rgthree";
|
||||
}
|
||||
}
|
||||
baseUrl = baseUrl || "./rgthree";
|
||||
return fetch(`${baseUrl}/logo_markup.svg?fg=currentColor&cssClass=rgthree-logo&w=auto&h=auto`)
|
||||
.then((r) => r.text())
|
||||
.then((t) => {
|
||||
if (t.length < 100) {
|
||||
t = `<svg viewBox="0 0 256 256" fill="currentColor" class="rgthree-logo">
|
||||
<path d="M88.503,158.997 L152.731,196.103 L152.738,196.092 L152.762,196.103 L152.769,196.106 L152.771,196.103 L183.922,142.084 L174.153,136.437 L148.611,180.676 L101.512,153.484 L132.193,30.415 L156.124,71.869 L165.896,66.225 L128.002,0.59 "></path>
|
||||
<path d="M55.586,148.581l13.44,47.521l0.014,0.051l0.168-0.051l10.689-3.022l-6.589-23.313l45.609,26.335l0.087,0.051l0.027-0.051 l5.617-9.718l-42.648-24.622l35.771-143.45L33.232,164.729l9.77,5.645L55.586,148.581z M87.394,93.484l-16.708,67.018l-5.018-17.747 l-8.028,2.27L87.394,93.484z"></path>
|
||||
<path d="M189.85,107.717 L137.892,137.718 L143.532,147.49 L185.723,123.133 L231.109,201.746 L24.895,201.746 L37.363,180.146 L27.592,174.505 L5.347,213.03 L250.653,213.03 "></path>
|
||||
<path d="M5.347,247.299v8.111h245.307v-8.111l-41.94-0.003c-1.336,0-2.404-1.065-2.441-2.396v-12.14 c0.037-1.315,1.089-2.368,2.41-2.385h41.972v-8.11H5.347v8.11h41.951c1.338,0.017,2.427,1.104,2.427,2.449v12.01 c0,1.365-1.105,2.462-2.457,2.462L5.347,247.299z M139.438,247.296c-1.334,0-2.406-1.065-2.439-2.396v-12.14 c0.033-1.315,1.085-2.368,2.41-2.385h46.415c1.335,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.459,2.462H139.438z M70.193,247.296c-1.339,0-2.408-1.065-2.441-2.396v-12.14c0.033-1.315,1.086-2.368,2.407-2.385h46.418 c1.336,0.017,2.425,1.104,2.425,2.449v12.01c0,1.365-1.103,2.462-2.458,2.462H70.193z"></path>
|
||||
</svg>`;
|
||||
}
|
||||
logoRgthree = t;
|
||||
return t;
|
||||
});
|
||||
}
|
||||
logoRgthreeAsync();
|
||||
export const github = `<svg viewBox="0 0 16 16" fill="currentColor" class="github-logo">
|
||||
<path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"></path>
|
||||
</svg>`;
|
||||
|
||||
@@ -82,7 +82,7 @@ class PromptService extends EventTarget {
|
||||
this.lastQueueRemaining = 0;
|
||||
const that = this;
|
||||
const queuePrompt = api.queuePrompt;
|
||||
api.queuePrompt = async function (num, prompt) {
|
||||
api.queuePrompt = async function (num, prompt, ...args) {
|
||||
let response;
|
||||
try {
|
||||
response = await queuePrompt.apply(api, [...arguments]);
|
||||
|
||||
@@ -168,7 +168,7 @@ export function areDataViewsEqual(a, b) {
|
||||
return true;
|
||||
}
|
||||
function looksLikeBase64(source) {
|
||||
return source.length > 500 || source.startsWith("data:");
|
||||
return source.length > 500 || source.startsWith("data:") || source.includes(";base64,");
|
||||
}
|
||||
export function areArrayBuffersEqual(a, b) {
|
||||
if (a == b || !a || !b) {
|
||||
@@ -176,13 +176,32 @@ export function areArrayBuffersEqual(a, b) {
|
||||
}
|
||||
return areDataViewsEqual(new DataView(a), new DataView(b));
|
||||
}
|
||||
export function getCanvasImageData(image) {
|
||||
export function newCanvas(widthOrPtOrImage, height) {
|
||||
let width;
|
||||
if (typeof widthOrPtOrImage !== "number") {
|
||||
width = widthOrPtOrImage.width;
|
||||
height = widthOrPtOrImage.height;
|
||||
}
|
||||
else {
|
||||
width = widthOrPtOrImage;
|
||||
height = height;
|
||||
}
|
||||
if (height == null) {
|
||||
throw new Error("Invalid height supplied when creating new canvas object.");
|
||||
}
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
if (widthOrPtOrImage instanceof HTMLImageElement) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(widthOrPtOrImage, 0, 0, width, height);
|
||||
}
|
||||
return canvas;
|
||||
}
|
||||
export function getCanvasImageData(image) {
|
||||
const canvas = newCanvas(image);
|
||||
const ctx = canvas.getContext("2d");
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
ctx.drawImage(image, 0, 0);
|
||||
const imageData = ctx.getImageData(0, 0, image.width, image.height);
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
return [canvas, ctx, imageData];
|
||||
}
|
||||
export async function convertToBase64(source) {
|
||||
@@ -196,6 +215,9 @@ export async function convertToBase64(source) {
|
||||
return convertToBase64(await loadImage(source));
|
||||
}
|
||||
if (source instanceof HTMLImageElement) {
|
||||
if (looksLikeBase64(source.src)) {
|
||||
return source.src;
|
||||
}
|
||||
const [canvas, ctx, imageData] = getCanvasImageData(source);
|
||||
return convertToBase64(canvas);
|
||||
}
|
||||
|
||||
@@ -299,6 +299,16 @@ export function empty(element) {
|
||||
}
|
||||
return element;
|
||||
}
|
||||
export function remove(element) {
|
||||
while (element.parentElement) {
|
||||
element.parentElement.removeChild(element);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
export function replaceChild(oldChildNode, newNode) {
|
||||
oldChildNode.parentNode.replaceChild(newNode, oldChildNode);
|
||||
return newNode;
|
||||
}
|
||||
export function appendChildren(el, children) {
|
||||
children = !Array.isArray(children) ? [children] : children;
|
||||
for (let child of children) {
|
||||
|
||||
Reference in New Issue
Block a user