editorControls.tsx 9.3 KB

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