class Tween {
var object;
Map _valuesStart = {};
Map _valuesEnd = {};
num _duration = 1000;
num _delayTime = 0;
num _startTime = null;
var _easingFunction = Easing.Linear.None;
var _interpolationFunction = Interpolation.Linear;
List _chainedTweens = [];
var _onStartCallback = null;
bool _onStartCallbackFired = false;
var _onUpdateCallback = null;
var _onCompleteCallback = null;
Tween(this.object);
to( properties, [duration] ) {
if ( duration != null ) {
_duration = duration;
}
_valuesEnd = properties;
}
// TODO(nelsonsilva) - We just support x, y and z props for now (no mirrors yet :(
_setPropertyValue(String name, Object value) {
switch(name) {
case "x": object.x = value; break;
case "y": object.y = value; break;
case "z": object.z = value; break;
default:
throw new Exception("The supplied property name ('$name') is not supported at this time.");
}
}
// TODO(nelsonsilva) - We just support x, y and z props for now (no mirrors yet :(
Object _getPropertyValue(String name) {
switch(name) {
case "x": return object.x;
case "y": return object.y;
case "z": return object.z;
default:
throw new Exception("The supplied property name ('$name') is not supported at this time.");
}
}
start( {num time} ) {
add( this );
_onStartCallbackFired = false;
_startTime = (time != null) ? time : new DateTime.now().millisecondsSinceEpoch;
_startTime += _delayTime;
_valuesEnd.forEach((property, _) {
var value = _getPropertyValue(property);
// This prevents the engine from interpolating null values
if ( value != null ) {
// check if an Array was provided as property value
if ( _valuesEnd[ property ] is List && ! _valuesEnd[ property ].isEmpty) {
// create a local copy of the Array with the start value at the front
_valuesEnd[ property ] = [ value ]..add( _valuesEnd[ property ] );
}
_valuesStart[ property ] = value;
}
});
}
stop() => remove( this );
set delay( amount ) { _delayTime = amount; }
set easing( easing ) { _easingFunction = easing; }
set interpolation( interpolation ) { _interpolationFunction = interpolation; }
chain( List tweens) { _chainedTweens = tweens; }
set onStart( callback ) { _onStartCallback = callback; }
set onUpdate( callback ) { _onUpdateCallback = callback; }
set onComplete( callback ) { _onCompleteCallback = callback; }
update( num time ) {
if ( time < _startTime ) {
return true;
}
if ( !_onStartCallbackFired ) {
if ( _onStartCallback != null ) {
_onStartCallback(object );
}
_onStartCallbackFired = true;
}
var elapsed = ( time - _startTime ) / _duration;
elapsed = elapsed > 1 ? 1 : elapsed;
var value = _easingFunction( elapsed );
_valuesStart.forEach((property, start) {
var end = _valuesEnd[ property ];
if ( end is List ) {
_setPropertyValue( property, _interpolationFunction( end, value ));
} else {
_setPropertyValue( property, start + ( end - start ) * value);
}
});
if ( _onUpdateCallback != null ) {
_onUpdateCallback( object, value );
}
if ( elapsed == 1 ) {
if ( _onCompleteCallback != null ) {
_onCompleteCallback( object );
}
_chainedTweens.forEach((t) => t.start(time));
return false;
}
return true;
}
}
start( {num time} ) {
add( this );
_onStartCallbackFired = false;
_startTime = (time != null) ? time : new DateTime.now().millisecondsSinceEpoch;
_startTime += _delayTime;
_valuesEnd.forEach((property, _) {
var value = _getPropertyValue(property);
// This prevents the engine from interpolating null values
if ( value != null ) {
// check if an Array was provided as property value
if ( _valuesEnd[ property ] is List && ! _valuesEnd[ property ].isEmpty) {
// create a local copy of the Array with the start value at the front
_valuesEnd[ property ] = [ value ]..add( _valuesEnd[ property ] );
}
_valuesStart[ property ] = value;
}
});
}