import { Observable, ReplaySubject, Subject } from 'rxjs'; /** * This internal interface is not intended for module export and should not be used as generic rendering/controller * interface. The renderer interface should be used for rendering related tasks instead. */ export interface Controllable { /** * Used to trigger an renderer update. Returns true iff rendering is invalidated and * a new multi-frame should be rendered- */ update(multiFrameNumber: number): boolean; /** * Used to prepare rendering of a multi-frame. */ prepare(): void; /** * Used to trigger rendering of a single, intermediate frame. */ frame(frameNumber: number): void; /** * Used to swap/blit frame from back to front buffer. */ swap(): void; } /** * This class controls the rendering flow by means of triggering rendering of a well defined amount of frames * (multi-frame number) for frame accumulation. Single frame rendering is handled with a multi-frame number of 1. If a * full multi-frame is accumulated, rendering halts. The rendering is not intended to be controlled by owning objects, * but via invalidation from within the renderer instead. However, an explicit redraw of a full single or multi-frame * can be invoked by calling `update()`. Furthermore, when using multi-frame rendering, the renderer can be halted at a * specific frame by setting a debug-frame number. * * Terminology: a multi-frame is the final result after accumulating a number of intermediate frames (frame). The * number of intermediate frames is defined by the multi-frame number. For a multi-frame, the controller invokes the * `prepare` on a controllable first, followed by multiple `frame` and `swap` calls. Please note that the * adaptive batch mode is yet experimental (can be enabled using `batchSize`). */ export declare class Controller { /** * Toggle for debug outputs; if true control flow will be logged. */ protected static _debug: boolean; set debug(value: boolean); /** * Number of intermediate frames that are rendered during one browser frame */ protected _batchSize: number; set batch(size: number); /** * @see {@link multiFrameNumber} * This property can be observed, e.g., `aController.multiFrameNumberObservable.subscribe()`. */ protected _multiFrameNumber: number; protected _multiFrameNumberSubject: ReplaySubject; /** * @see {@link debugFrameNumber} * This property can be observed, e.g., `aController.debugFrameNumberObservable.subscribe()`. */ protected _debugFrameNumber: number; protected _debugFrameNumberSubject: ReplaySubject; /** * @see {@link frameNumber} * This property can be observed, e.g., `aController.frameNumberObservable.subscribe()`. */ protected _frameNumber: number; protected _frameNumberSubject: ReplaySubject; /** @see {@link multiFrameDelay} */ protected _multiFrameDelay: number; /** Observable event that is triggered after frame invocation (renderer). */ protected _postFrameEventSubject: Subject; /** Observable event that is triggered after swap invocation (renderer). */ protected _postSwapEventSubject: Subject; /** * Controllable, e.g., an instance of a Renderer. */ protected _controllable: Controllable | undefined; /** * Holds the handle of the pending / executed animate frame request, if requested. Throughout the controller, only a * single request at a time is allowed. */ protected _animationFrameID: number; /** * Holds the handle of the running timeout to execute a new multi frame. Undefined if we currently do not wait for * a new multi frame. */ protected _timeoutID: number | undefined; /** * Blocking updates can be used to re-configure the controller without triggering */ protected _block: boolean; /** * Number of update requested while being in blocked mode. If there is one or more blocked requests, an update will * be triggered when unblocked. */ protected _blockedUpdates: number; /** * Total number of rendered intermediate frames. */ protected _intermediateFrameCount: number; /** * Total number of completed multi-frames. */ protected _multiFrameCount: number; /** * Time tracker used to the minimum and maximum frame time of an intermediate frame (per multi-frame). */ protected _intermediateFrameTimes: number[]; /** * Time tracker used to accumulate all durations of executed frame and swap callbacks per multi-frame. This is the * net rendering time and is used to derive the average frame time. */ protected _multiFrameTime: number; /** * Time tracker used to capture the time the update callback took. */ protected _updateFrameTime: number; /** * Used to measure the gross rendering time of a multi-frame. The first point in time denotes the start of the * rendering, the second, the point in time the last frame was rendered. * * Note: point in times might be shifted due to (un)pausing. Their intent is to allow measuring the rendering * duration, nothing else. */ protected _multiTime: Array; protected _invalidated: boolean; protected _force: boolean; protected request(source?: Controller.RequestType): void; protected invoke(source: Controller.RequestType): void; /** * Actual invocation of the controllable's update method. Returns true if multi frame rendering should be restarted, * false otherwise. */ protected invokeUpdate(): boolean; /** * Actual invocation of the controllable's prepare method. */ protected invokePrepare(): void; /** * Invokes rendering of an intermediate frame, increments the frame counter, and requests rendering of the next * frame. The rendering is invoked by means of a callback to the canvas renderer. This function implements various * asserts to assure correct control logic and absolutely prevent unnecessary frame requests. */ protected invokeFrameAndSwap(): void; protected startWaitMultiFrame(): void; protected cancelWaitMultiFrame(): void; protected isMultiFrameFinished(): boolean; /** * Utility for communicating this._multiFrameNumber changes to its associated subject. */ protected multiFrameNumberNext(): void; /** * Utility for communicating this._debugFrameNumber changes to its associated subject. */ protected debugFrameNumberNext(): void; /** * Utility for communicating this._frameNumber changes to its associated subject. */ protected frameNumberNext(): void; update(force?: boolean): void; /** * Block implicit updates, e.g., caused by various setters. This can be used to reconfigure the controller without * triggering to multiple intermediate updates. The block updates mode can be exited using `unblock`. */ block(): void; /** * Unblock updates. If there was at least one blocked update request, an immediate update is invoked. */ unblock(): void; cancel(): void; /** * Returns whether or not the control is blocking updates. * @returns - True if blocked, else false. */ get blocked(): boolean; /** * Sets the controllable, for which updates, frames, and swaps are invoked whenever rendering is * invalidated and an updated multi-frame is required. Swap is detached from frame since rendering an intermediate * frame is usually done offscreen and explicit swap control can be useful. * @param controllable - Controllable for update, frame, and swap invocation. */ set controllable(controllable: Controllable | undefined); /** * Returns the multi-frame number. The number is greater than or equal to zero. Multi-frame number is implemented * as a property and allows for change callback. * @returns - Multi-frame number. */ get multiFrameNumber(): number; /** * Changes the multi-frame number. If the provided value equals the current number set, nothing happens. If the * provided value is negative, the multi-frame number is set to 1. * @param multiFrameNumber - The multi-frame number targeted for rendering. */ set multiFrameNumber(multiFrameNumber: number); /** * Observable that can be used to subscribe to multi-frame number changes. */ get multiFrameNumber$(): Observable; /** * Returns the debug-frame number greater than or equal to zero. * @returns - Debug-frame number. */ get debugFrameNumber(): number; /** * Sets the debug.-frame number (debug number) that, if greater than zero, causes the rendering to halt when the * current frame number (frame number) equals the debug number. Debugging can be disabled by setting the debug * number to zero. * * If the debug number is greater than the frame number rendering is restarted by means of an update(). If the * debug number is less than the frame number the rendering continues and halts accordingly. If the debug number * equals the current debug number set, nothing happens. If the debug number is greater than the multi-frame * number, it is reduced to the multi-frame number. * * Note: in contrast to setting the multi-frame number, setting the debug-frame number unpauses the controller. * * @param debugFrameNumber - Debug-frame number. */ set debugFrameNumber(debugFrameNumber: number); /** * Observable that can be used to subscribe to debug-frame number changes. */ get debugFrameNumber$(): Observable; /** * Sets the multi-frame delay in milliseconds. This is used to delay rendering of subsequent intermediate frames * after an update. * @param multiFrameDelay - A multi-frame delay in milliseconds. */ set multiFrameDelay(multiFrameDelay: number); /** * Time in milliseconds used to delay rendering of subsequent intermediate frames after an update. * @returns - The current multi-frame delay in milliseconds. */ get multiFrameDelay(): number; /** * The current multi-frame number; it is less than or equal to the multi-frame number and enumerates the last * rendered frame. Note that this does not denote the number of 'completed' multi-frames rendered (not a continuous * frame count). * @returns - The current (intermediate) frame number. */ get frameNumber(): number; /** * Observable that can be used to subscribe to frame number changes. */ get frameNumber$(): Observable; /** * Returns the total number of rendered (requested and probably completed) intermediate frames. * @returns - The total number of intermediate frames rendered. */ get intermediateFrameCount(): number; /** * Returns the total number of completed multi-frames. * @returns - The total number of multi-frames completed. */ get multiFrameCount(): number; /** * Provides the average time it takes to render an intermediate frame within the current displayed multi-frame (if * a new multi-frame is triggered, the average frame time is reset). * @returns - Average frame time (intermediate frame rendering) in ms */ get averageFrameTime(): number; /** * Provides the update time tracked for the current multi-frame. * @returns - Time of the multi-frame update (before first intermediate frame is rendered) in ms */ get updateFrameTime(): number; /** * Provides the minimum rendering time tracked over all intermediate frames of the current multi-frame. * @returns - Minimum intermediate frame time in ms */ get minimumFrameTime(): number; /** * Provides the maximum rendering time tracked over all intermediate frames of the current multi-frame. Note that * the maximum frame time is most often caused by the first intermediate frame within a multi-frame due to lazy * stage initialization or reconfiguration. * @returns - Maximum intermediate frame time in ms */ get maximumFrameTime(): number; /** * The time in milliseconds that passed since the current multi-frame (up to the current frame number) was * requested. This time excludes time spent paused (e.g., caused by halting rendering at debug-frame number). * Note that this is not a measure of frame rendering performance. The number of frame requests per second might be * limited to 60Hz even though the rendering of an intermediate frame takes only a few milliseconds. * @returns - Time passed for current multi-frame in milliseconds. */ get multiFrameTime(): number; /** * The frames per second is based on the average number of a full intermediate frame request up to the current * frame number. * @returns - Number of frames per second based on the current multi-frame */ get framesPerSecond(): number; /** * Observable that can be used to subscribe to post frame events. */ get postFrameEvent$(): Observable; /** * Observable that can be used to subscribe to post swap events. */ get postSwapEvent$(): Observable; } export declare namespace Controller { enum RequestType { Frame = 0, MultiFrame = 1 } }