threepipe
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

util-buttons.ts 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import {AViewerPlugin, Class, createDiv, downloadBlob, FullScreenPlugin, ThreeViewer} from 'threepipe'
  2. import {autoRotateCC, collapse, download, expand, resetSettings, snapshot, trash} from './icons'
  3. import tippy, {createSingleton} from 'tippy.js'
  4. export function createUtilButtons(viewer: ThreeViewer, allPlugins: Class<AViewerPlugin>[]) {
  5. return [
  6. {
  7. id: 'reset-settings',
  8. icon: resetSettings,
  9. tooltip: 'Reset All Settings',
  10. onclick: async() => {
  11. if (!await viewer.dialog.confirm('Reset settings: Are you sure you want to reset all plugin settings?')) return
  12. const ps = allPlugins.map(p => viewer.getPlugin(p)!)
  13. for (const p of ps) {
  14. await (p as any)?.resetDefaults?.() // set in TweakpaneUiPlugin
  15. }
  16. },
  17. },
  18. {
  19. id: 'clear-scene',
  20. icon: trash,
  21. tooltip: 'Clear Scene',
  22. onclick: async() => {
  23. if (!await viewer.dialog.confirm('Clear scene: Are you sure you want to clear the scene?')) return
  24. viewer.scene.disposeSceneModels()
  25. },
  26. },
  27. // {
  28. // id: 'fit-scene',
  29. // icon: focus,
  30. // tooltip: 'Fit Object/Scene',
  31. // onclick: async() => {
  32. // await viewer.fitToView(viewer.getPlugin(PickingPlugin)?.getSelectedObject())
  33. // },
  34. // },
  35. // {
  36. // id: 'loop-cam-views',
  37. // icon: loopCamViews,
  38. // tooltip: 'Loop Camera Views',
  39. // toggle: true,
  40. // onclick: async() => {
  41. // if (!viewer.getPlugin(CameraViewPlugin)) return
  42. // viewer.getPlugin(CameraViewPlugin)!.viewLooping = !viewer.getPlugin(CameraViewPlugin)!.viewLooping
  43. // },
  44. // },
  45. // {
  46. // id: 'play-gltf',
  47. // icon: playIcon,
  48. // tooltip: 'GLTF Animations',
  49. // toggle: true,
  50. // onclick: async() => {
  51. // viewer.getPlugin(GLTFAnimationPlugin)?.playPauseAnimation()
  52. // },
  53. // },
  54. {
  55. id: 'auto-rotate-cc',
  56. icon: autoRotateCC,
  57. tooltip: 'Auto rotate',
  58. toggle: true,
  59. onclick: async() => {
  60. const controls = viewer.scene.mainCamera.controls
  61. if (controls?.autoRotate === undefined) return
  62. controls.autoRotate = !controls.autoRotate
  63. },
  64. },
  65. {
  66. id: 'snapshot',
  67. icon: snapshot,
  68. tooltip: 'Capture Snapshot',
  69. onclick: async() => {
  70. const image = await viewer.getScreenshotBlob({mimeType: 'image/png'})
  71. image && downloadBlob(image, 'screenshot.png')
  72. // todo use this for waitForProgressive
  73. // const s = viewer.getPlugin(CanvasSnipperPlugin)
  74. // if (!s) {
  75. // viewer.console.error('CanvasSnipperPlugin not added')
  76. // return
  77. // }
  78. // await s.downloadSnapshot()
  79. },
  80. },
  81. {
  82. id: 'glb-export',
  83. icon: download,
  84. tooltip: 'Export GLB',
  85. onclick: async() => {
  86. const glb = await viewer.exportScene()
  87. glb && downloadBlob(glb, 'scene.glb')
  88. // todo use this for all export settings
  89. // const exporter = viewer.getPlugin(AssetExporterPlugin)
  90. // if (!exporter) {
  91. // viewer.console.error('AssetExporterPlugin not added')
  92. // return
  93. // }
  94. // await exporter?.downloadSceneGlb()
  95. },
  96. },
  97. ]
  98. }
  99. export function setupFullscreenButton(viewer: ThreeViewer) {
  100. const fullScreenButton = createDiv({
  101. innerHTML: expand,
  102. id: 'fsToggle',
  103. classList: ['round-button'],
  104. addToBody: false,
  105. })
  106. fullScreenButton.dataset.tippyContent = 'Full-Screen'
  107. viewer.getPlugin(FullScreenPlugin)?.addEventListener('enter', () => {
  108. fullScreenButton.innerHTML = collapse
  109. fullScreenButton.dataset.tippyContent = 'Exit Full-Screen'
  110. })
  111. viewer.getPlugin(FullScreenPlugin)?.addEventListener('exit', () => {
  112. fullScreenButton.innerHTML = expand
  113. fullScreenButton.dataset.tippyContent = 'Full-Screen'
  114. })
  115. fullScreenButton.onclick = () => {
  116. viewer.getPlugin(FullScreenPlugin)?.toggle(viewer.container)
  117. }
  118. viewer.container.appendChild(fullScreenButton)
  119. tippy(fullScreenButton, {
  120. placement: 'left',
  121. })
  122. }
  123. export function setupUtilButtonsBar(viewer: ThreeViewer, allPlugins: Class<AViewerPlugin>[]) {
  124. const utilButtonsContainer = createDiv({
  125. classList: ['button-bar', 'util-buttons-container'],
  126. addToBody: false,
  127. })
  128. viewer.container.appendChild(utilButtonsContainer)
  129. const utilButtons = createUtilButtons(viewer, allPlugins)
  130. for (const utilButton of utilButtons) {
  131. const button = createDiv({
  132. innerHTML: utilButton.icon,
  133. id: utilButton.id,
  134. classList: ['button-bar-button', 'util-button'],
  135. addToBody: false,
  136. })
  137. button.dataset.tippyContent = utilButton.tooltip
  138. button.onclick = () => {
  139. if (utilButton.toggle) {
  140. button.classList.toggle('button-bar-selected-box')
  141. }
  142. utilButton.onclick()
  143. }
  144. utilButtonsContainer.appendChild(button)
  145. }
  146. createSingleton(tippy('.util-button'), {
  147. moveTransition: 'transform 0.2s ease-out',
  148. placement: 'top',
  149. })
  150. }