mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-09-29 03:22:21 +02:00
Squash Odysseus development history
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* Local two-color gradient tool.
|
||||
*
|
||||
* The drag becomes a retained effect on completion, so previews never mutate
|
||||
* source pixels or compound across pointer-move events.
|
||||
*/
|
||||
import { state } from '../state.js';
|
||||
import { canvasCoords } from '../canvas-coords.js';
|
||||
import { isLayerPixelLocked } from '../layer-groups.js';
|
||||
|
||||
export function createGradientTool({ activeLayer, saveState, composite, schedulePersist, renderLayerPanel, getSettings }) {
|
||||
let start = null;
|
||||
let lastPoint = null;
|
||||
let activeLayerId = null;
|
||||
let historySaved = false;
|
||||
|
||||
function settings() {
|
||||
const values = getSettings?.() || {};
|
||||
return {
|
||||
start: values.start || state.gradientStart || state.color,
|
||||
mid: values.mid || state.gradientMid || '#808080',
|
||||
midPosition: values.midPosition ?? state.gradientMidPosition ?? 50,
|
||||
midEnabled: values.midEnabled ?? state.gradientMidEnabled ?? false,
|
||||
extraStops: Array.isArray(values.extraStops) ? values.extraStops : (state.gradientStops || []),
|
||||
end: values.end || state.gradientEnd || '#ffffff',
|
||||
endAlpha: values.endAlpha ?? state.gradientEndAlpha ?? 100,
|
||||
opacity: values.opacity ?? state.gradientOpacity ?? 100,
|
||||
type: values.type || state.gradientType || 'linear-gradient',
|
||||
};
|
||||
}
|
||||
|
||||
function preview(point) {
|
||||
const layer = activeLayer();
|
||||
if (!start || !layer || layer.id !== activeLayerId) return false;
|
||||
const dx = point.x - start.x;
|
||||
const dy = point.y - start.y;
|
||||
if (Math.hypot(dx, dy) < 0.5) return false;
|
||||
const values = settings();
|
||||
const stops = [
|
||||
{ position: 0, color: values.start, alpha: 1 },
|
||||
...(values.midEnabled ? [{ position: Number(values.midPosition), color: values.mid, alpha: 1 }] : []),
|
||||
...values.extraStops.slice(0, 10).map(stop => ({
|
||||
position: Math.max(1, Math.min(99, Number(stop.position) || 50)),
|
||||
color: stop.color || '#808080',
|
||||
alpha: 1,
|
||||
})),
|
||||
{ position: 100, color: values.end, alpha: Math.max(0, Math.min(100, Number(values.endAlpha))) / 100 },
|
||||
].sort((a, b) => a.position - b.position);
|
||||
layer._effectPreview = {
|
||||
id: 'gradient-preview', type: values.type, name: values.type === 'radial-gradient' ? 'Radial Gradient' : 'Gradient', visible: true, opacity: 1,
|
||||
params: { x1: start.x, y1: start.y, x2: point.x, y2: point.y, stops, opacity: Math.max(0, Math.min(100, Number(values.opacity))) / 100 },
|
||||
};
|
||||
composite();
|
||||
return true;
|
||||
}
|
||||
|
||||
return {
|
||||
begin(e) {
|
||||
const layer = activeLayer();
|
||||
if (!layer) return false;
|
||||
if (isLayerPixelLocked(state, layer)) return false;
|
||||
if (layer.kind === 'placed') return false;
|
||||
activeLayerId = layer.id;
|
||||
start = canvasCoords(e, state.mainCanvas);
|
||||
lastPoint = { ...start };
|
||||
state.gradientActive = true;
|
||||
historySaved = false;
|
||||
return true;
|
||||
},
|
||||
|
||||
drag(e) {
|
||||
if (!state.gradientActive) return false;
|
||||
lastPoint = canvasCoords(e, state.mainCanvas);
|
||||
preview(lastPoint);
|
||||
return true;
|
||||
},
|
||||
|
||||
end(e) {
|
||||
if (!state.gradientActive) return false;
|
||||
const point = e && (Number.isFinite(e.clientX) || (e.touches && e.touches.length))
|
||||
? canvasCoords(e, state.mainCanvas)
|
||||
: lastPoint;
|
||||
const changed = point ? preview(point) : false;
|
||||
const layer = activeLayer();
|
||||
state.gradientActive = false;
|
||||
if (layer?._effectPreview && changed) {
|
||||
if (!historySaved) {
|
||||
saveState('Gradient');
|
||||
historySaved = true;
|
||||
}
|
||||
layer.effects = Array.isArray(layer.effects) ? layer.effects : [];
|
||||
layer.effects.push(layer._effectPreview);
|
||||
}
|
||||
if (layer) layer._effectPreview = null;
|
||||
start = null;
|
||||
lastPoint = null;
|
||||
activeLayerId = null;
|
||||
historySaved = false;
|
||||
if (changed) {
|
||||
renderLayerPanel?.();
|
||||
schedulePersist?.();
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
cancel() {
|
||||
if (!state.gradientActive) return false;
|
||||
const layer = activeLayer();
|
||||
if (layer) layer._effectPreview = null;
|
||||
state.gradientActive = false;
|
||||
start = null;
|
||||
lastPoint = null;
|
||||
activeLayerId = null;
|
||||
historySaved = false;
|
||||
composite();
|
||||
return true;
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user