|
@@ -7,6 +7,7 @@ import { Vector2, Vector3, Quaternion } from 'babylonjs/Maths/math.vector';
|
|
|
import { Size } from 'babylonjs/Maths/math.size';
|
|
|
import { Color3, Color4 } from 'babylonjs/Maths/math.color';
|
|
|
import { IAnimatable } from 'babylonjs/Animations/animatable.interface';
|
|
|
+import { IAnimationKey } from 'babylonjs';
|
|
|
|
|
|
interface IAddAnimationProps {
|
|
|
isOpen: boolean;
|
|
@@ -14,8 +15,10 @@ interface IAddAnimationProps {
|
|
|
entity: IAnimatable;
|
|
|
onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
|
|
|
setNotificationMessage: (message: string) => void;
|
|
|
- changed: () => void;
|
|
|
+ finishedUpdate: () => void;
|
|
|
+ addedNewAnimation: () => void;
|
|
|
fps: number;
|
|
|
+ selectedToUpdate?: Animation | undefined;
|
|
|
}
|
|
|
|
|
|
export class AddAnimation extends React.Component<
|
|
@@ -26,17 +29,95 @@ export class AddAnimation extends React.Component<
|
|
|
animationType: string;
|
|
|
loopMode: number;
|
|
|
animationTargetPath: string;
|
|
|
+ isUpdating: boolean;
|
|
|
}
|
|
|
> {
|
|
|
constructor(props: IAddAnimationProps) {
|
|
|
super(props);
|
|
|
- this.state = {
|
|
|
- animationName: '',
|
|
|
- animationTargetPath: '',
|
|
|
- animationType: 'Float',
|
|
|
- loopMode: Animation.ANIMATIONLOOPMODE_CYCLE,
|
|
|
- animationTargetProperty: '',
|
|
|
- };
|
|
|
+
|
|
|
+ if (this.props.selectedToUpdate !== undefined) {
|
|
|
+ this.state = {
|
|
|
+ animationName: this.props.selectedToUpdate.name,
|
|
|
+ animationTargetPath: '',
|
|
|
+ animationType: this.getTypeAsString(
|
|
|
+ this.props.selectedToUpdate.dataType
|
|
|
+ ),
|
|
|
+ loopMode:
|
|
|
+ this.props.selectedToUpdate.loopMode ??
|
|
|
+ Animation.ANIMATIONLOOPMODE_CYCLE,
|
|
|
+ animationTargetProperty: this.props.selectedToUpdate.targetProperty,
|
|
|
+ isUpdating: true,
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ this.state = {
|
|
|
+ animationName: '',
|
|
|
+ animationTargetPath: '',
|
|
|
+ animationType: 'Float',
|
|
|
+ loopMode: Animation.ANIMATIONLOOPMODE_CYCLE,
|
|
|
+ animationTargetProperty: '',
|
|
|
+ isUpdating: this.props.selectedToUpdate ? true : false,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ componentWillReceiveProps(nextProps: IAddAnimationProps) {
|
|
|
+ if (
|
|
|
+ nextProps.selectedToUpdate !== undefined &&
|
|
|
+ nextProps.selectedToUpdate !== this.props.selectedToUpdate
|
|
|
+ ) {
|
|
|
+ this.setState({
|
|
|
+ animationName: nextProps.selectedToUpdate.name,
|
|
|
+ animationTargetPath: '',
|
|
|
+ animationType: this.getTypeAsString(
|
|
|
+ nextProps.selectedToUpdate.dataType
|
|
|
+ ),
|
|
|
+ loopMode:
|
|
|
+ nextProps.selectedToUpdate.loopMode ??
|
|
|
+ Animation.ANIMATIONLOOPMODE_CYCLE,
|
|
|
+ animationTargetProperty: nextProps.selectedToUpdate.targetProperty,
|
|
|
+ isUpdating: true,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ if (nextProps.isOpen === true && nextProps.isOpen !== this.props.isOpen)
|
|
|
+ this.setState({
|
|
|
+ animationName: '',
|
|
|
+ animationTargetPath: '',
|
|
|
+ animationType: 'Float',
|
|
|
+ loopMode: Animation.ANIMATIONLOOPMODE_CYCLE,
|
|
|
+ animationTargetProperty: '',
|
|
|
+ isUpdating: false,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ updateAnimation() {
|
|
|
+ if (this.props.selectedToUpdate !== undefined) {
|
|
|
+ const oldNameValue = this.props.selectedToUpdate.name;
|
|
|
+ this.props.selectedToUpdate.name = this.state.animationName;
|
|
|
+ this.raiseOnPropertyUpdated(
|
|
|
+ oldNameValue,
|
|
|
+ this.state.animationName,
|
|
|
+ 'name'
|
|
|
+ );
|
|
|
+
|
|
|
+ const oldLoopModeValue = this.props.selectedToUpdate.loopMode;
|
|
|
+ this.props.selectedToUpdate.loopMode = this.state.loopMode;
|
|
|
+ this.raiseOnPropertyUpdated(
|
|
|
+ oldLoopModeValue,
|
|
|
+ this.state.loopMode,
|
|
|
+ 'loopMode'
|
|
|
+ );
|
|
|
+
|
|
|
+ const oldTargetPropertyValue = this.props.selectedToUpdate.targetProperty;
|
|
|
+ this.props.selectedToUpdate.targetProperty = this.state.animationTargetProperty;
|
|
|
+ this.raiseOnPropertyUpdated(
|
|
|
+ oldTargetPropertyValue,
|
|
|
+ this.state.animationTargetProperty,
|
|
|
+ 'targetProperty'
|
|
|
+ );
|
|
|
+
|
|
|
+ this.props.finishedUpdate();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
getAnimationTypeofChange(selected: string) {
|
|
@@ -64,10 +145,37 @@ export class AddAnimation extends React.Component<
|
|
|
dataType = Animation.ANIMATIONTYPE_COLOR4;
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
return dataType;
|
|
|
}
|
|
|
|
|
|
+ getTypeAsString(type: number) {
|
|
|
+ let typeAsString = 'Float';
|
|
|
+ switch (type) {
|
|
|
+ case Animation.ANIMATIONTYPE_FLOAT:
|
|
|
+ typeAsString = 'Float';
|
|
|
+ break;
|
|
|
+ case Animation.ANIMATIONTYPE_QUATERNION:
|
|
|
+ typeAsString = 'Quaternion';
|
|
|
+ break;
|
|
|
+ case Animation.ANIMATIONTYPE_VECTOR3:
|
|
|
+ typeAsString = 'Vector3';
|
|
|
+ break;
|
|
|
+ case Animation.ANIMATIONTYPE_VECTOR2:
|
|
|
+ typeAsString = 'Vector2';
|
|
|
+ break;
|
|
|
+ case Animation.ANIMATIONTYPE_SIZE:
|
|
|
+ typeAsString = 'Size';
|
|
|
+ break;
|
|
|
+ case Animation.ANIMATIONTYPE_COLOR3:
|
|
|
+ typeAsString = 'Color3';
|
|
|
+ break;
|
|
|
+ case Animation.ANIMATIONTYPE_COLOR4:
|
|
|
+ typeAsString = 'Color4';
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return typeAsString;
|
|
|
+ }
|
|
|
+
|
|
|
addAnimation() {
|
|
|
if (
|
|
|
this.state.animationName != '' &&
|
|
@@ -139,52 +247,37 @@ export class AddAnimation extends React.Component<
|
|
|
|
|
|
if (matched) {
|
|
|
let startValue;
|
|
|
- let endValue;
|
|
|
let outTangent;
|
|
|
- let inTangent;
|
|
|
+
|
|
|
// Default start and end values for new animations
|
|
|
switch (animationDataType) {
|
|
|
case Animation.ANIMATIONTYPE_FLOAT:
|
|
|
startValue = 1;
|
|
|
- endValue = 1;
|
|
|
outTangent = 0;
|
|
|
- inTangent = 0;
|
|
|
break;
|
|
|
case Animation.ANIMATIONTYPE_VECTOR2:
|
|
|
startValue = new Vector2(1, 1);
|
|
|
- endValue = new Vector2(1, 1);
|
|
|
outTangent = Vector2.Zero();
|
|
|
- inTangent = Vector2.Zero();
|
|
|
break;
|
|
|
case Animation.ANIMATIONTYPE_VECTOR3:
|
|
|
startValue = new Vector3(1, 1, 1);
|
|
|
- endValue = new Vector3(1, 1, 1);
|
|
|
outTangent = Vector3.Zero();
|
|
|
- inTangent = Vector3.Zero();
|
|
|
break;
|
|
|
case Animation.ANIMATIONTYPE_QUATERNION:
|
|
|
startValue = new Quaternion(1, 1, 1, 1);
|
|
|
- endValue = new Quaternion(1, 1, 1, 1);
|
|
|
outTangent = Quaternion.Zero();
|
|
|
- inTangent = Quaternion.Zero();
|
|
|
break;
|
|
|
case Animation.ANIMATIONTYPE_COLOR3:
|
|
|
startValue = new Color3(1, 1, 1);
|
|
|
- endValue = new Color3(1, 1, 1);
|
|
|
outTangent = new Color3(0, 0, 0);
|
|
|
- inTangent = new Color3(0, 0, 0);
|
|
|
break;
|
|
|
case Animation.ANIMATIONTYPE_COLOR4:
|
|
|
startValue = new Color4(1, 1, 1, 1);
|
|
|
- endValue = new Color4(1, 1, 1, 1);
|
|
|
outTangent = new Color4(0, 0, 0, 0);
|
|
|
- inTangent = new Color4(0, 0, 0, 0);
|
|
|
break;
|
|
|
case Animation.ANIMATIONTYPE_SIZE:
|
|
|
startValue = new Size(1, 1);
|
|
|
- endValue = new Size(1, 1);
|
|
|
outTangent = Size.Zero();
|
|
|
- inTangent = Size.Zero();
|
|
|
break;
|
|
|
default:
|
|
|
console.log('not recognized');
|
|
@@ -220,19 +313,13 @@ export class AddAnimation extends React.Component<
|
|
|
);
|
|
|
|
|
|
// Start with two keyframes
|
|
|
- var keys = [];
|
|
|
+ var keys: IAnimationKey[] = [];
|
|
|
keys.push({
|
|
|
frame: 0,
|
|
|
value: startValue,
|
|
|
outTangent: outTangent,
|
|
|
});
|
|
|
|
|
|
- keys.push({
|
|
|
- inTangent: inTangent,
|
|
|
- frame: 100,
|
|
|
- value: endValue,
|
|
|
- });
|
|
|
-
|
|
|
animation.setKeys(keys);
|
|
|
|
|
|
if (this.props.entity.animations) {
|
|
@@ -243,8 +330,7 @@ export class AddAnimation extends React.Component<
|
|
|
];
|
|
|
this.raiseOnPropertyChanged(updatedCollection, store);
|
|
|
this.props.entity.animations = updatedCollection;
|
|
|
- this.props.changed();
|
|
|
- this.props.close();
|
|
|
+ this.props.addedNewAnimation();
|
|
|
//Cleaning form fields
|
|
|
this.setState({
|
|
|
animationName: '',
|
|
@@ -280,6 +366,23 @@ export class AddAnimation extends React.Component<
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ raiseOnPropertyUpdated(
|
|
|
+ newValue: string | number | undefined,
|
|
|
+ previousValue: string | number,
|
|
|
+ property: string
|
|
|
+ ) {
|
|
|
+ if (!this.props.onPropertyChangedObservable) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.props.onPropertyChangedObservable.notifyObservers({
|
|
|
+ object: this.props.selectedToUpdate,
|
|
|
+ property: property,
|
|
|
+ value: newValue,
|
|
|
+ initialValue: previousValue,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
handleNameChange(event: React.ChangeEvent<HTMLInputElement>) {
|
|
|
event.preventDefault();
|
|
|
this.setState({ animationName: event.target.value.trim() });
|
|
@@ -312,15 +415,17 @@ export class AddAnimation extends React.Component<
|
|
|
style={{ display: this.props.isOpen ? 'block' : 'none' }}
|
|
|
>
|
|
|
<div className='sub-content'>
|
|
|
- <div className='label-input'>
|
|
|
- <label>Target Path</label>
|
|
|
- <input
|
|
|
- type='text'
|
|
|
- value={this.state.animationTargetPath}
|
|
|
- onChange={(e) => this.handlePathChange(e)}
|
|
|
- disabled
|
|
|
- ></input>
|
|
|
- </div>
|
|
|
+ {this.state.isUpdating ? null : (
|
|
|
+ <div className='label-input'>
|
|
|
+ <label>Target Path</label>
|
|
|
+ <input
|
|
|
+ type='text'
|
|
|
+ value={this.state.animationTargetPath}
|
|
|
+ onChange={(e) => this.handlePathChange(e)}
|
|
|
+ disabled
|
|
|
+ ></input>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
<div className='label-input'>
|
|
|
<label>Display Name</label>
|
|
|
<input
|
|
@@ -337,21 +442,23 @@ export class AddAnimation extends React.Component<
|
|
|
onChange={(e) => this.handlePropertyChange(e)}
|
|
|
></input>
|
|
|
</div>
|
|
|
- <div className='label-input'>
|
|
|
- <label>Type</label>
|
|
|
- <select
|
|
|
- onChange={(e) => this.handleTypeChange(e)}
|
|
|
- value={this.state.animationType}
|
|
|
- >
|
|
|
- <option value='Float'>Float</option>
|
|
|
- <option value='Vector3'>Vector3</option>
|
|
|
- <option value='Vector2'>Vector2</option>
|
|
|
- <option value='Quaternion'>Quaternion</option>
|
|
|
- <option value='Color3'>Color3</option>
|
|
|
- <option value='Color4'>Color4</option>
|
|
|
- <option value='Size'>Size</option>
|
|
|
- </select>
|
|
|
- </div>
|
|
|
+ {this.state.isUpdating ? null : (
|
|
|
+ <div className='label-input'>
|
|
|
+ <label>Type</label>
|
|
|
+ <select
|
|
|
+ onChange={(e) => this.handleTypeChange(e)}
|
|
|
+ value={this.state.animationType}
|
|
|
+ >
|
|
|
+ <option value='Float'>Float</option>
|
|
|
+ <option value='Vector3'>Vector3</option>
|
|
|
+ <option value='Vector2'>Vector2</option>
|
|
|
+ <option value='Quaternion'>Quaternion</option>
|
|
|
+ <option value='Color3'>Color3</option>
|
|
|
+ <option value='Color4'>Color4</option>
|
|
|
+ <option value='Size'>Size</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
<div className='label-input'>
|
|
|
<label>Loop Mode</label>
|
|
|
<select
|
|
@@ -369,8 +476,12 @@ export class AddAnimation extends React.Component<
|
|
|
</div>
|
|
|
<div className='confirm-buttons'>
|
|
|
<ButtonLineComponent
|
|
|
- label={'Create'}
|
|
|
- onClick={() => this.addAnimation()}
|
|
|
+ label={this.state.isUpdating ? 'Update' : 'Create'}
|
|
|
+ onClick={
|
|
|
+ this.state.isUpdating
|
|
|
+ ? () => this.updateAnimation()
|
|
|
+ : () => this.addAnimation()
|
|
|
+ }
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|