simple-settings.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /**
  2. * Copyright (c) 2019-2020 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. spin: PD.Group({
  44. spin: Canvas3DParams.trackball.params.spin,
  45. speed: Canvas3DParams.trackball.params.spinSpeed
  46. }, { pivot: 'spin' }),
  47. camera: Canvas3DParams.camera,
  48. background: PD.Group({
  49. color: PD.Color(Color(0xFCFBF9), { label: 'Background', description: 'Custom background color' }),
  50. transparent: PD.Boolean(false)
  51. }, { pivot: 'color' }),
  52. lighting: PD.Group({
  53. occlusion: Canvas3DParams.postprocessing.params.occlusion,
  54. outline: Canvas3DParams.postprocessing.params.outline,
  55. fog: Canvas3DParams.cameraFog,
  56. }, { isFlat: true }),
  57. clipping: PD.Group<any>({
  58. ...Canvas3DParams.cameraClipping.params,
  59. ...(Canvas3DParams.renderer.params.clip as any).params as any
  60. }, { pivot: 'radius' }),
  61. layout: PD.MultiSelect([] as LayoutOptions[], PD.objectToOptions(LayoutOptions)),
  62. };
  63. type SimpleSettingsParams = typeof SimpleSettingsParams
  64. const SimpleSettingsMapping = ParamMapping({
  65. params: (ctx: PluginUIContext) => {
  66. const params = PD.clone(SimpleSettingsParams);
  67. const controls = ctx.spec.components?.controls;
  68. if (controls) {
  69. const options: [LayoutOptions, string][] = [];
  70. if (controls.top !== 'none') options.push(['sequence', LayoutOptions.sequence]);
  71. if (controls.bottom !== 'none') options.push(['log', LayoutOptions.log]);
  72. if (controls.left !== 'none') options.push(['left', LayoutOptions.left]);
  73. params.layout.options = options;
  74. }
  75. return params;
  76. },
  77. target(ctx: PluginUIContext) {
  78. const c = ctx.spec.components?.controls;
  79. const r = ctx.layout.state.regionState;
  80. const layout: SimpleSettingsParams['layout']['defaultValue'] = [];
  81. if (r.top !== 'hidden' && (!c || c.top !== 'none')) layout.push('sequence');
  82. if (r.bottom !== 'hidden' && (!c || c.bottom !== 'none')) layout.push('log');
  83. if (r.left !== 'hidden' && (!c || c.left !== 'none')) layout.push('left');
  84. return { canvas: ctx.canvas3d?.props!, layout };
  85. }
  86. })({
  87. values(props, ctx) {
  88. const { canvas } = props;
  89. const renderer = canvas.renderer;
  90. return {
  91. layout: props.layout,
  92. spin: { spin: !!canvas.trackball.spin, speed: canvas.trackball.spinSpeed },
  93. camera: canvas.camera,
  94. background: {
  95. color: renderer.backgroundColor,
  96. transparent: canvas.transparentBackground
  97. },
  98. lighting: {
  99. occlusion: canvas.postprocessing.occlusion,
  100. outline: canvas.postprocessing.outline,
  101. fog: canvas.cameraFog,
  102. },
  103. clipping: {
  104. ...canvas.cameraClipping,
  105. ...canvas.renderer.clip
  106. }
  107. };
  108. },
  109. update(s, props) {
  110. const canvas = props.canvas as Mutable<Canvas3DProps>;
  111. canvas.trackball.spin = s.spin.spin;
  112. canvas.trackball.spinSpeed = s.spin.speed;
  113. canvas.camera = s.camera;
  114. canvas.transparentBackground = s.background.transparent;
  115. canvas.renderer.backgroundColor = s.background.color;
  116. canvas.postprocessing.occlusion = s.lighting.occlusion;
  117. canvas.postprocessing.outline = s.lighting.outline;
  118. canvas.cameraFog = s.lighting.fog;
  119. canvas.cameraClipping = {
  120. radius: s.clipping.radius,
  121. far: s.clipping.far,
  122. };
  123. canvas.renderer.clip = {
  124. variant: s.clipping.variant,
  125. objects: s.clipping.objects,
  126. };
  127. props.layout = s.layout;
  128. },
  129. async apply(props, ctx) {
  130. await PluginCommands.Canvas3D.SetSettings(ctx, { settings: props.canvas });
  131. const hideLeft = props.layout.indexOf('left') < 0;
  132. const state = produce(ctx.layout.state, s => {
  133. s.regionState.top = props.layout.indexOf('sequence') >= 0 ? 'full' : 'hidden';
  134. s.regionState.bottom = props.layout.indexOf('log') >= 0 ? 'full' : 'hidden';
  135. s.regionState.left = hideLeft ? 'hidden' : ctx.behaviors.layout.leftPanelTabName.value === 'none' ? 'collapsed' : 'full';
  136. });
  137. await PluginCommands.Layout.Update(ctx, { state });
  138. if (hideLeft) {
  139. PluginCommands.State.SetCurrentObject(ctx, { state: ctx.state.data, ref: StateTransform.RootRef });
  140. }
  141. }
  142. });