diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index cab2bb15dd9f76985c75db1a18082d7fb4bb0974..cb6992f2ddc6182bf968784a940cbc7a58c42001 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -150,9 +150,10 @@ namespace Canvas3D { export interface ClickEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, page?: Vec2, position?: Vec3 } export function fromCanvas(canvas: HTMLCanvasElement, props: Partial<Canvas3DProps> = {}, attribs: Partial<{ antialias: boolean, pixelScale: number, pickScale: number, enableWboit: boolean }> = {}) { + const antialias = (attribs.antialias ?? true) && !attribs.enableWboit; const gl = getGLContext(canvas, { alpha: true, - antialias: (attribs.antialias ?? true) && !attribs.enableWboit, + antialias, depth: true, preserveDrawingBuffer: true, premultipliedAlpha: true, @@ -197,6 +198,14 @@ namespace Canvas3D { if (isDebugMode) console.log('context restored'); }, false); + // disable postprocessing anti-aliasing if canvas anti-aliasing is enabled + if (antialias && !props.postprocessing?.antialiasing) { + props.postprocessing = { + ...DefaultCanvas3DParams.postprocessing, + antialiasing: { name: 'off', params: {} } + }; + } + return create(webgl, input, passes, props, { pixelScale }); } diff --git a/src/mol-canvas3d/passes/multi-sample.ts b/src/mol-canvas3d/passes/multi-sample.ts index 0a2e3f95f92f51ae63ee59178016f9df4cc16745..6db628cd96cc1cec14066676dabc18eea85913d6 100644 --- a/src/mol-canvas3d/passes/multi-sample.ts +++ b/src/mol-canvas3d/passes/multi-sample.ts @@ -193,7 +193,7 @@ export class MultiSamplePass { const { x, y, width, height } = camera.viewport; const sampleWeight = 1.0 / offsetList.length; - const postprocessingEnabled = PostprocessingPass.isEnabled(props.postprocessing) || props.postprocessing.antialiasing.name === 'on'; + const postprocessingEnabled = PostprocessingPass.isEnabled(props.postprocessing); if (sampleIndex === -1) { drawPass.render(renderer, camera, scene, helper, false, transparentBackground); diff --git a/src/mol-canvas3d/passes/postprocessing.ts b/src/mol-canvas3d/passes/postprocessing.ts index 91c0683e476588aa050b630e6a8af282d8d28569..5431aa2324d782a8b20c95b82d148a24f3a65205 100644 --- a/src/mol-canvas3d/passes/postprocessing.ts +++ b/src/mol-canvas3d/passes/postprocessing.ts @@ -110,7 +110,7 @@ export type PostprocessingProps = PD.Values<typeof PostprocessingParams> export class PostprocessingPass { static isEnabled(props: PostprocessingProps) { - return props.occlusion.name === 'on' || props.outline.name === 'on'; + return props.occlusion.name === 'on' || props.outline.name === 'on' || props.antialiasing.name === 'on'; } readonly target: RenderTarget @@ -146,7 +146,7 @@ export class PostprocessingPass { private updateState(camera: ICamera) { const { gl, state } = this.webgl; - state.disable(gl.SCISSOR_TEST); + state.enable(gl.SCISSOR_TEST); state.disable(gl.BLEND); state.disable(gl.DEPTH_TEST); state.depthMask(false); diff --git a/src/mol-plugin-state/transforms/representation.ts b/src/mol-plugin-state/transforms/representation.ts index 760d898f7e5633f5e9b363b9ad5b8bda9ad40ee8..d398cede578e5fc96ec5f2166aadbff1781f403e 100644 --- a/src/mol-plugin-state/transforms/representation.ts +++ b/src/mol-plugin-state/transforms/representation.ts @@ -131,7 +131,6 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ await Theme.ensureDependencies(propertyCtx, plugin.representation.structure.themes, { structure: a.data }, params); repr.setTheme(Theme.create(plugin.representation.structure.themes, { structure: a.data }, params)); - // TODO set initial state, repr.setState({}) const props = params.type.params || {}; await repr.createOrUpdate(props, a.data).runInContext(ctx); return new SO.Molecule.Structure.Representation3D({ repr, source: a }, { label: provider.label }); @@ -205,6 +204,8 @@ const UnwindStructureAssemblyRepresentation3D = PluginStateTransform.BuiltIn({ update({ a, b, newParams, oldParams }) { const structure = b.data.info as Structure; if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate; + if (a.data.repr !== b.data.source.data.repr) return StateTransformer.UpdateResult.Recreate; + if (oldParams.t === newParams.t) return StateTransformer.UpdateResult.Unchanged; const unitTransforms = b.data.state.unitTransforms!; unwindStructureAssembly(structure, unitTransforms, newParams.t); @@ -240,6 +241,8 @@ const ExplodeStructureRepresentation3D = PluginStateTransform.BuiltIn({ update({ a, b, newParams, oldParams }) { const structure = a.data.source.data; if (b.data.info !== structure.root) return StateTransformer.UpdateResult.Recreate; + if (a.data.repr !== b.data.source.data.repr) return StateTransformer.UpdateResult.Recreate; + if (oldParams.t === newParams.t) return StateTransformer.UpdateResult.Unchanged; const unitTransforms = b.data.state.unitTransforms!; explodeStructure(structure.root, unitTransforms, newParams.t); @@ -287,6 +290,8 @@ const OverpaintStructureRepresentation3DFromScript = PluginStateTransform.BuiltI const oldStructure = b.data.info as Structure; const newStructure = a.data.source.data; if (newStructure !== oldStructure) return StateTransformer.UpdateResult.Recreate; + if (a.data.repr !== b.data.source.data.repr) return StateTransformer.UpdateResult.Recreate; + const oldOverpaint = b.data.state.overpaint!; const newOverpaint = Overpaint.ofScript(newParams.layers, newStructure); if (Overpaint.areEqual(oldOverpaint, newOverpaint)) return StateTransformer.UpdateResult.Unchanged; @@ -337,6 +342,8 @@ const OverpaintStructureRepresentation3DFromBundle = PluginStateTransform.BuiltI const oldStructure = b.data.info as Structure; const newStructure = a.data.source.data; if (newStructure !== oldStructure) return StateTransformer.UpdateResult.Recreate; + if (a.data.repr !== b.data.source.data.repr) return StateTransformer.UpdateResult.Recreate; + const oldOverpaint = b.data.state.overpaint!; const newOverpaint = Overpaint.ofBundle(newParams.layers, newStructure); if (Overpaint.areEqual(oldOverpaint, newOverpaint)) return StateTransformer.UpdateResult.Unchanged; @@ -383,6 +390,8 @@ const TransparencyStructureRepresentation3DFromScript = PluginStateTransform.Bui update({ a, b, newParams, oldParams }) { const structure = b.data.info as Structure; if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate; + if (a.data.repr !== b.data.source.data.repr) return StateTransformer.UpdateResult.Recreate; + const oldTransparency = b.data.state.transparency!; const newTransparency = Transparency.ofScript(newParams.layers, structure); if (Transparency.areEqual(oldTransparency, newTransparency)) return StateTransformer.UpdateResult.Unchanged; @@ -430,6 +439,8 @@ const TransparencyStructureRepresentation3DFromBundle = PluginStateTransform.Bui update({ a, b, newParams, oldParams }) { const structure = b.data.info as Structure; if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate; + if (a.data.repr !== b.data.source.data.repr) return StateTransformer.UpdateResult.Recreate; + const oldTransparency = b.data.state.transparency!; const newTransparency = Transparency.ofBundle(newParams.layers, structure); if (Transparency.areEqual(oldTransparency, newTransparency)) return StateTransformer.UpdateResult.Unchanged; @@ -476,6 +487,8 @@ const ClippingStructureRepresentation3DFromScript = PluginStateTransform.BuiltIn update({ a, b, newParams, oldParams }) { const structure = b.data.info as Structure; if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate; + if (a.data.repr !== b.data.source.data.repr) return StateTransformer.UpdateResult.Recreate; + const oldClipping = b.data.state.clipping!; const newClipping = Clipping.ofScript(newParams.layers, structure); if (Clipping.areEqual(oldClipping, newClipping)) return StateTransformer.UpdateResult.Unchanged; @@ -523,6 +536,8 @@ const ClippingStructureRepresentation3DFromBundle = PluginStateTransform.BuiltIn update({ a, b, newParams, oldParams }) { const structure = b.data.info as Structure; if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate; + if (a.data.repr !== b.data.source.data.repr) return StateTransformer.UpdateResult.Recreate; + const oldClipping = b.data.state.clipping!; const newClipping = Clipping.ofBundle(newParams.layers, structure); if (Clipping.areEqual(oldClipping, newClipping)) return StateTransformer.UpdateResult.Unchanged; @@ -619,7 +634,6 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({ } })({ canAutoUpdate({ oldParams, newParams }) { - // TODO: allow for small molecules return oldParams.type.name === newParams.type.name; }, apply({ a, params }, plugin: PluginContext) { @@ -627,10 +641,10 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({ const propertyCtx = { runtime: ctx, assetManager: plugin.managers.asset }; const provider = plugin.representation.volume.registry.get(params.type.name); if (provider.ensureCustomProperties) await provider.ensureCustomProperties.attach(propertyCtx, a.data); - const props = params.type.params || {}; const repr = provider.factory({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.volume.themes }, provider.getParams); repr.setTheme(Theme.create(plugin.representation.volume.themes, { volume: a.data }, params)); - // TODO set initial state, repr.setState({}) + + const props = params.type.params || {}; await repr.createOrUpdate(props, a.data).runInContext(ctx); return new SO.Volume.Representation3D({ repr, source: a }, { label: provider.label, description: VolumeRepresentation3DHelpers.getDescription(props) }); }); @@ -673,7 +687,6 @@ const ShapeRepresentation3D = PluginStateTransform.BuiltIn({ return Task.create('Shape Representation', async ctx => { const props = { ...PD.getDefaultValues(a.data.params), ...params }; const repr = ShapeRepresentation(a.data.getShape, a.data.geometryUtils); - // TODO set initial state, repr.setState({}) await repr.createOrUpdate(props, a.data.data).runInContext(ctx); return new SO.Shape.Representation3D({ repr, source: a }, { label: a.data.label }); }); diff --git a/src/mol-plugin/behavior/dynamic/representation.ts b/src/mol-plugin/behavior/dynamic/representation.ts index 7816fe1621e9f24025cad55f5d6866650a2225c3..874d77c7b80b151a591c79de0a076979de003539 100644 --- a/src/mol-plugin/behavior/dynamic/representation.ts +++ b/src/mol-plugin/behavior/dynamic/representation.ts @@ -44,7 +44,7 @@ export const HighlightLoci = PluginBehavior.create({ ctor: class extends PluginBehavior.Handler<HighlightLociProps> { private lociMarkProvider = (interactionLoci: Representation.Loci, action: MarkerAction) => { if (!this.ctx.canvas3d || !this.params.mark) return; - this.ctx.canvas3d.mark({ loci: interactionLoci.loci }, action); + this.ctx.canvas3d.mark(interactionLoci, action); } register() { this.subscribeObservable(this.ctx.behaviors.interaction.hover, ({ current, buttons, modifiers }) => { @@ -57,12 +57,14 @@ export const HighlightLoci = PluginBehavior.create({ let matched = false; if (Binding.match(this.params.bindings.hoverHighlightOnly, buttons, modifiers)) { - this.ctx.managers.interactivity.lociHighlights.highlightOnly(current); + // remove repr to highlight loci everywhere on hover + this.ctx.managers.interactivity.lociHighlights.highlightOnly({ loci: current.loci }); matched = true; } if (Binding.match(this.params.bindings.hoverHighlightOnlyExtend, buttons, modifiers)) { - this.ctx.managers.interactivity.lociHighlights.highlightOnlyExtend(current); + // remove repr to highlight loci everywhere on hover + this.ctx.managers.interactivity.lociHighlights.highlightOnlyExtend({ loci: current.loci }); matched = true; }