vector3LineComponent.tsx 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import * as React from "react";
  2. import { Vector3 } from "babylonjs/Maths/math.vector";
  3. import { Observable } from "babylonjs/Misc/observable";
  4. import { NumericInputComponent } from "../lines/numericInputComponent";
  5. import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
  6. import { faMinus, faPlus } from "@fortawesome/free-solid-svg-icons";
  7. import { PropertyChangedEvent } from "../propertyChangedEvent";
  8. import { SliderLineComponent } from '../lines/sliderLineComponent';
  9. import { Tools } from 'babylonjs/Misc/tools';
  10. interface IVector3LineComponentProps {
  11. label: string;
  12. target: any;
  13. propertyName: string;
  14. step?: number;
  15. onChange?: (newvalue: Vector3) => void;
  16. useEuler?: boolean,
  17. onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
  18. noSlider?: boolean;
  19. }
  20. export class Vector3LineComponent extends React.Component<IVector3LineComponentProps, { isExpanded: boolean, value: Vector3 }> {
  21. static defaultProps = {
  22. step: 0.001, // cm
  23. };
  24. private _localChange = false;
  25. constructor(props: IVector3LineComponentProps) {
  26. super(props);
  27. this.state = { isExpanded: false, value: this.getCurrentValue().clone() }
  28. }
  29. getCurrentValue() {
  30. return this.props.target[this.props.propertyName];
  31. }
  32. shouldComponentUpdate(nextProps: IVector3LineComponentProps, nextState: { isExpanded: boolean, value: Vector3 }) {
  33. const nextPropsValue = this.getCurrentValue();
  34. if (!nextPropsValue.equals(nextState.value) || this._localChange) {
  35. nextState.value = nextPropsValue.clone();
  36. this._localChange = false;
  37. return true;
  38. }
  39. return false;
  40. }
  41. switchExpandState() {
  42. this._localChange = true;
  43. this.setState({ isExpanded: !this.state.isExpanded });
  44. }
  45. raiseOnPropertyChanged(previousValue: Vector3) {
  46. if (this.props.onChange) {
  47. this.props.onChange(this.state.value);
  48. }
  49. if (!this.props.onPropertyChangedObservable) {
  50. return;
  51. }
  52. this.props.onPropertyChangedObservable.notifyObservers({
  53. object: this.props.target,
  54. property: this.props.propertyName,
  55. value: this.state.value,
  56. initialValue: previousValue
  57. });
  58. }
  59. updateVector3() {
  60. const store = this.props.target[this.props.propertyName].clone();
  61. this.props.target[this.props.propertyName] = this.state.value;
  62. this.setState({ value: store });
  63. this.raiseOnPropertyChanged(store);
  64. }
  65. updateStateX(value: number) {
  66. this._localChange = true;
  67. this.state.value.x = value;
  68. this.updateVector3();
  69. }
  70. updateStateY(value: number) {
  71. this._localChange = true;
  72. this.state.value.y = value;
  73. this.updateVector3();
  74. }
  75. updateStateZ(value: number) {
  76. this._localChange = true;
  77. this.state.value.z = value;
  78. this.updateVector3();
  79. }
  80. render() {
  81. const chevron = this.state.isExpanded ? <FontAwesomeIcon icon={faMinus} /> : <FontAwesomeIcon icon={faPlus} />
  82. return (
  83. <div className="vector3Line">
  84. <div className="firstLine">
  85. <div className="label" title={this.props.label}>
  86. {this.props.label}
  87. </div>
  88. <div className="vector">
  89. {
  90. !this.props.useEuler &&
  91. `X: ${this.state.value.x.toFixed(2)}, Y: ${this.state.value.y.toFixed(2)}, Z: ${this.state.value.z.toFixed(2)}`
  92. }
  93. {
  94. this.props.useEuler &&
  95. `X: ${Tools.ToDegrees(this.state.value.x).toFixed(2)}, Y: ${Tools.ToDegrees(this.state.value.y).toFixed(2)}, Z: ${Tools.ToDegrees(this.state.value.z).toFixed(2)}`
  96. }
  97. </div>
  98. <div className="expand hoverIcon" onClick={() => this.switchExpandState()} title="Expand">
  99. {chevron}
  100. </div>
  101. </div>
  102. {
  103. this.state.isExpanded && !this.props.useEuler &&
  104. <div className="secondLine">
  105. <NumericInputComponent label="x" step={this.props.step} value={this.state.value.x} onChange={value => this.updateStateX(value)} />
  106. <NumericInputComponent label="y" step={this.props.step} value={this.state.value.y} onChange={value => this.updateStateY(value)} />
  107. <NumericInputComponent label="z" step={this.props.step} value={this.state.value.z} onChange={value => this.updateStateZ(value)} />
  108. </div>
  109. }
  110. {
  111. this.state.isExpanded && this.props.useEuler && !this.props.noSlider &&
  112. <div className="secondLine">
  113. <SliderLineComponent margin={true} label="x" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(this.state.value.x)} onChange={value => this.updateStateX(Tools.ToRadians(value))} />
  114. <SliderLineComponent margin={true} label="y" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(this.state.value.y)} onChange={value => this.updateStateY(Tools.ToRadians(value))} />
  115. <SliderLineComponent margin={true} label="z" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(this.state.value.z)} onChange={value => this.updateStateZ(Tools.ToRadians(value))} />
  116. </div>
  117. }
  118. {
  119. this.state.isExpanded && this.props.useEuler && this.props.noSlider &&
  120. <div className="secondLine">
  121. <NumericInputComponent label="x" step={this.props.step} value={Tools.ToDegrees(this.state.value.x)} onChange={value => this.updateStateX(Tools.ToRadians(value))} />
  122. <NumericInputComponent label="y" step={this.props.step} value={Tools.ToDegrees(this.state.value.y)} onChange={value => this.updateStateY(Tools.ToRadians(value))} />
  123. <NumericInputComponent label="z" step={this.props.step} value={Tools.ToDegrees(this.state.value.z)} onChange={value => this.updateStateZ(Tools.ToRadians(value))} />
  124. </div>
  125. }
  126. </div>
  127. );
  128. }
  129. }