Alejandro Toledo 5 years ago
parent
commit
56ca6c8d9b

+ 24 - 17
inspector/src/components/actionTabs/tabs/propertyGrids/animations/animationCurveEditorComponent.tsx

@@ -69,6 +69,7 @@ export class AnimationCurveEditorComponent extends React.Component<
     selectedCoordinate: number;
     animationLimit: number;
     fps: number;
+    isLooping: boolean;
   }
 > {
   private _snippetUrl = 'https://snippet.babylonjs.com';
@@ -138,6 +139,8 @@ export class AnimationCurveEditorComponent extends React.Component<
           : initialPathData;
     }
 
+    this._canvasLength = 240;
+
     // will update this until we have a top scroll/zoom feature
     let valueInd = [2, 1.8, 1.6, 1.4, 1.2, 1, 0.8, 0.6, 0.4, 0.2, 0];
     this.state = {
@@ -169,6 +172,7 @@ export class AnimationCurveEditorComponent extends React.Component<
       selectedCoordinate: 0,
       animationLimit: 120,
       fps: 60,
+      isLooping: true,
     };
   }
 
@@ -202,7 +206,7 @@ export class AnimationCurveEditorComponent extends React.Component<
   }
 
   setAxesLength() {
-    let length = 20;
+    let length = this.state.animationLimit * 2;
     let newlength = Math.round(this._canvasLength * this.state.scale);
     if (!isNaN(newlength) || newlength !== undefined) {
       length = newlength;
@@ -1394,12 +1398,15 @@ export class AnimationCurveEditorComponent extends React.Component<
       if (this.props.entity instanceof TargetedAnimation) {
         target = this.props.entity.target;
       }
-      if (this.state.isPlaying) {
+      if (this.state.isPlaying && direction === 0) {
         this.props.scene.stopAnimation(target);
         this.setState({ isPlaying: false });
         this._isPlaying = false;
         this.forceUpdate();
       } else {
+        if (this.state.isPlaying) {
+          this.props.scene.stopAnimation(target);
+        }
         let keys = this.state.selected.getKeys();
         let firstFrame = keys[0].frame;
         let LastFrame = keys[keys.length - 1].frame;
@@ -1408,7 +1415,8 @@ export class AnimationCurveEditorComponent extends React.Component<
             target,
             firstFrame,
             LastFrame,
-            true
+            this.state.isLooping,
+            this.state.fps
           );
         }
         if (direction === -1) {
@@ -1416,7 +1424,8 @@ export class AnimationCurveEditorComponent extends React.Component<
             target,
             LastFrame,
             firstFrame,
-            true
+            this.state.isLooping,
+            this.state.fps
           );
         }
         this._isPlaying = true;
@@ -1515,6 +1524,9 @@ export class AnimationCurveEditorComponent extends React.Component<
               setFps={(fps: number) => {
                 this.setState({ fps: fps });
               }}
+              setIsLooping={() => {
+                this.setState({ isLooping: !this.state.isLooping });
+              }}
             />
 
             <div
@@ -1559,16 +1571,6 @@ export class AnimationCurveEditorComponent extends React.Component<
                     ></path>
                   ))}
 
-                  <svg>
-                    <rect
-                      x='-4%'
-                      y='0%'
-                      width='4%'
-                      height='101%'
-                      fill='#222'
-                    ></rect>
-                  </svg>
-
                   {this.state.valueAxisLength.map((f, i) => {
                     return (
                       <svg key={i}>
@@ -1581,7 +1583,12 @@ export class AnimationCurveEditorComponent extends React.Component<
                         >
                           {f.label.toFixed(1)}
                         </text>
-                        <line x1='0' y1={f.value} x2='105%' y2={f.value}></line>
+                        <line
+                          x1='0'
+                          y1={f.value}
+                          x2={this.state.frameAxisLength.length * 10}
+                          y2={f.value}
+                        ></line>
                       </svg>
                     );
                   })}
@@ -1590,7 +1597,7 @@ export class AnimationCurveEditorComponent extends React.Component<
                     onClick={(e) => this.moveFrameTo(e)}
                     x='0%'
                     y='91%'
-                    width='105%'
+                    width={this.state.frameAxisLength.length * 10}
                     height='10%'
                     fill='#222'
                     style={{ cursor: 'pointer' }}
@@ -1611,7 +1618,7 @@ export class AnimationCurveEditorComponent extends React.Component<
                       {f.value % this.state.fps === 0 && f.value !== 0 ? (
                         <line
                           x1={f.value}
-                          y1='-100'
+                          y1='-100%'
                           x2={f.value}
                           y2='5%'
                         ></line>

+ 139 - 75
inspector/src/components/actionTabs/tabs/propertyGrids/animations/controls.tsx

@@ -1,94 +1,158 @@
-
-import * as React from "react";
+import * as React from 'react';
 import { IAnimationKey } from 'babylonjs/Animations/animationKey';
 import { IconButtonLineComponent } from '../../../lines/iconButtonLineComponent';
 
 interface IControlsProps {
-    keyframes: IAnimationKey[] | null;
-    selected: IAnimationKey | null;
-    currentFrame: number;
-    onCurrentFrameChange: (frame: number) => void;
-    playPause: (direction: number) => void;
-    isPlaying: boolean;
-    scrollable: React.RefObject<HTMLDivElement>
+  keyframes: IAnimationKey[] | null;
+  selected: IAnimationKey | null;
+  currentFrame: number;
+  onCurrentFrameChange: (frame: number) => void;
+  playPause: (direction: number) => void;
+  isPlaying: boolean;
+  scrollable: React.RefObject<HTMLDivElement>;
 }
 
-export class Controls extends React.Component<IControlsProps, { selected: IAnimationKey }>{
-    constructor(props: IControlsProps) {
-        super(props);
-        if (this.props.selected !== null) {
-            this.state = { selected: this.props.selected };
-        }
+export class Controls extends React.Component<
+  IControlsProps,
+  { selected: IAnimationKey; playingType: string }
+> {
+  constructor(props: IControlsProps) {
+    super(props);
+    if (this.props.selected !== null) {
+      this.state = { selected: this.props.selected, playingType: '' };
     }
+  }
 
-    playBackwards() {
-        this.props.playPause(-1);
-    }
+  playBackwards() {
+    this.setState({ playingType: 'reverse' });
+    this.props.playPause(-1);
+  }
 
-    play() {
-        this.props.playPause(1);
-    }
+  play() {
+    this.setState({ playingType: 'forward' });
+    this.props.playPause(1);
+  }
 
-    pause() {
-        if (this.props.isPlaying) {
-            this.props.playPause(1);
-        }
+  pause() {
+    if (this.props.isPlaying) {
+      this.setState({ playingType: '' });
+      this.props.playPause(0);
     }
+  }
 
-    nextFrame() {
-        this.props.onCurrentFrameChange(this.props.currentFrame + 1);
-        (this.props.scrollable.current as HTMLDivElement).scrollLeft = this.props.currentFrame * 5;
-    }
+  nextFrame() {
+    this.props.onCurrentFrameChange(this.props.currentFrame + 1);
+    (this.props.scrollable.current as HTMLDivElement).scrollLeft =
+      this.props.currentFrame * 5;
+  }
 
-    previousFrame() {
-        if (this.props.currentFrame !== 0) {
-            this.props.onCurrentFrameChange(this.props.currentFrame - 1);
-            (this.props.scrollable.current as HTMLDivElement).scrollLeft = -(this.props.currentFrame * 5);
-        }
+  previousFrame() {
+    if (this.props.currentFrame !== 0) {
+      this.props.onCurrentFrameChange(this.props.currentFrame - 1);
+      (this.props.scrollable.current as HTMLDivElement).scrollLeft = -(
+        this.props.currentFrame * 5
+      );
     }
+  }
 
-    nextKeyframe() {
-        if (this.props.keyframes !== null) {
-            let first = this.props.keyframes.find(kf => kf.frame > this.props.currentFrame);
-            if (first) {
-                this.props.onCurrentFrameChange(first.frame);
-                this.setState({ selected: first });
-                (this.props.scrollable.current as HTMLDivElement).scrollLeft = first.frame * 5;
-            }
-        }
+  nextKeyframe() {
+    if (this.props.keyframes !== null) {
+      let first = this.props.keyframes.find(
+        (kf) => kf.frame > this.props.currentFrame
+      );
+      if (first) {
+        this.props.onCurrentFrameChange(first.frame);
+        this.setState({ selected: first });
+        (this.props.scrollable.current as HTMLDivElement).scrollLeft =
+          first.frame * 5;
+      }
     }
+  }
 
-    previousKeyframe() {
-        if (this.props.keyframes !== null) {
-            let keyframes = [...this.props.keyframes]
-            let first = keyframes.reverse().find(kf => kf.frame < this.props.currentFrame);
-            if (first) {
-                this.props.onCurrentFrameChange(first.frame);
-                this.setState({ selected: first });
-                (this.props.scrollable.current as HTMLDivElement).scrollLeft = -(first.frame * 5);
-            }
-        }
+  previousKeyframe() {
+    if (this.props.keyframes !== null) {
+      let keyframes = [...this.props.keyframes];
+      let first = keyframes
+        .reverse()
+        .find((kf) => kf.frame < this.props.currentFrame);
+      if (first) {
+        this.props.onCurrentFrameChange(first.frame);
+        this.setState({ selected: first });
+        (this.props.scrollable.current as HTMLDivElement).scrollLeft = -(
+          first.frame * 5
+        );
+      }
     }
+  }
 
-    render() {
-        return (
-            <div className="controls">
-                <IconButtonLineComponent tooltip="Animation Start" icon="animation-start" onClick={() => this.previousFrame()}></IconButtonLineComponent>
-                <IconButtonLineComponent tooltip="Previous Keyframe" icon="animation-lastkey" onClick={() => this.previousKeyframe()}></IconButtonLineComponent>
-                {this.props.isPlaying ?
-                    <div className="stop-container">
-                        <IconButtonLineComponent tooltip="Play Reverse" icon="animation-stop" onClick={() => this.pause()}></IconButtonLineComponent>
-                    </div>
-                    :
-                    <div className="stop-container">
-                        <IconButtonLineComponent tooltip="Play Reverse" icon="animation-playrev" onClick={() => this.playBackwards()}></IconButtonLineComponent>
-                        <IconButtonLineComponent tooltip="Play Forward" icon="animation-playfwd" onClick={() => this.play()}></IconButtonLineComponent>
-                    </div>
-                }
-                <IconButtonLineComponent tooltip="Next Keyframe" icon="animation-nextkey" onClick={() => this.nextKeyframe()}></IconButtonLineComponent>
-                <IconButtonLineComponent tooltip="Animation End" icon="animation-end" onClick={() => this.nextFrame()}></IconButtonLineComponent>
-
-            </div>
-        )
-    }
-} 
+  render() {
+    return (
+      <div className='controls'>
+        <IconButtonLineComponent
+          tooltip='Animation Start'
+          icon='animation-start'
+          onClick={() => this.previousFrame()}
+        ></IconButtonLineComponent>
+        <IconButtonLineComponent
+          tooltip='Previous Keyframe'
+          icon='animation-lastkey'
+          onClick={() => this.previousKeyframe()}
+        ></IconButtonLineComponent>
+        {this.props.isPlaying ? (
+          <div className='stop-container'>
+            {this.state.playingType === 'reverse' ? (
+              <>
+                <IconButtonLineComponent
+                  tooltip='Pause'
+                  icon='animation-stop'
+                  onClick={() => this.pause()}
+                ></IconButtonLineComponent>
+                <IconButtonLineComponent
+                  tooltip='Play Forward'
+                  icon='animation-playfwd'
+                  onClick={() => this.play()}
+                ></IconButtonLineComponent>
+              </>
+            ) : (
+              <>
+                <IconButtonLineComponent
+                  tooltip='Play Reverse'
+                  icon='animation-playrev'
+                  onClick={() => this.playBackwards()}
+                ></IconButtonLineComponent>
+                <IconButtonLineComponent
+                  tooltip='Pause'
+                  icon='animation-stop'
+                  onClick={() => this.pause()}
+                ></IconButtonLineComponent>
+              </>
+            )}
+          </div>
+        ) : (
+          <div className='stop-container'>
+            <IconButtonLineComponent
+              tooltip='Play Reverse'
+              icon='animation-playrev'
+              onClick={() => this.playBackwards()}
+            ></IconButtonLineComponent>
+            <IconButtonLineComponent
+              tooltip='Play Forward'
+              icon='animation-playfwd'
+              onClick={() => this.play()}
+            ></IconButtonLineComponent>
+          </div>
+        )}
+        <IconButtonLineComponent
+          tooltip='Next Keyframe'
+          icon='animation-nextkey'
+          onClick={() => this.nextKeyframe()}
+        ></IconButtonLineComponent>
+        <IconButtonLineComponent
+          tooltip='Animation End'
+          icon='animation-end'
+          onClick={() => this.nextFrame()}
+        ></IconButtonLineComponent>
+      </div>
+    );
+  }
+}

+ 2 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/animations/curveEditor.scss

@@ -267,7 +267,6 @@
       cursor: pointer;
       background-position: center;
       width: 20px;
-      margin-left: 10px;
     }
 
     &.animation-triangle {
@@ -606,6 +605,8 @@
               .scrollbar {
                 cursor: pointer;
                 width: 100%;
+                height: 66px;
+                margin-top: -10px;
               }
 
               .left-grabber,

+ 3 - 16
inspector/src/components/actionTabs/tabs/propertyGrids/animations/editorControls.tsx

@@ -23,6 +23,7 @@ interface IEditorControlsProps {
   setNotificationMessage: (message: string) => void;
   selectAnimation: (selected: Animation, axis?: SelectedCoordinate) => void;
   setFps: (fps: number) => void;
+  setIsLooping: () => void;
   globalState: GlobalState;
   snippetServer: string;
   deselectAnimation: () => void;
@@ -39,7 +40,6 @@ export class EditorControls extends React.Component<
     animationsCount: number;
     framesPerSecond: number;
     snippetId: string;
-    loopMode: number;
     selected: Animation | undefined;
   }
 > {
@@ -53,8 +53,7 @@ export class EditorControls extends React.Component<
       isEditTabOpen: count === 0 ? false : true,
       isSaveTabOpen: false,
       isLoadTabOpen: false,
-      isLoopActive: false,
-      loopMode: Animation.ANIMATIONLOOPMODE_CYCLE,
+      isLoopActive: true,
       animationsCount: count,
       framesPerSecond: 60,
       snippetId: '',
@@ -83,22 +82,10 @@ export class EditorControls extends React.Component<
   }
 
   changeLoopBehavior() {
-    let loopMode = this.state.loopMode;
-    const animation = this.props.selected;
-    if (loopMode === 2) {
-      loopMode = Animation.ANIMATIONLOOPMODE_CYCLE;
-    } else {
-      loopMode = Animation.ANIMATIONLOOPMODE_CONSTANT;
-    }
-    if (animation) {
-      // Notify observers
-      animation.loopMode = loopMode;
-    }
-
     this.setState({
       isLoopActive: !this.state.isLoopActive,
-      loopMode: loopMode,
     });
+    this.props.setIsLooping();
   }
 
   handleTabs(tab: number) {

+ 87 - 48
inspector/src/components/actionTabs/tabs/propertyGrids/animations/svgDraggableArea.tsx

@@ -13,7 +13,10 @@ interface ISvgDraggableAreaProps {
   removeSelectedKeyframes: (points: IKeyframeSvgPoint[]) => void;
 }
 
-export class SvgDraggableArea extends React.Component<ISvgDraggableAreaProps> {
+export class SvgDraggableArea extends React.Component<
+  ISvgDraggableAreaProps,
+  { panX: number; panY: number }
+> {
   private _active: boolean;
   private _isCurrentPointControl: string;
   private _currentPointId: string;
@@ -29,6 +32,8 @@ export class SvgDraggableArea extends React.Component<ISvgDraggableAreaProps> {
     this._draggableArea = React.createRef();
     this._panStart = new Vector2(0, 0);
     this._panStop = new Vector2(0, 0);
+
+    this.state = { panX: 0, panY: 0 };
   }
 
   componentDidMount() {
@@ -63,9 +68,8 @@ export class SvgDraggableArea extends React.Component<ISvgDraggableAreaProps> {
     }
 
     if (e.target.classList.contains('pannable')) {
-      if (e.buttons === 1 && e.shiftKey) {
-        this._panStart.set(e.clientX, e.clientY);
-      }
+      this._active = true;
+      this._panStart.set(e.clientX, e.clientY);
     }
   }
 
@@ -78,21 +82,28 @@ export class SvgDraggableArea extends React.Component<ISvgDraggableAreaProps> {
       var coord = this.getMousePosition(e);
 
       if (coord !== undefined) {
-        var newPoints = [...this.props.keyframeSvgPoints];
-
-        let point = newPoints.find((kf) => kf.id === this._currentPointId);
-        if (point) {
-          // Check for NaN values here.
-          if (this._isCurrentPointControl === 'left') {
-            point.leftControlPoint = coord;
-            point.isLeftActive = true;
-          } else if (this._isCurrentPointControl === 'right') {
-            point.rightControlPoint = coord;
-            point.isRightActive = true;
-          } else {
-            point.keyframePoint = coord;
+        if (e.target.classList.contains('pannable')) {
+          if (this._panStart.x !== 0 && this._panStart.y !== 0) {
+            this._panStop.set(e.clientX, e.clientY);
+            this.panDirection();
+          }
+        } else {
+          var newPoints = [...this.props.keyframeSvgPoints];
+
+          let point = newPoints.find((kf) => kf.id === this._currentPointId);
+          if (point) {
+            // Check for NaN values here.
+            if (this._isCurrentPointControl === 'left') {
+              point.leftControlPoint = coord;
+              point.isLeftActive = true;
+            } else if (this._isCurrentPointControl === 'right') {
+              point.rightControlPoint = coord;
+              point.isRightActive = true;
+            } else {
+              point.keyframePoint = coord;
+            }
+            this.props.updatePosition(point, this._currentPointId);
           }
-          this.props.updatePosition(point, this._currentPointId);
         }
       }
     }
@@ -105,13 +116,8 @@ export class SvgDraggableArea extends React.Component<ISvgDraggableAreaProps> {
     this._active = false;
     this._currentPointId = '';
     this._isCurrentPointControl = '';
-
-    if (e.target.classList.contains('pannable')) {
-      if (this._panStart.x !== 0 && this._panStart.y !== 0) {
-        this._panStop.set(e.clientX, e.clientY);
-        this.panDirection();
-      }
-    }
+    this._panStart.set(0, 0);
+    this._panStop.set(0, 0);
   }
 
   getMousePosition(e: React.TouchEvent<SVGSVGElement>): Vector2 | undefined;
@@ -140,30 +146,58 @@ export class SvgDraggableArea extends React.Component<ISvgDraggableAreaProps> {
   }
 
   panDirection() {
-    // Movement Right to Left
-    if (this._panStart.x > this._panStop.x) {
-      console.log('right to left');
-      this.panTo('right', Math.abs(this._panStart.x - this._panStop.x));
-    }
+    // const moveX = Math.round(coord.x);
+    // const width = Math.round(this.props.scale * 200);
+    // this.setState({
+    //   panX: Math.round(coord.x),
+    //   panY: Math.round(coord.y),
+    // });
 
-    // Movement Right to Left
-    if (this._panStart.x < this._panStop.x) {
-      this.panTo('left', Math.abs(this._panStart.x - this._panStop.x));
-      console.log('left to right');
-    }
+    let movementX = this._panStart.x - this._panStop.x;
+    let movementY = this._panStart.y - this._panStop.y;
 
-    // Movement Bottom to Up
-    if (this._panStart.y > this._panStop.y) {
-      console.log('down up');
-    }
+    let newX = this.state.panX + movementX / 20;
+    let newY = this.state.panY + movementY / 20;
 
-    // Movement Up to Bottom
-    if (this._panStart.y < this._panStop.y) {
-      console.log('up down');
-    }
+    console.log(newX, newY);
 
-    this._panStart.set(0, 0);
-    this._panStop.set(0, 0);
+    // if (this._draggableArea.current){
+
+    //   const vb = `${movementX} ${movementY} ${Math.round(this.props.scale * 200)} ${Math.round(this.props.scale * 100)}`;
+    //  (this._draggableArea.current as SVGSVGElement).setAttribute('viewBox', vb);
+
+    // }
+
+    this.setState({
+      panX: Math.round(newX),
+      panY: Math.round(newY),
+    });
+    // this.setState({
+    //   panX: Math.round(coord.x),
+    //   panY: Math.round(coord.y),
+    //   });
+
+    // // Movement Right to Left
+    // if (this._panStart.x > this._panStop.x) {
+    //   console.log('right to left');
+    //   //this.panTo('right', Math.abs(this._panStart.x - this._panStop.x));
+    // }
+
+    // // Movement Right to Left
+    // if (this._panStart.x < this._panStop.x) {
+    //   //this.panTo('left', Math.abs(this._panStart.x - this._panStop.x));
+    //   console.log('left to right');
+    // }
+
+    // // Movement Bottom to Up
+    // if (this._panStart.y > this._panStop.y) {
+    //   console.log('down up');
+    // }
+
+    // // Movement Up to Bottom
+    // if (this._panStart.y < this._panStop.y) {
+    //   console.log('up down');
+    // }
   }
 
   panTo(direction: string, value: number) {
@@ -231,6 +265,11 @@ export class SvgDraggableArea extends React.Component<ISvgDraggableAreaProps> {
     return (
       <>
         <svg
+          style={{ width: 30, height: 364, position: 'absolute', zIndex: 1 }}
+        >
+          <rect x='0' y='0' width='30px' height='100%' fill='#222'></rect>
+        </svg>
+        <svg
           className='linear pannable'
           ref={this._draggableArea}
           tabIndex={0}
@@ -243,9 +282,9 @@ export class SvgDraggableArea extends React.Component<ISvgDraggableAreaProps> {
           onMouseLeave={(e) => this.dragEnd(e)}
           // Add way to add new keyframe
           onClick={(e) => this.focus(e)}
-          viewBox={`0 0 ${Math.round(this.props.scale * 200)} ${Math.round(
-            this.props.scale * 100
-          )}`}
+          viewBox={`${this.state.panX} ${this.state.panY} ${Math.round(
+            this.props.scale * 200
+          )} ${Math.round(this.props.scale * 100)}`}
         >
           {this.props.children}
           {this.props.keyframeSvgPoints.map((keyframe, i) => (

+ 2 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/animations/timeline.tsx

@@ -286,6 +286,8 @@ export class Timeline extends React.Component<
     e.preventDefault();
     if (e.target.className === 'scrollbar') {
       this.moveScrollbar(e.pageX);
+    } else {
+      console.log('out');
     }
 
     if (this._active === 'leftDraggable') {