controls.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import * as React from "react";
  2. import { IAnimationKey } from "babylonjs/Animations/animationKey";
  3. import { IconButtonLineComponent } from "../../../../../sharedUiComponents/lines/iconButtonLineComponent";
  4. interface IControlsProps {
  5. // Keyframes to choose start or end of animation playback
  6. keyframes: IAnimationKey[] | null;
  7. // The currently selected animation keyframe
  8. selected: IAnimationKey | null;
  9. // The current frame number
  10. currentFrame: number;
  11. // Event to change the current frame
  12. onCurrentFrameChange: (frame: number) => void;
  13. // Event to communicate canvas repposition
  14. repositionCanvas: (keyframe: IAnimationKey) => void;
  15. // Event to play, pause or play backwards the animation
  16. playPause: (direction: number) => void;
  17. // If the animation is playing
  18. isPlaying: boolean;
  19. // The reference to the scrollable dom object to set its position
  20. scrollable: React.RefObject<HTMLDivElement>;
  21. }
  22. /**
  23. * The playback controls for the animation editor
  24. */
  25. export class Controls extends React.Component<IControlsProps, { selected: IAnimationKey; playingType: string }> {
  26. readonly _sizeOfKeyframe: number = 5;
  27. constructor(props: IControlsProps) {
  28. super(props);
  29. if (this.props.selected !== null) {
  30. this.state = { selected: this.props.selected, playingType: "" };
  31. }
  32. }
  33. playBackwards = () => {
  34. this.setState({ playingType: "reverse" });
  35. this.props.playPause(-1);
  36. };
  37. play = () => {
  38. this.setState({ playingType: "forward" });
  39. this.props.playPause(1);
  40. };
  41. pause = () => {
  42. if (this.props.isPlaying) {
  43. this.setState({ playingType: "" });
  44. this.props.playPause(0);
  45. }
  46. };
  47. /**
  48. * Set animation to initial keyframe
  49. */
  50. moveToAnimationStart = () => {
  51. const startKeyframe = this.props.keyframes && this.props.keyframes[0];
  52. if (startKeyframe !== null) {
  53. if (typeof startKeyframe.frame === "number") {
  54. this.props.onCurrentFrameChange(startKeyframe.frame);
  55. }
  56. }
  57. };
  58. /**
  59. * Set animation to the last keyframe
  60. */
  61. moveToAnimationEnd = () => {
  62. const endKeyframe = this.props.keyframes && this.props.keyframes[this.props.keyframes.length - 1];
  63. if (endKeyframe !== null) {
  64. if (typeof endKeyframe.frame === "number") {
  65. this.props.onCurrentFrameChange(endKeyframe.frame);
  66. }
  67. }
  68. };
  69. /** Move to next keyframe */
  70. nextKeyframe = () => {
  71. if (this.props.keyframes !== null) {
  72. let first = this.props.keyframes.find((kf) => kf.frame > this.props.currentFrame);
  73. if (first) {
  74. this.props.onCurrentFrameChange(first.frame);
  75. this.setState({ selected: first });
  76. (this.props.scrollable.current as HTMLDivElement).scrollLeft = first.frame * this._sizeOfKeyframe;
  77. }
  78. }
  79. };
  80. /** Move to previous keyframe */
  81. previousKeyframe = () => {
  82. if (this.props.keyframes !== null) {
  83. let keyframes = [...this.props.keyframes];
  84. let first = keyframes.reverse().find((kf) => kf.frame < this.props.currentFrame);
  85. if (first) {
  86. this.props.onCurrentFrameChange(first.frame);
  87. this.setState({ selected: first });
  88. (this.props.scrollable.current as HTMLDivElement).scrollLeft = -(first.frame * this._sizeOfKeyframe);
  89. }
  90. }
  91. };
  92. render() {
  93. return (
  94. <div className="controls">
  95. <IconButtonLineComponent
  96. tooltip="Animation Start"
  97. icon="animation-start"
  98. onClick={this.moveToAnimationStart}
  99. ></IconButtonLineComponent>
  100. <IconButtonLineComponent
  101. tooltip="Previous Keyframe"
  102. icon="animation-lastkey"
  103. onClick={this.previousKeyframe}
  104. ></IconButtonLineComponent>
  105. {this.props.isPlaying ? (
  106. <div className="stop-container">
  107. {this.state.playingType === "reverse" ? (
  108. <>
  109. <IconButtonLineComponent
  110. tooltip="Pause"
  111. icon="animation-stop"
  112. onClick={this.pause}
  113. ></IconButtonLineComponent>
  114. <IconButtonLineComponent
  115. tooltip="Play Forward"
  116. icon="animation-playfwd"
  117. onClick={this.play}
  118. ></IconButtonLineComponent>
  119. </>
  120. ) : (
  121. <>
  122. <IconButtonLineComponent
  123. tooltip="Play Reverse"
  124. icon="animation-playrev"
  125. onClick={this.playBackwards}
  126. ></IconButtonLineComponent>
  127. <IconButtonLineComponent
  128. tooltip="Pause"
  129. icon="animation-stop"
  130. onClick={this.pause}
  131. ></IconButtonLineComponent>
  132. </>
  133. )}
  134. </div>
  135. ) : (
  136. <div className="stop-container">
  137. <IconButtonLineComponent
  138. tooltip="Play Reverse"
  139. icon="animation-playrev"
  140. onClick={this.playBackwards}
  141. ></IconButtonLineComponent>
  142. <IconButtonLineComponent
  143. tooltip="Play Forward"
  144. icon="animation-playfwd"
  145. onClick={this.play}
  146. ></IconButtonLineComponent>
  147. </div>
  148. )}
  149. <IconButtonLineComponent
  150. tooltip="Next Keyframe"
  151. icon="animation-nextkey"
  152. onClick={this.nextKeyframe}
  153. ></IconButtonLineComponent>
  154. <IconButtonLineComponent
  155. tooltip="Animation End"
  156. icon="animation-end"
  157. onClick={this.moveToAnimationEnd}
  158. ></IconButtonLineComponent>
  159. </div>
  160. );
  161. }
  162. }