tav-media
Version:
Cross platform media editing framework
228 lines (227 loc) • 7.99 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { tav } from '../tav';
import { MovieClip } from './tav-movie-clip';
import { FakeClip } from './tav-fake-clip';
import { updateNativeIfEffect } from '../types/tav-object';
/**
* An object that combines and arranges clips into a single composite clip that you can play or
* process.
* @category Clips
*/
export class Composition extends MovieClip {
constructor() {
super(...arguments);
this.type = 'Composition';
this.clips = [];
this.fakeClips = [];
this.lastNoticeUpdateFakeClip = null;
this._width = 1;
this._widthInvalid = true;
this._height = 1;
this._heightInvalid = true;
}
/**
* Create a new composition with specified size.
* @param width The width of the composition.
* @param height The height of the composition.
* @param contentStartTime The start time of the content of this composition.
* @param contentDuration The duration of the content of this composition.
*/
static Make(width, height, contentStartTime, contentDuration) {
return __awaiter(this, void 0, void 0, function* () {
const comp = new Composition();
comp.width = width;
comp.height = height;
comp.contentStartTime = contentStartTime;
comp.contentDuration = contentDuration;
return comp;
});
}
/**
* Adds a clip to this composition.
*/
addClip(clip) {
if (clip) {
// convert to composition to call protected method and vars
const child = clip;
child.removeFromParent();
child.attachToParent(this);
this.clips.push(child);
return;
}
console.warn('composition must add with a clip, but now is', clip);
}
/**
* Removes a clip from this composition.
* @param clip
*/
removeClip(clip) {
// convert to composition to call protected method and vars
const child = clip;
const index = this.clips.indexOf(child);
if (index >= 0) {
child.detachFromParent();
this.clips.splice(index, 1);
}
}
hasChildClip(clip) {
return this.clips.indexOf(clip) >= 0;
}
/**
* Removes all clips from this composition.
*/
removeAllClips() {
this.clips.forEach((clip) => {
// convert to composition to call protected method and vars
const child = clip;
child.detachFromParent();
});
this.clips.length = 0;
}
/**
* Get all chid clips
*/
getAllClips() {
return this.clips.concat();
}
/**
* Make fakeClip from this composition,
* used to reference a snapshot of this composition in other effects
*/
MakeFakeClip() {
const fakeClip = new FakeClip();
fakeClip.ontology = this;
this.fakeClips.push(fakeClip);
return fakeClip;
}
/**
* whether this composition has a fakeClip child that need rebuild
* @ignore
*/
hasFakeClipNativeInvalidated() {
for (const clip of this.clips) {
if (clip.hasFakeClipNativeInvalidated()) {
return true;
}
}
return false;
}
/**
* whether fake clips of this composition to rebuild
* @ignore
*/
noticeFakeClipsUpdate(noticeClip) {
if (noticeClip) {
this.lastNoticeUpdateFakeClip = noticeClip;
return;
}
const needNotice = this.fakeClips.filter(clip => clip !== this.lastNoticeUpdateFakeClip);
needNotice.forEach(clip => clip.setNativeInvalidated());
}
/**
* remove one fake clip from this composition's fake clips
* @ignore
*/
removeFakeClip(fakeClip) {
this.fakeClips.splice(this.fakeClips.indexOf(fakeClip), 1);
}
/**
* Release this composition and all clips of this composition.
*/
release() {
super.release();
this.clips.forEach(clip => clip.release());
}
createClip() {
return __awaiter(this, void 0, void 0, function* () {
const existing = this._nativeObject;
if (existing
&& !this._contentTimeInvalid
&& !this._heightInvalid
&& !this._widthInvalid) {
return existing;
}
const composition = tav.Composition.Make(this.width, this.height, this.contentStartTime || 0, this.contentDuration || this.duration);
composition.clips = [];
this._contentTimeInvalid = false;
this._heightInvalid = false;
this._widthInvalid = false;
return composition;
});
}
updateClip(composition) {
const _super = Object.create(null, {
updateClip: { get: () => super.updateClip }
});
var _a;
return __awaiter(this, void 0, void 0, function* () {
yield _super.updateClip.call(this, composition);
composition.removeAllClips();
// eslint-disable-next-line no-param-reassign
composition.clips = [];
for (const clip of this.clips) {
const nativeClip = yield clip.build();
if (nativeClip) {
(_a = composition.clips) === null || _a === void 0 ? void 0 : _a.push(nativeClip);
composition.addClip(nativeClip);
}
else {
console.error(`Found unsupported clip with type: ${clip.type}, id: ${clip.id}`);
}
}
this.noticeFakeClipsUpdate();
this.lastNoticeUpdateFakeClip = null;
});
}
get width() {
return this._width;
}
set width(w) {
if (w === this._width)
return;
if (w < 0) {
console.error('The width must be greater than or equal to 0.');
w = 0;
}
this._width = w;
this._widthInvalid = true;
this.invalidated();
}
get height() {
return this._height;
}
set height(h) {
if (h === this._height)
return;
if (h < 0) {
console.error('The height must be greater than or equal to 0.');
h = 0;
}
this._height = h;
this._heightInvalid = true;
this.invalidated();
}
}
__decorate([
updateNativeIfEffect
], Composition.prototype, "addClip", null);
__decorate([
updateNativeIfEffect
], Composition.prototype, "removeClip", null);
__decorate([
updateNativeIfEffect
], Composition.prototype, "removeAllClips", null);