export const DEFAULT_HISTORY = [ "A playful kitten wearing a colorful bow tie, sitting on a fluffy cloud, with a bright rainbow in the background", "A cheerful bunny in a pink dress holding a basket of flowers, standing in a sunny meadow with butterflies around", "A small dragon with big eyes and tiny wings, blowing gentle puffs of fire while sitting on top of a cupcake", "A happy, round penguin wearing a scarf and hat, sliding down a snowy hill with sparkles and snowflakes in the air", "A friendly octopus with heart-shaped eyes, holding balloons in each tentacle, floating in an underwater scene with smiling fish", "A chubby unicorn with pastel-colored mane and tail, flying through the sky with stars and sparkles surrounding it", "A joyful panda riding a bicycle through a bamboo forest, with colorful flowers and birds flying alongside", "A tiny robot with a big smile, watering a garden of glowing flowers under a starry sky", "A group of cute woodland animals having a tea party, with tiny teacups and plates of sweets on a tree stump", "A happy little fox wearing a superhero cape, flying above a vibrant cityscape at sunset", ]; export const Shapes = Object.freeze({ SQUARE: "square", CIRCLE: "circle", ROUND: "round", ROUND_L: "round_left", ROUND_R: "round_right", TRIANGLE: "triangle", STAR: "star", ELLIPSE: "ellipse", HHL_CIRCLE: "half horizontal left circle", HVL_CIRCLE: "half vertical left circle", HHR_CIRCLE: "half horizontal right circle", HVR_CIRCLE: "half vertical right circle", }); export const AppColors = Object.freeze({ WIDGET_BGCOLOR: LiteGraph.WIDGET_BGCOLOR, WIDGET_OUTLINE_COLOR: LiteGraph.WIDGET_OUTLINE_COLOR, WIDGET_TEXT_COLOR: LiteGraph.WIDGET_TEXT_COLOR, WIDGET_SECONDARY_TEXT_COLOR: LiteGraph.WIDGET_SECONDARY_TEXT_COLOR, NODE_TITLE_COLOR: LiteGraph.NODE_TITLE_COLOR, NODE_SELECTED_TITLE_COLOR: LiteGraph.NODE_SELECTED_TITLE_COLOR, NODE_TEXT_COLOR: LiteGraph.NODE_TEXT_COLOR, NODE_DEFAULT_COLOR: LiteGraph.NODE_DEFAULT_COLOR, NODE_DEFAULT_BGCOLOR: LiteGraph.NODE_DEFAULT_BGCOLOR, NODE_DEFAULT_BOXCOLOR: LiteGraph.NODE_DEFAULT_BOXCOLOR, NODE_DEFAULT_SHAPE: LiteGraph.NODE_DEFAULT_SHAPE, NODE_BOX_OUTLINE_COLOR: LiteGraph.NODE_BOX_OUTLINE_COLOR, DEFAULT_SHADOW_COLOR: LiteGraph.DEFAULT_SHADOW_COLOR, LINK_COLOR: LiteGraph.LINK_COLOR, EVENT_LINK_COLOR: LiteGraph.EVENT_LINK_COLOR, CONNECTING_LINK_COLOR: LiteGraph.CONNECTING_LINK_COLOR, }); export const Colors = [ "#ffffff", // White "#000000", // Black "#ff0000", // Red "#00ff00", // Green "#0000ff", // Blue "#ffff00", // Yellow "#ff00ff", // Magenta "#00ffff", // Cyan "#ffa500", // Orange "#800080", // Purple "#008000", // Dark Green "#800000", // Maroon "#808000", // Olive "#008080", // Teal "#d3d3d3", // Light Gray "#000080", // Navy "#ffc0cb", // Pink "#a52a2a", // Brown "#add8e6", // Light Blue "#ff4500", // Orange Red "#90ee90", // Light Green "#4b0082", // Indigo "#ffb6c1", // Light Pink "#ffd700", // Gold "#f0e68c", // Khaki "#c0c0c0", // Silver "#696969", // Dim Gray "#1e90ff", // Dodger Blue "#32cd32", // Lime Green "#ff6347", // Tomato "#dc143c", // Crimson "#4682b4", // Steel Blue "#8b4513", // Saddle Brown "#ffdab9", // Peach Puff "#b22222", // Firebrick "#228b22", // Forest Green "#f5deb3", // Wheat "#2f4f4f", // Dark Slate Gray "#6a5acd", // Slate Blue "#e9967a", // Dark Salmon "#ff69b4", // Hot Pink "#bc8f8f", // Rosy Brown "#deb887", // Burlywood "#7fffd4", // Aquamarine "#ff8c00", // Dark Orange ]; export const canvasRatios = new Map([ ["1:1", { width: 512, height: 512 }], ["2:3", { width: 341, height: 512 }], // Rounded to 341x512 (divisible by 64) ["3:4", { width: 384, height: 512 }], // Rounded to 384x512 (divisible by 64) ["9:16", { width: 288, height: 512 }], // Rounded to 288x512 (divisible by 64) ["9:21", { width: 192, height: 512 }], // Rounded to 192x512 (divisible by 64) ["3:2", { width: 512, height: 341 }], // Rounded to 512x341 (divisible by 64) ["4:3", { width: 512, height: 384 }], // Rounded to 512x384 (divisible by 64) ["16:9", { width: 512, height: 288 }], // Rounded to 512x288 (divisible by 64) ["21:9", { width: 512, height: 219 }], // Rounded to 512x219 (divisible by 64) ]); export const canvasScales = new Map([ ["0.5x", 1], ["1x", 2], ["2x", 4], ]); export const commonColors = [ "#000000", // Black "#FFFFFF", // White "#FF0000", // Red "#0000FF", // Blue "#008000", // Green "#FFFF00", // Yellow "#FFA500", // Orange "#800080", // Purple "#A52A2A", // Brown "rgba(255, 255, 255, 0.0)", // Transparent //"#808080", // Gray ]; export function log(...args) { if (allow_debug) { console.log(...args); // Spread args to log them properly } } export const Severity = Object.freeze({ WARN: "warn", ERROR: "error", INFO: "info", DEBUG: "debug", SUCCESS: "success", }); export function toast(severity, summary, detail, life = 3000) { app.extensionManager.toast.add({ severity, summary, detail, life, }); } export function lightenColor(color, percent) { const ctx = document.createElement("canvas").getContext("2d"); ctx.fillStyle = color; color = ctx.fillStyle; if (!color.startsWith("#")) { const rgbMatch = color.match(/\d+/g); if (rgbMatch) { color = `#${rgbMatch.map((x) => parseInt(x).toString(16).padStart(2, "0")).join("")}`; } } color = color.replace(/^#/, ""); let r = parseInt(color.substring(0, 2), 16); let g = parseInt(color.substring(2, 4), 16); let b = parseInt(color.substring(4, 6), 16); r = Math.min(255, Math.floor(r + (255 - r) * (percent / 100))); g = Math.min(255, Math.floor(g + (255 - g) * (percent / 100))); b = Math.min(255, Math.floor(b + (255 - b) * (percent / 100))); return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`; } export function isLowQuality() { var _a; const canvas = app.canvas; return (((_a = canvas.ds) === null || _a === void 0 ? void 0 : _a.scale) || 1) <= 0.5; } export function hexToImageData(hex) { const byteArray = new Uint8Array(hex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))); const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); const imageData = ctx.createImageData(canvas.width, canvas.height); // Assuming the image is in RGBA format (4 bytes per pixel) imageData.data.set(byteArray); return imageData; } export function trackMouseColor(event, canvas) { if (!canvas) return "rgb(255, 255, 255)"; // Default color if canvas is null const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const scaleY = canvas.height / rect.height; const mouseX = (event.clientX - rect.left) * scaleX; const mouseY = (event.clientY - rect.top) * scaleY; const ctx = canvas.getContext("2d", { willReadFrequently: true, }); if (!ctx) return "rgb(255, 255, 255)"; // Handle missing context try { const pixel = ctx.getImageData(mouseX, mouseY, 1, 1).data; return `rgb(${pixel[0]}, ${pixel[1]}, ${pixel[2]})`; } catch (error) { console.error("Error reading pixel data:", error); return "rgb(255, 255, 255)"; // Default color on error } } export function getCopyImageOption(img) { if (typeof window.ClipboardItem === "undefined") return []; return [ { content: "Copy Image", callback: async () => { const url = new URL(img.src); url.searchParams.delete("preview"); const writeImage = async (blob) => { await navigator.clipboard.write([ new ClipboardItem({ [blob.type]: blob, }), ]); }; try { const data = await fetch(url); const blob = await data.blob(); try { await writeImage(blob); } catch (error) { // Chrome seems to only support PNG on write, convert and try again if (blob.type !== "image/png") { const canvas = $el("canvas", { width: img.naturalWidth, height: img.naturalHeight, }); const ctx = canvas.getContext("2d"); let image; if (typeof window.createImageBitmap === "undefined") { image = new Image(); const p = new Promise((resolve, reject) => { image.onload = resolve; image.onerror = reject; }).finally(() => { URL.revokeObjectURL(image.src); }); image.src = URL.createObjectURL(blob); await p; } else { image = await createImageBitmap(blob); } try { ctx.drawImage(image, 0, 0); canvas.toBlob(writeImage, "image/png"); } finally { if (typeof image.close === "function") { image.close(); } } return; } throw error; } } catch (error) { toastStore.addAlert( t("toastMessages.errorCopyImage", { error: error.message ?? error, }) ); } }, }, ]; } export function getIndex(array, item) { return array.indexOf(item); } // Function to convert hex data to a Blob export function hexToBlob(hex) { const byteArray = new Uint8Array(hex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))); return new Blob([byteArray], { type: "image/png" }); // Use 'image/png' for PNG images } // Function to convert hex data to an Image export function hexDataToImage(hexData) { const blob = hexToBlob(hexData); const url = URL.createObjectURL(blob); const img = new Image(); img.src = url; // Set the image source to the created URL return img; // Return the image object } export async function getColorUnderMouseScreen(event) { // Create a hidden canvas const canvas = globalThis.LGraphCanvas.active_canvas.canvas; console.log("globalThis", globalThis); const context = canvas.getContext("2d"); // Get mouse position relative to the canvas const x = event.offsetX; const y = event.offsetY; // Get the color at the mouse position (RGB) const pixel = context.getImageData(x, y, 1, 1).data; // Convert to RGB string const color = `rgb(${pixel[0]}, ${pixel[1]}, ${pixel[2]})`; return color; } export function fakeMouseDown(canvas, node) { const graphMouse = app.canvas.graph_mouse; const x = graphMouse[0] - node.pos[0]; const y = graphMouse[1] - node.pos[1]; const mouseDownEvent = new MouseEvent("mousedown", { bubbles: true, // Allow the event to bubble up the DOM cancelable: true, // Allow the event to be canceled view: window, // Window that the event is dispatched to clientX: x, // X coordinate of the mouse clientY: y, // Y coordinate of the mouse }); console.log("x,y", x, y); // Dispatch the event on the specified element canvas.dispatchEvent(mouseDownEvent); } export function enterFreezeMode() { this.node.allow_interaction = false; this.node.allow_dragcanvas = false; this.node.allow_dragnodes = false; } export function exitFreezeMode() { this.node.allow_interaction = true; this.node.allow_dragcanvas = true; this.node.allow_dragnodes = true; } export function drawCheckerboard(ctx, width, height, cellSize = 10, yOffset = 80) { // Create an off-screen canvas for the pattern const patternCanvas = document.createElement("canvas"); patternCanvas.width = cellSize * 2; patternCanvas.height = cellSize * 2; const pCtx = patternCanvas.getContext("2d"); // Define colors const lightGray = "#CCCCCC"; const darkGray = "#999999"; // Draw checkerboard squares pCtx.fillStyle = lightGray; pCtx.fillRect(0, yOffset, cellSize * 2, cellSize * 2); pCtx.fillStyle = darkGray; pCtx.fillRect(0, yOffset, cellSize, cellSize); pCtx.fillRect(cellSize, cellSize, cellSize, cellSize); // Create pattern const pattern = ctx.createPattern(patternCanvas, "repeat"); // Apply pattern to the main canvas ctx.fillStyle = pattern; ctx.fillRect(0, yOffset, width, height); } export function drawAngledStripsOld(ctx, width, height, stripeWidth = 5, angle = 45) { // Save the current state of the canvas ctx.save(); const canvasWidth = 512; const canvasHeight = 592 + 80; // Calculate offsets to center the rectangle within the canvas const xOffset = (canvasWidth - width) / 2; const yOffset = (canvasHeight - height) / 2; // Define the clipping area with offset ctx.beginPath(); ctx.rect(xOffset, yOffset, width, height); // Define a rectangle for clipping with offset ctx.clip(); // Apply the clipping area // Define transparent red colors const red1 = "rgba(128, 128, 128, 0.3)"; // Faded red const red2 = "rgba(128, 128, 128, 0.5)"; // Darker red // Move canvas origin to the center of the rectangle ctx.translate(xOffset + width / 2, yOffset + height / 2); // Rotate the canvas const radianAngle = (angle * Math.PI) / 180; ctx.rotate(radianAngle); // Calculate the diagonal length to cover the full area const diagonal = Math.sqrt(width * width + height * height); // Draw diagonal stripes within the clipped area for (let x = -diagonal; x < diagonal; x += stripeWidth * 2) { ctx.fillStyle = red1; ctx.fillRect(x, -diagonal / 2, stripeWidth, diagonal); ctx.fillStyle = red2; ctx.fillRect(x + stripeWidth, -diagonal / 2, stripeWidth, diagonal); } // Restore the original state of the canvas ctx.restore(); } export function drawAngledStrips(ctx, width, height, scaleFactor = 1.0, stripeWidth = 5, angle = 45) { // Save the current state of the canvas ctx.save(); // Define the fixed canvas dimensions const canvasWidth = 512; const canvasHeight = 592 + 80; // Apply inverse scaling transformation ctx.scale(1 / scaleFactor, 1 / scaleFactor); // Calculate offsets to center the rectangle within the scaled canvas const xOffset = (canvasWidth - width * scaleFactor) / 2; const yOffset = (canvasHeight - height * scaleFactor) / 2; // Define the clipping area with offset ctx.beginPath(); ctx.rect(xOffset, yOffset, width * scaleFactor, height * scaleFactor); ctx.clip(); // Define transparent colors const red1 = "rgba(128, 128, 128, 0.3)"; const red2 = "rgba(128, 128, 128, 0.5)"; // Move canvas origin to the center of the scaled canvas ctx.translate(canvasWidth / 2, canvasHeight / 2); // Rotate the canvas const radianAngle = (angle * Math.PI) / 180; ctx.rotate(radianAngle); // Calculate the diagonal length to ensure full coverage const diagonal = Math.sqrt(width ** 2 + height ** 2) * scaleFactor; // Keep stripe width constant (independent of scaleFactor) const scaledStripeWidth = stripeWidth; // Draw diagonal stripes across the clipped area for (let x = -diagonal; x < diagonal; x += scaledStripeWidth * 2) { ctx.fillStyle = red1; ctx.fillRect(x, -diagonal / 2, scaledStripeWidth, diagonal); ctx.fillStyle = red2; ctx.fillRect(x + scaledStripeWidth, -diagonal / 2, scaledStripeWidth, diagonal); } // Restore the original canvas state ctx.restore(); } // Helper function to check if the color is transparent export function isTransparent(color) { // Convert hex to RGBA (if needed) function hexToRgba(hex) { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); const a = hex.length === 9 ? parseInt(hex.slice(7, 9), 16) / 255 : 1; return [r, g, b, a]; } const rgba = hexToRgba(color); // Assumes the color is in hex format, convert if necessary return rgba[3] === 0.0; // Check if the alpha is 0 } export function getRatioByDimensions(width, height) { for (let [ratio, dimensions] of canvasRatios.entries()) { if (dimensions.width === width && dimensions.height === height) { return ratio; } } return null; // Return null if no matching ratio is found } export function getIndexByDimensions(width, height) { const entriesArray = [...canvasRatios.entries()]; // Convert Map to array for (let i = 0; i < entriesArray.length; i++) { const [ratio, dimensions] = entriesArray[i]; if (dimensions.width === width && dimensions.height === height) { return i; // Return the index if found } } return -1; // Return -1 if no matching dimensions are found } // get connected node via input // const inputIndex = 0 // const inputLink = node.inputs[inputIndex].link; // const linkInfo = graph.links[inputLink]; // const sourceNode = graph.getNodeById(linkInfo.origin_id); // const sourceSlot = linkInfo.origin_slot; // const processMouseDown = LGraphCanvas.prototype.processMouseDown; // LGraphCanvas.prototype.processMouseDown = function(e) { // if (this.allowDebug) console.log('MouseDown',e); // return processMouseDown.apply(this, arguments); // }; // const processMouseMove = LGraphCanvas.prototype.processMouseMove; // LGraphCanvas.prototype.processMouseMove= function(e) { // if (this.allowDebug) console.log('MouseMove',e); // return processMouseDown.apply(this, arguments); // }; /* LiteGraph.NODE_TITLE_COLOR, LiteGraph.NODE_SELECTED_TITLE_COLOR, LiteGraph.NODE_TEXT_COLOR, LiteGraph.NODE_DEFAULT_COLOR, LiteGraph.NODE_TEXT_SIZE, LiteGraph.NODE_DEFAULT_BGCOLOR, LiteGraph.NODE_DEFAULT_BOXCOLOR, LiteGraph.NODE_BOX_OUTLINE_COLOR, LiteGraph.DEFAULT_SHADOW_COLOR, LiteGraph.WIDGET_BGCOLOR, LiteGraph.WIDGET_OUTLINE_COLOR, LiteGraph.WIDGET_TEXT_COLOR, LiteGraph.WIDGET_SECONDARY_TEXT_COLOR, LiteGraph.LINK_COLOR, LiteGraph.EVENT_LINK_COLOR, LiteGraph.CONNECTING_LINK_COLOR */ //const window = globalThis; /* Working Callbacks app.canvas.onMouse = (e) => { // any mouse button if (this.allowDebug) console.log("onMouse",e); }; app.canvas.onNodeMoved = ()=>{ if (this.allowDebug) console.log('noe moved',); } app.canvas.canvas.onmousewheel = (e)=>{ if (this.allowDebug) console.log('onmousewheel',); } app.canvas.canvas.onclick = (e) => { if (this.allowDebug) console.log("onclick"); }; app.canvas.canvas.onkeyup = (ke) => { //onkeydown//onkeypress if (this.allowDebug) console.log("onkeyup",ke); }; app.canvas.canvas.onkeydown = (ke) => { if (this.allowDebug) console.log("onkeyup",ke); }; app.canvas.canvas.ondblclick = (e) => { if (this.allowDebug) console.log("ondblclick",e); }; app.canvas.canvas.onmouseover = (e) => { if (this.allowDebug) console.log("onmouseover"); }; ======================== NOT working callback app.canvas.onMouseMoved = () => { if (this.allowDebug) console.log("Mouse moved"); }; app.canvas.onMouseUP = (e) => { if (this.allowDebug) console.log("Mouse UP"); }; app.canvas.canvas.onmouseup = (e) => { if (this.allowDebug) console.log("onmouseup",e); }; */