Added hotkeys for change brush size, increased the maximum brush size fixed the bug
parent
120f46efe6
commit
36762c013e
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 @@
|
|||
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
Binary file not shown.
|
|
@ -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"),
|
||||
|
|
|
|||
Loading…
Reference in New Issue