Merge verified Odysseus fixes

This commit is contained in:
pewdiepie-archdaemon
2026-07-23 14:49:02 +00:00
parent 4c9a8ca115
commit d8a2059df8
117 changed files with 15693 additions and 3191 deletions
+53 -15
View File
@@ -15,32 +15,60 @@
* createLayer: (name, w, h) => object,
* renderLayerPanel: () => void,
* composite: () => void,
* renderLayer?: (layer) => HTMLCanvasElement,
* uiModule: object,
* }} deps
*/
import { state } from './state.js';
export function mergeLayerDownAtIndex(idx) {
function _renderSource(layer, renderLayer) {
if (!layer) return null;
try {
return typeof renderLayer === 'function' ? (renderLayer(layer) || layer.canvas) : layer.canvas;
} catch {
return layer.canvas;
}
}
function _clearBakedAdjustments(layer) {
if (!layer) return;
layer.adjLayers = [];
layer._adjFinal = null;
layer._adjFinalKey = '';
layer._adjCache = null;
layer._adjCacheKey = '';
}
export function mergeLayerDownAtIndex(idx, renderLayer = null) {
if (idx < 1 || idx >= state.layers.length) return null;
const upper = state.layers[idx];
const lower = state.layers[idx - 1];
const upperOff = state.layerOffsets.get(upper.id) || { x: 0, y: 0 };
const lowerOff = state.layerOffsets.get(lower.id) || { x: 0, y: 0 };
lower.ctx.save();
lower.ctx.globalAlpha = upper.opacity;
lower.ctx.drawImage(
upper.canvas,
upperOff.x - lowerOff.x,
upperOff.y - lowerOff.y,
);
lower.ctx.restore();
const lowerSource = _renderSource(lower, renderLayer);
const upperSource = _renderSource(upper, renderLayer);
const merged = document.createElement('canvas');
merged.width = state.imgWidth;
merged.height = state.imgHeight;
const mctx = merged.getContext('2d');
mctx.globalAlpha = lower.opacity;
mctx.drawImage(lowerSource, lowerOff.x, lowerOff.y);
mctx.globalAlpha = upper.opacity;
mctx.drawImage(upperSource, upperOff.x, upperOff.y);
mctx.globalAlpha = 1;
lower.canvas = merged;
lower.ctx = lower.canvas.getContext('2d');
lower.opacity = 1;
lower.visible = true;
state.layerOffsets.set(lower.id, { x: 0, y: 0 });
_clearBakedAdjustments(lower);
state.layers.splice(idx, 1);
state.layerOffsets.delete(upper.id);
state.activeLayerId = lower.id;
return lower;
}
export function wireMergeButtons({ saveState, createLayer, renderLayerPanel, composite, uiModule }) {
export function wireMergeButtons({ saveState, createLayer, renderLayerPanel, composite, renderLayer, uiModule }) {
// Flatten Copy.
document.getElementById('ge-flatten')?.addEventListener('click', () => {
if (state.layers.length < 2) return;
@@ -51,9 +79,10 @@ export function wireMergeButtons({ saveState, createLayer, renderLayerPanel, com
if (!l.visible) continue;
const off = state.layerOffsets.get(l.id) || { x: 0, y: 0 };
ctx.globalAlpha = l.opacity;
ctx.drawImage(l.canvas, off.x, off.y);
ctx.drawImage(_renderSource(l, renderLayer), off.x, off.y);
ctx.globalAlpha = 1;
}
_clearBakedAdjustments(merged);
state.layers.push(merged);
state.activeLayerId = merged.id;
renderLayerPanel();
@@ -70,14 +99,23 @@ export function wireMergeButtons({ saveState, createLayer, renderLayerPanel, com
}
saveState('Merge all');
const base = visibleLayers[0];
const baseCtx = base.ctx;
for (let i = 1; i < visibleLayers.length; i++) {
const merged = document.createElement('canvas');
merged.width = state.imgWidth;
merged.height = state.imgHeight;
const baseCtx = merged.getContext('2d');
for (let i = 0; i < visibleLayers.length; i++) {
const l = visibleLayers[i];
const off = state.layerOffsets.get(l.id) || { x: 0, y: 0 };
baseCtx.globalAlpha = l.opacity;
baseCtx.drawImage(l.canvas, off.x, off.y);
baseCtx.drawImage(_renderSource(l, renderLayer), off.x, off.y);
baseCtx.globalAlpha = 1;
}
base.canvas = merged;
base.ctx = base.canvas.getContext('2d');
base.opacity = 1;
base.visible = true;
state.layerOffsets.set(base.id, { x: 0, y: 0 });
_clearBakedAdjustments(base);
// Free offset entries for the discarded layers; keep base.
for (const l of state.layers) {
if (l === base) continue;
@@ -95,7 +133,7 @@ export function wireMergeButtons({ saveState, createLayer, renderLayerPanel, com
const idx = state.layers.findIndex(l => l.id === state.activeLayerId);
if (idx < 1) return; // can't merge the bottom layer
saveState('Merge down');
mergeLayerDownAtIndex(idx);
mergeLayerDownAtIndex(idx, renderLayer);
renderLayerPanel();
composite();
uiModule.showToast('Layer merged down');