|
@@ -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/Animations/animationKey';
|
|
|
|
|
|
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<
|
|
@@ -23,49 +26,95 @@ export class AddAnimation extends React.Component<
|
|
|
{
|
|
|
animationName: string;
|
|
|
animationTargetProperty: string;
|
|
|
- animationType: string;
|
|
|
+ animationType: number;
|
|
|
loopMode: number;
|
|
|
animationTargetPath: string;
|
|
|
+ isUpdating: boolean;
|
|
|
}
|
|
|
> {
|
|
|
constructor(props: IAddAnimationProps) {
|
|
|
super(props);
|
|
|
- this.state = {
|
|
|
- animationName: '',
|
|
|
+ this.state = this.setInitialState(this.props.selectedToUpdate);
|
|
|
+ }
|
|
|
+
|
|
|
+ setInitialState(editingAnimation?: Animation) {
|
|
|
+ return {
|
|
|
+ animationName: editingAnimation ? editingAnimation.name : '',
|
|
|
animationTargetPath: '',
|
|
|
- animationType: 'Float',
|
|
|
- loopMode: Animation.ANIMATIONLOOPMODE_CYCLE,
|
|
|
- animationTargetProperty: '',
|
|
|
+ animationType: editingAnimation
|
|
|
+ ? editingAnimation.dataType
|
|
|
+ : Animation.ANIMATIONTYPE_FLOAT,
|
|
|
+ loopMode: editingAnimation
|
|
|
+ ? editingAnimation.loopMode ?? Animation.ANIMATIONLOOPMODE_CYCLE
|
|
|
+ : Animation.ANIMATIONLOOPMODE_CYCLE,
|
|
|
+ animationTargetProperty: editingAnimation
|
|
|
+ ? editingAnimation.targetProperty
|
|
|
+ : '',
|
|
|
+ isUpdating: editingAnimation ? true : false,
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- getAnimationTypeofChange(selected: string) {
|
|
|
- let dataType = 0;
|
|
|
- switch (selected) {
|
|
|
- case 'Float':
|
|
|
- dataType = Animation.ANIMATIONTYPE_FLOAT;
|
|
|
- break;
|
|
|
- case 'Quaternion':
|
|
|
- dataType = Animation.ANIMATIONTYPE_QUATERNION;
|
|
|
- break;
|
|
|
- case 'Vector3':
|
|
|
- dataType = Animation.ANIMATIONTYPE_VECTOR3;
|
|
|
- break;
|
|
|
- case 'Vector2':
|
|
|
- dataType = Animation.ANIMATIONTYPE_VECTOR2;
|
|
|
- break;
|
|
|
- case 'Size':
|
|
|
- dataType = Animation.ANIMATIONTYPE_SIZE;
|
|
|
- break;
|
|
|
- case 'Color3':
|
|
|
- dataType = Animation.ANIMATIONTYPE_COLOR3;
|
|
|
- break;
|
|
|
- case 'Color4':
|
|
|
- dataType = Animation.ANIMATIONTYPE_COLOR4;
|
|
|
- break;
|
|
|
+ componentWillReceiveProps(nextProps: IAddAnimationProps) {
|
|
|
+ if (
|
|
|
+ nextProps.selectedToUpdate !== undefined &&
|
|
|
+ nextProps.selectedToUpdate !== this.props.selectedToUpdate
|
|
|
+ ) {
|
|
|
+ this.setState(this.setInitialState(nextProps.selectedToUpdate));
|
|
|
+ } else {
|
|
|
+ if (nextProps.isOpen === true && nextProps.isOpen !== this.props.isOpen)
|
|
|
+ this.setState(this.setInitialState());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ 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();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- return dataType;
|
|
|
+ getTypeAsString(type: number) {
|
|
|
+ switch (type) {
|
|
|
+ case Animation.ANIMATIONTYPE_FLOAT:
|
|
|
+ return 'Float';
|
|
|
+ case Animation.ANIMATIONTYPE_QUATERNION:
|
|
|
+ return 'Quaternion';
|
|
|
+ case Animation.ANIMATIONTYPE_VECTOR3:
|
|
|
+ return 'Vector3';
|
|
|
+ case Animation.ANIMATIONTYPE_VECTOR2:
|
|
|
+ return 'Vector2';
|
|
|
+ case Animation.ANIMATIONTYPE_SIZE:
|
|
|
+ return 'Size';
|
|
|
+ case Animation.ANIMATIONTYPE_COLOR3:
|
|
|
+ return 'Color3';
|
|
|
+ case Animation.ANIMATIONTYPE_COLOR4:
|
|
|
+ return 'Color4';
|
|
|
+ default:
|
|
|
+ return 'Float';
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
addAnimation() {
|
|
@@ -76,9 +125,8 @@ export class AddAnimation extends React.Component<
|
|
|
let matchTypeTargetProperty = this.state.animationTargetProperty.split(
|
|
|
'.'
|
|
|
);
|
|
|
- let animationDataType = this.getAnimationTypeofChange(
|
|
|
- this.state.animationType
|
|
|
- );
|
|
|
+ let animationDataType = this.state.animationType;
|
|
|
+
|
|
|
let matched = false;
|
|
|
|
|
|
if (matchTypeTargetProperty.length === 1) {
|
|
@@ -116,9 +164,6 @@ export class AddAnimation extends React.Component<
|
|
|
? (matched = true)
|
|
|
: (matched = false);
|
|
|
break;
|
|
|
- default:
|
|
|
- console.log('not recognized');
|
|
|
- break;
|
|
|
}
|
|
|
} else {
|
|
|
this.props.setNotificationMessage(
|
|
@@ -139,55 +184,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');
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -220,19 +247,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,13 +264,12 @@ 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: '',
|
|
|
animationTargetPath: '',
|
|
|
- animationType: 'Float',
|
|
|
+ animationType: Animation.ANIMATIONTYPE_FLOAT,
|
|
|
loopMode: Animation.ANIMATIONLOOPMODE_CYCLE,
|
|
|
animationTargetProperty: '',
|
|
|
});
|
|
@@ -257,7 +277,9 @@ export class AddAnimation extends React.Component<
|
|
|
}
|
|
|
} else {
|
|
|
this.props.setNotificationMessage(
|
|
|
- `The property "${this.state.animationTargetProperty}" is not a "${this.state.animationType}" type`
|
|
|
+ `The property "${
|
|
|
+ this.state.animationTargetProperty
|
|
|
+ }" is not a "${this.getTypeAsString(this.state.animationType)}" type`
|
|
|
);
|
|
|
}
|
|
|
} else {
|
|
@@ -280,6 +302,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() });
|
|
@@ -292,7 +331,7 @@ export class AddAnimation extends React.Component<
|
|
|
|
|
|
handleTypeChange(event: React.ChangeEvent<HTMLSelectElement>) {
|
|
|
event.preventDefault();
|
|
|
- this.setState({ animationType: event.target.value });
|
|
|
+ this.setState({ animationType: parseInt(event.target.value) });
|
|
|
}
|
|
|
|
|
|
handlePropertyChange(event: React.ChangeEvent<HTMLInputElement>) {
|
|
@@ -312,15 +351,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 +378,25 @@ 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={Animation.ANIMATIONTYPE_FLOAT}>Float</option>
|
|
|
+ <option value={Animation.ANIMATIONTYPE_VECTOR3}>Vector3</option>
|
|
|
+ <option value={Animation.ANIMATIONTYPE_VECTOR2}>Vector2</option>
|
|
|
+ <option value={Animation.ANIMATIONTYPE_QUATERNION}>
|
|
|
+ Quaternion
|
|
|
+ </option>
|
|
|
+ <option value={Animation.ANIMATIONTYPE_COLOR3}>Color3</option>
|
|
|
+ <option value={Animation.ANIMATIONTYPE_COLOR4}>Color4</option>
|
|
|
+ <option value={Animation.ANIMATIONTYPE_SIZE}>Size</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
<div className='label-input'>
|
|
|
<label>Loop Mode</label>
|
|
|
<select
|
|
@@ -369,8 +414,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>
|