<commit_before>/*
  Copyright (C) 2008 by <NAME>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"

#include "csgeom/math.h"

#include "fsmnode.h"

template <>
class csHashComputer<CS::Plugin::Skeleton2::FSMNodeFactory::StateTransitionKey>
{
public:
  /// Compute a hash value for \a key.
  static uint ComputeHash (const CS::Plugin::Skeleton2::FSMNodeFactory::StateTransitionKey& key)
  {
    return (key.fromState ^ key.toState) ^ 0xABCDEF98;
  }
};


CS_PLUGIN_NAMESPACE_BEGIN(Skeleton2)
{
  AnimationFifo::AnimationFifo (AnimationFifoCb* cb)
    : currentState (STATE_STOPPED), cb (cb)
  {}

  void AnimationFifo::PushAnimation (CS::Animation::iSkeletonAnimNode* node, bool directSwitch,
    float blendInTime, size_t cbData)
  {
    if (!node)
      return;

    AnimationInstruction newInstr = {node, cbData, blendInTime, directSwitch};
    instructions.Push (newInstr);

    if (currentState == STATE_STOPPED)
    {
      currentState = STATE_PLAYING;
      currentAnimation = instructions.PopTop ();
      currentAnimation.node->Play ();
    }
  }

  void AnimationFifo::RemoveAnimations (size_t cbData)
  {
    AnimationInstruction instruction;
    instruction.cbData = cbData;

    // There can be at most two animations
    instructions.Delete (instruction);
    instructions.Delete (instruction);
  }

  void AnimationFifo::BlendState (CS::Animation::csSkeletalState* state, float baseWeight /* = 1.0f */)
  {
    switch (currentState)
    {
    case STATE_STOPPED:
      break;
    case STATE_PLAYING:
      {
        currentAnimation.node->BlendState (state, baseWeight);        
      }
      break;    
    case STATE_BLENDING:
      {
        if (instructions.GetSize () > 0)
        {
          AnimationInstruction& top = instructions.Top ();

          const float blendAmount = csClamp (blendTime / top.blendInTime, 1.0f, 0.0f);
          currentAnimation.node->BlendState (state, baseWeight);
          top.node->BlendState (state, baseWeight * blendAmount);
        }        
        else
        {
          currentAnimation.node->BlendState (state, baseWeight);
        }       
      }
      break;    
    }
  }

  void AnimationFifo::TickAnimation (float dt)
  {
    switch (currentState)
    {
    case STATE_STOPPED:
      break;
    case STATE_PLAYING:
      {
        if (instructions.GetSize () > 0)
        {
          AnimationInstruction& top = instructions.Top ();

          if (top.directSwitch ||
	      currentAnimation.node->GetPlaybackPosition ()
	      + dt * currentAnimation.node->GetPlaybackSpeed ()
	      + top.blendInTime
	      > currentAnimation.node->GetDuration ())
          {
            if (top.blendInTime > SMALL_EPSILON)
            {
              // Blend
              currentState = STATE_BLENDING;
              blendTime = 0;
              top.node->Play ();
            }
            else
            {
              // Switch
	      if (currentAnimation.node)
		currentAnimation.node->Stop ();
              currentAnimation = instructions.PopTop ();
              currentAnimation.node->Play ();

              if (cb)
              {
                cb->NewAnimation (currentAnimation.cbData);
              }
            }
          }
        }

        currentAnimation.node->TickAnimation (dt);        
      }
      break;    
    case STATE_BLENDING:
      {
        AnimationInstruction& top = instructions.Top ();

        if (blendTime + dt > top.blendInTime)
        {
          // Blend over, finalize switch
          currentAnimation.node->TickAnimation (dt);
	  currentAnimation.node->Stop ();
          currentAnimation = instructions.PopTop ();
          if (cb)
          {
            cb->NewAnimation (currentAnimation.cbData);
          }

          currentAnimation.node->TickAnimation (dt);

          currentState = STATE_PLAYING;
        }
        else<commit_msg>Fixed the returned current state<commit_after>/*
  Copyright (C) 2008 by <NAME>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"

#include "csgeom/math.h"

#include "fsmnode.h"

template <>
class csHashComputer<CS::Plugin::Skeleton2::FSMNodeFactory::StateTransitionKey>
{
public:
  /// Compute a hash value for \a key.
  static uint ComputeHash (const CS::Plugin::Skeleton2::FSMNodeFactory::StateTransitionKey& key)
  {
    return (key.fromState ^ key.toState) ^ 0xABCDEF98;
  }
};


CS_PLUGIN_NAMESPACE_BEGIN(Skeleton2)
{
  AnimationFifo::AnimationFifo (AnimationFifoCb* cb)
    : currentState (STATE_STOPPED), cb (cb)
  {}

  void AnimationFifo::PushAnimation (CS::Animation::iSkeletonAnimNode* node, bool directSwitch,
    float blendInTime, size_t cbData)
  {
    if (!node)
      return;

    AnimationInstruction newInstr = {node, cbData, blendInTime, directSwitch};
    instructions.Push (newInstr);

    if (currentState == STATE_STOPPED)
    {
      currentState = STATE_PLAYING;
      currentAnimation = instructions.PopTop ();
      currentAnimation.node->Play ();

      if (cb)
	cb->NewAnimation (currentAnimation.cbData);
    }
  }

  void AnimationFifo::RemoveAnimations (size_t cbData)
  {
    AnimationInstruction instruction;
    instruction.cbData = cbData;

    // There can be at most two animations
    instructions.Delete (instruction);
    instructions.Delete (instruction);
  }

  void AnimationFifo::BlendState (CS::Animation::csSkeletalState* state, float baseWeight /* = 1.0f */)
  {
    switch (currentState)
    {
    case STATE_STOPPED:
      break;
    case STATE_PLAYING:
      {
        currentAnimation.node->BlendState (state, baseWeight);        
      }
      break;    
    case STATE_BLENDING:
      {
        if (instructions.GetSize () > 0)
        {
          AnimationInstruction& top = instructions.Top ();

          const float blendAmount = csClamp (blendTime / top.blendInTime, 1.0f, 0.0f);
          currentAnimation.node->BlendState (state, baseWeight);
          top.node->BlendState (state, baseWeight * blendAmount);
        }        
        else
        {
          currentAnimation.node->BlendState (state, baseWeight);
        }       
      }
      break;    
    }
  }

  void AnimationFifo::TickAnimation (float dt)
  {
    switch (currentState)
    {
    case STATE_STOPPED:
      break;
    case STATE_PLAYING:
      {
        if (instructions.GetSize () > 0)
        {
          AnimationInstruction& top = instructions.Top ();

          if (top.directSwitch ||
	      currentAnimation.node->GetPlaybackPosition ()
	      + dt * currentAnimation.node->GetPlaybackSpeed ()
	      + top.blendInTime
	      > currentAnimation.node->GetDuration ())
          {
            if (top.blendInTime > SMALL_EPSILON)
            {
              // Blend
              currentState = STATE_BLENDING;
              blendTime = 0;
              top.node->Play ();

              if (cb)
                cb->NewAnimation (top.cbData);
            }
            else
            {
              // Switch
	      if (currentAnimation.node)
		currentAnimation.node->Stop ();
              currentAnimation = instructions.PopTop ();
              currentAnimation.node->Play ();

              if (cb)
                cb->NewAnimation (currentAnimation.cbData);
            }
          }
        }

        currentAnimation.node->TickAnimation (dt);        
      }
      break;    
    case STATE_BLENDING:
      {
        AnimationInstruction& top = instructions.Top ();

        if (blendTime + dt > top.blendInTime)
        {
          // Blend over, finalize switch
          currentAnimation.node->TickAnimation (dt);
	  currentAnimation.node->Stop ();
          currentAnimation = instructions.PopTop ();
          if (cb)
          {
            cb->NewAnimation (currentAnimation.cbData);
          }

          currentAnimation.node->TickAnimation (dt);

          currentState = STATE_PLAYING;
        }
        else
{'fraction_non_alphanumeric': 0.0932912906382516, 'fraction_numerical': 0.006088942046319452, 'mean_word_length': 2.2433004231311706, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5096601', 'n_tokens_mistral': 2707, 'n_tokens_neox': 2537, 'n_words': 659}