@3driseai/3drise-core 1.0.19 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animations/index.d.ts +2 -0
- package/dist/animations/index.d.ts.map +1 -0
- package/dist/animations/index.js +1 -0
- package/dist/animations/trackGenerators.d.ts +140 -0
- package/dist/animations/trackGenerators.d.ts.map +1 -0
- package/dist/animations/trackGenerators.js +443 -0
- package/dist/autoAnimate/bounds.d.ts +7 -0
- package/dist/autoAnimate/bounds.d.ts.map +1 -0
- package/dist/autoAnimate/bounds.js +23 -0
- package/dist/autoAnimate/composer.d.ts +30 -0
- package/dist/autoAnimate/composer.d.ts.map +1 -0
- package/dist/autoAnimate/composer.js +251 -0
- package/dist/autoAnimate/describeScene.d.ts +105 -0
- package/dist/autoAnimate/describeScene.d.ts.map +1 -0
- package/dist/autoAnimate/describeScene.js +165 -0
- package/dist/autoAnimate/draft.d.ts +59 -0
- package/dist/autoAnimate/draft.d.ts.map +1 -0
- package/dist/autoAnimate/draft.js +2 -0
- package/dist/autoAnimate/index.d.ts +14 -0
- package/dist/autoAnimate/index.d.ts.map +1 -0
- package/dist/autoAnimate/index.js +9 -0
- package/dist/autoAnimate/recipes.d.ts +87 -0
- package/dist/autoAnimate/recipes.d.ts.map +1 -0
- package/dist/autoAnimate/recipes.js +224 -0
- package/dist/autoAnimate/rng.d.ts +10 -0
- package/dist/autoAnimate/rng.d.ts.map +1 -0
- package/dist/autoAnimate/rng.js +16 -0
- package/dist/autoAnimate/sceneAnalyzer.d.ts +7 -0
- package/dist/autoAnimate/sceneAnalyzer.d.ts.map +1 -0
- package/dist/autoAnimate/sceneAnalyzer.js +291 -0
- package/dist/autoAnimate/types.d.ts +124 -0
- package/dist/autoAnimate/types.d.ts.map +1 -0
- package/dist/autoAnimate/types.js +1 -0
- package/dist/autoAnimate/validator.d.ts +10 -0
- package/dist/autoAnimate/validator.d.ts.map +1 -0
- package/dist/autoAnimate/validator.js +59 -0
- package/dist/data/effectsDefaults.d.ts +4 -0
- package/dist/data/effectsDefaults.d.ts.map +1 -1
- package/dist/data/effectsDefaults.js +393 -2
- package/dist/data/gridsDefaults.d.ts +5 -0
- package/dist/data/gridsDefaults.d.ts.map +1 -0
- package/dist/data/gridsDefaults.js +290 -0
- package/dist/data/index.d.ts +1 -0
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +1 -0
- package/dist/data/particlesDefaults.d.ts +3 -1
- package/dist/data/particlesDefaults.d.ts.map +1 -1
- package/dist/data/particlesDefaults.js +78 -0
- package/dist/environment/cloudConfigs.d.ts +313 -0
- package/dist/environment/cloudConfigs.d.ts.map +1 -0
- package/dist/environment/cloudConfigs.js +342 -0
- package/dist/environment/index.d.ts +5 -0
- package/dist/environment/index.d.ts.map +1 -0
- package/dist/environment/index.js +6 -0
- package/dist/environment/landscapeConfigs.d.ts +220 -0
- package/dist/environment/landscapeConfigs.d.ts.map +1 -0
- package/dist/environment/landscapeConfigs.js +256 -0
- package/dist/environment/oceanConfigs.d.ts +293 -0
- package/dist/environment/oceanConfigs.d.ts.map +1 -0
- package/dist/environment/oceanConfigs.js +380 -0
- package/dist/environment/terrainConfigs.d.ts +254 -0
- package/dist/environment/terrainConfigs.d.ts.map +1 -0
- package/dist/environment/terrainConfigs.js +292 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/properties/index.d.ts +4 -0
- package/dist/properties/index.d.ts.map +1 -0
- package/dist/properties/index.js +3 -0
- package/dist/properties/registry.d.ts +44 -0
- package/dist/properties/registry.d.ts.map +1 -0
- package/dist/properties/registry.js +343 -0
- package/dist/properties/tables/effectsProperties.d.ts +40 -0
- package/dist/properties/tables/effectsProperties.d.ts.map +1 -0
- package/dist/properties/tables/effectsProperties.js +512 -0
- package/dist/properties/tables/geometryProperties.d.ts +38 -0
- package/dist/properties/tables/geometryProperties.d.ts.map +1 -0
- package/dist/properties/tables/geometryProperties.js +91 -0
- package/dist/properties/tables/getPropertyConfig.d.ts +3 -0
- package/dist/properties/tables/getPropertyConfig.d.ts.map +1 -0
- package/dist/properties/tables/getPropertyConfig.js +16 -0
- package/dist/properties/tables/gridProperties.d.ts +6 -0
- package/dist/properties/tables/gridProperties.d.ts.map +1 -0
- package/dist/properties/tables/gridProperties.js +121 -0
- package/dist/properties/tables/index.d.ts +9 -0
- package/dist/properties/tables/index.d.ts.map +1 -0
- package/dist/properties/tables/index.js +8 -0
- package/dist/properties/tables/lightProperties.d.ts +14 -0
- package/dist/properties/tables/lightProperties.d.ts.map +1 -0
- package/dist/properties/tables/lightProperties.js +263 -0
- package/dist/properties/tables/materialBounds.d.ts +33 -0
- package/dist/properties/tables/materialBounds.d.ts.map +1 -0
- package/dist/properties/tables/materialBounds.js +180 -0
- package/dist/properties/tables/optionalProperties.d.ts +83 -0
- package/dist/properties/tables/optionalProperties.d.ts.map +1 -0
- package/dist/properties/tables/optionalProperties.js +710 -0
- package/dist/properties/tables/particlesProperties.d.ts +17 -0
- package/dist/properties/tables/particlesProperties.d.ts.map +1 -0
- package/dist/properties/tables/particlesProperties.js +334 -0
- package/dist/properties/types.d.ts +43 -0
- package/dist/properties/types.d.ts.map +1 -0
- package/dist/properties/types.js +12 -0
- package/dist/services/ShadersLibrary.d.ts +1 -1
- package/dist/services/ShadersLibrary.d.ts.map +1 -1
- package/dist/shaders/WallpaperGridMaterial.d.ts.map +1 -1
- package/dist/shaders/WallpaperGridMaterial.js +6 -1
- package/dist/three/GalleryLayoutV.d.ts.map +1 -1
- package/dist/three/GalleryLayoutV.js +0 -10
- package/dist/three/SceneBuilderV.d.ts.map +1 -1
- package/dist/three/SceneBuilderV.js +1 -7
- package/dist/types/generativeEffects.d.ts +0 -4
- package/dist/types/generativeEffects.d.ts.map +1 -1
- package/dist/types/generativeParticles.d.ts +175 -2
- package/dist/types/generativeParticles.d.ts.map +1 -1
- package/dist/types/objectSettings.d.ts +45 -4
- package/dist/types/objectSettings.d.ts.map +1 -1
- package/dist/types/scene3d.d.ts +3 -3
- package/dist/types/scene3d.d.ts.map +1 -1
- package/dist/utils/generativeAnimatable.d.ts +1 -1
- package/dist/utils/generativeAnimatable.d.ts.map +1 -1
- package/dist/utils/generativeAnimatable.js +7 -1
- package/dist/utils/getAnimatableProperties.d.ts +12 -1
- package/dist/utils/getAnimatableProperties.d.ts.map +1 -1
- package/dist/utils/getAnimatableProperties.js +35 -138
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/objectEffects.d.ts +6 -0
- package/dist/utils/objectEffects.d.ts.map +1 -0
- package/dist/utils/objectEffects.js +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const int = (key, label, min, max, def) => ({ type: 'range', key, label, min, max, step: 1, default: def });
|
|
2
|
+
const num = (key, label, min, max, step, def) => ({ type: 'range', key, label, min, max, step, default: def, digits: 2 });
|
|
3
|
+
const ang = (key, label, def) => ({ type: 'range', key, label, min: 0, max: Math.PI * 2, step: 0.05, default: def, digits: 2, unit: 'rad' });
|
|
4
|
+
const str = (key, label, def) => ({ type: 'text', key, label, default: def });
|
|
5
|
+
const CURVE = int('curveSegments', 'Curve detail', 6, 160, 64);
|
|
6
|
+
export const SHAPE_CONTROLS = {
|
|
7
|
+
heart: [CURVE],
|
|
8
|
+
star: [int('points', 'Points', 2, 12, 5), num('outer', 'Outer radius', 0.1, 0.6, 0.01, 0.5), num('inner', 'Inner radius', 0.05, 0.5, 0.01, 0.2), CURVE],
|
|
9
|
+
polygon: [int('sides', 'Sides', 3, 12, 6), CURVE],
|
|
10
|
+
gear: [int('teeth', 'Teeth', 4, 32, 12), num('outer', 'Outer', 0.2, 0.6, 0.01, 0.5), num('inner', 'Root', 0.15, 0.55, 0.01, 0.38), num('hole', 'Bore', 0.05, 0.35, 0.01, 0.16), CURVE],
|
|
11
|
+
flower: [int('petals', 'Petals', 3, 16, 6), num('outer', 'Outer', 0.2, 0.6, 0.01, 0.5), num('inner', 'Inner', 0.05, 0.5, 0.01, 0.26), num('sharp', 'Sharpness', 0.2, 3, 0.05, 0.7), CURVE],
|
|
12
|
+
spade: [CURVE],
|
|
13
|
+
club: [CURVE],
|
|
14
|
+
diamond: [CURVE],
|
|
15
|
+
droplet: [num('width', 'Width', 0.2, 0.8, 0.01, 0.5), num('taper', 'Taper', 0.4, 1.8, 0.01, 1), CURVE],
|
|
16
|
+
lightning: [num('width', 'Width', 0.3, 1, 0.01, 0.6), num('height', 'Height', 0.5, 1.4, 0.01, 1), CURVE],
|
|
17
|
+
sparkle: [int('points', 'Points', 3, 12, 4), num('outer', 'Outer', 0.2, 0.6, 0.01, 0.5), num('inner', 'Pinch', 0.02, 0.4, 0.01, 0.14), CURVE],
|
|
18
|
+
shield: [num('width', 'Width', 0.4, 1.2, 0.01, 0.8), CURVE],
|
|
19
|
+
pawPrint: [CURVE],
|
|
20
|
+
superformula: [
|
|
21
|
+
int('symmetry', 'Symmetry', 1, 20, 6), num('roundness', 'Roundness', 0.1, 2, 0.05, 0.3),
|
|
22
|
+
num('twist1', 'Twist 1', 0.1, 4, 0.05, 0.3), num('twist2', 'Twist 2', 0.1, 4, 0.05, 0.3),
|
|
23
|
+
num('stretchX', 'Stretch X', 0.3, 2, 0.05, 1), num('stretchY', 'Stretch Y', 0.3, 2, 0.05, 1),
|
|
24
|
+
int('samples', 'Resolution', 32, 512, 256), CURVE,
|
|
25
|
+
],
|
|
26
|
+
infinity: [num('waist', 'Waist', 0.04, 0.3, 0.01, 0.14), num('thickness', 'Ribbon', 0.05, 0.25, 0.01, 0.12), int('samples', 'Resolution', 64, 512, 220), CURVE],
|
|
27
|
+
box: [int('subdivisions', 'Subdivisions', 1, 24, 1)],
|
|
28
|
+
sphere: [num('radius', 'Radius', 0.1, 2, 0.01, 0.5), int('segments', 'Segments', 3, 64, 32), int('rings', 'Rings', 2, 64, 32)],
|
|
29
|
+
cylinder: [num('radiusTop', 'Top radius', 0, 2, 0.01, 0.5), num('radiusBottom', 'Bottom radius', 0, 2, 0.01, 0.5), num('height', 'Height', 0.1, 3, 0.01, 1), int('radialSegments', 'Radial segments', 3, 64, 32)],
|
|
30
|
+
cone: [num('radius', 'Radius', 0.1, 2, 0.01, 0.5), num('height', 'Height', 0.1, 3, 0.01, 1), int('radialSegments', 'Radial segments', 3, 64, 32)],
|
|
31
|
+
torus: [num('radius', 'Radius', 0.1, 2, 0.01, 0.5), num('tube', 'Tube', 0.02, 0.6, 0.01, 0.2), int('radialSegments', 'Radial segments', 3, 64, 16), int('tubularSegments', 'Tubular segments', 3, 200, 100)],
|
|
32
|
+
capsule: [num('radius', 'Radius', 0.05, 1.5, 0.01, 0.3), num('length', 'Length', 0.1, 3, 0.01, 1), int('capSegments', 'Cap segments', 1, 16, 4), int('radialSegments', 'Radial segments', 3, 64, 8)],
|
|
33
|
+
icosahedron: [num('radius', 'Radius', 0.1, 2, 0.01, 0.5), int('detail', 'Detail', 0, 5, 0)],
|
|
34
|
+
octahedron: [num('radius', 'Radius', 0.1, 2, 0.01, 0.5), int('detail', 'Detail', 0, 5, 0)],
|
|
35
|
+
tetrahedron: [num('radius', 'Radius', 0.1, 2, 0.01, 0.5), int('detail', 'Detail', 0, 5, 0)],
|
|
36
|
+
dodecahedron: [num('radius', 'Radius', 0.1, 2, 0.01, 0.5), int('detail', 'Detail', 0, 5, 0)],
|
|
37
|
+
plane: [num('width', 'Width', 0.2, 3, 0.01, 1), num('height', 'Height', 0.2, 3, 0.01, 1), int('widthSegments', 'Width segments', 1, 64, 1), int('heightSegments', 'Height segments', 1, 64, 1)],
|
|
38
|
+
ring: [num('innerRadius', 'Inner radius', 0.05, 1.5, 0.01, 0.3), num('outerRadius', 'Outer radius', 0.1, 2, 0.01, 0.8), int('thetaSegments', 'Theta segments', 3, 64, 32), int('phiSegments', 'Phi segments', 1, 32, 8)],
|
|
39
|
+
arcPlane: [num('radius', 'Radius', 0.2, 3, 0.01, 1), num('width', 'Band width', 0.02, 1, 0.01, 0.2), ang('startAngle', 'Start angle', 0), ang('endAngle', 'End angle', Math.PI), int('segments', 'Segments', 3, 128, 32)],
|
|
40
|
+
bentPlane: [num('radius', 'Radius', 0.2, 5, 0.01, 2), num('height', 'Height', 0.1, 3, 0.01, 1), ang('arc', 'Arc', Math.PI / 2), int('widthSegments', 'Width segments', 1, 64, 32), int('heightSegments', 'Height segments', 1, 64, 1)],
|
|
41
|
+
bentPlaneInverse: [num('radius', 'Radius', 0.2, 5, 0.01, 2), num('height', 'Height', 0.1, 3, 0.01, 1), ang('arc', 'Arc', Math.PI / 2), int('widthSegments', 'Width segments', 1, 64, 32), int('heightSegments', 'Height segments', 1, 64, 1)],
|
|
42
|
+
text: [str('text', 'Text', 'Hello'), num('size', 'Size', 0.2, 3, 0.01, 1), num('height', 'Depth', 0.05, 1, 0.01, 0.2)],
|
|
43
|
+
point: [num('size', 'Size', 0.02, 0.5, 0.01, 0.1)],
|
|
44
|
+
custom: [],
|
|
45
|
+
};
|
|
46
|
+
export const ALL_SHAPES = Object.keys(SHAPE_CONTROLS);
|
|
47
|
+
export function defaultShapeOptions(type = 'heart') {
|
|
48
|
+
const opts = { type };
|
|
49
|
+
for (const c of SHAPE_CONTROLS[type])
|
|
50
|
+
opts[c.key] = c.default;
|
|
51
|
+
return opts;
|
|
52
|
+
}
|
|
53
|
+
export function defaultShapeConfig(type = 'heart') {
|
|
54
|
+
return defaultShapeOptions(type);
|
|
55
|
+
}
|
|
56
|
+
export function defaultModeConfig(mode = 'solid') {
|
|
57
|
+
return { mode, count: 1000, symmetry: 6, spacing: 1, slices: 24, linkRadius: 0.18, angle: 18, lineWidth: 2.5 };
|
|
58
|
+
}
|
|
59
|
+
const cnt = { type: 'range', key: 'count', label: 'Count', min: 1000, max: 40000, step: 500, default: 1000, format: (v) => v.toLocaleString() };
|
|
60
|
+
const lw = { type: 'range', key: 'lineWidth', label: 'Line weight', min: 0.5, max: 8, step: 0.1, default: 2.5, digits: 1 };
|
|
61
|
+
export const MODE_CONTROLS = {
|
|
62
|
+
solid: [],
|
|
63
|
+
volume: [cnt],
|
|
64
|
+
surface: [cnt],
|
|
65
|
+
symmetric: [cnt, int('symmetry', 'Symmetry', 2, 16, 6)],
|
|
66
|
+
evenScatter: [cnt, num('spacing', 'Spacing', 0.5, 3, 0.05, 1)],
|
|
67
|
+
vertices: [],
|
|
68
|
+
edges3d: [int('angle', 'Edge angle', 0, 80, 18), lw],
|
|
69
|
+
profile2d: [lw],
|
|
70
|
+
wireframe: [lw],
|
|
71
|
+
contourSlices: [int('slices', 'Slices', 4, 60, 24), lw],
|
|
72
|
+
plexus: [cnt, num('linkRadius', 'Link radius', 0.05, 0.5, 0.01, 0.18), lw],
|
|
73
|
+
};
|
|
74
|
+
export const MODE_GROUPS = [
|
|
75
|
+
{ label: 'mesh', modes: ['solid'] },
|
|
76
|
+
{ label: 'points', modes: ['volume', 'surface', 'symmetric', 'evenScatter', 'vertices'] },
|
|
77
|
+
{ label: 'lines', modes: ['edges3d', 'profile2d', 'wireframe', 'contourSlices', 'plexus'] },
|
|
78
|
+
];
|
|
79
|
+
export const MODE_LABEL = {
|
|
80
|
+
solid: 'Solid',
|
|
81
|
+
volume: 'Volume',
|
|
82
|
+
surface: 'Surface',
|
|
83
|
+
symmetric: 'Symmetric',
|
|
84
|
+
evenScatter: 'Even',
|
|
85
|
+
vertices: 'Vertices',
|
|
86
|
+
edges3d: 'Edges',
|
|
87
|
+
profile2d: 'Profile',
|
|
88
|
+
wireframe: 'Wireframe',
|
|
89
|
+
contourSlices: 'Contours',
|
|
90
|
+
plexus: 'Plexus',
|
|
91
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getPropertyConfig.d.ts","sourceRoot":"","sources":["../../../src/properties/tables/getPropertyConfig.ts"],"names":[],"mappings":"AAWA,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,sDAK7C,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Moved from client (client/app/utils/getPropertyConfig.ts).
|
|
2
|
+
import { EFFECT_PROPERTIES } from './effectsProperties.js';
|
|
3
|
+
import { PARTICLES_PROPERTIES } from './particlesProperties.js';
|
|
4
|
+
import { environmentOptionalProperties } from './optionalProperties.js';
|
|
5
|
+
const allProperties = {
|
|
6
|
+
...EFFECT_PROPERTIES,
|
|
7
|
+
...PARTICLES_PROPERTIES,
|
|
8
|
+
...environmentOptionalProperties,
|
|
9
|
+
};
|
|
10
|
+
/** Property rows for a generative effect / particles type or an environment element. */
|
|
11
|
+
export const getPropertyConfig = (type) => {
|
|
12
|
+
if (type in allProperties) {
|
|
13
|
+
return allProperties[type];
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { OptionalProperty } from './optionalProperties';
|
|
2
|
+
/** Knobs every shader-plane grid shares. */
|
|
3
|
+
export declare const GRID_SURFACE_PROPERTIES: OptionalProperty[];
|
|
4
|
+
/** Every shader-plane grid's inputs: its own knobs first, then the shared surface. */
|
|
5
|
+
export declare const GRID_PROPERTIES: Record<string, OptionalProperty[]>;
|
|
6
|
+
//# sourceMappingURL=gridProperties.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gridProperties.d.ts","sourceRoot":"","sources":["../../../src/properties/tables/gridProperties.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAiB7D,4CAA4C;AAC5C,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAwBrD,CAAC;AAmFF,sFAAsF;AACtF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAE9D,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// GRID OPTIONAL PROPERTIES
|
|
3
|
+
// The configurable inputs of each shader-plane grid (createdObject type 'grid'),
|
|
4
|
+
// keyed by config.type. Every grid shares the surface vocabulary below; each adds
|
|
5
|
+
// its own knobs. Rendered by ConfigControllerUi, so a grid slider looks and behaves
|
|
6
|
+
// like every other slider in the app.
|
|
7
|
+
//
|
|
8
|
+
// Each entry must be a real config key of that grid (viewer types/gridConfigs.ts).
|
|
9
|
+
// =============================================================================
|
|
10
|
+
const LINE_MODES = ['0', '1', '2', '3', '4'];
|
|
11
|
+
const LINE_MODE_LABELS = ['Static', 'Ripple', 'Flow', 'Scan', 'Pulse'];
|
|
12
|
+
const CELL_MODES = ['0', '1', '2', '3', '4'];
|
|
13
|
+
const CELL_MODE_LABELS = ['Off', 'Wave', 'Twinkle', 'Ripple', 'Alternate'];
|
|
14
|
+
/** Knobs every shader-plane grid shares. */
|
|
15
|
+
export const GRID_SURFACE_PROPERTIES = [
|
|
16
|
+
{ name: 'cellSize', description: 'Size of one tile, in world units', type: 'number', min: 0.1, max: 40, step: 0.1 },
|
|
17
|
+
{ name: 'lineWidth', description: 'Line thickness, in pixels', type: 'number', min: 0, max: 6, step: 0.05 },
|
|
18
|
+
{ name: 'sectionSize', description: 'How many tiles make one accent group', type: 'number', min: 0, max: 20, step: 1 },
|
|
19
|
+
{ name: 'sectionWidth', description: 'Accent line thickness, in pixels; 0 hides the accents', type: 'number', min: 0, max: 6, step: 0.05 },
|
|
20
|
+
{ name: 'lineMode', description: 'How the lines animate', type: 'select', options: LINE_MODES, optionLabels: LINE_MODE_LABELS },
|
|
21
|
+
{ name: 'cellMode', description: 'How the cells light up', type: 'select', options: CELL_MODES, optionLabels: CELL_MODE_LABELS },
|
|
22
|
+
{ name: 'animSpeed', description: 'Animation speed', type: 'number', min: 0, max: 5, step: 0.05 },
|
|
23
|
+
{ name: 'animScale', description: 'Spatial scale of the animation', type: 'number', min: 0, max: 3, step: 0.05 },
|
|
24
|
+
{ name: 'animIntensity', description: 'Strength of the animation', type: 'number', min: 0, max: 3, step: 0.05 },
|
|
25
|
+
{ name: 'fadeDistance', description: 'Radius at which the grid fades out', type: 'number', min: 1, max: 200, step: 0.5 },
|
|
26
|
+
{ name: 'fadeStrength', description: 'How hard the edge fades', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
27
|
+
{ name: 'displace', description: 'Lift the surface along its normal (subdivides the plane)', type: 'number', min: 0, max: 5, step: 0.05 },
|
|
28
|
+
{ name: 'size', description: 'Size of the plane, per side', type: 'number', min: 5, max: 400, step: 1 },
|
|
29
|
+
{ name: 'lineColor', description: 'Line colour', type: 'color' },
|
|
30
|
+
{ name: 'sectionColor', description: 'Accent colour', type: 'color' },
|
|
31
|
+
{ name: 'cellColor', description: 'Cell fill colour', type: 'color' },
|
|
32
|
+
{ name: 'glowColor', description: 'Glow colour of the animated highlights', type: 'color' },
|
|
33
|
+
{ name: 'bgColor', description: 'Background colour', type: 'color' },
|
|
34
|
+
{ name: 'bgOpacity', description: 'Background opacity; 0 leaves only the lines', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
35
|
+
{ name: 'flat', description: 'Lie flat (on) or stand upright (off)', type: 'boolean' },
|
|
36
|
+
{ name: 'followMouse', description: 'Ripples and focus follow the pointer', type: 'boolean' },
|
|
37
|
+
{ name: 'reveal', description: 'How much of the grid is built (0 gone, 1 complete)', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
38
|
+
{ name: 'revealDuration', description: 'Seconds to build or dissolve; 0 applies instantly', type: 'number', min: 0, max: 10, step: 0.1 },
|
|
39
|
+
];
|
|
40
|
+
const own = {
|
|
41
|
+
advancedGrid: [],
|
|
42
|
+
quasiGrid: [
|
|
43
|
+
{ name: 'symmetry', description: 'Line families, 3..9. 5 is Penrose; 4 and 6 come out periodic', type: 'number', min: 3, max: 9, step: 1 },
|
|
44
|
+
{ name: 'phase', description: 'Slides the pattern through itself', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
45
|
+
],
|
|
46
|
+
hexGrid: [
|
|
47
|
+
{ name: 'plateau', description: 'With displacement, each hex lifts as a flat plate', type: 'boolean' },
|
|
48
|
+
],
|
|
49
|
+
circuitGrid: [
|
|
50
|
+
{ name: 'powered', description: 'Fraction of tiles carrying a powered trace', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
51
|
+
{ name: 'chipChance', description: 'Fraction of tiles replaced by a chip; 0 disables chips', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
52
|
+
{ name: 'padSize', description: 'Solder-pad size; 0 disables pads', type: 'number', min: 0, max: 2, step: 0.01 },
|
|
53
|
+
],
|
|
54
|
+
voronoiGrid: [
|
|
55
|
+
{ name: 'jitter', description: '0 regular lattice, 1 fully scattered seeds', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
56
|
+
{ name: 'drift', description: 'How far the seeds wander; 0 freezes the cells', type: 'number', min: 0, max: 2, step: 0.01 },
|
|
57
|
+
],
|
|
58
|
+
radarGrid: [
|
|
59
|
+
{ name: 'spokes', description: 'Radial spokes; 0 disables them', type: 'number', min: 0, max: 72, step: 1 },
|
|
60
|
+
{ name: 'sweepWidth', description: 'Length of the sweep trail, as a fraction of a turn', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
61
|
+
{ name: 'blipDensity', description: 'Chance a sector holds a blip', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
62
|
+
],
|
|
63
|
+
moireGrid: [
|
|
64
|
+
{ name: 'shape', description: 'Lattice shape of both layers', type: 'select', options: ['square', 'hex', 'rings'], optionLabels: ['Square', 'Hex', 'Rings'] },
|
|
65
|
+
{ name: 'layerAngle', description: 'Angle between the layers, in radians; small values beat slowly', type: 'number', min: 0, max: 0.5, step: 0.001 },
|
|
66
|
+
{ name: 'layerScale', description: 'Spacing ratio of the second layer; near 1 gives long beats', type: 'number', min: 0.8, max: 1.25, step: 0.001 },
|
|
67
|
+
{ name: 'spin', description: 'Counter-rotation speed; 0 freezes the pattern', type: 'number', min: -5, max: 5, step: 0.05 },
|
|
68
|
+
],
|
|
69
|
+
fractalGrid: [
|
|
70
|
+
{ name: 'depth', description: 'Maximum subdivision levels', type: 'number', min: 1, max: 6, step: 1 },
|
|
71
|
+
{ name: 'splitRadius', description: 'Radius around the focus inside which cells subdivide', type: 'number', min: 0, max: 10, step: 0.05 },
|
|
72
|
+
{ name: 'splitJitter', description: 'Wobble of the split edge', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
73
|
+
],
|
|
74
|
+
contourGrid: [
|
|
75
|
+
{ name: 'levels', description: 'Contour steps across the height range', type: 'number', min: 2, max: 64, step: 1 },
|
|
76
|
+
{ name: 'roughness', description: 'Terrain roughness: 0.35 rolling, 0.65 craggy', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
77
|
+
{ name: 'warp', description: 'Bends the contours into ridges and valleys', type: 'number', min: 0, max: 2, step: 0.01 },
|
|
78
|
+
],
|
|
79
|
+
flowNetGrid: [
|
|
80
|
+
{ name: 'obstacleRadius', description: 'Cylinder radius, in cells', type: 'number', min: 0, max: 10, step: 0.05 },
|
|
81
|
+
{ name: 'circulation', description: 'Circulation around the cylinder (lift)', type: 'number', min: -6, max: 6, step: 1 },
|
|
82
|
+
{ name: 'flowAngle', description: 'Free-stream direction, in radians', type: 'number', min: -3.1416, max: 3.1416, step: 0.01 },
|
|
83
|
+
],
|
|
84
|
+
chladniGrid: [
|
|
85
|
+
{ name: 'modeN', description: 'First mode number of the standing wave', type: 'number', min: 1, max: 12, step: 1 },
|
|
86
|
+
{ name: 'modeM', description: 'Second mode number of the standing wave', type: 'number', min: 1, max: 12, step: 1 },
|
|
87
|
+
{ name: 'morph', description: 'Drift to the neighbouring resonance; 0 holds the pattern', type: 'number', min: 0, max: 2, step: 0.01 },
|
|
88
|
+
{ name: 'grain', description: 'Amount of sand on the plate', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
89
|
+
],
|
|
90
|
+
hyperbolicGrid: [
|
|
91
|
+
{ name: 'sides', description: 'Sides of each polygon (p)', type: 'number', min: 3, max: 12, step: 1 },
|
|
92
|
+
{ name: 'valence', description: 'Polygons around each vertex (q)', type: 'number', min: 3, max: 12, step: 1 },
|
|
93
|
+
{ name: 'drift', description: 'How far the tiling glides through itself', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
94
|
+
],
|
|
95
|
+
gravWaveGrid: [
|
|
96
|
+
{ name: 'strain', description: 'Wave amplitude; 0 leaves only the static wells', type: 'number', min: 0, max: 3, step: 0.01 },
|
|
97
|
+
{ name: 'chirpTime', description: 'Seconds per inspiral-merger-ringdown cycle', type: 'number', min: 4, max: 60, step: 0.5 },
|
|
98
|
+
{ name: 'waveSpeed', description: 'Wave speed, in cells per second', type: 'number', min: 0.5, max: 20, step: 0.1 },
|
|
99
|
+
{ name: 'massRatio', description: 'Mass ratio m2/m1', type: 'number', min: 0.1, max: 1, step: 0.01 },
|
|
100
|
+
],
|
|
101
|
+
girihGrid: [
|
|
102
|
+
{ name: 'tiling', description: 'Base tiling', type: 'select', options: ['0', '1', '2'], optionLabels: ['4.8.8', 'Hexagons', '3.6.3.6'] },
|
|
103
|
+
{ name: 'contactAngle', description: 'Hankin contact angle, degrees; 67.5 is the classic 8-point star', type: 'number', min: 20, max: 85, step: 0.5 },
|
|
104
|
+
{ name: 'strapWidth', description: 'Width of the strapwork band, in cells', type: 'number', min: 0, max: 0.3, step: 0.005 },
|
|
105
|
+
{ name: 'angleDrift', description: 'Degrees the contact angle drifts, morphing the pattern', type: 'number', min: 0, max: 30, step: 0.5 },
|
|
106
|
+
],
|
|
107
|
+
wallpaperGrid: [
|
|
108
|
+
{ name: 'group', description: 'Wallpaper group (-1 cycles through all 17)', type: 'number', min: -1, max: 16, step: 1 },
|
|
109
|
+
{ name: 'cycleTime', description: 'Seconds per group while cycling', type: 'number', min: 1, max: 60, step: 0.5 },
|
|
110
|
+
{ name: 'motif', description: 'Motif complexity', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
111
|
+
{ name: 'levels', description: 'Number of contour levels', type: 'number', min: 2, max: 32, step: 1 },
|
|
112
|
+
],
|
|
113
|
+
reactionDiffusionGrid: [
|
|
114
|
+
{ name: 'feed', description: 'Gray-Scott feed rate F', type: 'number', min: 0.01, max: 0.08, step: 0.0005 },
|
|
115
|
+
{ name: 'kill', description: 'Gray-Scott kill rate k', type: 'number', min: 0.04, max: 0.075, step: 0.0005 },
|
|
116
|
+
{ name: 'variation', description: 'Spread of F and k across the tile, so morphologies coexist', type: 'number', min: 0, max: 1, step: 0.01 },
|
|
117
|
+
{ name: 'tileCells', description: 'Cells covered by one simulation tile', type: 'number', min: 1, max: 20, step: 1 },
|
|
118
|
+
],
|
|
119
|
+
};
|
|
120
|
+
/** Every shader-plane grid's inputs: its own knobs first, then the shared surface. */
|
|
121
|
+
export const GRID_PROPERTIES = Object.fromEntries(Object.entries(own).map(([type, props]) => [type, [...props, ...GRID_SURFACE_PROPERTIES]]));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './optionalProperties';
|
|
2
|
+
export * from './lightProperties';
|
|
3
|
+
export * from './particlesProperties';
|
|
4
|
+
export * from './effectsProperties';
|
|
5
|
+
export * from './gridProperties';
|
|
6
|
+
export * from './materialBounds';
|
|
7
|
+
export * from './getPropertyConfig';
|
|
8
|
+
export * from './geometryProperties';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/properties/tables/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './optionalProperties.js';
|
|
2
|
+
export * from './lightProperties.js';
|
|
3
|
+
export * from './particlesProperties.js';
|
|
4
|
+
export * from './effectsProperties.js';
|
|
5
|
+
export * from './gridProperties.js';
|
|
6
|
+
export * from './materialBounds.js';
|
|
7
|
+
export * from './getPropertyConfig.js';
|
|
8
|
+
export * from './geometryProperties.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LightType } from '../../types/lights';
|
|
2
|
+
import type { OptionalProperty } from './optionalProperties';
|
|
3
|
+
export type LightTab = 'light' | 'bulb' | 'beam' | 'array' | 'tube' | 'flame' | 'candle';
|
|
4
|
+
export type LightProperty = OptionalProperty & {
|
|
5
|
+
tab?: LightTab;
|
|
6
|
+
};
|
|
7
|
+
export declare const LIGHT_PROPERTIES: Record<LightType, LightProperty[]>;
|
|
8
|
+
/** Re-export under the name the controller already uses; the table itself lives in core. */
|
|
9
|
+
export declare const LIGHT_DEFAULTS: Record<LightType, Record<string, unknown>>;
|
|
10
|
+
/** Knobs hidden by another knob's value (colour vs temperature, tint only when tinted). */
|
|
11
|
+
export declare function isLightPropertyHidden(name: string, values: Record<string, unknown>): boolean;
|
|
12
|
+
export declare const SHADOW_MAP_SIZES: string[];
|
|
13
|
+
export declare const SHADOW_PROPERTIES: Record<LightType, OptionalProperty[]>;
|
|
14
|
+
//# sourceMappingURL=lightProperties.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lightProperties.d.ts","sourceRoot":"","sources":["../../../src/properties/tables/lightProperties.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AACzF,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG;IAAE,GAAG,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC;AAQlE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,CA4I/D,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAkB,CAAC;AAEzF,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CA2C5F;AAMD,eAAO,MAAM,gBAAgB,UAAyC,CAAC;AAmBvE,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,gBAAgB,EAAE,CAkBnE,CAAC"}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
// Moved from client (client/app/utils/lightProperties.ts). Property tables — the registry (../registry) is built on these.
|
|
2
|
+
// =============================================================================
|
|
3
|
+
// lightProperties — the knobs LightControllerUi shows, per light type
|
|
4
|
+
// =============================================================================
|
|
5
|
+
//
|
|
6
|
+
// OptionalProperty arrays in the same shape as PARTICLES_PROPERTIES, so the
|
|
7
|
+
// light panel renders with BaseControllerUi's PropertiesTab / ColorsTab and
|
|
8
|
+
// looks like every other controller.
|
|
9
|
+
//
|
|
10
|
+
// `tab` groups a knob; only the bulb has more than one ('light' + 'bulb').
|
|
11
|
+
// LIGHT_DEFAULTS fills in a knob a saved config does not carry yet (every
|
|
12
|
+
// light saved before the bulb existed has no `temperature`, for one), so the
|
|
13
|
+
// control still shows instead of silently disappearing.
|
|
14
|
+
//
|
|
15
|
+
import { DEFAULT_LIGHTS } from '../../data/lightsDefaults.js';
|
|
16
|
+
const enabled = { name: 'enabled', label: 'Enabled', type: 'boolean', description: 'Switch the light off without deleting it' };
|
|
17
|
+
const color = { name: 'color', type: 'color', description: 'Light colour' };
|
|
18
|
+
const intensity = (max) => ({ name: 'intensity', type: 'number', min: 0, max, step: 0.01, description: 'Brightness of the light' });
|
|
19
|
+
const distance = { name: 'distance', type: 'number', min: 0, max: 100, step: 0.1, description: 'Range of the light. 0 = unlimited' };
|
|
20
|
+
const decay = { name: 'decay', type: 'number', min: 0, max: 2, step: 0.01, description: 'How fast the light dims with distance. 2 is physically correct' };
|
|
21
|
+
export const LIGHT_PROPERTIES = {
|
|
22
|
+
ambient: [enabled, intensity(5), color],
|
|
23
|
+
directional: [enabled, intensity(10), color],
|
|
24
|
+
point: [enabled, intensity(20), distance, decay, color],
|
|
25
|
+
spot: [
|
|
26
|
+
enabled, intensity(20), distance, decay,
|
|
27
|
+
{ name: 'angle', type: 'number', min: 0.01, max: Math.PI / 2, step: 0.01, description: 'Cone half-angle, radians' },
|
|
28
|
+
{ name: 'penumbra', type: 'number', min: 0, max: 1, step: 0.01, description: 'Softness of the cone edge' },
|
|
29
|
+
color,
|
|
30
|
+
],
|
|
31
|
+
lightBulb: [
|
|
32
|
+
// Light tab
|
|
33
|
+
{ ...enabled, tab: 'light' },
|
|
34
|
+
{ name: 'on', label: 'Power', type: 'boolean', tab: 'light', description: 'Switch the bulb on or off. Runs the warm-up / cool-down' },
|
|
35
|
+
{ name: 'colorMode', label: 'Colour', type: 'select', tab: 'light', options: ['temperature', 'color'], optionLabels: ['Temperature', 'Custom colour'], description: 'Drive the colour from a Kelvin temperature, or pick one' },
|
|
36
|
+
{ ...intensity(20), tab: 'light' },
|
|
37
|
+
{ name: 'temperature', label: 'Temperature (K)', type: 'number', min: 1000, max: 10000, step: 50, tab: 'light', description: '2700K warm incandescent, 4000K neutral, 6500K daylight' },
|
|
38
|
+
{ ...distance, tab: 'light' },
|
|
39
|
+
{ ...decay, tab: 'light' },
|
|
40
|
+
{ ...color, tab: 'light' },
|
|
41
|
+
// Bulb tab
|
|
42
|
+
{ name: 'shape', type: 'select', tab: 'bulb', options: ['classic', 'globe', 'edison', 'tube'], optionLabels: ['Classic', 'Globe', 'Edison', 'Tube'], description: 'Glass silhouette and matching filament' },
|
|
43
|
+
{ name: 'glass', type: 'select', tab: 'bulb', options: ['clear', 'frosted', 'tinted'], optionLabels: ['Clear', 'Frosted', 'Tinted'], description: 'Glass finish' },
|
|
44
|
+
{ name: 'warmup', label: 'Warm-up (s)', type: 'number', min: 0, max: 3, step: 0.05, tab: 'bulb', description: 'Time for the filament to heat up. Cooling takes ~2.5x longer. 0 = instant' },
|
|
45
|
+
{ name: 'flicker', type: 'number', min: 0, max: 1, step: 0.01, tab: 'bulb', description: 'Random dips in brightness' },
|
|
46
|
+
{ name: 'halo', type: 'number', min: 0, max: 2, step: 0.01, tab: 'bulb', description: 'Strength of the glow around the bulb' },
|
|
47
|
+
{ name: 'glassTint', label: 'Glass tint', type: 'color', tab: 'bulb', description: 'Glass colour when the glass is Tinted' },
|
|
48
|
+
],
|
|
49
|
+
spotBeam: [
|
|
50
|
+
// Light tab
|
|
51
|
+
{ ...enabled, tab: 'light' },
|
|
52
|
+
{ name: 'on', label: 'Power', type: 'boolean', tab: 'light', description: 'Switch the lamp on or off. Runs the warm-up' },
|
|
53
|
+
{ name: 'colorMode', label: 'Colour', type: 'select', tab: 'light', options: ['temperature', 'color'], optionLabels: ['Temperature', 'Custom colour'], description: 'Drive the colour from a Kelvin temperature, or pick one' },
|
|
54
|
+
{ ...intensity(50), tab: 'light' },
|
|
55
|
+
{ name: 'temperature', label: 'Temperature (K)', type: 'number', min: 1000, max: 10000, step: 50, tab: 'light', description: '3200K tungsten stage lamp, 5600K daylight' },
|
|
56
|
+
{ name: 'angle', type: 'number', min: 0.01, max: Math.PI / 2, step: 0.01, tab: 'light', description: 'Cone half-angle, radians' },
|
|
57
|
+
{ name: 'penumbra', type: 'number', min: 0, max: 1, step: 0.01, tab: 'light', description: 'Softness of the cone edge' },
|
|
58
|
+
{ ...distance, tab: 'light' },
|
|
59
|
+
{ ...decay, tab: 'light' },
|
|
60
|
+
{ ...color, tab: 'light' },
|
|
61
|
+
// Beam tab
|
|
62
|
+
{ name: 'pattern', label: 'Gobo', type: 'select', tab: 'beam', options: ['round', 'slot', 'bars', 'blinds', 'window', 'leaves'], optionLabels: ['Round', 'Slot', 'Bars', 'Blinds', 'Window', 'Leaves'], description: 'Shapes both the pool on the floor and the haze in the air' },
|
|
63
|
+
{ name: 'patternSoftness', label: 'Gobo softness', type: 'number', min: 0, max: 1, step: 0.01, tab: 'beam', description: 'Edge softness of the gobo' },
|
|
64
|
+
{ name: 'patternRotation', label: 'Gobo rotation', type: 'number', min: 0, max: Math.PI * 2, step: 0.01, tab: 'beam', description: 'Turns the gobo, radians' },
|
|
65
|
+
{ name: 'beamMode', label: 'Beam quality', type: 'select', tab: 'beam', options: ['none', 'soft', 'layered', 'volumetric'], optionLabels: ['None', 'Soft', 'Layered', 'Volumetric'], description: 'How the beam in the air is drawn. Volumetric carries the gobo through the haze and costs the most' },
|
|
66
|
+
{ name: 'beam', label: 'Beam', type: 'number', min: 0, max: 3, step: 0.01, tab: 'beam', description: 'Brightness of the beam in the air. 0 hides it' },
|
|
67
|
+
{ name: 'beamLength', label: 'Beam length', type: 'number', min: 0.05, max: 1, step: 0.01, tab: 'beam', description: 'How far down the throw the beam reaches' },
|
|
68
|
+
{ name: 'beamNoise', label: 'Haze', type: 'number', min: 0, max: 1, step: 0.01, tab: 'beam', description: 'Breakup in the beam, like smoke drifting through it' },
|
|
69
|
+
{ name: 'beamSteps', label: 'Beam steps', type: 'number', min: 8, max: 48, step: 1, tab: 'beam', description: 'Raymarch samples for the Volumetric beam. Higher is smoother and slower' },
|
|
70
|
+
{ name: 'emitter', label: 'Source', type: 'select', tab: 'beam', options: ['none', 'dot', 'lens'], optionLabels: ['Hidden', 'Dot', 'Lens'], description: 'The bit of visible geometry at the light itself' },
|
|
71
|
+
{ name: 'warmup', label: 'Warm-up (s)', type: 'number', min: 0, max: 3, step: 0.05, tab: 'beam', description: 'Time for the lamp to come up to full. 0 = instant' },
|
|
72
|
+
{ name: 'flicker', type: 'number', min: 0, max: 1, step: 0.01, tab: 'beam', description: 'Random dips in brightness' },
|
|
73
|
+
{ name: 'halo', type: 'number', min: 0, max: 2, step: 0.01, tab: 'beam', description: 'Strength of the glow around the source' },
|
|
74
|
+
],
|
|
75
|
+
ledArray: [
|
|
76
|
+
// Light tab
|
|
77
|
+
{ ...enabled, tab: 'light' },
|
|
78
|
+
{ name: 'on', label: 'Power', type: 'boolean', tab: 'light', description: 'Switch the array on or off. An LED has no thermal lag, so this is instant unless Warm-up says otherwise' },
|
|
79
|
+
{ name: 'colorMode', label: 'Colour', type: 'select', tab: 'light', options: ['temperature', 'color', 'rgb'], optionLabels: ['Temperature', 'Custom colour', 'RGB'], description: 'Kelvin, one colour, or a hue running across the array' },
|
|
80
|
+
{ ...intensity(40), tab: 'light' },
|
|
81
|
+
{ name: 'temperature', label: 'Temperature (K)', type: 'number', min: 1800, max: 10000, step: 50, tab: 'light', description: '2700K warm white, 4000K neutral, 6500K cool daylight' },
|
|
82
|
+
{ name: 'rgbSpread', label: 'Hue spread', type: 'number', min: 0, max: 2, step: 0.01, tab: 'light', description: 'How many turns of hue fit across the array' },
|
|
83
|
+
{ name: 'rgbSpeed', label: 'Chase', type: 'number', min: -2, max: 2, step: 0.01, tab: 'light', description: 'How fast the hue runs along the array' },
|
|
84
|
+
{ ...distance, tab: 'light' },
|
|
85
|
+
{ ...decay, tab: 'light' },
|
|
86
|
+
{ ...color, tab: 'light' },
|
|
87
|
+
// Array tab
|
|
88
|
+
{ name: 'layout', type: 'select', tab: 'array', options: ['single', 'strip', 'panel', 'ring'], optionLabels: ['Single', 'Strip', 'Panel', 'Ring'], description: 'How the dies are arranged' },
|
|
89
|
+
{ name: 'count', label: 'Dies', type: 'number', min: 1, max: 64, step: 1, tab: 'array', description: 'Dies along the main axis' },
|
|
90
|
+
{ name: 'rows', type: 'number', min: 1, max: 12, step: 1, tab: 'array', description: 'Rows of dies. Panel only' },
|
|
91
|
+
{ name: 'spacing', type: 'number', min: 0.005, max: 0.5, step: 0.005, tab: 'array', description: 'Distance between dies' },
|
|
92
|
+
{ name: 'dieSize', label: 'Die size', type: 'number', min: 0.002, max: 0.1, step: 0.001, tab: 'array', description: 'Size of one die' },
|
|
93
|
+
{ name: 'emitter', label: 'Source', type: 'select', tab: 'array', options: ['dies', 'none'], optionLabels: ['Dies', 'Hidden'], description: 'Hide the dies to leave only the light' },
|
|
94
|
+
{ name: 'diffuser', type: 'number', min: 0, max: 1, step: 0.01, tab: 'array', description: 'Sheet over the dies. A bigger source, so it softens the shadow too' },
|
|
95
|
+
{ name: 'pwm', label: 'PWM', type: 'number', min: 0, max: 1, step: 0.01, tab: 'array', description: 'The high-frequency chop a dimmed LED runs on. Reads as a slow strobe, the way a camera sees it' },
|
|
96
|
+
{ name: 'warmup', label: 'Warm-up (s)', type: 'number', min: 0, max: 3, step: 0.05, tab: 'array', description: 'Fade-up time. 0 = instant, which is what an LED actually does' },
|
|
97
|
+
{ name: 'flicker', type: 'number', min: 0, max: 1, step: 0.01, tab: 'array', description: 'Random dips in brightness' },
|
|
98
|
+
{ name: 'halo', type: 'number', min: 0, max: 2, step: 0.01, tab: 'array', description: 'Strength of the glow around the array' },
|
|
99
|
+
],
|
|
100
|
+
fluorescentTube: [
|
|
101
|
+
// Light tab
|
|
102
|
+
{ ...enabled, tab: 'light' },
|
|
103
|
+
{ name: 'on', label: 'Power', type: 'boolean', tab: 'light', description: 'Switch the fixture on or off' },
|
|
104
|
+
{ name: 'colorMode', label: 'Colour', type: 'select', tab: 'light', options: ['temperature', 'color'], optionLabels: ['Temperature', 'Custom colour'], description: 'Drive the colour from a Kelvin temperature, or pick one' },
|
|
105
|
+
{ ...intensity(60), tab: 'light' },
|
|
106
|
+
{ name: 'temperature', label: 'Temperature (K)', type: 'number', min: 2700, max: 8000, step: 50, tab: 'light', description: '3000K warm white, 4000K cool white, 6500K daylight' },
|
|
107
|
+
{ name: 'greenShift', label: 'Green spike', type: 'number', min: 0, max: 1, step: 0.01, tab: 'light', description: "The phosphor's green cast. Real halophosphate tubes read distinctly green next to daylight" },
|
|
108
|
+
{ name: 'shadowStrength', label: 'Shadow core', type: 'number', min: 0, max: 1, step: 0.01, tab: 'light', description: 'Share of the output coming from a point at the middle of the fixture. A rect-area light cannot cast a shadow, so only this part does. 0 = pure soft area light, no shadow' },
|
|
109
|
+
{ ...color, tab: 'light' },
|
|
110
|
+
// Tube tab
|
|
111
|
+
{ name: 'tubes', type: 'number', min: 1, max: 4, step: 1, tab: 'tube', description: 'Tubes in the fixture' },
|
|
112
|
+
{ name: 'tubeSpacing', label: 'Tube spacing', type: 'number', min: 0.02, max: 0.6, step: 0.005, tab: 'tube', description: 'Distance between tubes' },
|
|
113
|
+
{ name: 'length', type: 'number', min: 0.1, max: 4, step: 0.05, tab: 'tube', description: 'Tube length' },
|
|
114
|
+
{ name: 'diameter', type: 'number', min: 0.006, max: 0.12, step: 0.002, tab: 'tube', description: 'Tube diameter' },
|
|
115
|
+
{ name: 'emitter', label: 'Source', type: 'select', tab: 'tube', options: ['tubes', 'none'], optionLabels: ['Tubes', 'Hidden'], description: 'Hide the tubes to leave only the light' },
|
|
116
|
+
{ name: 'startup', type: 'select', tab: 'tube', options: ['instant', 'stutter'], optionLabels: ['Instant', 'Stutter'], description: 'Stutter strikes the arc with false starts first, the way a magnetic ballast does' },
|
|
117
|
+
{ name: 'warmup', label: 'Warm-up (s)', type: 'number', min: 0, max: 5, step: 0.05, tab: 'tube', description: 'Time for the mercury vapour to reach full output' },
|
|
118
|
+
{ name: 'hum', label: 'Ballast hum', type: 'number', min: 0, max: 1, step: 0.01, tab: 'tube', description: 'Depth of the 100 Hz ripple a magnetic ballast leaves in the light' },
|
|
119
|
+
{ name: 'age', type: 'number', min: 0, max: 1, step: 0.01, tab: 'tube', description: 'Wear: dimmer, blackened ends, a longer strike and more flicker' },
|
|
120
|
+
// The rect-area light has neither; these govern the shadow core only.
|
|
121
|
+
{ ...distance, tab: 'tube', description: 'Range of the shadow core. 0 = unlimited' },
|
|
122
|
+
{ ...decay, tab: 'tube', description: 'How fast the shadow core dims with distance. 2 is physically correct' },
|
|
123
|
+
{ name: 'flicker', type: 'number', min: 0, max: 1, step: 0.01, tab: 'tube', description: 'Random dips in brightness, on top of whatever Age adds' },
|
|
124
|
+
{ name: 'halo', type: 'number', min: 0, max: 2, step: 0.01, tab: 'tube', description: 'Strength of the wash around the fixture' },
|
|
125
|
+
],
|
|
126
|
+
candle: [
|
|
127
|
+
// Light tab
|
|
128
|
+
{ ...enabled, tab: 'light' },
|
|
129
|
+
{ name: 'on', label: 'Lit', type: 'boolean', tab: 'light', description: 'Lighting it runs the ignition; putting it out snuffs the flame and leaves a thread of smoke' },
|
|
130
|
+
{ name: 'colorMode', label: 'Colour', type: 'select', tab: 'light', options: ['temperature', 'color'], optionLabels: ['Temperature', 'Custom colour'], description: 'Drive the colour from a Kelvin temperature, or pick one' },
|
|
131
|
+
{ ...intensity(6), tab: 'light' },
|
|
132
|
+
{ name: 'temperature', label: 'Temperature (K)', type: 'number', min: 1200, max: 3200, step: 10, tab: 'light', description: 'A candle is about 1850K' },
|
|
133
|
+
{ ...distance, tab: 'light' },
|
|
134
|
+
{ ...decay, tab: 'light' },
|
|
135
|
+
{ ...color, tab: 'light' },
|
|
136
|
+
// Flame tab
|
|
137
|
+
{ name: 'flameMode', label: 'Flame quality', type: 'select', tab: 'flame', options: ['volumetric', 'billboard'], optionLabels: ['Volumetric', 'Billboard'], description: 'Volumetric raymarches the flame, so it has real depth from every angle. Billboard is the same flame on one quad — for scenes full of candles' },
|
|
138
|
+
{ name: 'flameHeight', label: 'Flame height', type: 'number', min: 0.008, max: 0.2, step: 0.001, tab: 'flame', description: 'A real candle flame is 3-6 cm' },
|
|
139
|
+
{ name: 'flameWidth', label: 'Flame width', type: 'number', min: 0.2, max: 2, step: 0.01, tab: 'flame', description: 'Width relative to the height' },
|
|
140
|
+
{ name: 'movement', type: 'number', min: 0, max: 1, step: 0.01, tab: 'flame', description: 'How much the flame moves at all. 0 holds it perfectly still — it can still flicker in brightness' },
|
|
141
|
+
{ name: 'flicker', type: 'number', min: 0, max: 1, step: 0.01, tab: 'flame', description: 'Depth of the brightness dip. This is the light’s output, not its shape' },
|
|
142
|
+
{ name: 'flickerHz', label: 'Flicker rate (Hz)', type: 'number', min: 4, max: 20, step: 0.1, tab: 'flame', description: 'Real candle flames oscillate near 11 Hz almost regardless of size' },
|
|
143
|
+
{ name: 'draught', type: 'number', min: 0, max: 1, step: 0.01, tab: 'flame', description: 'Air movement: lean, stretch, turbulence, and guttering once it is strong' },
|
|
144
|
+
{ name: 'blue', label: 'Blue base', type: 'number', min: 0, max: 1, step: 0.01, tab: 'flame', description: 'The blue cone at the wick, where there is plenty of oxygen' },
|
|
145
|
+
{ name: 'blueBasePercentage', label: 'Blue base height', type: 'number', min: 0, max: 100, step: 1, tab: 'flame', description: 'How much of the flame’s height reads blue, as a percentage. Past about 40 it fills in rather than staying a collar' },
|
|
146
|
+
{ name: 'soot', type: 'number', min: 0, max: 1, step: 0.01, tab: 'flame', description: 'How much the soot absorbs: gives the flame a body instead of a ghost' },
|
|
147
|
+
{ name: 'flameSteps', label: 'Raymarch steps', type: 'number', min: 8, max: 40, step: 1, tab: 'flame', description: 'Volumetric only. Higher is smoother and slower' },
|
|
148
|
+
{ name: 'flameGain', label: 'Flame gain', type: 'number', min: 1, max: 20, step: 0.1, tab: 'flame', description: 'Emission scale. Raise for a hotter, whiter flame' },
|
|
149
|
+
{ name: 'flameWhite', label: 'White point', type: 'number', min: 1.5, max: 10, step: 0.1, tab: 'flame', description: 'Where the flame\u2019s own knee clips to white. Lower blows the core out sooner' },
|
|
150
|
+
{ name: 'ignite', label: 'Ignition (s)', type: 'number', min: 0, max: 5, step: 0.05, tab: 'flame', description: 'Time for the wick to catch and the flame to establish. 0 = instant' },
|
|
151
|
+
{ name: 'smoke', label: 'Smoke when snuffed', type: 'boolean', tab: 'flame', description: 'A thread of smoke for a few seconds after it goes out' },
|
|
152
|
+
{ name: 'halo', type: 'number', min: 0, max: 2, step: 0.01, tab: 'flame', description: 'Strength of the wash around the flame' },
|
|
153
|
+
// Candle tab
|
|
154
|
+
{ name: 'body', type: 'select', tab: 'candle', options: ['pillar', 'taper', 'tealight', 'none'], optionLabels: ['Pillar', 'Taper', 'Tealight', 'None'], description: 'None leaves the flame and the light on their own, to drop into your own candle' },
|
|
155
|
+
{ name: 'height', type: 'number', min: 0.01, max: 1, step: 0.005, tab: 'candle', description: 'Candle height, before the body style\u2019s own proportions' },
|
|
156
|
+
{ name: 'radius', type: 'number', min: 0.004, max: 0.15, step: 0.001, tab: 'candle', description: 'Candle radius' },
|
|
157
|
+
{ name: 'melt', type: 'number', min: 0, max: 1, step: 0.01, tab: 'candle', description: 'How far it has burned down: the depth of the well round the wick' },
|
|
158
|
+
{ name: 'waxGlow', label: 'Wax glow', type: 'number', min: 0, max: 1, step: 0.01, tab: 'candle', description: 'How much the wax is lit from inside' },
|
|
159
|
+
{ name: 'waxColor', label: 'Wax colour', type: 'color', tab: 'candle', description: 'Wax colour' },
|
|
160
|
+
],
|
|
161
|
+
};
|
|
162
|
+
/** Re-export under the name the controller already uses; the table itself lives in core. */
|
|
163
|
+
export const LIGHT_DEFAULTS = DEFAULT_LIGHTS;
|
|
164
|
+
/** Knobs hidden by another knob's value (colour vs temperature, tint only when tinted). */
|
|
165
|
+
export function isLightPropertyHidden(name, values) {
|
|
166
|
+
const type = values.type;
|
|
167
|
+
if (type === 'ledArray') {
|
|
168
|
+
const mode = values.colorMode ?? 'temperature';
|
|
169
|
+
if (name === 'color')
|
|
170
|
+
return mode !== 'color';
|
|
171
|
+
if (name === 'temperature')
|
|
172
|
+
return mode === 'rgb';
|
|
173
|
+
if (name === 'rgbSpread' || name === 'rgbSpeed')
|
|
174
|
+
return mode !== 'rgb';
|
|
175
|
+
if (name === 'rows')
|
|
176
|
+
return (values.layout ?? 'panel') !== 'panel';
|
|
177
|
+
if (name === 'count')
|
|
178
|
+
return (values.layout ?? 'panel') === 'single';
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
if (type === 'candle') {
|
|
182
|
+
const mode = values.colorMode ?? 'temperature';
|
|
183
|
+
if (name === 'color')
|
|
184
|
+
return mode !== 'color';
|
|
185
|
+
if (name === 'temperature')
|
|
186
|
+
return mode !== 'temperature';
|
|
187
|
+
// Only the raymarched flame has steps, and the wax knobs mean nothing
|
|
188
|
+
// when there is no wax.
|
|
189
|
+
if (name === 'flameSteps')
|
|
190
|
+
return (values.flameMode ?? 'volumetric') !== 'volumetric';
|
|
191
|
+
if (name === 'height' || name === 'radius' || name === 'melt' || name === 'waxGlow' || name === 'waxColor')
|
|
192
|
+
return (values.body ?? 'pillar') === 'none';
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
if (type === 'fluorescentTube') {
|
|
196
|
+
const mode = values.colorMode ?? 'temperature';
|
|
197
|
+
if (name === 'color')
|
|
198
|
+
return mode !== 'color';
|
|
199
|
+
if (name === 'temperature')
|
|
200
|
+
return mode !== 'temperature';
|
|
201
|
+
if (name === 'tubeSpacing')
|
|
202
|
+
return (typeof values.tubes === 'number' ? values.tubes : 1) < 2;
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
if (type !== 'lightBulb' && type !== 'spotBeam')
|
|
206
|
+
return false;
|
|
207
|
+
const mode = values.colorMode ?? 'temperature';
|
|
208
|
+
if (name === 'color')
|
|
209
|
+
return mode !== 'color';
|
|
210
|
+
if (name === 'temperature')
|
|
211
|
+
return mode !== 'temperature';
|
|
212
|
+
if (type === 'lightBulb') {
|
|
213
|
+
if (name === 'glassTint')
|
|
214
|
+
return (values.glass ?? 'clear') !== 'tinted';
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
// spotBeam: the beam knobs mean nothing with the beam off, and the step count
|
|
218
|
+
// only drives the raymarched mode.
|
|
219
|
+
const beamMode = values.beamMode ?? 'soft';
|
|
220
|
+
if (name === 'beamSteps')
|
|
221
|
+
return beamMode !== 'volumetric';
|
|
222
|
+
if (name === 'beam' || name === 'beamLength' || name === 'beamNoise')
|
|
223
|
+
return beamMode === 'none';
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
// -----------------------------------------------------------------------------
|
|
227
|
+
// Shadow
|
|
228
|
+
// -----------------------------------------------------------------------------
|
|
229
|
+
export const SHADOW_MAP_SIZES = ['256', '512', '1024', '2048', '4096'];
|
|
230
|
+
const common = [
|
|
231
|
+
{ name: 'enabled', label: 'Cast shadows', type: 'boolean', description: 'A point light / bulb shadow costs six extra renders' },
|
|
232
|
+
{ name: 'mapSize', label: 'Resolution', type: 'select', options: SHADOW_MAP_SIZES, description: 'Shadow map size. Higher is sharper and slower' },
|
|
233
|
+
{ name: 'intensity', type: 'number', min: 0, max: 1, step: 0.01, description: 'How dark the shadow is' },
|
|
234
|
+
{ name: 'radius', label: 'Softness', type: 'number', min: 0, max: 10, step: 0.1, description: 'Blur radius of the shadow edge (PCF shadows)' },
|
|
235
|
+
{ name: 'bias', type: 'number', min: -0.01, max: 0.01, step: 0.0001, description: 'Fixes shadow acne. Too far and shadows detach from objects' },
|
|
236
|
+
{ name: 'normalBias', label: 'Normal bias', type: 'number', min: 0, max: 0.1, step: 0.001, description: 'Acne fix along the surface normal; better on curved surfaces' },
|
|
237
|
+
{ name: 'cameraNear', label: 'Near', type: 'number', min: 0.01, max: 10, step: 0.01, description: 'Closest distance that casts a shadow' },
|
|
238
|
+
{ name: 'cameraFar', label: 'Far', type: 'number', min: 1, max: 1000, step: 1, description: 'Farthest distance that casts a shadow' },
|
|
239
|
+
];
|
|
240
|
+
const spotShadow = [
|
|
241
|
+
...common,
|
|
242
|
+
{ name: 'cameraFov', label: 'Shadow FOV', type: 'number', min: 1, max: 120, step: 1, description: 'Field of view of the shadow camera' },
|
|
243
|
+
{ name: 'focus', type: 'number', min: 0, max: 1, step: 0.01, description: 'Tightens the shadow camera around the cone' },
|
|
244
|
+
];
|
|
245
|
+
export const SHADOW_PROPERTIES = {
|
|
246
|
+
ambient: [],
|
|
247
|
+
point: common,
|
|
248
|
+
lightBulb: common,
|
|
249
|
+
spot: spotShadow,
|
|
250
|
+
spotBeam: spotShadow,
|
|
251
|
+
ledArray: common,
|
|
252
|
+
candle: common,
|
|
253
|
+
// The shadow belongs to the point light at the fixture's centre, so the point
|
|
254
|
+
// light's settings are the ones that matter.
|
|
255
|
+
fluorescentTube: common,
|
|
256
|
+
directional: [
|
|
257
|
+
...common,
|
|
258
|
+
{ name: 'cameraLeft', label: 'Left', type: 'number', min: -200, max: 0, step: 1, description: 'Shadow area, left edge' },
|
|
259
|
+
{ name: 'cameraRight', label: 'Right', type: 'number', min: 0, max: 200, step: 1, description: 'Shadow area, right edge' },
|
|
260
|
+
{ name: 'cameraTop', label: 'Top', type: 'number', min: 0, max: 200, step: 1, description: 'Shadow area, top edge' },
|
|
261
|
+
{ name: 'cameraBottom', label: 'Bottom', type: 'number', min: -200, max: 0, step: 1, description: 'Shadow area, bottom edge' },
|
|
262
|
+
],
|
|
263
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface MaterialPropertyBounds {
|
|
2
|
+
min: number;
|
|
3
|
+
max: number;
|
|
4
|
+
step: number;
|
|
5
|
+
label?: string;
|
|
6
|
+
accentColor?: 'cyan' | 'purple' | 'pink' | 'green' | 'yellow' | 'blue';
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Known bounds for standard Three.js material properties.
|
|
10
|
+
* Used by MaterialControllerUi to render SliderControls with correct ranges.
|
|
11
|
+
*
|
|
12
|
+
* If a property is not in this map, it falls back to a sensible default (0–1, step 0.01).
|
|
13
|
+
*/
|
|
14
|
+
export declare const MATERIAL_PROPERTY_BOUNDS: Record<string, MaterialPropertyBounds>;
|
|
15
|
+
/**
|
|
16
|
+
* Default bounds for unknown numeric properties.
|
|
17
|
+
*/
|
|
18
|
+
export declare const DEFAULT_MATERIAL_BOUNDS: MaterialPropertyBounds;
|
|
19
|
+
/**
|
|
20
|
+
* Get bounds for a property, falling back to defaults.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getMaterialBounds(key: string): MaterialPropertyBounds;
|
|
23
|
+
/**
|
|
24
|
+
* Get a human-readable label for a property key.
|
|
25
|
+
* Uses the bounds label if available, otherwise converts camelCase to Title Case.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getMaterialPropertyLabel(key: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Generate random values for numeric and color properties within their bounds.
|
|
30
|
+
* Skips texture/mapping properties and internal fields.
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateRandomMaterialSettings(currentSettings: Record<string, any>): Record<string, any>;
|
|
33
|
+
//# sourceMappingURL=materialBounds.d.ts.map
|