model.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  7. import { PluginContext } from '../../mol-plugin/context';
  8. export { PluginStateAnimation };
  9. // TODO: helpers for building animations (once more animations are added)
  10. // for example "composite animation"
  11. interface PluginStateAnimation<P = any, S = any> {
  12. name: string,
  13. readonly display: { readonly name: string, readonly description?: string },
  14. readonly isExportable?: boolean,
  15. params(ctx: PluginContext): PD.For<P>,
  16. canApply?(ctx: PluginContext): PluginStateAnimation.CanApply,
  17. initialState(params: P, ctx: PluginContext): S,
  18. getDuration?(params: P, ctx: PluginContext): PluginStateAnimation.Duration,
  19. // Optionally returns new state
  20. setup?(params: P, state: S, ctx: PluginContext): void | Promise<S> | Promise<void>,
  21. teardown?(params: P, state: S, ctx: PluginContext): void | Promise<void>,
  22. /**
  23. * Apply the current frame and modify the state.
  24. * @param t Current absolute time since the animation started.
  25. */
  26. apply(state: S, t: PluginStateAnimation.Time, ctx: PluginStateAnimation.Context<P>): Promise<PluginStateAnimation.ApplyResult<S>>,
  27. /**
  28. * The state must be serializable to JSON. If JSON.stringify is not enough,
  29. * custom converted to an object that works with JSON.stringify can be provided.
  30. */
  31. stateSerialization?: { toJSON(state: S): any, fromJSON(data: any): S }
  32. }
  33. namespace PluginStateAnimation {
  34. export type CanApply = { canApply: true } | { canApply: false, reason?: string }
  35. export type Duration = { kind: 'unknown' } | { kind: 'infinite' } | { kind: 'fixed', durationMs: number }
  36. export interface Instance<A extends PluginStateAnimation> {
  37. definition: PluginStateAnimation,
  38. params: Params<A>,
  39. customDurationMs?: number
  40. }
  41. export interface Time {
  42. lastApplied: number,
  43. current: number,
  44. animation?: { currentFrame: number, frameCount: number }
  45. }
  46. export type ApplyResult<S> = { kind: 'finished' } | { kind: 'skip' } | { kind: 'next', state: S }
  47. export interface Context<P> {
  48. params: P,
  49. plugin: PluginContext
  50. }
  51. export type Params<A extends PluginStateAnimation> = A extends PluginStateAnimation<infer P> ? P : never
  52. export function create<P, S>(params: PluginStateAnimation<P, S>) {
  53. return params;
  54. }
  55. export function getDuration<A extends PluginStateAnimation>(ctx: PluginContext, instance: Instance<A>) {
  56. if (instance.customDurationMs) return instance.customDurationMs;
  57. const d = instance.definition.getDuration?.(instance.params, ctx);
  58. if (d?.kind === 'fixed') return d.durationMs;
  59. }
  60. }