meshPropertyGridComponent.tsx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. import * as React from "react";
  2. import { Observable } from "babylonjs/Misc/observable";
  3. import { Tools } from "babylonjs/Misc/tools";
  4. import { Color3, Vector3 } from "babylonjs/Maths/math";
  5. import { Mesh } from "babylonjs/Meshes/mesh";
  6. import { VertexBuffer } from "babylonjs/Meshes/buffer";
  7. import { LinesBuilder } from "babylonjs/Meshes/Builders/linesBuilder";
  8. import { PhysicsImpostor } from "babylonjs/Physics/physicsImpostor";
  9. import { Scene } from "babylonjs/scene";
  10. import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
  11. import { LineContainerComponent } from "../../../lineContainerComponent";
  12. import { TextLineComponent } from "../../../lines/textLineComponent";
  13. import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
  14. import { Vector3LineComponent } from "../../../lines/vector3LineComponent";
  15. import { SliderLineComponent } from "../../../lines/sliderLineComponent";
  16. import { QuaternionLineComponent } from "../../../lines/quaternionLineComponent";
  17. import { FloatLineComponent } from "../../../lines/floatLineComponent";
  18. import { LockObject } from "../lockObject";
  19. import { GlobalState } from '../../../../globalState';
  20. import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
  21. import { StandardMaterial } from 'babylonjs/Materials/standardMaterial';
  22. import { Color3LineComponent } from '../../../lines/color3LineComponent';
  23. import { MorphTarget } from 'babylonjs/Morph/morphTarget';
  24. import { OptionsLineComponent } from '../../../lines/optionsLineComponent';
  25. import { AbstractMesh } from 'babylonjs/Meshes/abstractMesh';
  26. interface IMeshPropertyGridComponentProps {
  27. globalState: GlobalState;
  28. mesh: Mesh;
  29. lockObject: LockObject;
  30. onSelectionChangedObservable?: Observable<any>;
  31. onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
  32. }
  33. export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGridComponentProps, {
  34. displayNormals: boolean,
  35. displayVertexColors: boolean
  36. }> {
  37. constructor(props: IMeshPropertyGridComponentProps) {
  38. super(props);
  39. this.state = {
  40. displayNormals: false,
  41. displayVertexColors: false
  42. };
  43. }
  44. renderWireframeOver() {
  45. const mesh = this.props.mesh;
  46. const scene = mesh.getScene();
  47. if (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) {
  48. mesh.reservedDataStore.wireframeOver.dispose(false, true);
  49. mesh.reservedDataStore.wireframeOver = null;
  50. this.forceUpdate();
  51. return;
  52. }
  53. var wireframeOver = mesh.clone()!;
  54. wireframeOver.reservedDataStore = { hidden: true };
  55. // Sets up the mesh to be attached to the parent.
  56. // So all neutral in local space.
  57. wireframeOver.parent = mesh;
  58. wireframeOver.position = Vector3.Zero();
  59. wireframeOver.scaling = new Vector3(1, 1, 1);
  60. wireframeOver.rotation = Vector3.Zero();
  61. wireframeOver.rotationQuaternion = null;
  62. var material = new StandardMaterial("wireframeOver", scene);
  63. material.reservedDataStore = { hidden: true };
  64. wireframeOver.material = material;
  65. material.zOffset = 1;
  66. material.disableLighting = true;
  67. material.backFaceCulling = false;
  68. material.emissiveColor = Color3.White();
  69. material.wireframe = true;
  70. if (!mesh.reservedDataStore) {
  71. mesh.reservedDataStore = {};
  72. }
  73. mesh.reservedDataStore.wireframeOver = wireframeOver;
  74. this.forceUpdate();
  75. }
  76. renderNormalVectors() {
  77. const mesh = this.props.mesh;
  78. const scene = mesh.getScene();
  79. if (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) {
  80. mesh.reservedDataStore.normalLines.dispose();
  81. mesh.reservedDataStore.normalLines = null;
  82. this.forceUpdate();
  83. return;
  84. }
  85. var normals = mesh.getVerticesData(VertexBuffer.NormalKind);
  86. var positions = mesh.getVerticesData(VertexBuffer.PositionKind);
  87. const color = Color3.White();
  88. const size = mesh.getBoundingInfo().diagonalLength * 0.05;
  89. var lines = [];
  90. for (var i = 0; i < normals!.length; i += 3) {
  91. var v1 = Vector3.FromArray(positions!, i);
  92. var v2 = v1.add(Vector3.FromArray(normals!, i).scaleInPlace(size));
  93. lines.push([v1, v2]);
  94. }
  95. var normalLines = LinesBuilder.CreateLineSystem("normalLines", { lines: lines }, scene);
  96. normalLines.color = color;
  97. normalLines.parent = mesh;
  98. normalLines.reservedDataStore = { hidden: true };
  99. if (!mesh.reservedDataStore) {
  100. mesh.reservedDataStore = {};
  101. }
  102. mesh.reservedDataStore.normalLines = normalLines;
  103. this.forceUpdate();
  104. }
  105. displayNormals() {
  106. const mesh = this.props.mesh;
  107. const scene = mesh.getScene();
  108. if (mesh.material && mesh.material.getClassName() === "NormalMaterial") {
  109. mesh.material.dispose();
  110. mesh.material = mesh.reservedDataStore.originalMaterial;
  111. mesh.reservedDataStore.originalMaterial = null;
  112. this.setState({ displayNormals: false });
  113. } else {
  114. if (!(BABYLON as any).NormalMaterial) {
  115. this.setState({ displayNormals: true });
  116. Tools.LoadScript("https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.js", () => {
  117. this.displayNormals();
  118. });
  119. return;
  120. }
  121. if (!mesh.reservedDataStore) {
  122. mesh.reservedDataStore = {};
  123. }
  124. if (!mesh.reservedDataStore.originalMaterial) {
  125. mesh.reservedDataStore.originalMaterial = mesh.material;
  126. }
  127. const normalMaterial = new (BABYLON as any).NormalMaterial("normalMaterial", scene);
  128. normalMaterial.disableLighting = true;
  129. if (mesh.material) {
  130. normalMaterial.sideOrientation = mesh.material.sideOrientation;
  131. }
  132. normalMaterial.reservedDataStore = { hidden: true };
  133. mesh.material = normalMaterial;
  134. this.setState({ displayNormals: true });
  135. }
  136. }
  137. displayVertexColors() {
  138. const mesh = this.props.mesh;
  139. const scene = mesh.getScene();
  140. if (mesh.material && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial) {
  141. mesh.material.dispose();
  142. mesh.material = mesh.reservedDataStore.originalMaterial;
  143. mesh.reservedDataStore.originalMaterial = null;
  144. this.setState({ displayVertexColors: false });
  145. } else {
  146. if (!mesh.reservedDataStore) {
  147. mesh.reservedDataStore = {};
  148. }
  149. if (!mesh.reservedDataStore.originalMaterial) {
  150. mesh.reservedDataStore.originalMaterial = mesh.material;
  151. }
  152. const vertexColorMaterial = new StandardMaterial("vertex colors", scene);
  153. vertexColorMaterial.disableLighting = true;
  154. vertexColorMaterial.emissiveColor = Color3.White();
  155. if (mesh.material) {
  156. vertexColorMaterial.sideOrientation = mesh.material.sideOrientation;
  157. }
  158. vertexColorMaterial.reservedDataStore = { hidden: true, isVertexColorMaterial: true };
  159. mesh.useVertexColors = true;
  160. mesh.material = vertexColorMaterial;
  161. this.setState({ displayVertexColors: true });
  162. }
  163. }
  164. onMaterialLink() {
  165. if (!this.props.onSelectionChangedObservable) {
  166. return;
  167. }
  168. const mesh = this.props.mesh;
  169. this.props.onSelectionChangedObservable.notifyObservers(mesh.material);
  170. }
  171. onSourceMeshLink() {
  172. if (!this.props.onSelectionChangedObservable) {
  173. return;
  174. }
  175. const instanceMesh = this.props.mesh as any;
  176. this.props.onSelectionChangedObservable.notifyObservers(instanceMesh.sourceMesh);
  177. }
  178. convertPhysicsTypeToString(): string {
  179. const mesh = this.props.mesh;
  180. switch (mesh.physicsImpostor!.type) {
  181. case PhysicsImpostor.NoImpostor:
  182. return "No impostor";
  183. case PhysicsImpostor.SphereImpostor:
  184. return "Sphere";
  185. case PhysicsImpostor.BoxImpostor:
  186. return "Box";
  187. case PhysicsImpostor.PlaneImpostor:
  188. return "Plane";
  189. case PhysicsImpostor.MeshImpostor:
  190. return "Mesh";
  191. case PhysicsImpostor.CylinderImpostor:
  192. return "Cylinder";
  193. case PhysicsImpostor.ParticleImpostor:
  194. return "Particle";
  195. case PhysicsImpostor.HeightmapImpostor:
  196. return "Heightmap";
  197. case PhysicsImpostor.ConvexHullImpostor:
  198. return "Convex hull";
  199. case PhysicsImpostor.RopeImpostor:
  200. return "Rope";
  201. case PhysicsImpostor.SoftbodyImpostor:
  202. return "Soft body";
  203. }
  204. return "Unknown";
  205. }
  206. render() {
  207. const mesh = this.props.mesh;
  208. const scene = mesh.getScene();
  209. const displayNormals = mesh.material != null && mesh.material.getClassName() === "NormalMaterial";
  210. const displayVertexColors = !!(mesh.material != null && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial);
  211. const renderNormalVectors = (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) ? true : false;
  212. const renderWireframeOver = (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) ? true : false;
  213. var morphTargets: MorphTarget[] = [];
  214. if (mesh.morphTargetManager) {
  215. for (var index = 0; index < mesh.morphTargetManager.numTargets; index++) {
  216. morphTargets.push(mesh.morphTargetManager.getTarget(index));
  217. }
  218. }
  219. var algorithmOptions = [
  220. { label: "Accurate", value: AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE },
  221. { label: "Conservative", value: AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE },
  222. ];
  223. var occlusionTypeOptions = [
  224. { label: "None", value: AbstractMesh.OCCLUSION_TYPE_NONE },
  225. { label: "Optimistic", value: AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC },
  226. { label: "Strict", value: AbstractMesh.OCCLUSION_TYPE_STRICT },
  227. ];
  228. return (
  229. <div className="pane">
  230. <CustomPropertyGridComponent globalState={this.props.globalState} target={mesh}
  231. lockObject={this.props.lockObject}
  232. onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  233. <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
  234. <TextLineComponent label="ID" value={mesh.id} />
  235. <TextLineComponent label="Unique ID" value={mesh.uniqueId.toString()} />
  236. <TextLineComponent label="Class" value={mesh.getClassName()} />
  237. <TextLineComponent label="Vertices" value={mesh.getTotalVertices().toString()} />
  238. <TextLineComponent label="Faces" value={(mesh.getTotalIndices() / 3).toFixed(0)} />
  239. <TextLineComponent label="Sub-meshes" value={mesh.subMeshes ? mesh.subMeshes.length.toString() : "0"} />
  240. <TextLineComponent label="Has skeleton" value={mesh.skeleton ? "Yes" : "No"} />
  241. <CheckBoxLineComponent label="Is enabled" isSelected={() => mesh.isEnabled()} onSelect={(value) => mesh.setEnabled(value)} />
  242. <CheckBoxLineComponent label="Is pickable" target={mesh} propertyName="isPickable" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  243. {
  244. mesh.material && (!mesh.material.reservedDataStore || !mesh.material.reservedDataStore.hidden) &&
  245. <TextLineComponent label="Material" value={mesh.material.name} onLink={() => this.onMaterialLink()} />
  246. }
  247. {
  248. mesh.isAnInstance &&
  249. <TextLineComponent label="Source" value={(mesh as any).sourceMesh.name} onLink={() => this.onSourceMeshLink()} />
  250. }
  251. </LineContainerComponent>
  252. <LineContainerComponent globalState={this.props.globalState} title="TRANSFORMS">
  253. <Vector3LineComponent label="Position" target={mesh} propertyName="position" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  254. {
  255. !mesh.rotationQuaternion &&
  256. <Vector3LineComponent label="Rotation" useEuler={this.props.globalState.onlyUseEulers} target={mesh} propertyName="rotation" step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  257. }
  258. {
  259. mesh.rotationQuaternion &&
  260. <QuaternionLineComponent label="Rotation" useEuler={this.props.globalState.onlyUseEulers} target={mesh} propertyName="rotationQuaternion" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  261. }
  262. <Vector3LineComponent label="Scaling" target={mesh} propertyName="scaling" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  263. </LineContainerComponent>
  264. <LineContainerComponent globalState={this.props.globalState} title="DISPLAY" closed={true}>
  265. {
  266. !mesh.isAnInstance &&
  267. <SliderLineComponent label="Visibility" target={mesh} propertyName="visibility" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  268. }
  269. <FloatLineComponent lockObject={this.props.lockObject} label="Alpha index" target={mesh} propertyName="alphaIndex" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  270. <CheckBoxLineComponent label="Receive shadows" target={mesh} propertyName="receiveShadows" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  271. {
  272. mesh.isVerticesDataPresent(VertexBuffer.ColorKind) &&
  273. <CheckBoxLineComponent label="Use vertex colors" target={mesh} propertyName="useVertexColors" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  274. }
  275. {
  276. scene.fogMode !== Scene.FOGMODE_NONE &&
  277. <CheckBoxLineComponent label="Apply fog" target={mesh} propertyName="applyFog" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  278. }
  279. {
  280. !mesh.parent &&
  281. <CheckBoxLineComponent label="Infinite distance" target={mesh} propertyName="infiniteDistance" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  282. }
  283. </LineContainerComponent>
  284. {
  285. mesh.morphTargetManager != null &&
  286. <LineContainerComponent globalState={this.props.globalState} title="MORPH TARGETS" closed={true}>
  287. {
  288. morphTargets.map((mt, i) => {
  289. return (
  290. <SliderLineComponent label={mt.name} target={mt} propertyName="influence" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  291. )
  292. })
  293. }
  294. </LineContainerComponent>
  295. }
  296. <LineContainerComponent globalState={this.props.globalState} title="ADVANCED" closed={true}>
  297. {
  298. mesh.useBones &&
  299. <CheckBoxLineComponent label="Compute bones using shaders" target={mesh} propertyName="computeBonesUsingShaders" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  300. }
  301. <CheckBoxLineComponent label="Collisions" target={mesh} propertyName="checkCollisions" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  302. <TextLineComponent label="Has normals" value={mesh.isVerticesDataPresent(VertexBuffer.NormalKind) ? "Yes" : "No"} />
  303. <TextLineComponent label="Has vertex colors" value={mesh.isVerticesDataPresent(VertexBuffer.ColorKind) ? "Yes" : "No"} />
  304. <TextLineComponent label="Has UV set 0" value={mesh.isVerticesDataPresent(VertexBuffer.UVKind) ? "Yes" : "No"} />
  305. <TextLineComponent label="Has UV set 1" value={mesh.isVerticesDataPresent(VertexBuffer.UV2Kind) ? "Yes" : "No"} />
  306. <TextLineComponent label="Has UV set 2" value={mesh.isVerticesDataPresent(VertexBuffer.UV3Kind) ? "Yes" : "No"} />
  307. <TextLineComponent label="Has UV set 3" value={mesh.isVerticesDataPresent(VertexBuffer.UV4Kind) ? "Yes" : "No"} />
  308. <TextLineComponent label="Has tangents" value={mesh.isVerticesDataPresent(VertexBuffer.TangentKind) ? "Yes" : "No"} />
  309. <TextLineComponent label="Has matrix weights" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind) ? "Yes" : "No"} />
  310. <TextLineComponent label="Has matrix indices" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind) ? "Yes" : "No"} />
  311. </LineContainerComponent>
  312. {
  313. mesh.physicsImpostor != null &&
  314. <LineContainerComponent globalState={this.props.globalState} title="PHYSICS" closed={true}>
  315. <FloatLineComponent lockObject={this.props.lockObject} label="Mass" target={mesh.physicsImpostor} propertyName="mass" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  316. <FloatLineComponent lockObject={this.props.lockObject} label="Friction" target={mesh.physicsImpostor} propertyName="friction" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  317. <FloatLineComponent lockObject={this.props.lockObject} label="Restitution" target={mesh.physicsImpostor} propertyName="restitution" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  318. <TextLineComponent label="Type" value={this.convertPhysicsTypeToString()} />
  319. </LineContainerComponent>
  320. }
  321. <LineContainerComponent globalState={this.props.globalState} title="OCCLUSIONS" closed={true}>
  322. <OptionsLineComponent label="Type" options={occlusionTypeOptions} target={mesh} propertyName="occlusionType" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  323. <SliderLineComponent label="Retry count" minimum={-1} maximum={10} decimalCount={0} step={1} target={mesh} propertyName="occlusionRetryCount" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  324. <OptionsLineComponent label="Algorithm" options={algorithmOptions} target={mesh} propertyName="occlusionQueryAlgorithmType" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  325. </LineContainerComponent>
  326. <LineContainerComponent globalState={this.props.globalState} title="EDGE RENDERING" closed={true}>
  327. <CheckBoxLineComponent label="Enable" target={mesh} isSelected={() => mesh.edgesRenderer != null} onSelect={value => {
  328. if (value) {
  329. mesh.enableEdgesRendering();
  330. } else {
  331. mesh.disableEdgesRendering();
  332. }
  333. }} />
  334. <SliderLineComponent label="Edge width" minimum={0} maximum={10} step={0.1} target={mesh} propertyName="edgesWidth" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  335. <Color3LineComponent label="Edge color" target={mesh} propertyName="edgesColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  336. </LineContainerComponent>
  337. <LineContainerComponent globalState={this.props.globalState} title="OUTLINE & OVERLAY" closed={true}>
  338. <CheckBoxLineComponent label="Render overlay" target={mesh} propertyName="renderOverlay" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  339. <Color3LineComponent label="Overlay color" target={mesh} propertyName="overlayColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  340. <CheckBoxLineComponent label="Render outline" target={mesh} propertyName="renderOutline" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  341. <Color3LineComponent label="Outline color" target={mesh} propertyName="outlineColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  342. </LineContainerComponent>
  343. <LineContainerComponent globalState={this.props.globalState} title="DEBUG" closed={true}>
  344. <CheckBoxLineComponent label="Display normals" isSelected={() => displayNormals} onSelect={() => this.displayNormals()} />
  345. <CheckBoxLineComponent label="Display vertex colors" isSelected={() => displayVertexColors} onSelect={() => this.displayVertexColors()} />
  346. {
  347. mesh.isVerticesDataPresent(VertexBuffer.NormalKind) &&
  348. <CheckBoxLineComponent label="Render vertex normals" isSelected={() => renderNormalVectors} onSelect={() => this.renderNormalVectors()} />
  349. }
  350. <CheckBoxLineComponent label="Render wireframe over mesh" isSelected={() => renderWireframeOver} onSelect={() => this.renderWireframeOver()} />
  351. </LineContainerComponent>
  352. </div>
  353. );
  354. }
  355. }