editorControls.tsx 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. import * as React from 'react';
  2. import { Observable } from 'babylonjs/Misc/observable';
  3. import { PropertyChangedEvent } from '../../../../../components/propertyChangedEvent';
  4. import { Animation } from 'babylonjs/Animations/animation';
  5. import { IconButtonLineComponent } from '../../../lines/iconButtonLineComponent';
  6. import { NumericInputComponent } from '../../../lines/numericInputComponent';
  7. import { AddAnimation } from './addAnimation';
  8. import { AnimationListTree, SelectedCoordinate } from './animationListTree';
  9. import { IAnimatable } from 'babylonjs/Animations/animatable.interface';
  10. import { TargetedAnimation } from 'babylonjs/Animations/animationGroup';
  11. import { LoadSnippet } from './loadsnippet';
  12. import { SaveSnippet } from './saveSnippet';
  13. import { LockObject } from '../lockObject';
  14. import { GlobalState } from '../../../../globalState';
  15. interface IEditorControlsProps {
  16. isTargetedAnimation: boolean;
  17. entity: IAnimatable | TargetedAnimation;
  18. selected: Animation | null;
  19. lockObject: LockObject;
  20. onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
  21. setNotificationMessage: (message: string) => void;
  22. selectAnimation: (selected: Animation, axis?: SelectedCoordinate) => void;
  23. setFps: (fps: number) => void;
  24. setIsLooping: () => void;
  25. globalState: GlobalState;
  26. snippetServer: string;
  27. deselectAnimation: () => void;
  28. }
  29. export class EditorControls extends React.Component<
  30. IEditorControlsProps,
  31. {
  32. isAnimationTabOpen: boolean;
  33. isEditTabOpen: boolean;
  34. isLoadTabOpen: boolean;
  35. isSaveTabOpen: boolean;
  36. isLoopActive: boolean;
  37. animationsCount: number;
  38. framesPerSecond: number;
  39. snippetId: string;
  40. selected: Animation | undefined;
  41. }
  42. > {
  43. constructor(props: IEditorControlsProps) {
  44. super(props);
  45. let count = this.props.isTargetedAnimation
  46. ? 1
  47. : (this.props.entity as IAnimatable).animations?.length ?? 0;
  48. this.state = {
  49. isAnimationTabOpen: count === 0 ? true : false,
  50. isEditTabOpen: count === 0 ? false : true,
  51. isSaveTabOpen: false,
  52. isLoadTabOpen: false,
  53. isLoopActive: true,
  54. animationsCount: count,
  55. framesPerSecond: 60,
  56. snippetId: '',
  57. selected: undefined,
  58. };
  59. }
  60. animationAdded() {
  61. this.setState({
  62. animationsCount: this.recountAnimations(),
  63. isEditTabOpen: true,
  64. isAnimationTabOpen: false,
  65. });
  66. }
  67. finishedUpdate() {
  68. this.setState({
  69. isEditTabOpen: true,
  70. isAnimationTabOpen: false,
  71. selected: undefined,
  72. });
  73. }
  74. recountAnimations() {
  75. return (this.props.entity as IAnimatable).animations?.length ?? 0;
  76. }
  77. changeLoopBehavior() {
  78. this.setState({
  79. isLoopActive: !this.state.isLoopActive,
  80. });
  81. this.props.setIsLooping();
  82. }
  83. handleTabs(tab: number) {
  84. let state = {
  85. isAnimationTabOpen: true,
  86. isLoadTabOpen: false,
  87. isSaveTabOpen: false,
  88. isEditTabOpen: false,
  89. };
  90. switch (tab) {
  91. case 0:
  92. state = {
  93. isAnimationTabOpen: true,
  94. isLoadTabOpen: false,
  95. isSaveTabOpen: false,
  96. isEditTabOpen: false,
  97. };
  98. break;
  99. case 1:
  100. state = {
  101. isAnimationTabOpen: false,
  102. isLoadTabOpen: true,
  103. isSaveTabOpen: false,
  104. isEditTabOpen: false,
  105. };
  106. break;
  107. case 2:
  108. state = {
  109. isAnimationTabOpen: false,
  110. isLoadTabOpen: false,
  111. isSaveTabOpen: true,
  112. isEditTabOpen: false,
  113. };
  114. break;
  115. case 3:
  116. state = {
  117. isAnimationTabOpen: false,
  118. isLoadTabOpen: false,
  119. isSaveTabOpen: false,
  120. isEditTabOpen: true,
  121. };
  122. break;
  123. }
  124. this.setState(state);
  125. }
  126. handleChangeFps(fps: number) {
  127. this.props.setFps(fps);
  128. this.setState({ framesPerSecond: fps });
  129. }
  130. emptiedList() {
  131. this.setState({
  132. animationsCount: this.recountAnimations(),
  133. isEditTabOpen: false,
  134. isAnimationTabOpen: true,
  135. });
  136. }
  137. animationsLoaded(numberOfAnimations: number) {
  138. this.setState({
  139. animationsCount: numberOfAnimations,
  140. isEditTabOpen: true,
  141. isAnimationTabOpen: false,
  142. isLoadTabOpen: false,
  143. isSaveTabOpen: false,
  144. });
  145. }
  146. editAnimation(selected: Animation) {
  147. this.setState({
  148. selected: selected,
  149. isEditTabOpen: false,
  150. isAnimationTabOpen: true,
  151. isLoadTabOpen: false,
  152. isSaveTabOpen: false,
  153. });
  154. }
  155. render() {
  156. return (
  157. <div className='animation-list'>
  158. <div className='controls-header'>
  159. {this.props.isTargetedAnimation ? null : (
  160. <IconButtonLineComponent
  161. active={this.state.isAnimationTabOpen}
  162. tooltip='Add Animation'
  163. icon='medium add-animation'
  164. onClick={() => this.handleTabs(0)}
  165. ></IconButtonLineComponent>
  166. )}
  167. <IconButtonLineComponent
  168. active={this.state.isLoadTabOpen}
  169. tooltip='Load Animation'
  170. icon='medium load'
  171. onClick={() => this.handleTabs(1)}
  172. ></IconButtonLineComponent>
  173. {this.state.animationsCount === 0 ? null : (
  174. <IconButtonLineComponent
  175. active={this.state.isSaveTabOpen}
  176. tooltip='Save Animation'
  177. icon='medium save'
  178. onClick={() => this.handleTabs(2)}
  179. ></IconButtonLineComponent>
  180. )}
  181. {this.state.animationsCount === 0 ? null : (
  182. <IconButtonLineComponent
  183. active={this.state.isEditTabOpen}
  184. tooltip='Edit Animations'
  185. icon='medium animation-edit'
  186. onClick={() => this.handleTabs(3)}
  187. ></IconButtonLineComponent>
  188. )}
  189. {this.state.isEditTabOpen ? (
  190. <div className='input-fps'>
  191. <NumericInputComponent
  192. label={''}
  193. precision={0}
  194. value={this.state.framesPerSecond}
  195. onChange={(framesPerSecond: number) =>
  196. this.handleChangeFps(framesPerSecond)
  197. }
  198. />
  199. <p>fps</p>
  200. </div>
  201. ) : null}
  202. {this.state.isEditTabOpen ? (
  203. <IconButtonLineComponent
  204. tooltip='Loop/Unloop'
  205. icon={`medium ${
  206. this.state.isLoopActive
  207. ? 'loop-active last'
  208. : 'loop-inactive last'
  209. }`}
  210. onClick={() => this.changeLoopBehavior()}
  211. ></IconButtonLineComponent>
  212. ) : null}
  213. </div>
  214. {this.props.isTargetedAnimation ? null : (
  215. <AddAnimation
  216. isOpen={this.state.isAnimationTabOpen}
  217. close={() => {
  218. this.setState({ isAnimationTabOpen: false, isEditTabOpen: true });
  219. }}
  220. entity={this.props.entity as IAnimatable}
  221. setNotificationMessage={(message: string) => {
  222. this.props.setNotificationMessage(message);
  223. }}
  224. addedNewAnimation={() => this.animationAdded()}
  225. onPropertyChangedObservable={this.props.onPropertyChangedObservable}
  226. fps={this.state.framesPerSecond}
  227. selectedToUpdate={this.state.selected}
  228. finishedUpdate={() => this.finishedUpdate()}
  229. />
  230. )}
  231. {this.state.isLoadTabOpen ? (
  232. <LoadSnippet
  233. animationsLoaded={(numberOfAnimations: number) =>
  234. this.animationsLoaded(numberOfAnimations)
  235. }
  236. lockObject={this.props.lockObject}
  237. animations={[]}
  238. snippetServer={this.props.snippetServer}
  239. globalState={this.props.globalState}
  240. setSnippetId={(id: string) => this.setState({ snippetId: id })}
  241. entity={this.props.entity}
  242. setNotificationMessage={this.props.setNotificationMessage}
  243. />
  244. ) : null}
  245. {this.state.isSaveTabOpen ? (
  246. <SaveSnippet
  247. lockObject={this.props.lockObject}
  248. animations={(this.props.entity as IAnimatable).animations}
  249. snippetServer={this.props.snippetServer}
  250. globalState={this.props.globalState}
  251. snippetId={this.state.snippetId}
  252. />
  253. ) : null}
  254. {this.state.isEditTabOpen ? (
  255. <AnimationListTree
  256. deselectAnimation={() => this.props.deselectAnimation()}
  257. isTargetedAnimation={this.props.isTargetedAnimation}
  258. entity={this.props.entity}
  259. selected={this.props.selected}
  260. onPropertyChangedObservable={this.props.onPropertyChangedObservable}
  261. empty={() => this.emptiedList()}
  262. selectAnimation={this.props.selectAnimation}
  263. editAnimation={(selected: Animation) =>
  264. this.editAnimation(selected)
  265. }
  266. />
  267. ) : null}
  268. </div>
  269. );
  270. }
  271. }