c-frame / aframe-extras

Add-ons and helpers for A-Frame VR.
https://c-frame.github.io/aframe-extras/examples/
MIT License
972 stars 305 forks source link

timeScale -1 not working #364

Closed lijualivenow closed 1 year ago

lijualivenow commented 3 years ago

model.setAttribute('animation-mixer', {timeScale: -1})

not working

timeScale: 0 and 1 is working

dirkk0 commented 3 years ago

It does work for me: https://mech-walker.glitch.me/

via https://glitch.com/edit/#!/mech-walker?path=index.html%3A20%3A15

kylebakerio commented 3 years ago

timescale 1 set manually for me doesn't play my animation. Had to set to .99.

kylebakerio commented 3 years ago

-.5 is not working for me right now. Unfortunately, glitch seems to be experiencing an error and I cannot load the glitch code, either.

kylebakerio commented 3 years ago

I see that that code, by looking in sources, is using the dist version of aframe-extras, which doesn't include support for startFrame. Sadly, I need to play a certain animation backwards, and my artist has encoded my animations as different frame sections. It seems that negative timeScales have problems in the undistributed version, but the current dist version doesn't support startFrame. Nothing to do but ask the artist to break these up into different models or learn how to save them as different animations.

lijualivenow commented 3 years ago

I did reverse animation using ThreeJS

here is my code

const nextButtonComponent = () => ({
  init() {
    const scene = this.el.sceneEl
    const animationList = ['idle', 'pockets', 'hiphop', 'chicken']
    const model = document.getElementById('model')
    const nextButton = document.getElementById('nextbutton')
    const prevbutton = document.getElementById('prevbutton')
    const clock = new THREE.Clock()
    let deltatime = clock.getDelta()
    let modelMesh
    let mixer
    let clips
    nextButton.style.display = 'block'
    prevbutton.style.display = 'block'
    let idx = 1  // Start with the 2nd animation because the model starts with idle animation

    function playAnimationByIndex(mIndex) {
      if (modelMesh) {
        const clip = THREE.AnimationClip.findByName(clips, animationList[mIndex])
        const action = mixer.clipAction(clip)
        action.reset()
        action.paused = false
        action.setLoop(THREE.LoopOnce)
        action.clampWhenFinished = true
        action.timeScale = 1
        action.play()
        action.enable = true
      }
    }

    function playReverseAnimationByIndex(mIndex) {
      if (modelMesh) {
        const clip = THREE.AnimationClip.findByName(clips, animationList[mIndex])
        const action = mixer.clipAction(clip)
        action.reset()
        if (action.time === 0) {
          action.time = clip.duration
        }
        action.paused = false
        action.setLoop(THREE.LoopOnce)
        action.timeScale = -1.0
        action.play()
      }
    }

    function nextAnimation() {
      if (modelMesh) {
        playAnimationByIndex(idx)
        idx = (idx + 1) % animationList.length
      }
    }

    function reveseAnimation(){
      playReverseAnimationByIndex(idx)
    }

    function update(event) {
      if (mixer) {
        deltatime = clock.getDelta()
        mixer.update(deltatime)
      }
    }
    nextButton.onclick = nextAnimation
    prevbutton.onclick = reveseAnimation

    model.addEventListener('model-loaded', (e) => {
      modelMesh = model.getObject3D('mesh')
      mixer = new THREE.AnimationMixer(modelMesh)
      clips = modelMesh.animations
    })
    scene.addEventListener('updated', update)
  },
  tick(time) {
    this.el.sceneEl.emit('updated')
  },
})

export {nextButtonComponent}
koktavy commented 3 years ago

In the animation-mixer update method, parameter changes besides clip only apply to the active actions. The changes should be applied just before playing other clips in playAction but it seems that isn't happening correctly.

One workaround is to remove the mixer and set it again:

animatedEl.removeAttribute('animation-mixer')
animatedEl.setAttribute('animation-mixer', 'clip: *; timeScale: -1; clampWhenFinished:true; repetitions:1;')
vincentfretin commented 1 year ago

Is this still an issue? If yes, do you have a fix? Somebody want to create a PR?

vincentfretin commented 1 year ago

Can somebody create a glitch with a reproducible case if this is still an issue? Thank you.

dirkk0 commented 1 year ago

No, it does work, see my glitch here: https://mech-walker.glitch.me/ The Mech walks backwards.

vincentfretin commented 1 year ago

Thank you @dirkk0 I'll close then. If anyone still has an issue, please create a new issue with a reproducible case that use a master build on glitch.

v5ma commented 6 months ago

Here is an example that works, and an explanation for why it works. GLBanireverse