meshPropertyGridComponent.tsx 32 KB

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