Source: ui/widget/sound-mixer.js

  1. import { Form } from './form.js';
  2. import { FormArea } from './form-area.js';
  3. import { HorizontalSliderPanel } from './slider-panel.js';
  4. import { MediaStreams } from '../../core/media-streams.js';
  5. class MixerForm extends Form {
  6. constructor(scene) {
  7. super();
  8. this.scene = scene;
  9. this.smallFontSize = this.fontSize / 2;
  10. this.smallHeightInPixels = this.heightInPixels / 2;
  11. this.textureHeight = null;
  12. this.textureWidth = null;
  13. }
  14. init(sounds = {
  15. avatar: [],
  16. spatial: [],
  17. other: []
  18. }) {
  19. this.createPanel();
  20. this.grid = new BABYLON.GUI.Grid();
  21. this.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  22. this.grid.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
  23. this.grid.paddingLeft = 10;
  24. this.grid.paddingTop = 10;
  25. this.grid.addColumnDefinition(0.5);
  26. this.grid.addColumnDefinition(0.5);
  27. this.grid.addRowDefinition(this.heightInPixels, true);
  28. this.grid.addControl(this.textBlock("Main volume"), 0, 0);
  29. this.grid.addControl(this.slider(volume => this.scene.mainSoundTrack.setVolume(volume / 100), this.scene.mainSoundTrack._outputAudioNode.gain.value * 100, this.fontSize * 0.7), 0, 1);
  30. this.grid.addRowDefinition(this.heightInPixels, true);
  31. this.grid.addControl(this.textBlock("Avatars"), this.grid.rowCount, 0);
  32. let distanceSlider = new HorizontalSliderPanel("Range", 10, 1000, MediaStreams.soundProperties.maxDistance);
  33. distanceSlider.panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
  34. distanceSlider.header.width = "110px";
  35. distanceSlider.setDecimals(0);
  36. distanceSlider.slider.onValueChangedObservable.add(value => MediaStreams.soundProperties.maxDistance = value);
  37. this.grid.addControl(distanceSlider.panel, 1, 1);
  38. this.showSounds(sounds.avatar);
  39. this.grid.addRowDefinition(this.heightInPixels, true);
  40. this.grid.addControl(this.textBlock("Spatial"), this.grid.rowCount, 0);
  41. this.showSounds(sounds.spatial);
  42. this.grid.addRowDefinition(this.heightInPixels, true);
  43. this.grid.addControl(this.textBlock("Other"), this.grid.rowCount, 0);
  44. this.showSounds(sounds.other);
  45. this.addControl(this.grid);
  46. // CHECKME: HUD?
  47. this.textureWidth = 768;
  48. this.textureHeight = this.heightInPixels * 4 + this.smallHeightInPixels * (Math.max(this.grid.rowCount - 3, 1));
  49. //let texture = VRSPACEUI.hud.addForm(this, 768, this.heightInPixels * 4 + this.smallHeightInPixels * (Math.max(this.grid.rowCount - 3, 1)));
  50. //texture.background = "#808080";
  51. //VRSPACEUI.hud.addForm(this,512,512);
  52. }
  53. showSounds(list) {
  54. let fontSize = this.fontSize;
  55. let heightInPixels = this.heightInPixels;
  56. this.fontSize = this.smallFontSize;
  57. this.heightInPixels = this.smallHeightInPixels;
  58. for (let row = this.grid.rowCount, i = 0; i < list.length; row++, i++) {
  59. let sound = list[i];
  60. this.grid.addRowDefinition(this.heightInPixels, true);
  61. // CHECKME: sound names?
  62. this.grid.addControl(this.textBlock(sound.name), row, 0);
  63. this.grid.addControl(this.slider(value => sound.setVolume(value / 100), sound.getVolume() * 100), row, 1);
  64. }
  65. this.fontSize = fontSize;
  66. this.heightInPixels = heightInPixels;
  67. }
  68. slider(callback, value = 100, fontSize = this.smallFontSize / 2) {
  69. let sliderPanel = new HorizontalSliderPanel("", 1, 100, value);
  70. sliderPanel.panel.height = "100%";
  71. sliderPanel.slider.height = "50%";
  72. sliderPanel.header.height = "50%";
  73. sliderPanel.header.fontSizeInPixels = fontSize;
  74. //sliderPanel.panel.isVertical = true;
  75. sliderPanel.setDecimals(0);
  76. sliderPanel.slider.onValueChangedObservable.add(value => callback(value));
  77. return sliderPanel.panel;
  78. }
  79. }
  80. /**
  81. * Sound mixer component.
  82. */
  83. export class SoundMixer {
  84. static instance = null;
  85. constructor(scene) {
  86. if (SoundMixer.instance) {
  87. throw "there can be only one";
  88. }
  89. this.scene = scene;
  90. this.form = null;
  91. }
  92. init() {
  93. this.sounds = {
  94. avatar: [],
  95. spatial: [],
  96. other: []
  97. };
  98. this.scene.mainSoundTrack.soundCollection.forEach(sound => {
  99. if (sound._connectedTransformNode) {
  100. if (typeof sound._connectedTransformNode.VRObject != "undefined") {
  101. // sound stream of an avatar
  102. console.log("Avatar sound: " + sound.name, sound);
  103. this.sounds.avatar.push(sound);
  104. } else {
  105. // spatial sound not managed by the server
  106. console.log("Scene sound: " + sound.name, sound);
  107. this.sounds.spatial.push(sound);
  108. }
  109. } else {
  110. // not a spatial sound
  111. console.log("Other sound: " + sound.name, sound);
  112. this.sounds.other.push(sound);
  113. }
  114. });
  115. console.log(this.sounds);
  116. }
  117. show() {
  118. if (this.form) {
  119. this.form.dispose();
  120. this.form = null;
  121. }
  122. this.init();
  123. let form = new MixerForm(this.scene);
  124. form.init(this.sounds);
  125. this.form = new FormArea(this.scene, form);
  126. this.form.size = .5;
  127. this.form.show(form.textureWidth, form.textureHeight);
  128. this.form.attachToHud();
  129. this.form.detach(2);
  130. this.form.group.billboardMode = BABYLON.Mesh.BILLBOARDMODE_Y;
  131. }
  132. dispose() {
  133. if (this.form) {
  134. this.form.dispose();
  135. this.form = null;
  136. }
  137. SoundMixer.instance = null;
  138. }
  139. /**
  140. * Returns the sound mixer instance, creates a new one if needed.
  141. * @returns { SoundMixer }
  142. */
  143. static getInstance(scene) {
  144. if (!SoundMixer.instance) {
  145. SoundMixer.instance = new SoundMixer(scene);
  146. }
  147. return SoundMixer.instance;
  148. }
  149. }