@motionscript/molecule 0.0.0-stage → 0.1.0-alpha.0

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +201 -0
  3. package/dist/browser/index.js +4 -0
  4. package/dist/browser/index.js.map +7 -0
  5. package/dist/browser/manifest.json +11 -0
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +3 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/nodes.d.ts +18 -0
  11. package/dist/nodes.d.ts.map +1 -0
  12. package/dist/nodes.js +18 -0
  13. package/dist/nodes.js.map +1 -0
  14. package/dist/protein/chemistry.d.ts +52 -0
  15. package/dist/protein/chemistry.d.ts.map +1 -0
  16. package/dist/protein/chemistry.js +208 -0
  17. package/dist/protein/chemistry.js.map +1 -0
  18. package/dist/protein/index.d.ts +35 -0
  19. package/dist/protein/index.d.ts.map +1 -0
  20. package/dist/protein/index.js +35 -0
  21. package/dist/protein/index.js.map +1 -0
  22. package/dist/protein/parse.d.ts +32 -0
  23. package/dist/protein/parse.d.ts.map +1 -0
  24. package/dist/protein/parse.js +387 -0
  25. package/dist/protein/parse.js.map +1 -0
  26. package/dist/protein/protein.d.ts +265 -0
  27. package/dist/protein/protein.d.ts.map +1 -0
  28. package/dist/protein/protein.js +645 -0
  29. package/dist/protein/protein.js.map +1 -0
  30. package/dist/protein/ribbon.d.ts +83 -0
  31. package/dist/protein/ribbon.d.ts.map +1 -0
  32. package/dist/protein/ribbon.js +468 -0
  33. package/dist/protein/ribbon.js.map +1 -0
  34. package/dist/protein/shared.d.ts +221 -0
  35. package/dist/protein/shared.d.ts.map +1 -0
  36. package/dist/protein/shared.js +478 -0
  37. package/dist/protein/shared.js.map +1 -0
  38. package/dist/protein/structure.d.ts +184 -0
  39. package/dist/protein/structure.d.ts.map +1 -0
  40. package/dist/protein/structure.js +324 -0
  41. package/dist/protein/structure.js.map +1 -0
  42. package/package.json +64 -3
  43. package/registry.json +22 -0
  44. package/src/index.ts +2 -0
  45. package/src/nodes.ts +18 -0
  46. package/src/protein/chemistry.ts +223 -0
  47. package/src/protein/index.ts +34 -0
  48. package/src/protein/parse.ts +427 -0
  49. package/src/protein/protein.ts +897 -0
  50. package/src/protein/ribbon.ts +658 -0
  51. package/src/protein/shared.ts +622 -0
  52. package/src/protein/structure.ts +491 -0
  53. package/README.md +0 -4
@@ -0,0 +1,265 @@
1
+ import { type Command, type CommandArgs, Canvas3D, Scene3D, type Canvas3DProps, type Color, type NodeConfig } from "@motionscript/core";
2
+ import { type OrbitTarget } from "@motionscript/core/component";
3
+ import { type ProteinColorScheme, type ProteinRepresentation } from "./shared.js";
4
+ import { type ProteinStructure } from "./structure.js";
5
+ export interface ProteinProps extends Canvas3DProps {
6
+ /**
7
+ * The molecule to draw, already parsed.
8
+ *
9
+ * A value rather than a source, and that is the whole arrangement: reading a
10
+ * coordinate file means a network round-trip or a file read, and this node is
11
+ * constructed inside a synchronous render pass. So the fetching and the
12
+ * parsing happen *before* the build — see `parseStructure` and the app's
13
+ * structure store — and what arrives here is finished data. It is the same
14
+ * bargain a chart makes with its rows.
15
+ */
16
+ structure: ProteinStructure;
17
+ /** How the molecule is drawn. See {@link ProteinRepresentation}. */
18
+ representation: ProteinRepresentation;
19
+ /** What decides an atom's colour. See {@link ProteinColorScheme}. */
20
+ colorScheme: ProteinColorScheme;
21
+ /** The colour the `uniform` scheme paints, and every scheme's fallback. */
22
+ color: Color;
23
+ /**
24
+ * Every colour the *other* schemes paint from — see {@link ProteinPalette},
25
+ * which is the shape these are read as rather than a prop of its own.
26
+ *
27
+ * Thirteen props rather than one palette because a prop is a whole value: a
28
+ * single one would make a `to` that reddens the helices a statement about the
29
+ * eight chain colours too, and the ones the author never touched would snap.
30
+ * Each of these carries over and tweens on its own, like every other colour in
31
+ * the app.
32
+ */
33
+ helixColor: string;
34
+ sheetColor: string;
35
+ coilColor: string;
36
+ /** The two ends of the N→C ramp, swept through HSL between them. */
37
+ residueStartColor: string;
38
+ residueEndColor: string;
39
+ /** One per chain, cycling past the eighth. */
40
+ chainColor1: string;
41
+ chainColor2: string;
42
+ chainColor3: string;
43
+ chainColor4: string;
44
+ chainColor5: string;
45
+ chainColor6: string;
46
+ chainColor7: string;
47
+ chainColor8: string;
48
+ /**
49
+ * Atom size as a fraction of the true van der Waals radius.
50
+ *
51
+ * 1 is the space-filling model — atoms at the size they actually are, touching
52
+ * their neighbours. Ball-and-stick shrinks them further on its own, so this
53
+ * stays "how big are the atoms" in both rather than meaning something
54
+ * different in each.
55
+ */
56
+ atomScale: number;
57
+ /** Bond stick radius, in Ångströms. */
58
+ bondRadius: number;
59
+ /** Backbone tube radius, in Ångströms. A ribbon swells past this on a helix. */
60
+ ribbonRadius: number;
61
+ /** Whether to draw ligands, ions and cofactors — everything that isn't polymer. */
62
+ ligands: boolean;
63
+ /** Whether to draw crystallographic waters. Off, because there are hundreds. */
64
+ waters: boolean;
65
+ /** Mesh detail: segments around a sphere or a stick. */
66
+ quality: number;
67
+ /** Camera orbit about the vertical axis, in **degrees**. Animate this to spin. */
68
+ orbit: number;
69
+ /** Camera elevation above the horizon, in **degrees**. */
70
+ elevation: number;
71
+ /**
72
+ * How far back the camera sits, as a multiple of the molecule's own radius.
73
+ *
74
+ * A multiple rather than a distance, because the things this node draws differ
75
+ * in size by two orders of magnitude — crambin is 12 Å across and a ribosome
76
+ * is 300 — and a stored distance that framed one would put the other off
77
+ * screen or inside the camera. As a ratio the same number frames both, and it
78
+ * goes on meaning the same thing when the structure is swapped.
79
+ */
80
+ zoom: number;
81
+ /** Strength of the ambient fill. */
82
+ ambientIntensity: number;
83
+ /** Colour of the ambient fill. White leaves the molecule's own colours alone. */
84
+ ambientColor: Color;
85
+ /** Strength of the key light; the rim light is derived from it. */
86
+ keyIntensity: number;
87
+ /** Colour of the key light, and of the rim derived from it. */
88
+ keyColor: Color;
89
+ }
90
+ /**
91
+ * A molecular structure viewer.
92
+ *
93
+ * Extends {@link Canvas3D} — as `Graph3D` does — so this class only has to say
94
+ * *what* to draw, and the bridge from the 2D scene graph into the 3D renderer is
95
+ * the base class's business. It overrides `buildScene3D`, the single seam both
96
+ * the real render and the asset declaration pass go through.
97
+ *
98
+ * <Protein width="fill" height="fill"
99
+ * structure={parseStructure(text, "6LU7")}
100
+ * representation="ribbon" colorScheme="secondary" />
101
+ *
102
+ * **There is no pointer here.** Every other molecular viewer is driven by
103
+ * dragging the molecule around, and this one cannot be: the studio renders a
104
+ * timeline, so the camera has to be something a `to` command can tween and a
105
+ * scrub can reproduce exactly — frame 300 must be identical whether it was
106
+ * reached by playing forward or by dragging the playhead backwards. So the
107
+ * camera is three tweenable numbers (`orbit`, `elevation`, `zoom`), and spinning
108
+ * the molecule is a command rather than a gesture.
109
+ *
110
+ * Atoms and bonds are drawn **instanced**: one sphere geometry and one cylinder
111
+ * geometry, placed thousands of times in a single draw call each. A mesh per
112
+ * atom would be tens of thousands of draw calls a frame, which no renderer
113
+ * survives — and the instance lists themselves are cached (see {@link built}),
114
+ * because they don't change when the camera moves and the camera is what
115
+ * normally moves.
116
+ */
117
+ export declare class Protein extends Canvas3D<ProteinProps> {
118
+ /**
119
+ * The molecule.
120
+ *
121
+ * Snaps rather than interpolating, and every other non-scalar prop here
122
+ * interpolates. There is no halfway point between two different molecules —
123
+ * atom 4,000 of one is not the same atom as atom 4,000 of the other, and
124
+ * blending their coordinates would produce a cloud that is neither. Swapping
125
+ * the structure is a change of *subject*, so it lands at the end of a tween
126
+ * the way a change of text does.
127
+ */
128
+ structure: ProteinStructure;
129
+ representation: ProteinRepresentation;
130
+ colorScheme: ProteinColorScheme;
131
+ color: Color;
132
+ /**
133
+ * The palette, thirteen props of it — see {@link ProteinProps.helixColor} for
134
+ * why it is thirteen and not one.
135
+ *
136
+ * No `mapper`, unlike the three `Color` props around them: these stay hex
137
+ * strings because a hex string is what an instance tint is handed, and
138
+ * {@link lerpHexColor} is the tween that goes with that. The defaults are
139
+ * written out rather than read off {@link DEFAULT_PROTEIN_PALETTE} because a
140
+ * decorator default has to be a literal the class carries; the two are pinned
141
+ * against each other by a test.
142
+ */
143
+ helixColor: string;
144
+ sheetColor: string;
145
+ coilColor: string;
146
+ residueStartColor: string;
147
+ residueEndColor: string;
148
+ chainColor1: string;
149
+ chainColor2: string;
150
+ chainColor3: string;
151
+ chainColor4: string;
152
+ chainColor5: string;
153
+ chainColor6: string;
154
+ chainColor7: string;
155
+ chainColor8: string;
156
+ atomScale: number;
157
+ bondRadius: number;
158
+ ribbonRadius: number;
159
+ ligands: boolean;
160
+ waters: boolean;
161
+ /**
162
+ * Structural, like `Graph3D.segments`: a geometry is immutable, so every
163
+ * intermediate value of a tween reallocates the sphere and the cylinder. Set
164
+ * once; the appearance schema marks it non-animatable to say the same thing
165
+ * from the other side.
166
+ */
167
+ quality: number;
168
+ orbit: number;
169
+ elevation: number;
170
+ zoom: number;
171
+ /**
172
+ * The default rig, and only the default rig — the same four controls the 3D
173
+ * viewport carries, in the same order and with the same defaults, because
174
+ * "how is this lit" is one question and a molecule is not a special case of
175
+ * it. Each light is a **strength and a colour**, in that order: how much
176
+ * light, and what colour it is.
177
+ *
178
+ * Both colours default to white rather than to a tint, so a rig nobody has
179
+ * touched grades nothing. A coloured default would be a look applied to every
180
+ * structure in every scene by a control the author never opened.
181
+ */
182
+ ambientIntensity: number;
183
+ ambientColor: Color;
184
+ keyIntensity: number;
185
+ keyColor: Color;
186
+ constructor(props?: NodeConfig<Protein, ProteinProps>);
187
+ /**
188
+ * Frame the scene at a spherical camera placement. Every axis is optional,
189
+ * so "pull back" and "spin round" stay separate intentions — see
190
+ * {@link OrbitTarget}.
191
+ */
192
+ orbitTo(args: CommandArgs<{
193
+ target: OrbitTarget;
194
+ }> & {
195
+ duration: number;
196
+ }): Command<ProteinProps>;
197
+ /**
198
+ * Drift the camera around the molecule for the command's duration — a
199
+ * continuous orbit at `speed` with a lateral `sway` and a `zoom` pulse
200
+ * (`breathe`), both on a shared `cycle` so they don't beat against each
201
+ * other. `settle` eases in from wherever the camera already is, so `float`
202
+ * after an `orbitTo` does not snap.
203
+ */
204
+ float(args: CommandArgs<{
205
+ speed?: number;
206
+ elevation?: number;
207
+ zoom?: number;
208
+ sway?: number;
209
+ breathe?: number;
210
+ cycle?: number;
211
+ settle?: number;
212
+ }> & {
213
+ duration?: number;
214
+ }): Command<ProteinProps>;
215
+ /**
216
+ * The thirteen colour props, as the one value the colourers take.
217
+ *
218
+ * Rebuilt per call rather than cached: it is thirteen property reads behind
219
+ * `built()`'s own cache, which is what stops it happening per frame.
220
+ */
221
+ private paletteOf;
222
+ protected buildScene3D(): Scene3D;
223
+ /** The molecule itself, in whichever representation is showing. */
224
+ private addMolecule;
225
+ /** One instanced sphere op, skipped entirely when there is nothing in it. */
226
+ private addSpheres;
227
+ /** One instanced cylinder op. */
228
+ private addSticks;
229
+ /**
230
+ * Everything the builder needs, cached against the inputs that decide it.
231
+ *
232
+ * This is the node's one piece of memoisation and it earns its keep. The
233
+ * builder runs every frame; between two frames the thing that has normally
234
+ * changed is the camera; and none of what is cached here depends on the
235
+ * camera. Without it, orbiting a 20,000-atom structure would rebuild a
236
+ * 20,000-entry placement list and a 40,000-entry stick list sixty times a
237
+ * second — for a picture whose atoms have not moved.
238
+ *
239
+ * The structure is compared by **identity** rather than by contents: it is a
240
+ * parsed value produced once, upstream, so a different object genuinely means
241
+ * a different molecule.
242
+ */
243
+ private cache;
244
+ private built;
245
+ /** Builds the placement lists for the current representation. */
246
+ private build;
247
+ /**
248
+ * The polymer, as whichever sweep its representation calls for.
249
+ *
250
+ * Two genuinely different builds rather than one with a radius switch, and
251
+ * the split is the same one the representations themselves are: `backbone`
252
+ * asks *where does the chain go*, which an even round tube answers exactly
253
+ * and completely; `ribbon` asks *what is it folded into*, which is the
254
+ * cartoon convention and needs a cross-section with a width, a thickness and
255
+ * a side (see `ribbon.ts`).
256
+ */
257
+ private addRuns;
258
+ /** Whether an atom passes the ligand and water filters. */
259
+ private isShowing;
260
+ /** Segments around a sphere's equator. */
261
+ private sphereQuality;
262
+ /** Segments around a stick or a tube — half a sphere's, since it has no poles. */
263
+ private stickQuality;
264
+ }
265
+ //# sourceMappingURL=protein.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protein.d.ts","sourceRoot":"","sources":["../../src/protein/protein.ts"],"names":[],"mappings":"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"}