Added hotkeys for change brush size, increased the maximum brush size fixed the bug

Gradio-v4-updates
Danil Boldyrev 2023-09-26 19:08:17 +03:00
parent 120f46efe6
commit 36762c013e
6 changed files with 1148 additions and 1112 deletions

View File

@ -30,10 +30,12 @@ if os.path.isfile(config_path):
# Check if "canvas-zoom" is in the list of disabled_extensions
if "canvas-zoom" in config.get('disabled_extensions', []):
launch.run(f'"{python}" -m pip install --force-reinstall --no-deps gradio=={gradio_version}', desc=f"Uninstalling modified gradio for canvas-zoom", errdesc=f"Couldn't uninstall canvas-zoom", live=False)
os.remove(script_path)
# Check if disable_all_extensions is not "none"
if config.get('disable_all_extensions', 'none') == 'all':
launch.run(f'"{python}" -m pip install --force-reinstall --no-deps gradio=={gradio_version}', desc=f"Uninstalling modified gradio for canvas-zoom", errdesc=f"Couldn't uninstall canvas-zoom", live=False)
os.remove(script_path)
# Check if the folder exists
if not os.path.exists(canvasZoomPath) and gradio_version is not None:

View File

@ -22,10 +22,11 @@
export let container_height = 200;
export let shape;
if(window.maskOpacity) mask_opacity = window.maskOpacity
if (window.maskOpacity) mask_opacity = window.maskOpacity;
let colorPickerEnabled = localStorage.setItem("colorPickerEnable", false);
let transparentMask = localStorage.setItem("transparentMask", false);
let posX = 0;
let posY = 0;
let lineStartPoint = null;
@ -724,7 +725,7 @@
} else if (brush_radius > 20) {
ctx.lineWidth = 2; // Change the value to control the thickness of the border
} else {
ctx.lineWidth = 1;
ctx.lineWidth = 2;
}
}

View File

@ -15,6 +15,13 @@
export let mode: "mask" | "other" = "other";
export let brush_color = "#000";
let maxBrushSize = window.maxBrushSize;
if (maxBrushSize) {
maxBrushSize = maxBrushSize / 100;
} else {
maxBrushSize = 1;
}
brush_color_store.subscribe(($brush_color) => {
brush_color = $brush_color;
});
@ -35,7 +42,7 @@
bind:value={brush_radius}
type="range"
min={0.5 * (img_width / width)}
max={75 * (img_width / width)}
max={75 * (img_width / width) * maxBrushSize}
/>
{/if}
</span>

View File

@ -1,10 +1,10 @@
/**
/**
* onUiLoaded is a function that is called when the UI is loaded.
* @param {Function} callback - The function to be called when the UI is loaded.
* @returns {void}
* @example
*/
onUiLoaded(async () => {
onUiLoaded(async () => {
const elementIDs = {
img2img: "#img2img_img2img_tab",
sketch: "#img2img_sketch",
@ -18,7 +18,7 @@
sendToInpainBtn: "#image_buttons_img2img #inpaint_tab",
sendToInpainBtnT2I: "#image_buttons_txt2img #inpaint_tab",
sendToInpainBtnNew: "#img2img_send_to_inpaint",
sendToInpainBtnT2INew : "#txt2img_send_to_inpaint"
sendToInpainBtnT2INew: "#txt2img_send_to_inpaint"
};
const tabNameToElementId = {
"Inpaint sketch": elementIDs.inpaintSketch,
@ -168,11 +168,13 @@
const userValue = hotkeysConfigOpts[key];
const defaultValue = defaultHotkeysConfig[key];
if(key === "canvas_zoom_undo_extra_key") {
if (key === "canvas_zoom_undo_extra_key") {
result[key] = userValue
continue
}
// if(key === "canvas_zoom_inc_brush_size" || key === "canvas_zoom_dec_brush_size")
if (userValue === undefined || invalidTypes.has(typeof userValue) || userValue.startsWith("#") || userValue === "disable") {
result[key] = userValue === undefined ? defaultValue : userValue;
} else if (isValidHotkey(userValue)) {
@ -185,11 +187,15 @@
console.error(`Hotkey: ${formatHotkeyForDisplay(userValue)} for ${key} is repeated and conflicts with another hotkey. The default hotkey is used: ${formatHotkeyForDisplay(defaultValue)}`);
result[key] = defaultValue;
}
} else {
if (key === "canvas_zoom_inc_brush_size" || key === "canvas_zoom_dec_brush_size") {
result[key] = defaultValue;
} else {
console.error(`Hotkey: ${formatHotkeyForDisplay(userValue)} for ${key} is not valid. The default hotkey is used: ${formatHotkeyForDisplay(defaultValue)}`);
result[key] = defaultValue;
}
}
}
return result;
};
@ -292,7 +298,7 @@
canvas_hotkey_zoom: "Alt",
canvas_hotkey_adjust: "Ctrl",
canvas_zoom_undo_extra_key: "Ctrl",
canvas_zoom_hotkey_undo : "KeyZ",
canvas_zoom_hotkey_undo: "KeyZ",
canvas_hotkey_reset: "KeyR",
canvas_hotkey_fullscreen: "KeyS",
canvas_hotkey_move: "KeyF",
@ -302,9 +308,11 @@
canvas_zoom_hotkey_dropper: "KeyA",
canvas_zoom_hotkey_fill: "KeyH",
canvas_zoom_hotkey_transparency: "KeyC",
canvas_zoom_inc_brush_size: "BracketRight",
canvas_zoom_dec_brush_size: "BracketLeft",
canvas_zoom_hide_btn: true,
canvas_show_tooltip: true,
canvas_auto_expand : true,
canvas_auto_expand: true,
canvas_zoom_mask_clear: true,
canvas_zoom_enable_integration: true,
canvas_zoom_brush_opacity: false,
@ -314,6 +322,7 @@
canvas_zoom_add_buttons: false,
canvas_zoom_inpaint_brushcolor: "#000000",
canvas_zoom_transparency_level: 70,
canvas_zoom_brush_size: 200,
canvas_zoom_disabled_functions: [],
};
@ -330,10 +339,12 @@
"Dropper": "canvas_zoom_hotkey_dropper",
"Fill": "canvas_zoom_hotkey_fill",
"Transparency Mode": "canvas_zoom_hotkey_transparency",
// "Increase brush size": "canvas_hotkey_inc_brush_size",
// "Decrease brush size": "canvas_hotkey_dec_brush_size",
};
// Disable funcs
const preHotkeysConfig = disableFunctions(hotkeysConfigOpts,hotkeysConfigOpts.canvas_zoom_disabled_functions)
const preHotkeysConfig = disableFunctions(hotkeysConfigOpts, hotkeysConfigOpts.canvas_zoom_disabled_functions)
// Disable unnecessary user functions
const hotkeysConfig = createHotkeyConfig(defaultHotkeysConfig, preHotkeysConfig);
@ -346,6 +357,7 @@
let brushOpacity = 1;
window.maskOpacity = hotkeysConfig.canvas_zoom_transparency_level / 100
window.maxBrushSize = hotkeysConfig.canvas_zoom_brush_size
// Element data holder
const elemData = {};
@ -399,13 +411,13 @@
// img2img_sketch_default_brush_color, img2img_inpaint_mask_brush_color.
if(canvasColor.img2img_inpaint_mask_brush_color){
if (canvasColor.img2img_inpaint_mask_brush_color) {
localStorage.setItem("brush_color", canvasColor.img2img_inpaint_mask_brush_color);
} else {
localStorage.setItem("brush_color", hotkeysConfig.canvas_zoom_inpaint_brushcolor);
}
if(canvasColor.img2img_sketch_default_brush_color){
if (canvasColor.img2img_sketch_default_brush_color) {
localStorage.setItem("sketch_brush_color", canvasColor.img2img_sketch_default_brush_color);
}
@ -697,6 +709,7 @@
if (input) {
input.click();
if (!withoutValue) {
const maxValue = parseFloat(input.getAttribute("max")) || 100;
const changeAmount = maxValue * (percentage / 100);
const newValue =
@ -759,7 +772,7 @@
let { zoomLevel } = elemData[elemId];
if(!zoomLevel) {
if (!zoomLevel) {
zoomLevel = 1;
elemData[elemId].zoomLevel = zoomLevel;
}
@ -963,7 +976,7 @@
const isAuxButton = e.button >= 3;
const activeTab = activeElement;
if(hotkeysConfig.canvas_zoom_undo_extra_key === "None" || isAuxButton){
if (hotkeysConfig.canvas_zoom_undo_extra_key === "None" || isAuxButton) {
isCtrlPressed = true
} else {
if (!isModifierKey(e, hotkeysConfig.canvas_zoom_undo_extra_key)) return;
@ -1092,6 +1105,8 @@
[hotkeysConfig.canvas_zoom_hotkey_fill]: fillCanvasWithColor,
[hotkeysConfig.canvas_zoom_hotkey_transparency]: toggleOpacityMode,
[hotkeysConfig.canvas_zoom_hotkey_undo]: undoLastAction,
[hotkeysConfig.canvas_zoom_inc_brush_size]: () => adjustBrushSize(elemId, -5, false),
[hotkeysConfig.canvas_zoom_dec_brush_size]: () => adjustBrushSize(elemId, 5, false),
};
const action = hotkeyActions[event.code];
@ -1116,16 +1131,16 @@
// We make the transparency of the brush and the transparency of the mask the same
function matchBrushOpacity(){
function matchBrushOpacity() {
const canvas = document.querySelector(`${elementIDs.inpaint} canvas[key="interface"]`);
if(canvas && brushOpacity !== hotkeysConfig.canvas_zoom_transparency_level){
if (canvas && brushOpacity !== hotkeysConfig.canvas_zoom_transparency_level) {
setBrushOpacity(100 - hotkeysConfig.canvas_zoom_transparency_level)
brushOpacity = hotkeysConfig.canvas_zoom_transparency_level
}
}
if(hotkeysConfig.canvas_zoom_brush_opacity){
targetElement.addEventListener("mousemove",matchBrushOpacity)
if (hotkeysConfig.canvas_zoom_brush_opacity) {
targetElement.addEventListener("mousemove", matchBrushOpacity)
}
// Simulation of the function to put a long image into the screen.
@ -1162,10 +1177,10 @@
});
// Apply auto expand if enabled
if (hotkeysConfig.canvas_auto_expand && (!window.applyZoomAndPan || isExtension )) {
if (hotkeysConfig.canvas_auto_expand && (!window.applyZoomAndPan || isExtension)) {
targetElement.addEventListener("mousemove", autoExpand);
// 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 });
}
targetElement.addEventListener("mousemove", getMousePosition);
@ -1199,6 +1214,14 @@
}
};
targetElement.addEventListener("mouseout", () => {
const canvas = targetElement.querySelector(`${elemId} canvas`)
if (canvas) {
hideCanvasButtons(false)
}
})
/**
* Handles mouse leave events to remove key down events and reset active element.
*/
@ -1282,9 +1305,9 @@
*/
const updatePanPosition = (movementX, movementY) => {
let {zoomLevel, panX, panY} = elemData[elemId];
let { zoomLevel, panX, panY } = elemData[elemId];
if(typeof zoomLevel === 'undefined' || typeof panX === 'undefined' || typeof panY === 'undefined') {
if (typeof zoomLevel === 'undefined' || typeof panX === 'undefined' || typeof panY === 'undefined') {
zoomLevel = 1;
panX = 0;
panY = 0;
@ -1401,9 +1424,9 @@
})
}
applyZoomAndPan(elementIDs.sketch,false);
applyZoomAndPan(elementIDs.inpaint,false);
applyZoomAndPan(elementIDs.inpaintSketch,false);
applyZoomAndPan(elementIDs.sketch, false);
applyZoomAndPan(elementIDs.inpaint, false);
applyZoomAndPan(elementIDs.inpaintSketch, false);
// Make Canvas zoom func global, like in build in extension
// Temp disable have bugs :(
@ -1417,7 +1440,7 @@
* @param {Array} elementIDs - An array of element IDs to which the event listeners should be added.
*/
// Make the function global so that other extensions can take advantage of this solution
const applyZoomAndPanIntegration = async(id, elementIDs) => {
const applyZoomAndPanIntegration = async (id, elementIDs) => {
const mainEl = document.querySelector(id);
if (id.toLocaleLowerCase() === "none") {
for (const elementID of elementIDs) {
@ -1429,13 +1452,13 @@
}
if (!mainEl) return;
mainEl.addEventListener("click", async() => {
mainEl.addEventListener("click", async () => {
for (const elementID of elementIDs) {
const el = await waitForElement(elementID);
if (!el) break;
applyZoomAndPan(elementID);
}
}, {once: true});
}, { once: true });
};
@ -1467,7 +1490,7 @@
}
// The controlNet author has implemented this functionality in new versions
if(!window.applyZoomAndPanIntegration && integrateControlNet){
if (!window.applyZoomAndPanIntegration && integrateControlNet) {
// Add integration with ControlNet txt2img Tabs
applyZoomAndPanIntegration("#txt2img_controlnet",
Array.from({ length: 10 }, (_, i) => `#txt2img_controlnet_ControlNet-${i}_input_image`));
@ -1483,4 +1506,4 @@
});
});

View File

@ -9,6 +9,8 @@ shared.options_templates.update(shared.options_section(('canvas_zoom', "Canvas Z
"canvas_hotkey_move": shared.OptionInfo("F", "Moving the canvas"),
"canvas_hotkey_fullscreen": shared.OptionInfo("S", "Fullscreen Mode, maximizes the picture so that it fits into the screen and stretches it to its full width "),
"canvas_hotkey_reset": shared.OptionInfo("R", "Reset zoom and canvas positon"),
"canvas_zoom_inc_brush_size": shared.OptionInfo("]", "Increase brush size"),
"canvas_zoom_dec_brush_size": shared.OptionInfo("[", "Decrease brush size"),
"canvas_zoom_hotkey_open_colorpanel": shared.OptionInfo("Q", "Quickly open the color panel"),
"canvas_zoom_hotkey_pin_colorpanel": shared.OptionInfo("T", "Attach the color panel to the mouse "),
"canvas_zoom_hotkey_dropper": shared.OptionInfo("A", "Toggle dropper ( Works in Sketch and Inpaint Sketch )"),
@ -20,9 +22,10 @@ shared.options_templates.update(shared.options_section(('canvas_zoom', "Canvas Z
"canvas_zoom_mask_clear": shared.OptionInfo(True, "Enable mask clearing in inpaint after any picture is moved in inpaint via buttons"),
"canvas_auto_expand": shared.OptionInfo(True, "Automatic expansion of an image that does not fit completely within the canvas area, similar to manual S and R entry"),
"canvas_zoom_enable_integration": shared.OptionInfo(True, "Enable integration with ControlNet, Regional Prompter and Latent Couple(Two Shot), Inpaint Anything"),
"canvas_zoom_brush_size": shared.OptionInfo(200, "Increase % of the maximum brush size", gr.Slider, {"minimum": 100, "maximum": 1000, "step": 50}),
"canvas_zoom_transparency_level": shared.OptionInfo(70, "Opacity level in inpaint.Works with webui 1.6 otherwise this setting will adjust the transparency in transparency mode from the extension", gr.Slider, {"minimum": 10, "maximum": 100, "step": 5}),
"canvas_zoom_brush_opacity": shared.OptionInfo(False, "Makes the brush the same transparency as the mask"),
"canvas_zoom_inpaint_prevent_work": shared.OptionInfo(False, "Always prevent inpainting models work on txt2img tab by default"),
# "canvas_zoom_inpaint_prevent_work": shared.OptionInfo(False, "Always prevent inpainting models work on txt2img tab by default"), #TODO
"canvas_zoom_inpaint_label": shared.OptionInfo(True, "INPAINT - Show the label next to the model selection when you select an inpaint model"),
"canvas_zoom_inpaint_warning": shared.OptionInfo(True, "INPAINT - Show warning when you try to use inpaint model in txt2img mode(The model name must contain 'inpainting' or 'inpaint'.)"),
"canvas_zoom_inpaint_change_btn_color": shared.OptionInfo(False, "INPAINT - Enable button color change when inpaint model is selected"),