bool VAnimationComponent::Play(const char * szAnimationName, bool bLoop, const char * szEndEventName, bool bEndEventOnce)
{
  VisBaseEntity_cl* pOwnerEntity = vstatic_cast<VisBaseEntity_cl*>(GetOwner());
  if (pOwnerEntity == NULL)
    return false;

  if(m_pAnimCtrl != NULL) 
    m_pAnimCtrl->RemoveEventListener(m_pOwner);

  // we know, that the owner is at least a VisBaseEntity_cl,
  // since the component is only attachable to VisBaseEntity_cl or inherited classes
  m_pAnimCtrl = VisAnimConfig_cl::StartSkeletalAnimation(pOwnerEntity, szAnimationName, bLoop ? VANIMCTRL_LOOP : VSKELANIMCTRL_DEFAULTS);

  // fall back for vertex animations
  if(m_pAnimCtrl == NULL)
  {
    m_pAnimCtrl = VisAnimConfig_cl::StartVertexAnimation(pOwnerEntity, szAnimationName, bLoop ? VANIMCTRL_LOOP : VVERTANIMCTRL_DEFAULTS);

    if(m_pAnimCtrl == NULL) 
      return false;
  }

  // register event if specified
  if(szEndEventName)
    AddEndEvent(szEndEventName, bEndEventOnce);

  m_pAnimCtrl->AddEventListener(m_pOwner);

  VisAnimConfig_cl* pAnimConfig = pOwnerEntity->GetAnimConfig();
  if (pAnimConfig != NULL)
  {
    pAnimConfig->SetFlags(pAnimConfig->GetFlags() | MULTITHREADED_ANIMATION);
  }
  
  m_sCurrentAnim = szAnimationName;
  return true;
}
BOOL VLineFollowerComponent::StartAnimation(const char *szAnimName)
{
  VisBaseEntity_cl* pOwner = (VisBaseEntity_cl *)GetOwner();
  if (!pOwner)
    return false;

  m_bPlayingAnim = false;

  // Check for animation sequences
  VDynamicMesh *pMesh = pOwner->GetMesh();
  if (!pMesh || !pMesh->GetSequenceSetCollection() || !pMesh->GetSequenceSetCollection()->GetSequenceSetCount())
    return false;

  VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult = NULL;
  VisVertexAnimDeformer_cl* pVertexAnimDeformer = NULL;

  // Get the sequence(s) for vertex and skeletal animation
  VisSkeletalAnimSequence_cl* pAnimSequenceSkeletal = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence(szAnimName, VIS_MODELANIM_SKELETAL);
  VisVertexAnimSequence_cl* pAnimSequenceVertex = (VisVertexAnimSequence_cl*)pMesh->GetSequence(szAnimName, VIS_MODELANIM_VERTEX);

  // If no sequence with the given name is present
  if ((!pAnimSequenceSkeletal) && (!pAnimSequenceVertex))
  {
    VisAnimSequenceSet_cl * pSequenceSet =  pMesh->GetSequenceSetCollection()->GetSequenceSet(0);
    // Find the first skeletal or vertex animation and use it
    for (int i=0; i< pSequenceSet->GetSequenceCount(); ++i)
    {
      VisAnimSequence_cl* pTempAnimSequence = pSequenceSet->GetSequence(i);
      if (pTempAnimSequence->GetType() == VIS_MODELANIM_SKELETAL)
      {
        // If it is a skeletal animation, create a config for it
        VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);
        VisSkeletalAnimControl_cl* pSkeletalAnimControl = VisSkeletalAnimControl_cl::Create(pMesh->GetSkeleton(), (VisSkeletalAnimSequence_cl*)pTempAnimSequence, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
        pFinalSkeletalResult->SetSkeletalAnimInput(pSkeletalAnimControl);
        pOwner->SetAnimConfig(pConfig);
        m_bPlayingAnim = true;
        return true;
      }
      else if (pTempAnimSequence->GetType() == VIS_MODELANIM_VERTEX)
      {
        // If it is a vertex animation, create a config for it
        VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateVertexConfig(pMesh, &pVertexAnimDeformer);
        VisVertexAnimControl_cl* pVertexAnimControl = VisVertexAnimControl_cl::Create((VisVertexAnimSequence_cl*)pTempAnimSequence, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
        pVertexAnimDeformer->AddVertexAnimControl(pVertexAnimControl, 1.0f);
        pOwner->SetAnimConfig(pConfig);
        m_bPlayingAnim = true;
        return true;
      }
    }
    // If neither a skeletal nor a vertex animation has been found, report failure
    return false;
  }

  // If both a vertex and a skeletal animation with the given name has been found
  // create a combined config for skeletal and vertex animation.
  VisAnimConfig_cl* pConfig = NULL;
  if ((pAnimSequenceSkeletal) && (pAnimSequenceVertex))
    pConfig = VisAnimConfig_cl::CreateSkeletalVertexConfig(pMesh, &pFinalSkeletalResult, &pVertexAnimDeformer);

  // If it is just a skeletal animation, create a config for it
  if (pAnimSequenceSkeletal)
  {    
    if (!pConfig)
      pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);

    // If a skeletal animation has been found create a control for it
    VisSkeletalAnimControl_cl* pSkeletalAnimControl = VisSkeletalAnimControl_cl::Create(pMesh->GetSkeleton(), pAnimSequenceSkeletal, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
    // And set it as the input for the final skeletal result
    pFinalSkeletalResult->SetSkeletalAnimInput(pSkeletalAnimControl);
  }

  // If it is just a vertex animation, create a config for it
  if (pAnimSequenceVertex)
  {
    if (!pConfig)
      pConfig = VisAnimConfig_cl::CreateVertexConfig(pMesh, &pVertexAnimDeformer);

    // If a vertex animation has been found create a control for it
    VisVertexAnimControl_cl* pVertexAnimControl = VisVertexAnimControl_cl::Create(pAnimSequenceVertex, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
    // And set add it to the vertex anim deformer
    pVertexAnimDeformer->AddVertexAnimControl(pVertexAnimControl, 1.0f);
  }

  // Set the current config
  pOwner->SetAnimConfig(pConfig);

  // Make sure we get the motion delta from the animation
  pOwner->GetAnimConfig()->SetFlags(pOwner->GetAnimConfig()->GetFlags() | APPLY_MOTION_DELTA | MULTITHREADED_ANIMATION);

  // And report success
  m_bPlayingAnim = true;
  return true;
}