layers... now exist?
Signed-off-by: Victor Seiji Hariki <victorseijih@gmail.com>
This commit is contained in:
parent
583f9245b6
commit
aec096b856
10 changed files with 128 additions and 28 deletions
16
css/ui/layers.css
Normal file
16
css/ui/layers.css
Normal file
|
@ -0,0 +1,16 @@
|
|||
#layer-list {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
#layer-list .ui-layer {
|
||||
cursor: pointer;
|
||||
background-color: #fff3;
|
||||
}
|
||||
|
||||
#layer-list .ui-layer:hover {
|
||||
filter: brightness(90%);
|
||||
}
|
||||
|
||||
#layer-list .ui-layer:active {
|
||||
filter: brightness(80%);
|
||||
}
|
15
index.html
15
index.html
|
@ -12,6 +12,7 @@
|
|||
<link href="css/ui/generic.css" rel="stylesheet" />
|
||||
|
||||
<link href="css/ui/history.css" rel="stylesheet" />
|
||||
<link href="css/ui/layers.css" rel="stylesheet" />
|
||||
<link href="css/ui/toolbar.css" rel="stylesheet" />
|
||||
|
||||
<!-- Tool Specific CSS -->
|
||||
|
@ -194,11 +195,22 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Layers -->
|
||||
<div
|
||||
id="ui-layers"
|
||||
class="floating-window"
|
||||
style="right: 10px; bottom: 10px">
|
||||
<div class="draggable floating-window-title">Layers</div>
|
||||
<div class="menu-container" style="min-width: 200px">
|
||||
<div id="layer-list" class="layer-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Toolbar -->
|
||||
<div
|
||||
id="ui-toolbar"
|
||||
class="floating-window toolbar"
|
||||
style="right: 10px; top: 350px">
|
||||
style="right: 270px; top: 10px">
|
||||
<div class="draggable handle">
|
||||
<span class="line"></span>
|
||||
</div>
|
||||
|
@ -225,6 +237,7 @@
|
|||
<!-- Content -->
|
||||
<script src="js/index.js" type="text/javascript"></script>
|
||||
<script src="js/ui/floating/history.js" type="text/javascript"></script>
|
||||
<script src="js/ui/floating/layers.js" type="text/javascript"></script>
|
||||
|
||||
<!-- Load Tools -->
|
||||
<script src="js/ui/tool/dream.js" type="text/javascript"></script>
|
||||
|
|
|
@ -334,8 +334,8 @@ function newImage(evt) {
|
|||
commands.runCommand("eraseImage", "Clear Canvas", {
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: imgCanvas.width,
|
||||
h: imgCanvas.height,
|
||||
w: uiLayers.active.canvas.width,
|
||||
h: uiLayers.active.canvas.height,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -765,7 +765,7 @@ async function upscaleAndDownload() {
|
|||
// get cropped canvas, send it to upscaler, download result
|
||||
var upscale_factor = 2; // TODO: make this a user input 1.x - 4.0 or something
|
||||
var upscaler = document.getElementById("upscalers").value;
|
||||
var croppedCanvas = cropCanvas(imgCanvas);
|
||||
var croppedCanvas = cropCanvas(uiLayers.active.canvas);
|
||||
if (croppedCanvas != null) {
|
||||
var upscaler = document.getElementById("upscalers").value;
|
||||
var url =
|
||||
|
|
|
@ -52,7 +52,17 @@ const getVisible = (bb) => {
|
|||
canvas.width = bb.w;
|
||||
canvas.height = bb.h;
|
||||
ctx.drawImage(bgLayer.canvas, bb.x, bb.y, bb.w, bb.h, 0, 0, bb.w, bb.h);
|
||||
ctx.drawImage(imgCanvas, bb.x, bb.y, bb.w, bb.h, 0, 0, bb.w, bb.h);
|
||||
ctx.drawImage(
|
||||
uiLayers.active.canvas,
|
||||
bb.x,
|
||||
bb.y,
|
||||
bb.w,
|
||||
bb.h,
|
||||
0,
|
||||
0,
|
||||
bb.w,
|
||||
bb.h
|
||||
);
|
||||
|
||||
return canvas;
|
||||
};
|
||||
|
|
|
@ -192,7 +192,7 @@ commands.createCommand(
|
|||
|
||||
// Check if we have state
|
||||
if (!state.context) {
|
||||
const context = options.ctx || imgCtx;
|
||||
const context = options.ctx || uiLayers.active.ctx;
|
||||
state.context = context;
|
||||
|
||||
// Saving what was in the canvas before the command
|
||||
|
@ -252,7 +252,7 @@ commands.createCommand(
|
|||
|
||||
// Check if we have state
|
||||
if (!state.context) {
|
||||
const context = options.ctx || imgCtx;
|
||||
const context = options.ctx || uiLayers.active.ctx;
|
||||
state.context = context;
|
||||
|
||||
// Saving what was in the canvas before the command
|
||||
|
|
|
@ -250,14 +250,14 @@ function cropCanvas(sourceCanvas, options = {}) {
|
|||
*
|
||||
* @param {Object} options - Optional Information
|
||||
* @param {boolean} [options.cropToContent] - If we wish to crop to content first (default: true)
|
||||
* @param {HTMLCanvasElement} [options.canvas] - The source canvas (default: imgCanvas)
|
||||
* @param {HTMLCanvasElement} [options.canvas] - The source canvas (default: uiLayers.active.canvas)
|
||||
* @param {string} [options.filename] - The filename to save as (default: '[ISO date] [Hours] [Minutes] [Seconds] openOutpaint image.png').\
|
||||
* If null, opens image in new tab.
|
||||
*/
|
||||
function downloadCanvas(options = {}) {
|
||||
defaultOpt(options, {
|
||||
cropToContent: true,
|
||||
canvas: imgCanvas,
|
||||
canvas: uiLayers.active.canvas,
|
||||
filename:
|
||||
new Date()
|
||||
.toISOString()
|
||||
|
|
56
js/ui/floating/layers.js
Normal file
56
js/ui/floating/layers.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* The layering UI window
|
||||
*/
|
||||
|
||||
const uiLayers = {
|
||||
layers: [],
|
||||
active: null,
|
||||
|
||||
_syncLayers() {
|
||||
const layersEl = document.getElementById("layer-list");
|
||||
|
||||
const children = Array.from(layersEl.children);
|
||||
|
||||
this.layers.forEach((uiLayer) => {
|
||||
if (!uiLayer.entry) {
|
||||
uiLayer.entry = document.createElement("div");
|
||||
uiLayer.entry.textContent = uiLayer.name;
|
||||
|
||||
uiLayer.entry.id = `ui-layer-${uiLayer.id}`;
|
||||
uiLayer.entry.classList.add("ui-layer");
|
||||
uiLayer.entry.addEventListener(
|
||||
"click",
|
||||
() => (this.active = uiLayer.layer)
|
||||
);
|
||||
|
||||
if (true || children.length === 0) layersEl.appendChild(uiLayer.entry);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addLayer(group, name) {
|
||||
const layer = imageCollection.registerLayer(null, {
|
||||
name,
|
||||
after:
|
||||
(this.layers.length > 0 && this.layers[this.layers.length - 1].layer) ||
|
||||
bgLayer,
|
||||
});
|
||||
|
||||
const uiLayer = {
|
||||
id: layer.id,
|
||||
group,
|
||||
name,
|
||||
entry: null,
|
||||
layer,
|
||||
};
|
||||
this.layers.push(uiLayer);
|
||||
|
||||
this.active = uiLayer.layer;
|
||||
|
||||
this._syncLayers();
|
||||
|
||||
return uiLayer;
|
||||
},
|
||||
};
|
||||
uiLayers.addLayer(null, "Default Image Layer");
|
||||
uiLayers.addLayer(null, "Test Extra Layer");
|
|
@ -271,20 +271,20 @@ const colorBrushTool = () =>
|
|||
const bkpcanvas = state.eraseBackup.canvas;
|
||||
const bkpctx = state.eraseBackup.ctx;
|
||||
bkpctx.clearRect(0, 0, bkpcanvas.width, bkpcanvas.height);
|
||||
bkpctx.drawImage(imgCanvas, 0, 0);
|
||||
bkpctx.drawImage(uiLayers.active.canvas, 0, 0);
|
||||
|
||||
imgCtx.globalCompositeOperation = "destination-out";
|
||||
_color_brush_erase_callback(evn, state, imgCtx);
|
||||
imgCtx.globalCompositeOperation = "source-over";
|
||||
uiLayers.active.ctx.globalCompositeOperation = "destination-out";
|
||||
_color_brush_erase_callback(evn, state, uiLayers.active.ctx);
|
||||
uiLayers.active.ctx.globalCompositeOperation = "source-over";
|
||||
_color_brush_erase_callback(evn, state, state.eraseLayer.ctx);
|
||||
};
|
||||
|
||||
state.erasecb = (evn) => {
|
||||
if (state.eyedropper || !state.erasing) return;
|
||||
if (state.affectMask) _mask_brush_erase_callback(evn, state);
|
||||
imgCtx.globalCompositeOperation = "destination-out";
|
||||
_color_brush_erase_callback(evn, state, imgCtx);
|
||||
imgCtx.globalCompositeOperation = "source-over";
|
||||
uiLayers.active.ctx.globalCompositeOperation = "destination-out";
|
||||
_color_brush_erase_callback(evn, state, uiLayers.active.ctx);
|
||||
uiLayers.active.ctx.globalCompositeOperation = "source-over";
|
||||
_color_brush_erase_callback(evn, state, state.eraseLayer.ctx);
|
||||
};
|
||||
|
||||
|
@ -300,8 +300,13 @@ const colorBrushTool = () =>
|
|||
const cropped = cropCanvas(canvas, {border: 10});
|
||||
const bb = cropped.bb;
|
||||
|
||||
imgCtx.clearRect(0, 0, imgCanvas.width, imgCanvas.height);
|
||||
imgCtx.drawImage(bkpcanvas, 0, 0);
|
||||
uiLayers.active.ctx.clearRect(
|
||||
0,
|
||||
0,
|
||||
uiLayers.active.canvas.width,
|
||||
uiLayers.active.canvas.height
|
||||
);
|
||||
uiLayers.active.ctx.drawImage(bkpcanvas, 0, 0);
|
||||
|
||||
commands.runCommand("eraseImage", "Color Brush Erase", {
|
||||
mask: cropped.canvas,
|
||||
|
|
|
@ -367,7 +367,7 @@ const dream_generate_callback = async (evn, state) => {
|
|||
blockNewImages = true;
|
||||
|
||||
// Use txt2img if canvas is blank
|
||||
if (isCanvasBlank(bb.x, bb.y, bb.w, bb.h, imgCanvas)) {
|
||||
if (isCanvasBlank(bb.x, bb.y, bb.w, bb.h, uiLayers.active.canvas)) {
|
||||
// Dream
|
||||
_generate("txt2img", request, bb);
|
||||
} else {
|
||||
|
@ -384,7 +384,7 @@ const dream_generate_callback = async (evn, state) => {
|
|||
// Get init image
|
||||
auxCtx.fillRect(0, 0, request.width, request.height);
|
||||
auxCtx.drawImage(
|
||||
imgCanvas,
|
||||
uiLayers.active.canvas,
|
||||
bb.x,
|
||||
bb.y,
|
||||
bb.w,
|
||||
|
@ -417,7 +417,7 @@ const dream_generate_callback = async (evn, state) => {
|
|||
|
||||
auxCtx.globalCompositeOperation = "destination-in";
|
||||
auxCtx.drawImage(
|
||||
imgCanvas,
|
||||
uiLayers.active.canvas,
|
||||
bb.x,
|
||||
bb.y,
|
||||
bb.w,
|
||||
|
@ -430,7 +430,7 @@ const dream_generate_callback = async (evn, state) => {
|
|||
} else {
|
||||
auxCtx.globalCompositeOperation = "destination-in";
|
||||
auxCtx.drawImage(
|
||||
imgCanvas,
|
||||
uiLayers.active.canvas,
|
||||
bb.x,
|
||||
bb.y,
|
||||
bb.w,
|
||||
|
@ -536,7 +536,7 @@ const dream_img2img_callback = (evn, state) => {
|
|||
);
|
||||
|
||||
// Do nothing if no image exists
|
||||
if (isCanvasBlank(bb.x, bb.y, bb.w, bb.h, imgCanvas)) return;
|
||||
if (isCanvasBlank(bb.x, bb.y, bb.w, bb.h, uiLayers.active.canvas)) return;
|
||||
|
||||
// Build request to the API
|
||||
const request = {};
|
||||
|
@ -565,7 +565,7 @@ const dream_img2img_callback = (evn, state) => {
|
|||
// Get init image
|
||||
auxCtx.fillRect(0, 0, request.width, request.height);
|
||||
auxCtx.drawImage(
|
||||
imgCanvas,
|
||||
uiLayers.active.canvas,
|
||||
bb.x,
|
||||
bb.y,
|
||||
bb.w,
|
||||
|
|
|
@ -84,7 +84,7 @@ const selectTransformTool = () =>
|
|||
// Clears selection and make things right
|
||||
state.reset = () => {
|
||||
if (state.selected)
|
||||
imgCtx.drawImage(
|
||||
uiLayers.active.ctx.drawImage(
|
||||
state.original.image,
|
||||
state.original.x,
|
||||
state.original.y
|
||||
|
@ -312,7 +312,7 @@ const selectTransformTool = () =>
|
|||
|
||||
// If something is selected, commit changes to the canvas
|
||||
if (state.selected) {
|
||||
imgCtx.drawImage(
|
||||
uiLayers.active.ctx.drawImage(
|
||||
state.selected.image,
|
||||
state.original.x,
|
||||
state.original.y
|
||||
|
@ -406,7 +406,7 @@ const selectTransformTool = () =>
|
|||
const ctx = cvs.getContext("2d");
|
||||
|
||||
ctx.drawImage(
|
||||
imgCanvas,
|
||||
uiLayers.active.canvas,
|
||||
state.selected.x,
|
||||
state.selected.y,
|
||||
state.selected.w,
|
||||
|
@ -417,7 +417,7 @@ const selectTransformTool = () =>
|
|||
state.selected.h
|
||||
);
|
||||
|
||||
imgCtx.clearRect(
|
||||
uiLayers.active.ctx.clearRect(
|
||||
state.selected.x,
|
||||
state.selected.y,
|
||||
state.selected.w,
|
||||
|
|
Loading…
Reference in a new issue