sandbox.tsx 5.9 KB

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