mirror of
https://github.com/lllyasviel/Fooocus.git
synced 2026-08-16 13:13:16 +02:00
Merge branch 'main_upstream'
This commit is contained in:
@@ -94,6 +94,10 @@
|
|||||||
overflow:inherit !important;
|
overflow:inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gradio-container{
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
/* fullpage image viewer */
|
/* fullpage image viewer */
|
||||||
|
|
||||||
#lightboxModal{
|
#lightboxModal{
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
version = '2.1.840'
|
version = '2.1.843'
|
||||||
|
|||||||
+85
-206
@@ -1,18 +1,5 @@
|
|||||||
onUiLoaded(async() => {
|
onUiLoaded(async() => {
|
||||||
// Helper functions
|
// Helper functions
|
||||||
// Get active tab
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for an element to be present in the DOM.
|
|
||||||
*/
|
|
||||||
const waitForElement = (id) => new Promise(resolve => {
|
|
||||||
const checkForElement = () => {
|
|
||||||
const element = document.querySelector(id);
|
|
||||||
if (element) return resolve(element);
|
|
||||||
setTimeout(checkForElement, 100);
|
|
||||||
};
|
|
||||||
checkForElement();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Detect whether the element has a horizontal scroll bar
|
// Detect whether the element has a horizontal scroll bar
|
||||||
function hasHorizontalScrollbar(element) {
|
function hasHorizontalScrollbar(element) {
|
||||||
@@ -33,140 +20,40 @@ onUiLoaded(async() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if hotkey is valid
|
|
||||||
function isValidHotkey(value) {
|
|
||||||
const specialKeys = ["Ctrl", "Alt", "Shift", "Disable"];
|
|
||||||
return (
|
|
||||||
(typeof value === "string" &&
|
|
||||||
value.length === 1 &&
|
|
||||||
/[a-z]/i.test(value)) ||
|
|
||||||
specialKeys.includes(value)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize hotkey
|
|
||||||
function normalizeHotkey(hotkey) {
|
|
||||||
return hotkey.length === 1 ? "Key" + hotkey.toUpperCase() : hotkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format hotkey for display
|
|
||||||
function formatHotkeyForDisplay(hotkey) {
|
|
||||||
return hotkey.startsWith("Key") ? hotkey.slice(3) : hotkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create hotkey configuration with the provided options
|
// Create hotkey configuration with the provided options
|
||||||
function createHotkeyConfig(defaultHotkeysConfig) {
|
function createHotkeyConfig(defaultHotkeysConfig) {
|
||||||
const result = {}; // Resulting hotkey configuration
|
const result = {}; // Resulting hotkey configuration
|
||||||
|
|
||||||
for (const key in defaultHotkeysConfig) {
|
for (const key in defaultHotkeysConfig) {
|
||||||
result[key] = defaultHotkeysConfig[key];
|
result[key] = defaultHotkeysConfig[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disables functions in the config object based on the provided list of function names
|
|
||||||
function disableFunctions(config, disabledFunctions) {
|
|
||||||
// Bind the hasOwnProperty method to the functionMap object to avoid errors
|
|
||||||
const hasOwnProperty =
|
|
||||||
Object.prototype.hasOwnProperty.bind(functionMap);
|
|
||||||
|
|
||||||
// Loop through the disabledFunctions array and disable the corresponding functions in the config object
|
|
||||||
disabledFunctions.forEach(funcName => {
|
|
||||||
if (hasOwnProperty(funcName)) {
|
|
||||||
const key = functionMap[funcName];
|
|
||||||
config[key] = "disable";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Return the updated config object
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The restoreImgRedMask function displays a red mask around an image to indicate the aspect ratio.
|
|
||||||
* If the image display property is set to 'none', the mask breaks. To fix this, the function
|
|
||||||
* temporarily sets the display property to 'block' and then hides the mask again after 300 milliseconds
|
|
||||||
* to avoid breaking the canvas. Additionally, the function adjusts the mask to work correctly on
|
|
||||||
* very long images.
|
|
||||||
*/
|
|
||||||
function restoreImgRedMask(elements) {
|
|
||||||
const mainTabId = getTabId(elements);
|
|
||||||
|
|
||||||
if (!mainTabId) return;
|
|
||||||
|
|
||||||
const mainTab = gradioApp().querySelector(mainTabId);
|
|
||||||
const img = mainTab.querySelector("img");
|
|
||||||
const imageARPreview = gradioApp().querySelector("#imageARPreview");
|
|
||||||
|
|
||||||
if (!img || !imageARPreview) return;
|
|
||||||
|
|
||||||
imageARPreview.style.transform = "";
|
|
||||||
if (parseFloat(mainTab.style.width) > 865) {
|
|
||||||
const transformString = mainTab.style.transform;
|
|
||||||
const scaleMatch = transformString.match(
|
|
||||||
/scale\(([-+]?[0-9]*\.?[0-9]+)\)/
|
|
||||||
);
|
|
||||||
let zoom = 1; // default zoom
|
|
||||||
|
|
||||||
if (scaleMatch && scaleMatch[1]) {
|
|
||||||
zoom = Number(scaleMatch[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
imageARPreview.style.transformOrigin = "0 0";
|
|
||||||
imageARPreview.style.transform = `scale(${zoom})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (img.style.display !== "none") return;
|
|
||||||
|
|
||||||
img.style.display = "block";
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
img.style.display = "none";
|
|
||||||
}, 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default config
|
// Default config
|
||||||
const defaultHotkeysConfig = {
|
const defaultHotkeysConfig = {
|
||||||
canvas_hotkey_zoom: "Alt",
|
canvas_hotkey_zoom: "Shift",
|
||||||
canvas_hotkey_adjust: "Ctrl",
|
canvas_hotkey_adjust: "Ctrl",
|
||||||
|
canvas_zoom_undo_extra_key: "Ctrl",
|
||||||
|
canvas_zoom_hotkey_undo: "KeyZ",
|
||||||
canvas_hotkey_reset: "KeyR",
|
canvas_hotkey_reset: "KeyR",
|
||||||
canvas_hotkey_fullscreen: "KeyS",
|
canvas_hotkey_fullscreen: "KeyS",
|
||||||
canvas_hotkey_move: "KeyF",
|
canvas_hotkey_move: "KeyF",
|
||||||
canvas_hotkey_overlap: "KeyO",
|
|
||||||
canvas_disabled_functions: [],
|
|
||||||
canvas_show_tooltip: true,
|
canvas_show_tooltip: true,
|
||||||
canvas_auto_expand: true,
|
canvas_auto_expand: true,
|
||||||
canvas_blur_prompt: false,
|
canvas_blur_prompt: true,
|
||||||
};
|
|
||||||
|
|
||||||
const functionMap = {
|
|
||||||
"Zoom": "canvas_hotkey_zoom",
|
|
||||||
"Adjust brush size": "canvas_hotkey_adjust",
|
|
||||||
"Moving canvas": "canvas_hotkey_move",
|
|
||||||
"Fullscreen": "canvas_hotkey_fullscreen",
|
|
||||||
"Reset Zoom": "canvas_hotkey_reset",
|
|
||||||
"Overlap": "canvas_hotkey_overlap"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Loading the configuration from opts
|
// Loading the configuration from opts
|
||||||
const preHotkeysConfig = createHotkeyConfig(
|
const hotkeysConfig = createHotkeyConfig(
|
||||||
defaultHotkeysConfig
|
defaultHotkeysConfig
|
||||||
);
|
);
|
||||||
|
|
||||||
// Disable functions that are not needed by the user
|
|
||||||
const hotkeysConfig = disableFunctions(
|
|
||||||
preHotkeysConfig,
|
|
||||||
preHotkeysConfig.canvas_disabled_functions
|
|
||||||
);
|
|
||||||
|
|
||||||
let isMoving = false;
|
let isMoving = false;
|
||||||
let mouseX, mouseY;
|
|
||||||
let activeElement;
|
let activeElement;
|
||||||
|
|
||||||
const elemData = {};
|
const elemData = {};
|
||||||
|
|
||||||
function applyZoomAndPan(elemId, isExtension = true) {
|
function applyZoomAndPan(elemId) {
|
||||||
const targetElement = gradioApp().querySelector(elemId);
|
const targetElement = gradioApp().querySelector(elemId);
|
||||||
|
|
||||||
if (!targetElement) {
|
if (!targetElement) {
|
||||||
@@ -181,6 +68,7 @@ onUiLoaded(async() => {
|
|||||||
panX: 0,
|
panX: 0,
|
||||||
panY: 0
|
panY: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
let fullScreenMode = false;
|
let fullScreenMode = false;
|
||||||
|
|
||||||
// Create tooltip
|
// Create tooltip
|
||||||
@@ -211,44 +99,46 @@ onUiLoaded(async() => {
|
|||||||
action: "Adjust brush size",
|
action: "Adjust brush size",
|
||||||
keySuffix: " + wheel"
|
keySuffix: " + wheel"
|
||||||
},
|
},
|
||||||
|
{configKey: "canvas_zoom_hotkey_undo", action: "Undo last action", keyPrefix: `${hotkeysConfig.canvas_zoom_undo_extra_key} + ` },
|
||||||
{configKey: "canvas_hotkey_reset", action: "Reset zoom"},
|
{configKey: "canvas_hotkey_reset", action: "Reset zoom"},
|
||||||
{
|
{
|
||||||
configKey: "canvas_hotkey_fullscreen",
|
configKey: "canvas_hotkey_fullscreen",
|
||||||
action: "Fullscreen mode"
|
action: "Fullscreen mode"
|
||||||
},
|
},
|
||||||
{configKey: "canvas_hotkey_move", action: "Move canvas"},
|
{configKey: "canvas_hotkey_move", action: "Move canvas"}
|
||||||
{configKey: "canvas_hotkey_overlap", action: "Overlap"}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Create hotkeys array with disabled property based on the config values
|
// Create hotkeys array based on the config values
|
||||||
const hotkeys = hotkeysInfo.map(info => {
|
const hotkeys = hotkeysInfo.map((info) => {
|
||||||
const configValue = hotkeysConfig[info.configKey];
|
const configValue = hotkeysConfig[info.configKey];
|
||||||
const key = info.keySuffix ?
|
|
||||||
`${configValue}${info.keySuffix}` :
|
let key = configValue.slice(-1);
|
||||||
configValue.charAt(configValue.length - 1);
|
|
||||||
return {
|
if (info.keySuffix) {
|
||||||
key,
|
key = `${configValue}${info.keySuffix}`;
|
||||||
action: info.action,
|
|
||||||
disabled: configValue === "disable"
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const hotkey of hotkeys) {
|
|
||||||
if (hotkey.disabled) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info.keyPrefix && info.keyPrefix !== "None + ") {
|
||||||
|
key = `${info.keyPrefix}${configValue[3]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
action: info.action,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
hotkeys
|
||||||
|
.forEach(hotkey => {
|
||||||
|
const p = document.createElement("p");
|
||||||
|
p.innerHTML = `<b>${hotkey.key}</b> - ${hotkey.action}`;
|
||||||
|
tooltipContent.appendChild(p);
|
||||||
|
});
|
||||||
|
|
||||||
|
tooltip.append(info, tooltipContent);
|
||||||
|
|
||||||
const p = document.createElement("p");
|
// Add a hint element to the target element
|
||||||
p.innerHTML = `<b>${hotkey.key}</b> - ${hotkey.action}`;
|
toolTipElemnt.appendChild(tooltip);
|
||||||
tooltipContent.appendChild(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add information and content elements to the tooltip element
|
|
||||||
tooltip.appendChild(info);
|
|
||||||
tooltip.appendChild(tooltipContent);
|
|
||||||
|
|
||||||
// Add a hint element to the target element
|
|
||||||
toolTipElemnt.appendChild(tooltip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Show tool tip if setting enable
|
//Show tool tip if setting enable
|
||||||
@@ -264,9 +154,7 @@ onUiLoaded(async() => {
|
|||||||
panY: 0
|
panY: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isExtension) {
|
targetElement.style.overflow = "hidden";
|
||||||
targetElement.style.overflow = "hidden";
|
|
||||||
}
|
|
||||||
|
|
||||||
targetElement.isZoomed = false;
|
targetElement.isZoomed = false;
|
||||||
|
|
||||||
@@ -284,7 +172,7 @@ onUiLoaded(async() => {
|
|||||||
closeBtn.addEventListener("click", resetZoom);
|
closeBtn.addEventListener("click", resetZoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canvas && isExtension) {
|
if (canvas) {
|
||||||
const parentElement = targetElement.closest('[id^="component-"]');
|
const parentElement = targetElement.closest('[id^="component-"]');
|
||||||
if (
|
if (
|
||||||
canvas &&
|
canvas &&
|
||||||
@@ -297,16 +185,6 @@ onUiLoaded(async() => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
canvas &&
|
|
||||||
!isExtension &&
|
|
||||||
parseFloat(canvas.style.width) > 865 &&
|
|
||||||
parseFloat(targetElement.style.width) > 865
|
|
||||||
) {
|
|
||||||
fitToElement();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
targetElement.style.width = "";
|
targetElement.style.width = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,12 +250,10 @@ onUiLoaded(async() => {
|
|||||||
|
|
||||||
targetElement.style.transformOrigin = "0 0";
|
targetElement.style.transformOrigin = "0 0";
|
||||||
targetElement.style.transform = `translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px) scale(${newZoomLevel})`;
|
targetElement.style.transform = `translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px) scale(${newZoomLevel})`;
|
||||||
|
targetElement.style.overflow = "visible";
|
||||||
|
|
||||||
toggleOverlap("on");
|
toggleOverlap("on");
|
||||||
if (isExtension) {
|
|
||||||
targetElement.style.overflow = "visible";
|
|
||||||
}
|
|
||||||
|
|
||||||
return newZoomLevel;
|
return newZoomLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,6 +264,7 @@ onUiLoaded(async() => {
|
|||||||
|
|
||||||
let zoomPosX, zoomPosY;
|
let zoomPosX, zoomPosY;
|
||||||
let delta = 0.2;
|
let delta = 0.2;
|
||||||
|
|
||||||
if (elemData[elemId].zoomLevel > 7) {
|
if (elemData[elemId].zoomLevel > 7) {
|
||||||
delta = 0.9;
|
delta = 0.9;
|
||||||
} else if (elemData[elemId].zoomLevel > 2) {
|
} else if (elemData[elemId].zoomLevel > 2) {
|
||||||
@@ -421,12 +298,7 @@ onUiLoaded(async() => {
|
|||||||
|
|
||||||
let parentElement;
|
let parentElement;
|
||||||
|
|
||||||
if (isExtension) {
|
parentElement = targetElement.closest('[id^="component-"]');
|
||||||
parentElement = targetElement.closest('[id^="component-"]');
|
|
||||||
} else {
|
|
||||||
parentElement = targetElement.parentElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get element and screen dimensions
|
// Get element and screen dimensions
|
||||||
const elementWidth = targetElement.offsetWidth;
|
const elementWidth = targetElement.offsetWidth;
|
||||||
@@ -455,6 +327,26 @@ onUiLoaded(async() => {
|
|||||||
toggleOverlap("off");
|
toggleOverlap("off");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Undo last action
|
||||||
|
function undoLastAction(e) {
|
||||||
|
let isCtrlPressed = isModifierKey(e, hotkeysConfig.canvas_zoom_undo_extra_key)
|
||||||
|
const isAuxButton = e.button >= 3;
|
||||||
|
|
||||||
|
if (isAuxButton) {
|
||||||
|
isCtrlPressed = true
|
||||||
|
} else {
|
||||||
|
if (!isModifierKey(e, hotkeysConfig.canvas_zoom_undo_extra_key)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move undoBtn query outside the if statement to avoid unnecessary queries
|
||||||
|
const undoBtn = document.querySelector(`${activeElement} button[aria-label="Undo"]`);
|
||||||
|
|
||||||
|
if ((isCtrlPressed) && undoBtn ) {
|
||||||
|
e.preventDefault();
|
||||||
|
undoBtn.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function fits the target element to the screen by calculating
|
* This function fits the target element to the screen by calculating
|
||||||
* the required scale and offsets. It also updates the global variables
|
* the required scale and offsets. It also updates the global variables
|
||||||
@@ -469,13 +361,8 @@ onUiLoaded(async() => {
|
|||||||
|
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
if (canvas.offsetWidth > 862 || isExtension) {
|
targetElement.style.width = (canvas.offsetWidth + 2) + "px";
|
||||||
targetElement.style.width = (canvas.offsetWidth + 2) + "px";
|
targetElement.style.overflow = "visible";
|
||||||
}
|
|
||||||
|
|
||||||
if (isExtension) {
|
|
||||||
targetElement.style.overflow = "visible";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fullScreenMode) {
|
if (fullScreenMode) {
|
||||||
resetZoom();
|
resetZoom();
|
||||||
@@ -549,11 +436,11 @@ onUiLoaded(async() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const hotkeyActions = {
|
const hotkeyActions = {
|
||||||
[hotkeysConfig.canvas_hotkey_reset]: resetZoom,
|
[hotkeysConfig.canvas_hotkey_reset]: resetZoom,
|
||||||
[hotkeysConfig.canvas_hotkey_overlap]: toggleOverlap,
|
[hotkeysConfig.canvas_hotkey_overlap]: toggleOverlap,
|
||||||
[hotkeysConfig.canvas_hotkey_fullscreen]: fitToScreen
|
[hotkeysConfig.canvas_hotkey_fullscreen]: fitToScreen,
|
||||||
|
[hotkeysConfig.canvas_zoom_hotkey_undo]: undoLastAction,
|
||||||
};
|
};
|
||||||
|
|
||||||
const action = hotkeyActions[event.code];
|
const action = hotkeyActions[event.code];
|
||||||
@@ -597,26 +484,27 @@ onUiLoaded(async() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
targetElement.addEventListener("mousemove", getMousePosition);
|
targetElement.addEventListener("mousemove", getMousePosition);
|
||||||
|
targetElement.addEventListener("auxclick", undoLastAction);
|
||||||
|
|
||||||
//observers
|
//observers
|
||||||
// Creating an observer with a callback function to handle DOM changes
|
// Creating an observer with a callback function to handle DOM changes
|
||||||
const observer = new MutationObserver((mutationsList, observer) => {
|
const observer = new MutationObserver((mutationsList, observer) => {
|
||||||
for (let mutation of mutationsList) {
|
for (let mutation of mutationsList) {
|
||||||
// If the style attribute of the canvas has changed, by observation it happens only when the picture changes
|
// If the style attribute of the canvas has changed, by observation it happens only when the picture changes
|
||||||
if (mutation.type === 'attributes' && mutation.attributeName === 'style' &&
|
if (mutation.type === 'attributes' && mutation.attributeName === 'style' &&
|
||||||
mutation.target.tagName.toLowerCase() === 'canvas') {
|
mutation.target.tagName.toLowerCase() === 'canvas') {
|
||||||
targetElement.isExpanded = false;
|
targetElement.isExpanded = false;
|
||||||
setTimeout(resetZoom, 10);
|
setTimeout(resetZoom, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Apply auto expand if enabled
|
// Apply auto expand if enabled
|
||||||
if (hotkeysConfig.canvas_auto_expand) {
|
if (hotkeysConfig.canvas_auto_expand) {
|
||||||
targetElement.addEventListener("mousemove", autoExpand);
|
targetElement.addEventListener("mousemove", autoExpand);
|
||||||
// Set up an observer to track attribute changes
|
// Set up an observer to track attribute changes
|
||||||
observer.observe(targetElement, {attributes: true, childList: true, subtree: true});
|
observer.observe(targetElement, { attributes: true, childList: true, subtree: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle events only inside the targetElement
|
// Handle events only inside the targetElement
|
||||||
let isKeyDownHandlerAttached = false;
|
let isKeyDownHandlerAttached = false;
|
||||||
@@ -661,7 +549,7 @@ onUiLoaded(async() => {
|
|||||||
function handleMoveKeyDown(e) {
|
function handleMoveKeyDown(e) {
|
||||||
|
|
||||||
// Disable key locks to make pasting from the buffer work correctly
|
// Disable key locks to make pasting from the buffer work correctly
|
||||||
if ((e.ctrlKey && e.code === 'KeyV') || (e.ctrlKey && event.code === 'KeyC') || e.code === "F5") {
|
if ((e.ctrlKey && e.code === 'KeyV') || (e.ctrlKey && e.code === 'KeyC') || e.code === "F5") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -713,11 +601,7 @@ onUiLoaded(async() => {
|
|||||||
if (isMoving && elemId === activeElement) {
|
if (isMoving && elemId === activeElement) {
|
||||||
updatePanPosition(e.movementX, e.movementY);
|
updatePanPosition(e.movementX, e.movementY);
|
||||||
targetElement.style.pointerEvents = "none";
|
targetElement.style.pointerEvents = "none";
|
||||||
|
targetElement.style.overflow = "visible";
|
||||||
if (isExtension) {
|
|
||||||
targetElement.style.overflow = "visible";
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
targetElement.style.pointerEvents = "auto";
|
targetElement.style.pointerEvents = "auto";
|
||||||
}
|
}
|
||||||
@@ -745,18 +629,13 @@ onUiLoaded(async() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isExtension) {
|
targetElement.addEventListener("mousemove", checkForOutBox);
|
||||||
targetElement.addEventListener("mousemove", checkForOutBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
window.addEventListener('resize', (e) => {
|
window.addEventListener('resize', (e) => {
|
||||||
resetZoom();
|
resetZoom();
|
||||||
|
|
||||||
if (isExtension) {
|
targetElement.isExpanded = false;
|
||||||
targetElement.isExpanded = false;
|
targetElement.isZoomed = false;
|
||||||
targetElement.isZoomed = false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gradioApp().addEventListener("mousemove", handleMoveByKey);
|
gradioApp().addEventListener("mousemove", handleMoveByKey);
|
||||||
|
|||||||
@@ -29,9 +29,7 @@ def attention_basic_with_sim(q, k, v, heads, mask=None):
|
|||||||
|
|
||||||
# force cast to fp32 to avoid overflowing
|
# force cast to fp32 to avoid overflowing
|
||||||
if _ATTN_PRECISION =="fp32":
|
if _ATTN_PRECISION =="fp32":
|
||||||
with torch.autocast(enabled=False, device_type = 'cuda'):
|
sim = einsum('b i d, b j d -> b i j', q.float(), k.float()) * scale
|
||||||
q, k = q.float(), k.float()
|
|
||||||
sim = einsum('b i d, b j d -> b i j', q, k) * scale
|
|
||||||
else:
|
else:
|
||||||
sim = einsum('b i d, b j d -> b i j', q, k) * scale
|
sim = einsum('b i d, b j d -> b i j', q, k) * scale
|
||||||
|
|
||||||
@@ -113,7 +111,6 @@ class SelfAttentionGuidance:
|
|||||||
m = model.clone()
|
m = model.clone()
|
||||||
|
|
||||||
attn_scores = None
|
attn_scores = None
|
||||||
mid_block_shape = None
|
|
||||||
|
|
||||||
# TODO: make this work properly with chunked batches
|
# TODO: make this work properly with chunked batches
|
||||||
# currently, we can only save the attn from one UNet call
|
# currently, we can only save the attn from one UNet call
|
||||||
@@ -136,7 +133,6 @@ class SelfAttentionGuidance:
|
|||||||
|
|
||||||
def post_cfg_function(args):
|
def post_cfg_function(args):
|
||||||
nonlocal attn_scores
|
nonlocal attn_scores
|
||||||
nonlocal mid_block_shape
|
|
||||||
uncond_attn = attn_scores
|
uncond_attn = attn_scores
|
||||||
|
|
||||||
sag_scale = scale
|
sag_scale = scale
|
||||||
|
|||||||
@@ -104,9 +104,7 @@ def attention_basic(q, k, v, heads, mask=None):
|
|||||||
|
|
||||||
# force cast to fp32 to avoid overflowing
|
# force cast to fp32 to avoid overflowing
|
||||||
if _ATTN_PRECISION =="fp32":
|
if _ATTN_PRECISION =="fp32":
|
||||||
with torch.autocast(enabled=False, device_type = 'cuda'):
|
sim = einsum('b i d, b j d -> b i j', q.float(), k.float()) * scale
|
||||||
q, k = q.float(), k.float()
|
|
||||||
sim = einsum('b i d, b j d -> b i j', q, k) * scale
|
|
||||||
else:
|
else:
|
||||||
sim = einsum('b i d, b j d -> b i j', q, k) * scale
|
sim = einsum('b i d, b j d -> b i j', q, k) * scale
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from ldm_patched.k_diffusion import sampling as k_diffusion_sampling
|
|||||||
from ldm_patched.unipc import uni_pc
|
from ldm_patched.unipc import uni_pc
|
||||||
import torch
|
import torch
|
||||||
import enum
|
import enum
|
||||||
|
import collections
|
||||||
from ldm_patched.modules import model_management
|
from ldm_patched.modules import model_management
|
||||||
import math
|
import math
|
||||||
from ldm_patched.modules import model_base
|
from ldm_patched.modules import model_base
|
||||||
@@ -61,9 +62,7 @@ def get_area_and_mult(conds, x_in, timestep_in):
|
|||||||
for c in model_conds:
|
for c in model_conds:
|
||||||
conditioning[c] = model_conds[c].process_cond(batch_size=x_in.shape[0], device=x_in.device, area=area)
|
conditioning[c] = model_conds[c].process_cond(batch_size=x_in.shape[0], device=x_in.device, area=area)
|
||||||
|
|
||||||
control = None
|
control = conds.get('control', None)
|
||||||
if 'control' in conds:
|
|
||||||
control = conds['control']
|
|
||||||
|
|
||||||
patches = None
|
patches = None
|
||||||
if 'gligen' in conds:
|
if 'gligen' in conds:
|
||||||
@@ -78,7 +77,8 @@ def get_area_and_mult(conds, x_in, timestep_in):
|
|||||||
|
|
||||||
patches['middle_patch'] = [gligen_patch]
|
patches['middle_patch'] = [gligen_patch]
|
||||||
|
|
||||||
return (input_x, mult, conditioning, area, control, patches)
|
cond_obj = collections.namedtuple('cond_obj', ['input_x', 'mult', 'conditioning', 'area', 'control', 'patches'])
|
||||||
|
return cond_obj(input_x, mult, conditioning, area, control, patches)
|
||||||
|
|
||||||
def cond_equal_size(c1, c2):
|
def cond_equal_size(c1, c2):
|
||||||
if c1 is c2:
|
if c1 is c2:
|
||||||
@@ -91,24 +91,24 @@ def cond_equal_size(c1, c2):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def can_concat_cond(c1, c2):
|
def can_concat_cond(c1, c2):
|
||||||
if c1[0].shape != c2[0].shape:
|
if c1.input_x.shape != c2.input_x.shape:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
#control
|
def objects_concatable(obj1, obj2):
|
||||||
if (c1[4] is None) != (c2[4] is None):
|
if (obj1 is None) != (obj2 is None):
|
||||||
return False
|
|
||||||
if c1[4] is not None:
|
|
||||||
if c1[4] is not c2[4]:
|
|
||||||
return False
|
return False
|
||||||
|
if obj1 is not None:
|
||||||
|
if obj1 is not obj2:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
#patches
|
if not objects_concatable(c1.control, c2.control):
|
||||||
if (c1[5] is None) != (c2[5] is None):
|
|
||||||
return False
|
return False
|
||||||
if (c1[5] is not None):
|
|
||||||
if c1[5] is not c2[5]:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return cond_equal_size(c1[2], c2[2])
|
if not objects_concatable(c1.patches, c2.patches):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return cond_equal_size(c1.conditioning, c2.conditioning)
|
||||||
|
|
||||||
def cond_cat(c_list):
|
def cond_cat(c_list):
|
||||||
c_crossattn = []
|
c_crossattn = []
|
||||||
@@ -184,13 +184,13 @@ def calc_cond_uncond_batch(model, cond, uncond, x_in, timestep, model_options):
|
|||||||
for x in to_batch:
|
for x in to_batch:
|
||||||
o = to_run.pop(x)
|
o = to_run.pop(x)
|
||||||
p = o[0]
|
p = o[0]
|
||||||
input_x += [p[0]]
|
input_x.append(p.input_x)
|
||||||
mult += [p[1]]
|
mult.append(p.mult)
|
||||||
c += [p[2]]
|
c.append(p.conditioning)
|
||||||
area += [p[3]]
|
area.append(p.area)
|
||||||
cond_or_uncond += [o[1]]
|
cond_or_uncond.append(o[1])
|
||||||
control = p[4]
|
control = p.control
|
||||||
patches = p[5]
|
patches = p.patches
|
||||||
|
|
||||||
batch_chunks = len(cond_or_uncond)
|
batch_chunks = len(cond_or_uncond)
|
||||||
input_x = torch.cat(input_x)
|
input_x = torch.cat(input_x)
|
||||||
|
|||||||
+1
-1
@@ -191,7 +191,7 @@ def encode_vae_inpaint(vae, pixels, mask):
|
|||||||
|
|
||||||
latent_mask = mask[:, None, :, :]
|
latent_mask = mask[:, None, :, :]
|
||||||
latent_mask = torch.nn.functional.interpolate(latent_mask, size=(H * 8, W * 8), mode="bilinear").round()
|
latent_mask = torch.nn.functional.interpolate(latent_mask, size=(H * 8, W * 8), mode="bilinear").round()
|
||||||
latent_mask = torch.nn.functional.max_pool2d(latent_mask, (8, 8)).round()
|
latent_mask = torch.nn.functional.max_pool2d(latent_mask, (8, 8)).round().to(latent)
|
||||||
|
|
||||||
return latent, latent_mask
|
return latent, latent_mask
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -269,9 +269,10 @@ def sdxl_encode_adm_patched(self, **kwargs):
|
|||||||
height = float(height) * positive_adm_scale
|
height = float(height) * positive_adm_scale
|
||||||
|
|
||||||
def embedder(number_list):
|
def embedder(number_list):
|
||||||
h = [self.embedder(torch.Tensor([number])) for number in number_list]
|
h = torch.tensor(number_list, dtype=torch.float32)
|
||||||
y = torch.flatten(torch.cat(h)).unsqueeze(dim=0).repeat(clip_pooled.shape[0], 1)
|
h = self.embedder(h)
|
||||||
return y
|
h = torch.flatten(h).unsqueeze(dim=0).repeat(clip_pooled.shape[0], 1)
|
||||||
|
return h
|
||||||
|
|
||||||
width, height = round_to_64(width), round_to_64(height)
|
width, height = round_to_64(width), round_to_64(height)
|
||||||
target_width, target_height = round_to_64(target_width), round_to_64(target_height)
|
target_width, target_height = round_to_64(target_width), round_to_64(target_height)
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ See also the common problems and troubleshoots [here](troubleshoot.md).
|
|||||||
|
|
||||||
In Colab, you can modify the last line to `!python entry_with_update.py --share` or `!python entry_with_update.py --preset anime --share` or `!python entry_with_update.py --preset realistic --share` for Fooocus Default/Anime/Realistic Edition.
|
In Colab, you can modify the last line to `!python entry_with_update.py --share` or `!python entry_with_update.py --preset anime --share` or `!python entry_with_update.py --preset realistic --share` for Fooocus Default/Anime/Realistic Edition.
|
||||||
|
|
||||||
Note that this Colab will disable refiner by default because Colab free's resource is relatively limited.
|
Note that this Colab will disable refiner by default because Colab free's resource is relatively limited (and some "big" features like image prompt may cause free-tier Colab to disconnect). We make sure that basic text-to-image is always working on free-tier Colab.
|
||||||
|
|
||||||
Thanks to [camenduru](https://github.com/camenduru)!
|
Thanks to [camenduru](https://github.com/camenduru)!
|
||||||
|
|
||||||
@@ -384,7 +384,7 @@ See also [About Forking and Promotion of Forks](https://github.com/lllyasviel/Fo
|
|||||||
|
|
||||||
## Thanks
|
## Thanks
|
||||||
|
|
||||||
Special thanks to [twri](https://github.com/twri) and [3Diva](https://github.com/3Diva) for creating additional SDXL styles available in Fooocus.
|
Special thanks to [twri](https://github.com/twri) and [3Diva](https://github.com/3Diva) for creating additional SDXL styles available in Fooocus. Thanks [daswer123](https://github.com/daswer123) for contributing the Canvas Zoom!
|
||||||
|
|
||||||
## Update Log
|
## Update Log
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
# 2.1.843
|
||||||
|
|
||||||
|
* Many improvements to Canvas. Thanks CanvasZoom author!
|
||||||
|
|
||||||
|
# 2.1.841
|
||||||
|
|
||||||
|
* Backend maintain.
|
||||||
|
* Fix some potential frozen after model mismatch.
|
||||||
|
* Fix crash when cfg=1 when using anime preset.
|
||||||
|
* Added some guidelines for troubleshoot the "CUDA kernel errors asynchronously" problem.
|
||||||
|
* Fix inpaint device problem in `--always-gpu` mode.
|
||||||
|
|
||||||
# 2.1.839
|
# 2.1.839
|
||||||
|
|
||||||
* Maintained some computation codes in backend for efficiency.
|
* Maintained some computation codes in backend for efficiency.
|
||||||
|
|||||||
Reference in New Issue
Block a user