0

I have a Shady script for running an interactive program that involves numerous Stimulus objects with multiple dynamic properties. The World itself also has some dynamic properties.

I need a way to temporarily stop the interactive program. I can handle this "paused" state myself in my custom Animate callbacks attached to the world/stimuli, which are few in number, but it is clearly not ideal to handle it in every single dynamic property function. Is there a way to "pause" and later "unpause" all dynamics simultaneously? Preferably, at least the World.Animate callback (and all event handlers) would still be called each frame in this paused state so I can monitor the condition for unpausing and possibly do something different while paused.

swjm
  • 46
  • 5

1 Answers1

0

Looking at the _FrameCallback code in the Shady.Rendering submodule, it seems there's no global flag that says "run animation callbacks but not dynamic property evaluations". There's also no official/documented pathway to doing it.

However, on an instance-by-instance basis there's an unofficial way you could suspend dynamics: just nix out the undocumented ._dynamics attribute, perhaps storing it somewhere for later reinstatement. Do the same with the .Animate attribute to disable animation callbacks. To disable both types of dynamic together in one fell swoop, how about this:

def ToggleDynamics(x):
    x._disabled_dynamics, x._dynamics = x._dynamics, getattr(x, '_disabled_dynamics', {})
    x._disabled_Animate, x.Animate = x.Animate, getattr(x, '_disabled_Animate', None)

where x is your World or Stimulus instance. Then, to take this toggle global, you could do:

def ToggleDynamicsEverywhere(world):
    for thing in [world] + list(world.stimuli.values()):
        ToggleDynamics(thing)

Try that in python -m Shady shell showcase and you'll see that ToggleDynamicsEverywhere(world) suspends everything except video playback.

There are some fairly obvious ways you could customize these two functions to unequivocally enable/disable dynamics rather than toggling them, or to operate on all Stimulus instances but exclude the World, or to disable dynamic-properties-but-not-animation-callbacks or vice versa.

jez
  • 14,867
  • 5
  • 37
  • 64
  • A quick and dirty alternative is simply to say `world.fakeFrameRate=float('inf')` and that seems to stop time for any dynamic that depends on an input time `t`. But the dynamics are still called, so any changes they cause independent of `t` will still happen. – jez Jun 15 '20 at 17:39
  • 1
    Storing and restoring `_dynamics` works nicely. I'm also recording the duration of the paused period and using it to increment `stimulus.t0` when unpausing, which makes the dynamics act as though the missing time never happened. – swjm Jun 15 '20 at 19:25