@threlte/theatre 0.0.1

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 (32) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +19 -0
  3. package/dist/CHANGELOG.md +165 -0
  4. package/dist/LICENSE.md +21 -0
  5. package/dist/README.md +19 -0
  6. package/dist/components/Editable/Editable.svelte +301 -0
  7. package/dist/components/Editable/Editable.svelte.d.ts +7 -0
  8. package/dist/components/Editable/createRawEventDispatcher.d.ts +7 -0
  9. package/dist/components/Editable/createRawEventDispatcher.js +19 -0
  10. package/dist/components/Editable/typeGuards.d.ts +5 -0
  11. package/dist/components/Editable/typeGuards.js +12 -0
  12. package/dist/components/Editable/types.d.ts +28 -0
  13. package/dist/components/Editable/types.js +1 -0
  14. package/dist/components/Editable/utils.d.ts +25 -0
  15. package/dist/components/Editable/utils.js +86 -0
  16. package/dist/components/Project/Project.svelte +19 -0
  17. package/dist/components/Project/Project.svelte.d.ts +22 -0
  18. package/dist/components/Sheet/Sheet.svelte +70 -0
  19. package/dist/components/Sheet/Sheet.svelte.d.ts +65 -0
  20. package/dist/components/Studio/InnerStudio.svelte +16 -0
  21. package/dist/components/Studio/InnerStudio.svelte.d.ts +14 -0
  22. package/dist/components/Studio/Studio.svelte +10 -0
  23. package/dist/components/Studio/Studio.svelte.d.ts +18 -0
  24. package/dist/components/Theatre/Theatre.svelte +16 -0
  25. package/dist/components/Theatre/Theatre.svelte.d.ts +20 -0
  26. package/dist/components/consts.d.ts +6 -0
  27. package/dist/components/consts.js +5 -0
  28. package/dist/components/theatre.d.ts +2 -0
  29. package/dist/components/theatre.js +2 -0
  30. package/dist/index.d.ts +5 -0
  31. package/dist/index.js +6 -0
  32. package/package.json +52 -0
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Grischa Erbe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ ![Threlte Logo](https://user-images.githubusercontent.com/46897060/178455971-434f4c5d-6c26-4d34-acdc-b4b50e2a8a2c.png)
2
+
3
+ <h1 align="center">@threlte/theatre</h1>
4
+
5
+ Provides easy to use components and hooks to use [Theatre.js](https://www.theatrejs.com/) in threlte.
6
+
7
+ ## Official Documentation
8
+
9
+ Visit [threlte.xyz](https://threlte.xyz)
10
+
11
+ ## Support
12
+
13
+ Join the [Discord server](https://discord.gg/EqUBCfCaGm)
14
+
15
+ ---
16
+
17
+ ### License
18
+
19
+ The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
@@ -0,0 +1,165 @@
1
+ # @threlte/extras
2
+
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d69391a: Add Attractor component and documentation
8
+
9
+ ## 0.4.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 4b4d7be: Added rapiers damping properties to the component <RigidBody>
14
+
15
+ ## 0.3.2
16
+
17
+ ### Patch Changes
18
+
19
+ - c7e226f: useJoint is now exported and its types are fixed
20
+
21
+ ## 0.3.1
22
+
23
+ ### Patch Changes
24
+
25
+ - 9d29fc0: removed unused variable
26
+
27
+ ## 0.3.0
28
+
29
+ ### Minor Changes
30
+
31
+ - 1a0f305: removed properties "manifold" and "flipped" from contact force event
32
+
33
+ ### Patch Changes
34
+
35
+ - 291af9b: Exporting rapier event types for easier method typing
36
+
37
+ ## 0.2.0
38
+
39
+ ### Minor Changes
40
+
41
+ - 73b533d: Added contact force events and streamlined event management
42
+
43
+ ### Patch Changes
44
+
45
+ - 7d46de2: sensors need events too!
46
+
47
+ ## 0.1.0
48
+
49
+ ### Minor Changes
50
+
51
+ - c272617: Hooks added to add Joints, Collider and AutoColliders now accepts density, mass or massProperties, documentation for joints hooks added, "Basic Vehicle Controller" Recipe added.
52
+
53
+ ## 0.0.3
54
+
55
+ ### Patch Changes
56
+
57
+ - cd6dac6: cleaned up dead code in RigidBody component
58
+
59
+ ## 0.0.2
60
+
61
+ ### Patch Changes
62
+
63
+ - 62d2c5c: fixed `<RigidBody>` initial transforms
64
+
65
+ ## 0.0.1
66
+
67
+ ### Patch Changes
68
+
69
+ - 7a3fa6b: # NEW PACKAGE: @threlte/rapier
70
+
71
+ This package provides easy to use components and hooks to use the [rapier](https://rapier.rs/) physics engine in threlte.
72
+
73
+ It comes with several components to get you started: [`<World>`](https://threlte.xyz/rapier/world), [`<RigidBody>`](https://threlte.xyz/rapier/rigid-body), [`<Collider>`](https://threlte.xyz/rapier/collider), [`<AutoColliders>`](https://threlte.xyz/rapier/auto-colliders), [`<CollisionGroups>`](https://threlte.xyz/rapier/collision-groups) and [`<Debug>`](https://threlte.xyz/rapier/debug).
74
+
75
+ It also features several handy hooks: [`<useRapier>`](https://threlte.xyz/rapier/use-rapier), [`<useCollisionGroups>`](https://threlte.xyz/rapier/use-collision-groups) and [`<useRigidBody>`](https://threlte.xyz/rapier/use-rigid-body).
76
+
77
+ ## 4.0.0
78
+
79
+ ### Major Changes
80
+
81
+ - 52e021c: # Breaking Change
82
+
83
+ The threlte repository has been moved to its own GitHub Organization: [https://github.com/threlte/threlte](https://github.com/threlte/threlte).
84
+ threlte consists now of two npm packages: `@threlte/core` and `@threlte/extras`, managed in a mono repository:
85
+
86
+ `@threlte/core` consists of components, hooks and other utilites that follow three.js principles, nomenclature and inheritance as closely as useful and possible. Therefore components that have been part of the package `threlte` have been moved to the new home of all kinds of useful abstractons: `@threlte/extras`.
87
+
88
+ `@threlte/extras` consists of useful abstractions and helpers that you may find yourself use all the time. These components do not need to follow three.js principles as strict as exports from `@threlte/core`, but they do where it makes sense.
89
+
90
+ ## The breaking changes in detail:
91
+
92
+ - Moved `<GLTF>` component as well as `useGltf` hook to `@threlte/extras`.
93
+ - Moved `<Text>` component to `@threlte/extras`.
94
+
95
+ ## How to update
96
+
97
+ Replace imports from `threlte` and `threlte/extras`:
98
+
99
+ 1. `npm rm threlte`
100
+ 2. `npm i -D @threlte/core @threlte/extras`
101
+ 3. Replace `import {…} from 'threlte'` with `import {…} from '@threlte/core'`
102
+ 4. Replace `import {…} from 'threlte/extras'` with `import {…} from '@threlte/extras'`
103
+
104
+ Specifically replace imports of `<GLTF>`, `useGltf` or `<Text>`:
105
+
106
+ 3. Replace `import { GLTF, useGltf, Text } from 'threlte'` with `import { GLTF, useGltf, Text } from '@threlte/extras'`
107
+
108
+ # Other changes
109
+
110
+ - The documentation is now hosted on Vercel and as such we are hoping for a Vercel Sponsorship for OSS. There have also been some style fixes and overhauls.
111
+
112
+ ## 3.13.10
113
+
114
+ ### Patch Changes
115
+
116
+ - 4de7371: added svelte identifier
117
+
118
+ ## 3.13.9
119
+
120
+ ### Patch Changes
121
+
122
+ - 41cc5a1: test
123
+
124
+ ## 3.13.8
125
+
126
+ ### Patch Changes
127
+
128
+ - 79a64f5: test
129
+
130
+ ## 3.13.7
131
+
132
+ ### Patch Changes
133
+
134
+ - test
135
+
136
+ ## 3.13.6
137
+
138
+ ### Patch Changes
139
+
140
+ - trying to delete
141
+
142
+ ## 3.13.5
143
+
144
+ ### Patch Changes
145
+
146
+ - 11aa5eb: yes
147
+
148
+ ## 3.13.4
149
+
150
+ ### Patch Changes
151
+
152
+ - 0c40456: added scripts to clean up packages
153
+ - 7cc4e5d: added node types
154
+
155
+ ## 3.13.3
156
+
157
+ ### Patch Changes
158
+
159
+ - a2a6d93: test
160
+
161
+ ## 3.13.2
162
+
163
+ ### Patch Changes
164
+
165
+ - 8dbf8cd: Test
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Grischa Erbe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/README.md ADDED
@@ -0,0 +1,19 @@
1
+ ![Threlte Logo](https://user-images.githubusercontent.com/46897060/178455971-434f4c5d-6c26-4d34-acdc-b4b50e2a8a2c.png)
2
+
3
+ <h1 align="center">@threlte/theatre</h1>
4
+
5
+ Provides easy to use components and hooks to use [Theatre.js](https://www.theatrejs.com/) in threlte.
6
+
7
+ ## Official Documentation
8
+
9
+ Visit [threlte.xyz](https://threlte.xyz)
10
+
11
+ ## Support
12
+
13
+ Join the [Discord server](https://discord.gg/EqUBCfCaGm)
14
+
15
+ ---
16
+
17
+ ### License
18
+
19
+ The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
@@ -0,0 +1,301 @@
1
+ <script>import { TransformControls, useParent, useThrelte } from '@threlte/core';
2
+ import { getContext } from 'svelte';
3
+ import { DEG2RAD, RAD2DEG } from 'three/src/math/MathUtils';
4
+ import { globalObjects, globalStudio } from '../consts';
5
+ import { createRawEventDispatcher } from './createRawEventDispatcher';
6
+ import { isObject3D, isOrthographicOrPerspectiveCamera, isPrimitive } from './typeGuards';
7
+ import { getAutoPropValue, parseAutoPropKeyByPath, resolve } from './utils';
8
+ export let name;
9
+ export let transform = false;
10
+ export let props = undefined;
11
+ export let controls = undefined;
12
+ export let snap = undefined;
13
+ const parent = useParent();
14
+ const { invalidate } = useThrelte();
15
+ /**
16
+ * Automatic Props that are defined via boolean or string values can't use the
17
+ * component prop name as the theatre prop name because component prop names
18
+ * do not need to be alphanumeric whereas theatre prop names do. Thats why we
19
+ * need to define a mapping of theatre prop names to component prop names in
20
+ * order to resolve the target of the prop. Also, some props get a special
21
+ * treatment in terms of UI presentation or data transformation. That is
22
+ * represented by the `type` property.
23
+ */
24
+ const autoProps = new Map();
25
+ /**
26
+ * Transform props are props that are added via the component prop
27
+ * "transform".
28
+ */
29
+ const transformProps = (transform &&
30
+ $parent &&
31
+ $parent.isObject3D &&
32
+ $parent.position &&
33
+ $parent.rotation &&
34
+ $parent.scale && {
35
+ Position: { ...$parent.position },
36
+ Rotation: {
37
+ x: $parent.rotation.x * RAD2DEG,
38
+ y: $parent.rotation.y * RAD2DEG,
39
+ z: $parent.rotation.z * RAD2DEG
40
+ },
41
+ Scale: { ...$parent.scale }
42
+ }) ||
43
+ undefined;
44
+ /**
45
+ * If transform props are defined, we need to add them to the list of auto
46
+ * props.
47
+ */
48
+ if (transformProps) {
49
+ autoProps.set('Position', {
50
+ path: 'position',
51
+ transform: 'none'
52
+ });
53
+ autoProps.set('Rotation', {
54
+ path: 'rotation',
55
+ transform: 'euler'
56
+ });
57
+ autoProps.set('Scale', {
58
+ path: 'scale',
59
+ transform: 'none'
60
+ });
61
+ }
62
+ const parseAutoProp = {
63
+ boolean: (propName, _) => {
64
+ /**
65
+ * If the prop value is a boolean, we need to infer some things based on the name of the prop:
66
+ * - initial value
67
+ * - target object
68
+ * - target key
69
+ * - prop key (because these need to be alphanumeric)
70
+ * This also means handling special cases like euler angles and colors
71
+ */
72
+ const key = parseAutoPropKeyByPath(propName);
73
+ const { transform, value } = getAutoPropValue($parent, propName);
74
+ const prop = { [key]: value };
75
+ autoProps.set(key, {
76
+ path: propName,
77
+ transform
78
+ });
79
+ return prop;
80
+ },
81
+ string: (propName, propValue) => {
82
+ /**
83
+ * If the prop value is a string, we need to infer some things based on the name of the prop:
84
+ * - initial value
85
+ * - target object
86
+ * - target key
87
+ * This also means handling special cases like euler angles and colors
88
+ * The prop value is used as the prop key
89
+ */
90
+ const { transform, value } = getAutoPropValue($parent, propName);
91
+ const prop = { [propName]: value };
92
+ autoProps.set(name, {
93
+ path: propName,
94
+ transform
95
+ });
96
+ return prop;
97
+ }
98
+ };
99
+ const parsedProps = Object.entries($$restProps)
100
+ .filter(Boolean)
101
+ .map(([key, value]) => {
102
+ if (typeof value === 'boolean') {
103
+ return parseAutoProp.boolean(key, value);
104
+ }
105
+ else if (typeof value === 'string') {
106
+ return parseAutoProp.string(key, value);
107
+ }
108
+ throw new Error(`Invalid prop type for auto prop ${key}: ` + typeof value + '. Expected boolean or string.');
109
+ })
110
+ .reduce((acc, curr) => ({ ...acc, ...curr }), {});
111
+ const sheet = getContext('theatre-sheet');
112
+ const projectId = sheet.address.projectId;
113
+ const sheetId = sheet.address.sheetId;
114
+ const instanceId = sheet.address.sheetInstanceId;
115
+ const object = globalObjects.get(`${projectId}-${sheetId}-${instanceId}-${name}`) ??
116
+ sheet.object(name, {
117
+ ...parsedProps,
118
+ ...props,
119
+ ...transformProps
120
+ });
121
+ globalObjects.set(`${projectId}-${sheetId}-${instanceId}-${name}`, object);
122
+ let values = object.value;
123
+ const dispatchRaw = createRawEventDispatcher();
124
+ let selected = false;
125
+ let isMouseDown = false;
126
+ /**
127
+ * The values behind properties with these keys make updating the projection
128
+ * matrix necessary.
129
+ */
130
+ const updateProjectionMatrixKeys = [
131
+ 'fov',
132
+ 'near',
133
+ 'far',
134
+ 'zoom',
135
+ 'left',
136
+ 'right',
137
+ 'top',
138
+ 'bottom',
139
+ 'aspect'
140
+ ];
141
+ object.onValuesChange((newValues) => {
142
+ // assign new values to slot prop
143
+ values = newValues;
144
+ // dispatch events to parent component callbacks
145
+ dispatchRaw('change', newValues);
146
+ // update auto props
147
+ Object.entries(newValues).forEach((prop) => {
148
+ // do not apply values while the transformControls are on
149
+ if (isMouseDown && selected && transform && controls)
150
+ return;
151
+ if (!prop)
152
+ return;
153
+ const [key, value] = prop;
154
+ const autoProp = autoProps.get(key);
155
+ if (!autoProp)
156
+ return;
157
+ const { path, transform: type } = autoProp;
158
+ const { key: targetKey, target } = resolve($parent, path);
159
+ if (isPrimitive(value)) {
160
+ target[targetKey] = value;
161
+ }
162
+ else if (type === 'euler') {
163
+ Object.entries(value).forEach(([k, v]) => {
164
+ target[targetKey][k] = v * DEG2RAD;
165
+ });
166
+ }
167
+ else {
168
+ Object.entries(value).forEach(([k, v]) => {
169
+ target[targetKey][k] = v;
170
+ });
171
+ }
172
+ if (updateProjectionMatrixKeys.includes(targetKey) &&
173
+ isOrthographicOrPerspectiveCamera($parent)) {
174
+ $parent.updateProjectionMatrix();
175
+ }
176
+ invalidate();
177
+ });
178
+ });
179
+ export const read = () => {
180
+ if (!$globalStudio)
181
+ return;
182
+ let props = {};
183
+ for (const [key, value] of autoProps.entries()) {
184
+ const prop = {
185
+ [key]: getAutoPropValue($parent, value.path).value
186
+ };
187
+ props = {
188
+ ...props,
189
+ ...prop
190
+ };
191
+ }
192
+ $globalStudio.transaction(({ set }) => {
193
+ set(object.props, props);
194
+ });
195
+ };
196
+ let scrub = undefined;
197
+ const onMouseDown = () => {
198
+ scrub = $globalStudio?.scrub();
199
+ isMouseDown = true;
200
+ };
201
+ const onMouseUp = async () => {
202
+ isMouseDown = false;
203
+ scrub?.commit();
204
+ scrub = undefined;
205
+ };
206
+ const onChange = () => {
207
+ if (!isMouseDown)
208
+ return;
209
+ if (!transform)
210
+ return;
211
+ if (!selected)
212
+ return;
213
+ scrub?.capture(({ set }) => {
214
+ if (!$parent)
215
+ return;
216
+ const { position, rotation, scale } = $parent;
217
+ if (mode === 'translate') {
218
+ set(object.props.Position, {
219
+ x: position.x,
220
+ y: position.y,
221
+ z: position.z
222
+ });
223
+ }
224
+ else if (mode === 'rotate') {
225
+ set(object.props.Rotation, {
226
+ x: rotation.x * RAD2DEG,
227
+ y: rotation.y * RAD2DEG,
228
+ z: rotation.z * RAD2DEG
229
+ });
230
+ }
231
+ else if (mode === 'scale') {
232
+ set(object.props.Scale, {
233
+ x: scale.x,
234
+ y: scale.y,
235
+ z: scale.z
236
+ });
237
+ }
238
+ });
239
+ };
240
+ $globalStudio?.onSelectionChange((newSelection) => {
241
+ if (newSelection.includes(object)) {
242
+ selected = true;
243
+ }
244
+ else {
245
+ selected = false;
246
+ }
247
+ });
248
+ let mode = 'translate';
249
+ let snapActive = false;
250
+ $: snapValues = {
251
+ translate: snap?.translate ?? 1,
252
+ rotate: (snap?.rotate ?? 45) * DEG2RAD,
253
+ scale: snap?.scale ?? 0.1
254
+ };
255
+ const onKeyPress = (e) => {
256
+ if (e.key === 't') {
257
+ mode = 'translate';
258
+ }
259
+ if (e.key === 'r') {
260
+ mode = 'rotate';
261
+ }
262
+ if (e.key === 's') {
263
+ mode = 'scale';
264
+ }
265
+ };
266
+ const onKeyDown = (e) => {
267
+ if (e.key === 'Shift') {
268
+ snapActive = true;
269
+ }
270
+ };
271
+ const onKeyUp = (e) => {
272
+ if (e.key === 'Shift') {
273
+ snapActive = false;
274
+ }
275
+ };
276
+ </script>
277
+
278
+ <svelte:window
279
+ on:keypress={onKeyPress}
280
+ on:keydown={onKeyDown}
281
+ on:keyup={onKeyUp}
282
+ />
283
+
284
+ {#if selected && isObject3D($parent) && transform && controls}
285
+ <TransformControls
286
+ {mode}
287
+ translationSnap={snapActive ? snapValues.translate : null}
288
+ rotationSnap={snapActive ? snapValues.rotate : null}
289
+ scaleSnap={snapActive ? snapValues.scale : null}
290
+ on:change={onChange}
291
+ on:mouseDown={onMouseDown}
292
+ on:mouseUp={onMouseUp}
293
+ />
294
+ {/if}
295
+
296
+ <slot
297
+ {values}
298
+ {read}
299
+ {sheet}
300
+ {object}
301
+ />
@@ -0,0 +1,7 @@
1
+ import { SvelteComponentTyped } from 'svelte'
2
+
3
+ export default class Editable<T> extends SvelteComponentTyped<
4
+ import('./types').Props<T>,
5
+ import('./types').Events<T>,
6
+ import('./types').Slots<T>
7
+ > {}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * This event dispatcher creates Raw Events unline sveltes own event dispatcher
3
+ * which nests the data in a detail object. This is not nesessary for our use
4
+ * case and makes it harder to work with the data.
5
+ * @returns
6
+ */
7
+ export declare function createRawEventDispatcher<EventMap extends Record<string, unknown> = any>(): <EventKey extends Extract<keyof EventMap, string>>(type: EventKey, value?: EventMap[EventKey]) => void;
@@ -0,0 +1,19 @@
1
+ import { get_current_component } from 'svelte/internal';
2
+ /**
3
+ * This event dispatcher creates Raw Events unline sveltes own event dispatcher
4
+ * which nests the data in a detail object. This is not nesessary for our use
5
+ * case and makes it harder to work with the data.
6
+ * @returns
7
+ */
8
+ export function createRawEventDispatcher() {
9
+ const component = get_current_component();
10
+ const dispatchRawEvent = (type, value) => {
11
+ const callbacks = component.$$.callbacks[type];
12
+ if (callbacks) {
13
+ callbacks.forEach((fn) => {
14
+ fn(value);
15
+ });
16
+ }
17
+ };
18
+ return dispatchRawEvent;
19
+ }
@@ -0,0 +1,5 @@
1
+ import type { Object3D, OrthographicCamera, PerspectiveCamera } from 'three';
2
+ import type { Primitive } from 'type-fest';
3
+ export declare const isObject3D: (value: any) => value is Object3D<import("three").Event>;
4
+ export declare const isPrimitive: (value: any) => value is Primitive;
5
+ export declare const isOrthographicOrPerspectiveCamera: (value: any) => value is PerspectiveCamera | OrthographicCamera;
@@ -0,0 +1,12 @@
1
+ export const isObject3D = (value) => {
2
+ return value && value.isObject3D;
3
+ };
4
+ export const isPrimitive = (value) => {
5
+ return (value === null ||
6
+ typeof value === 'string' ||
7
+ typeof value === 'number' ||
8
+ typeof value === 'boolean');
9
+ };
10
+ export const isOrthographicOrPerspectiveCamera = (value) => {
11
+ return (value && value.isOrthographicCamera) || value.isPerspectiveCamera;
12
+ };
@@ -0,0 +1,28 @@
1
+ import type { ISheet, ISheetObject, UnknownShorthandCompoundProps } from '@theatre/core';
2
+ export declare type StringProp = string;
3
+ export declare type BooleanProp = boolean;
4
+ export declare type AutoProp = StringProp | BooleanProp;
5
+ export declare type Props<T extends UnknownShorthandCompoundProps> = {
6
+ name: string;
7
+ props?: T;
8
+ transform?: boolean;
9
+ controls?: boolean;
10
+ snap?: {
11
+ translate?: number;
12
+ rotate?: number;
13
+ scale?: number;
14
+ };
15
+ read?: () => void;
16
+ } & Record<string, AutoProp | any>;
17
+ export declare type Slots<T extends UnknownShorthandCompoundProps> = {
18
+ default: {
19
+ sheet: ISheet;
20
+ object: ISheetObject<T>;
21
+ values: ISheetObject<T>['value'];
22
+ read: () => void;
23
+ };
24
+ };
25
+ export declare type Events<T extends UnknownShorthandCompoundProps> = {
26
+ change: ISheetObject<T>['value'];
27
+ };
28
+ export declare type PropTransform = 'none' | 'euler';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ import type { PropTransform } from './types';
2
+ /**
3
+ * Resolves a property path to the target and the key.
4
+ * @param target
5
+ * @param propertyPath
6
+ * @returns
7
+ */
8
+ export declare const resolve: (target: any, propertyPath: string) => {
9
+ target: any;
10
+ key: string;
11
+ };
12
+ export declare const parseAutoPropKeyByPath: (path: string) => string;
13
+ /**
14
+ * Auto props need an initial value to be initialized correctly. This value has
15
+ * to be retrieved from the target and in some special cases the value needs to
16
+ * be parsed differently.
17
+ * @param target
18
+ * @param key
19
+ * @returns
20
+ */
21
+ export declare const getAutoPropValue: (parent: any, path: string) => {
22
+ transform: PropTransform;
23
+ value: any;
24
+ };
25
+ export declare const wait: (ms: number) => Promise<unknown>;
@@ -0,0 +1,86 @@
1
+ import { Color, Euler } from 'three';
2
+ import { RAD2DEG } from 'three/src/math/MathUtils';
3
+ import { types } from '../theatre';
4
+ import { isPrimitive } from './typeGuards';
5
+ /**
6
+ * Resolves a property path to the target and the key.
7
+ * @param target
8
+ * @param propertyPath
9
+ * @returns
10
+ */
11
+ export const resolve = (target, propertyPath) => {
12
+ if (propertyPath.includes('.')) {
13
+ const path = propertyPath.split('.');
14
+ const key = path.pop();
15
+ for (let i = 0; i < path.length; i += 1) {
16
+ target = target[path[i]];
17
+ }
18
+ return {
19
+ target,
20
+ key
21
+ };
22
+ }
23
+ else {
24
+ return {
25
+ target,
26
+ key: propertyPath
27
+ };
28
+ }
29
+ };
30
+ export const parseAutoPropKeyByPath = (path) => {
31
+ return path
32
+ .split('.')
33
+ .map((k) => k.charAt(0).toUpperCase() + k.slice(1))
34
+ .join('');
35
+ };
36
+ /**
37
+ * The values behind properties with these keys are assumed to be normalized, so
38
+ * in the range [0, 1].
39
+ */
40
+ const normalizedValueKeys = ['opacity', 'metalness', 'roughness'];
41
+ /**
42
+ * Auto props need an initial value to be initialized correctly. This value has
43
+ * to be retrieved from the target and in some special cases the value needs to
44
+ * be parsed differently.
45
+ * @param target
46
+ * @param key
47
+ * @returns
48
+ */
49
+ export const getAutoPropValue = (parent, path) => {
50
+ const { key, target } = resolve(parent, path);
51
+ // Throw error when key is not found in target
52
+ if (!(key in target)) {
53
+ throw new Error(`Key ${key} not found in target`);
54
+ }
55
+ let type = 'none';
56
+ let value = target[key];
57
+ if (normalizedValueKeys.includes(key)) {
58
+ value = types.number(value, { range: [0, 1] });
59
+ }
60
+ else if (value instanceof Color) {
61
+ // Colors get an RGBA interface
62
+ value = types.rgba({
63
+ r: value.r,
64
+ g: value.g,
65
+ b: value.b,
66
+ a: 1
67
+ });
68
+ }
69
+ else if (value instanceof Euler) {
70
+ // Euler angles will be displayed in degrees
71
+ type = 'euler';
72
+ value = {
73
+ x: value.x * RAD2DEG,
74
+ y: value.y * RAD2DEG,
75
+ z: value.z * RAD2DEG
76
+ };
77
+ }
78
+ else if (!isPrimitive(value)) {
79
+ value = { ...value };
80
+ }
81
+ return {
82
+ transform: type,
83
+ value
84
+ };
85
+ };
86
+ export const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
@@ -0,0 +1,19 @@
1
+ <script>import { globalProjects } from '../consts';
2
+ import { getProject } from '../theatre';
3
+ import { setContext } from 'svelte';
4
+ export let name = 'default';
5
+ export let config = undefined;
6
+ const project = globalProjects.get(name) ?? getProject(name, config);
7
+ globalProjects.set(name, project);
8
+ let isReady = false;
9
+ const init = async () => {
10
+ await project.ready;
11
+ isReady = true;
12
+ };
13
+ init();
14
+ setContext(`theatre-project`, project);
15
+ </script>
16
+
17
+ {#if isReady}
18
+ <slot {project} />
19
+ {/if}
@@ -0,0 +1,22 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { IProjectConfig } from '@theatre/core';
3
+ declare const __propDef: {
4
+ props: {
5
+ name?: string | undefined;
6
+ config?: IProjectConfig | undefined;
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {
12
+ default: {
13
+ project: import("@theatre/core").IProject;
14
+ };
15
+ };
16
+ };
17
+ export declare type ProjectProps = typeof __propDef.props;
18
+ export declare type ProjectEvents = typeof __propDef.events;
19
+ export declare type ProjectSlots = typeof __propDef.slots;
20
+ export default class Project extends SvelteComponentTyped<ProjectProps, ProjectEvents, ProjectSlots> {
21
+ }
22
+ export {};
@@ -0,0 +1,70 @@
1
+ <script>import { globalSheets } from '../consts';
2
+ import { getContext, onDestroy, setContext } from 'svelte';
3
+ import { onChange, val } from '../theatre';
4
+ export let name = 'default';
5
+ export let instance = undefined;
6
+ /**
7
+ * If a number is passed, it will be used as the delay to start autoplaying
8
+ */
9
+ export let autoPlay = false;
10
+ /**
11
+ * Resets the playhead to 0 when the sheet is unmounted or mounted or both
12
+ */
13
+ export let autoReset = false;
14
+ export let autoPause = false;
15
+ export let isPlaying = false;
16
+ const project = getContext(`theatre-project`);
17
+ const projectName = project.address.projectId;
18
+ export const sheet = globalSheets.get(`${projectName}-${name}-${instance}`) ?? project.sheet(name, instance);
19
+ globalSheets.set(`${projectName}-${name}-${instance}`, sheet);
20
+ export const sequence = sheet.sequence;
21
+ setContext(`theatre-sheet`, sheet);
22
+ export const play = (...args) => {
23
+ return sequence.play(...args);
24
+ };
25
+ export const pause = (...args) => {
26
+ return sequence.pause(...args);
27
+ };
28
+ const unsubscribe = onChange(sequence.pointer.playing, (playing) => {
29
+ isPlaying = playing;
30
+ });
31
+ onDestroy(unsubscribe);
32
+ export let position = undefined;
33
+ $: if (position !== undefined) {
34
+ sequence.position = position;
35
+ }
36
+ let timeoutHandler = undefined;
37
+ if (autoPlay) {
38
+ const options = typeof autoPlay === 'boolean' ? {} : autoPlay;
39
+ if (options.delay) {
40
+ timeoutHandler = setTimeout(() => {
41
+ sequence.play(options);
42
+ }, options.delay);
43
+ }
44
+ else {
45
+ sequence.play(options);
46
+ }
47
+ }
48
+ if (autoReset && (typeof autoReset === 'boolean' || autoReset === 'onMount')) {
49
+ sequence.position = 0;
50
+ }
51
+ onDestroy(() => {
52
+ if (timeoutHandler) {
53
+ clearTimeout(timeoutHandler);
54
+ }
55
+ if (autoPause) {
56
+ sequence.pause();
57
+ }
58
+ if (autoReset && (typeof autoReset === 'boolean' || autoReset === 'onDestroy')) {
59
+ sequence.position = 0;
60
+ }
61
+ });
62
+ </script>
63
+
64
+ <slot
65
+ {sheet}
66
+ {sequence}
67
+ {isPlaying}
68
+ {play}
69
+ {pause}
70
+ />
@@ -0,0 +1,65 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { ISequence } from '@theatre/core';
3
+ declare const __propDef: {
4
+ props: {
5
+ name?: string | undefined;
6
+ instance?: string | undefined;
7
+ /**
8
+ * If a number is passed, it will be used as the delay to start autoplaying
9
+ */ autoPlay?: boolean | ({
10
+ iterationCount?: number | undefined;
11
+ range?: [from: number, to: number] | undefined;
12
+ rate?: number | undefined;
13
+ direction?: ("reverse" | "alternate" | "normal" | "alternateReverse") | undefined;
14
+ } & {
15
+ delay?: number | undefined;
16
+ }) | undefined;
17
+ /**
18
+ * Resets the playhead to 0 when the sheet is unmounted or mounted or both
19
+ */ autoReset?: boolean | "onMount" | "onDestroy" | undefined;
20
+ autoPause?: boolean | undefined;
21
+ isPlaying?: boolean | undefined;
22
+ sheet?: import("@theatre/core").ISheet | undefined;
23
+ sequence?: ISequence | undefined;
24
+ play?: ((conf?: {
25
+ iterationCount?: number | undefined;
26
+ range?: [from: number, to: number] | undefined;
27
+ rate?: number | undefined;
28
+ direction?: ("reverse" | "alternate" | "normal" | "alternateReverse") | undefined;
29
+ } | undefined) => Promise<boolean>) | undefined;
30
+ pause?: (() => void) | undefined;
31
+ position?: number | undefined;
32
+ };
33
+ events: {
34
+ [evt: string]: CustomEvent<any>;
35
+ };
36
+ slots: {
37
+ default: {
38
+ sheet: import("@theatre/core").ISheet;
39
+ sequence: ISequence;
40
+ isPlaying: boolean;
41
+ play: (conf?: {
42
+ iterationCount?: number | undefined;
43
+ range?: [from: number, to: number] | undefined;
44
+ rate?: number | undefined;
45
+ direction?: ("reverse" | "alternate" | "normal" | "alternateReverse") | undefined;
46
+ } | undefined) => Promise<boolean>;
47
+ pause: () => void;
48
+ };
49
+ };
50
+ };
51
+ export declare type SheetProps = typeof __propDef.props;
52
+ export declare type SheetEvents = typeof __propDef.events;
53
+ export declare type SheetSlots = typeof __propDef.slots;
54
+ export default class Sheet extends SvelteComponentTyped<SheetProps, SheetEvents, SheetSlots> {
55
+ get sheet(): import("@theatre/core").ISheet;
56
+ get sequence(): ISequence;
57
+ get play(): (conf?: {
58
+ iterationCount?: number | undefined;
59
+ range?: [from: number, to: number] | undefined;
60
+ rate?: number | undefined;
61
+ direction?: ("reverse" | "alternate" | "normal" | "alternateReverse") | undefined;
62
+ } | undefined) => Promise<boolean>;
63
+ get pause(): () => void;
64
+ }
65
+ export {};
@@ -0,0 +1,16 @@
1
+ <script>import { globalStudio } from '../consts';
2
+ import { onDestroy, onMount } from 'svelte';
3
+ onMount(async () => {
4
+ if ($globalStudio) {
5
+ $globalStudio.ui.restore();
6
+ return;
7
+ }
8
+ const studioPkg = await import('@theatre/studio');
9
+ const studio = studioPkg.default;
10
+ studio.initialize();
11
+ globalStudio.set(studio);
12
+ });
13
+ onDestroy(() => {
14
+ $globalStudio?.ui.hide();
15
+ });
16
+ </script>
@@ -0,0 +1,14 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {};
4
+ events: {
5
+ [evt: string]: CustomEvent<any>;
6
+ };
7
+ slots: {};
8
+ };
9
+ export declare type InnerStudioProps = typeof __propDef.props;
10
+ export declare type InnerStudioEvents = typeof __propDef.events;
11
+ export declare type InnerStudioSlots = typeof __propDef.slots;
12
+ export default class InnerStudio extends SvelteComponentTyped<InnerStudioProps, InnerStudioEvents, InnerStudioSlots> {
13
+ }
14
+ export {};
@@ -0,0 +1,10 @@
1
+ <script>import InnerStudio from './InnerStudio.svelte';
2
+ export let enabled = true;
3
+ const browser = typeof window !== 'undefined';
4
+ </script>
5
+
6
+ {#if browser && enabled}
7
+ <InnerStudio />
8
+ {/if}
9
+
10
+ <slot />
@@ -0,0 +1,18 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ enabled?: boolean | undefined;
5
+ };
6
+ events: {
7
+ [evt: string]: CustomEvent<any>;
8
+ };
9
+ slots: {
10
+ default: {};
11
+ };
12
+ };
13
+ export declare type StudioProps = typeof __propDef.props;
14
+ export declare type StudioEvents = typeof __propDef.events;
15
+ export declare type StudioSlots = typeof __propDef.slots;
16
+ export default class Studio extends SvelteComponentTyped<StudioProps, StudioEvents, StudioSlots> {
17
+ }
18
+ export {};
@@ -0,0 +1,16 @@
1
+ <script>import Project from '../Project/Project.svelte';
2
+ import Sheet from '../Sheet/Sheet.svelte';
3
+ import Studio from '../Studio/Studio.svelte';
4
+ export let studio = true;
5
+ export let config = undefined;
6
+ </script>
7
+
8
+ {#if studio}
9
+ <Studio />
10
+ {/if}
11
+
12
+ <Project {config}>
13
+ <Sheet>
14
+ <slot />
15
+ </Sheet>
16
+ </Project>
@@ -0,0 +1,20 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { IProjectConfig } from '@theatre/core';
3
+ declare const __propDef: {
4
+ props: {
5
+ studio?: boolean | undefined;
6
+ config?: IProjectConfig | undefined;
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {
12
+ default: {};
13
+ };
14
+ };
15
+ export declare type TheatreProps = typeof __propDef.props;
16
+ export declare type TheatreEvents = typeof __propDef.events;
17
+ export declare type TheatreSlots = typeof __propDef.slots;
18
+ export default class Theatre extends SvelteComponentTyped<TheatreProps, TheatreEvents, TheatreSlots> {
19
+ }
20
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { IProject, ISheet, ISheetObject } from '@theatre/core';
2
+ import type { IStudio } from '@theatre/studio';
3
+ export declare const globalProjects: Map<string, IProject>;
4
+ export declare const globalSheets: Map<string, ISheet>;
5
+ export declare const globalObjects: Map<string, ISheetObject<import("@theatre/core").UnknownShorthandCompoundProps>>;
6
+ export declare const globalStudio: import("svelte/store").Writable<IStudio | undefined>;
@@ -0,0 +1,5 @@
1
+ import { writable } from 'svelte/store';
2
+ export const globalProjects = new Map();
3
+ export const globalSheets = new Map();
4
+ export const globalObjects = new Map();
5
+ export const globalStudio = writable(undefined);
@@ -0,0 +1,2 @@
1
+ import * as theatreCore from '@theatre/core';
2
+ export declare const getProject: typeof theatreCore.getProject, types: typeof theatreCore.types, onChange: typeof theatreCore.onChange, val: typeof theatreCore.val;
@@ -0,0 +1,2 @@
1
+ import * as theatreCore from '@theatre/core';
2
+ export const { getProject, types, onChange, val } = theatreCore;
@@ -0,0 +1,5 @@
1
+ export { default as Studio } from './components/Studio/Studio.svelte';
2
+ export { default as Project } from './components/Project/Project.svelte';
3
+ export { default as Sheet } from './components/Sheet/Sheet.svelte';
4
+ export { default as Editable } from './components/Editable/Editable.svelte';
5
+ export { default as Theatre } from './components/Theatre/Theatre.svelte';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ // components
2
+ export { default as Studio } from './components/Studio/Studio.svelte';
3
+ export { default as Project } from './components/Project/Project.svelte';
4
+ export { default as Sheet } from './components/Sheet/Sheet.svelte';
5
+ export { default as Editable } from './components/Editable/Editable.svelte';
6
+ export { default as Theatre } from './components/Theatre/Theatre.svelte';
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@threlte/theatre",
3
+ "version": "0.0.1",
4
+ "author": "Grischa Erbe <hello@legrisch.com> (https://legrisch.com)",
5
+ "license": "MIT",
6
+ "devDependencies": {
7
+ "@sveltejs/adapter-auto": "1.0.0-next.61",
8
+ "@sveltejs/adapter-static": "1.0.0-next.35",
9
+ "@sveltejs/kit": "1.0.0-next.377",
10
+ "@theatre/core": "0.5.1-rc.1",
11
+ "@theatre/studio": "0.5.1-rc.1",
12
+ "@threlte/core": "5.0.7",
13
+ "@types/node": "^18.0.3",
14
+ "@types/three": "^0.144.0",
15
+ "@typescript-eslint/eslint-plugin": "^4.31.1",
16
+ "@typescript-eslint/parser": "^4.31.1",
17
+ "@yushijinhun/three-minifier-rollup": "^0.3.1",
18
+ "eslint": "^7.32.0",
19
+ "eslint-config-prettier": "^8.3.0",
20
+ "eslint-plugin-svelte3": "^3.2.1",
21
+ "prettier": "^2.6.2",
22
+ "prettier-plugin-svelte": "^2.4.0",
23
+ "svelte": "^3.47.0",
24
+ "svelte-check": "^2.7.0",
25
+ "svelte-preprocess": "^4.10.5",
26
+ "svelte2tsx": "^0.5.9",
27
+ "three": "^0.145.0",
28
+ "ts-node": "^10.8.2",
29
+ "tsafe": "^0.9.0",
30
+ "tslib": "^2.3.1",
31
+ "type-fest": "^2.13.0",
32
+ "typescript": "^4.6.3"
33
+ },
34
+ "type": "module",
35
+ "exports": {
36
+ "./package.json": "./package.json",
37
+ ".": "./dist/index.js"
38
+ },
39
+ "types": "./dist/index.d.ts",
40
+ "svelte": "./dist/index.js",
41
+ "files": [
42
+ "dist"
43
+ ],
44
+ "scripts": {
45
+ "package": "svelte-kit package && ts-node --esm ./scripts/cleanupPackage.ts && rm ./dist/package.json",
46
+ "check": "svelte-check --tsconfig ./tsconfig.json",
47
+ "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
48
+ "lint": "prettier --check --plugin-search-dir=. . && eslint .",
49
+ "format": "prettier --write --plugin-search-dir=. .",
50
+ "cleanup": "rm -rf node_modules && rm -rf .svelte-kit"
51
+ }
52
+ }