|
@@ -85,20 +85,39 @@ THREE.TimelinerController.prototype = {
|
|
|
|
|
|
var track = this._tracks[ channelName ],
|
|
|
times = track.times,
|
|
|
- index = times.indexOf( time );
|
|
|
+ index = Timeliner.binarySearch( times, time ),
|
|
|
+ values = track.values,
|
|
|
+ stride = track.getValueSize(),
|
|
|
+ offset = index * stride;
|
|
|
|
|
|
- if ( index === -1 ) index = times.length;
|
|
|
+ if ( index < 0 ) {
|
|
|
|
|
|
- var values = track.values,
|
|
|
- offset = index * track.getValueSize();
|
|
|
+ // insert new keyframe
|
|
|
|
|
|
- // note: not calling track.getValueSize with
|
|
|
- // inconsistent array sizes
|
|
|
+ index = ~ index;
|
|
|
+ offset = index * stride;
|
|
|
|
|
|
- times[ index ] = time;
|
|
|
- this._propRefs[ channelName ].getValue( values, offset );
|
|
|
+ var nTimes = times.length + 1,
|
|
|
+ nValues = values.length + stride;
|
|
|
+
|
|
|
+ times[ index ] = time;
|
|
|
+
|
|
|
+ for ( var i = nTimes - 1; i !== index; -- i ) {
|
|
|
+
|
|
|
+ times[ i ] = times[ i - 1 ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ for ( var i = nValues - 1,
|
|
|
+ e = offset + stride - 1; i !== e; -- i ) {
|
|
|
+
|
|
|
+ values[ i ] = values[ i - stride ];
|
|
|
|
|
|
- this._sort( track );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ this._propRefs[ channelName ].getValue( values, offset );
|
|
|
|
|
|
},
|
|
|
|
|
@@ -106,52 +125,58 @@ THREE.TimelinerController.prototype = {
|
|
|
|
|
|
var track = this._tracks[ channelName ],
|
|
|
times = track.times,
|
|
|
- index = times.indexOf( time );
|
|
|
+ index = Timeliner.binarySearch( times, time );
|
|
|
|
|
|
- if ( index === 0 ) {
|
|
|
+ // we disallow to remove the keyframe when it is the last one we have,
|
|
|
+ // since the animation system is designed to always produce a defined
|
|
|
+ // state
|
|
|
|
|
|
- // we disallow to remove the first keyframe
|
|
|
- // since the animation system is designed to
|
|
|
- // always produce a defined state - we allow
|
|
|
- // the initial state to be changed however
|
|
|
+ if ( times.length > 1 && index >= 0 ) {
|
|
|
|
|
|
- this.setKeyframe( channelName, time );
|
|
|
+ var nTimes = times.length - 1,
|
|
|
+ values = track.values,
|
|
|
+ stride = track.getValueSize(),
|
|
|
+ nValues = values.length - stride;
|
|
|
|
|
|
- } else if ( index !== -1 ) {
|
|
|
+ // note: no track.getValueSize when array sizes are out of sync
|
|
|
|
|
|
- var values = track.values,
|
|
|
- stride = track.getValueSize(),
|
|
|
- offset = index * stride,
|
|
|
+ for ( var i = index; i !== nTimes; ++ i ) {
|
|
|
|
|
|
- nValues = values.length;
|
|
|
+ times[ i ] = times[ i + 1 ];
|
|
|
|
|
|
- // note: not calling track.getValueSize with
|
|
|
- // inconsistent array sizes
|
|
|
+ }
|
|
|
|
|
|
- times[ index ] = times[ times.length - 1 ];
|
|
|
times.pop();
|
|
|
|
|
|
- for ( var i = nValues - stride; i !== nValues; ++ i ) {
|
|
|
+ for ( var offset = index * stride; offset !== nValues; ++ offset ) {
|
|
|
|
|
|
- values[ offset ++ ] = values[ i ];
|
|
|
+ values[ offset ] = values[ offset + stride ];
|
|
|
|
|
|
}
|
|
|
|
|
|
- values.length = nValues - stride;
|
|
|
-
|
|
|
- this._sort( track );
|
|
|
+ values.length = nValues;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
- hasKeyframe: function( channelName, time ) {
|
|
|
+ moveKeyframe: function( channelName, time, delta, moveRemaining ) {
|
|
|
|
|
|
var track = this._tracks[ channelName ],
|
|
|
times = track.times,
|
|
|
- index = times.indexOf( time );
|
|
|
+ index = Timeliner.binarySearch( times, time );
|
|
|
|
|
|
- return index !== -1;
|
|
|
+ if ( index >= 0 ) {
|
|
|
+
|
|
|
+ var endAt = moveRemaining ? times.length : index + 1,
|
|
|
+ needsSort = times[ index - 1 ] <= time ||
|
|
|
+ ! moveRemaining && time >= times[ index + 1 ];
|
|
|
+
|
|
|
+ while ( index !== endAt ) times[ index ++ ] += delta;
|
|
|
+
|
|
|
+ if ( needsSort ) this._sort( track );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
},
|
|
|
|