engine.views.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import { Engine } from "../engine.js";
  2. import { Observable } from "../../Misc/observable.js";
  3. /**
  4. * Class used to define an additional view for the engine
  5. * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/multiCanvas
  6. */
  7. export class EngineView {
  8. }
  9. const _onBeforeViewRenderObservable = new Observable();
  10. const _onAfterViewRenderObservable = new Observable();
  11. Object.defineProperty(Engine.prototype, "onBeforeViewRenderObservable", {
  12. get: function () {
  13. return _onBeforeViewRenderObservable;
  14. },
  15. });
  16. Object.defineProperty(Engine.prototype, "onAfterViewRenderObservable", {
  17. get: function () {
  18. return _onAfterViewRenderObservable;
  19. },
  20. });
  21. Object.defineProperty(Engine.prototype, "inputElement", {
  22. get: function () {
  23. return this._inputElement;
  24. },
  25. set: function (value) {
  26. if (this._inputElement !== value) {
  27. this._inputElement = value;
  28. this._onEngineViewChanged?.();
  29. }
  30. },
  31. });
  32. Engine.prototype.getInputElement = function () {
  33. return this.inputElement || this.getRenderingCanvas();
  34. };
  35. Engine.prototype.registerView = function (canvas, camera, clearBeforeCopy) {
  36. if (!this.views) {
  37. this.views = [];
  38. }
  39. for (const view of this.views) {
  40. if (view.target === canvas) {
  41. return view;
  42. }
  43. }
  44. const masterCanvas = this.getRenderingCanvas();
  45. if (masterCanvas) {
  46. canvas.width = masterCanvas.width;
  47. canvas.height = masterCanvas.height;
  48. }
  49. const newView = { target: canvas, camera, clearBeforeCopy, enabled: true, id: (Math.random() * 100000).toFixed() };
  50. this.views.push(newView);
  51. if (camera && !Array.isArray(camera)) {
  52. camera.onDisposeObservable.add(() => {
  53. this.unRegisterView(canvas);
  54. });
  55. }
  56. return newView;
  57. };
  58. Engine.prototype.unRegisterView = function (canvas) {
  59. if (!this.views || this.views.length === 0) {
  60. return this;
  61. }
  62. for (const view of this.views) {
  63. if (view.target === canvas) {
  64. const index = this.views.indexOf(view);
  65. if (index !== -1) {
  66. this.views.splice(index, 1);
  67. }
  68. break;
  69. }
  70. }
  71. return this;
  72. };
  73. Engine.prototype._renderViewStep = function (view) {
  74. const canvas = view.target;
  75. const context = canvas.getContext("2d");
  76. if (!context) {
  77. return true;
  78. }
  79. const parent = this.getRenderingCanvas();
  80. _onBeforeViewRenderObservable.notifyObservers(view);
  81. const camera = view.camera;
  82. let previewCamera = null;
  83. let previewCameras = null;
  84. let scene = null;
  85. if (camera) {
  86. scene = Array.isArray(camera) ? camera[0].getScene() : camera.getScene();
  87. previewCamera = scene.activeCamera;
  88. previewCameras = scene.activeCameras;
  89. this.activeView = view;
  90. if (Array.isArray(camera)) {
  91. scene.activeCameras = camera;
  92. }
  93. else {
  94. scene.activeCamera = camera;
  95. scene.activeCameras = null;
  96. }
  97. }
  98. if (view.customResize) {
  99. view.customResize(canvas);
  100. }
  101. else {
  102. // Set sizes
  103. const width = Math.floor(canvas.clientWidth / this._hardwareScalingLevel);
  104. const height = Math.floor(canvas.clientHeight / this._hardwareScalingLevel);
  105. const dimsChanged = width !== canvas.width || parent.width !== canvas.width || height !== canvas.height || parent.height !== canvas.height;
  106. if (canvas.clientWidth && canvas.clientHeight && dimsChanged) {
  107. canvas.width = width;
  108. canvas.height = height;
  109. this.setSize(width, height);
  110. }
  111. }
  112. if (!parent.width || !parent.height) {
  113. return false;
  114. }
  115. // Render the frame
  116. this._renderFrame();
  117. this.flushFramebuffer();
  118. // Copy to target
  119. if (view.clearBeforeCopy) {
  120. context.clearRect(0, 0, parent.width, parent.height);
  121. }
  122. context.drawImage(parent, 0, 0);
  123. // Restore
  124. if (scene) {
  125. scene.activeCameras = previewCameras;
  126. scene.activeCamera = previewCamera;
  127. }
  128. _onAfterViewRenderObservable.notifyObservers(view);
  129. return true;
  130. };
  131. Engine.prototype._renderViews = function () {
  132. if (!this.views || this.views.length === 0) {
  133. return false;
  134. }
  135. const parent = this.getRenderingCanvas();
  136. if (!parent) {
  137. return false;
  138. }
  139. let inputElementView;
  140. for (const view of this.views) {
  141. if (!view.enabled) {
  142. continue;
  143. }
  144. const canvas = view.target;
  145. // Always render the view correspondent to the inputElement for last
  146. if (canvas === this.inputElement) {
  147. inputElementView = view;
  148. continue;
  149. }
  150. if (!this._renderViewStep(view)) {
  151. return false;
  152. }
  153. }
  154. if (inputElementView) {
  155. if (!this._renderViewStep(inputElementView)) {
  156. return false;
  157. }
  158. }
  159. this.activeView = null;
  160. return true;
  161. };
  162. //# sourceMappingURL=engine.views.js.map