gltfComponent.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import * as React from "react";
  2. import { Scene } from "babylonjs/scene";
  3. import { LineContainerComponent } from "../../lineContainerComponent";
  4. import { CheckBoxLineComponent } from "../../lines/checkBoxLineComponent";
  5. import { GlobalState } from "../../../globalState";
  6. import { FloatLineComponent } from "../../lines/floatLineComponent";
  7. import { OptionsLineComponent } from "../../lines/optionsLineComponent";
  8. import { MessageLineComponent } from "../../lines/messageLineComponent";
  9. import { faCheck, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
  10. import { TextLineComponent } from "../../lines/textLineComponent";
  11. import { GLTFLoaderCoordinateSystemMode, GLTFLoaderAnimationStartMode } from "babylonjs-loaders/glTF/index";
  12. import { Nullable } from 'babylonjs/types';
  13. import { Observer } from 'babylonjs/Misc/observable';
  14. import { IGLTFValidationResults } from "babylonjs-gltf2interface";
  15. interface IGLTFComponentProps {
  16. scene: Scene;
  17. globalState: GlobalState;
  18. }
  19. export class GLTFComponent extends React.Component<IGLTFComponentProps> {
  20. private _onValidationResultsUpdatedObserver: Nullable<Observer<Nullable<IGLTFValidationResults>>> = null;
  21. constructor(props: IGLTFComponentProps) {
  22. super(props);
  23. const extensionStates = this.props.globalState.glTFLoaderExtensionDefaults;
  24. extensionStates["MSFT_lod"] = extensionStates["MSFT_lod"] || { enabled: true, maxLODsToLoad: 10 };
  25. extensionStates["MSFT_minecraftMesh"] = extensionStates["MSFT_minecraftMesh"] || { enabled: true };
  26. extensionStates["MSFT_sRGBFactors"] = extensionStates["MSFT_sRGBFactors"] || { enabled: true };
  27. extensionStates["MSFT_audio_emitter"] = extensionStates["MSFT_audio_emitter"] || { enabled: true };
  28. extensionStates["KHR_draco_mesh_compression"] = extensionStates["KHR_draco_mesh_compression"] || { enabled: true };
  29. extensionStates["KHR_materials_pbrSpecularGlossiness"] = extensionStates["KHR_materials_pbrSpecularGlossiness"] || { enabled: true };
  30. extensionStates["KHR_materials_clearcoat"] = extensionStates["KHR_materials_clearcoat"] || { enabled: true };
  31. extensionStates["KHR_materials_sheen"] = extensionStates["KHR_materials_sheen"] || { enabled: true };
  32. extensionStates["KHR_materials_specular"] = extensionStates["KHR_materials_specular"] || { enabled: true };
  33. extensionStates["KHR_materials_unlit"] = extensionStates["KHR_materials_unlit"] || { enabled: true };
  34. extensionStates["KHR_lights_punctual"] = extensionStates["KHR_lights_punctual"] || { enabled: true };
  35. extensionStates["KHR_texture_transform"] = extensionStates["KHR_texture_transform"] || { enabled: true };
  36. extensionStates["EXT_lights_image_based"] = extensionStates["EXT_lights_image_based"] || { enabled: true };
  37. const loaderState = this.props.globalState.glTFLoaderDefaults;
  38. if (loaderState["animationStartMode"] === undefined) {
  39. loaderState["animationStartMode"] = GLTFLoaderAnimationStartMode.FIRST;
  40. }
  41. loaderState["capturePerformanceCounters"] = loaderState["capturePerformanceCounters"] || false;
  42. loaderState["compileMaterials"] = loaderState["compileMaterials"] || false;
  43. loaderState["compileShadowGenerators"] = loaderState["compileShadowGenerators"] || false;
  44. loaderState["coordinateSystemMode"] = loaderState["coordinateSystemMode"] || GLTFLoaderCoordinateSystemMode.AUTO;
  45. loaderState["loggingEnabled"] = loaderState["loggingEnabled"] || false;
  46. loaderState["transparencyAsCoverage"] = loaderState["transparencyAsCoverage"] || false;
  47. loaderState["useClipPlane"] = loaderState["useClipPlane"] || false;
  48. loaderState["validate"] = loaderState["validate"] || true;
  49. }
  50. openValidationDetails() {
  51. const validationResults = this.props.globalState.validationResults;
  52. const win = window.open("", "_blank");
  53. if (win) {
  54. // TODO: format this better and use generator registry (https://github.com/KhronosGroup/glTF-Generator-Registry)
  55. win.document.title = "glTF Validation Results";
  56. win.document.body.innerText = JSON.stringify(validationResults, null, 2);
  57. win.document.body.style.whiteSpace = "pre";
  58. win.document.body.style.fontFamily = `monospace`;
  59. win.document.body.style.fontSize = `14px`;
  60. win.focus();
  61. }
  62. }
  63. prepareText(singularForm: string, count: number) {
  64. if (count) {
  65. return `${count} ${singularForm}s`;
  66. }
  67. return `${singularForm}`;
  68. }
  69. componentDidMount() {
  70. if (this.props.globalState) {
  71. this._onValidationResultsUpdatedObserver = this.props.globalState.onValidationResultsUpdatedObservable.add(() => {
  72. this.forceUpdate();
  73. });
  74. }
  75. }
  76. componentWillUnmount() {
  77. if (this.props.globalState) {
  78. if (this._onValidationResultsUpdatedObserver) {
  79. this.props.globalState.onValidationResultsUpdatedObservable.remove(this._onValidationResultsUpdatedObserver);
  80. }
  81. }
  82. }
  83. renderValidation() {
  84. const validationResults = this.props.globalState.validationResults;
  85. if (!validationResults) {
  86. return null;
  87. }
  88. const issues = validationResults.issues;
  89. return (
  90. <LineContainerComponent globalState={this.props.globalState} title="GLTF VALIDATION" closed={!issues.numErrors && !issues.numWarnings}>
  91. {
  92. issues.numErrors !== 0 &&
  93. <MessageLineComponent text="Your file has some validation issues" icon={faTimesCircle} color="Red" />
  94. }
  95. {
  96. issues.numErrors === 0 &&
  97. <MessageLineComponent text="Your file is a valid glTF file" icon={faCheck} color="Green" />
  98. }
  99. <TextLineComponent label="Errors" value={issues.numErrors.toString()} />
  100. <TextLineComponent label="Warnings" value={issues.numWarnings.toString()} />
  101. <TextLineComponent label="Infos" value={issues.numInfos.toString()} />
  102. <TextLineComponent label="Hints" value={issues.numHints.toString()} />
  103. <TextLineComponent label="More details" value="Click here" onLink={() => this.openValidationDetails()} />
  104. </LineContainerComponent>
  105. );
  106. }
  107. render() {
  108. const extensionStates = this.props.globalState.glTFLoaderExtensionDefaults;
  109. const loaderState = this.props.globalState.glTFLoaderDefaults;
  110. var animationStartMode = [
  111. { label: "None", value: GLTFLoaderAnimationStartMode.NONE },
  112. { label: "First", value: GLTFLoaderAnimationStartMode.FIRST },
  113. { label: "ALL", value: GLTFLoaderAnimationStartMode.ALL }
  114. ];
  115. var coordinateSystemMode = [
  116. { label: "Auto", value: GLTFLoaderCoordinateSystemMode.AUTO },
  117. { label: "Right handed", value: GLTFLoaderCoordinateSystemMode.FORCE_RIGHT_HANDED }
  118. ];
  119. return (
  120. <div>
  121. <LineContainerComponent globalState={this.props.globalState} title="GLTF LOADER" closed={true}>
  122. <OptionsLineComponent label="Animation start mode" options={animationStartMode} target={loaderState} propertyName="animationStartMode" />
  123. <CheckBoxLineComponent label="Capture performance counters" target={loaderState} propertyName="capturePerformanceCounters" />
  124. <CheckBoxLineComponent label="Compile materials" target={loaderState} propertyName="compileMaterials" />
  125. <CheckBoxLineComponent label="Compile shadow generators" target={loaderState} propertyName="compileShadowGenerators" />
  126. <OptionsLineComponent label="Coordinate system" options={coordinateSystemMode} target={loaderState} propertyName="coordinateSystemMode" />
  127. <CheckBoxLineComponent label="Enable logging" target={loaderState} propertyName="loggingEnabled" />
  128. <CheckBoxLineComponent label="Transparency as coverage" target={loaderState} propertyName="transparencyAsCoverage" />
  129. <CheckBoxLineComponent label="Use clip plane" target={loaderState} propertyName="useClipPlane" />
  130. <CheckBoxLineComponent label="Validate" target={loaderState} propertyName="validate" />
  131. <MessageLineComponent text="You need to reload your file to see these changes" />
  132. </LineContainerComponent>
  133. <LineContainerComponent globalState={this.props.globalState} title="GLTF EXTENSIONS" closed={true}>
  134. <CheckBoxLineComponent label="MSFT_lod" isSelected={() => extensionStates["MSFT_lod"].enabled} onSelect={(value) => extensionStates["MSFT_lod"].enabled = value} />
  135. <FloatLineComponent label="Maximum LODs" target={extensionStates["MSFT_lod"]} propertyName="maxLODsToLoad" additionalClass="gltf-extension-property" isInteger={true} />
  136. <CheckBoxLineComponent label="MSFT_minecraftMesh" isSelected={() => extensionStates["MSFT_minecraftMesh"].enabled} onSelect={(value) => extensionStates["MSFT_minecraftMesh"].enabled = value} />
  137. <CheckBoxLineComponent label="MSFT_sRGBFactors" isSelected={() => extensionStates["MSFT_sRGBFactors"].enabled} onSelect={(value) => extensionStates["MSFT_sRGBFactors"].enabled = value} />
  138. <CheckBoxLineComponent label="MSFT_audio_emitter" isSelected={() => extensionStates["MSFT_audio_emitter"].enabled} onSelect={(value) => extensionStates["MSFT_audio_emitter"].enabled = value} />
  139. <CheckBoxLineComponent label="KHR_draco_mesh_compression" isSelected={() => extensionStates["KHR_draco_mesh_compression"].enabled} onSelect={(value) => extensionStates["KHR_draco_mesh_compression"].enabled = value} />
  140. <CheckBoxLineComponent label="KHR_materials_pbrSpecularGlossiness" isSelected={() => extensionStates["KHR_materials_pbrSpecularGlossiness"].enabled} onSelect={(value) => extensionStates["KHR_materials_pbrSpecularGlossiness"].enabled = value} />
  141. <CheckBoxLineComponent label="KHR_materials_clearcoat" isSelected={() => extensionStates["KHR_materials_clearcoat"].enabled} onSelect={(value) => extensionStates["KHR_materials_clearcoat"].enabled = value} />
  142. <CheckBoxLineComponent label="KHR_materials_sheen" isSelected={() => extensionStates["KHR_materials_sheen"].enabled} onSelect={(value) => extensionStates["KHR_materials_sheen"].enabled = value} />
  143. <CheckBoxLineComponent label="KHR_materials_specular" isSelected={() => extensionStates["KHR_materials_specular"].enabled} onSelect={(value) => extensionStates["KHR_materials_specular"].enabled = value} />
  144. <CheckBoxLineComponent label="KHR_materials_unlit" isSelected={() => extensionStates["KHR_materials_unlit"].enabled} onSelect={(value) => extensionStates["KHR_materials_unlit"].enabled = value} />
  145. <CheckBoxLineComponent label="KHR_lights_punctual" isSelected={() => extensionStates["KHR_lights_punctual"].enabled} onSelect={(value) => extensionStates["KHR_lights_punctual"].enabled = value} />
  146. <CheckBoxLineComponent label="KHR_texture_transform" isSelected={() => extensionStates["KHR_texture_transform"].enabled} onSelect={(value) => extensionStates["KHR_texture_transform"].enabled = value} />
  147. <CheckBoxLineComponent label="EXT_lights_image_based" isSelected={() => extensionStates["EXT_lights_image_based"].enabled} onSelect={(value) => extensionStates["EXT_lights_image_based"].enabled = value} />
  148. <MessageLineComponent text="You need to reload your file to see these changes" />
  149. </LineContainerComponent>
  150. {
  151. loaderState["validate"] && this.props.globalState.validationResults &&
  152. this.renderValidation()
  153. }
  154. </div>
  155. );
  156. }
  157. }