in Firmware/ExpressivePixelsCore/CAnimationManager.cpp [192:361]
bool CAnimationManager::ProcessFrame(ACTIVE_ANIMATIONSEQUENCE *pSequence, uint8_t *pFrameAsBytes)
{
char frameType;
uint16_t pixelCount;
uint16_t totalPixels = m_pCDisplayTopology != NULL ? m_pCDisplayTopology->TotalPixels() : m_pCDisplayArray->TotalPixels();
// Only read more if there are frames remaining
if(pSequence->currentFrameOffset < pSequence->Sequence.Meta.cbFrames)
{
// Read frame type
if(!ReadAnimationBytes(pSequence, (uint8_t *) &frameType, sizeof(frameType)))
return true;
// Determine the animation frame type or action
switch(frameType)
{
case 'I':
// Extract the pixel count
if(!ReadAnimationBytes(pSequence, (uint8_t *) &pixelCount, sizeof(pixelCount)))
return true;
//DEBUGLOGLN("Animator KEY frame %d pixels", pixelCount);
// Process pixels
for(int i = 0 ; i < pixelCount ; i++)
{
uint8_t paletteIndex;
uint16_t pixelPosition;
// Extract palette index
if(!ReadAnimationBytes(pSequence, (uint8_t *) &paletteIndex, sizeof(paletteIndex)))
return true;
if (paletteIndex <= pSequence->Sequence.Meta.cbPallete - 1)
{
PALETTE_ENTRY *paletteEntry = pSequence->Sequence.pPalette + paletteIndex;
uint32_t color = CDisplayArray::ColorFromBytes(paletteEntry->r, paletteEntry->g, paletteEntry->b);
// Figure topographical position
if(m_pCDisplayTopology != NULL)
pixelPosition = m_nRotation == 0 ? m_pCDisplayTopology->Map(i) : m_pCDisplayTopology->MapRotated(i, m_nRotation);
else
pixelPosition = i;
if (pixelPosition != TOPOLOGYPIXEL_UNASSIGNED)
{
if (pFrameAsBytes != NULL)
m_pCDisplayArray->GetPixelBytes(color, pFrameAsBytes + (i * 3), pFrameAsBytes + (i * 3) + 1, pFrameAsBytes + (i * 3) + 2);
else
// Extract color from palette and set LED color
m_pCDisplayArray->SetPixelColor(pixelPosition, color);
}
}
}
if (pFrameAsBytes == NULL)
m_pCDisplayArray->Show();
break;
case 'P':
// Extract the pixel count
if(!ReadAnimationBytes(pSequence, (uint8_t *) &pixelCount, sizeof(pixelCount)))
return true;
//DEBUGLOGLN("Animator Predictive frame %d pixels", pixelCount);
// Process pixels
for(int i = 0 ; i < pixelCount ; i++)
{
uint8_t paletteIndex;
uint16_t logicalPixelPosition = 0;
uint16_t physicalPixelPosition = TOPOLOGYPIXEL_UNASSIGNED;
// Determine if 8 or 16 bit pixel position size
uint8_t pixelPositionByteSize = totalPixels > 256 ? sizeof(uint16_t) : sizeof(uint8_t);
// Extract pixel position
if(!ReadAnimationBytes(pSequence, (uint8_t *) &logicalPixelPosition, pixelPositionByteSize))
return true;
// Extract palette index
if(!ReadAnimationBytes(pSequence, (uint8_t *) &paletteIndex, sizeof(paletteIndex)))
return true;
if (paletteIndex < pSequence->Sequence.Meta.cbPallete)
{
PALETTE_ENTRY *paletteEntry = pSequence->Sequence.pPalette + paletteIndex;
uint32_t color = CDisplayArray::ColorFromBytes(paletteEntry->r, paletteEntry->g, paletteEntry->b);
if (m_pCDisplayTopology != NULL)
physicalPixelPosition = m_nRotation == 0 ? m_pCDisplayTopology->Map(logicalPixelPosition) : m_pCDisplayTopology->MapRotated(logicalPixelPosition, m_nRotation);
// If a positional pixel
if(physicalPixelPosition != TOPOLOGYPIXEL_UNASSIGNED)
{
if (pFrameAsBytes != NULL)
m_pCDisplayArray->GetPixelBytes(color, pFrameAsBytes + (logicalPixelPosition * 3), pFrameAsBytes + (logicalPixelPosition * 3) + 1, pFrameAsBytes + (logicalPixelPosition * 3) + 2);
else
// Extract color from palette and set LED color
m_pCDisplayArray->SetPixelColor(physicalPixelPosition, color);
}
}
}
if (pFrameAsBytes == NULL)
m_pCDisplayArray->Show();
break;
case 'D':
uint16_t delayMillis;
if (!ReadAnimationBytes(pSequence, (uint8_t *) &delayMillis, sizeof(delayMillis)))
return true;
m_activeDelayMillis = delayMillis;
m_previousDelayMillis = millis();
DEBUGLOGLN("WAIT %d", m_activeDelayMillis);
break;
case 'F':
uint16_t fadeMillis;
if (!ReadAnimationBytes(pSequence, (uint8_t *) &fadeMillis, sizeof(fadeMillis)))
return true;
m_activeFadeKernel = 0;
m_activeFadeMillis = fadeMillis;
m_previousFadeMillis = millis();
DEBUGLOGLN("FADE over %d ms", m_activeFadeMillis);
return false;
}
}
// See if all of the animation bytes have been read
if(pFrameAsBytes == NULL && pSequence->currentFrameOffset >= pSequence->Sequence.Meta.cbFrames)
{
//DEBUGLOGLN("Animator ALL animation bytes read %d >= %d", pSequence->currentFrameOffset ,pSequence->Sequence.framesByteLen);
/*** Last frame in animation now complete ***/
if(pSequence->Sequence.Meta.loopCount == 1)
return true;
else
{
if (pSequence->Sequence.Meta.loopCount > 1)
{
if (pSequence->Sequence.Meta.loopCount < 255)
{
// This animation repeats
pSequence->currentRepeatIteration++;
// If all repeats complete
if(pSequence->currentRepeatIteration >= pSequence->Sequence.Meta.loopCount)
{
//DEBUGLOGLN("Animator ALL repeats complete %d >= %d", pSequence->currentRepeatIteration, pSequence->Sequence.loopCount);
// Return full complete
return true;
}
}
}
else if (m_disableInfiniteLooping)
return true;
// Start the animation over again
pSequence->currentFrameOffset = 0;
#ifdef VARIANTCAPABILITY_STORAGE
if (pSequence->Sequence.pFile != NULL)
CStorage::Seek(pSequence->Sequence.pFile, pSequence->Sequence.frameBytesStartOffset);
#endif
m_pCDisplayArray->Clear();
}
}
// Animation still in progress
//DEBUGLOGLN("Animation still in progress");
return false;
}