angular-three-theatre
Version:
TheatreJS for Angular Three
697 lines (675 loc) • 31.3 kB
JavaScript
import * as i0 from '@angular/core';
import { input, computed, effect, Component, ChangeDetectionStrategy, inject, DestroyRef, model, untracked, Directive, InjectionToken, booleanAttribute, TemplateRef, ViewContainerRef, linkedSignal, signal, viewChild, afterNextRender, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { getProject, val, onChange, types } from '@theatre/core';
import { omit, pick, injectStore, resolveRef, resolveInstanceKey, extend } from 'angular-three';
import { mergeInputs } from 'ngxtension/inject-inputs';
import * as THREE from 'three';
import { Group } from 'three';
import { NgtsTransformControls } from 'angular-three-soba/gizmos';
import Studio from '@theatre/studio';
class TheatreProject {
constructor() {
this.name = input('default-theatre-project');
this.config = input({});
this.project = computed(() => getProject(this.name(), this.config()));
this.sheets = {};
effect(() => {
const project = this.project();
project.ready.then();
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreProject, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.1", 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: `
<ng-content />
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreProject, decorators: [{
type: Component,
args: [{
selector: 'theatre-project',
template: `
<ng-content />
`,
changeDetection: ChangeDetectionStrategy.OnPush,
}]
}], ctorParameters: () => [] });
class TheatreSheet {
constructor() {
this.name = input('default-theatre-sheet');
this.project = inject(TheatreProject);
this.sheet = computed(() => {
const name = this.name();
const existing = this.project.sheets[name] || [];
if (existing[0]) {
existing[1]++;
return existing[0];
}
const sheet = this.project.project().sheet(name);
this.project.sheets[name] = [sheet, 1];
return sheet;
});
inject(DestroyRef).onDestroy(() => {
const existing = this.project.sheets[this.name()];
if (!existing)
return;
if (existing[1] >= 1) {
existing[1]--;
}
if (existing[1] === 0) {
delete this.project.sheets[this.name()];
}
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSheet, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.1", type: TheatreSheet, isStandalone: true, selector: "theatre-sheet", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
<ng-content />
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSheet, decorators: [{
type: Component,
args: [{
selector: 'theatre-sheet',
template: `
<ng-content />
`,
changeDetection: ChangeDetectionStrategy.OnPush,
}]
}], ctorParameters: () => [] });
const defaultOptions = {
rate: 1,
autoplay: false,
autopause: false,
delay: 0,
};
class TheatreSequence {
constructor() {
this.options = input(defaultOptions, { alias: 'sequence', transform: mergeInputs(defaultOptions) });
this.audioOptions = input(undefined, { alias: 'sequenceAudio' });
this.position = model(0);
this.playing = model(false);
this.length = model(0);
this.playOptions = omit(this.options, ['autoplay', 'autopause', 'delay', 'autoreset']);
this.autoplay = pick(this.options, 'autoplay');
this.autopause = pick(this.options, 'autopause');
this.autoreset = pick(this.options, 'autoreset');
this.delay = pick(this.options, 'delay');
this.project = inject(TheatreProject);
this.sheet = inject(TheatreSheet, { host: true });
this.sequence = computed(() => this.sheet.sheet().sequence);
effect((onCleanup) => {
const autoplay = untracked(this.autoplay);
if (!autoplay)
return;
const delay = untracked(this.delay);
const id = setTimeout(() => {
untracked(() => this.play());
}, delay);
onCleanup(() => {
clearTimeout(id);
});
});
effect((onCleanup) => {
const autopause = untracked(this.autopause);
onCleanup(() => {
if (autopause) {
this.pause();
}
});
});
effect((onCleanup) => {
const autoreset = untracked(this.autoreset);
if (autoreset === 'init' || autoreset === 'always') {
untracked(() => this.reset());
}
onCleanup(() => {
if (autoreset === 'destroy' || autoreset === 'always') {
untracked(() => this.reset());
}
});
});
effect(() => {
const [audioOptions, sequence] = [this.audioOptions(), untracked(this.sequence)];
if (audioOptions)
sequence.attachAudio(audioOptions);
});
effect(() => {
const [playOptions, sequence] = [this.playOptions(), untracked(this.sequence)];
const isPlaying = val(sequence.pointer.playing);
if (isPlaying) {
this.pause();
this.play(playOptions);
}
});
effect((onCleanup) => {
const sequence = this.sequence();
const cleanups = [];
cleanups.push(onChange(sequence.pointer.position, (value) => this.position.set(value)), onChange(sequence.pointer.playing, (value) => this.playing.set(value)), onChange(sequence.pointer.length, (value) => this.length.set(value)));
onCleanup(() => {
cleanups.forEach((cleanup) => cleanup());
});
});
}
pause() {
const sequence = this.sequence();
sequence.pause();
}
play(options = {}) {
const sequence = this.sequence();
const project = this.project.project();
project.ready.then(() => {
sequence.play({ ...this.playOptions(), ...options });
});
}
reset() {
const sequence = this.sequence();
const isPlaying = val(sequence.pointer.playing);
sequence.position = 0;
if (isPlaying)
this.play();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSequence, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.1", type: TheatreSequence, isStandalone: true, selector: "theatre-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" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSequence, decorators: [{
type: Directive,
args: [{ selector: 'theatre-sheet[sequence]' }]
}], ctorParameters: () => [] });
const THEATRE_STUDIO = new InjectionToken('Theatre Studio');
let TheatreSheetObject$1 = class TheatreSheetObject {
constructor() {
this.key = input.required({ alias: 'sheetObject' });
this.props = input({});
this.detach = input(false, { transform: booleanAttribute });
this.selected = model(false);
this.templateRef = inject(TemplateRef);
this.vcr = inject(ViewContainerRef);
this.sheet = inject(TheatreSheet);
this.studio = inject(THEATRE_STUDIO, { optional: true });
this.store = injectStore();
this.originalSheetObject = computed(() => {
const sheet = this.sheet.sheet();
return sheet.object(this.key(), untracked(this.props), { reconfigure: true });
});
this.sheetObject = linkedSignal(this.originalSheetObject);
this.values = linkedSignal(() => this.sheetObject().value);
this.detached = false;
this.aggregatedProps = {};
effect(() => {
this.aggregatedProps = { ...this.aggregatedProps, ...this.props() };
});
effect((onCleanup) => {
const sheetObject = this.sheetObject();
const cleanup = sheetObject.onValuesChange((newValues) => {
this.values.set(newValues);
this.store.snapshot.invalidate();
});
onCleanup(cleanup);
});
effect((onCleanup) => {
const studio = this.studio?.();
if (!studio)
return;
const sheetObject = this.sheetObject();
const cleanup = studio.onSelectionChange((selection) => {
this.selected.set(selection.includes(sheetObject));
});
onCleanup(cleanup);
});
effect((onCleanup) => {
const view = this.vcr.createEmbeddedView(this.templateRef, {
select: this.select.bind(this),
deselect: this.deselect.bind(this),
sheetObject: this.sheetObject.asReadonly(),
values: this.values.asReadonly(),
});
view.detectChanges();
onCleanup(() => {
view.destroy();
});
});
inject(DestroyRef).onDestroy(() => {
if (this.detach()) {
this.detached = true;
this.sheet.sheet().detachObject(this.key());
}
});
}
update() {
if (this.detached)
return;
const [sheet, key] = [untracked(this.sheet.sheet), untracked(this.key)];
sheet.detachObject(key);
this.sheetObject.set(sheet.object(key, this.aggregatedProps, { reconfigure: true }));
}
addProps(props) {
this.aggregatedProps = { ...this.aggregatedProps, ...props };
this.update();
}
removeProps(props) {
const [detach, sheet, key] = [untracked(this.detach), untracked(this.sheet.sheet), untracked(this.key)];
// remove props from sheet object
props.forEach((prop) => {
delete this.aggregatedProps[prop];
});
// if there are no more props, detach sheet object
if (Object.keys(this.aggregatedProps).length === 0) {
// detach sheet object
if (detach) {
sheet.detachObject(key);
}
}
else {
// update sheet object (reconfigure)
this.update();
}
}
select() {
const studio = this.studio?.();
if (!studio)
return;
studio.setSelection([this.sheetObject()]);
}
deselect() {
const studio = this.studio?.();
if (!studio)
return;
if (studio.selection.includes(this.sheetObject())) {
studio.setSelection([]);
}
}
static ngTemplateContextGuard(_, ctx) {
return true;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSheetObject, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.1", type: TheatreSheetObject, isStandalone: true, selector: "ng-template[sheetObject]", inputs: { key: { classPropertyName: "key", publicName: "sheetObject", isSignal: true, isRequired: true, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, detach: { classPropertyName: "detach", publicName: "detach", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange" }, ngImport: i0 }); }
};
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSheetObject$1, decorators: [{
type: Directive,
args: [{ selector: 'ng-template[sheetObject]' }]
}], ctorParameters: () => [] });
function createTransformer(transformer) {
return transformer;
}
const _color = new THREE.Color();
const color = createTransformer({
transform(value) {
value.getRGB(_color, THREE.SRGBColorSpace);
return types.rgba({ r: _color.r, g: _color.g, b: _color.b, a: 1 });
},
apply(target, path, value) {
target[path].setRGB(value.r, value.g, value.b, THREE.SRGBColorSpace);
},
});
const degrees = createTransformer({
transform(target) {
return types.number(target * THREE.MathUtils.RAD2DEG);
},
apply(target, path, value) {
target[path] = value * THREE.MathUtils.DEG2RAD;
},
});
const euler = createTransformer({
transform(value) {
return types.compound({
x: value.x * THREE.MathUtils.RAD2DEG,
y: value.y * THREE.MathUtils.RAD2DEG,
z: value.z * THREE.MathUtils.RAD2DEG,
});
},
apply(target, path, value) {
target[path].x = value.x * THREE.MathUtils.DEG2RAD;
target[path].y = value.y * THREE.MathUtils.DEG2RAD;
target[path].z = value.z * THREE.MathUtils.DEG2RAD;
},
});
const generic = createTransformer({
transform(value) {
if (typeof value === 'number') {
return types.number(value === Infinity ? Number.MAX_VALUE : value);
}
else if (typeof value === 'string') {
return types.string(value);
}
else if (typeof value === 'boolean') {
return types.boolean(value);
}
return types.compound({ ...value });
},
apply(target, path, value) {
if (target[path] !== null && typeof target[path] === 'object') {
Object.assign(target[path], value);
}
else {
target[path] = value;
}
},
});
const normalized = createTransformer({
transform(value) {
return types.number(value, { range: [0, 1] });
},
apply(target, path, value) {
target[path] = value;
},
});
const side = createTransformer({
transform(value) {
// TODO: fix this type
return types.stringLiteral(value === THREE.FrontSide ? 'f' : value === THREE.BackSide ? 'b' : 'd', { f: 'Front', b: 'Back', d: 'Double' }, { as: 'switch' });
},
apply(target, path, value) {
target[path] = value === 'f' ? THREE.FrontSide : value === 'b' ? THREE.BackSide : THREE.DoubleSide;
},
});
function isFullOrEndingPattern(fullPropertyPath, pattern) {
return fullPropertyPath.endsWith(`.${pattern}`) || fullPropertyPath === pattern;
}
function getDefaultTransformer(target, path, fullPropertyPath) {
const property = target[path];
if (property.isEuler)
return euler;
if (property.isColor)
return color;
if (isFullOrEndingPattern(fullPropertyPath, 'rotation.x') ||
isFullOrEndingPattern(fullPropertyPath, 'rotation.y') ||
isFullOrEndingPattern(fullPropertyPath, 'rotation.z') ||
(target.isEuler && (fullPropertyPath === 'x' || fullPropertyPath === 'y' || fullPropertyPath === 'z'))) {
return degrees;
}
if (isFullOrEndingPattern(fullPropertyPath, 'r'))
return normalized;
if (isFullOrEndingPattern(fullPropertyPath, 'g'))
return normalized;
if (isFullOrEndingPattern(fullPropertyPath, 'b'))
return normalized;
if (isFullOrEndingPattern(fullPropertyPath, 'opacity'))
return normalized;
if (isFullOrEndingPattern(fullPropertyPath, 'roughness'))
return normalized;
if (isFullOrEndingPattern(fullPropertyPath, 'metalness'))
return normalized;
if (isFullOrEndingPattern(fullPropertyPath, 'transmission'))
return normalized;
if (isFullOrEndingPattern(fullPropertyPath, 'side'))
return side;
return generic;
}
const updateProjectionMatrixKeys = ['fov', 'near', 'far', 'zoom', 'left', 'right', 'top', 'bottom', 'aspect'];
class TheatreSheetObjectSync {
constructor() {
this.parent = input.required({
alias: 'sync',
});
this.props = input([], { alias: 'syncProps' });
this.sheetObject = inject(TheatreSheetObject$1);
this.studio = inject(THEATRE_STUDIO, { optional: true });
this.parentRef = computed(() => {
const parent = this.parent();
if (typeof parent === 'function')
return resolveRef(parent());
return resolveRef(parent);
});
this.resolvedProps = computed(() => {
const props = this.props();
return props.reduce((resolved, prop) => {
if (typeof prop === 'string') {
resolved.push([prop, { key: this.resolvePropertyPath(prop) }]);
}
else {
if (typeof prop[1] === 'string') {
resolved.push([prop[0], { key: prop[1] }]);
}
else {
resolved.push(prop);
}
}
return resolved;
}, []);
});
this.init = signal(false);
this.propsMapping = {};
effect(() => {
const parent = this.parentRef();
if (!parent)
return;
const propsToAdd = {};
const resolvedProps = this.resolvedProps();
resolvedProps.forEach(([propName, { key, label, transformer }]) => {
const { root, targetKey, targetProp } = resolveInstanceKey(parent, propName);
const rawValue = root[targetKey];
const valueTransformer = transformer ?? getDefaultTransformer(root, targetKey, propName);
const value = valueTransformer.transform(rawValue);
value.label = label ?? key;
this.propsMapping[key] = { path: propName, transformer: valueTransformer };
propsToAdd[key] = value;
});
this.sheetObject.addProps(propsToAdd);
this.init.set(true);
});
effect((onCleanup) => {
const parent = this.parentRef();
if (!parent)
return;
const init = this.init();
if (!init)
return;
const sheetObject = this.sheetObject.sheetObject();
const cleanup = sheetObject.onValuesChange((newValues) => {
Object.keys(newValues).forEach((key) => {
// first, check if the prop is mapped in this component
const propMapping = this.propsMapping[key];
if (!propMapping)
return;
// we're using the addedProps map to infer the target property name from the property name on values
const { root, targetProp, targetKey } = resolveInstanceKey(parent, propMapping.path);
// use a transformer to apply value
const transformer = propMapping.transformer;
transformer.apply(root, targetKey, newValues[key]);
if (updateProjectionMatrixKeys.includes(targetKey)) {
root.updateProjectionMatrix?.();
}
});
});
onCleanup(cleanup);
});
inject(DestroyRef).onDestroy(() => {
this.sheetObject.removeProps(Object.keys(this.propsMapping));
});
}
resolvePropertyPath(propPath) {
return (propPath
// make the label alphanumeric by first removing dots (fundamental feature for pierced props)
.replace(/\./g, '-')
// make the following characters uppercase
.replace(/-([a-z])/g, (g) => g[1].toUpperCase())
// convert to safe alphanumeric characters without dashes
.replace(/[^a-zA-Z0-9]/g, ''));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSheetObjectSync, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.1", 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 } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSheetObjectSync, decorators: [{
type: Directive,
args: [{ selector: '[sync]' }]
}], ctorParameters: () => [] });
class TheatreSheetObjectTransform {
onMouseDown() {
if (!this.studio)
return;
if (this.scrub)
return;
this.scrub = this.studio().scrub();
}
onMouseUp() {
if (!this.scrub)
return;
this.scrub.commit();
this.scrub = undefined;
}
onChange() {
if (!this.scrub)
return;
this.scrub.capture((api) => {
const sheetObject = this.sheetObject.sheetObject();
if (!sheetObject)
return;
const group = this.groupRef().nativeElement;
const key = this.key();
const baseTarget = key ? sheetObject.props[key] : sheetObject.props;
api.set(baseTarget['position'], { ...group.position });
api.set(baseTarget['rotation'], {
x: group.rotation.x * THREE.MathUtils.RAD2DEG,
y: group.rotation.y * THREE.MathUtils.RAD2DEG,
z: group.rotation.z * THREE.MathUtils.RAD2DEG,
});
api.set(baseTarget['scale'], { ...group.scale });
});
}
constructor() {
this.label = input();
this.key = input();
this.options = input({});
this.groupRef = viewChild.required('group');
this.sheetObject = inject(TheatreSheetObject$1);
this.studio = inject(THEATRE_STUDIO, { optional: true });
this.selected = this.sheetObject.selected.asReadonly();
this.positionTransformer = computed(() => getDefaultTransformer(this.groupRef().nativeElement, 'position', 'position'));
this.rotationTransformer = computed(() => getDefaultTransformer(this.groupRef().nativeElement, 'rotation', 'rotation'));
this.scaleTransformer = computed(() => getDefaultTransformer(this.groupRef().nativeElement, 'scale', 'scale'));
extend({ Group });
afterNextRender(() => {
this.init();
});
effect((onCleanup) => {
const [sheetObject, key, positionTransformer, rotationTransformer, scaleTransformer, group] = [
this.sheetObject.sheetObject(),
untracked(this.key),
untracked(this.positionTransformer),
untracked(this.rotationTransformer),
untracked(this.scaleTransformer),
untracked(this.groupRef).nativeElement,
];
const cleanup = sheetObject.onValuesChange((newValues) => {
let object = newValues;
if (key) {
if (!newValues[key])
return;
object = newValues[key];
}
else {
if (!newValues['position'] || !newValues['rotation'] || !newValues['scale'])
return;
}
// sanity check
if (!object)
return;
positionTransformer.apply(group, 'position', object['position']);
rotationTransformer.apply(group, 'rotation', object['rotation']);
scaleTransformer.apply(group, 'scale', object['scale']);
});
onCleanup(cleanup);
});
inject(DestroyRef).onDestroy(() => {
const key = this.key();
this.sheetObject.removeProps(key ? [key] : ['position', 'rotation', 'scale']);
});
}
init() {
const [group, key, label, positionTransformer, rotationTransformer, scaleTransformer] = [
this.groupRef().nativeElement,
this.key(),
this.label(),
this.positionTransformer(),
this.rotationTransformer(),
this.scaleTransformer(),
];
const position = positionTransformer.transform(group.position);
const rotation = rotationTransformer.transform(group.rotation);
const scale = scaleTransformer.transform(group.scale);
if (key) {
this.sheetObject.addProps({
[key]: types.compound({ position, rotation, scale }, { label: label ?? key }),
});
}
else {
this.sheetObject.addProps({ position, rotation, scale });
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSheetObjectTransform, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", 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 }], ngImport: i0, template: `
(selected()) {
<ngts-transform-controls
[object]="$any(group)"
[options]="options()"
(mouseDown)="onMouseDown()"
(mouseUp)="onMouseUp()"
(change)="onChange()"
/>
}
<ngt-group #group>
<ng-content />
</ngt-group>
`, isInline: true, dependencies: [{ kind: "component", type: NgtsTransformControls, selector: "ngts-transform-controls", inputs: ["object", "options"], outputs: ["change", "mouseDown", "mouseUp", "objectChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreSheetObjectTransform, decorators: [{
type: Component,
args: [{
selector: 'theatre-transform',
template: `
(selected()) {
<ngts-transform-controls
[object]="$any(group)"
[options]="options()"
(mouseDown)="onMouseDown()"
(mouseUp)="onMouseUp()"
(change)="onChange()"
/>
}
<ngt-group #group>
<ng-content />
</ngt-group>
`,
imports: [NgtsTransformControls],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
changeDetection: ChangeDetectionStrategy.OnPush,
}]
}], ctorParameters: () => [] });
const TheatreSheetObject = [TheatreSheetObject$1, TheatreSheetObjectTransform, TheatreSheetObjectSync];
class TheatreStudio {
constructor() {
this.enabled = input(true, { alias: 'studio', transform: booleanAttribute });
this.Studio = signal(Studio);
this.studio = this.Studio.asReadonly();
this.Studio().initialize();
effect((onCleanup) => {
const [enabled, studio] = [this.enabled(), this.Studio()];
if (enabled) {
studio.ui.restore();
}
else {
studio.ui.hide();
}
onCleanup(() => {
studio.ui.hide();
});
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreStudio, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.1", type: TheatreStudio, isStandalone: true, selector: "theatre-project[studio]", inputs: { enabled: { classPropertyName: "enabled", publicName: "studio", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
{ provide: THEATRE_STUDIO, useFactory: (studio) => studio.studio, deps: [TheatreStudio] },
], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TheatreStudio, decorators: [{
type: Directive,
args: [{
selector: 'theatre-project[studio]',
providers: [
{ provide: THEATRE_STUDIO, useFactory: (studio) => studio.studio, deps: [TheatreStudio] },
],
}]
}], ctorParameters: () => [] });
/**
* Generated bundle index. Do not edit.
*/
export { TheatreProject, TheatreSequence, TheatreSheet, TheatreSheetObject, TheatreSheetObject$1 as TheatreSheetObjectImpl, TheatreSheetObjectSync, TheatreSheetObjectTransform, TheatreStudio };
//# sourceMappingURL=angular-three-theatre.mjs.map