Animation - advanced (Sample)

From SEGGER Wiki
Jump to: navigation, search
GUI_AdvancedAnimation.c
GUI AdvancedAnimation.gif
File(s) required
  • GUI_AdvancedAnimation.c
Runs in simulation Yes
Runs on target Yes
Download GUI_AdvancedAnimation.c

This sample demonstrates how more advanced animations can be created with emWin. The advanced animation makes use of slice callbacks, custom position calculation and multiple animation items.

Related articles

Code

/*********************************************************************
*                    SEGGER Microcontroller GmbH                     *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2020  SEGGER Microcontroller GmbH                *
*                                                                    *
*        Internet: www.segger.com    Support:  support@segger.com    *
*                                                                    *
**********************************************************************

** emWin V6.10 - Graphical user interface for embedded applications **
emWin is protected by international copyright laws.   Knowledge of the
source code may not be used to write a similar product.  This file may
only  be used  in accordance  with  a license  and should  not be  re-
distributed in any way. We appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : GUI_AdvancedAnimation.c
Purpose     : Sample showing how to create more advanced animations,
              showing features such as slice callbacks, custom
              position calculation and usage of several animation
              items.
Requirements: WindowManager - ( )
              MemoryDevices - ( )
              AntiAliasing  - ( )
              VNC-Server    - ( )
              PNG-Library   - ( )
              TrueTypeFonts - ( )
----------------------------------------------------------------------
*/

#include <stddef.h>

#include "GUI.h"

/*********************************************************************
*
*       Types
*
**********************************************************************
*/
typedef struct {
  int xSize, ySize;
  int xPart, yPart;
  int xPos, yPos;
  int Dir;
  int Size;
  int ObjectSize;
} ANIM_DATA;

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       _CalcPosition
*
*  Purpose:
*    Optional application defined position calculation in dependence
*    of the point of time within the animations timeline.
*/
static I32 _CalcPosition(GUI_TIMER_TIME ts, GUI_TIMER_TIME te, GUI_TIMER_TIME tNow) {
  I32 Result;
  int Diff, Pos, Modulation;

  Diff = te - ts;
  //
  // Linear calculation
  //
  if (Diff) {
    Result = (tNow * GUI_ANIM_RANGE) / (te - ts);
  } else {
    Result = GUI_ANIM_RANGE;
  }
  //
  // Modulation
  //
  Modulation = GUI_ANIM_RANGE >> 3;
  Pos = Result / Modulation;
  Result -= Modulation * Pos;
  if (Pos & 1) {
    Result  = Modulation - Result;
    Result  = (Result * Result) / Modulation;
    Result  = Modulation - Result;
  } else {
    Result  = (Result * Result) / Modulation;
  }
  Result += Modulation * Pos;
  return Result;
}

/*********************************************************************
*
*       _SliceInfo
*
*  Purpose:
*    Called before the first and after the last animation item of one
*    'slice' is drawn. A 'slice' means one or more animation item
*    which need to be drawn at a determined point in time.
*
*    That mechanism is used here to avoid flickering.
*/
static void _SliceInfo(int State, void * pVoid) {
  GUI_USE_PARA(pVoid);
  switch (State) {
  case GUI_ANIM_START:
    GUI_MULTIBUF_Begin();
    break;
  case GUI_ANIM_END:
    GUI_MULTIBUF_End();
    break;
  }
}

/*********************************************************************
*
*       _PrepareDrawing
*
*  Parameters:
*    pInfo   - Animation information passed by emWin to the application
*    pVoid   - Application defined void pointer
*    ppData  - Data (pointer) pointer to application data
*    xPosOld - Position to be used for clearing the display
*    Index   - Index of animation
*/
static void _PrepareDrawing(GUI_ANIM_INFO * pInfo, void * pVoid, ANIM_DATA ** ppData, int xPosOld, int Index) {
  ANIM_DATA * pData;

  //
  // Use custom void pointer for pointing to application defined data structure
  //
  pData = *ppData = (ANIM_DATA *)pVoid;
  //
  // Calculate x-position in dependence of current animation value
  //
  switch (pData->Dir) {
  case +1:
    pData->xPos = pData->xPart + ((pData->xSize - pData->xPart * 2) * pInfo->Pos) / GUI_ANIM_RANGE;
    break;
  case -1:
    pData->xPos = pData->xSize - pData->xPart - 1 - ((pData->xSize - pData->xPart * 2) * pInfo->Pos) / GUI_ANIM_RANGE;
    break;
  }
  //
  // Calculate object size in dependence of position
  //
  pData->ObjectSize = (pData->Size * pInfo->Pos) / GUI_ANIM_RANGE;
  //
  // Calculate y-position in dependence of animation index
  //
  pData->yPos = pData->yPart * (2 * Index + 1);
  //
  // Clears the area of the previous drawing
  //
  if (xPosOld) {
    GUI_ClearRect(xPosOld - pData->yPart, pData->yPos - pData->yPart, xPosOld + pData->yPart, pData->yPos + pData->yPart - 1);
  }
  //
  // Set item color in dependence of animation state
  //
  switch (pInfo->State) {
  case GUI_ANIM_END:
    pData->Dir = ((((pData->Dir + 1) / 2) ^ 1) * 2) - 1;
    //lint -fallthrough
  case GUI_ANIM_START:
    GUI_SetColor(GUI_RED);
    break;
  case GUI_ANIM_RUNNING:
    GUI_SetColor(GUI_GREEN);
    break;
  }
}

/*********************************************************************
*
*       _AnimDrawCircle
*/
static void _AnimDrawCircle(GUI_ANIM_INFO * pInfo, void * pVoid) {
  ANIM_DATA * pData;
  static int xPosOld;

  _PrepareDrawing(pInfo, pVoid, &pData, xPosOld, 0);
  GUI_DrawCircle(pData->xPos, pData->yPos, pData->ObjectSize);
  xPosOld = pData->xPos;
}

/*********************************************************************
*
*       _AnimDrawRect
*/
static void _AnimDrawRect(GUI_ANIM_INFO * pInfo, void * pVoid) {
  ANIM_DATA * pData;
  static int xPosOld;

  _PrepareDrawing(pInfo, pVoid, &pData, xPosOld, 2);
  GUI_DrawRect(pData->xPos - pData->ObjectSize, pData->yPos - pData->ObjectSize, pData->xPos + pData->ObjectSize, pData->yPos + pData->ObjectSize);
  xPosOld = pData->xPos;
}

/*********************************************************************
*
*       _AnimFillCircle
*/
static void _AnimFillCircle(GUI_ANIM_INFO * pInfo, void * pVoid) {
  ANIM_DATA * pData;
  static int xPosOld;

  _PrepareDrawing(pInfo, pVoid, &pData, xPosOld, 1);
  GUI_FillCircle(pData->xPos, pData->yPos, pData->ObjectSize);
  xPosOld = pData->xPos;
}

/*********************************************************************
*
*       _AnimFillRect
*/
static void _AnimFillRect(GUI_ANIM_INFO * pInfo, void * pVoid) {
  ANIM_DATA * pData;
  static int xPosOld;

  _PrepareDrawing(pInfo, pVoid, &pData, xPosOld, 3);
  GUI_FillRect(pData->xPos - pData->ObjectSize, pData->yPos - pData->ObjectSize, pData->xPos + pData->ObjectSize, pData->yPos + pData->ObjectSize);
  xPosOld = pData->xPos;
}

/*********************************************************************
*
*       _AnimDrawCross
*/
static void _AnimDrawCross(GUI_ANIM_INFO * pInfo, void * pVoid) {
  ANIM_DATA * pData;
  static int xPosOld;

  _PrepareDrawing(pInfo, pVoid, &pData, xPosOld, 4);
  GUI_DrawHLine(pData->yPos, pData->xPos - pData->ObjectSize, pData->xPos + pData->ObjectSize);
  GUI_DrawVLine(pData->xPos, pData->yPos - pData->ObjectSize, pData->yPos + pData->ObjectSize);
  xPosOld = pData->xPos;
}

/*********************************************************************
*
*       _SetupAnimationData
*/
static void _SetupAnimationData(ANIM_DATA * pData) {
  //
  // Get display size
  //
  pData->xSize = LCD_GetXSize();
  pData->ySize = LCD_GetYSize();
  pData->xPart = pData->xSize / 10;
  pData->yPart = pData->ySize / 10;
  pData->Size  = (pData->yPart * 4) / 5;
  pData->Dir   = 1;
}

/*********************************************************************
*
*       _AnimCreate
*/
static void _AnimCreate(ANIM_DATA * pData) {
  GUI_ANIM_HANDLE hAnim;

  //
  // Create animation object
  //
  //   Remark: The min time/frame here is 100 to be able to notice
  //           the colors. In a real application this value should
  //           be significantly smaller to ensure a smooth motion.
  //
  //   Slice callback routine --------------+
  //   Custom *void pointer --------+       |
  //   Minimum time per frame --+   |       |
  //   Duration ----------+     |   |       |
  //                      |     |   |       |
  hAnim = GUI_ANIM_Create(4000, 50, pData, _SliceInfo);
  //
  // Add animation items
  //
  //   Animation routine to be called ----------------------------+
  //   Custom *void pointer ---------------------------+          |
  //   Method of position calculation +                |          |
  //   End on timeline ---------+     |                |          |
  //   Start on timeline -+     |     |                |          |
  //                      |     |     |                |          |
  GUI_ANIM_AddItem(hAnim,    0, 2000, ANIM_ACCEL,      pData + 0, _AnimDrawCircle);
  GUI_ANIM_AddItem(hAnim,  500, 2500, ANIM_DECEL,      pData + 1, _AnimDrawRect);
  GUI_ANIM_AddItem(hAnim, 1000, 3000, ANIM_ACCELDECEL, pData + 2, _AnimFillCircle);
  GUI_ANIM_AddItem(hAnim, 1500, 3500, ANIM_LINEAR,     pData + 3, _AnimFillRect);
  GUI_ANIM_AddItem(hAnim, 2000, 4000, _CalcPosition,   pData + 4, _AnimDrawCross);  // Item with custom defined position calculation
  //
  // Start animation
  //
  // Function to be called on animation delete --+
  //                           +-----------------+
  // Num loops ------------+   |
  // Animation ------+     |   |
  //                 |     |   |
  GUI_ANIM_StartEx(hAnim, -1, NULL);  // -1 means endless loop
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       MainTask
*/
void MainTask(void) {
  ANIM_DATA aData[5];
  int i;

  GUI_Init();
  //
  // Initialize some data used for drawing operations
  //
  for (i = 0; i < (int)GUI_COUNTOF(aData); i++) {
    _SetupAnimationData(&aData[i]);
  }
  //
  // Create animation and pass pointer to user data and animation context
  //
  _AnimCreate(aData);
  //
  // Keep alive...
  //
  while (1) {
    GUI_Delay(100);
  }
}

/*************************** End of file ****************************/