fix select interaction with layers and wrong sampler
Signed-off-by: Victor Seiji Hariki <victorseijih@gmail.com>
This commit is contained in:
parent
35d5868854
commit
518e60f44a
9 changed files with 231 additions and 40 deletions
|
@ -318,6 +318,7 @@
|
|||
type="text/javascript"></script>
|
||||
|
||||
<!-- Content -->
|
||||
<script src="js/global.js" type="text/javascript"></script>
|
||||
<script src="js/prompt.js" type="text/javascript"></script>
|
||||
<script src="js/index.js" type="text/javascript"></script>
|
||||
|
||||
|
|
19
js/global.js
Normal file
19
js/global.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* Stores global variables without polluting the global namespace.
|
||||
*/
|
||||
|
||||
const global = {
|
||||
// Connection
|
||||
_connection: "offline",
|
||||
set connection(v) {
|
||||
this._connection = v;
|
||||
|
||||
toolbar &&
|
||||
toolbar.currentTool &&
|
||||
toolbar.currentTool.state.redraw &&
|
||||
toolbar.currentTool.state.redraw();
|
||||
},
|
||||
get connection() {
|
||||
return this._connection;
|
||||
},
|
||||
};
|
33
js/index.js
33
js/index.js
|
@ -340,7 +340,11 @@ async function testHostConnection() {
|
|||
},
|
||||
};
|
||||
|
||||
statuses[status] && statuses[status]();
|
||||
statuses[status] &&
|
||||
(() => {
|
||||
statuses[status]();
|
||||
global.connection = status;
|
||||
})();
|
||||
};
|
||||
|
||||
setConnectionStatus("before");
|
||||
|
@ -411,7 +415,7 @@ async function testHostConnection() {
|
|||
return status;
|
||||
};
|
||||
|
||||
await checkConnection(true);
|
||||
await checkConnection(!urlParams.has("noprompt"));
|
||||
|
||||
// On click, attempt to refresh
|
||||
connectionIndicator.onclick = async () => {
|
||||
|
@ -457,6 +461,8 @@ function clearPaintedMask() {
|
|||
|
||||
function march(bb, options = {}) {
|
||||
defaultOpt(options, {
|
||||
title: null,
|
||||
titleStyle: "#FFF5",
|
||||
style: "#FFFF",
|
||||
width: "2px",
|
||||
filter: null,
|
||||
|
@ -471,6 +477,7 @@ function march(bb, options = {}) {
|
|||
// Get temporary layer to draw marching ants
|
||||
const layer = imageCollection.registerLayer(null, {
|
||||
bb: expanded,
|
||||
category: "display",
|
||||
});
|
||||
layer.canvas.style.imageRendering = "pixelated";
|
||||
let offset = 0;
|
||||
|
@ -490,6 +497,16 @@ function drawMarchingAnts(ctx, bb, offset, options) {
|
|||
ctx.save();
|
||||
|
||||
ctx.clearRect(0, 0, bb.w + 2, bb.h + 2);
|
||||
|
||||
// Draw Tool Name
|
||||
if (bb.h > 40 && options.title) {
|
||||
ctx.font = `bold 20px Open Sans`;
|
||||
|
||||
ctx.textAlign = "left";
|
||||
ctx.fillStyle = options.titleStyle;
|
||||
ctx.fillText(options.title, 10, 30, bb.w);
|
||||
}
|
||||
|
||||
ctx.strokeStyle = options.style;
|
||||
ctx.strokeWidth = options.width;
|
||||
ctx.filter = options.filter;
|
||||
|
@ -920,6 +937,12 @@ async function getSamplers() {
|
|||
try {
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
samplerAutoComplete.onchange.on(({value}) => {
|
||||
stableDiffusionData.sampler_index = value;
|
||||
localStorage.setItem("openoutpaint/sampler", value);
|
||||
});
|
||||
|
||||
samplerAutoComplete.options = data.map((sampler) => ({
|
||||
name: sampler.name,
|
||||
value: sampler.name,
|
||||
|
@ -932,11 +955,7 @@ async function getSamplers() {
|
|||
samplerAutoComplete.value = data[0].name;
|
||||
localStorage.setItem("openoutpaint/sampler", samplerAutoComplete.value);
|
||||
}
|
||||
|
||||
samplerAutoComplete.onchange.on(({value}) => {
|
||||
stableDiffusionData.sampler_index = value;
|
||||
localStorage.setItem("openoutpaint/sampler", value);
|
||||
});
|
||||
stableDiffusionData.sampler_index = samplerAutoComplete.value;
|
||||
} catch (e) {
|
||||
console.warn("[index] Failed to fetch samplers");
|
||||
console.warn(e);
|
||||
|
|
|
@ -20,20 +20,25 @@ const imageCollection = layers.registerCollection(
|
|||
|
||||
const bgLayer = imageCollection.registerLayer("bg", {
|
||||
name: "Background",
|
||||
category: "background",
|
||||
});
|
||||
const imgLayer = imageCollection.registerLayer("image", {
|
||||
name: "Image",
|
||||
category: "image",
|
||||
ctxOptions: {desynchronized: true},
|
||||
});
|
||||
const maskPaintLayer = imageCollection.registerLayer("mask", {
|
||||
name: "Mask Paint",
|
||||
category: "mask",
|
||||
ctxOptions: {desynchronized: true},
|
||||
});
|
||||
const ovLayer = imageCollection.registerLayer("overlay", {
|
||||
name: "Overlay",
|
||||
category: "display",
|
||||
});
|
||||
const debugLayer = imageCollection.registerLayer("debug", {
|
||||
name: "Debug Layer",
|
||||
category: "display",
|
||||
});
|
||||
|
||||
const imgCanvas = imgLayer.canvas; // where dreams go
|
||||
|
|
|
@ -340,6 +340,7 @@ const layers = {
|
|||
* @param {object} options
|
||||
* @param {string} options.name
|
||||
* @param {?BoundingBox} options.bb
|
||||
* @param {string} [options.category]
|
||||
* @param {{w: number, h: number}} options.resolution
|
||||
* @param {?string} options.group
|
||||
* @param {object} options.after
|
||||
|
@ -362,6 +363,9 @@ const layers = {
|
|||
h: collection.size.h,
|
||||
},
|
||||
|
||||
// Category of the layer
|
||||
category: null,
|
||||
|
||||
// Resolution for layer
|
||||
resolution: null,
|
||||
|
||||
|
@ -451,6 +455,7 @@ const layers = {
|
|||
key,
|
||||
name: options.name,
|
||||
full,
|
||||
category: options.category,
|
||||
|
||||
state: new Proxy(
|
||||
{visible: true},
|
||||
|
@ -494,6 +499,10 @@ const layers = {
|
|||
return this._collection.origin;
|
||||
},
|
||||
|
||||
get hidden() {
|
||||
return !this.state.visible;
|
||||
},
|
||||
|
||||
/** Our canvas */
|
||||
canvas,
|
||||
ctx,
|
||||
|
|
|
@ -3,10 +3,17 @@
|
|||
*/
|
||||
|
||||
const uil = {
|
||||
/** @type {Observer<{uilayer: UILayer}>} */
|
||||
onactive: new Observer(),
|
||||
|
||||
_ui_layer_list: document.getElementById("layer-list"),
|
||||
layers: [],
|
||||
_active: null,
|
||||
set active(v) {
|
||||
this.onactive.emit({
|
||||
uilayer: v,
|
||||
});
|
||||
|
||||
Array.from(this._ui_layer_list.children).forEach((child) => {
|
||||
child.classList.remove("active");
|
||||
});
|
||||
|
@ -188,6 +195,7 @@ const uil = {
|
|||
_addLayer(group, name) {
|
||||
const layer = imageCollection.registerLayer(null, {
|
||||
name,
|
||||
category: "user",
|
||||
after:
|
||||
(this.layers.length > 0 && this.layers[this.layers.length - 1].layer) ||
|
||||
bgLayer,
|
||||
|
@ -285,11 +293,13 @@ const uil = {
|
|||
* @param {BoundingBox} bb The bouding box to get visible data from
|
||||
* @param {object} [options] Options
|
||||
* @param {boolean} [options.includeBg=false] Whether to include the background
|
||||
* @param {string[]} [options.categories] Categories of layers to consider visible
|
||||
* @returns {HTMLCanvasElement} The canvas element containing visible image data
|
||||
*/
|
||||
getVisible(bb, options = {}) {
|
||||
defaultOpt(options, {
|
||||
includeBg: false,
|
||||
categories: ["user", "image"],
|
||||
});
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
|
@ -297,22 +307,17 @@ const uil = {
|
|||
|
||||
canvas.width = bb.w;
|
||||
canvas.height = bb.h;
|
||||
if (options.includeBg)
|
||||
ctx.drawImage(bgLayer.canvas, bb.x, bb.y, bb.w, bb.h, 0, 0, bb.w, bb.h);
|
||||
this.layers.forEach((layer) => {
|
||||
if (!layer.hidden)
|
||||
ctx.drawImage(
|
||||
layer.layer.canvas,
|
||||
bb.x,
|
||||
bb.y,
|
||||
bb.w,
|
||||
bb.h,
|
||||
0,
|
||||
0,
|
||||
bb.w,
|
||||
bb.h
|
||||
);
|
||||
|
||||
const categories = new Set(options.categories);
|
||||
if (options.includeBg) categories.add("background");
|
||||
const layers = imageCollection._layers;
|
||||
|
||||
layers.reduceRight((_, layer) => {
|
||||
console.debug(layer.name, layer.category, layer.hidden);
|
||||
if (categories.has(layer.category) && !layer.hidden)
|
||||
ctx.drawImage(layer.canvas, bb.x, bb.y, bb.w, bb.h, 0, 0, bb.w, bb.h);
|
||||
});
|
||||
console.debug("END");
|
||||
|
||||
return canvas;
|
||||
},
|
||||
|
@ -336,6 +341,7 @@ commands.createCommand(
|
|||
|
||||
const layer = imageCollection.registerLayer(null, {
|
||||
name,
|
||||
category: "user",
|
||||
after:
|
||||
(uil.layers.length > 0 && uil.layers[uil.layers.length - 1].layer) ||
|
||||
bgLayer,
|
||||
|
|
|
@ -62,16 +62,19 @@ const colorBrushTool = () =>
|
|||
|
||||
state.drawLayer = imageCollection.registerLayer(null, {
|
||||
after: imgLayer,
|
||||
category: "display",
|
||||
ctxOptions: {willReadFrequently: true},
|
||||
});
|
||||
state.drawLayer.canvas.style.filter = "opacity(70%)";
|
||||
state.eraseLayer = imageCollection.registerLayer(null, {
|
||||
after: imgLayer,
|
||||
category: "processing",
|
||||
ctxOptions: {willReadFrequently: true},
|
||||
});
|
||||
state.eraseLayer.hide();
|
||||
state.eraseBackup = imageCollection.registerLayer(null, {
|
||||
after: imgLayer,
|
||||
category: "processing",
|
||||
});
|
||||
state.eraseBackup.hide();
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ const _monitorProgress = (bb, oncheck = null) => {
|
|||
// Get temporary layer to draw progress bar
|
||||
const layer = imageCollection.registerLayer(null, {
|
||||
bb: expanded,
|
||||
category: "display",
|
||||
});
|
||||
layer.canvas.style.opacity = "70%";
|
||||
|
||||
|
@ -293,6 +294,7 @@ const _generate = async (endpoint, request, bb, options = {}) => {
|
|||
// Layer for the images
|
||||
const layer = imageCollection.registerLayer(null, {
|
||||
after: maskPaintLayer,
|
||||
category: "display",
|
||||
});
|
||||
|
||||
const redraw = (url = images[at]) => {
|
||||
|
@ -1250,6 +1252,8 @@ const dreamTool = () =>
|
|||
),
|
||||
},
|
||||
{
|
||||
toolTextStyle:
|
||||
global.connection === "online" ? "#FFF5" : "#F555",
|
||||
reticleStyle: state.selection.inside ? "#F55" : "#FFF",
|
||||
sizeTextStyle: style,
|
||||
}
|
||||
|
@ -1277,6 +1281,7 @@ const dreamTool = () =>
|
|||
h: stableDiffusionData.height,
|
||||
},
|
||||
{
|
||||
toolTextStyle: global.connection === "online" ? "#FFF5" : "#F555",
|
||||
sizeTextStyle: style,
|
||||
}
|
||||
);
|
||||
|
@ -1305,8 +1310,19 @@ const dreamTool = () =>
|
|||
w: stableDiffusionData.width,
|
||||
h: stableDiffusionData.height,
|
||||
};
|
||||
|
||||
if (global.connection === "online") {
|
||||
dream_generate_callback(bb, resolution, state);
|
||||
} else {
|
||||
const stop = march(bb, {
|
||||
title: "offline",
|
||||
titleStyle: "#F555",
|
||||
style: "#F55",
|
||||
});
|
||||
setTimeout(stop, 2000);
|
||||
}
|
||||
state.selection.deselect();
|
||||
state.redraw();
|
||||
};
|
||||
state.erasecb = (evn, estate) => {
|
||||
if (state.selection.exists) {
|
||||
|
@ -1613,6 +1629,8 @@ const img2imgTool = () =>
|
|||
),
|
||||
},
|
||||
{
|
||||
toolTextStyle:
|
||||
global.connection === "online" ? "#FFF5" : "#F555",
|
||||
reticleStyle: state.selection.inside ? "#F55" : "#FFF",
|
||||
sizeTextStyle: style,
|
||||
}
|
||||
|
@ -1642,6 +1660,8 @@ const img2imgTool = () =>
|
|||
"Img2Img",
|
||||
{w: request.width, h: request.height},
|
||||
{
|
||||
toolTextStyle:
|
||||
global.connection === "online" ? "#FFF5" : "#F555",
|
||||
sizeTextStyle: style,
|
||||
}
|
||||
);
|
||||
|
@ -1766,7 +1786,16 @@ const img2imgTool = () =>
|
|||
w: stableDiffusionData.width,
|
||||
h: stableDiffusionData.height,
|
||||
};
|
||||
if (global.connection === "online") {
|
||||
dream_img2img_callback(bb, resolution, state);
|
||||
} else {
|
||||
const stop = march(bb, {
|
||||
title: "offline",
|
||||
titleStyle: "#F555",
|
||||
style: "#F55",
|
||||
});
|
||||
setTimeout(stop, 2000);
|
||||
}
|
||||
state.selection.deselect();
|
||||
state.redraw();
|
||||
};
|
||||
|
|
|
@ -20,6 +20,9 @@ const selectTransformTool = () =>
|
|||
keyboard.listen.onkeyclick.on(state.keyclickcb);
|
||||
keyboard.listen.onkeydown.on(state.keydowncb);
|
||||
|
||||
// Layer system handlers
|
||||
uil.onactive.on(state.uilayeractivecb);
|
||||
|
||||
// Registers keyboard shortcuts
|
||||
keyboard.onShortcut({ctrl: true, key: "KeyC"}, state.ctrlccb);
|
||||
keyboard.onShortcut({ctrl: true, key: "KeyV"}, state.ctrlvcb);
|
||||
|
@ -42,6 +45,8 @@ const selectTransformTool = () =>
|
|||
keyboard.deleteShortcut(state.ctrlvcb, "KeyV");
|
||||
keyboard.deleteShortcut(state.ctrlxcb, "KeyX");
|
||||
|
||||
uil.onactive.clear(state.uilayeractivecb);
|
||||
|
||||
// Clear any selections
|
||||
state.reset();
|
||||
|
||||
|
@ -61,6 +66,7 @@ const selectTransformTool = () =>
|
|||
state.useClipboard = !!(
|
||||
navigator.clipboard && navigator.clipboard.write
|
||||
); // Use it by default if supported
|
||||
state.selectionPeekOpacity = 40;
|
||||
|
||||
state.original = null;
|
||||
state.dragging = null;
|
||||
|
@ -78,22 +84,33 @@ const selectTransformTool = () =>
|
|||
|
||||
// Some things to easy request for a redraw
|
||||
state.lastMouseTarget = null;
|
||||
state.lastMouseMove = null;
|
||||
state.lastMouseMove = {x: 0, y: 0};
|
||||
|
||||
state.redraw = () => {
|
||||
ovLayer.clear();
|
||||
state.movecb(state.lastMouseMove);
|
||||
};
|
||||
|
||||
state.uilayeractivecb = ({uilayer}) => {
|
||||
if (state.originalDisplayLayer) {
|
||||
state.originalDisplayLayer.moveAfter(uilayer.layer);
|
||||
}
|
||||
};
|
||||
|
||||
// Clears selection and make things right
|
||||
state.reset = () => {
|
||||
if (state.selected)
|
||||
uil.ctx.drawImage(
|
||||
state.reset = (erase = false) => {
|
||||
if (state.selected && !erase)
|
||||
state.originalLayer.ctx.drawImage(
|
||||
state.original.image,
|
||||
state.original.x,
|
||||
state.original.y
|
||||
);
|
||||
|
||||
if (state.originalDisplayLayer) {
|
||||
imageCollection.deleteLayer(state.originalDisplayLayer);
|
||||
state.originalDisplayLayer = null;
|
||||
}
|
||||
|
||||
if (state.dragging) state.dragging = null;
|
||||
else state.selected = null;
|
||||
|
||||
|
@ -254,6 +271,8 @@ const selectTransformTool = () =>
|
|||
};
|
||||
|
||||
// Draw Image
|
||||
ovCtx.save();
|
||||
ovCtx.filter = `opacity(${state.selectionPeekOpacity}%)`;
|
||||
ovCtx.drawImage(
|
||||
state.selected.image,
|
||||
0,
|
||||
|
@ -265,6 +284,22 @@ const selectTransformTool = () =>
|
|||
state.selected.w,
|
||||
state.selected.h
|
||||
);
|
||||
ovCtx.restore();
|
||||
|
||||
state.originalDisplayLayer.clear();
|
||||
state.originalDisplayLayer.ctx.save();
|
||||
state.originalDisplayLayer.ctx.drawImage(
|
||||
state.selected.image,
|
||||
0,
|
||||
0,
|
||||
state.selected.image.width,
|
||||
state.selected.image.height,
|
||||
state.selected.x,
|
||||
state.selected.y,
|
||||
state.selected.w,
|
||||
state.selected.h
|
||||
);
|
||||
state.originalDisplayLayer.ctx.restore();
|
||||
|
||||
// Draw selection box
|
||||
uiCtx.strokeStyle = "#FFF";
|
||||
|
@ -337,7 +372,8 @@ const selectTransformTool = () =>
|
|||
state.clickcb = (evn) => {
|
||||
if (
|
||||
!state.original ||
|
||||
(state.original.x === state.selected.x &&
|
||||
(state.originalLayer === uil.layer &&
|
||||
state.original.x === state.selected.x &&
|
||||
state.original.y === state.selected.y &&
|
||||
state.original.w === state.selected.w &&
|
||||
state.original.h === state.selected.h)
|
||||
|
@ -348,16 +384,15 @@ const selectTransformTool = () =>
|
|||
|
||||
// If something is selected, commit changes to the canvas
|
||||
if (state.selected) {
|
||||
uil.ctx.drawImage(
|
||||
state.originalLayer.ctx.drawImage(
|
||||
state.selected.image,
|
||||
state.original.x,
|
||||
state.original.y
|
||||
);
|
||||
commands.runCommand(
|
||||
"eraseImage",
|
||||
"Image Transform Erase",
|
||||
state.original
|
||||
);
|
||||
commands.runCommand("eraseImage", "Image Transform Erase", {
|
||||
...state.original,
|
||||
ctx: state.originalLayer.ctx,
|
||||
});
|
||||
commands.runCommand("drawImage", "Image Transform Draw", {
|
||||
image: state.selected.image,
|
||||
x: Math.round(state.selected.x),
|
||||
|
@ -365,10 +400,7 @@ const selectTransformTool = () =>
|
|||
w: Math.round(state.selected.w),
|
||||
h: Math.round(state.selected.h),
|
||||
});
|
||||
state.original = null;
|
||||
state.selected = null;
|
||||
|
||||
state.redraw();
|
||||
state.reset(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -451,6 +483,11 @@ const selectTransformTool = () =>
|
|||
x,
|
||||
y
|
||||
);
|
||||
state.originalLayer = uil.layer;
|
||||
state.originalDisplayLayer = imageCollection.registerLayer(null, {
|
||||
after: uil.layer,
|
||||
category: "select-display",
|
||||
});
|
||||
|
||||
// Cut out selected portion of the image for manipulation
|
||||
const cvs = document.createElement("canvas");
|
||||
|
@ -622,6 +659,22 @@ const selectTransformTool = () =>
|
|||
if (!(navigator.clipboard && navigator.clipboard.write))
|
||||
clipboardCheckbox.checkbox.disabled = true; // Disable if not available
|
||||
|
||||
// Selection Peek Opacity
|
||||
state.ctxmenu.selectionPeekOpacitySlider = _toolbar_input.slider(
|
||||
state,
|
||||
"selectionPeekOpacity",
|
||||
"Peek Opacity",
|
||||
{
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 10,
|
||||
textStep: 1,
|
||||
cb: () => {
|
||||
state.redraw();
|
||||
},
|
||||
}
|
||||
).slider;
|
||||
|
||||
// Some useful actions to do with selection
|
||||
const actionArray = document.createElement("div");
|
||||
actionArray.classList.add("button-array");
|
||||
|
@ -629,7 +682,7 @@ const selectTransformTool = () =>
|
|||
// Save button
|
||||
const saveSelectionButton = document.createElement("button");
|
||||
saveSelectionButton.classList.add("button", "tool");
|
||||
saveSelectionButton.textContent = "Save";
|
||||
saveSelectionButton.textContent = "Save Sel.";
|
||||
saveSelectionButton.title = "Saves Selection";
|
||||
saveSelectionButton.onclick = () => {
|
||||
downloadCanvas({
|
||||
|
@ -655,25 +708,72 @@ const selectTransformTool = () =>
|
|||
actionArray.appendChild(saveSelectionButton);
|
||||
actionArray.appendChild(createResourceButton);
|
||||
|
||||
// Some useful actions to do with selection
|
||||
const visibleActionArray = document.createElement("div");
|
||||
visibleActionArray.classList.add("button-array");
|
||||
|
||||
// Save Visible button
|
||||
const saveVisibleSelectionButton = document.createElement("button");
|
||||
saveVisibleSelectionButton.classList.add("button", "tool");
|
||||
saveVisibleSelectionButton.textContent = "Save Vis.";
|
||||
saveVisibleSelectionButton.title = "Saves Visible Selection";
|
||||
saveVisibleSelectionButton.onclick = () => {
|
||||
const canvas = uil.getVisible(state.selected, {
|
||||
categories: ["image", "user", "select-display"],
|
||||
});
|
||||
downloadCanvas({
|
||||
cropToContent: false,
|
||||
canvas,
|
||||
});
|
||||
};
|
||||
|
||||
// Save Visible as Resource Button
|
||||
const createVisibleResourceButton = document.createElement("button");
|
||||
createVisibleResourceButton.classList.add("button", "tool");
|
||||
createVisibleResourceButton.textContent = "Vis. to Res.";
|
||||
createVisibleResourceButton.title =
|
||||
"Saves Visible Selection as a Resource";
|
||||
createVisibleResourceButton.onclick = () => {
|
||||
const canvas = uil.getVisible(state.selected, {
|
||||
categories: ["image", "user", "select-display"],
|
||||
});
|
||||
const image = document.createElement("img");
|
||||
image.src = canvas.toDataURL();
|
||||
image.onload = () => {
|
||||
tools.stamp.state.addResource("Selection Resource", image);
|
||||
tools.stamp.enable();
|
||||
};
|
||||
};
|
||||
|
||||
visibleActionArray.appendChild(saveVisibleSelectionButton);
|
||||
visibleActionArray.appendChild(createVisibleResourceButton);
|
||||
|
||||
// Disable buttons (if nothing is selected)
|
||||
state.ctxmenu.disableButtons = () => {
|
||||
saveSelectionButton.disabled = true;
|
||||
createResourceButton.disabled = true;
|
||||
saveVisibleSelectionButton.disabled = true;
|
||||
createVisibleResourceButton.disabled = true;
|
||||
};
|
||||
|
||||
// Disable buttons (if something is selected)
|
||||
state.ctxmenu.enableButtons = () => {
|
||||
saveSelectionButton.disabled = "";
|
||||
createResourceButton.disabled = "";
|
||||
saveVisibleSelectionButton.disabled = "";
|
||||
createVisibleResourceButton.disabled = "";
|
||||
};
|
||||
state.ctxmenu.actionArray = actionArray;
|
||||
state.ctxmenu.visibleActionArray = visibleActionArray;
|
||||
}
|
||||
menu.appendChild(state.ctxmenu.snapToGridLabel);
|
||||
menu.appendChild(document.createElement("br"));
|
||||
menu.appendChild(state.ctxmenu.keepAspectRatioLabel);
|
||||
menu.appendChild(document.createElement("br"));
|
||||
menu.appendChild(state.ctxmenu.useClipboardLabel);
|
||||
menu.appendChild(state.ctxmenu.selectionPeekOpacitySlider);
|
||||
menu.appendChild(state.ctxmenu.actionArray);
|
||||
menu.appendChild(state.ctxmenu.visibleActionArray);
|
||||
},
|
||||
shortcut: "S",
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue