Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APIs for integrating into existing event loop #336

Open
arthuro555 opened this issue Nov 2, 2023 · 3 comments
Open

APIs for integrating into existing event loop #336

arthuro555 opened this issue Nov 2, 2023 · 3 comments

Comments

@arthuro555
Copy link

Description

The Rive Advanced API requires that one uses rive's requestAnimationFrame. However, that is not practical for an HTML5 game engine:

  • All games need the game loop, not all games require rive animations. Thus we need to either override requestAnimationFrame to rive's globally, or to always include rive in builds even when it is not in use.
  • We may not be using requestAnimationFrame: when the window is not focused, requestAnimationFrame does not trigger, but some games require to continuously run, so we may for example switch to setTimeout during that time to ensure the game logic keeps on running, and rive might break there.
  • Generally it requires integrating rive more deeply into the core of the engine than it needs to be (when it could just be an extension)

Proposed solution

I am assuming rive is only doing this as a hand-holding way to ensure some code is called before and after rendering. However, since that is supposed to be the "Low level" API, it is expected either way that the API might not be convenient or hand-holding but in exchange allows complete power and flexibility.

Therefore, I think it would be great to be able to do something like rive.startFrame()/rive.endFrame() as an alternative (or full replacement) to rive's requestAnimationFrame

@zplata
Copy link
Contributor

zplata commented Nov 14, 2023

Hi! You're right in that we're creating a simple wrapper around the requestAnimationFrame function, mainly as a way to coordinate rendering calls that are deferred. This helps coordinate certain scenarios such as Rive assets with mesh's, where there's an offscreen context we draw to first before other main canvas2d draw calls. The rive-wrapped rAF function calls a (not-exposed) function called flushCanvasRenderers that helps coordinate that sequence.

If we exposed this flushCanvasRenderers function, you could certainly use your own game's rAF loop and then before calling the next frame, call this new exposed function to draw Rive content. And in the case of you switching to setTimeout, you should still be able to advance the artboard and stateMachine / animation by passing some elapsed time, however you want to track that, as you normally would within the rAF loop. Would this help with your integration?

Example of what this might look like:

function draw(time) {
    if (!lastTime) {
      lastTime = time;
    }
    const elapsedMs = time - lastTime;
    const elapsedSeconds = elapsedMs / 1000;
    lastTime = time;

    renderer.clear();
    if (artboard) {
      if (stateMachine) {
        stateMachine.advance(elapsedSeconds);
      }
      artboard.advance(elapsedSeconds);
      renderer.save();
      renderer.align(
        rive.Fit.contain,
        rive.Alignment.center,
        {
          minX: 0,
          minY: 0,
          maxX: canvas.width,
          maxY: canvas.height,
        },
        artboard.bounds
      );
      artboard.draw(renderer);
      renderer.restore();
    }
    // Draw Rive contents
    rive.flushCanvasRenderers();
    requestAnimationFrame(draw);
  }
  requestAnimationFrame(draw);

@arthuro555
Copy link
Author

Yes, that sounds perfect. Thank you for your response!

rive-engineering pushed a commit that referenced this issue Jan 22, 2024
poc for adding flush.

I think we just need to add `flushCanvasRenderers` as `flush` (also add this for the flushSkiaRenderer) and that should address #336.

obviously needs clean up, but just wanna make sure its worth sticking this in.

is there a good way to get back to the "issue" request to enquire if this will sort the problem? or do we just update the api and check in?

Diffs=
ebff4893c poc for adding "flush" (#6237)

Co-authored-by: Maxwell Talbot <talbot.maxwell@gmail.com>
Co-authored-by: Zachary Plata <plata.zach@gmail.com>
@zplata
Copy link
Contributor

zplata commented Feb 6, 2024

Hi sorry for the delay here.. but we just introduced a similarly-named API into v2.10.0.

You can use your own rAF loop, just make sure to call rive.resolveAnimationFrame() at the end of the loop, like in the snippet a few messages up. We're updating docs right now to reflect the new API, but you should be able to try it out now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants