Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

aframe-gltf-anim.js 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*!
  2. * A minimalistic A-Frame component for animating 3D models
  3. * @author Alexandre Martins <alemartf(at)gmail.com> (https://github.com/alemart)
  4. * @license MIT
  5. */
  6. AFRAME.registerComponent('gltf-anim', {
  7. schema: {
  8. /** the name of an animation clip */
  9. 'clip': { type: 'string', default: '' },
  10. /** whether or not to loop the animation */
  11. 'loop': { type: 'boolean', default: true },
  12. /** scaling factor for the playback speed */
  13. 'speed': { type: 'number', default: 1 },
  14. /** duration in seconds of transitions between clips */
  15. 'transitionDuration': { type: 'number', default: 0 },
  16. },
  17. init()
  18. {
  19. const el = this.el;
  20. this._model = null;
  21. this._action = null;
  22. el.addEventListener('model-loaded', event => {
  23. if(event.target === el) {
  24. this._model = event.detail.model;
  25. this._refresh();
  26. }
  27. });
  28. el.addEventListener('model-error', event => {
  29. if(event.target === el) {
  30. this._model = null;
  31. this._refresh();
  32. }
  33. });
  34. },
  35. update(oldData)
  36. {
  37. if(!this._model)
  38. return;
  39. if(this.data.clip != oldData.clip)
  40. this._switchClip();
  41. if(!this._action)
  42. return;
  43. if(Math.abs(this.data.speed - oldData.speed) > 1e-5)
  44. this._action.timeScale = this.data.speed;
  45. if(this.data.loop != oldData.loop)
  46. this._action.loop = this.data.loop ? THREE.LoopRepeat : THREE.LoopOnce;
  47. },
  48. remove()
  49. {
  50. if(this._action)
  51. this._action.getMixer().stopAllAction();
  52. this._action = null;
  53. this._model = null;
  54. },
  55. tick(time, delta)
  56. {
  57. if(this._action) {
  58. const mixer = this._action.getMixer();
  59. mixer.update(delta * 0.001);
  60. }
  61. },
  62. _refresh()
  63. {
  64. if(this._action) {
  65. this._action.getMixer().stopAllAction();
  66. this._action = null;
  67. }
  68. if(this._model) {
  69. if((this._action = this._clipAction(null)))
  70. this._action.play();
  71. }
  72. },
  73. _switchClip()
  74. {
  75. const oldAction = this._action;
  76. if(!oldAction) {
  77. this._refresh();
  78. return;
  79. }
  80. const newAction = this._clipAction(oldAction.getMixer());
  81. if(!newAction) {
  82. this._refresh();
  83. return;
  84. }
  85. this._action = newAction;
  86. this._action.reset().play().crossFadeFrom(oldAction, Math.max(0, this.data.transitionDuration));
  87. },
  88. _clipAction(existingMixer)
  89. {
  90. if(!this._model)
  91. return null;
  92. const mixer = (existingMixer && existingMixer.getRoot() === this._model) ? existingMixer : new THREE.AnimationMixer(this._model);
  93. const clips = this._model.animations;
  94. if(!clips || clips.length == 0)
  95. return null;
  96. const name = (this.data.clip != '') ? this.data.clip : this._defaultClipName(clips);
  97. const clip = THREE.AnimationClip.findByName(clips, name);
  98. if(!clip)
  99. return null;
  100. const action = mixer.clipAction(clip);
  101. action.loop = this.data.loop ? THREE.LoopRepeat : THREE.LoopOnce;
  102. action.timeScale = this.data.speed;
  103. return action;
  104. },
  105. _defaultClipName(clips)
  106. {
  107. const sortedNames = clips.map(clip => clip.name).sort();
  108. return sortedNames[0];
  109. },
  110. });