Selaa lähdekoodia

P8 skeleton viewer try2 (#8702)

* here we go agian...

* reorder display modes

* lint

* treeshake fix

* quick fixes and enabled sphere only mode

* linting

* quick fixes

* reorder of properties and methods

* param fixes and descriptions

* inspector updates start

* inspector updates and bone gizmo attachments

* merge with main

* Revert "merge with main"

This reverts commit 33408e5606c95d08a89d3c6ec7e556c4e2a5fe09.

* fixes
Andrew Butt 5 vuotta sitten
vanhempi
commit
99ce5414b8

+ 193 - 145
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/skeletonPropertyGridComponent.tsx

@@ -1,146 +1,194 @@
-import * as React from "react";
-
-import { Observable } from "babylonjs/Misc/observable";
-
-import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
-import { LineContainerComponent } from "../../../lineContainerComponent";
-import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
-import { TextLineComponent } from "../../../lines/textLineComponent";
-import { LockObject } from "../lockObject";
-import { GlobalState } from '../../../../globalState';
-import { Skeleton } from 'babylonjs/Bones/skeleton';
-import { AnimationGridComponent } from '../animations/animationPropertyGridComponent';
-import { SkeletonViewer } from 'babylonjs/Debug/skeletonViewer';
-import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
-import { OptionsLineComponent } from "../../../lines/optionsLineComponent";
-
-interface ISkeletonPropertyGridComponentProps {
-    globalState: GlobalState;
-    skeleton: Skeleton,
-    lockObject: LockObject,
-    onPropertyChangedObservable?: Observable<PropertyChangedEvent>
-}
-
-export class SkeletonPropertyGridComponent extends React.Component<ISkeletonPropertyGridComponentProps> {
-    private _skeletonViewersEnabled = false;
-    private _skeletonViewerDisplayOptions = { displayMode : SkeletonViewer.DISPLAY_LINES }
-    private _skeletonViewers = new Array<SkeletonViewer>();
-
-    constructor(props: ISkeletonPropertyGridComponentProps) {
-        super(props);
-        
-        this.checkSkeletonViewerState(this.props);
-    }
-
-    switchSkeletonViewers() {
-        this._skeletonViewersEnabled = !this._skeletonViewersEnabled;
-        const scene = this.props.skeleton.getScene();
-
-        if (this._skeletonViewersEnabled) {
-            for (var mesh of scene.meshes) {
-                if (mesh.skeleton === this.props.skeleton) {
-                    var found = false;
-                    for (var sIndex = 0; sIndex < this._skeletonViewers.length; sIndex++) {
-                        if (this._skeletonViewers[sIndex].skeleton === mesh.skeleton) {
-                            found = true;
-                            break;
-                        }
-                    }
-                    if (found) {
-                        continue;
-                    }
-                    var viewer = new SkeletonViewer(mesh.skeleton, mesh, scene, false, 3, { displayMode: this._skeletonViewerDisplayOptions.displayMode });
-                    viewer.isEnabled = true;
-                    this._skeletonViewers.push(viewer);
-                    if (!mesh.reservedDataStore) {
-                        mesh.reservedDataStore = {};
-                    }
-                    mesh.reservedDataStore.skeletonViewer = viewer;                   
-                }
-            }
-        } else {
-            for (var index = 0; index < this._skeletonViewers.length; index++) {
-                this._skeletonViewers[index].mesh.reservedDataStore.skeletonViewer = null;
-                this._skeletonViewers[index].dispose();
-            }
-            this._skeletonViewers = [];
-
-        }
-    }
-
-    checkSkeletonViewerState(props: ISkeletonPropertyGridComponentProps) {
-        const scene = props.skeleton.getScene();
-        this._skeletonViewers = [];
-
-        if (!scene) {
-            return;
-        }
-
-        for (var mesh of scene.meshes) {
-            if (mesh.skeleton === props.skeleton && mesh.reservedDataStore && mesh.reservedDataStore.skeletonViewer) {
-                this._skeletonViewers.push(mesh.reservedDataStore.skeletonViewer);
-            }
-        }
-
-        this._skeletonViewersEnabled = (this._skeletonViewers.length > 0);
-    }
-
-    changeDisplayMode(){
-        if (this._skeletonViewersEnabled){              
-            for (var index = 0; index < this._skeletonViewers.length; index++) {
-                this._skeletonViewers[index].changeDisplayMode( this._skeletonViewerDisplayOptions.displayMode || 0 );
-            }                   
-        }
-    }
-
-    shouldComponentUpdate(nextProps: ISkeletonPropertyGridComponentProps) {
-        if (nextProps.skeleton !== this.props.skeleton) {
-            this.checkSkeletonViewerState(nextProps);
-        }
-
-        return true;
-    }
-
-    onOverrideMeshLink() {
-        if (!this.props.globalState.onSelectionChangedObservable) {
-            return;
-        }
-
-        const skeleton = this.props.skeleton;
-        this.props.globalState.onSelectionChangedObservable.notifyObservers(skeleton.overrideMesh);
-    }        
-
-    render() {
-        const skeleton = this.props.skeleton;
-
-        const debugModeOptions = [
-            { label: "Lines", value: SkeletonViewer.DISPLAY_LINES },
-            { label: "Spheres", value: SkeletonViewer.DISPLAY_SPHERES },
-            { label: "Sphere and Spurs", value: SkeletonViewer.DISPLAY_SPHERE_AND_SPURS }
-        ];
-
-
-        return (
-            <div className="pane">
-                <CustomPropertyGridComponent globalState={this.props.globalState} target={skeleton}
-                    lockObject={this.props.lockObject}
-                    onPropertyChangedObservable={this.props.onPropertyChangedObservable} />                    
-                <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
-                    <TextLineComponent label="ID" value={skeleton.id} />
-                    <TextLineComponent label="Bone count" value={skeleton.bones.length.toString()} />
-                    {
-                        skeleton.overrideMesh &&
-                        <TextLineComponent label="Override mesh" value={skeleton.overrideMesh.name} onLink={() => this.onOverrideMeshLink()}/>
-                    }                        
-                    <CheckBoxLineComponent label="Use texture to store matrices" target={skeleton} propertyName="useTextureToStoreBoneMatrices" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    
-                    <LineContainerComponent globalState={this.props.globalState} title="DEBUG">                        
-                        <CheckBoxLineComponent label="Enabled" isSelected={() => this._skeletonViewersEnabled} onSelect={() => this.switchSkeletonViewers()} />
-                        <OptionsLineComponent label="displayMode" options={debugModeOptions} target={this._skeletonViewerDisplayOptions} propertyName="displayMode" onPropertyChangedObservable={this.props.onPropertyChangedObservable} onSelect={() => this.changeDisplayMode()} />
-                    </LineContainerComponent>                    
-                </LineContainerComponent>
-                <AnimationGridComponent globalState={this.props.globalState} animatable={skeleton} scene={skeleton.getScene()} lockObject={this.props.lockObject} />
-            </div>
-        );
-    }
+import * as React from "react";
+
+import { Observable } from "babylonjs/Misc/observable";
+
+import { PropertyChangedEvent } from "../../../../propertyChangedEvent";
+import { LineContainerComponent } from "../../../lineContainerComponent";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
+import { TextLineComponent } from "../../../lines/textLineComponent";
+import { LockObject } from "../lockObject";
+import { GlobalState } from '../../../../globalState';
+import { Skeleton } from 'babylonjs/Bones/skeleton';
+import { AnimationGridComponent } from '../animations/animationPropertyGridComponent';
+import { SkeletonViewer } from 'babylonjs/Debug/skeletonViewer';
+import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
+import { OptionsLineComponent } from "../../../lines/optionsLineComponent";
+import { FloatLineComponent } from "../../../lines/floatLineComponent";
+
+
+interface ISkeletonPropertyGridComponentProps {
+    globalState: GlobalState;
+    skeleton: Skeleton,
+    lockObject: LockObject,
+    onPropertyChangedObservable?: Observable<PropertyChangedEvent>
+}
+
+export class SkeletonPropertyGridComponent extends React.Component<ISkeletonPropertyGridComponentProps> {
+    private _skeletonViewersEnabled = false;
+
+    private _skeletonViewerDisplayOptions = { 
+        displayMode : SkeletonViewer.DISPLAY_LINES,
+        sphereBaseSize : 0.15,
+        sphereScaleUnit : 2,
+        sphereFactor : 0.865,
+        midStep : 0.235,
+        midStepFactor : 0.155
+
+    }
+
+    private _skeletonViewers = new Array<SkeletonViewer>();
+
+    constructor(props: ISkeletonPropertyGridComponentProps) {
+        super(props);
+        
+        this.checkSkeletonViewerState(this.props);
+    }
+
+    switchSkeletonViewers() {
+        this._skeletonViewersEnabled = !this._skeletonViewersEnabled;
+        const scene = this.props.skeleton.getScene();
+
+        if (this._skeletonViewersEnabled) {
+            for (var mesh of scene.meshes) {
+                if (mesh.skeleton === this.props.skeleton) {
+                    var found = false;
+                    for (var sIndex = 0; sIndex < this._skeletonViewers.length; sIndex++) {
+                        if (this._skeletonViewers[sIndex].skeleton === mesh.skeleton) {
+                            found = true;
+                            break;
+                        }
+                    }
+                    if (found) {
+                        continue;
+                    }
+
+                    var viewer = new SkeletonViewer(mesh.skeleton, mesh, scene, false, 3, { 
+                        displayMode: this._skeletonViewerDisplayOptions.displayMode,
+                        displayOptions : {
+                            sphereBaseSize : this._skeletonViewerDisplayOptions.sphereBaseSize,
+                            sphereScaleUnit : this._skeletonViewerDisplayOptions.sphereScaleUnit,
+                            sphereFactor : this._skeletonViewerDisplayOptions.sphereFactor,
+                            midStep : this._skeletonViewerDisplayOptions.midStep,
+                            midStepFactor : this._skeletonViewerDisplayOptions.midStepFactor
+                        }
+                    });
+
+                    viewer.isEnabled = true;
+                    this._skeletonViewers.push(viewer);
+                    if (!mesh.reservedDataStore) {
+                        mesh.reservedDataStore = {};
+                    }
+                    mesh.reservedDataStore.skeletonViewer = viewer;                   
+                }
+            }
+        } else {
+            for (var index = 0; index < this._skeletonViewers.length; index++) {
+                this._skeletonViewers[index].mesh.reservedDataStore.skeletonViewer = null;
+                this._skeletonViewers[index].dispose();
+            }
+            this._skeletonViewers = [];
+
+        }
+    }
+
+    checkSkeletonViewerState(props: ISkeletonPropertyGridComponentProps) {
+        const scene = props.skeleton.getScene();
+        this._skeletonViewers = [];
+
+        if (!scene) {
+            return;
+        }
+
+        for (var mesh of scene.meshes) {
+            if (mesh.skeleton === props.skeleton && mesh.reservedDataStore && mesh.reservedDataStore.skeletonViewer) {
+                this._skeletonViewers.push(mesh.reservedDataStore.skeletonViewer);
+            }
+        }
+
+        this._skeletonViewersEnabled = (this._skeletonViewers.length > 0);
+    }
+
+    changeDisplayMode(){
+        if (this._skeletonViewersEnabled){              
+            for (var index = 0; index < this._skeletonViewers.length; index++) {
+                this._skeletonViewers[index].changeDisplayMode( this._skeletonViewerDisplayOptions.displayMode || 0 );
+            }                   
+        }
+    }
+
+    changeDisplayOptions(option: string, value: number){
+        if (this._skeletonViewersEnabled){              
+            for (var index = 0; index < this._skeletonViewers.length; index++) {
+                this._skeletonViewers[index].changeDisplayOptions( option, value );
+            } 
+            if((this._skeletonViewerDisplayOptions as any)[option] !== undefined ){
+                (this._skeletonViewerDisplayOptions as any)[option] = value;
+            }            
+        }
+    }
+
+    shouldComponentUpdate(nextProps: ISkeletonPropertyGridComponentProps) {
+        if (nextProps.skeleton !== this.props.skeleton) {
+            this.checkSkeletonViewerState(nextProps);
+        }
+
+        return true;
+    }
+
+    onOverrideMeshLink() {
+        if (!this.props.globalState.onSelectionChangedObservable) {
+            return;
+        }
+
+        const skeleton = this.props.skeleton;
+        this.props.globalState.onSelectionChangedObservable.notifyObservers(skeleton.overrideMesh);
+    }        
+
+    render() {
+        const skeleton = this.props.skeleton;
+
+        const debugModeOptions = [
+            { label: "Lines", value: SkeletonViewer.DISPLAY_LINES },
+            { label: "Spheres", value: SkeletonViewer.DISPLAY_SPHERES },
+            { label: "Sphere and Spurs", value: SkeletonViewer.DISPLAY_SPHERE_AND_SPURS }
+        ];
+
+        let displayOptions;
+        if(this._skeletonViewerDisplayOptions.displayMode > SkeletonViewer.DISPLAY_LINES){
+            displayOptions = 
+            (<LineContainerComponent globalState={this.props.globalState} title="DISPLAY OPTIONS">
+                <FloatLineComponent label="sphereBaseSize" target={this._skeletonViewerDisplayOptions} propertyName='sphereBaseSize' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('sphereBaseSize', value)}}/>
+                <FloatLineComponent label="sphereScaleUnit" target={this._skeletonViewerDisplayOptions} propertyName='sphereScaleUnit' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('sphereScaleUnit', value)}}/>
+                <FloatLineComponent label="sphereFactor" target={this._skeletonViewerDisplayOptions} propertyName='sphereFactor' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('sphereFactor', value)}}/>
+                <FloatLineComponent label="midStep" target={this._skeletonViewerDisplayOptions} propertyName='midStep' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('midStep', value)}}/>
+                <FloatLineComponent label="midStepFactor" target={this._skeletonViewerDisplayOptions} propertyName='midStepFactor' onPropertyChangedObservable={this.props.onPropertyChangedObservable} onChange={(value)=>{this.changeDisplayOptions('midStepFactor', value)}}/>
+            </LineContainerComponent>)
+        }else{
+             displayOptions = (null)
+        }
+
+        return (
+            <div className="pane">
+                <CustomPropertyGridComponent globalState={this.props.globalState} target={skeleton}
+                    lockObject={this.props.lockObject}
+                    onPropertyChangedObservable={this.props.onPropertyChangedObservable} />                    
+                <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
+                    <TextLineComponent label="ID" value={skeleton.id} />
+                    <TextLineComponent label="Bone count" value={skeleton.bones.length.toString()} />
+                    {
+                        skeleton.overrideMesh &&
+                        <TextLineComponent label="Override mesh" value={skeleton.overrideMesh.name} onLink={() => this.onOverrideMeshLink()}/>
+                    }                        
+                    <CheckBoxLineComponent label="Use texture to store matrices" target={skeleton} propertyName="useTextureToStoreBoneMatrices" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    
+                    <LineContainerComponent globalState={this.props.globalState} title="DEBUG">                        
+                        <CheckBoxLineComponent label="Enabled" isSelected={() => this._skeletonViewersEnabled} onSelect={() => this.switchSkeletonViewers()} />
+                        <OptionsLineComponent label="displayMode" options={debugModeOptions} target={this._skeletonViewerDisplayOptions} propertyName="displayMode" onPropertyChangedObservable={this.props.onPropertyChangedObservable} onSelect={() => this.changeDisplayMode()} />
+                        {displayOptions}                   
+                    </LineContainerComponent>                    
+                </LineContainerComponent>
+                <AnimationGridComponent globalState={this.props.globalState} animatable={skeleton} scene={skeleton.getScene()} lockObject={this.props.lockObject} />
+            </div>
+        );
+    }
 }

+ 4 - 0
inspector/src/components/sceneExplorer/entities/sceneTreeItemComponent.tsx

@@ -90,6 +90,8 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
                         this.forceUpdate();
                     }
                     manager.attachToMesh(this._selectedEntity.reservedDataStore.lightGizmo.attachedMesh);
+                }else if(className.indexOf("Bone") !== -1){
+                    manager.attachToMesh((this._selectedEntity._linkedTransformNode)?this._selectedEntity._linkedTransformNode:this._selectedEntity);
                 } else {
                     manager.attachToMesh(null);
                 }
@@ -319,6 +321,8 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
                         this.forceUpdate();
                     }
                     manager.attachToMesh(this._selectedEntity.reservedDataStore.lightGizmo.attachedMesh);
+                } else if(className.indexOf("Bone") !== -1){
+                    manager.attachToMesh((this._selectedEntity._linkedTransformNode)?this._selectedEntity._linkedTransformNode:this._selectedEntity);
                 }
             }
         }

+ 18 - 0
src/Debug/skeletonViewer.ts

@@ -536,6 +536,24 @@ export class SkeletonViewer {
         }
     }
 
+    /** Changes the displayMode of the skeleton viewer
+     * @param option String of the option name
+     * @param value The numerical option value
+     */
+    public changeDisplayOptions(option: string, value: number): void {
+        let wasEnabled = (this.isEnabled) ? true : false;
+        (this.options.displayOptions as any)[option] = value;
+        this.isEnabled = false;
+        if (this._debugMesh) {
+            this._debugMesh.dispose();
+            this._debugMesh = null;
+            this.ready = false;
+        }
+        this.update();
+        this._bindObs();
+        this.isEnabled = wasEnabled;
+    }
+
     /** Release associated resources */
     public dispose(): void {
         this.isEnabled = false;