sandbox.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import * as React from "react";
  2. import * as ReactDOM from "react-dom";
  3. import { GlobalState } from './globalState';
  4. import { RenderingZone } from './components/renderingZone';
  5. import { Footer } from './components/footer';
  6. import { EnvironmentTools } from './tools/environmentTools';
  7. import { Vector3 } from 'babylonjs/Maths/math.vector';
  8. require("./scss/main.scss");
  9. var fullScreenLogo = require("./img/logo-fullscreen.svg");
  10. interface ISandboxProps {
  11. }
  12. export class Sandbox extends React.Component<ISandboxProps, { isFooterVisible: boolean, errorMessage: string }> {
  13. private _globalState: GlobalState;
  14. private _assetUrl?: string;
  15. private _autoRotate?: boolean;
  16. private _cameraPosition?: Vector3;
  17. private _logoRef: React.RefObject<HTMLImageElement>;
  18. private _dropTextRef: React.RefObject<HTMLDivElement>;
  19. private _clickInterceptorRef: React.RefObject<HTMLDivElement>;
  20. public constructor(props: ISandboxProps) {
  21. super(props);
  22. this._globalState = new GlobalState();
  23. this._logoRef = React.createRef();
  24. this._dropTextRef = React.createRef();
  25. this._clickInterceptorRef = React.createRef();
  26. this.state = { isFooterVisible: true, errorMessage: "" };
  27. this.checkUrl();
  28. EnvironmentTools.HookWithEnvironmentChange(this._globalState);
  29. // Events
  30. this._globalState.onSceneLoaded.add((info) => {
  31. document.title = "Babylon.js - " + info.filename;
  32. this._globalState.currentScene = info.scene;
  33. if (this._globalState.currentScene.meshes.length === 0 && this._globalState.currentScene.clearColor.r === 1 && this._globalState.currentScene.clearColor.g === 0 && this._globalState.currentScene.clearColor.b === 0) {
  34. this._logoRef.current!.className = "";
  35. }
  36. else {
  37. this._logoRef.current!.className = "hidden";
  38. this._dropTextRef.current!.className = "hidden";
  39. }
  40. });
  41. this._globalState.onError.add((error) => {
  42. if (error.scene) {
  43. this._globalState.showDebugLayer();
  44. }
  45. if (error.message) {
  46. this.setState({ errorMessage: error.message });
  47. }
  48. });
  49. this._globalState.onRequestClickInterceptor.add(() => {
  50. let div = this._clickInterceptorRef.current!;
  51. if (div.classList.contains("hidden")) {
  52. div.classList.remove("hidden");
  53. } else {
  54. div.classList.add("hidden");
  55. }
  56. });
  57. // Keyboard
  58. window.addEventListener("keydown", (event: KeyboardEvent) => {
  59. // Press space to toggle footer
  60. if (event.keyCode === 32 && event.target && (event.target as HTMLElement).nodeName !== "INPUT") {
  61. this.setState({ isFooterVisible: !this.state.isFooterVisible });
  62. }
  63. });
  64. }
  65. checkUrl() {
  66. // Check URL
  67. var indexOf = location.href.indexOf("?");
  68. if (indexOf !== -1) {
  69. var params = location.href.substr(indexOf + 1).split("&");
  70. for (var index = 0; index < params.length; index++) {
  71. var param = params[index].split("=");
  72. var name = param[0];
  73. var value = param[1];
  74. switch (name) {
  75. case "assetUrl": {
  76. this._assetUrl = value;
  77. break;
  78. }
  79. case "autoRotate": {
  80. this._autoRotate = !!value;
  81. break;
  82. }
  83. case "cameraPosition": {
  84. this._cameraPosition = Vector3.FromArray(value.split(",").map(function (component) { return +component; }));
  85. break;
  86. }
  87. case "kiosk": {
  88. this.state = { isFooterVisible: value === "true" ? false : true, errorMessage: "" };
  89. break;
  90. }
  91. }
  92. }
  93. }
  94. }
  95. componentDidUpdate() {
  96. this._assetUrl = undefined;
  97. this._cameraPosition = undefined;
  98. }
  99. public render() {
  100. return (
  101. <div id="root">
  102. <p id="droptext" ref={this._dropTextRef}>Drag and drop gltf, glb, obj or babylon files to view them</p>
  103. <RenderingZone globalState={this._globalState}
  104. assetUrl={this._assetUrl}
  105. autoRotate={this._autoRotate}
  106. cameraPosition={this._cameraPosition}
  107. expanded={!this.state.isFooterVisible} />
  108. <div ref={this._clickInterceptorRef}
  109. onClick={() => {
  110. this._globalState.onClickInterceptorClicked.notifyObservers();
  111. this._clickInterceptorRef.current!.classList.add("hidden");
  112. }}
  113. className="clickInterceptor hidden"></div>
  114. {
  115. this.state.isFooterVisible &&
  116. <Footer globalState={this._globalState} />
  117. }
  118. <div id="logoContainer">
  119. <img id="logo" src={fullScreenLogo} ref={this._logoRef} />
  120. </div>
  121. {
  122. this.state.errorMessage &&
  123. <div id="errorZone">
  124. <div className="message">
  125. {this.state.errorMessage}
  126. </div>
  127. <button type="button" className="close"
  128. onClick={() => this.setState({ errorMessage: "" })}
  129. data-dismiss="alert">&times;</button>
  130. </div>
  131. }
  132. </div>
  133. );
  134. }
  135. public static Show(hostElement: HTMLElement) {
  136. const sandBox = React.createElement(Sandbox, {});
  137. ReactDOM.render(sandBox, hostElement);
  138. }
  139. }