Skip to content
Snippets Groups Projects
Commit e55c2e04 authored by David Sehnal's avatar David Sehnal
Browse files

mol-plugin: basic animation support

parent 45c991b0
No related branches found
No related tags found
No related merge requests found
...@@ -66,4 +66,8 @@ ...@@ -66,4 +66,8 @@
background: white; background: white;
cursor: inherit; cursor: inherit;
display: block; display: block;
}
.msp-animation-section {
margin-bottom: $control-spacing;
} }
\ No newline at end of file
...@@ -45,6 +45,7 @@ class PluginState { ...@@ -45,6 +45,7 @@ class PluginState {
return { return {
data: this.dataState.getSnapshot(), data: this.dataState.getSnapshot(),
behaviour: this.behaviorState.getSnapshot(), behaviour: this.behaviorState.getSnapshot(),
animation: this.animation.getSnapshot(),
cameraSnapshots: this.cameraSnapshots.getStateSnapshot(), cameraSnapshots: this.cameraSnapshots.getStateSnapshot(),
canvas3d: { canvas3d: {
camera: this.plugin.canvas3d.camera.getSnapshot(), camera: this.plugin.canvas3d.camera.getSnapshot(),
...@@ -62,6 +63,9 @@ class PluginState { ...@@ -62,6 +63,9 @@ class PluginState {
if (snapshot.canvas3d.camera) this.plugin.canvas3d.camera.setState(snapshot.canvas3d.camera); if (snapshot.canvas3d.camera) this.plugin.canvas3d.camera.setState(snapshot.canvas3d.camera);
} }
this.plugin.canvas3d.requestDraw(true); this.plugin.canvas3d.requestDraw(true);
if (snapshot.animation) {
this.animation.setSnapshot(snapshot.animation);
}
} }
dispose() { dispose() {
...@@ -94,6 +98,7 @@ namespace PluginState { ...@@ -94,6 +98,7 @@ namespace PluginState {
export interface Snapshot { export interface Snapshot {
data?: State.Snapshot, data?: State.Snapshot,
behaviour?: State.Snapshot, behaviour?: State.Snapshot,
animation?: PluginAnimationManager.Snapshot,
cameraSnapshots?: CameraSnapshotManager.StateSnapshot, cameraSnapshots?: CameraSnapshotManager.StateSnapshot,
canvas3d?: { canvas3d?: {
camera?: Camera.Snapshot, camera?: Camera.Snapshot,
......
...@@ -82,7 +82,7 @@ class PluginAnimationManager extends PluginComponent<PluginAnimationManager.Stat ...@@ -82,7 +82,7 @@ class PluginAnimationManager extends PluginComponent<PluginAnimationManager.Stat
this.triggerUpdate(); this.triggerUpdate();
} }
animate = async (t: number) => { private animate = async (t: number) => {
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,
...@@ -100,6 +100,38 @@ class PluginAnimationManager extends PluginComponent<PluginAnimationManager.Stat ...@@ -100,6 +100,38 @@ class PluginAnimationManager extends PluginComponent<PluginAnimationManager.Stat
} }
} }
getSnapshot(): PluginAnimationManager.Snapshot {
if (!this.current) return { state: this.latestState };
return {
state: this.latestState,
current: {
paramValues: this._current.paramValues,
state: this._current.anim.stateSerialization ? this._current.anim.stateSerialization.toJSON(this._current.state) : this._current.state
}
};
}
setSnapshot(snapshot: PluginAnimationManager.Snapshot) {
this.updateState({ animationState: snapshot.state.animationState });
this.updateParams(snapshot.state.params);
if (snapshot.current) {
this.current.paramValues = snapshot.current.paramValues;
this.current.state = this._current.anim.stateSerialization
? this._current.anim.stateSerialization.fromJSON(snapshot.current.state)
: snapshot.current.state;
this.triggerUpdate();
if (this.latestState.animationState === 'playing') this.resume();
}
}
private resume() {
this._current.lastTime = 0;
this._current.startedTime = -1;
requestAnimationFrame(this.animate);
}
constructor(ctx: PluginContext) { constructor(ctx: PluginContext) {
super(ctx, { params: { current: '' }, animationState: 'stopped' }); super(ctx, { params: { current: '' }, animationState: 'stopped' });
} }
...@@ -119,4 +151,12 @@ namespace PluginAnimationManager { ...@@ -119,4 +151,12 @@ namespace PluginAnimationManager {
params: { current: string }, params: { current: string },
animationState: 'stopped' | 'playing' animationState: 'stopped' | 'playing'
} }
export interface Snapshot {
state: State,
current?: {
paramValues: any,
state: any
}
}
} }
\ No newline at end of file
...@@ -23,9 +23,9 @@ interface PluginStateAnimation<P extends PD.Params = any, S = any> { ...@@ -23,9 +23,9 @@ interface PluginStateAnimation<P extends PD.Params = any, S = any> {
/** /**
* The state must be serializable to JSON. If JSON.stringify is not enough, * The state must be serializable to JSON. If JSON.stringify is not enough,
* custom serializer can be provided. * custom converted to an object that works with JSON.stringify can be provided.
*/ */
stateSerialization?: { toJSON?(state: S): any, fromJSON?(data: any): S } stateSerialization?: { toJSON(state: S): any, fromJSON(data: any): S }
} }
namespace PluginStateAnimation { namespace PluginStateAnimation {
......
...@@ -62,8 +62,8 @@ class Layout extends PluginComponent { ...@@ -62,8 +62,8 @@ class Layout extends PluginComponent {
{layout.showControls && this.region('right', <div className='msp-scrollable-container msp-right-controls'> {layout.showControls && this.region('right', <div className='msp-scrollable-container msp-right-controls'>
<CurrentObject /> <CurrentObject />
<Controls /> <Controls />
<CameraSnapshots />
<AnimationControls /> <AnimationControls />
<CameraSnapshots />
<StateSnapshots /> <StateSnapshots />
</div>)} </div>)}
{layout.showControls && this.region('bottom', <Log />)} {layout.showControls && this.region('bottom', <Log />)}
......
...@@ -33,8 +33,7 @@ export class AnimationControls extends PluginComponent<{ }> { ...@@ -33,8 +33,7 @@ export class AnimationControls extends PluginComponent<{ }> {
const isDisabled = anim.latestState.animationState === 'playing'; const isDisabled = anim.latestState.animationState === 'playing';
// TODO: give it its own style return <div className='msp-animation-section'>
return <div style={{ marginBottom: '10px' }}>
<div className='msp-section-header'>Animations</div> <div className='msp-section-header'>Animations</div>
<ParameterControls params={anim.getParams()} values={anim.latestState.params} onChange={this.updateParams} isDisabled={isDisabled} /> <ParameterControls params={anim.getParams()} values={anim.latestState.params} onChange={this.updateParams} isDisabled={isDisabled} />
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment