Files
bubblechambersimart/src/compose/schema.js
2026-06-02 19:17:19 -04:00

137 lines
6.2 KiB
JavaScript

/* ============================================================
compose/schema.js — UI control descriptors for the composer, and
the DEFAULT composition (two-point floor grid). Data only (no DOM).
Each group: { id, label, transform?, enable?, controls:[ {path,label,type,...} ] }
path = dotted path INTO the group's config. types:
range {min,max,step} · color (#hex) · select {options} · toggle · text
Groups with transform:true get an auto x/y/rotation/scale block.
============================================================ */
export const DEFAULT_COMPOSITION = {
size: 1600, seed: 'MESON-5113',
background: {
color: 'rgb(229,222,203)',
film: { opacity: 0.6, density: 0.5, seed: 8 },
aging: { opacity: 0.5, scratches: 5, dust: 0.45, foxing: 0.5, seed: 5 },
grain: { opacity: 0.42, intensity: 0.42, seed: 19 },
glow: { strength: 0.55 }, // lit-page glow (lighter warm centre)
vignette: { strength: 0.4 }, // soft darkening toward the edges
},
fieldSea: {
enabled: true, layerOpacity: 1, transform: { x: 0, y: 0, rotation: 0, scale: 1 }, seed: 'VACUUM-5113',
color: { hueBack: 0.54, hueFront: 0.47, sat: 0.6 },
layers: 3, chaos: 0.3, blips: 0.7, mound: 0.3, horizonY: 0.36, lines: 46,
},
fieldGrid: {
enabled: true, layerOpacity: 1, pos: 'over', style: 'floor', transform: { x: 0, y: 0, rotation: 0, scale: 1 },
color: { hue: 0.5, hue2: 0.55, sat: 0.32, lightNear: 0.34, lightFar: 0.62 }, opacity: 0.44,
pitch: 0.45, yaw: 0.42, persp: 1.1, dist: 2.8, nx: 16, nz: 24, originY: 0.34, ripple: { amp: 0, freqI: 0.5, freqK: 0.35, phase: 0 },
},
disk: {
enabled: true, layerOpacity: 1, transform: { x: 0, y: -0.26, rotation: 0, scale: 0.78 },
hue: 0.06, sat: 0.82, size: 0.16, pressure: 0.85, intensity: 0.85, striations: 0.6, stain: 0.35, soften: 1.35,
},
bubble: {
enabled: true, layerOpacity: 1, transform: { x: 0.28, y: -0.1, rotation: 10, scale: 0.78 },
palette: 'magentarise', saturation: 1.05, traceHue: 0, transparentBase: true,
primaries: 18, sweepers: 5, cosmics: 6, eloss: 0.34, bfield: 1.0, deltaRate: 0.6,
},
fiduciaries: {
enabled: true, layerOpacity: 1, label: 'No 001', pencil: '#39312a', width: 1.0, arrow: true, corners: false, caption: '',
},
};
const R = (path, label, min, max, step) => ({ path, label, type: 'range', min, max, step });
export const GROUPS_SCHEMA = [
{
id: 'background', label: 'Background', controls: [
{ path: 'color', label: 'Paper colour', type: 'color' },
R('film.opacity', 'Film opacity', 0, 1, 0.01),
R('film.density', 'Film density', 0, 1, 0.01),
R('aging.opacity', 'Aging opacity', 0, 1, 0.01),
R('aging.scratches', 'Scratches', 0, 20, 1),
R('aging.foxing', 'Foxing', 0, 1, 0.01),
R('aging.dust', 'Dust', 0, 1, 0.01),
R('grain.opacity', 'Grain opacity', 0, 1, 0.01),
R('grain.intensity', 'Grain intensity', 0, 1, 0.01),
R('glow.strength', 'Page glow', 0, 1, 0.01),
R('vignette.strength', 'Vignette', 0, 1, 0.01),
],
},
{
id: 'fieldSea', label: 'Field · Sea', transform: true, enable: true, controls: [
R('color.hueBack', 'Hue · far', 0, 1, 0.005),
R('color.hueFront', 'Hue · near', 0, 1, 0.005),
R('color.sat', 'Saturation', 0, 1, 0.01),
R('layers', 'Plate layers', 1, 3, 1),
R('chaos', 'Chaos', 0, 1, 0.01),
R('blips', 'Blips', 0, 2, 0.05),
R('mound', 'Mound', 0, 1, 0.01),
R('horizonY', 'Horizon Y', 0.2, 0.6, 0.01),
R('lines', '# lines', 16, 80, 1),
{ path: 'seed', label: 'Seed', type: 'text' },
],
},
{
id: 'fieldGrid', label: 'Field · Grid', transform: true, enable: true, controls: [
{ path: 'style', label: 'Style', type: 'select', options: ['floor', 'radial'] },
{ path: 'pos', label: 'Stack position', type: 'select', options: ['over', 'behind'] },
R('opacity', 'Opacity', 0, 1, 0.01),
R('pitch', 'Pitch', 0, 1.4, 0.01),
R('yaw', 'Yaw · two-point', -1, 1, 0.01),
R('persp', 'Perspective', 0, 2, 0.01),
R('dist', 'Camera distance', 1.2, 6, 0.05),
R('nx', 'Width lines', 4, 36, 1),
R('nz', 'Depth lines', 4, 48, 1),
R('originY', 'Horizon Y', -0.4, 0.6, 0.01),
R('color.hue', 'Hue', 0, 1, 0.005),
R('color.sat', 'Saturation', 0, 1, 0.01),
R('ripple.amp', 'Floor ripple', 0, 2, 0.02),
],
},
{
id: 'disk', label: 'Disk · sun', transform: true, enable: true, controls: [
R('hue', 'Hue', 0, 1, 0.005),
R('sat', 'Saturation', 0, 1, 0.01),
R('size', 'Size', 0.05, 0.4, 0.005),
R('pressure', 'Pressure · dark core', 0, 1, 0.01),
R('intensity', 'Intensity', 0, 1, 0.01),
R('striations', 'Striations', 0, 1, 0.01),
R('stain', 'Staining', 0, 1, 0.01),
],
},
{
id: 'bubble', label: 'Bubble · event', transform: true, enable: true, controls: [
{ path: 'palette', label: 'Palette', type: 'select', options: ['magentarise', 'mono', 'kind', 'kindrise', 'kindlife', 'charge', 'beta', 'lifecycle', 'cyanotype'] },
{ path: 'transparentBase', label: 'Transparent base', type: 'toggle' },
R('saturation', 'Saturation', 0, 1.5, 0.01),
R('traceHue', 'Trace hue', 0, 1, 0.005),
R('primaries', 'Primaries', 3, 40, 1),
R('sweepers', 'Sweepers · arcs', 0, 12, 1),
R('cosmics', 'Cosmics', 0, 16, 1),
R('eloss', 'Energy loss', 0, 1.5, 0.01),
R('bfield', 'B-field', 0.2, 3, 0.01),
R('deltaRate', 'δ-ray rate', 0, 1, 0.01),
],
},
{
id: 'fiduciaries', label: 'Fiduciaries', transform: true, enable: true, controls: [
{ path: 'label', label: 'Label', type: 'text' },
{ path: 'pencil', label: 'Pencil', type: 'color' },
R('width', 'Line width', 0.3, 3, 0.1),
{ path: 'arrow', label: 'Arrow', type: 'toggle' },
{ path: 'corners', label: 'Registration corners', type: 'toggle' },
{ path: 'caption', label: 'Caption', type: 'text' },
],
},
];
// the common transform block, generated for groups with transform:true
export const COMMON_CONTROLS = [
R('layerOpacity', 'Opacity', 0, 1, 0.01),
R('transform.x', 'Centre X', -1, 1, 0.01),
R('transform.y', 'Centre Y', -1, 1, 0.01),
R('transform.rotation', 'Rotation°', -180, 180, 1),
R('transform.scale', 'Scale', 0.1, 2.5, 0.01),
];