simple-settings.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /**
  2. * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. * @author David Sehnal <david.sehnal@gmail.com>
  6. */
  7. import { produce } from 'immer';
  8. import { Canvas3DParams, Canvas3DProps } from '../../mol-canvas3d/canvas3d';
  9. import { PluginCommands } from '../../mol-plugin/commands';
  10. import { StateTransform } from '../../mol-state';
  11. import { Color } from '../../mol-util/color';
  12. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  13. import { ParamMapping } from '../../mol-util/param-mapping';
  14. import { Mutable } from '../../mol-util/type-helpers';
  15. import { PluginUIComponent } from '../base';
  16. import { PluginUIContext } from '../context';
  17. import { ParameterMappingControl } from '../controls/parameters';
  18. import { ViewportHelpContent } from './help';
  19. export class SimpleSettingsControl extends PluginUIComponent {
  20. componentDidMount() {
  21. this.subscribe(this.plugin.events.canvas3d.settingsUpdated, () => this.forceUpdate());
  22. this.subscribe(this.plugin.canvas3d!.camera.stateChanged, state => {
  23. if (state.radiusMax !== undefined || state.radius !== undefined) {
  24. this.forceUpdate();
  25. }
  26. });
  27. }
  28. render() {
  29. if (!this.plugin.canvas3d) return null;
  30. return <>
  31. <ParameterMappingControl mapping={SimpleSettingsMapping} />
  32. <ViewportHelpContent />
  33. </>;
  34. }
  35. }
  36. const LayoutOptions = {
  37. 'sequence': 'Sequence',
  38. 'log': 'Log',
  39. 'left': 'Left Panel'
  40. };
  41. type LayoutOptions = keyof typeof LayoutOptions
  42. const SimpleSettingsParams = {
  43. animate: Canvas3DParams.trackball.params.animate,
  44. camera: Canvas3DParams.camera,
  45. background: PD.Group({
  46. color: PD.Color(Color(0xFCFBF9), { label: 'Background', description: 'Custom background color' }),
  47. transparent: PD.Boolean(false)
  48. }, { pivot: 'color' }),
  49. lighting: PD.Group({
  50. occlusion: Canvas3DParams.postprocessing.params.occlusion,
  51. outline: Canvas3DParams.postprocessing.params.outline,
  52. fog: Canvas3DParams.cameraFog,
  53. }, { isFlat: true }),
  54. clipping: PD.Group<any>({
  55. ...Canvas3DParams.cameraClipping.params,
  56. }, { pivot: 'radius' }),
  57. layout: PD.MultiSelect([] as LayoutOptions[], PD.objectToOptions(LayoutOptions)),
  58. };
  59. type SimpleSettingsParams = typeof SimpleSettingsParams
  60. const SimpleSettingsMapping = ParamMapping({
  61. params: (ctx: PluginUIContext) => {
  62. const params = PD.clone(SimpleSettingsParams);
  63. const controls = ctx.spec.components?.controls;
  64. if (controls) {
  65. const options: [LayoutOptions, string][] = [];
  66. if (controls.top !== 'none') options.push(['sequence', LayoutOptions.sequence]);
  67. if (controls.bottom !== 'none') options.push(['log', LayoutOptions.log]);
  68. if (controls.left !== 'none') options.push(['left', LayoutOptions.left]);
  69. params.layout.options = options;
  70. }
  71. return params;
  72. },
  73. target(ctx: PluginUIContext) {
  74. const c = ctx.spec.components?.controls;
  75. const r = ctx.layout.state.regionState;
  76. const layout: SimpleSettingsParams['layout']['defaultValue'] = [];
  77. if (r.top !== 'hidden' && (!c || c.top !== 'none')) layout.push('sequence');
  78. if (r.bottom !== 'hidden' && (!c || c.bottom !== 'none')) layout.push('log');
  79. if (r.left !== 'hidden' && (!c || c.left !== 'none')) layout.push('left');
  80. return { canvas: ctx.canvas3d?.props!, layout };
  81. }
  82. })({
  83. values(props, ctx) {
  84. const { canvas } = props;
  85. const renderer = canvas.renderer;
  86. return {
  87. layout: props.layout,
  88. animate: canvas.trackball.animate,
  89. camera: canvas.camera,
  90. background: {
  91. color: renderer.backgroundColor,
  92. transparent: canvas.transparentBackground
  93. },
  94. lighting: {
  95. occlusion: canvas.postprocessing.occlusion,
  96. outline: canvas.postprocessing.outline,
  97. fog: canvas.cameraFog,
  98. },
  99. clipping: {
  100. ...canvas.cameraClipping,
  101. }
  102. };
  103. },
  104. update(s, props) {
  105. const canvas = props.canvas as Mutable<Canvas3DProps>;
  106. canvas.trackball.animate = s.animate;
  107. canvas.camera = s.camera;
  108. canvas.transparentBackground = s.background.transparent;
  109. canvas.renderer.backgroundColor = s.background.color;
  110. canvas.postprocessing.occlusion = s.lighting.occlusion;
  111. canvas.postprocessing.outline = s.lighting.outline;
  112. canvas.cameraFog = s.lighting.fog;
  113. canvas.cameraClipping = {
  114. radius: s.clipping.radius,
  115. far: s.clipping.far,
  116. };
  117. props.layout = s.layout;
  118. },
  119. async apply(props, ctx) {
  120. await PluginCommands.Canvas3D.SetSettings(ctx, { settings: props.canvas });
  121. const hideLeft = props.layout.indexOf('left') < 0;
  122. const state = produce(ctx.layout.state, s => {
  123. s.regionState.top = props.layout.indexOf('sequence') >= 0 ? 'full' : 'hidden';
  124. s.regionState.bottom = props.layout.indexOf('log') >= 0 ? 'full' : 'hidden';
  125. s.regionState.left = hideLeft ? 'hidden' : ctx.behaviors.layout.leftPanelTabName.value === 'none' ? 'collapsed' : 'full';
  126. });
  127. await PluginCommands.Layout.Update(ctx, { state });
  128. if (hideLeft) {
  129. PluginCommands.State.SetCurrentObject(ctx, { state: ctx.state.data, ref: StateTransform.RootRef });
  130. }
  131. }
  132. });