meshPropertyGridComponent.tsx 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. import * as React from "react";
  2. import { Observable } from "babylonjs/Misc/observable";
  3. import { Tools } from "babylonjs/Misc/tools";
  4. import { Vector3, TmpVectors } from "babylonjs/Maths/math.vector";
  5. import { Color3 } from 'babylonjs/Maths/math.color';
  6. import { Mesh } from "babylonjs/Meshes/mesh";
  7. import { VertexBuffer } from "babylonjs/Meshes/buffer";
  8. import { LinesBuilder } from "babylonjs/Meshes/Builders/linesBuilder";
  9. import { PhysicsImpostor } from "babylonjs/Physics/physicsImpostor";
  10. import { Scene } from "babylonjs/scene";
  11. import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
  12. import { LineContainerComponent } from "../../../lineContainerComponent";
  13. import { TextLineComponent } from "../../../lines/textLineComponent";
  14. import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
  15. import { Vector3LineComponent } from "../../../lines/vector3LineComponent";
  16. import { SliderLineComponent } from "../../../lines/sliderLineComponent";
  17. import { QuaternionLineComponent } from "../../../lines/quaternionLineComponent";
  18. import { FloatLineComponent } from "../../../lines/floatLineComponent";
  19. import { LockObject } from "../lockObject";
  20. import { GlobalState } from '../../../../globalState';
  21. import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
  22. import { StandardMaterial } from 'babylonjs/Materials/standardMaterial';
  23. import { Color3LineComponent } from '../../../lines/color3LineComponent';
  24. import { MorphTarget } from 'babylonjs/Morph/morphTarget';
  25. import { OptionsLineComponent } from '../../../lines/optionsLineComponent';
  26. import { AbstractMesh } from 'babylonjs/Meshes/abstractMesh';
  27. import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
  28. import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
  29. import { AnimationGridComponent } from '../animations/animationPropertyGridComponent';
  30. import { RenderingManager } from 'babylonjs/Rendering/renderingManager';
  31. import { CommonPropertyGridComponent } from '../commonPropertyGridComponent';
  32. import { VariantsPropertyGridComponent } from '../variantsPropertyGridComponent';
  33. import { HexLineComponent } from '../../../lines/hexLineComponent';
  34. import { SkeletonViewer } from 'babylonjs/Debug/skeletonViewer';
  35. import { ShaderMaterial } from 'babylonjs/Materials/shaderMaterial';
  36. interface IMeshPropertyGridComponentProps {
  37. globalState: GlobalState;
  38. mesh: Mesh;
  39. lockObject: LockObject;
  40. onSelectionChangedObservable?: Observable<any>;
  41. onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
  42. }
  43. export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGridComponentProps, {
  44. displayNormals: boolean,
  45. displayVertexColors: boolean,
  46. displayBoneWeights: boolean,
  47. displayBoneIndex: number,
  48. displaySkeletonMap:boolean
  49. }> {
  50. constructor(props: IMeshPropertyGridComponentProps) {
  51. super(props);
  52. this.state = {
  53. displayNormals: false,
  54. displayVertexColors: false,
  55. displayBoneWeights: false,
  56. displayBoneIndex: 0,
  57. displaySkeletonMap: false
  58. };
  59. }
  60. renderWireframeOver() {
  61. const mesh = this.props.mesh;
  62. const scene = mesh.getScene();
  63. if (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) {
  64. mesh.reservedDataStore.wireframeOver.dispose(false, true);
  65. mesh.reservedDataStore.wireframeOver = null;
  66. this.forceUpdate();
  67. return;
  68. }
  69. var wireframeOver = mesh.clone()!;
  70. wireframeOver.reservedDataStore = { hidden: true };
  71. // Sets up the mesh to be attached to the parent.
  72. // So all neutral in local space.
  73. wireframeOver.parent = mesh;
  74. wireframeOver.position = Vector3.Zero();
  75. wireframeOver.scaling = new Vector3(1, 1, 1);
  76. wireframeOver.rotation = Vector3.Zero();
  77. wireframeOver.rotationQuaternion = null;
  78. var material = new StandardMaterial("wireframeOver", scene);
  79. material.reservedDataStore = { hidden: true };
  80. wireframeOver.material = material;
  81. material.zOffset = 1;
  82. material.disableLighting = true;
  83. material.backFaceCulling = false;
  84. material.emissiveColor = Color3.White();
  85. material.wireframe = true;
  86. if (!mesh.reservedDataStore) {
  87. mesh.reservedDataStore = {};
  88. }
  89. mesh.reservedDataStore.wireframeOver = wireframeOver;
  90. this.forceUpdate();
  91. }
  92. renderNormalVectors() {
  93. const mesh = this.props.mesh;
  94. const scene = mesh.getScene();
  95. if (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) {
  96. mesh.reservedDataStore.normalLines.dispose();
  97. mesh.reservedDataStore.normalLines = null;
  98. this.forceUpdate();
  99. return;
  100. }
  101. var normals = mesh.getVerticesData(VertexBuffer.NormalKind);
  102. var positions = mesh.getVerticesData(VertexBuffer.PositionKind);
  103. const color = Color3.White();
  104. const bbox = mesh.getBoundingInfo();
  105. const diag = bbox.maximum.subtractToRef(bbox.minimum, TmpVectors.Vector3[0]);
  106. const size = diag.length() * 0.05;
  107. var lines = [];
  108. for (var i = 0; i < normals!.length; i += 3) {
  109. var v1 = Vector3.FromArray(positions!, i);
  110. var v2 = v1.add(Vector3.FromArray(normals!, i).scaleInPlace(size));
  111. lines.push([v1, v2]);
  112. }
  113. var normalLines = LinesBuilder.CreateLineSystem("normalLines", { lines: lines }, scene);
  114. normalLines.color = color;
  115. normalLines.parent = mesh;
  116. normalLines.reservedDataStore = { hidden: true };
  117. if (!mesh.reservedDataStore) {
  118. mesh.reservedDataStore = {};
  119. }
  120. mesh.reservedDataStore.normalLines = normalLines;
  121. this.forceUpdate();
  122. }
  123. displayNormals() {
  124. const mesh = this.props.mesh;
  125. const scene = mesh.getScene();
  126. if (mesh.material && mesh.material.getClassName() === "NormalMaterial") {
  127. mesh.material.dispose();
  128. mesh.material = mesh.reservedDataStore.originalMaterial;
  129. mesh.reservedDataStore.originalMaterial = null;
  130. this.setState({ displayNormals: false });
  131. } else {
  132. if (!(BABYLON as any).NormalMaterial) {
  133. this.setState({ displayNormals: true });
  134. Tools.LoadScript("https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.js", () => {
  135. this.displayNormals();
  136. });
  137. return;
  138. }
  139. if (!mesh.reservedDataStore) {
  140. mesh.reservedDataStore = {};
  141. }
  142. if (!mesh.reservedDataStore.originalMaterial) {
  143. mesh.reservedDataStore.originalMaterial = mesh.material;
  144. }
  145. const normalMaterial = new (BABYLON as any).NormalMaterial("normalMaterial", scene);
  146. normalMaterial.disableLighting = true;
  147. if (mesh.material) {
  148. normalMaterial.sideOrientation = mesh.material.sideOrientation;
  149. }
  150. normalMaterial.reservedDataStore = { hidden: true };
  151. mesh.material = normalMaterial;
  152. this.setState({ displayNormals: true });
  153. }
  154. }
  155. displayVertexColors() {
  156. const mesh = this.props.mesh;
  157. const scene = mesh.getScene();
  158. if (mesh.material && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial) {
  159. mesh.material.dispose();
  160. mesh.material = mesh.reservedDataStore.originalMaterial;
  161. mesh.reservedDataStore.originalMaterial = null;
  162. this.setState({ displayVertexColors: false });
  163. } else {
  164. if (!mesh.reservedDataStore) {
  165. mesh.reservedDataStore = {};
  166. }
  167. if (!mesh.reservedDataStore.originalMaterial) {
  168. mesh.reservedDataStore.originalMaterial = mesh.material;
  169. }
  170. const vertexColorMaterial = new StandardMaterial("vertex colors", scene);
  171. vertexColorMaterial.disableLighting = true;
  172. vertexColorMaterial.emissiveColor = Color3.White();
  173. if (mesh.material) {
  174. vertexColorMaterial.sideOrientation = mesh.material.sideOrientation;
  175. }
  176. vertexColorMaterial.reservedDataStore = { hidden: true, isVertexColorMaterial: true };
  177. mesh.useVertexColors = true;
  178. mesh.material = vertexColorMaterial;
  179. this.setState({ displayVertexColors: true });
  180. }
  181. }
  182. displayBoneWeights() {
  183. const mesh = this.props.mesh;
  184. const scene = mesh.getScene();
  185. if (mesh.material && mesh.material.getClassName() === "BoneWeightShader") {
  186. mesh.material.dispose();
  187. mesh.material = mesh.reservedDataStore.originalMaterial;
  188. mesh.reservedDataStore.originalMaterial = null;
  189. this.setState({ displayBoneWeights: false });
  190. } else {
  191. if (!mesh.reservedDataStore) {
  192. mesh.reservedDataStore = {};
  193. }
  194. if (!mesh.reservedDataStore.originalMaterial) {
  195. mesh.reservedDataStore.originalMaterial = mesh.material;
  196. }
  197. if (!mesh.reservedDataStore.displayBoneIndex) {
  198. mesh.reservedDataStore.displayBoneIndex = this.state.displayBoneIndex;
  199. }
  200. if (mesh.skeleton){
  201. const boneWeightsShader = SkeletonViewer.CreateBoneWeightShader({skeleton:mesh.skeleton}, scene)
  202. boneWeightsShader.reservedDataStore = { hidden: true };
  203. mesh.material = boneWeightsShader;
  204. this.setState({ displayBoneWeights: true });
  205. }
  206. }
  207. }
  208. displaySkeletonMap() {
  209. const mesh = this.props.mesh;
  210. const scene = mesh.getScene();
  211. if (mesh.material && mesh.material.getClassName() === "SkeletonMapShader") {
  212. mesh.material.dispose();
  213. mesh.material = mesh.reservedDataStore.originalMaterial;
  214. mesh.reservedDataStore.originalMaterial = null;
  215. this.setState({ displaySkeletonMap: false });
  216. } else {
  217. if (!mesh.reservedDataStore) {
  218. mesh.reservedDataStore = {};
  219. }
  220. if (!mesh.reservedDataStore.originalMaterial) {
  221. mesh.reservedDataStore.originalMaterial = mesh.material;
  222. }
  223. if (mesh.skeleton){
  224. const skeletonMapShader = SkeletonViewer.CreateSkeletonMapShader({skeleton:mesh.skeleton}, scene)
  225. skeletonMapShader.reservedDataStore = { hidden: true };
  226. mesh.material = skeletonMapShader;
  227. this.setState({ displaySkeletonMap: true });
  228. }
  229. }
  230. }
  231. onBoneDisplayIndexChange(value:number):void{
  232. let mesh = this.props.mesh
  233. mesh.reservedDataStore.displayBoneIndex = value
  234. this.setState({ displayBoneIndex: value });
  235. if (mesh.material && mesh.material.getClassName() === "BoneWeightShader") {
  236. (mesh.material as ShaderMaterial).setFloat('targetBoneIndex', value)
  237. }
  238. }
  239. onMaterialLink() {
  240. if (!this.props.onSelectionChangedObservable) {
  241. return;
  242. }
  243. const mesh = this.props.mesh;
  244. this.props.onSelectionChangedObservable.notifyObservers(mesh.material);
  245. }
  246. onSourceMeshLink() {
  247. if (!this.props.onSelectionChangedObservable) {
  248. return;
  249. }
  250. const instanceMesh = this.props.mesh as any;
  251. this.props.onSelectionChangedObservable.notifyObservers(instanceMesh.sourceMesh);
  252. }
  253. onSkeletonLink() {
  254. if (!this.props.onSelectionChangedObservable) {
  255. return;
  256. }
  257. const mesh = this.props.mesh;
  258. this.props.onSelectionChangedObservable.notifyObservers(mesh.skeleton);
  259. }
  260. convertPhysicsTypeToString(): string {
  261. const mesh = this.props.mesh;
  262. switch (mesh.physicsImpostor!.type) {
  263. case PhysicsImpostor.NoImpostor:
  264. return "No impostor";
  265. case PhysicsImpostor.SphereImpostor:
  266. return "Sphere";
  267. case PhysicsImpostor.BoxImpostor:
  268. return "Box";
  269. case PhysicsImpostor.PlaneImpostor:
  270. return "Plane";
  271. case PhysicsImpostor.MeshImpostor:
  272. return "Mesh";
  273. case PhysicsImpostor.CylinderImpostor:
  274. return "Cylinder";
  275. case PhysicsImpostor.ParticleImpostor:
  276. return "Particle";
  277. case PhysicsImpostor.HeightmapImpostor:
  278. return "Heightmap";
  279. case PhysicsImpostor.ConvexHullImpostor:
  280. return "Convex hull";
  281. case PhysicsImpostor.RopeImpostor:
  282. return "Rope";
  283. case PhysicsImpostor.SoftbodyImpostor:
  284. return "Soft body";
  285. }
  286. return "Unknown";
  287. }
  288. render() {
  289. const mesh = this.props.mesh;
  290. const scene = mesh.getScene();
  291. const displayNormals = mesh.material != null && mesh.material.getClassName() === "NormalMaterial";
  292. const displayVertexColors = !!(mesh.material != null && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial);
  293. const renderNormalVectors = (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) ? true : false;
  294. const renderWireframeOver = (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) ? true : false;
  295. const displayBoneWeights = mesh.material != null && mesh.material.getClassName() === "BoneWeightShader";
  296. const displaySkeletonMap = mesh.material != null && mesh.material.getClassName() === "SkeletonMapShader";
  297. var morphTargets: MorphTarget[] = [];
  298. if (mesh.morphTargetManager) {
  299. for (var index = 0; index < mesh.morphTargetManager.numTargets; index++) {
  300. morphTargets.push(mesh.morphTargetManager.getTarget(index));
  301. }
  302. }
  303. var algorithmOptions = [
  304. { label: "Accurate", value: AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE },
  305. { label: "Conservative", value: AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE },
  306. ];
  307. var occlusionTypeOptions = [
  308. { label: "None", value: AbstractMesh.OCCLUSION_TYPE_NONE },
  309. { label: "Optimistic", value: AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC },
  310. { label: "Strict", value: AbstractMesh.OCCLUSION_TYPE_STRICT },
  311. ];
  312. let sortedMaterials = scene.materials.slice(0).sort((a, b) => (a.name || "no name").localeCompare(b.name || "no name"));
  313. var materialOptions = sortedMaterials.map((m, i) => {
  314. return {
  315. label: m.name || "no name",
  316. value: i
  317. };});
  318. materialOptions.splice(0, 0, {
  319. label: "None (Default Fallback)",
  320. value: -1
  321. });
  322. return (
  323. <div className="pane">
  324. <CustomPropertyGridComponent globalState={this.props.globalState} target={mesh}
  325. lockObject={this.props.lockObject}
  326. onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  327. <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
  328. <TextLineComponent label="ID" value={mesh.id} />
  329. <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={mesh} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
  330. <TextLineComponent label="Unique ID" value={mesh.uniqueId.toString()} />
  331. <TextLineComponent label="Class" value={mesh.getClassName()} />
  332. <TextLineComponent label="Vertices" value={mesh.getTotalVertices().toString()} />
  333. <TextLineComponent label="Faces" value={(mesh.getTotalIndices() / 3).toFixed(0)} />
  334. <TextLineComponent label="Sub-meshes" value={mesh.subMeshes ? mesh.subMeshes.length.toString() : "0"} />
  335. {
  336. mesh.parent &&
  337. <TextLineComponent label="Parent" value={mesh.parent.name} onLink={() => this.props.globalState.onSelectionChangedObservable.notifyObservers(mesh.parent)}/>
  338. }
  339. {
  340. mesh.skeleton &&
  341. <TextLineComponent label="Skeleton" value={mesh.skeleton.name} onLink={() => this.onSkeletonLink()}/>
  342. }
  343. <CheckBoxLineComponent label="Is enabled" isSelected={() => mesh.isEnabled()} onSelect={(value) => mesh.setEnabled(value)} />
  344. <CheckBoxLineComponent label="Is pickable" target={mesh} propertyName="isPickable" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  345. {
  346. mesh.material && (!mesh.material.reservedDataStore || !mesh.material.reservedDataStore.hidden) &&
  347. <TextLineComponent label="Link to material" value={mesh.material.name} onLink={() => this.onMaterialLink()} />
  348. }
  349. { !mesh.isAnInstance &&
  350. <OptionsLineComponent label="Active material" options={materialOptions}
  351. target={mesh} propertyName="material"
  352. noDirectUpdate={true}
  353. onSelect={(value: number) => {
  354. if (value < 0) {
  355. mesh.material = null;
  356. } else {
  357. mesh.material = sortedMaterials[value];
  358. }
  359. this.forceUpdate();
  360. }}
  361. extractValue={() => mesh.material ? sortedMaterials.indexOf(mesh.material) : -1}
  362. onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  363. }
  364. {
  365. mesh.isAnInstance &&
  366. <TextLineComponent label="Source" value={(mesh as any).sourceMesh.name} onLink={() => this.onSourceMeshLink()} />
  367. }
  368. <ButtonLineComponent label="Dispose" onClick={() => {
  369. mesh.dispose();
  370. this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
  371. }} />
  372. </LineContainerComponent>
  373. <CommonPropertyGridComponent host={mesh} lockObject={this.props.lockObject} globalState={this.props.globalState} />
  374. <VariantsPropertyGridComponent host={mesh} lockObject={this.props.lockObject} globalState={this.props.globalState} />
  375. <LineContainerComponent globalState={this.props.globalState} title="TRANSFORMS">
  376. <Vector3LineComponent label="Position" target={mesh} propertyName="position" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  377. {
  378. !mesh.rotationQuaternion &&
  379. <Vector3LineComponent label="Rotation" useEuler={this.props.globalState.onlyUseEulers} target={mesh} propertyName="rotation" step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  380. }
  381. {
  382. mesh.rotationQuaternion &&
  383. <QuaternionLineComponent label="Rotation" useEuler={this.props.globalState.onlyUseEulers} target={mesh} propertyName="rotationQuaternion" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  384. }
  385. <Vector3LineComponent label="Scaling" target={mesh} propertyName="scaling" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  386. </LineContainerComponent>
  387. <LineContainerComponent globalState={this.props.globalState} title="DISPLAY" closed={true}>
  388. {
  389. !mesh.isAnInstance &&
  390. <SliderLineComponent label="Visibility" target={mesh} propertyName="visibility" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  391. }
  392. <FloatLineComponent lockObject={this.props.lockObject} label="Alpha index" target={mesh} propertyName="alphaIndex" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  393. <CheckBoxLineComponent label="Receive shadows" target={mesh} propertyName="receiveShadows" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  394. {
  395. mesh.isVerticesDataPresent(VertexBuffer.ColorKind) &&
  396. <CheckBoxLineComponent label="Use vertex colors" target={mesh} propertyName="useVertexColors" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  397. }
  398. {
  399. mesh.isVerticesDataPresent(VertexBuffer.ColorKind) &&
  400. <CheckBoxLineComponent label="Has vertex alpha" target={mesh} propertyName="hasVertexAlpha" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  401. }
  402. {
  403. scene.fogMode !== Scene.FOGMODE_NONE &&
  404. <CheckBoxLineComponent label="Apply fog" target={mesh} propertyName="applyFog" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  405. }
  406. {
  407. !mesh.parent &&
  408. <CheckBoxLineComponent label="Infinite distance" target={mesh} propertyName="infiniteDistance" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  409. }
  410. <SliderLineComponent label="Rendering group ID" decimalCount={0} target={mesh} propertyName="renderingGroupId" minimum={RenderingManager.MIN_RENDERINGGROUPS} maximum={RenderingManager.MAX_RENDERINGGROUPS - 1} step={1} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  411. <HexLineComponent isInteger lockObject={this.props.lockObject} label="Layer mask" target={mesh} propertyName="layerMask" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  412. </LineContainerComponent>
  413. {
  414. mesh.morphTargetManager != null &&
  415. <LineContainerComponent globalState={this.props.globalState} title="MORPH TARGETS" closed={true}>
  416. {
  417. morphTargets.map((mt, i) => {
  418. return (
  419. <SliderLineComponent key={i} label={mt.name} target={mt} propertyName="influence" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  420. );
  421. })
  422. }
  423. </LineContainerComponent>
  424. }
  425. <AnimationGridComponent globalState={this.props.globalState} animatable={mesh} scene={mesh.getScene()} lockObject={this.props.lockObject} />
  426. <LineContainerComponent globalState={this.props.globalState} title="ADVANCED" closed={true}>
  427. {
  428. mesh.useBones &&
  429. <CheckBoxLineComponent label="Compute bones using shaders" target={mesh} propertyName="computeBonesUsingShaders" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  430. }
  431. <CheckBoxLineComponent label="Collisions" target={mesh} propertyName="checkCollisions" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  432. <TextLineComponent label="Geometry ID" value={mesh.geometry?.uniqueId.toString()} />
  433. <TextLineComponent label="Has normals" value={mesh.isVerticesDataPresent(VertexBuffer.NormalKind) ? "Yes" : "No"} />
  434. <TextLineComponent label="Has vertex colors" value={mesh.isVerticesDataPresent(VertexBuffer.ColorKind) ? "Yes" : "No"} />
  435. <TextLineComponent label="Has UV set 0" value={mesh.isVerticesDataPresent(VertexBuffer.UVKind) ? "Yes" : "No"} />
  436. <TextLineComponent label="Has UV set 1" value={mesh.isVerticesDataPresent(VertexBuffer.UV2Kind) ? "Yes" : "No"} />
  437. <TextLineComponent label="Has UV set 2" value={mesh.isVerticesDataPresent(VertexBuffer.UV3Kind) ? "Yes" : "No"} />
  438. <TextLineComponent label="Has UV set 3" value={mesh.isVerticesDataPresent(VertexBuffer.UV4Kind) ? "Yes" : "No"} />
  439. <TextLineComponent label="Has tangents" value={mesh.isVerticesDataPresent(VertexBuffer.TangentKind) ? "Yes" : "No"} />
  440. <TextLineComponent label="Has matrix weights" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind) ? "Yes" : "No"} />
  441. <TextLineComponent label="Has matrix indices" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind) ? "Yes" : "No"} />
  442. </LineContainerComponent>
  443. {
  444. mesh.physicsImpostor != null &&
  445. <LineContainerComponent globalState={this.props.globalState} title="PHYSICS" closed={true}>
  446. <FloatLineComponent lockObject={this.props.lockObject} label="Mass" target={mesh.physicsImpostor} propertyName="mass" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  447. <FloatLineComponent lockObject={this.props.lockObject} label="Friction" target={mesh.physicsImpostor} propertyName="friction" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  448. <FloatLineComponent lockObject={this.props.lockObject} label="Restitution" target={mesh.physicsImpostor} propertyName="restitution" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  449. <TextLineComponent label="Type" value={this.convertPhysicsTypeToString()} />
  450. </LineContainerComponent>
  451. }
  452. <LineContainerComponent globalState={this.props.globalState} title="OCCLUSIONS" closed={true}>
  453. <OptionsLineComponent label="Type" options={occlusionTypeOptions} target={mesh} propertyName="occlusionType" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  454. <SliderLineComponent label="Retry count" minimum={-1} maximum={10} decimalCount={0} step={1} target={mesh} propertyName="occlusionRetryCount" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  455. <OptionsLineComponent label="Algorithm" options={algorithmOptions} target={mesh} propertyName="occlusionQueryAlgorithmType" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  456. </LineContainerComponent>
  457. <LineContainerComponent globalState={this.props.globalState} title="EDGE RENDERING" closed={true}>
  458. <CheckBoxLineComponent label="Enable" target={mesh} isSelected={() => mesh.edgesRenderer != null} onSelect={(value) => {
  459. if (value) {
  460. mesh.enableEdgesRendering();
  461. } else {
  462. mesh.disableEdgesRendering();
  463. }
  464. }} />
  465. <SliderLineComponent label="Edge width" minimum={0} maximum={10} step={0.1} target={mesh} propertyName="edgesWidth" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  466. <Color3LineComponent label="Edge color" target={mesh} propertyName="edgesColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  467. </LineContainerComponent>
  468. {
  469. !mesh.isAnInstance &&
  470. <LineContainerComponent globalState={this.props.globalState} title="OUTLINE & OVERLAY" closed={true}>
  471. <CheckBoxLineComponent label="Render overlay" target={mesh} propertyName="renderOverlay" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  472. <Color3LineComponent label="Overlay color" target={mesh} propertyName="overlayColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  473. <CheckBoxLineComponent label="Render outline" target={mesh} propertyName="renderOutline" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  474. <Color3LineComponent label="Outline color" target={mesh} propertyName="outlineColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
  475. </LineContainerComponent>
  476. }
  477. <LineContainerComponent globalState={this.props.globalState} title="DEBUG" closed={true}>
  478. {
  479. !mesh.isAnInstance &&
  480. <CheckBoxLineComponent label="Display normals" isSelected={() => displayNormals} onSelect={() => this.displayNormals()} />
  481. }
  482. {
  483. !mesh.isAnInstance &&
  484. <CheckBoxLineComponent label="Display vertex colors" isSelected={() => displayVertexColors} onSelect={() => this.displayVertexColors()} />
  485. }
  486. {
  487. mesh.isVerticesDataPresent(VertexBuffer.NormalKind) &&
  488. <CheckBoxLineComponent label="Render vertex normals" isSelected={() => renderNormalVectors} onSelect={() => this.renderNormalVectors()} />
  489. }
  490. {
  491. !mesh.isAnInstance &&
  492. <CheckBoxLineComponent label="Render wireframe over mesh" isSelected={() => renderWireframeOver} onSelect={() => this.renderWireframeOver()} />
  493. }
  494. {
  495. !mesh.isAnInstance && mesh.skeleton &&
  496. <CheckBoxLineComponent label="Display BoneWeights" isSelected={() => displayBoneWeights} onSelect={() => this.displayBoneWeights()} />
  497. }
  498. {
  499. !mesh.isAnInstance && this.state.displayBoneWeights && mesh.skeleton &&
  500. <SliderLineComponent label="Target Bone" decimalCount={0} target={mesh.reservedDataStore} propertyName="displayBoneIndex" minimum={0} maximum={mesh.skeleton.bones.length-1 || 0} step={1} onChange={(value)=>{this.onBoneDisplayIndexChange(value)}} />
  501. }
  502. {
  503. !mesh.isAnInstance && mesh.skeleton &&
  504. <CheckBoxLineComponent label="Display SkeletonMap" isSelected={() => displaySkeletonMap } onSelect={() => this.displaySkeletonMap()} />
  505. }
  506. </LineContainerComponent>
  507. </div>
  508. );
  509. }
  510. }