@johnmorrisdotca/uchusen-rockets 0.3.0 → 0.4.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.
- package/CHANGELOG.md +16 -5
- package/README.md +241 -4
- package/dist/attrs.d.ts +70 -4
- package/dist/attrs.js +59 -4
- package/dist/build/glb.d.ts +25 -0
- package/dist/build/glb.js +14 -0
- package/dist/build/index.d.ts +89 -4
- package/dist/build/index.js +55 -4
- package/dist/build/lineup.d.ts +56 -2
- package/dist/build/lineup.js +23 -2
- package/dist/builder.d.ts +47 -1
- package/dist/builder.js +14 -1
- package/dist/crossfade.d.ts +44 -2
- package/dist/crossfade.js +44 -2
- package/dist/data/credits.d.ts +44 -1
- package/dist/data/credits.js +22 -1
- package/dist/data/flight-log.d.ts +33 -1
- package/dist/data/flight-log.js +22 -1
- package/dist/data/flights.d.ts +54 -2
- package/dist/data/flights.js +10 -0
- package/dist/data/makers.d.ts +21 -0
- package/dist/data/makers.js +10 -0
- package/dist/data/sources.d.ts +32 -0
- package/dist/data/sources.js +10 -0
- package/dist/data/types.d.ts +81 -1
- package/dist/data/types.js +26 -1
- package/dist/element.d.ts +61 -3
- package/dist/element.js +50 -3
- package/dist/embed.d.ts +110 -5
- package/dist/embed.js +88 -5
- package/dist/engines.d.ts +86 -4
- package/dist/engines.js +75 -4
- package/dist/fit.d.ts +68 -0
- package/dist/fit.js +13 -0
- package/dist/flight.d.ts +134 -9
- package/dist/flight.js +122 -9
- package/dist/flightbar.d.ts +12 -0
- package/dist/flightbar.js +12 -0
- package/dist/framing.d.ts +182 -8
- package/dist/framing.js +127 -6
- package/dist/layout.d.ts +65 -1
- package/dist/layout.js +43 -1
- package/dist/looks.d.ts +64 -1
- package/dist/looks.js +42 -1
- package/dist/model/materials.d.ts +32 -0
- package/dist/model/materials.js +10 -0
- package/dist/model/registry.d.ts +22 -0
- package/dist/model/registry.js +22 -0
- package/dist/parts.d.ts +33 -1
- package/dist/pixels.d.ts +44 -4
- package/dist/pixels.js +44 -4
- package/dist/react.d.ts +24 -0
- package/dist/react.js +13 -0
- package/dist/rockets.d.ts +91 -3
- package/dist/rockets.js +58 -2
- package/dist/spin.d.ts +57 -2
- package/dist/spin.js +35 -2
- package/dist/tilt.d.ts +48 -4
- package/dist/tilt.js +26 -4
- package/package.json +10 -5
package/dist/framing.js
CHANGED
|
@@ -1,11 +1,69 @@
|
|
|
1
1
|
// Where the camera stands. One rule for the drawing and the 3D view, so the drawing turns into the 3D view without a jump. Pure, in metres.
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* The camera's field of view, in degrees, top to bottom. Narrow, because a rocket is long.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { FOV_DEG } from "@johnmorrisdotca/uchusen-rockets";
|
|
8
|
+
*
|
|
9
|
+
* console.log(FOV_DEG);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
3
12
|
export const FOV_DEG = 24;
|
|
4
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* The width of the picture a drawing is made in, in drawing units.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { PICTURE_W, PICTURE_H } from "@johnmorrisdotca/uchusen-rockets";
|
|
19
|
+
*
|
|
20
|
+
* console.log(PICTURE_W, PICTURE_H);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
5
23
|
export const PICTURE_W = 480;
|
|
24
|
+
/**
|
|
25
|
+
* The height of the picture a drawing is made in, in drawing units.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { PICTURE_H } from "@johnmorrisdotca/uchusen-rockets";
|
|
30
|
+
*
|
|
31
|
+
* console.log(PICTURE_H);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
6
34
|
export const PICTURE_H = 640;
|
|
35
|
+
/**
|
|
36
|
+
* The names of the views, in the order the demo lists them: `three-quarter`, `front`, `back`, `side` and `below`.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { VIEW_NAMES } from "@johnmorrisdotca/uchusen-rockets";
|
|
41
|
+
*
|
|
42
|
+
* console.log(VIEW_NAMES.join(", "));
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
7
45
|
export const VIEW_NAMES = ["three-quarter", "front", "back", "side", "below"];
|
|
46
|
+
/**
|
|
47
|
+
* The view used when none is named or the name is not a view: `three-quarter`.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { DEFAULT_VIEW } from "@johnmorrisdotca/uchusen-rockets";
|
|
52
|
+
*
|
|
53
|
+
* console.log(DEFAULT_VIEW);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
8
56
|
export const DEFAULT_VIEW = "three-quarter";
|
|
57
|
+
/**
|
|
58
|
+
* The angle of each named view.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* import { VIEWS } from "@johnmorrisdotca/uchusen-rockets";
|
|
63
|
+
*
|
|
64
|
+
* console.log(VIEWS.front, VIEWS.below);
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
9
67
|
export const VIEWS = {
|
|
10
68
|
"three-quarter": { az: 32, el: 9 },
|
|
11
69
|
front: { az: 0, el: 3 },
|
|
@@ -13,13 +71,49 @@ export const VIEWS = {
|
|
|
13
71
|
side: { az: 90, el: 3 },
|
|
14
72
|
below: { az: 24, el: -70 },
|
|
15
73
|
};
|
|
74
|
+
/**
|
|
75
|
+
* A value from outside as a view's name.
|
|
76
|
+
*
|
|
77
|
+
* @param value Anything.
|
|
78
|
+
* @returns The name if it is one of the views, and `three-quarter` for anything else.
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* import { cleanView } from "@johnmorrisdotca/uchusen-rockets";
|
|
82
|
+
*
|
|
83
|
+
* console.log(cleanView("side"), cleanView("sideways"), cleanView(42));
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
16
86
|
export const cleanView = (value) => (VIEW_NAMES.includes(value) ? value : DEFAULT_VIEW);
|
|
17
87
|
export const deg = (d) => (d * Math.PI) / 180;
|
|
18
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* What the family's view controls choose: the turn and tip, in degrees, from a base angle. Dragging right makes `yaw` larger, which carries the camera the other way round; `tilt` larger tips the top away, which lowers the camera.
|
|
90
|
+
*
|
|
91
|
+
* @param base The angle to turn from.
|
|
92
|
+
* @param yaw Degrees turned round.
|
|
93
|
+
* @param tilt Degrees tipped up or down.
|
|
94
|
+
* @returns The new angle.
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* import { turnedBy, VIEWS } from "@johnmorrisdotca/uchusen-rockets";
|
|
98
|
+
*
|
|
99
|
+
* console.log(turnedBy(VIEWS.front, 30, 10));
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
19
102
|
export function turnedBy(base, yaw, tilt) {
|
|
20
103
|
return { az: base.az - yaw, el: Math.min(87, Math.max(-87, base.el - tilt)) };
|
|
21
104
|
}
|
|
22
|
-
/**
|
|
105
|
+
/**
|
|
106
|
+
* The unit vector from what is looked at towards the camera.
|
|
107
|
+
*
|
|
108
|
+
* @param angle The angle to look from.
|
|
109
|
+
* @returns A unit vector.
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* import { directionOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
113
|
+
*
|
|
114
|
+
* console.log(directionOf({ az: 0, el: 0 }));
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
23
117
|
export function directionOf({ az, el }) {
|
|
24
118
|
const c = Math.cos(deg(el));
|
|
25
119
|
return [c * Math.sin(deg(az)), Math.sin(deg(el)), c * Math.cos(deg(az))];
|
|
@@ -30,14 +124,41 @@ const unit = (a) => {
|
|
|
30
124
|
const l = Math.hypot(...a) || 1;
|
|
31
125
|
return [a[0] / l, a[1] / l, a[2] / l];
|
|
32
126
|
};
|
|
33
|
-
/**
|
|
127
|
+
/**
|
|
128
|
+
* The camera's own axes for looking along `direction`, with up as near to +Y as it can be.
|
|
129
|
+
*
|
|
130
|
+
* @param direction The direction from the target to the camera.
|
|
131
|
+
* @returns The camera's right, up and forward axes.
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* import { axesOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
135
|
+
*
|
|
136
|
+
* console.log(axesOf([0, 0, 1]));
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
34
139
|
export function axesOf(direction) {
|
|
35
140
|
const forward = [-direction[0], -direction[1], -direction[2]];
|
|
36
141
|
const near = Math.abs(forward[1]) > 0.999;
|
|
37
142
|
const right = unit(cross(forward, near ? [0, 0, -1] : [0, 1, 0]));
|
|
38
143
|
return { right, up: cross(right, forward), forward };
|
|
39
144
|
}
|
|
40
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
* The nearest camera that holds the whole of `min` to `max` in a picture `aspect` wide for 1 tall, from `angle`.
|
|
147
|
+
*
|
|
148
|
+
* @param min The lowest corner of the box to hold.
|
|
149
|
+
* @param max The highest corner.
|
|
150
|
+
* @param angle The angle to look from.
|
|
151
|
+
* @param aspect The picture's width over its height.
|
|
152
|
+
* @param margin Room left round the box, as a multiple. Defaults to 1.08.
|
|
153
|
+
* @returns The camera that holds the whole box.
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* import { frameFor, VIEWS } from "@johnmorrisdotca/uchusen-rockets";
|
|
157
|
+
*
|
|
158
|
+
* const framing = frameFor([-4.5, 0, -4.5], [4.5, 124, 4.5], VIEWS.front, 480 / 640);
|
|
159
|
+
* console.log(framing.target, framing.distance.toFixed(0));
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
41
162
|
export function frameFor(min, max, angle, aspect, margin = 1.08) {
|
|
42
163
|
const target = [(min[0] + max[0]) / 2, (min[1] + max[1]) / 2, (min[2] + max[2]) / 2];
|
|
43
164
|
const direction = directionOf(angle);
|
package/dist/layout.d.ts
CHANGED
|
@@ -1,16 +1,80 @@
|
|
|
1
1
|
import type { Vec3 } from "./framing.ts";
|
|
2
2
|
import type { PartRecord } from "./parts.ts";
|
|
3
|
+
/**
|
|
4
|
+
* What to show of a rocket: `together`, `apart`, or the slot of one part, such as `booster`.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import type { ShowName } from "@johnmorrisdotca/uchusen-rockets";
|
|
9
|
+
*
|
|
10
|
+
* const shows: ShowName[] = ["together", "apart", "booster"];
|
|
11
|
+
* console.log(shows);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
3
14
|
export type ShowName = "together" | "apart" | (string & {});
|
|
4
15
|
/** A part's own width from the axis, for keeping apart parts clear of each other. */
|
|
5
16
|
export type WidthOf = (part: PartRecord) => number;
|
|
17
|
+
/**
|
|
18
|
+
* Where one part stands for a choice of what to show: its slot, its position in metres and whether it is shown at all.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { placesFor, type Place } from "@johnmorrisdotca/uchusen-rockets";
|
|
23
|
+
*
|
|
24
|
+
* const places: Place[] = placesFor([], "together", () => 1);
|
|
25
|
+
* console.log(places.length);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
6
28
|
export interface Place {
|
|
7
29
|
slot: string;
|
|
8
30
|
at: Vec3;
|
|
9
31
|
shown: boolean;
|
|
10
32
|
}
|
|
11
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* The first choices of `show`, then one per slot.
|
|
35
|
+
*
|
|
36
|
+
* @param slots A variant's slots, from the bottom.
|
|
37
|
+
* @returns What can be shown: together and apart first when there is more than one slot, then one for each slot.
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { showsOf, variantOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
41
|
+
*
|
|
42
|
+
* console.log(showsOf(variantOf("falcon-9", "block-5")?.slots ?? []));
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
12
45
|
export declare const showsOf: (slots: readonly string[]) => string[];
|
|
46
|
+
/**
|
|
47
|
+
* A value from outside as something that can be shown.
|
|
48
|
+
*
|
|
49
|
+
* @param value Anything.
|
|
50
|
+
* @param slots The variant's slots.
|
|
51
|
+
* @returns The value if it can be shown, and the first choice (together) for anything else.
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { cleanShow, variantOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
55
|
+
*
|
|
56
|
+
* const slots = variantOf("falcon-9", "block-5")?.slots ?? [];
|
|
57
|
+
* console.log(cleanShow("first-stage", slots), cleanShow("nonsense", slots));
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
13
60
|
export declare function cleanShow(value: unknown, slots: readonly string[]): string;
|
|
61
|
+
/**
|
|
62
|
+
* Where each part stands: up the stack joint to joint, or spread apart on a diagonal of the ground, or one part alone.
|
|
63
|
+
*
|
|
64
|
+
* @param parts The parts with their slots, from the bottom.
|
|
65
|
+
* @param show What to show.
|
|
66
|
+
* @param widthOf The width of a part, for spacing when they are apart.
|
|
67
|
+
* @returns A place for each part.
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
71
|
+
* import { placesFor } from "@johnmorrisdotca/uchusen-rockets";
|
|
72
|
+
*
|
|
73
|
+
* const rocket = build({ rocket: "falcon-9", variant: "block-5" });
|
|
74
|
+
* const parts = rocket.parts.map((part) => ({ slot: part.slot, part: part.record }));
|
|
75
|
+
* console.log(placesFor(parts, "apart", (part) => part.diameter / 2).map((place) => place.slot));
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
14
78
|
export declare function placesFor(parts: readonly {
|
|
15
79
|
slot: string;
|
|
16
80
|
part: PartRecord;
|
package/dist/layout.js
CHANGED
|
@@ -1,11 +1,53 @@
|
|
|
1
1
|
/** Seen square-on to the diagonal the parts take the whole distance; from the front or the side, seven tenths of it. */
|
|
2
2
|
const APART_SPREAD = 1.45;
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* The first choices of `show`, then one per slot.
|
|
5
|
+
*
|
|
6
|
+
* @param slots A variant's slots, from the bottom.
|
|
7
|
+
* @returns What can be shown: together and apart first when there is more than one slot, then one for each slot.
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { showsOf, variantOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
11
|
+
*
|
|
12
|
+
* console.log(showsOf(variantOf("falcon-9", "block-5")?.slots ?? []));
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
4
15
|
export const showsOf = (slots) => (slots.length > 1 ? ["together", "apart", ...slots] : [...slots]);
|
|
16
|
+
/**
|
|
17
|
+
* A value from outside as something that can be shown.
|
|
18
|
+
*
|
|
19
|
+
* @param value Anything.
|
|
20
|
+
* @param slots The variant's slots.
|
|
21
|
+
* @returns The value if it can be shown, and the first choice (together) for anything else.
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { cleanShow, variantOf } from "@johnmorrisdotca/uchusen-rockets";
|
|
25
|
+
*
|
|
26
|
+
* const slots = variantOf("falcon-9", "block-5")?.slots ?? [];
|
|
27
|
+
* console.log(cleanShow("first-stage", slots), cleanShow("nonsense", slots));
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
5
30
|
export function cleanShow(value, slots) {
|
|
6
31
|
const shows = showsOf(slots);
|
|
7
32
|
return typeof value === "string" && shows.includes(value) ? value : shows[0];
|
|
8
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Where each part stands: up the stack joint to joint, or spread apart on a diagonal of the ground, or one part alone.
|
|
36
|
+
*
|
|
37
|
+
* @param parts The parts with their slots, from the bottom.
|
|
38
|
+
* @param show What to show.
|
|
39
|
+
* @param widthOf The width of a part, for spacing when they are apart.
|
|
40
|
+
* @returns A place for each part.
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { build } from "@johnmorrisdotca/uchusen-rockets/build";
|
|
44
|
+
* import { placesFor } from "@johnmorrisdotca/uchusen-rockets";
|
|
45
|
+
*
|
|
46
|
+
* const rocket = build({ rocket: "falcon-9", variant: "block-5" });
|
|
47
|
+
* const parts = rocket.parts.map((part) => ({ slot: part.slot, part: part.record }));
|
|
48
|
+
* console.log(placesFor(parts, "apart", (part) => part.diameter / 2).map((place) => place.slot));
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
9
51
|
export function placesFor(parts, show, widthOf) {
|
|
10
52
|
if (show === "apart") {
|
|
11
53
|
const widths = parts.map(({ part }) => widthOf(part));
|
package/dist/looks.d.ts
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The names of the looks: `line`, `thick` and `painted`.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { LOOK_NAMES } from "@johnmorrisdotca/uchusen-rockets";
|
|
7
|
+
*
|
|
8
|
+
* console.log(LOOK_NAMES.join(", "));
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
1
11
|
export declare const LOOK_NAMES: readonly ["line", "thick", "painted"];
|
|
12
|
+
/**
|
|
13
|
+
* The name of one look in `LOOK_NAMES`.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import type { LookName } from "@johnmorrisdotca/uchusen-rockets";
|
|
18
|
+
*
|
|
19
|
+
* const look: LookName = "thick";
|
|
20
|
+
* console.log(look);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
2
23
|
export type LookName = (typeof LOOK_NAMES)[number];
|
|
24
|
+
/**
|
|
25
|
+
* The look used when none is named or the name is not a look: `line`.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { DEFAULT_LOOK } from "@johnmorrisdotca/uchusen-rockets";
|
|
30
|
+
*
|
|
31
|
+
* console.log(DEFAULT_LOOK);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
3
34
|
export declare const DEFAULT_LOOK: LookName;
|
|
35
|
+
/**
|
|
36
|
+
* What a look changes: the colour and width of its lines in a 3D view and in a drawing, how much of the weld lines shows, the fills by material group and whether there is a halo. A look never changes a shape.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { LOOKS, type Look } from "@johnmorrisdotca/uchusen-rockets";
|
|
41
|
+
*
|
|
42
|
+
* const thick: Look = LOOKS.thick;
|
|
43
|
+
* console.log(thick.line, thick.outline);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
4
46
|
export interface Look {
|
|
5
47
|
/** The colour of its lines. */
|
|
6
48
|
line: string;
|
|
@@ -20,6 +62,27 @@ export interface Look {
|
|
|
20
62
|
halo: boolean;
|
|
21
63
|
}
|
|
22
64
|
export type FillName = "hull" | "white" | "tile" | "metal" | "dark" | "bell" | "foam";
|
|
65
|
+
/**
|
|
66
|
+
* Every look, by name. A look is one entry of this table.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { LOOKS } from "@johnmorrisdotca/uchusen-rockets";
|
|
71
|
+
*
|
|
72
|
+
* console.log(Object.keys(LOOKS));
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
23
75
|
export declare const LOOKS: Readonly<Record<LookName, Look>>;
|
|
24
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* A value from outside as a look's name: the default for anything else.
|
|
78
|
+
*
|
|
79
|
+
* @param value Anything.
|
|
80
|
+
* @returns The look's name if it is one, and the default (`line`) for anything else.
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* import { cleanLook } from "@johnmorrisdotca/uchusen-rockets";
|
|
84
|
+
*
|
|
85
|
+
* console.log(cleanLook("painted"), cleanLook("shiny"));
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
25
88
|
export declare const cleanLook: (value: unknown) => LookName;
|
package/dist/looks.js
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
// The three looks, each one table entry: the line drawing, the thick lines, and the painted rocket. A look changes lines, colours and fills, never a shape. Pure.
|
|
2
|
+
/**
|
|
3
|
+
* The names of the looks: `line`, `thick` and `painted`.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { LOOK_NAMES } from "@johnmorrisdotca/uchusen-rockets";
|
|
8
|
+
*
|
|
9
|
+
* console.log(LOOK_NAMES.join(", "));
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
2
12
|
export const LOOK_NAMES = ["line", "thick", "painted"];
|
|
13
|
+
/**
|
|
14
|
+
* The look used when none is named or the name is not a look: `line`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { DEFAULT_LOOK } from "@johnmorrisdotca/uchusen-rockets";
|
|
19
|
+
*
|
|
20
|
+
* console.log(DEFAULT_LOOK);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
3
23
|
export const DEFAULT_LOOK = "line";
|
|
4
24
|
const NIGHT = {
|
|
5
25
|
hull: ["#0c1422", "#2a3850", "#0c1422"],
|
|
@@ -10,6 +30,16 @@ const NIGHT = {
|
|
|
10
30
|
bell: ["#0a0f18", "#242f42", "#0a0f18"],
|
|
11
31
|
foam: ["#16202f", "#3a475c", "#16202f"],
|
|
12
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Every look, by name. A look is one entry of this table.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { LOOKS } from "@johnmorrisdotca/uchusen-rockets";
|
|
39
|
+
*
|
|
40
|
+
* console.log(Object.keys(LOOKS));
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
13
43
|
export const LOOKS = {
|
|
14
44
|
line: { line: "#8fa1b8", outlinePx: 1.4, featurePx: 1, weldPx: 0.6, weldOpacity: 0.45, outline: 1.2, feature: 0.8, weld: 0.45, fills: NIGHT, halo: true },
|
|
15
45
|
thick: { line: "#b4c2d4", outlinePx: 3.4, featurePx: 2, weldPx: 0.9, weldOpacity: 0.5, outline: 3.4, feature: 1.7, weld: 0.6, fills: NIGHT, halo: true },
|
|
@@ -34,5 +64,16 @@ export const LOOKS = {
|
|
|
34
64
|
halo: false,
|
|
35
65
|
},
|
|
36
66
|
};
|
|
37
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* A value from outside as a look's name: the default for anything else.
|
|
69
|
+
*
|
|
70
|
+
* @param value Anything.
|
|
71
|
+
* @returns The look's name if it is one, and the default (`line`) for anything else.
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* import { cleanLook } from "@johnmorrisdotca/uchusen-rockets";
|
|
75
|
+
*
|
|
76
|
+
* console.log(cleanLook("painted"), cleanLook("shiny"));
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
38
79
|
export const cleanLook = (value) => (LOOK_NAMES.includes(value) ? value : DEFAULT_LOOK);
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import type { FillName } from "../looks.ts";
|
|
2
|
+
/**
|
|
3
|
+
* One material: its colour, how metal and how rough it is in a 3D view, and the fill group it takes in a drawing.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { MATERIALS, type MaterialSpec } from "@johnmorrisdotca/uchusen-rockets";
|
|
8
|
+
*
|
|
9
|
+
* const steel: MaterialSpec = MATERIALS.steel;
|
|
10
|
+
* console.log(steel.color, steel.fill);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
2
13
|
export interface MaterialSpec {
|
|
3
14
|
color: string;
|
|
4
15
|
metal: number;
|
|
@@ -6,6 +17,16 @@ export interface MaterialSpec {
|
|
|
6
17
|
/** The fill it takes in a drawing. */
|
|
7
18
|
fill: FillName;
|
|
8
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Every material the meshes use, by name. One naming scheme serves every source.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { MATERIALS } from "@johnmorrisdotca/uchusen-rockets";
|
|
26
|
+
*
|
|
27
|
+
* console.log(Object.keys(MATERIALS).length > 5);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
9
30
|
export declare const MATERIALS: {
|
|
10
31
|
readonly steel: {
|
|
11
32
|
readonly color: "#c3c7cb";
|
|
@@ -152,4 +173,15 @@ export declare const MATERIALS: {
|
|
|
152
173
|
readonly fill: "metal";
|
|
153
174
|
};
|
|
154
175
|
};
|
|
176
|
+
/**
|
|
177
|
+
* The name of one material in `MATERIALS`.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* import type { MaterialName } from "@johnmorrisdotca/uchusen-rockets";
|
|
182
|
+
*
|
|
183
|
+
* const name: MaterialName = "steel";
|
|
184
|
+
* console.log(name);
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
155
187
|
export type MaterialName = keyof typeof MATERIALS;
|
package/dist/model/materials.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every material the meshes use, by name. One naming scheme serves every source.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { MATERIALS } from "@johnmorrisdotca/uchusen-rockets";
|
|
7
|
+
*
|
|
8
|
+
* console.log(Object.keys(MATERIALS).length > 5);
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
1
11
|
export const MATERIALS = {
|
|
2
12
|
steel: { color: "#c3c7cb", metal: 1, rough: 0.3, fill: "hull" },
|
|
3
13
|
tile: { color: "#101114", metal: 0, rough: 0.62, fill: "tile" },
|
package/dist/model/registry.d.ts
CHANGED
|
@@ -4,5 +4,27 @@ export interface PartEntry {
|
|
|
4
4
|
record: PartRecord;
|
|
5
5
|
pieces: () => Piece[];
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Every part of every rocket, each with its record: its real size in metres, the joints it mates at, and where its shape came from.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { PART_ENTRIES } from "@johnmorrisdotca/uchusen-rockets";
|
|
13
|
+
*
|
|
14
|
+
* console.log(PART_ENTRIES.length, PART_ENTRIES[0]?.record.name);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
7
17
|
export declare const PART_ENTRIES: readonly PartEntry[];
|
|
18
|
+
/**
|
|
19
|
+
* Finds a part by its id.
|
|
20
|
+
*
|
|
21
|
+
* @param id A part's id.
|
|
22
|
+
* @returns The part's entry, or undefined for an id that is not a part.
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { partEntry } from "@johnmorrisdotca/uchusen-rockets";
|
|
26
|
+
*
|
|
27
|
+
* console.log(partEntry("raptor-vacuum")?.record.height, partEntry("nonsense"));
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
8
30
|
export declare const partEntry: (id: string) => PartEntry | undefined;
|
package/dist/model/registry.js
CHANGED
|
@@ -162,6 +162,28 @@ const RAPTOR_LENGTH = { value: 3.1, source: "wikipedia-raptor", note: "The famil
|
|
|
162
162
|
const b3 = STARSHIP_DRAWS.v3;
|
|
163
163
|
const b2 = STARSHIP_DRAWS.v2;
|
|
164
164
|
entries.push(detail("raptor-sea-level", "engine", "Raptor, sea-level", 3.1, 1.24, { height: RAPTOR_LENGTH, diameter: RAPTOR_DIAMETER }, () => raptor([0, 0], 0, "sea")), detail("raptor-vacuum", "engine", "Raptor, vacuum", 4.4, 2.3, { height: blankFigure, diameter: blankFigure }, () => raptor([0, 0], 0, "vacuum")), detail("grid-fin-four", "fin", "Grid fin, Blocks 1 and 2", 0.9, 2.9, { height: blankFigure, diameter: blankFigure }, () => gridFin(90, 0, b2.radius, b2.fins.reach, b2.fins.width, b2.fins.thick, false)), detail("grid-fin-three", "fin", "Grid fin, Block 3", 0.9, 3.4, { height: blankFigure, diameter: blankFigure }, () => gridFin(90, 0, b3.radius, b3.fins.reach, b3.fins.width, b3.fins.thick, true)), detail("flap-aft", "flap", "Aft flap", 11.6, 3.8, { height: blankFigure, diameter: blankFigure }, () => [flap(b3.aft, 1)]), detail("flap-forward", "flap", "Forward flap, Blocks 2 and 3", 8.1, 4.7, { height: blankFigure, diameter: blankFigure }, () => [flap(b3.forward, 1)]), detail("merlin-sea-level", "engine", "Merlin, sea-level", 2, 0.92, { height: blankFigure, diameter: blankFigure }, () => merlin([0, 0], 0, 0.46, 2)));
|
|
165
|
+
/**
|
|
166
|
+
* Every part of every rocket, each with its record: its real size in metres, the joints it mates at, and where its shape came from.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* import { PART_ENTRIES } from "@johnmorrisdotca/uchusen-rockets";
|
|
171
|
+
*
|
|
172
|
+
* console.log(PART_ENTRIES.length, PART_ENTRIES[0]?.record.name);
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
165
175
|
export const PART_ENTRIES = entries;
|
|
166
176
|
const byId = new Map(entries.map((entry) => [entry.record.id, entry]));
|
|
177
|
+
/**
|
|
178
|
+
* Finds a part by its id.
|
|
179
|
+
*
|
|
180
|
+
* @param id A part's id.
|
|
181
|
+
* @returns The part's entry, or undefined for an id that is not a part.
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* import { partEntry } from "@johnmorrisdotca/uchusen-rockets";
|
|
185
|
+
*
|
|
186
|
+
* console.log(partEntry("raptor-vacuum")?.record.height, partEntry("nonsense"));
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
167
189
|
export const partEntry = (id) => byId.get(id);
|
package/dist/parts.d.ts
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
import type { CreditId } from "./data/credits.ts";
|
|
2
2
|
import type { Figure } from "./data/types.ts";
|
|
3
|
+
/**
|
|
4
|
+
* What kind of part a record is: a booster, a ship, a stage, a fairing, a capsule, an engine, a fin and so on. A joint only mates a part of a kind that fits it.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { partEntry, type PartKind } from "@johnmorrisdotca/uchusen-rockets";
|
|
9
|
+
*
|
|
10
|
+
* const kind: PartKind | undefined = partEntry("raptor-vacuum")?.record.kind;
|
|
11
|
+
* console.log(kind);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
3
14
|
export type PartKind = "booster" | "first-stage" | "ship" | "second-stage" | "fairing" | "capsule" | "trunk" | "engine" | "fin" | "flap" | "ring" | "test-vehicle" | "third-stage" | "adapter" | "service-module" | "tower" | "tank" | "solid-booster" | "liquid-booster" | "orbiter" | "deck" | "mount" | "arms" | "site" | "spacecraft";
|
|
4
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Where a part mates. Every part's origin is the middle of its base on its axis, at its lowest point; Y is up and the windward side faces +Z, in metres.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { partEntry, type Joint } from "@johnmorrisdotca/uchusen-rockets";
|
|
21
|
+
*
|
|
22
|
+
* const top: Joint | undefined = partEntry("starship-v3-booster")?.record.joints.top;
|
|
23
|
+
* console.log(top);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
5
26
|
export interface Joint {
|
|
6
27
|
/** What this joint is, so only like meets like: "stage". */
|
|
7
28
|
kind: "stage";
|
|
@@ -10,6 +31,17 @@ export interface Joint {
|
|
|
10
31
|
/** Metres across at the joint. */
|
|
11
32
|
diameter: number;
|
|
12
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The one record every part has: its id, kind and name, the rocket and variants it is true for, its height and diameter in metres, the sourced figures, its joints, any painted model, and where its shape came from.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { partEntry, type PartRecord } from "@johnmorrisdotca/uchusen-rockets";
|
|
40
|
+
*
|
|
41
|
+
* const record: PartRecord | undefined = partEntry("starship-v3-ship")?.record;
|
|
42
|
+
* console.log(record?.name, record?.height, record?.trueTo);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
13
45
|
export interface PartRecord {
|
|
14
46
|
id: string;
|
|
15
47
|
kind: PartKind;
|
package/dist/pixels.d.ts
CHANGED
|
@@ -1,8 +1,48 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* The most the backing store may hold, in pixels (a 620 x 827 view at a ratio of 2 is 2 million).
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { MAX_PIXELS } from "@johnmorrisdotca/uchusen-rockets";
|
|
7
|
+
*
|
|
8
|
+
* console.log(MAX_PIXELS);
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
2
11
|
export declare const MAX_PIXELS = 6000000;
|
|
3
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* The longest side the backing store may have.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { MAX_SIDE } from "@johnmorrisdotca/uchusen-rockets";
|
|
18
|
+
*
|
|
19
|
+
* console.log(MAX_SIDE);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
4
22
|
export declare const MAX_SIDE = 4096;
|
|
5
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* The sharpest ratio ever used, however dense the screen.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { MAX_RATIO } from "@johnmorrisdotca/uchusen-rockets";
|
|
29
|
+
*
|
|
30
|
+
* console.log(MAX_RATIO);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
6
33
|
export declare const MAX_RATIO = 2;
|
|
7
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* The device pixel ratio to draw a `width` x `height` view at: the screen's own, held to 2, to 4096 pixels a side and to 6 million in all. At least 0.25, and 1 for a nonsense value.
|
|
36
|
+
*
|
|
37
|
+
* @param width The view's width in CSS pixels.
|
|
38
|
+
* @param height Its height in CSS pixels.
|
|
39
|
+
* @param deviceRatio The screen's own pixel ratio.
|
|
40
|
+
* @returns The ratio to draw at.
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { pixelRatioFor } from "@johnmorrisdotca/uchusen-rockets";
|
|
44
|
+
*
|
|
45
|
+
* console.log(pixelRatioFor(620, 827, 3), pixelRatioFor(3000, 3000, 2));
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
8
48
|
export declare function pixelRatioFor(width: number, height: number, deviceRatio: number): number;
|