graphActionsBar.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import * as React from "react";
  2. import { IconButtonLineComponent } from "../../../lines/iconButtonLineComponent";
  3. import { IActionableKeyFrame } from "./animationCurveEditorComponent";
  4. interface IGraphActionsBarProps {
  5. addKeyframe: () => void;
  6. removeKeyframe: () => void;
  7. frameSelectedKeyframes: () => void;
  8. handleValueChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  9. handleFrameChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  10. flatTangent: () => void;
  11. brokeTangents: () => void;
  12. setLerpToActiveControlPoint: () => void;
  13. brokenMode: boolean;
  14. lerpMode: boolean;
  15. actionableKeyframe: IActionableKeyFrame;
  16. title: string;
  17. enabled: boolean;
  18. setKeyframeValue: (actionableKeyframe: IActionableKeyFrame) => void;
  19. }
  20. export class GraphActionsBar extends React.Component<IGraphActionsBarProps, { frame: string; value: string }> {
  21. private _frameInput: React.RefObject<HTMLInputElement>;
  22. private _valueInput: React.RefObject<HTMLInputElement>;
  23. constructor(props: IGraphActionsBarProps) {
  24. super(props);
  25. this._frameInput = React.createRef();
  26. this._valueInput = React.createRef();
  27. const { frame, value } = this.selectedKeyframeChanged(this.props.actionableKeyframe);
  28. this.state = { frame, value };
  29. }
  30. componentDidMount() {
  31. this._frameInput.current?.addEventListener("keyup", this.isEnterKeyUp.bind(this));
  32. this._valueInput.current?.addEventListener("keyup", this.isEnterKeyUp.bind(this));
  33. }
  34. componentDidUpdate(prevProps: IGraphActionsBarProps, prevState: any) {
  35. if (prevProps.actionableKeyframe !== this.props.actionableKeyframe) {
  36. const { frame, value } = this.selectedKeyframeChanged(this.props.actionableKeyframe);
  37. this.setState({ frame, value });
  38. }
  39. }
  40. selectedKeyframeChanged(keyframe: IActionableKeyFrame) {
  41. let frame = "";
  42. if (typeof keyframe.frame === "number") {
  43. frame = keyframe.frame.toString();
  44. }
  45. let value = "";
  46. if (typeof keyframe.value === "number") {
  47. value = keyframe.value.toFixed(3);
  48. }
  49. return { frame, value };
  50. }
  51. componentWillUnmount() {
  52. this._frameInput.current?.removeEventListener("keyup", this.isEnterKeyUp.bind(this));
  53. this._valueInput.current?.removeEventListener("keyup", this.isEnterKeyUp.bind(this));
  54. }
  55. isEnterKeyUp(event: KeyboardEvent) {
  56. event.preventDefault();
  57. if (event.key === "Enter") {
  58. const actionableKeyframe: IActionableKeyFrame = { frame: this.getFrame(), value: this.getValue() };
  59. this.props.setKeyframeValue(actionableKeyframe);
  60. }
  61. }
  62. onBlur = (event: React.FocusEvent<HTMLInputElement>) => {
  63. event.preventDefault();
  64. if (event.target.value !== "") {
  65. const actionableKeyframe: IActionableKeyFrame = { frame: this.getFrame(), value: this.getValue() };
  66. this.props.setKeyframeValue(actionableKeyframe);
  67. }
  68. };
  69. getFrame() {
  70. let frame;
  71. if (this.state.frame === "") {
  72. frame = "";
  73. } else {
  74. frame = parseInt(this.state.frame);
  75. }
  76. return frame;
  77. }
  78. getValue() {
  79. let value;
  80. if (this.state.value !== "") {
  81. value = parseFloat(this.state.value);
  82. } else {
  83. value = "";
  84. }
  85. return value;
  86. }
  87. handleValueChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  88. e.preventDefault();
  89. this.setState({ value: e.target.value });
  90. };
  91. handleFrameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  92. e.preventDefault();
  93. this.setState({ frame: e.target.value });
  94. };
  95. render() {
  96. return (
  97. <div className="actions-wrapper">
  98. <div className="title-container">
  99. <div className="icon babylon-logo"></div>
  100. <div className="title">{this.props.title}</div>
  101. </div>
  102. <div className="buttons-container" style={{ pointerEvents: this.props.enabled ? "all" : "none" }}>
  103. <div className="action-input frame-input">
  104. <input
  105. ref={this._frameInput}
  106. type="number"
  107. onChange={this.handleFrameChange}
  108. value={this.state.frame}
  109. step="1"
  110. disabled={this.props.actionableKeyframe.frame === undefined}
  111. onBlur={this.onBlur}
  112. />
  113. </div>
  114. <div className="action-input">
  115. <input
  116. ref={this._valueInput}
  117. type="number"
  118. value={this.state.value}
  119. onChange={this.handleValueChange}
  120. step="0.01"
  121. disabled={this.props.actionableKeyframe.value === undefined}
  122. onBlur={this.onBlur}
  123. />
  124. </div>
  125. <IconButtonLineComponent tooltip={"Add Keyframe"} icon="new-key" onClick={this.props.addKeyframe} />
  126. <IconButtonLineComponent
  127. tooltip={"Frame selected keyframes"}
  128. icon="frame"
  129. onClick={this.props.frameSelectedKeyframes}
  130. />
  131. <IconButtonLineComponent
  132. tooltip={"Flat Tangents"}
  133. icon="flat-tangent"
  134. onClick={this.props.flatTangent}
  135. />
  136. <IconButtonLineComponent
  137. tooltip={this.props.brokenMode ? "Broken Mode On" : "Broken Mode Off"}
  138. icon={this.props.brokenMode ? "break-tangent" : "unify-tangent"}
  139. onClick={this.props.brokeTangents}
  140. />
  141. <IconButtonLineComponent
  142. tooltip={"Linear"}
  143. icon="linear-tangent"
  144. onClick={this.props.setLerpToActiveControlPoint}
  145. />
  146. </div>
  147. </div>
  148. );
  149. }
  150. }