Skip to content

Commit ac14210

Browse files
committed
fix(theatre): exportAs; expose sheetObject on transform and sync;
1 parent 41b9428 commit ac14210

File tree

6 files changed

+83
-41
lines changed

6 files changed

+83
-41
lines changed

libs/theatre/src/index.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
export * from './lib/project';
2-
export * from './lib/sequence';
3-
export * from './lib/sheet';
42
export * from './lib/sheet-object';
53
export * from './lib/studio/studio';
4+
5+
export * from './lib/sequence';
6+
export { TheatreSheet as TheatreSheetImpl } from './lib/sheet';
7+
8+
import { TheatreSequence } from './lib/sequence';
9+
import { TheatreSheet as Impl } from './lib/sheet';
10+
11+
export const TheatreSheet = [Impl, TheatreSequence] as const;

libs/theatre/src/lib/sequence.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const defaultOptions: TheatreSequenceOptions = {
3434
delay: 0,
3535
};
3636

37-
@Directive({ selector: 'theatre-sheet[sequence]' })
37+
@Directive({ selector: 'theatre-sheet[sequence]', exportAs: 'sequence' })
3838
export class TheatreSequence {
3939
options = input(defaultOptions, { alias: 'sequence', transform: mergeInputs(defaultOptions) });
4040
audioOptions = input<AttachAudioOptions | undefined>(undefined, { alias: 'sequenceAudio' });

libs/theatre/src/lib/sheet-object/sheet-object.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ import { injectStore } from 'angular-three';
1717
import { TheatreSheet } from '../sheet';
1818
import { THEATRE_STUDIO } from '../studio/studio-token';
1919

20-
@Directive({ selector: 'ng-template[sheetObject]' })
20+
@Directive({ selector: 'ng-template[sheetObject]', exportAs: 'sheetObject' })
2121
export class TheatreSheetObject {
2222
key = input.required<string>({ alias: 'sheetObject' });
23-
props = input<UnknownShorthandCompoundProps>({});
24-
detach = input(false, { transform: booleanAttribute });
25-
selected = model<boolean>(false);
23+
props = input<UnknownShorthandCompoundProps>({}, { alias: 'sheetObjectProps' });
24+
detach = input(false, { transform: booleanAttribute, alias: 'sheetObjectDetach' });
25+
selected = model<boolean>(false, { alias: 'sheetObjectSelected' });
2626

2727
private templateRef = inject(TemplateRef);
2828
private vcr = inject(ViewContainerRef);

libs/theatre/src/lib/sheet-object/sync.ts

+61-27
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { computed, DestroyRef, Directive, effect, ElementRef, inject, input, signal } from '@angular/core';
1+
import { computed, DestroyRef, Directive, effect, ElementRef, inject, input } from '@angular/core';
22
import { NgtAnyRecord, resolveInstanceKey, resolveRef } from 'angular-three';
33
import { THEATRE_STUDIO } from '../studio/studio-token';
44
import { getDefaultTransformer } from '../transformers/default-transformer';
@@ -7,7 +7,7 @@ import { TheatreSheetObject } from './sheet-object';
77

88
const updateProjectionMatrixKeys = ['fov', 'near', 'far', 'zoom', 'left', 'right', 'top', 'bottom', 'aspect'];
99

10-
@Directive({ selector: '[sync]' })
10+
@Directive({ selector: '[sync]', exportAs: 'sync' })
1111
export class TheatreSheetObjectSync<TObject extends object> {
1212
parent = input.required<TObject | ElementRef<TObject> | (() => TObject | ElementRef<TObject> | undefined | null)>({
1313
alias: 'sync',
@@ -16,7 +16,8 @@ export class TheatreSheetObjectSync<TObject extends object> {
1616
Array<string | [string, string | { label?: string; key?: string; transformer?: TheatreTransformer }]>
1717
>([], { alias: 'syncProps' });
1818

19-
private sheetObject = inject(TheatreSheetObject);
19+
private theatreSheetObject = inject(TheatreSheetObject);
20+
sheetObject = computed(() => this.theatreSheetObject.sheetObject());
2021
private studio = inject(THEATRE_STUDIO, { optional: true });
2122

2223
private parentRef = computed(() => {
@@ -46,48 +47,52 @@ export class TheatreSheetObjectSync<TObject extends object> {
4647
);
4748
});
4849

49-
private init = signal(false);
50-
private propsMapping: Record<string, { path: string; transformer: TheatreTransformer }> = {};
50+
private propsToAdd = computed(() => {
51+
const parent = this.parentRef();
52+
if (!parent) return null;
5153

52-
constructor() {
53-
effect(() => {
54-
const parent = this.parentRef();
55-
if (!parent) return;
54+
const propsToAdd: NgtAnyRecord = {};
55+
const resolvedProps = this.resolvedProps();
56+
resolvedProps.forEach(([propName, { key, label, transformer }]) => {
57+
const { root, targetKey } = resolveInstanceKey(parent, propName);
58+
const rawValue = root[targetKey];
59+
const valueTransformer = transformer ?? getDefaultTransformer(root, targetKey, propName);
60+
const value = valueTransformer.transform(rawValue);
61+
62+
value.label = label ?? key;
5663

57-
const propsToAdd: NgtAnyRecord = {};
58-
const resolvedProps = this.resolvedProps();
59-
resolvedProps.forEach(([propName, { key, label, transformer }]) => {
60-
const { root, targetKey, targetProp } = resolveInstanceKey(parent, propName);
61-
const rawValue = root[targetKey];
62-
const valueTransformer = transformer ?? getDefaultTransformer(root, targetKey, propName);
63-
const value = valueTransformer.transform(rawValue);
64+
this.propsMapping[key] = { path: propName, transformer: valueTransformer };
65+
propsToAdd[key] = value;
66+
});
6467

65-
value.label = label ?? key;
68+
return propsToAdd;
69+
});
6670

67-
this.propsMapping[key] = { path: propName, transformer: valueTransformer };
68-
propsToAdd[key] = value;
69-
});
71+
private propsMapping: Record<string, { path: string; transformer: TheatreTransformer }> = {};
7072

71-
this.sheetObject.addProps(propsToAdd);
72-
this.init.set(true);
73+
constructor() {
74+
effect(() => {
75+
const propsToAdd = this.propsToAdd();
76+
if (!propsToAdd) return;
77+
this.theatreSheetObject.addProps(propsToAdd);
7378
});
7479

7580
effect((onCleanup) => {
7681
const parent = this.parentRef();
7782
if (!parent) return;
7883

79-
const init = this.init();
80-
if (!init) return;
84+
const propsToAdd = this.propsToAdd();
85+
if (!propsToAdd) return;
8186

82-
const sheetObject = this.sheetObject.sheetObject();
87+
const sheetObject = this.sheetObject();
8388
const cleanup = sheetObject.onValuesChange((newValues) => {
8489
Object.keys(newValues).forEach((key) => {
8590
// first, check if the prop is mapped in this component
8691
const propMapping = this.propsMapping[key];
8792
if (!propMapping) return;
8893

8994
// we're using the addedProps map to infer the target property name from the property name on values
90-
const { root, targetProp, targetKey } = resolveInstanceKey(parent, propMapping.path);
95+
const { root, targetKey } = resolveInstanceKey(parent, propMapping.path);
9196

9297
// use a transformer to apply value
9398
const transformer = propMapping.transformer;
@@ -103,10 +108,39 @@ export class TheatreSheetObjectSync<TObject extends object> {
103108
});
104109

105110
inject(DestroyRef).onDestroy(() => {
106-
this.sheetObject.removeProps(Object.keys(this.propsMapping));
111+
this.theatreSheetObject.removeProps(Object.keys(this.propsMapping));
107112
});
108113
}
109114

115+
capture() {
116+
const studio = this.studio?.();
117+
if (!studio) return;
118+
119+
const parent = this.parentRef();
120+
if (!parent) return;
121+
122+
const sheetObject = this.sheetObject();
123+
if (!sheetObject) return;
124+
125+
const scrub = studio.scrub();
126+
127+
Object.keys(sheetObject.value).forEach((key) => {
128+
// first, check if the prop is mapped in this component
129+
const propMapping = this.propsMapping[key];
130+
if (!propMapping) return;
131+
132+
// we're using the addedProps map to infer the target property name from the property name on values
133+
const { targetProp } = resolveInstanceKey(parent, propMapping.path);
134+
const value = propMapping.transformer.transform(targetProp).default;
135+
136+
scrub.capture(({ set }) => {
137+
set(sheetObject.props[key], value);
138+
});
139+
});
140+
141+
scrub.commit();
142+
}
143+
110144
private resolvePropertyPath(propPath: string) {
111145
return (
112146
propPath

libs/theatre/src/lib/sheet-object/transform.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ export class TheatreSheetObjectTransform<TLabel extends string | undefined> {
5252

5353
groupRef = viewChild.required<ElementRef<THREE.Group>>('group');
5454

55-
private sheetObject = inject(TheatreSheetObject);
55+
private theatreSheetObject = inject(TheatreSheetObject);
56+
sheetObject = computed(() => this.theatreSheetObject.sheetObject());
5657
private studio = inject(THEATRE_STUDIO, { optional: true });
5758

58-
protected selected = this.sheetObject.selected.asReadonly();
59+
protected selected = this.theatreSheetObject.selected.asReadonly();
5960
private scrub?: IScrub;
6061

6162
private positionTransformer = computed(() =>
@@ -82,7 +83,7 @@ export class TheatreSheetObjectTransform<TLabel extends string | undefined> {
8283
if (!this.scrub) return;
8384

8485
this.scrub.capture((api) => {
85-
const sheetObject = this.sheetObject.sheetObject();
86+
const sheetObject = this.sheetObject();
8687
if (!sheetObject) return;
8788

8889
const group = this.groupRef().nativeElement;
@@ -109,7 +110,7 @@ export class TheatreSheetObjectTransform<TLabel extends string | undefined> {
109110

110111
effect((onCleanup) => {
111112
const [sheetObject, key, positionTransformer, rotationTransformer, scaleTransformer, group] = [
112-
this.sheetObject.sheetObject(),
113+
this.sheetObject(),
113114
untracked(this.key),
114115
untracked(this.positionTransformer),
115116
untracked(this.rotationTransformer),
@@ -140,7 +141,7 @@ export class TheatreSheetObjectTransform<TLabel extends string | undefined> {
140141

141142
inject(DestroyRef).onDestroy(() => {
142143
const key = this.key();
143-
this.sheetObject.removeProps(key ? [key] : ['position', 'rotation', 'scale']);
144+
this.theatreSheetObject.removeProps(key ? [key] : ['position', 'rotation', 'scale']);
144145
});
145146
}
146147

@@ -159,11 +160,11 @@ export class TheatreSheetObjectTransform<TLabel extends string | undefined> {
159160
const scale = scaleTransformer.transform(group.scale);
160161

161162
if (key) {
162-
this.sheetObject.addProps({
163+
this.theatreSheetObject.addProps({
163164
[key]: types.compound({ position, rotation, scale }, { label: label ?? key }),
164165
});
165166
} else {
166-
this.sheetObject.addProps({ position, rotation, scale });
167+
this.theatreSheetObject.addProps({ position, rotation, scale });
167168
}
168169
}
169170
}

libs/theatre/src/lib/studio/studio.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { THEATRE_STUDIO } from './studio-token';
44

55
@Directive({
66
selector: 'theatre-project[studio]',
7+
exportAs: 'studio',
78
providers: [
89
{ provide: THEATRE_STUDIO, useFactory: (studio: TheatreStudio) => studio.studio, deps: [TheatreStudio] },
910
],

0 commit comments

Comments
 (0)