Skip to content
Snippets Groups Projects
Commit e3d264e2 authored by dsehnal's avatar dsehnal
Browse files

Pass animation info to state animations

+ Fix camera stutter for "camera spin"
parent 9bd60f8e
No related branches found
No related tags found
No related merge requests found
...@@ -7,6 +7,8 @@ Note that since we don't clearly distinguish between a public and private interf ...@@ -7,6 +7,8 @@ Note that since we don't clearly distinguish between a public and private interf
## [Unreleased] ## [Unreleased]
- Fix ``getOperatorsForIndex`` - Fix ``getOperatorsForIndex``
- Pass animation info (current frame & count) to state animations
- Fix camera stutter for "camera spin" animation
## [v3.0.0-dev.9] - 2022-01-09 ## [v3.0.0-dev.9] - 2022-01-09
......
...@@ -73,7 +73,7 @@ export async function encodeMp4Animation<A extends PluginStateAnimation>(plugin: ...@@ -73,7 +73,7 @@ export async function encodeMp4Animation<A extends PluginStateAnimation>(plugin:
await plugin.managers.animation.play(params.animation.definition, params.animation.params); await plugin.managers.animation.play(params.animation.definition, params.animation.params);
stoppedAnimation = false; stoppedAnimation = false;
for (let i = 0; i <= N; i++) { for (let i = 0; i <= N; i++) {
await loop.tick(i * dt, { isSynchronous: true, manualDraw: true }); await loop.tick(i * dt, { isSynchronous: true, animation: { currentFrame: i, frameCount: N }, manualDraw: true });
const image = params.pass.getImageData(width, height, normalizedViewport); const image = params.pass.getImageData(width, height, normalizedViewport);
encoder.addFrameRgba(image.data); encoder.addFrameRgba(image.data);
......
...@@ -39,13 +39,9 @@ export const AnimateCameraSpin = PluginStateAnimation.create({ ...@@ -39,13 +39,9 @@ export const AnimateCameraSpin = PluginStateAnimation.create({
return { kind: 'finished' }; return { kind: 'finished' };
} }
const phase = clamp(t.current / ctx.params.durationInMs, 0, 1); const phase = t.animation
? t.animation?.currentFrame / (t.animation.frameCount + 1)
if (phase >= 0.99999) { : clamp(t.current / ctx.params.durationInMs, 0, 1);
ctx.plugin.canvas3d?.requestCameraReset({ snapshot, durationMs: 0 });
return { kind: 'finished' };
}
const angle = 2 * Math.PI * phase * ctx.params.speed * (ctx.params.direction === 'ccw' ? -1 : 1); const angle = 2 * Math.PI * phase * ctx.params.speed * (ctx.params.direction === 'ccw' ? -1 : 1);
Vec3.sub(_dir, snapshot.position, snapshot.target); Vec3.sub(_dir, snapshot.position, snapshot.target);
...@@ -55,6 +51,10 @@ export const AnimateCameraSpin = PluginStateAnimation.create({ ...@@ -55,6 +51,10 @@ export const AnimateCameraSpin = PluginStateAnimation.create({
const position = Vec3.add(Vec3(), snapshot.target, _dir); const position = Vec3.add(Vec3(), snapshot.target, _dir);
ctx.plugin.canvas3d?.requestCameraReset({ snapshot: { ...snapshot, position }, durationMs: 0 }); ctx.plugin.canvas3d?.requestCameraReset({ snapshot: { ...snapshot, position }, durationMs: 0 });
if (phase >= 0.99999) {
return { kind: 'finished' };
}
return { kind: 'next', state: animState }; return { kind: 'next', state: animState };
} }
}); });
\ No newline at end of file
...@@ -51,7 +51,8 @@ namespace PluginStateAnimation { ...@@ -51,7 +51,8 @@ namespace PluginStateAnimation {
export interface Time { export interface Time {
lastApplied: number, lastApplied: number,
current: number current: number,
animation?: { currentFrame: number, frameCount: number }
} }
export type ApplyResult<S> = { kind: 'finished' } | { kind: 'skip' } | { kind: 'next', state: S } export type ApplyResult<S> = { kind: 'finished' } | { kind: 'skip' } | { kind: 'next', state: S }
......
...@@ -99,12 +99,12 @@ class PluginAnimationManager extends StatefulPluginComponent<PluginAnimationMana ...@@ -99,12 +99,12 @@ class PluginAnimationManager extends StatefulPluginComponent<PluginAnimationMana
await this.start(); await this.start();
} }
async tick(t: number, isSynchronous?: boolean) { async tick(t: number, isSynchronous?: boolean, animation?: PluginAnimationManager.AnimationInfo) {
this.currentTime = t; this.currentTime = t;
if (this.isStopped) return; if (this.isStopped) return;
if (isSynchronous) { if (isSynchronous || animation) {
await this.applyFrame(); await this.applyFrame(animation);
} else { } else {
this.applyAsync(); this.applyAsync();
} }
...@@ -165,12 +165,12 @@ class PluginAnimationManager extends StatefulPluginComponent<PluginAnimationMana ...@@ -165,12 +165,12 @@ class PluginAnimationManager extends StatefulPluginComponent<PluginAnimationMana
} }
} }
private async applyFrame() { private async applyFrame(animation?: PluginAnimationManager.AnimationInfo) {
const t = this.currentTime; const t = this.currentTime;
if (this._current.startedTime < 0) this._current.startedTime = t; if (this._current.startedTime < 0) this._current.startedTime = t;
const newState = await this._current.anim.apply( const newState = await this._current.anim.apply(
this._current.state, this._current.state,
{ lastApplied: this._current.lastTime, current: t - this._current.startedTime }, { lastApplied: this._current.lastTime, current: t - this._current.startedTime, animation },
{ params: this._current.paramValues, plugin: this.context }); { params: this._current.paramValues, plugin: this.context });
if (newState.kind === 'finished') { if (newState.kind === 'finished') {
...@@ -228,6 +228,11 @@ class PluginAnimationManager extends StatefulPluginComponent<PluginAnimationMana ...@@ -228,6 +228,11 @@ class PluginAnimationManager extends StatefulPluginComponent<PluginAnimationMana
} }
namespace PluginAnimationManager { namespace PluginAnimationManager {
export interface AnimationInfo {
currentFrame: number,
frameCount: number
}
export interface Current { export interface Current {
anim: PluginStateAnimation anim: PluginStateAnimation
params: PD.Params, params: PD.Params,
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
import { PluginContext } from './context'; import { PluginContext } from './context';
import { now } from '../mol-util/now'; import { now } from '../mol-util/now';
import { PluginAnimationManager } from '../mol-plugin-state/manager/animation';
export class PluginAnimationLoop { export class PluginAnimationLoop {
private currentFrame: any = void 0; private currentFrame: any = void 0;
...@@ -15,8 +16,8 @@ export class PluginAnimationLoop { ...@@ -15,8 +16,8 @@ export class PluginAnimationLoop {
return this._isAnimating; return this._isAnimating;
} }
async tick(t: number, options?: { isSynchronous?: boolean, manualDraw?: boolean }) { async tick(t: number, options?: { isSynchronous?: boolean, manualDraw?: boolean, animation?: PluginAnimationManager.AnimationInfo }) {
await this.plugin.managers.animation.tick(t, options?.isSynchronous); await this.plugin.managers.animation.tick(t, options?.isSynchronous, options?.animation);
this.plugin.canvas3d?.tick(t as now.Timestamp, options); this.plugin.canvas3d?.tick(t as now.Timestamp, options);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment