Game Development Community

How to schedule() something for the next frame from script ?

by Orion Elenzil · in Torque Game Engine · 08/29/2006 (3:44 pm) · 5 replies

I'll start with the goal:

i'd like to set the profile of a certain control,
take a snapshot of the control w/ the new profile,
and then restore the original profile,
all as quickly as possible.
from script.

- prefereably w/o the user seeing even a flicker, but more on that later..


the reason you can't just do this:

%myControl.setProfile(profileB);
snapshot(%myControl);
%myControl.setProfile(profileA);

is of course that %myControl doesn't get a chance to render its lovely self between the two setProfile()s.

i tried delaying the snapshot() by "0" and "1" ms, but that didn't work. "100" works intermittently, which i've been programming long enough to know that in cases like this, "intermittently" actually means that even if i used 500 instead of 100, it'll still fail in the field all the time.

so i'm thinking of doing something starting a little looping schedule which just waits for $TSControl::frameCount to incriment.

but i'd love it if there were something cleaner.



- now all these methods will involve the user seeing at least one frame of the temporary profile.

a couple work-arounds exist:

* the first is rather elegant but a lot of work: basically do something similar to Manoel's water-shader resource, and render to a hidden bitmap, and make the rendering code aware of whether it's rendering to the normal bitmap or a special one. this is nice because it's more or less a sure thing, and we wouldn't have to involve any schedules at all! but it's a bunch of work and i'm not sure it's worth it at this stage just to save the user a little flicker.

* the second is a wild and wooly idea and may be straight-up bad. The notion here is to force just that one control to render, and without swapping the front & back buffers, grab the screencap from the back buffer, and then allow the following normal render cycle to repair the damage. - is this just crazy ?


tia,
orion

#1
08/29/2006 (3:56 pm)
Personally, I'd just do your first "workaround". I'd try to just make it a feature of GuiControl, but then I like to live in the C code and make it do all sorts of unnatural things.

I'm not sure how much you can do from script, without at least extending the engine code a little bit.
#2
08/29/2006 (3:58 pm)
So i implemented the wait-for-$TSControl::FrameCount-to-increase-thing and it worked as well as could be expected. edit: that is, the control flashes for exactly one frame, but the resulting snapshots are always taken during that one frame.

here's the pseudo-ish code in case anyone's interested,
with lots of details removed for clarity.

function doSnap()
{
   theControl.setProfile(profileB);
   $lastFrame = $TSControl::frameCount;
   waitForNextFrameToSnap();
}

function waitForNextFrameToSnap()
{
   cancel($waitForFrameSchedule);
   
   if ($TSControl::frameCount <= $lastFrame)
   {
      $waitForFrameSchedule = schedule(50, 0, "waitForNextFrameToSnap");
      return;
   }
   
   doSnap2();
}

function doSnap2()
{
   takeSnapshot(theControl);

   theControl.setProfile(profileA);
}
#3
08/29/2006 (4:00 pm)
Hi James - thanks for the reply.

yeah, that's definitely the high road.
I think i'm gonna roll with the kinda janky schedule thing for now
since it basically works and the flash isn't so bad compared to some of the other fish to fry around here.

i'm sure this will be revisted in the next couple months,
i'll post a follow up.
#4
08/29/2006 (4:07 pm)
Nice. I was wondering if there was a frame counter or if you could just watch for game time to change or something.

However, isn't 50ms is assuming your framerate is 20 fps or slower? If you wanted it to never be more than 1 frame, I would think you'd want to make the schedule run as fast as possible.
#5
08/29/2006 (4:12 pm)
Good point.
hmm.
i'm nervous about setting up a bunch of fast schedule()s on slow machines, tho.

let's see. say we've got a really bad FPS of 10. that's about 100ms per frame.
eh, it's probably okay to shorten the schedule to something like 10ms. thanks!

actually i didn't even realized that the sim ran faster than the framerate,
which is what i seem to be seeing since schedule(0) definitely occurred before another frame had been rendered.