Home Reference Source Repository

js/SceneKit/SCNActionRepeat.js

  1. 'use strict'
  2.  
  3. import SCNAction from './SCNAction'
  4. import SCNActionTimingMode from './SCNActionTimingMode'
  5.  
  6. export default class SCNActionRepeat extends SCNAction {
  7. static get _propTypes() {
  8. return {
  9. _timesToRepeat: 'float',
  10. _finished: 'boolean',
  11. _duration: 'float',
  12. _timingMode: 'integer',
  13. _beginTime: 'float',
  14. _isRunning: 'boolean',
  15. _repeatedAction: 'SCNAction',
  16. _forever: 'boolean',
  17. _timesRepeated: 'integer',
  18. _pausedTime: 'float',
  19.  
  20. name: ['string', null]
  21. }
  22. }
  23.  
  24. /**
  25. * constructor
  26. * @access public
  27. * @constructor
  28. */
  29. constructor() {
  30. super()
  31.  
  32. this._timesToRepeat = 0
  33. this._repeatedAction = null
  34. this._forever = false
  35. this._timesRepeated = 0
  36. this._finished = false
  37. this._duration = 0
  38. this._timingMode = SCNActionTimingMode.linear
  39. this._beginTime = 0
  40. this._isRunning = false
  41. this._pausedTime = 0
  42. }
  43.  
  44. /**
  45. * Creates an action that repeats another action a specified number of times.
  46. * @access public
  47. * @param {SCNAction} action - The action to be executed.
  48. * @param {number} count - The number of times to execute the action.
  49. * @returns {SCNAction} -
  50. * @desc When the action executes, the associated action runs to completion and then repeats, until the count is reached.This action is reversible; it creates a new action that is the reverse of the specified action and then repeats it the same number of times.
  51. * @see https://developer.apple.com/documentation/scenekit/scnaction/1522764-repeat
  52. */
  53. static repeat(action, count) {
  54. const _action = new SCNActionRepeat()
  55. _action._repeatedAction = action
  56. _action._duration = action.duration
  57. _action._timesToRepeat = count
  58. _action._forever = (count === Infinity)
  59. return _action
  60. }
  61.  
  62. /**
  63. * Creates an action that repeats another action forever.
  64. * @access public
  65. * @param {SCNAction} action - The action to execute.
  66. * @returns {SCNAction} -
  67. * @desc When the action executes, the associated action runs to completion and then repeats.This action is reversible; it creates a new action that is the reverse of the specified action and then repeats it forever.NoteThe action to be repeated must have a non-instantaneous duration.
  68. * @see https://developer.apple.com/documentation/scenekit/scnaction/1522908-repeatforever
  69. */
  70. static repeatForever(action) {
  71. return this.repeat(action, Infinity)
  72. }
  73.  
  74. /**
  75. * @access public
  76. * @returns {SCNActionRepeat} -
  77. */
  78. copy() {
  79. const action = super.copy()
  80.  
  81. action._timesToRepeat = this._timesToRepeat
  82. action._repeatedAction = this._repeatedAction.copy()
  83. action._forever = this._forever
  84. action._timesRepeated = this._timesRepeated
  85.  
  86. return action
  87. }
  88.  
  89. _getTime(time, needTimeConversion) {
  90. if(!needTimeConversion){
  91. return time
  92. }
  93.  
  94. const baseTime = this._basetimeFromTime(time)
  95. if(this.timingFunction === null){
  96. return baseTime
  97. }
  98.  
  99. const n = Math.floor(baseTime)
  100. const t = this.timingFunction._getValueAtTime(baseTime - n)
  101. return n + t
  102. }
  103.  
  104. /**
  105. * apply action to the given node.
  106. * @access private
  107. * @param {Object} obj - target object to apply this action.
  108. * @param {number} time - active time
  109. * @param {boolean} [needTimeConversion = true] -
  110. * @returns {void}
  111. */
  112. _applyAction(obj, time, needTimeConversion = true) {
  113. const dt = this._getTime(time, needTimeConversion)
  114. const timesRepeated = Math.floor(dt)
  115. while(timesRepeated > this._timesRepeated){
  116. this._timesRepeated += 1
  117. this._repeatedAction._applyAction(obj, 1.0, false)
  118. if(!this._forever && this._timesRepeated >= this._timesToRepeat){
  119. this._finished = true
  120. return
  121. }
  122. this._repeatedAction._resetFinished()
  123. }
  124. let t = dt - this._timesRepeated
  125. this._repeatedAction._applyAction(obj, t, false)
  126. this._finished = false
  127. }
  128.  
  129. get duration() {
  130. if(this._forever){
  131. return Infinity
  132. }
  133. return this._repeatedAction.duration * this._timesToRepeat
  134. }
  135.  
  136. _resetFinished() {
  137. this._repeatedAction._resetFinished()
  138. this._timesRepeated = 0
  139. this._finished = false
  140. }
  141. }
  142.  
  143. SCNAction.repeat = SCNActionRepeat.repeat
  144. SCNAction.repeatForever = SCNActionRepeat.repeatForever