AnimationAction.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. *
  3. * Runnable instance of an AnimationClip.
  4. *
  5. * Multiple Actions are required to add the same clip with the (same or
  6. * different) mixer(s) simultaneously.
  7. *
  8. *
  9. * @author Ben Houston / http://clara.io/
  10. * @author David Sarno / http://lighthaus.us/
  11. */
  12. THREE.AnimationAction = function ( clip, startTime, timeScale, weight, loop ) {
  13. if( clip === undefined ) throw new Error( 'clip is null' );
  14. this.name = '';
  15. this.clip = clip;
  16. this.localRoot = null;
  17. this.startTime = startTime || 0;
  18. this.timeScale = timeScale || 1;
  19. this.weight = weight || 1;
  20. this.loop = loop || THREE.LoopRepeat;
  21. this.loopCount = 0;
  22. this.enabled = true; // allow for easy disabling of the action.
  23. this.actionTime = - this.startTime;
  24. this.clipTime = 0;
  25. this.mixer = null;
  26. var tracks = clip.tracks,
  27. nTracks = tracks.length,
  28. interpolants = new Array( nTracks );
  29. for ( var i = 0; i !== nTracks; ++ i ) {
  30. interpolants[ i ] = tracks[ i ].createInterpolant( null );
  31. }
  32. this._interpolants = interpolants;
  33. this._propertyBindings = new Array( nTracks );
  34. this._prevRootUuid = '';
  35. this._prevMixerUuid = '';
  36. };
  37. /*
  38. THREE.LoopOnce = 2200;
  39. THREE.LoopRepeat = 2201;
  40. THREE.LoopPingPing = 2202;
  41. */
  42. THREE.AnimationAction.prototype = {
  43. constructor: THREE.AnimationAction,
  44. getName: function() {
  45. return this.name || this.clip.name;
  46. },
  47. setLocalRoot: function( localRoot ) {
  48. this.localRoot = localRoot;
  49. return this;
  50. },
  51. updateTime: function( clipDeltaTime ) {
  52. var previousClipTime = this.clipTime;
  53. var previousLoopCount = this.loopCount;
  54. var previousActionTime = this.actionTime;
  55. var duration = this.clip.duration;
  56. this.actionTime = this.actionTime + clipDeltaTime;
  57. if( this.loop === THREE.LoopOnce ) {
  58. this.loopCount = 0;
  59. this.clipTime = Math.min( Math.max( this.actionTime, 0 ), duration );
  60. // if time is changed since last time, see if we have hit a start/end limit
  61. if( this.clipTime !== previousClipTime ) {
  62. if( this.clipTime === duration ) {
  63. this.mixer.dispatchEvent( { type: 'finished', action: this, direction: 1 } );
  64. }
  65. else if( this.clipTime === 0 ) {
  66. this.mixer.dispatchEvent( { type: 'finished', action: this, direction: -1 } );
  67. }
  68. }
  69. return this.clipTime;
  70. }
  71. this.loopCount = Math.floor( this.actionTime / duration );
  72. var newClipTime = this.actionTime - this.loopCount * duration;
  73. newClipTime = newClipTime % duration;
  74. // if we are ping pong looping, ensure that we go backwards when appropriate
  75. if( this.loop == THREE.LoopPingPong ) {
  76. if( Math.abs( this.loopCount % 2 ) === 1 ) {
  77. newClipTime = duration - newClipTime;
  78. }
  79. }
  80. this.clipTime = newClipTime;
  81. if( this.loopCount !== previousLoopCount ) {
  82. this.mixer.dispatchEvent( { type: 'loop', action: this, loopDelta: ( this.loopCount - this.loopCount ) } );
  83. }
  84. return this.clipTime;
  85. },
  86. syncWith: function( action ) {
  87. this.actionTime = action.actionTime;
  88. this.timeScale = action.timeScale;
  89. return this;
  90. },
  91. warpToDuration: function( duration ) {
  92. this.timeScale = this.clip.duration / duration;
  93. return this;
  94. },
  95. init: function( time ) {
  96. this.clipTime = time - this.startTime;
  97. return this;
  98. },
  99. // pass in time, not clip time, allows for fadein/fadeout across multiple loops of the clip
  100. getTimeScaleAt: function( time ) {
  101. var timeScale = this.timeScale;
  102. if( timeScale.evaluate !== undefined ) {
  103. return timeScale.evaluate( time )[ 0 ];
  104. }
  105. return timeScale;
  106. },
  107. // pass in time, not clip time, allows for fadein/fadeout across multiple loops of the clip
  108. getWeightAt: function( time ) {
  109. var weight = this.weight;
  110. if( weight.evaluate !== undefined ) {
  111. return weight.evaluate( time )[ 0 ];
  112. }
  113. return weight;
  114. }
  115. };