Skip to content
Snippets Groups Projects
Commit ed75fe54 authored by Alexander Rose's avatar Alexander Rose
Browse files

structure animation tweaks

parent 8c0a3a4a
Branches
Tags
No related merge requests found
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
...@@ -11,74 +11,93 @@ import { degToRad } from 'mol-math/misc'; ...@@ -11,74 +11,93 @@ import { degToRad } from 'mol-math/misc';
import { Mat4, Vec3 } from 'mol-math/linear-algebra'; import { Mat4, Vec3 } from 'mol-math/linear-algebra';
import { PluginStateObject as SO, PluginStateObject } from '../../state/objects'; import { PluginStateObject as SO, PluginStateObject } from '../../state/objects';
import { StateSelection } from 'mol-state/state/selection'; import { StateSelection } from 'mol-state/state/selection';
import { StateObjectCell, State } from 'mol-state';
const StructureAnimationParams = {
rotate: PD.Boolean(false)
}
type StructureAnimationProps = PD.Values<typeof StructureAnimationParams>
function getRootStructure(root: StateObjectCell, state: State) {
let parent: StateObjectCell | undefined
while (true) {
const _parent = StateSelection.findAncestorOfType(state.tree, state.cells, root.transform.ref, [PluginStateObject.Molecule.Structure])
if (_parent) {
parent = _parent
root = _parent
} else {
break
}
}
if (!parent || !parent.obj) return
return parent.obj as PluginStateObject.Molecule.Structure
}
// TODO this is just for testing purposes // TODO this is just for testing purposes
export const Animation = PluginBehavior.create<{ play: boolean }>({ export const StructureAnimation = PluginBehavior.create<StructureAnimationProps>({
name: 'animation', name: 'structure-animation',
display: { name: 'Animation', group: 'Animation' }, display: { name: 'Structure Animation', group: 'Animation' },
ctor: class extends PluginBehavior.Handler<{ play: boolean }> { ctor: class extends PluginBehavior.Handler<StructureAnimationProps> {
private tmpMat = Mat4.identity() private tmpMat = Mat4.identity()
private rotMat = Mat4.identity() private rotMat = Mat4.identity()
private transMat = Mat4.identity() private transMat = Mat4.identity()
private animMat = Mat4.identity() private rotAnimMat = Mat4.identity()
private transVec = Vec3.zero() private transVec = Vec3.zero()
private rotVec = Vec3.create(0, 1, 0) private rotVec = Vec3.create(0, 1, 0)
private animHandle = -1
constructor(protected ctx: PluginContext, protected params: { play: boolean }) { private rotateAnimHandle = -1
constructor(protected ctx: PluginContext, protected params: StructureAnimationProps) {
super(ctx, params) super(ctx, params)
this.update(params) this.update(params)
} }
animate(play: boolean) { rotate(play: boolean) {
if (play) { if (play) {
const state = this.ctx.state.dataState const state = this.ctx.state.dataState
const reprs = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Representation3D)); const reprs = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Representation3D));
const anim = (t: number) => { const rotate = (t: number) => {
const rad = degToRad((t / 10) % 360) const rad = degToRad((t / 10) % 360)
Mat4.rotate(this.rotMat, this.tmpMat, rad, this.rotVec) Mat4.rotate(this.rotMat, this.tmpMat, rad, this.rotVec)
for (const r of reprs) { for (const r of reprs) {
if (!SO.isRepresentation3D(r.obj)) return if (!SO.isRepresentation3D(r.obj)) return
const parent = StateSelection.findAncestorOfType(state.tree, state.cells, r.transform.ref, [PluginStateObject.Molecule.Structure]) const structure = getRootStructure(r, state)
if (!parent || !parent.obj) continue if (!structure) continue
const structure = parent.obj as PluginStateObject.Molecule.Structure
Vec3.negate(this.transVec, Vec3.copy(this.transVec, structure.data.boundary.sphere.center)) Vec3.negate(this.transVec, Vec3.copy(this.transVec, structure.data.boundary.sphere.center))
Mat4.fromTranslation(this.transMat, this.transVec) Mat4.fromTranslation(this.transMat, this.transVec)
Mat4.mul(this.animMat, this.rotMat, this.transMat) Mat4.mul(this.rotAnimMat, this.rotMat, this.transMat)
Vec3.copy(this.transVec, structure.data.boundary.sphere.center) Vec3.copy(this.transVec, structure.data.boundary.sphere.center)
Mat4.fromTranslation(this.transMat, this.transVec) Mat4.fromTranslation(this.transMat, this.transVec)
Mat4.mul(this.animMat, this.transMat, this.animMat) Mat4.mul(this.rotAnimMat, this.transMat, this.rotAnimMat)
r.obj.data.setState({ transform: this.animMat }) r.obj.data.setState({ transform: this.rotAnimMat })
this.ctx.canvas3d.add(r.obj.data) this.ctx.canvas3d.add(r.obj.data)
this.ctx.canvas3d.requestDraw(true) this.ctx.canvas3d.requestDraw(true)
} }
this.animHandle = requestAnimationFrame(anim) this.rotateAnimHandle = requestAnimationFrame(rotate)
} }
this.animHandle = requestAnimationFrame(anim) this.rotateAnimHandle = requestAnimationFrame(rotate)
} else { } else {
cancelAnimationFrame(this.animHandle) cancelAnimationFrame(this.rotateAnimHandle)
} }
} }
register(): void { } register(): void { }
update(p: { play: boolean }) { update(p: StructureAnimationProps) {
let updated = this.params.play !== p.play let updated = this.params.rotate !== p.rotate
this.params.play = p.play this.params.rotate = p.rotate
if (updated) { if (updated) {
this.animate(this.params.play) this.rotate(this.params.rotate)
} }
return updated; return updated;
} }
unregister() { unregister() {
cancelAnimationFrame(this.animHandle) cancelAnimationFrame(this.rotateAnimHandle)
} }
}, },
params: () => ({ params: () => StructureAnimationParams
play: PD.Boolean(false)
})
}); });
\ No newline at end of file
...@@ -37,7 +37,7 @@ const DefaultSpec: PluginSpec = { ...@@ -37,7 +37,7 @@ const DefaultSpec: PluginSpec = {
PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci), PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci),
PluginSpec.Behavior(PluginBehaviors.Representation.DefaultLociLabelProvider), PluginSpec.Behavior(PluginBehaviors.Representation.DefaultLociLabelProvider),
PluginSpec.Behavior(PluginBehaviors.Camera.FocusLociOnSelect, { minRadius: 20, extraRadius: 4 }), PluginSpec.Behavior(PluginBehaviors.Camera.FocusLociOnSelect, { minRadius: 20, extraRadius: 4 }),
PluginSpec.Behavior(PluginBehaviors.Animation.Animation, { play: false }), PluginSpec.Behavior(PluginBehaviors.Animation.StructureAnimation, { rotate: false }),
PluginSpec.Behavior(PluginBehaviors.CustomProps.PDBeStructureQualityReport, { autoAttach: true }), PluginSpec.Behavior(PluginBehaviors.CustomProps.PDBeStructureQualityReport, { autoAttach: true }),
PluginSpec.Behavior(PluginBehaviors.CustomProps.RCSBAssemblySymmetry, { autoAttach: true }), PluginSpec.Behavior(PluginBehaviors.CustomProps.RCSBAssemblySymmetry, { autoAttach: true }),
] ]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment