浏览代码

Merge pull request #9131 from RaananW/boneTargetNameOptions

Bone target name select box
David Catuhe 4 年之前
父节点
当前提交
fd74b788c9

+ 1 - 0
dist/preview release/what's new.md

@@ -98,6 +98,7 @@
 - View & edit textures in pop out inspector using tools such as brush and floodfill. Supports region selection, individual channel editing, mipmap previews, and resizing. ([DarraghBurkeMS](https://github.com/DarraghBurkeMS))
 - Added mesh debug tools to display bone influence weights and bone indices maps. ([Pryme8](https://github.com/Pryme8))
 - Added more functionality and options to the skeleton debug panel. ([Pryme8](https://github.com/Pryme8))
+- Along with bone index it is now possible to select a bone using its name when viewing bone weights ([#9117](https://github.com/BabylonJS/Babylon.js/issues/9117)) ([RaananW](https://github.com/RaananW))
 
 ### Cameras
 

+ 11 - 13
inspector/src/components/actionTabs/lines/optionsLineComponent.tsx

@@ -5,12 +5,13 @@ import { PropertyChangedEvent } from "../../propertyChangedEvent";
 
 export const Null_Value = Number.MAX_SAFE_INTEGER;
 
-class ListLineOption {
+export class ListLineOption {
     public label: string;
     public value: number;
+    selected?: boolean;
 }
 
-interface IOptionsLineComponentProps {
+export interface IOptionsLineComponentProps {
     label: string;
     target: any;
     propertyName: string;
@@ -90,19 +91,16 @@ export class OptionsLineComponent extends React.Component<IOptionsLineComponentP
     render() {
         return (
             <div className="listLine">
-                <div className="label">
-                    {this.props.label}
-
-                </div>
+                <div className="label">{this.props.label}</div>
                 <div className="options">
                     <select onChange={(evt) => this.updateValue(evt.target.value)} value={this.state.value ?? ""}>
-                        {
-                            this.props.options.map((option, i) => {
-                                return (
-                                    <option key={option.label + i} value={option.value}>{option.label}</option>
-                                );
-                            })
-                        }
+                        {this.props.options.map((option, i) => {
+                            return (
+                                <option selected={option.selected} key={option.label + i} value={option.value}>
+                                    {option.label}
+                                </option>
+                            );
+                        })}
                     </select>
                 </div>
             </div>

+ 152 - 164
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx

@@ -3,7 +3,7 @@ import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Tools } from "babylonjs/Misc/tools";
 import { Vector3, TmpVectors } from "babylonjs/Maths/math.vector";
-import { Color3 } from 'babylonjs/Maths/math.color';
+import { Color3 } from "babylonjs/Maths/math.color";
 import { Mesh } from "babylonjs/Meshes/mesh";
 import { VertexBuffer } from "babylonjs/Meshes/buffer";
 import { LinesBuilder } from "babylonjs/Meshes/Builders/linesBuilder";
@@ -19,22 +19,22 @@ import { SliderLineComponent } from "../../../lines/sliderLineComponent";
 import { QuaternionLineComponent } from "../../../lines/quaternionLineComponent";
 import { FloatLineComponent } from "../../../lines/floatLineComponent";
 import { LockObject } from "../lockObject";
-import { GlobalState } from '../../../../globalState';
-import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
-import { StandardMaterial } from 'babylonjs/Materials/standardMaterial';
-import { Color3LineComponent } from '../../../lines/color3LineComponent';
-import { MorphTarget } from 'babylonjs/Morph/morphTarget';
-import { OptionsLineComponent } from '../../../lines/optionsLineComponent';
-import { AbstractMesh } from 'babylonjs/Meshes/abstractMesh';
-import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
-import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
-import { AnimationGridComponent } from '../animations/animationPropertyGridComponent';
-import { RenderingManager } from 'babylonjs/Rendering/renderingManager';
-import { CommonPropertyGridComponent } from '../commonPropertyGridComponent';
-import { VariantsPropertyGridComponent } from '../variantsPropertyGridComponent';
-import { HexLineComponent } from '../../../lines/hexLineComponent';
-import { SkeletonViewer } from 'babylonjs/Debug/skeletonViewer';
-import { ShaderMaterial } from 'babylonjs/Materials/shaderMaterial';
+import { GlobalState } from "../../../../globalState";
+import { CustomPropertyGridComponent } from "../customPropertyGridComponent";
+import { StandardMaterial } from "babylonjs/Materials/standardMaterial";
+import { Color3LineComponent } from "../../../lines/color3LineComponent";
+import { MorphTarget } from "babylonjs/Morph/morphTarget";
+import { OptionsLineComponent, ListLineOption } from "../../../lines/optionsLineComponent";
+import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+import { ButtonLineComponent } from "../../../lines/buttonLineComponent";
+import { TextInputLineComponent } from "../../../lines/textInputLineComponent";
+import { AnimationGridComponent } from "../animations/animationPropertyGridComponent";
+import { RenderingManager } from "babylonjs/Rendering/renderingManager";
+import { CommonPropertyGridComponent } from "../commonPropertyGridComponent";
+import { VariantsPropertyGridComponent } from "../variantsPropertyGridComponent";
+import { HexLineComponent } from "../../../lines/hexLineComponent";
+import { SkeletonViewer } from "babylonjs/Debug/skeletonViewer";
+import { ShaderMaterial } from "babylonjs/Materials/shaderMaterial";
 
 interface IMeshPropertyGridComponentProps {
     globalState: GlobalState;
@@ -44,16 +44,19 @@ interface IMeshPropertyGridComponentProps {
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
 }
 
-export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGridComponentProps, {
-    displayNormals: boolean,
-    displayVertexColors: boolean,
-    displayBoneWeights: boolean,
-    displayBoneIndex: number,
-    displaySkeletonMap:boolean
-}> {
+export class MeshPropertyGridComponent extends React.Component<
+    IMeshPropertyGridComponentProps,
+    {
+        displayNormals: boolean;
+        displayVertexColors: boolean;
+        displayBoneWeights: boolean;
+        displayBoneIndex: number;
+        displaySkeletonMap: boolean;
+    }
+> {
     constructor(props: IMeshPropertyGridComponentProps) {
         super(props);
-        
+
         const mesh = this.props.mesh;
 
         this.state = {
@@ -61,7 +64,7 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
             displayVertexColors: false,
             displayBoneWeights: !!(mesh.material && mesh.material.getClassName() === "BoneWeightShader"),
             displayBoneIndex: 0,
-            displaySkeletonMap: false
+            displaySkeletonMap: false,
         };
     }
 
@@ -159,7 +162,6 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
             mesh.reservedDataStore.originalMaterial = null;
             this.setState({ displayNormals: false });
         } else {
-
             if (!(BABYLON as any).NormalMaterial) {
                 this.setState({ displayNormals: true });
                 Tools.LoadScript("https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.js", () => {
@@ -198,7 +200,6 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
             mesh.reservedDataStore.originalMaterial = null;
             this.setState({ displayVertexColors: false });
         } else {
-
             if (!mesh.reservedDataStore) {
                 mesh.reservedDataStore = {};
             }
@@ -229,7 +230,6 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
             mesh.reservedDataStore.originalMaterial = null;
             this.setState({ displayBoneWeights: false });
         } else {
-          
             if (!mesh.reservedDataStore) {
                 mesh.reservedDataStore = {};
             }
@@ -239,12 +239,12 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
             if (!mesh.reservedDataStore.displayBoneIndex) {
                 mesh.reservedDataStore.displayBoneIndex = this.state.displayBoneIndex;
             }
-            if (mesh.skeleton){
-                const boneWeightsShader = SkeletonViewer.CreateBoneWeightShader({skeleton:mesh.skeleton}, scene)
+            if (mesh.skeleton) {
+                const boneWeightsShader = SkeletonViewer.CreateBoneWeightShader({ skeleton: mesh.skeleton }, scene);
                 boneWeightsShader.reservedDataStore = { hidden: true };
                 mesh.material = boneWeightsShader;
                 this.setState({ displayBoneWeights: true });
-            }            
+            }
         }
     }
 
@@ -257,28 +257,28 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
             mesh.material = mesh.reservedDataStore.originalMaterial;
             mesh.reservedDataStore.originalMaterial = null;
             this.setState({ displaySkeletonMap: false });
-        } else {          
+        } else {
             if (!mesh.reservedDataStore) {
                 mesh.reservedDataStore = {};
             }
             if (!mesh.reservedDataStore.originalMaterial) {
                 mesh.reservedDataStore.originalMaterial = mesh.material;
-            }  
-            if (mesh.skeleton){
-                const skeletonMapShader = SkeletonViewer.CreateSkeletonMapShader({skeleton:mesh.skeleton}, scene)
+            }
+            if (mesh.skeleton) {
+                const skeletonMapShader = SkeletonViewer.CreateSkeletonMapShader({ skeleton: mesh.skeleton }, scene);
                 skeletonMapShader.reservedDataStore = { hidden: true };
                 mesh.material = skeletonMapShader;
                 this.setState({ displaySkeletonMap: true });
-            }            
+            }
         }
     }
 
-    onBoneDisplayIndexChange(value:number):void{
-        let mesh = this.props.mesh
-        mesh.reservedDataStore.displayBoneIndex = value
+    onBoneDisplayIndexChange(value: number): void {
+        let mesh = this.props.mesh;
+        mesh.reservedDataStore.displayBoneIndex = value;
         this.setState({ displayBoneIndex: value });
         if (mesh.material && mesh.material.getClassName() === "BoneWeightShader") {
-            (mesh.material as ShaderMaterial).setFloat('targetBoneIndex', value)
+            (mesh.material as ShaderMaterial).setFloat("targetBoneIndex", value);
         }
     }
 
@@ -345,8 +345,8 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
 
         const displayNormals = mesh.material != null && mesh.material.getClassName() === "NormalMaterial";
         const displayVertexColors = !!(mesh.material != null && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial);
-        const renderNormalVectors = (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) ? true : false;
-        const renderWireframeOver = (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) ? true : false;
+        const renderNormalVectors = mesh.reservedDataStore && mesh.reservedDataStore.normalLines ? true : false;
+        const renderWireframeOver = mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver ? true : false;
         const displayBoneWeights = mesh.material != null && mesh.material.getClassName() === "BoneWeightShader";
         const displaySkeletonMap = mesh.material != null && mesh.material.getClassName() === "SkeletonMapShader";
 
@@ -371,47 +371,47 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
 
         let sortedMaterials = scene.materials.slice(0).sort((a, b) => (a.name || "no name").localeCompare(b.name || "no name"));
 
-        var materialOptions = sortedMaterials.map((m, i) => {
+        const materialOptions = sortedMaterials.map((m, i) => {
             return {
                 label: m.name || "no name",
-                value: i
-            };});
+                value: i,
+            };
+        });
 
         materialOptions.splice(0, 0, {
             label: "None (Default Fallback)",
-            value: -1
+            value: -1,
         });
 
+        const targetBoneOptions: ListLineOption[] = mesh.skeleton ? mesh.skeleton.bones.map((bone, idx) => {
+            return {
+                label: bone.name,
+                value: idx,
+            };
+        }) : [];
+
         return (
             <div className="pane">
-                <CustomPropertyGridComponent globalState={this.props.globalState} target={mesh}
-                    lockObject={this.props.lockObject}
-                    onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                <CustomPropertyGridComponent globalState={this.props.globalState} target={mesh} lockObject={this.props.lockObject} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
                     <TextLineComponent label="ID" value={mesh.id} />
-                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={mesh} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
+                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={mesh} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <TextLineComponent label="Unique ID" value={mesh.uniqueId.toString()} />
                     <TextLineComponent label="Class" value={mesh.getClassName()} />
                     <TextLineComponent label="Vertices" value={mesh.getTotalVertices().toString()} />
                     <TextLineComponent label="Faces" value={(mesh.getTotalIndices() / 3).toFixed(0)} />
                     <TextLineComponent label="Sub-meshes" value={mesh.subMeshes ? mesh.subMeshes.length.toString() : "0"} />
-                    {
-                        mesh.parent &&
-                        <TextLineComponent label="Parent" value={mesh.parent.name} onLink={() => this.props.globalState.onSelectionChangedObservable.notifyObservers(mesh.parent)}/>
-                    }
-                    {
-                        mesh.skeleton &&
-                        <TextLineComponent label="Skeleton" value={mesh.skeleton.name} onLink={() => this.onSkeletonLink()}/>
-                    }
+                    {mesh.parent && <TextLineComponent label="Parent" value={mesh.parent.name} onLink={() => this.props.globalState.onSelectionChangedObservable.notifyObservers(mesh.parent)} />}
+                    {mesh.skeleton && <TextLineComponent label="Skeleton" value={mesh.skeleton.name} onLink={() => this.onSkeletonLink()} />}
                     <CheckBoxLineComponent label="Is enabled" isSelected={() => mesh.isEnabled()} onSelect={(value) => mesh.setEnabled(value)} />
                     <CheckBoxLineComponent label="Is pickable" target={mesh} propertyName="isPickable" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    {
-                        mesh.material && (!mesh.material.reservedDataStore || !mesh.material.reservedDataStore.hidden) &&
-                        <TextLineComponent label="Link to material" value={mesh.material.name} onLink={() => this.onMaterialLink()} />
-                    }
-                    {   !mesh.isAnInstance &&
-                        <OptionsLineComponent label="Active material" options={materialOptions}
-                            target={mesh} propertyName="material"
+                    {mesh.material && (!mesh.material.reservedDataStore || !mesh.material.reservedDataStore.hidden) && <TextLineComponent label="Link to material" value={mesh.material.name} onLink={() => this.onMaterialLink()} />}
+                    {!mesh.isAnInstance && (
+                        <OptionsLineComponent
+                            label="Active material"
+                            options={materialOptions}
+                            target={mesh}
+                            propertyName="material"
                             noDirectUpdate={true}
                             onSelect={(value: number) => {
                                 if (value < 0) {
@@ -422,77 +422,57 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
 
                                 this.forceUpdate();
                             }}
-                            extractValue={() => mesh.material ? sortedMaterials.indexOf(mesh.material) : -1}
-                            onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    }
-                    {
-                        mesh.isAnInstance &&
-                        <TextLineComponent label="Source" value={(mesh as any).sourceMesh.name} onLink={() => this.onSourceMeshLink()} />
-                    }
-                    <ButtonLineComponent label="Dispose" onClick={() => {
-                        mesh.dispose();
-                        this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
-                    }} />
+                            extractValue={() => (mesh.material ? sortedMaterials.indexOf(mesh.material) : -1)}
+                            onPropertyChangedObservable={this.props.onPropertyChangedObservable}
+                        />
+                    )}
+                    {mesh.isAnInstance && <TextLineComponent label="Source" value={(mesh as any).sourceMesh.name} onLink={() => this.onSourceMeshLink()} />}
+                    <ButtonLineComponent
+                        label="Dispose"
+                        onClick={() => {
+                            mesh.dispose();
+                            this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
+                        }}
+                    />
                 </LineContainerComponent>
                 <CommonPropertyGridComponent host={mesh} lockObject={this.props.lockObject} globalState={this.props.globalState} />
                 <VariantsPropertyGridComponent host={mesh} lockObject={this.props.lockObject} globalState={this.props.globalState} />
                 <LineContainerComponent globalState={this.props.globalState} title="TRANSFORMS">
                     <Vector3LineComponent label="Position" target={mesh} propertyName="position" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    {
-                        !mesh.rotationQuaternion &&
-                        <Vector3LineComponent label="Rotation" useEuler={this.props.globalState.onlyUseEulers} target={mesh} propertyName="rotation" step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    }
-                    {
-                        mesh.rotationQuaternion &&
-                        <QuaternionLineComponent label="Rotation" useEuler={this.props.globalState.onlyUseEulers} target={mesh} propertyName="rotationQuaternion" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    }
+                    {!mesh.rotationQuaternion && <Vector3LineComponent label="Rotation" useEuler={this.props.globalState.onlyUseEulers} target={mesh} propertyName="rotation" step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
+                    {mesh.rotationQuaternion && <QuaternionLineComponent label="Rotation" useEuler={this.props.globalState.onlyUseEulers} target={mesh} propertyName="rotationQuaternion" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
                     <Vector3LineComponent label="Scaling" target={mesh} propertyName="scaling" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="DISPLAY" closed={true}>
-                    {
-                        !mesh.isAnInstance &&
-                        <SliderLineComponent label="Visibility" target={mesh} propertyName="visibility" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    }
+                    {!mesh.isAnInstance && <SliderLineComponent label="Visibility" target={mesh} propertyName="visibility" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
                     <FloatLineComponent lockObject={this.props.lockObject} label="Alpha index" target={mesh} propertyName="alphaIndex" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Receive shadows" target={mesh} propertyName="receiveShadows" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    {
-                        mesh.isVerticesDataPresent(VertexBuffer.ColorKind) &&
-                        <CheckBoxLineComponent label="Use vertex colors" target={mesh} propertyName="useVertexColors" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    }
-                    {
-                        mesh.isVerticesDataPresent(VertexBuffer.ColorKind) &&
-                        <CheckBoxLineComponent label="Has vertex alpha" target={mesh} propertyName="hasVertexAlpha" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    }
-                    {
-                        scene.fogMode !== Scene.FOGMODE_NONE &&
-                        <CheckBoxLineComponent label="Apply fog" target={mesh} propertyName="applyFog" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    }
-                    {
-                        !mesh.parent &&
-                        <CheckBoxLineComponent label="Infinite distance" target={mesh} propertyName="infiniteDistance" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    }
-                    <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} />                    
+                    {mesh.isVerticesDataPresent(VertexBuffer.ColorKind) && <CheckBoxLineComponent label="Use vertex colors" target={mesh} propertyName="useVertexColors" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
+                    {mesh.isVerticesDataPresent(VertexBuffer.ColorKind) && <CheckBoxLineComponent label="Has vertex alpha" target={mesh} propertyName="hasVertexAlpha" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
+                    {scene.fogMode !== Scene.FOGMODE_NONE && <CheckBoxLineComponent label="Apply fog" target={mesh} propertyName="applyFog" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
+                    {!mesh.parent && <CheckBoxLineComponent label="Infinite distance" target={mesh} propertyName="infiniteDistance" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
+                    <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}
+                    />
                     <HexLineComponent isInteger lockObject={this.props.lockObject} label="Layer mask" target={mesh} propertyName="layerMask" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
-                {
-                    mesh.morphTargetManager != null &&
+                {mesh.morphTargetManager != null && (
                     <LineContainerComponent globalState={this.props.globalState} title="MORPH TARGETS" closed={true}>
-                        {
-                            morphTargets.map((mt, i) => {
-                                return (
-                                    <SliderLineComponent key={i} label={mt.name} target={mt} propertyName="influence" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                                );
-                            })
-                        }
+                        {morphTargets.map((mt, i) => {
+                            return <SliderLineComponent key={i} label={mt.name} target={mt} propertyName="influence" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />;
+                        })}
                     </LineContainerComponent>
-
-                }
+                )}
                 <AnimationGridComponent globalState={this.props.globalState} animatable={mesh} scene={mesh.getScene()} lockObject={this.props.lockObject} />
                 <LineContainerComponent globalState={this.props.globalState} title="ADVANCED" closed={true}>
-                    {
-                        mesh.useBones &&
-                        <CheckBoxLineComponent label="Compute bones using shaders" target={mesh} propertyName="computeBonesUsingShaders" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    }
+                    {mesh.useBones && <CheckBoxLineComponent label="Compute bones using shaders" target={mesh} propertyName="computeBonesUsingShaders" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
                     <CheckBoxLineComponent label="Collisions" target={mesh} propertyName="checkCollisions" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <TextLineComponent label="Geometry ID" value={mesh.geometry?.uniqueId.toString()} />
                     <TextLineComponent label="Has normals" value={mesh.isVerticesDataPresent(VertexBuffer.NormalKind) ? "Yes" : "No"} />
@@ -505,72 +485,80 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                     <TextLineComponent label="Has matrix weights" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind) ? "Yes" : "No"} />
                     <TextLineComponent label="Has matrix indices" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind) ? "Yes" : "No"} />
                 </LineContainerComponent>
-                {
-                    mesh.physicsImpostor != null &&
+                {mesh.physicsImpostor != null && (
                     <LineContainerComponent globalState={this.props.globalState} title="PHYSICS" closed={true}>
                         <FloatLineComponent lockObject={this.props.lockObject} label="Mass" target={mesh.physicsImpostor} propertyName="mass" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <FloatLineComponent lockObject={this.props.lockObject} label="Friction" target={mesh.physicsImpostor} propertyName="friction" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <FloatLineComponent lockObject={this.props.lockObject} label="Restitution" target={mesh.physicsImpostor} propertyName="restitution" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <TextLineComponent label="Type" value={this.convertPhysicsTypeToString()} />
                     </LineContainerComponent>
-                }
+                )}
                 <LineContainerComponent globalState={this.props.globalState} title="OCCLUSIONS" closed={true}>
                     <OptionsLineComponent label="Type" options={occlusionTypeOptions} target={mesh} propertyName="occlusionType" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <SliderLineComponent label="Retry count" minimum={-1} maximum={10} decimalCount={0} step={1} target={mesh} propertyName="occlusionRetryCount" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <OptionsLineComponent label="Algorithm" options={algorithmOptions} target={mesh} propertyName="occlusionQueryAlgorithmType" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="EDGE RENDERING" closed={true}>
-                    <CheckBoxLineComponent label="Enable" target={mesh} isSelected={() => mesh.edgesRenderer != null} onSelect={(value) => {
-                        if (value) {
-                            mesh.enableEdgesRendering();
-                        } else {
-                            mesh.disableEdgesRendering();
-                        }
-                    }} />
+                    <CheckBoxLineComponent
+                        label="Enable"
+                        target={mesh}
+                        isSelected={() => mesh.edgesRenderer != null}
+                        onSelect={(value) => {
+                            if (value) {
+                                mesh.enableEdgesRendering();
+                            } else {
+                                mesh.disableEdgesRendering();
+                            }
+                        }}
+                    />
                     <SliderLineComponent label="Edge width" minimum={0} maximum={10} step={0.1} target={mesh} propertyName="edgesWidth" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <Color3LineComponent label="Edge color" target={mesh} propertyName="edgesColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
-                {
-                        !mesh.isAnInstance &&
+                {!mesh.isAnInstance && (
                     <LineContainerComponent globalState={this.props.globalState} title="OUTLINE & OVERLAY" closed={true}>
                         <CheckBoxLineComponent label="Render overlay" target={mesh} propertyName="renderOverlay" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <Color3LineComponent label="Overlay color" target={mesh} propertyName="overlayColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <CheckBoxLineComponent label="Render outline" target={mesh} propertyName="renderOutline" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <Color3LineComponent label="Outline color" target={mesh} propertyName="outlineColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     </LineContainerComponent>
-                }
+                )}
                 <LineContainerComponent globalState={this.props.globalState} title="DEBUG" closed={true}>
-                    {
-                        !mesh.isAnInstance &&
-                        <CheckBoxLineComponent label="Display normals" isSelected={() => displayNormals} onSelect={() => this.displayNormals()} />
-                    }
-                    {
-                        !mesh.isAnInstance &&
-                        <CheckBoxLineComponent label="Display vertex colors" isSelected={() => displayVertexColors} onSelect={() => this.displayVertexColors()} />
-                    }
-                    {
-                        mesh.isVerticesDataPresent(VertexBuffer.NormalKind) &&
-                        <CheckBoxLineComponent label="Render vertex normals" isSelected={() => renderNormalVectors} onSelect={() => this.renderNormalVectors()} />
-                    }
-                    {
-                        !mesh.isAnInstance &&
-                        <CheckBoxLineComponent label="Render wireframe over mesh" isSelected={() => renderWireframeOver} onSelect={() => this.renderWireframeOver()} />
-                    }
-                    {
-                        !mesh.isAnInstance && mesh.skeleton &&
-                        <CheckBoxLineComponent label="Display BoneWeights" isSelected={() => displayBoneWeights} onSelect={() => this.displayBoneWeights()} />
-                    }
-                    {
-                        !mesh.isAnInstance && this.state.displayBoneWeights && mesh.skeleton &&
-                        <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)}} />                        
-                    }
-                    {
-                        !mesh.isAnInstance && mesh.skeleton &&
-                        <CheckBoxLineComponent label="Display SkeletonMap" isSelected={() => displaySkeletonMap } onSelect={() => this.displaySkeletonMap()} />
-                    }                
-
+                    {!mesh.isAnInstance && <CheckBoxLineComponent label="Display normals" isSelected={() => displayNormals} onSelect={() => this.displayNormals()} />}
+                    {!mesh.isAnInstance && <CheckBoxLineComponent label="Display vertex colors" isSelected={() => displayVertexColors} onSelect={() => this.displayVertexColors()} />}
+                    {mesh.isVerticesDataPresent(VertexBuffer.NormalKind) && <CheckBoxLineComponent label="Render vertex normals" isSelected={() => renderNormalVectors} onSelect={() => this.renderNormalVectors()} />}
+                    {!mesh.isAnInstance && <CheckBoxLineComponent label="Render wireframe over mesh" isSelected={() => renderWireframeOver} onSelect={() => this.renderWireframeOver()} />}
+                    {!mesh.isAnInstance && mesh.skeleton && <CheckBoxLineComponent label="Display BoneWeights" isSelected={() => displayBoneWeights} onSelect={() => this.displayBoneWeights()} />}
+                    {!mesh.isAnInstance && this.state.displayBoneWeights && mesh.skeleton && (
+                        <OptionsLineComponent
+                            label="Target Bone Name"
+                            options={targetBoneOptions}
+                            target={mesh.reservedDataStore}
+                            propertyName="displayBoneIndex"
+                            noDirectUpdate={true}
+                            onSelect={(value: number) => {
+                                this.onBoneDisplayIndexChange(value);
+                                this.forceUpdate();
+                            }}
+                        />
+                    )}
+                    {!mesh.isAnInstance && this.state.displayBoneWeights && mesh.skeleton && (
+                        <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);
+                                this.forceUpdate();
+                            }}
+                        />
+                    )}
+                    {!mesh.isAnInstance && mesh.skeleton && <CheckBoxLineComponent label="Display SkeletonMap" isSelected={() => displaySkeletonMap} onSelect={() => this.displaySkeletonMap()} />}
                 </LineContainerComponent>
             </div>
         );
     }
-}
+}