angular-three-theatre 4.0.0-next.115 → 4.0.0-next.118
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/README.md +134 -0
- package/fesm2022/angular-three-theatre.mjs +665 -54
- package/fesm2022/angular-three-theatre.mjs.map +1 -1
- package/package.json +4 -4
- package/types/angular-three-theatre.d.ts +734 -0
- package/index.d.ts +0 -203
|
@@ -7,23 +7,57 @@ import { Group } from 'three';
|
|
|
7
7
|
import { NgtsTransformControls } from 'angular-three-soba/gizmos';
|
|
8
8
|
import { mergeInputs } from 'ngxtension/inject-inputs';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Component that creates and manages a Theatre.js project.
|
|
12
|
+
*
|
|
13
|
+
* A Theatre.js project is the top-level container for all animation data.
|
|
14
|
+
* It contains sheets, which in turn contain sheet objects that hold animatable properties.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```html
|
|
18
|
+
* <theatre-project name="my-animation" [config]="{ state: savedState }">
|
|
19
|
+
* <ng-container sheet="scene1">
|
|
20
|
+
* <!-- sheet objects here -->
|
|
21
|
+
* </ng-container>
|
|
22
|
+
* </theatre-project>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
10
25
|
class TheatreProject {
|
|
11
26
|
constructor() {
|
|
27
|
+
/**
|
|
28
|
+
* The name of the Theatre.js project.
|
|
29
|
+
* This name is used to identify the project and must be unique.
|
|
30
|
+
*
|
|
31
|
+
* @default 'default-theatre-project'
|
|
32
|
+
*/
|
|
12
33
|
this.name = input('default-theatre-project', ...(ngDevMode ? [{ debugName: "name" }] : []));
|
|
34
|
+
/**
|
|
35
|
+
* Configuration options for the Theatre.js project.
|
|
36
|
+
* Can include saved state data for restoring animations.
|
|
37
|
+
*
|
|
38
|
+
* @default {}
|
|
39
|
+
*/
|
|
13
40
|
this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
41
|
+
/**
|
|
42
|
+
* Computed signal containing the Theatre.js project instance.
|
|
43
|
+
*/
|
|
14
44
|
this.project = computed(() => getProject(this.name(), this.config()), ...(ngDevMode ? [{ debugName: "project" }] : []));
|
|
45
|
+
/**
|
|
46
|
+
* Internal registry of sheets created within this project.
|
|
47
|
+
* Tracks sheet instances and their reference counts for cleanup.
|
|
48
|
+
*/
|
|
15
49
|
this.sheets = {};
|
|
16
50
|
effect(() => {
|
|
17
51
|
const project = this.project();
|
|
18
52
|
project.ready.then();
|
|
19
53
|
});
|
|
20
54
|
}
|
|
21
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
22
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "
|
|
55
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreProject, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
56
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: TheatreProject, isStandalone: true, selector: "theatre-project", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
23
57
|
<ng-content />
|
|
24
58
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
25
59
|
}
|
|
26
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreProject, decorators: [{
|
|
27
61
|
type: Component,
|
|
28
62
|
args: [{
|
|
29
63
|
selector: 'theatre-project',
|
|
@@ -32,24 +66,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
32
66
|
`,
|
|
33
67
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
34
68
|
}]
|
|
35
|
-
}], ctorParameters: () => [] });
|
|
69
|
+
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
|
|
36
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Directive that creates and manages a Theatre.js sheet within a project.
|
|
73
|
+
*
|
|
74
|
+
* A sheet is a container for sheet objects and their animations. Multiple sheets
|
|
75
|
+
* can exist within a project, allowing you to organize animations into logical groups.
|
|
76
|
+
*
|
|
77
|
+
* The directive automatically handles reference counting and cleanup when the
|
|
78
|
+
* directive is destroyed.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```html
|
|
82
|
+
* <theatre-project>
|
|
83
|
+
* <ng-container sheet="mainScene">
|
|
84
|
+
* <!-- sheet objects here -->
|
|
85
|
+
* </ng-container>
|
|
86
|
+
* </theatre-project>
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```html
|
|
91
|
+
* <!-- Using with template reference -->
|
|
92
|
+
* <ng-container sheet="mySheet" #sheetRef="sheet">
|
|
93
|
+
* {{ sheetRef.sheet().sequence.position }}
|
|
94
|
+
* </ng-container>
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
37
97
|
let TheatreSheet$1 = class TheatreSheet {
|
|
38
98
|
constructor() {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}]));
|
|
99
|
+
/**
|
|
100
|
+
* The name of the sheet within the project.
|
|
101
|
+
* This name must be unique within the parent project.
|
|
102
|
+
*
|
|
103
|
+
* @default 'default-theatre-sheet'
|
|
104
|
+
*/
|
|
105
|
+
this.name = input('default-theatre-sheet', { ...(ngDevMode ? { debugName: "name" } : {}), transform: (value) => {
|
|
106
|
+
if (value === '')
|
|
107
|
+
return 'default-theatre-sheet';
|
|
108
|
+
return value;
|
|
109
|
+
},
|
|
110
|
+
alias: 'sheet' });
|
|
52
111
|
this.project = inject(TheatreProject);
|
|
112
|
+
/**
|
|
113
|
+
* Computed signal containing the Theatre.js sheet instance.
|
|
114
|
+
* Returns an existing sheet if one with the same name already exists,
|
|
115
|
+
* otherwise creates a new sheet.
|
|
116
|
+
*/
|
|
53
117
|
this.sheet = computed(() => {
|
|
54
118
|
const name = this.name();
|
|
55
119
|
const existing = this.project.sheets[name] || [];
|
|
@@ -73,22 +137,99 @@ let TheatreSheet$1 = class TheatreSheet {
|
|
|
73
137
|
}
|
|
74
138
|
});
|
|
75
139
|
}
|
|
76
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
77
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
140
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
141
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreSheet, isStandalone: true, selector: "[sheet]", inputs: { name: { classPropertyName: "name", publicName: "sheet", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["sheet"], ngImport: i0 }); }
|
|
78
142
|
};
|
|
79
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
143
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheet$1, decorators: [{
|
|
80
144
|
type: Directive,
|
|
81
145
|
args: [{ selector: '[sheet]', exportAs: 'sheet' }]
|
|
82
|
-
}], ctorParameters: () => [] });
|
|
146
|
+
}], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheet", required: false }] }] } });
|
|
83
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Injection token for accessing the Theatre.js Studio instance.
|
|
150
|
+
*
|
|
151
|
+
* The studio provides a visual editor for creating and editing animations.
|
|
152
|
+
* This token is provided by the TheatreStudio directive and can be injected
|
|
153
|
+
* into child components.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* import { THEATRE_STUDIO } from 'angular-three-theatre';
|
|
158
|
+
*
|
|
159
|
+
* @Component({...})
|
|
160
|
+
* export class MyComponent {
|
|
161
|
+
* private studio = inject(THEATRE_STUDIO, { optional: true });
|
|
162
|
+
*
|
|
163
|
+
* selectObject() {
|
|
164
|
+
* this.studio()?.setSelection([mySheetObject]);
|
|
165
|
+
* }
|
|
166
|
+
* }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
84
169
|
const THEATRE_STUDIO = new InjectionToken('Theatre Studio');
|
|
85
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Directive that creates a Theatre.js sheet object for animating properties.
|
|
173
|
+
*
|
|
174
|
+
* A sheet object is a container for animatable properties within a sheet.
|
|
175
|
+
* This directive must be applied to an `ng-template` element and provides
|
|
176
|
+
* a structural context with access to the sheet object and its values.
|
|
177
|
+
*
|
|
178
|
+
* The template context includes:
|
|
179
|
+
* - `sheetObject`: The Theatre.js sheet object instance (read-only signal)
|
|
180
|
+
* - `values`: Current values of all animated properties (read-only signal)
|
|
181
|
+
* - `select()`: Method to select this object in Theatre.js Studio
|
|
182
|
+
* - `deselect()`: Method to deselect this object in Theatre.js Studio
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```html
|
|
186
|
+
* <ng-template sheetObject="cube" [sheetObjectProps]="{ opacity: 1 }" let-values="values">
|
|
187
|
+
* <ngt-mesh>
|
|
188
|
+
* <ngt-mesh-standard-material [opacity]="values().opacity" />
|
|
189
|
+
* </ngt-mesh>
|
|
190
|
+
* </ng-template>
|
|
191
|
+
* ```
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```html
|
|
195
|
+
* <!-- With selection support -->
|
|
196
|
+
* <ng-template
|
|
197
|
+
* sheetObject="cube"
|
|
198
|
+
* [(sheetObjectSelected)]="isSelected"
|
|
199
|
+
* let-select="select"
|
|
200
|
+
* let-deselect="deselect"
|
|
201
|
+
* >
|
|
202
|
+
* <ngt-mesh (click)="select()" />
|
|
203
|
+
* </ng-template>
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
86
206
|
let TheatreSheetObject$1 = class TheatreSheetObject {
|
|
87
207
|
constructor() {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Unique key identifying this sheet object within its parent sheet.
|
|
210
|
+
* This key is used by Theatre.js to track and persist animation data.
|
|
211
|
+
*/
|
|
212
|
+
this.key = input.required({ ...(ngDevMode ? { debugName: "key" } : {}), alias: 'sheetObject' });
|
|
213
|
+
/**
|
|
214
|
+
* Initial properties and their default values for this sheet object.
|
|
215
|
+
* These properties will be animatable in Theatre.js Studio.
|
|
216
|
+
*
|
|
217
|
+
* @default {}
|
|
218
|
+
*/
|
|
219
|
+
this.props = input({}, { ...(ngDevMode ? { debugName: "props" } : {}), alias: 'sheetObjectProps' });
|
|
220
|
+
/**
|
|
221
|
+
* Whether to detach (remove) the sheet object when this directive is destroyed.
|
|
222
|
+
* When true, the animation data for this object will be removed from the sheet.
|
|
223
|
+
*
|
|
224
|
+
* @default false
|
|
225
|
+
*/
|
|
226
|
+
this.detach = input(false, { ...(ngDevMode ? { debugName: "detach" } : {}), transform: booleanAttribute, alias: 'sheetObjectDetach' });
|
|
227
|
+
/**
|
|
228
|
+
* Two-way bindable signal indicating whether this object is selected in Theatre.js Studio.
|
|
229
|
+
*
|
|
230
|
+
* @default false
|
|
231
|
+
*/
|
|
232
|
+
this.selected = model(false, { ...(ngDevMode ? { debugName: "selected" } : {}), alias: 'sheetObjectSelected' });
|
|
92
233
|
this.templateRef = inject(TemplateRef);
|
|
93
234
|
this.vcr = inject(ViewContainerRef);
|
|
94
235
|
this.sheet = inject(TheatreSheet$1);
|
|
@@ -98,8 +239,16 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
|
|
|
98
239
|
const sheet = this.sheet.sheet();
|
|
99
240
|
return sheet.object(this.key(), untracked(this.props), { reconfigure: true });
|
|
100
241
|
}, ...(ngDevMode ? [{ debugName: "originalSheetObject" }] : []));
|
|
101
|
-
|
|
102
|
-
|
|
242
|
+
/**
|
|
243
|
+
* Signal containing the Theatre.js sheet object instance.
|
|
244
|
+
* This is a linked signal that updates when the sheet or key changes.
|
|
245
|
+
*/
|
|
246
|
+
this.sheetObject = linkedSignal(this.originalSheetObject, ...(ngDevMode ? [{ debugName: "sheetObject" }] : []));
|
|
247
|
+
/**
|
|
248
|
+
* Signal containing the current values of all animated properties.
|
|
249
|
+
* Updates automatically when Theatre.js values change.
|
|
250
|
+
*/
|
|
251
|
+
this.values = linkedSignal(() => this.sheetObject().value, ...(ngDevMode ? [{ debugName: "values" }] : []));
|
|
103
252
|
this.detached = false;
|
|
104
253
|
this.aggregatedProps = {};
|
|
105
254
|
effect(() => {
|
|
@@ -142,6 +291,10 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
|
|
|
142
291
|
}
|
|
143
292
|
});
|
|
144
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Updates the sheet object with the current aggregated props.
|
|
296
|
+
* Detaches the existing object and creates a new one with reconfigured properties.
|
|
297
|
+
*/
|
|
145
298
|
update() {
|
|
146
299
|
if (this.detached)
|
|
147
300
|
return;
|
|
@@ -149,10 +302,22 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
|
|
|
149
302
|
sheet.detachObject(key);
|
|
150
303
|
this.sheetObject.set(sheet.object(key, this.aggregatedProps, { reconfigure: true }));
|
|
151
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Adds new properties to the sheet object.
|
|
307
|
+
* The properties are merged with existing properties and the object is reconfigured.
|
|
308
|
+
*
|
|
309
|
+
* @param props - Properties to add to the sheet object
|
|
310
|
+
*/
|
|
152
311
|
addProps(props) {
|
|
153
312
|
this.aggregatedProps = { ...this.aggregatedProps, ...props };
|
|
154
313
|
this.update();
|
|
155
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* Removes properties from the sheet object.
|
|
317
|
+
* If all properties are removed and `detach` is true, the object is detached from the sheet.
|
|
318
|
+
*
|
|
319
|
+
* @param props - Array of property names to remove
|
|
320
|
+
*/
|
|
156
321
|
removeProps(props) {
|
|
157
322
|
const [detach, sheet, key] = [untracked(this.detach), untracked(this.sheet.sheet), untracked(this.key)];
|
|
158
323
|
// remove props from sheet object
|
|
@@ -171,12 +336,20 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
|
|
|
171
336
|
this.update();
|
|
172
337
|
}
|
|
173
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Selects this sheet object in Theatre.js Studio.
|
|
341
|
+
* Only works when the studio is available.
|
|
342
|
+
*/
|
|
174
343
|
select() {
|
|
175
344
|
const studio = this.studio?.();
|
|
176
345
|
if (!studio)
|
|
177
346
|
return;
|
|
178
347
|
studio.setSelection([this.sheetObject()]);
|
|
179
348
|
}
|
|
349
|
+
/**
|
|
350
|
+
* Deselects this sheet object in Theatre.js Studio.
|
|
351
|
+
* Only deselects if this object is currently selected.
|
|
352
|
+
*/
|
|
180
353
|
deselect() {
|
|
181
354
|
const studio = this.studio?.();
|
|
182
355
|
if (!studio)
|
|
@@ -185,22 +358,64 @@ let TheatreSheetObject$1 = class TheatreSheetObject {
|
|
|
185
358
|
studio.setSelection([]);
|
|
186
359
|
}
|
|
187
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Type guard for the template context.
|
|
363
|
+
* Provides type safety for the template variables exposed by this directive.
|
|
364
|
+
*
|
|
365
|
+
* @param _ - The directive instance
|
|
366
|
+
* @param ctx - The template context
|
|
367
|
+
* @returns Type predicate for the template context
|
|
368
|
+
*/
|
|
188
369
|
static ngTemplateContextGuard(_, ctx) {
|
|
189
370
|
return true;
|
|
190
371
|
}
|
|
191
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
192
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
372
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObject, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
373
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreSheetObject, isStandalone: true, selector: "ng-template[sheetObject]", inputs: { key: { classPropertyName: "key", publicName: "sheetObject", isSignal: true, isRequired: true, transformFunction: null }, props: { classPropertyName: "props", publicName: "sheetObjectProps", isSignal: true, isRequired: false, transformFunction: null }, detach: { classPropertyName: "detach", publicName: "sheetObjectDetach", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "sheetObjectSelected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "sheetObjectSelectedChange" }, exportAs: ["sheetObject"], ngImport: i0 }); }
|
|
193
374
|
};
|
|
194
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
375
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObject$1, decorators: [{
|
|
195
376
|
type: Directive,
|
|
196
377
|
args: [{ selector: 'ng-template[sheetObject]', exportAs: 'sheetObject' }]
|
|
197
|
-
}], ctorParameters: () => [] });
|
|
378
|
+
}], ctorParameters: () => [], propDecorators: { key: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetObject", required: true }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetObjectProps", required: false }] }], detach: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetObjectDetach", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetObjectSelected", required: false }] }, { type: i0.Output, args: ["sheetObjectSelectedChange"] }] } });
|
|
198
379
|
|
|
380
|
+
/**
|
|
381
|
+
* Factory function for creating a Theatre.js transformer.
|
|
382
|
+
*
|
|
383
|
+
* This is a convenience function that provides type inference for transformer creation.
|
|
384
|
+
*
|
|
385
|
+
* @param transformer - The transformer configuration object
|
|
386
|
+
* @returns The same transformer object (identity function with type inference)
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* ```typescript
|
|
390
|
+
* import { createTransformer } from 'angular-three-theatre';
|
|
391
|
+
* import { types } from '@theatre/core';
|
|
392
|
+
*
|
|
393
|
+
* export const percentage = createTransformer({
|
|
394
|
+
* transform: (value) => types.number(value * 100, { range: [0, 100] }),
|
|
395
|
+
* apply: (target, property, value) => { target[property] = value / 100; }
|
|
396
|
+
* });
|
|
397
|
+
* ```
|
|
398
|
+
*/
|
|
199
399
|
function createTransformer(transformer) {
|
|
200
400
|
return transformer;
|
|
201
401
|
}
|
|
202
402
|
|
|
203
403
|
const _color = new THREE.Color();
|
|
404
|
+
/**
|
|
405
|
+
* Transformer for Three.js Color objects.
|
|
406
|
+
*
|
|
407
|
+
* Converts Three.js Color to Theatre.js RGBA format for the color picker UI.
|
|
408
|
+
* Uses sRGB color space for accurate color representation.
|
|
409
|
+
*
|
|
410
|
+
* @example
|
|
411
|
+
* ```typescript
|
|
412
|
+
* import { color } from 'angular-three-theatre';
|
|
413
|
+
*
|
|
414
|
+
* // Used automatically for Color properties, or manually:
|
|
415
|
+
* [sync]="material"
|
|
416
|
+
* [syncProps]="[['emissive', { transformer: color }]]"
|
|
417
|
+
* ```
|
|
418
|
+
*/
|
|
204
419
|
const color = createTransformer({
|
|
205
420
|
transform(value) {
|
|
206
421
|
value.getRGB(_color, THREE.SRGBColorSpace);
|
|
@@ -211,6 +426,21 @@ const color = createTransformer({
|
|
|
211
426
|
},
|
|
212
427
|
});
|
|
213
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Transformer for radian values that displays as degrees in the UI.
|
|
431
|
+
*
|
|
432
|
+
* Converts between radians (used by Three.js) and degrees (more intuitive for users).
|
|
433
|
+
* Used automatically for rotation.x, rotation.y, and rotation.z properties.
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* ```typescript
|
|
437
|
+
* import { degrees } from 'angular-three-theatre';
|
|
438
|
+
*
|
|
439
|
+
* // Used automatically for rotation components, or manually:
|
|
440
|
+
* [sync]="camera"
|
|
441
|
+
* [syncProps]="[['fov', { transformer: degrees }]]"
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
214
444
|
const degrees = createTransformer({
|
|
215
445
|
transform(target) {
|
|
216
446
|
return types.number(target * THREE.MathUtils.RAD2DEG);
|
|
@@ -220,6 +450,23 @@ const degrees = createTransformer({
|
|
|
220
450
|
},
|
|
221
451
|
});
|
|
222
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Transformer for Three.js Euler rotation objects.
|
|
455
|
+
*
|
|
456
|
+
* Converts Euler angles from radians to degrees for display in Theatre.js Studio.
|
|
457
|
+
* Creates a compound property with x, y, z components shown in degrees.
|
|
458
|
+
*
|
|
459
|
+
* Used automatically for properties where `isEuler` is true (e.g., Object3D.rotation).
|
|
460
|
+
*
|
|
461
|
+
* @example
|
|
462
|
+
* ```typescript
|
|
463
|
+
* import { euler } from 'angular-three-theatre';
|
|
464
|
+
*
|
|
465
|
+
* // Used automatically for Euler properties, or manually:
|
|
466
|
+
* [sync]="mesh"
|
|
467
|
+
* [syncProps]="[['rotation', { transformer: euler }]]"
|
|
468
|
+
* ```
|
|
469
|
+
*/
|
|
223
470
|
const euler = createTransformer({
|
|
224
471
|
transform(value) {
|
|
225
472
|
return types.compound({
|
|
@@ -235,6 +482,26 @@ const euler = createTransformer({
|
|
|
235
482
|
},
|
|
236
483
|
});
|
|
237
484
|
|
|
485
|
+
/**
|
|
486
|
+
* Generic fallback transformer that handles common JavaScript types.
|
|
487
|
+
*
|
|
488
|
+
* Automatically detects the value type and applies the appropriate Theatre.js type:
|
|
489
|
+
* - Numbers → `types.number` (Infinity converted to MAX_VALUE)
|
|
490
|
+
* - Strings → `types.string`
|
|
491
|
+
* - Booleans → `types.boolean`
|
|
492
|
+
* - Objects → `types.compound` (spreads properties)
|
|
493
|
+
*
|
|
494
|
+
* Used as the default transformer when no specific transformer matches.
|
|
495
|
+
*
|
|
496
|
+
* @example
|
|
497
|
+
* ```typescript
|
|
498
|
+
* import { generic } from 'angular-three-theatre';
|
|
499
|
+
*
|
|
500
|
+
* // Explicitly use generic transformer:
|
|
501
|
+
* [sync]="mesh"
|
|
502
|
+
* [syncProps]="[['customProperty', { transformer: generic }]]"
|
|
503
|
+
* ```
|
|
504
|
+
*/
|
|
238
505
|
const generic = createTransformer({
|
|
239
506
|
transform(value) {
|
|
240
507
|
if (typeof value === 'number') {
|
|
@@ -258,6 +525,22 @@ const generic = createTransformer({
|
|
|
258
525
|
},
|
|
259
526
|
});
|
|
260
527
|
|
|
528
|
+
/**
|
|
529
|
+
* Transformer for normalized values in the 0-1 range.
|
|
530
|
+
*
|
|
531
|
+
* Creates a number input with a slider constrained to the 0-1 range.
|
|
532
|
+
* Used automatically for material properties like opacity, roughness,
|
|
533
|
+
* metalness, transmission, and color components (r, g, b).
|
|
534
|
+
*
|
|
535
|
+
* @example
|
|
536
|
+
* ```typescript
|
|
537
|
+
* import { normalized } from 'angular-three-theatre';
|
|
538
|
+
*
|
|
539
|
+
* // Used automatically for common properties, or manually:
|
|
540
|
+
* [sync]="material"
|
|
541
|
+
* [syncProps]="[['customNormalizedValue', { transformer: normalized }]]"
|
|
542
|
+
* ```
|
|
543
|
+
*/
|
|
261
544
|
const normalized = createTransformer({
|
|
262
545
|
transform(value) {
|
|
263
546
|
return types.number(value, { range: [0, 1] });
|
|
@@ -267,6 +550,23 @@ const normalized = createTransformer({
|
|
|
267
550
|
},
|
|
268
551
|
});
|
|
269
552
|
|
|
553
|
+
/**
|
|
554
|
+
* Transformer for Three.js material side property.
|
|
555
|
+
*
|
|
556
|
+
* Converts between Three.js side constants (FrontSide, BackSide, DoubleSide)
|
|
557
|
+
* and a switch UI in Theatre.js Studio with human-readable labels.
|
|
558
|
+
*
|
|
559
|
+
* Used automatically for the `side` property on materials.
|
|
560
|
+
*
|
|
561
|
+
* @example
|
|
562
|
+
* ```typescript
|
|
563
|
+
* import { side } from 'angular-three-theatre';
|
|
564
|
+
*
|
|
565
|
+
* // Used automatically for material.side, or manually:
|
|
566
|
+
* [sync]="material"
|
|
567
|
+
* [syncProps]="[['side', { transformer: side }]]"
|
|
568
|
+
* ```
|
|
569
|
+
*/
|
|
270
570
|
const side = createTransformer({
|
|
271
571
|
transform(value) {
|
|
272
572
|
// TODO: fix this type
|
|
@@ -277,9 +577,42 @@ const side = createTransformer({
|
|
|
277
577
|
},
|
|
278
578
|
});
|
|
279
579
|
|
|
580
|
+
/**
|
|
581
|
+
* Checks if a property path matches a pattern exactly or ends with the pattern.
|
|
582
|
+
*
|
|
583
|
+
* @param fullPropertyPath - The full property path (e.g., 'material.opacity')
|
|
584
|
+
* @param pattern - The pattern to match (e.g., 'opacity')
|
|
585
|
+
* @returns True if the path matches or ends with the pattern
|
|
586
|
+
*/
|
|
280
587
|
function isFullOrEndingPattern(fullPropertyPath, pattern) {
|
|
281
588
|
return fullPropertyPath.endsWith(`.${pattern}`) || fullPropertyPath === pattern;
|
|
282
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Determines the appropriate transformer for a Three.js property based on its type and path.
|
|
592
|
+
*
|
|
593
|
+
* This function automatically selects the best transformer for common Three.js properties:
|
|
594
|
+
* - Euler rotations → `euler` transformer (degrees display)
|
|
595
|
+
* - Color values → `color` transformer (RGBA picker)
|
|
596
|
+
* - Rotation components (x, y, z) → `degrees` transformer
|
|
597
|
+
* - Color components (r, g, b) → `normalized` transformer (0-1 range)
|
|
598
|
+
* - Material properties (opacity, roughness, metalness, transmission) → `normalized` transformer
|
|
599
|
+
* - Side property → `side` transformer (Front/Back/Double switch)
|
|
600
|
+
* - All others → `generic` transformer
|
|
601
|
+
*
|
|
602
|
+
* @param target - The parent object containing the property
|
|
603
|
+
* @param path - The property name on the target
|
|
604
|
+
* @param fullPropertyPath - The full dot-notation path to the property
|
|
605
|
+
* @returns The appropriate transformer for the property
|
|
606
|
+
*
|
|
607
|
+
* @example
|
|
608
|
+
* ```typescript
|
|
609
|
+
* import { getDefaultTransformer } from 'angular-three-theatre';
|
|
610
|
+
*
|
|
611
|
+
* const mesh = new THREE.Mesh();
|
|
612
|
+
* const transformer = getDefaultTransformer(mesh, 'rotation', 'rotation');
|
|
613
|
+
* // Returns the euler transformer
|
|
614
|
+
* ```
|
|
615
|
+
*/
|
|
283
616
|
function getDefaultTransformer(target, path, fullPropertyPath) {
|
|
284
617
|
const property = target[path];
|
|
285
618
|
if (property.isEuler)
|
|
@@ -312,13 +645,67 @@ function getDefaultTransformer(target, path, fullPropertyPath) {
|
|
|
312
645
|
}
|
|
313
646
|
|
|
314
647
|
const updateProjectionMatrixKeys = ['fov', 'near', 'far', 'zoom', 'left', 'right', 'top', 'bottom', 'aspect'];
|
|
648
|
+
/**
|
|
649
|
+
* Directive that synchronizes Three.js object properties with Theatre.js animations.
|
|
650
|
+
*
|
|
651
|
+
* This directive allows you to expose specific properties of a Three.js object
|
|
652
|
+
* to Theatre.js for animation. It automatically handles property transformation
|
|
653
|
+
* (e.g., converting Euler angles to degrees for the UI).
|
|
654
|
+
*
|
|
655
|
+
* Must be used within a `TheatreSheetObject` context.
|
|
656
|
+
*
|
|
657
|
+
* @example
|
|
658
|
+
* ```html
|
|
659
|
+
* <ng-template sheetObject="myMaterial">
|
|
660
|
+
* <ngt-mesh-standard-material
|
|
661
|
+
* [sync]="material"
|
|
662
|
+
* [syncProps]="['opacity', 'roughness', 'metalness']"
|
|
663
|
+
* #material
|
|
664
|
+
* />
|
|
665
|
+
* </ng-template>
|
|
666
|
+
* ```
|
|
667
|
+
*
|
|
668
|
+
* @example
|
|
669
|
+
* ```html
|
|
670
|
+
* <!-- With custom property mapping -->
|
|
671
|
+
* <ng-template sheetObject="myLight">
|
|
672
|
+
* <ngt-point-light
|
|
673
|
+
* [sync]="light"
|
|
674
|
+
* [syncProps]="[
|
|
675
|
+
* ['intensity', { label: 'Light Intensity', key: 'lightIntensity' }],
|
|
676
|
+
* 'color'
|
|
677
|
+
* ]"
|
|
678
|
+
* #light
|
|
679
|
+
* />
|
|
680
|
+
* </ng-template>
|
|
681
|
+
* ```
|
|
682
|
+
*
|
|
683
|
+
* @typeParam TObject - The type of the Three.js object being synchronized
|
|
684
|
+
*/
|
|
315
685
|
class TheatreSheetObjectSync {
|
|
316
686
|
constructor() {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
687
|
+
/**
|
|
688
|
+
* The Three.js object to synchronize with Theatre.js.
|
|
689
|
+
* Can be an object reference, ElementRef, or a function returning either.
|
|
690
|
+
*/
|
|
691
|
+
this.parent = input.required({ ...(ngDevMode ? { debugName: "parent" } : {}), alias: 'sync' });
|
|
692
|
+
/**
|
|
693
|
+
* Array of property paths to synchronize with Theatre.js.
|
|
694
|
+
*
|
|
695
|
+
* Each item can be:
|
|
696
|
+
* - A string property path (e.g., 'opacity', 'position.x')
|
|
697
|
+
* - A tuple of [propertyPath, keyOrOptions] where options can include:
|
|
698
|
+
* - `label`: Display label in Theatre.js Studio
|
|
699
|
+
* - `key`: Unique key for the property in Theatre.js
|
|
700
|
+
* - `transformer`: Custom transformer for the property value
|
|
701
|
+
*
|
|
702
|
+
* @default []
|
|
703
|
+
*/
|
|
704
|
+
this.props = input([], { ...(ngDevMode ? { debugName: "props" } : {}), alias: 'syncProps' });
|
|
321
705
|
this.theatreSheetObject = inject(TheatreSheetObject$1);
|
|
706
|
+
/**
|
|
707
|
+
* Computed signal containing the Theatre.js sheet object instance.
|
|
708
|
+
*/
|
|
322
709
|
this.sheetObject = computed(() => this.theatreSheetObject.sheetObject(), ...(ngDevMode ? [{ debugName: "sheetObject" }] : []));
|
|
323
710
|
this.studio = inject(THEATRE_STUDIO, { optional: true });
|
|
324
711
|
this.parentRef = computed(() => {
|
|
@@ -398,6 +785,13 @@ class TheatreSheetObjectSync {
|
|
|
398
785
|
this.theatreSheetObject.removeProps(Object.keys(this.propsMapping));
|
|
399
786
|
});
|
|
400
787
|
}
|
|
788
|
+
/**
|
|
789
|
+
* Captures the current values of all synchronized properties from the Three.js object
|
|
790
|
+
* and commits them to Theatre.js.
|
|
791
|
+
*
|
|
792
|
+
* This is useful for "baking" the current state of the Three.js object into the
|
|
793
|
+
* Theatre.js animation. Requires Theatre.js Studio to be available.
|
|
794
|
+
*/
|
|
401
795
|
capture() {
|
|
402
796
|
const studio = this.studio?.();
|
|
403
797
|
if (!studio)
|
|
@@ -423,6 +817,12 @@ class TheatreSheetObjectSync {
|
|
|
423
817
|
});
|
|
424
818
|
scrub.commit();
|
|
425
819
|
}
|
|
820
|
+
/**
|
|
821
|
+
* Converts a property path (e.g., 'position.x') to a safe alphanumeric key.
|
|
822
|
+
*
|
|
823
|
+
* @param propPath - The property path to convert
|
|
824
|
+
* @returns A safe alphanumeric key string
|
|
825
|
+
*/
|
|
426
826
|
resolvePropertyPath(propPath) {
|
|
427
827
|
return (propPath
|
|
428
828
|
// make the label alphanumeric by first removing dots (fundamental feature for pierced props)
|
|
@@ -432,14 +832,48 @@ class TheatreSheetObjectSync {
|
|
|
432
832
|
// convert to safe alphanumeric characters without dashes
|
|
433
833
|
.replace(/[^a-zA-Z0-9]/g, ''));
|
|
434
834
|
}
|
|
435
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
436
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
835
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObjectSync, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
836
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreSheetObjectSync, isStandalone: true, selector: "[sync]", inputs: { parent: { classPropertyName: "parent", publicName: "sync", isSignal: true, isRequired: true, transformFunction: null }, props: { classPropertyName: "props", publicName: "syncProps", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["sync"], ngImport: i0 }); }
|
|
437
837
|
}
|
|
438
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
838
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObjectSync, decorators: [{
|
|
439
839
|
type: Directive,
|
|
440
840
|
args: [{ selector: '[sync]', exportAs: 'sync' }]
|
|
441
|
-
}], ctorParameters: () => [] });
|
|
841
|
+
}], ctorParameters: () => [], propDecorators: { parent: [{ type: i0.Input, args: [{ isSignal: true, alias: "sync", required: true }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "syncProps", required: false }] }] } });
|
|
442
842
|
|
|
843
|
+
/**
|
|
844
|
+
* Component that provides transform controls for animating position, rotation, and scale
|
|
845
|
+
* of child Three.js objects via Theatre.js.
|
|
846
|
+
*
|
|
847
|
+
* When the sheet object is selected in Theatre.js Studio, transform controls appear
|
|
848
|
+
* allowing direct manipulation of the object's transform. Changes are captured and
|
|
849
|
+
* committed to Theatre.js.
|
|
850
|
+
*
|
|
851
|
+
* Must be used within a `TheatreSheetObject` context.
|
|
852
|
+
*
|
|
853
|
+
* @example
|
|
854
|
+
* ```html
|
|
855
|
+
* <ng-template sheetObject="myCube">
|
|
856
|
+
* <theatre-transform>
|
|
857
|
+
* <ngt-mesh>
|
|
858
|
+
* <ngt-box-geometry />
|
|
859
|
+
* <ngt-mesh-standard-material />
|
|
860
|
+
* </ngt-mesh>
|
|
861
|
+
* </theatre-transform>
|
|
862
|
+
* </ng-template>
|
|
863
|
+
* ```
|
|
864
|
+
*
|
|
865
|
+
* @example
|
|
866
|
+
* ```html
|
|
867
|
+
* <!-- With custom key and options -->
|
|
868
|
+
* <ng-template sheetObject="scene">
|
|
869
|
+
* <theatre-transform key="cubeTransform" label="Cube" [options]="{ mode: 'rotate' }">
|
|
870
|
+
* <ngt-mesh />
|
|
871
|
+
* </theatre-transform>
|
|
872
|
+
* </ng-template>
|
|
873
|
+
* ```
|
|
874
|
+
*
|
|
875
|
+
* @typeParam TLabel - The type of the label string
|
|
876
|
+
*/
|
|
443
877
|
class TheatreSheetObjectTransform {
|
|
444
878
|
onMouseDown() {
|
|
445
879
|
if (!this.studio)
|
|
@@ -474,12 +908,31 @@ class TheatreSheetObjectTransform {
|
|
|
474
908
|
});
|
|
475
909
|
}
|
|
476
910
|
constructor() {
|
|
911
|
+
/**
|
|
912
|
+
* Display label for the transform properties in Theatre.js Studio.
|
|
913
|
+
*/
|
|
477
914
|
this.label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : []));
|
|
915
|
+
/**
|
|
916
|
+
* Unique key for grouping the transform properties in Theatre.js.
|
|
917
|
+
* If provided, position/rotation/scale will be nested under this key.
|
|
918
|
+
*/
|
|
478
919
|
this.key = input(...(ngDevMode ? [undefined, { debugName: "key" }] : []));
|
|
920
|
+
/**
|
|
921
|
+
* Options for the transform controls gizmo.
|
|
922
|
+
* Allows configuring the transform mode, snap values, and coordinate space.
|
|
923
|
+
*
|
|
924
|
+
* @default {}
|
|
925
|
+
*/
|
|
479
926
|
this.options = input({}, ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
927
|
+
/**
|
|
928
|
+
* Reference to the Three.js Group element that wraps the transformed content.
|
|
929
|
+
*/
|
|
480
930
|
this.groupRef = viewChild.required('group');
|
|
481
931
|
this.controlsRef = viewChild(NgtsTransformControls, ...(ngDevMode ? [{ debugName: "controlsRef" }] : []));
|
|
482
932
|
this.theatreSheetObject = inject(TheatreSheetObject$1);
|
|
933
|
+
/**
|
|
934
|
+
* Computed signal containing the Theatre.js sheet object instance.
|
|
935
|
+
*/
|
|
483
936
|
this.sheetObject = computed(() => this.theatreSheetObject.sheetObject(), ...(ngDevMode ? [{ debugName: "sheetObject" }] : []));
|
|
484
937
|
this.studio = inject(THEATRE_STUDIO, { optional: true });
|
|
485
938
|
this.selected = this.theatreSheetObject.selected.asReadonly();
|
|
@@ -559,8 +1012,8 @@ class TheatreSheetObjectTransform {
|
|
|
559
1012
|
this.theatreSheetObject.addProps({ position, rotation, scale });
|
|
560
1013
|
}
|
|
561
1014
|
}
|
|
562
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
563
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1015
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObjectTransform, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1016
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: TheatreSheetObjectTransform, isStandalone: true, selector: "theatre-transform", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "groupRef", first: true, predicate: ["group"], descendants: true, isSignal: true }, { propertyName: "controlsRef", first: true, predicate: NgtsTransformControls, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
564
1017
|
@if (selected()) {
|
|
565
1018
|
<ngts-transform-controls [object]="$any(group)" [options]="options()" />
|
|
566
1019
|
}
|
|
@@ -570,7 +1023,7 @@ class TheatreSheetObjectTransform {
|
|
|
570
1023
|
</ngt-group>
|
|
571
1024
|
`, isInline: true, dependencies: [{ kind: "component", type: NgtsTransformControls, selector: "ngts-transform-controls", inputs: ["object", "options"], outputs: ["change", "mouseDown", "mouseUp", "objectChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
572
1025
|
}
|
|
573
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1026
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSheetObjectTransform, decorators: [{
|
|
574
1027
|
type: Component,
|
|
575
1028
|
args: [{
|
|
576
1029
|
selector: 'theatre-transform',
|
|
@@ -587,14 +1040,77 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
587
1040
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
588
1041
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
589
1042
|
}]
|
|
590
|
-
}], ctorParameters: () => [] });
|
|
1043
|
+
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], groupRef: [{ type: i0.ViewChild, args: ['group', { isSignal: true }] }], controlsRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => NgtsTransformControls), { isSignal: true }] }] } });
|
|
591
1044
|
|
|
1045
|
+
/**
|
|
1046
|
+
* Combined array of sheet object directives for convenient importing.
|
|
1047
|
+
*
|
|
1048
|
+
* Includes:
|
|
1049
|
+
* - `TheatreSheetObject` - Base directive for creating sheet objects
|
|
1050
|
+
* - `TheatreSheetObjectTransform` - Component for animating transform properties
|
|
1051
|
+
* - `TheatreSheetObjectSync` - Directive for syncing arbitrary object properties
|
|
1052
|
+
*
|
|
1053
|
+
* @example
|
|
1054
|
+
* ```typescript
|
|
1055
|
+
* import { TheatreSheetObject } from 'angular-three-theatre';
|
|
1056
|
+
*
|
|
1057
|
+
* @Component({
|
|
1058
|
+
* imports: [TheatreSheetObject],
|
|
1059
|
+
* template: `
|
|
1060
|
+
* <ng-template sheetObject="myObject">
|
|
1061
|
+
* <theatre-transform>
|
|
1062
|
+
* <ngt-mesh />
|
|
1063
|
+
* </theatre-transform>
|
|
1064
|
+
* </ng-template>
|
|
1065
|
+
* `
|
|
1066
|
+
* })
|
|
1067
|
+
* export class MyComponent {}
|
|
1068
|
+
* ```
|
|
1069
|
+
*/
|
|
592
1070
|
const TheatreSheetObject = [TheatreSheetObject$1, TheatreSheetObjectTransform, TheatreSheetObjectSync];
|
|
593
1071
|
|
|
1072
|
+
/**
|
|
1073
|
+
* Directive that initializes and manages the Theatre.js Studio.
|
|
1074
|
+
*
|
|
1075
|
+
* Theatre.js Studio is a visual editor that allows you to create and edit
|
|
1076
|
+
* animations directly in the browser. The studio UI is dynamically imported
|
|
1077
|
+
* to avoid including it in production builds.
|
|
1078
|
+
*
|
|
1079
|
+
* This directive must be applied to a `theatre-project` element and provides
|
|
1080
|
+
* the studio instance via the `THEATRE_STUDIO` injection token.
|
|
1081
|
+
*
|
|
1082
|
+
* @example
|
|
1083
|
+
* ```html
|
|
1084
|
+
* <!-- Enable studio (default) -->
|
|
1085
|
+
* <theatre-project studio>
|
|
1086
|
+
* <ng-container sheet="scene">...</ng-container>
|
|
1087
|
+
* </theatre-project>
|
|
1088
|
+
*
|
|
1089
|
+
* <!-- Conditionally enable/disable studio -->
|
|
1090
|
+
* <theatre-project [studio]="isDevelopment">
|
|
1091
|
+
* <ng-container sheet="scene">...</ng-container>
|
|
1092
|
+
* </theatre-project>
|
|
1093
|
+
*
|
|
1094
|
+
* <!-- Disable studio -->
|
|
1095
|
+
* <theatre-project [studio]="false">
|
|
1096
|
+
* <ng-container sheet="scene">...</ng-container>
|
|
1097
|
+
* </theatre-project>
|
|
1098
|
+
* ```
|
|
1099
|
+
*/
|
|
594
1100
|
class TheatreStudio {
|
|
595
1101
|
constructor() {
|
|
596
|
-
|
|
1102
|
+
/**
|
|
1103
|
+
* Whether the studio UI should be visible.
|
|
1104
|
+
* When false, the studio UI is hidden but the studio instance remains active.
|
|
1105
|
+
*
|
|
1106
|
+
* @default true
|
|
1107
|
+
*/
|
|
1108
|
+
this.enabled = input(true, { ...(ngDevMode ? { debugName: "enabled" } : {}), alias: 'studio', transform: booleanAttribute });
|
|
597
1109
|
this.Studio = signal(null, ...(ngDevMode ? [{ debugName: "Studio" }] : []));
|
|
1110
|
+
/**
|
|
1111
|
+
* Read-only signal containing the Theatre.js Studio instance.
|
|
1112
|
+
* May be null while the studio is being loaded.
|
|
1113
|
+
*/
|
|
598
1114
|
this.studio = this.Studio.asReadonly();
|
|
599
1115
|
import('@theatre/studio').then((m) => {
|
|
600
1116
|
const Studio = 'default' in m.default ? m.default.default : m.default;
|
|
@@ -617,12 +1133,12 @@ class TheatreStudio {
|
|
|
617
1133
|
});
|
|
618
1134
|
});
|
|
619
1135
|
}
|
|
620
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
621
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
1136
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreStudio, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1137
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreStudio, isStandalone: true, selector: "theatre-project[studio]", inputs: { enabled: { classPropertyName: "enabled", publicName: "studio", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
622
1138
|
{ provide: THEATRE_STUDIO, useFactory: (studio) => studio.studio, deps: [TheatreStudio] },
|
|
623
1139
|
], exportAs: ["studio"], ngImport: i0 }); }
|
|
624
1140
|
}
|
|
625
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1141
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreStudio, decorators: [{
|
|
626
1142
|
type: Directive,
|
|
627
1143
|
args: [{
|
|
628
1144
|
selector: 'theatre-project[studio]',
|
|
@@ -631,7 +1147,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
631
1147
|
{ provide: THEATRE_STUDIO, useFactory: (studio) => studio.studio, deps: [TheatreStudio] },
|
|
632
1148
|
],
|
|
633
1149
|
}]
|
|
634
|
-
}], ctorParameters: () => [] });
|
|
1150
|
+
}], ctorParameters: () => [], propDecorators: { enabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "studio", required: false }] }] } });
|
|
635
1151
|
|
|
636
1152
|
const defaultOptions = {
|
|
637
1153
|
rate: 1,
|
|
@@ -639,12 +1155,65 @@ const defaultOptions = {
|
|
|
639
1155
|
autopause: false,
|
|
640
1156
|
delay: 0,
|
|
641
1157
|
};
|
|
1158
|
+
/**
|
|
1159
|
+
* Directive that provides control over a Theatre.js sequence.
|
|
1160
|
+
*
|
|
1161
|
+
* A sequence controls the playback of animations within a sheet. This directive
|
|
1162
|
+
* provides methods to play, pause, and reset the sequence, as well as reactive
|
|
1163
|
+
* signals for the current position, playing state, and length.
|
|
1164
|
+
*
|
|
1165
|
+
* Must be used on an element that also has the `sheet` directive.
|
|
1166
|
+
*
|
|
1167
|
+
* @example
|
|
1168
|
+
* ```html
|
|
1169
|
+
* <ng-container sheet="scene" [sequence]="{ autoplay: true, rate: 1 }" #seq="sequence">
|
|
1170
|
+
* <p>Position: {{ seq.position() }}</p>
|
|
1171
|
+
* <button (click)="seq.play()">Play</button>
|
|
1172
|
+
* <button (click)="seq.pause()">Pause</button>
|
|
1173
|
+
* </ng-container>
|
|
1174
|
+
* ```
|
|
1175
|
+
*
|
|
1176
|
+
* @example
|
|
1177
|
+
* ```html
|
|
1178
|
+
* <!-- With audio synchronization -->
|
|
1179
|
+
* <ng-container
|
|
1180
|
+
* sheet="scene"
|
|
1181
|
+
* [sequence]="{ autoplay: true }"
|
|
1182
|
+
* [sequenceAudio]="{ source: '/audio/soundtrack.mp3' }"
|
|
1183
|
+
* />
|
|
1184
|
+
* ```
|
|
1185
|
+
*/
|
|
642
1186
|
class TheatreSequence {
|
|
643
1187
|
constructor() {
|
|
644
|
-
|
|
645
|
-
|
|
1188
|
+
/**
|
|
1189
|
+
* Sequence configuration options.
|
|
1190
|
+
* Merged with default options using ngxtension's mergeInputs.
|
|
1191
|
+
*
|
|
1192
|
+
* @default { rate: 1, autoplay: false, autopause: false, delay: 0 }
|
|
1193
|
+
*/
|
|
1194
|
+
this.options = input(defaultOptions, { ...(ngDevMode ? { debugName: "options" } : {}), alias: 'sequence', transform: mergeInputs(defaultOptions) });
|
|
1195
|
+
/**
|
|
1196
|
+
* Audio options for synchronizing playback with an audio file.
|
|
1197
|
+
* When provided, the sequence will be synchronized with the audio.
|
|
1198
|
+
*/
|
|
1199
|
+
this.audioOptions = input(undefined, { ...(ngDevMode ? { debugName: "audioOptions" } : {}), alias: 'sequenceAudio' });
|
|
1200
|
+
/**
|
|
1201
|
+
* Two-way bindable signal for the current playback position in seconds.
|
|
1202
|
+
*
|
|
1203
|
+
* @default 0
|
|
1204
|
+
*/
|
|
646
1205
|
this.position = model(0, ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
1206
|
+
/**
|
|
1207
|
+
* Two-way bindable signal indicating whether the sequence is currently playing.
|
|
1208
|
+
*
|
|
1209
|
+
* @default false
|
|
1210
|
+
*/
|
|
647
1211
|
this.playing = model(false, ...(ngDevMode ? [{ debugName: "playing" }] : []));
|
|
1212
|
+
/**
|
|
1213
|
+
* Two-way bindable signal for the total length of the sequence in seconds.
|
|
1214
|
+
*
|
|
1215
|
+
* @default 0
|
|
1216
|
+
*/
|
|
648
1217
|
this.length = model(0, ...(ngDevMode ? [{ debugName: "length" }] : []));
|
|
649
1218
|
this.playOptions = omit(this.options, ['autoplay', 'autopause', 'delay', 'autoreset']);
|
|
650
1219
|
this.autoplay = pick(this.options, 'autoplay');
|
|
@@ -653,6 +1222,9 @@ class TheatreSequence {
|
|
|
653
1222
|
this.delay = pick(this.options, 'delay');
|
|
654
1223
|
this.project = inject(TheatreProject);
|
|
655
1224
|
this.sheet = inject(TheatreSheet$1, { host: true });
|
|
1225
|
+
/**
|
|
1226
|
+
* Computed signal containing the Theatre.js sequence instance.
|
|
1227
|
+
*/
|
|
656
1228
|
this.sequence = computed(() => this.sheet.sheet().sequence, ...(ngDevMode ? [{ debugName: "sequence" }] : []));
|
|
657
1229
|
effect((onCleanup) => {
|
|
658
1230
|
const autoplay = untracked(this.autoplay);
|
|
@@ -707,10 +1279,21 @@ class TheatreSequence {
|
|
|
707
1279
|
});
|
|
708
1280
|
});
|
|
709
1281
|
}
|
|
1282
|
+
/**
|
|
1283
|
+
* Pauses the sequence playback at the current position.
|
|
1284
|
+
*/
|
|
710
1285
|
pause() {
|
|
711
1286
|
const sequence = this.sequence();
|
|
712
1287
|
sequence.pause();
|
|
713
1288
|
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Starts or resumes sequence playback.
|
|
1291
|
+
*
|
|
1292
|
+
* Waits for the project to be ready before starting playback.
|
|
1293
|
+
* Options are merged with the configured play options.
|
|
1294
|
+
*
|
|
1295
|
+
* @param options - Optional play options that override the configured options
|
|
1296
|
+
*/
|
|
714
1297
|
play(options = {}) {
|
|
715
1298
|
const sequence = this.sequence();
|
|
716
1299
|
const project = this.project.project();
|
|
@@ -718,6 +1301,12 @@ class TheatreSequence {
|
|
|
718
1301
|
sequence.play({ ...this.playOptions(), ...options });
|
|
719
1302
|
});
|
|
720
1303
|
}
|
|
1304
|
+
/**
|
|
1305
|
+
* Resets the sequence position to 0.
|
|
1306
|
+
*
|
|
1307
|
+
* If the sequence was playing before reset, it will continue playing
|
|
1308
|
+
* from the beginning.
|
|
1309
|
+
*/
|
|
721
1310
|
reset() {
|
|
722
1311
|
const sequence = this.sequence();
|
|
723
1312
|
const isPlaying = val(sequence.pointer.playing);
|
|
@@ -725,14 +1314,36 @@ class TheatreSequence {
|
|
|
725
1314
|
if (isPlaying)
|
|
726
1315
|
this.play();
|
|
727
1316
|
}
|
|
728
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
729
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
1317
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSequence, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1318
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: TheatreSequence, isStandalone: true, selector: "[sheet][sequence]", inputs: { options: { classPropertyName: "options", publicName: "sequence", isSignal: true, isRequired: false, transformFunction: null }, audioOptions: { classPropertyName: "audioOptions", publicName: "sequenceAudio", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, playing: { classPropertyName: "playing", publicName: "playing", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { position: "positionChange", playing: "playingChange", length: "lengthChange" }, exportAs: ["sequence"], ngImport: i0 }); }
|
|
730
1319
|
}
|
|
731
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1320
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TheatreSequence, decorators: [{
|
|
732
1321
|
type: Directive,
|
|
733
1322
|
args: [{ selector: '[sheet][sequence]', exportAs: 'sequence' }]
|
|
734
|
-
}], ctorParameters: () => [] });
|
|
1323
|
+
}], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "sequence", required: false }] }], audioOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "sequenceAudio", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }, { type: i0.Output, args: ["positionChange"] }], playing: [{ type: i0.Input, args: [{ isSignal: true, alias: "playing", required: false }] }, { type: i0.Output, args: ["playingChange"] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }, { type: i0.Output, args: ["lengthChange"] }] } });
|
|
735
1324
|
|
|
1325
|
+
/**
|
|
1326
|
+
* Angular Three Theatre.js integration library
|
|
1327
|
+
*
|
|
1328
|
+
* This library provides Angular components and directives for integrating
|
|
1329
|
+
* Theatre.js animation toolkit with Angular Three applications.
|
|
1330
|
+
*
|
|
1331
|
+
* @packageDocumentation
|
|
1332
|
+
*/
|
|
1333
|
+
/**
|
|
1334
|
+
* Combined array of TheatreSheet and TheatreSequence directives for convenient importing.
|
|
1335
|
+
*
|
|
1336
|
+
* @example
|
|
1337
|
+
* ```typescript
|
|
1338
|
+
* import { TheatreSheet } from 'angular-three-theatre';
|
|
1339
|
+
*
|
|
1340
|
+
* @Component({
|
|
1341
|
+
* imports: [TheatreSheet],
|
|
1342
|
+
* template: `<ng-container sheet="mySheet" sequence />`
|
|
1343
|
+
* })
|
|
1344
|
+
* export class MyComponent {}
|
|
1345
|
+
* ```
|
|
1346
|
+
*/
|
|
736
1347
|
const TheatreSheet = [TheatreSheet$1, TheatreSequence];
|
|
737
1348
|
|
|
738
1349
|
/**
|