previewMeshControlComponent.tsx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import * as React from "react";
  2. import { GlobalState } from '../../globalState';
  3. import { Color3, Color4 } from 'babylonjs/Maths/math.color';
  4. import { PreviewMeshType } from './previewMeshType';
  5. import { DataStorage } from 'babylonjs/Misc/dataStorage';
  6. import { OptionsLineComponent } from '../../sharedComponents/optionsLineComponent';
  7. import { Observer } from 'babylonjs/Misc/observable';
  8. import { Nullable } from 'babylonjs/types';
  9. import { NodeMaterialModes } from 'babylonjs/Materials/Node/Enums/nodeMaterialModes';
  10. const popUpIcon: string = require("./svgs/popOut.svg");
  11. const colorPicker: string = require("./svgs/colorPicker.svg");
  12. const pauseIcon: string = require("./svgs/pauseIcon.svg");
  13. const playIcon: string = require("./svgs/playIcon.svg");
  14. interface IPreviewMeshControlComponent {
  15. globalState: GlobalState;
  16. togglePreviewAreaComponent: () => void;
  17. }
  18. export class PreviewMeshControlComponent extends React.Component<IPreviewMeshControlComponent> {
  19. private colorInputRef: React.RefObject<HTMLInputElement>;
  20. private filePickerRef: React.RefObject<HTMLInputElement>;
  21. private _onResetRequiredObserver: Nullable<Observer<void>>;
  22. constructor(props: IPreviewMeshControlComponent) {
  23. super(props);
  24. this.colorInputRef = React.createRef();
  25. this.filePickerRef = React.createRef();
  26. this._onResetRequiredObserver = this.props.globalState.onResetRequiredObservable.add(() => {
  27. this.forceUpdate();
  28. });
  29. }
  30. componentWillUnmount() {
  31. this.props.globalState.onResetRequiredObservable.remove(this._onResetRequiredObserver);
  32. }
  33. changeMeshType(newOne: PreviewMeshType) {
  34. if (this.props.globalState.previewMeshType === newOne) {
  35. return;
  36. }
  37. this.props.globalState.previewMeshType = newOne;
  38. this.props.globalState.onPreviewCommandActivated.notifyObservers(false);
  39. DataStorage.WriteNumber("PreviewMeshType", newOne);
  40. this.forceUpdate();
  41. }
  42. useCustomMesh(evt: any) {
  43. var files: File[] = evt.target.files;
  44. if (files && files.length) {
  45. let file = files[0];
  46. this.props.globalState.previewMeshFile = file;
  47. this.props.globalState.previewMeshType = PreviewMeshType.Custom;
  48. this.props.globalState.onPreviewCommandActivated.notifyObservers(false);
  49. this.props.globalState.listOfCustomPreviewMeshFiles = [file];
  50. this.forceUpdate();
  51. }
  52. if (this.filePickerRef.current) {
  53. this.filePickerRef.current.value = "";
  54. }
  55. }
  56. onPopUp() {
  57. this.props.togglePreviewAreaComponent();
  58. }
  59. changeAnimation() {
  60. this.props.globalState.rotatePreview = !this.props.globalState.rotatePreview;
  61. this.props.globalState.onAnimationCommandActivated.notifyObservers();
  62. this.forceUpdate();
  63. }
  64. changeBackground(value: string) {
  65. const newColor = Color3.FromHexString(value);
  66. DataStorage.WriteNumber("BackgroundColorR", newColor.r);
  67. DataStorage.WriteNumber("BackgroundColorG", newColor.g);
  68. DataStorage.WriteNumber("BackgroundColorB", newColor.b);
  69. const newBackgroundColor = Color4.FromColor3(newColor, 1.0);
  70. this.props.globalState.backgroundColor = newBackgroundColor;
  71. this.props.globalState.onPreviewBackgroundChanged.notifyObservers();
  72. }
  73. changeBackgroundClick() {
  74. this.colorInputRef.current?.click();
  75. }
  76. render() {
  77. var meshTypeOptions = [
  78. { label: "Cube", value: PreviewMeshType.Box },
  79. { label: "Cylinder", value: PreviewMeshType.Cylinder },
  80. { label: "Plane", value: PreviewMeshType.Plane },
  81. { label: "Shader ball", value: PreviewMeshType.ShaderBall },
  82. { label: "Sphere", value: PreviewMeshType.Sphere },
  83. { label: "Load...", value: PreviewMeshType.Custom + 1 }
  84. ];
  85. var particleTypeOptions = [
  86. { label: "Default particle system", value: PreviewMeshType.DefaultParticle },
  87. { label: "Explosion", value: PreviewMeshType.Explosion },
  88. { label: "Fire", value: PreviewMeshType.Fire },
  89. { label: "Rain", value: PreviewMeshType.Rain },
  90. { label: "Smoke", value: PreviewMeshType.Smoke },
  91. { label: "Load...", value: PreviewMeshType.Custom + 1 }
  92. ];
  93. if (this.props.globalState.listOfCustomPreviewMeshFiles.length > 0) {
  94. meshTypeOptions.splice(0, 0, {
  95. label: "Custom", value: PreviewMeshType.Custom
  96. });
  97. particleTypeOptions.splice(0, 0, {
  98. label: "Custom", value: PreviewMeshType.Custom
  99. });
  100. }
  101. var options = this.props.globalState.mode === NodeMaterialModes.Particle ? particleTypeOptions : meshTypeOptions;
  102. var accept = this.props.globalState.mode === NodeMaterialModes.Particle ? ".json" : ".gltf, .glb, .babylon, .obj";
  103. return (
  104. <div id="preview-mesh-bar">
  105. { (this.props.globalState.mode === NodeMaterialModes.Material || this.props.globalState.mode === NodeMaterialModes.Particle) && <>
  106. <OptionsLineComponent label="" options={options} target={this.props.globalState}
  107. propertyName="previewMeshType"
  108. noDirectUpdate={true}
  109. onSelect={(value: any) => {
  110. if (value !== PreviewMeshType.Custom + 1) {
  111. this.changeMeshType(value);
  112. } else {
  113. this.filePickerRef.current?.click();
  114. }
  115. }} />
  116. <div style={{
  117. display: "none"
  118. }} title="Preview with a custom mesh" >
  119. <input ref={this.filePickerRef} id="file-picker" type="file" onChange={(evt) => this.useCustomMesh(evt)} accept={accept}/>
  120. </div>
  121. </> }
  122. { this.props.globalState.mode === NodeMaterialModes.Material && <>
  123. <div
  124. title="Turn-table animation"
  125. onClick={() => this.changeAnimation()} className="button" id="play-button">
  126. {this.props.globalState.rotatePreview ? <img src={pauseIcon} alt=""/> : <img src={playIcon} alt=""/>}
  127. </div>
  128. <div
  129. id="color-picker-button"
  130. title="Background color"
  131. className={"button align"}
  132. onClick={(_) => this.changeBackgroundClick()}
  133. >
  134. <img src={colorPicker} alt=""/>
  135. <label htmlFor="color-picker" id="color-picker-label">
  136. </label>
  137. <input ref={this.colorInputRef} id="color-picker" type="color" onChange={(evt) => this.changeBackground(evt.target.value)} />
  138. </div>
  139. </> }
  140. <div
  141. title="Open preview in new window" id="preview-new-window"
  142. onClick={() => this.onPopUp()} className="button">
  143. <img src={popUpIcon} alt=""/>
  144. </div>
  145. </div>
  146. );
  147. }
  148. }