Files
odysseus/static/js/editor/brush-presets.js
T
pewdiepie-archdaemonandClaude Opus 5.5 5fac693c1c feat(photo-editor): Ajax Image Editor client (Photoshop-parity tools)
Photoshop-parity editor client: layers, selection/masking, brushes,
smart filters, LUT import, Quick Edit, mobile gestures, workspaces,
batch operations, and the service-worker versioning (v978->v1006).

Source: vendor/photocraft (ad1cff44) photo-editor client files, merged
onto upstream/dev (a8c147b2). Conflict resolution documented in
pr_work/A_conflicts.md; editor files taken from vendor/photocraft
(upstream's editor is an earlier snapshot of the same feature).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 11:57:35 +00:00

51 lines
2.0 KiB
JavaScript

const STORAGE_KEY = 'odysseus.editor.brush-presets.v1';
const BUILT_INS = [
{ id: 'soft-round', name: 'Soft Round', size: 80, opacity: 100, flow: 35, softness: 100, spacing: 12, smoothing: 25, blendMode: 'source-over' },
{ id: 'hard-round', name: 'Hard Round', size: 24, opacity: 100, flow: 100, softness: 0, spacing: 18, smoothing: 15, blendMode: 'source-over' },
{ id: 'detail', name: 'Detail', size: 6, opacity: 100, flow: 70, softness: 20, spacing: 10, smoothing: 55, blendMode: 'source-over' },
{ id: 'pixel-1px', name: 'Pixel', size: 1, opacity: 100, flow: 100, softness: 0, spacing: 1, smoothing: 0, blendMode: 'source-over', pixel: true },
];
export function loadBrushPresets(storage = globalThis.localStorage) {
let custom = [];
try {
const parsed = JSON.parse(storage?.getItem(STORAGE_KEY) || '[]');
if (Array.isArray(parsed)) custom = parsed.filter(item => item && typeof item.name === 'string');
} catch {}
return [...BUILT_INS.map(item => ({ ...item, builtIn: true })), ...custom];
}
export function saveCustomBrushPresets(presets, storage = globalThis.localStorage) {
const custom = (presets || []).filter(item => item && !item.builtIn);
storage?.setItem(STORAGE_KEY, JSON.stringify(custom));
}
export function captureBrushPreset(state, name) {
return {
id: `custom-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
name: String(name || 'Brush').trim() || 'Brush',
size: state.brushSize,
opacity: state.brushOpacity,
flow: state.brushFlow,
softness: state.brushSoftness,
spacing: state.brushSpacing,
smoothing: state.brushSmoothing,
blendMode: state.brushBlendMode,
pixel: !!state.brushPixel,
};
}
export function applyBrushPreset(state, preset) {
if (!preset) return;
state.brushSize = preset.size;
state.brushOpacity = preset.opacity;
state.brushFlow = preset.flow;
state.brushSoftness = preset.softness;
state.brushSpacing = preset.spacing;
state.brushSmoothing = preset.smoothing;
state.brushBlendMode = preset.blendMode || 'source-over';
state.brushPixel = !!preset.pixel;
}