PDA

View Full Version : IBitmapControl animation


Guod3
02-23-2011, 08:07 PM
As part of a midi visualisation plug, I am designing animated glyphs using variant of IBitmapControl, call it IBitmapGlyphControl .

The glyph animation is triggered by passing a normalised value to it in ProcessMidiMsg()
with GetGUI()->SetControlFromPlug(GlyphIdx,CntlVal)

Now the glyph animates frame by frame until completion.

Is it the Draw method of IBitmapGlyphControl that calls SetDirty(true) so that it gets redrawn the next frame?
The intention is that Draw gets called whether or not the frame needs to change so that the glyph can control the progression of frames i.e Speed up by skipping bitmap indeces, slow down by not progressing bitmap index every frame etc.
When the animation has completed all the frames, it leaves the last index active, and does not call SetDirty(true) so that the endframe does not change (and is redrawn as required by closing/opening the window etc.)
Does this sound like a valid approach?

cc_
02-24-2011, 02:33 AM
I recently had to do something similar to smooth a mechanical meter display. I did it in IsDirty like this:


bool ISmoothedBitmapControl::IsDirty() {
double out = mFilter.filter( mValue );
// if close force to being equal to stop wasting redraws
if (fabs(out - mValue ) < 0.002) { out = mValue; }
if ( out != mDrawValue ) {
mDrawValue = out;
return true;
}
else {
return mDirty;
}
}


Of course I had to also change the Draw method so it draws based on mDrawValue instead of mValue.

Guod3
02-24-2011, 01:25 PM
Yes, it turns out changing the way IsDirty() returns its output is the way to control the animation. Here's mine:

bool IBitmapGlyphControl::Draw(IGraphics* pGraphics)
{
if (mValue){ //if input>zero e.g velocity event (MUST be normalized)
CurrentFrame = 1 + int(0.5 + mValue * (double) (mBitmap.N - 1));//calculate sub bitmap index (start point of animation)
mValue=0.0; //stop it from retriggering until new event
}
bool retval= pGraphics->DrawBitmap(&mBitmap, &mRECT, CurrentFrame, &mBlend); //draw the new frame
if (CurrentFrame>1){ //update to next frame
--CurrentFrame; //counting back to 1;
}
return retval;
}

bool IBitmapGlyphControl::IsDirty()
{
if (CurrentFrame>1)
return true; //animation is progressing, force redraw next display update (24fps)
else
return mDirty; //animation is done but redraw the last frame when required by GUI
}