// Constructor
 public IFABlenderMain(List <IFAClip> oldMain, IFAClip newMain, string interpolationMode, DrawGraphOnImage drawGraphOnImage)
 {
     this.oldMainClips      = oldMain;
     this.newMainClip       = newMain;
     this.interpolationMode = interpolationMode;
     this.drawGraphOnImage  = drawGraphOnImage;
     createAllClips();
     createOldMainClipsInitialWeights();
 }
 public IFABlenderTransition(List <IFAClip> oldMain, IFAClip transition, IFAClip newMain, string interpolationMode, DrawGraphOnImage drawGraphOnImage,
                             float blendDuration, float bezierP1, float bezierP2)
     : this(oldMain, transition, newMain, interpolationMode, drawGraphOnImage)
 {
     this.blendDuration = blendDuration;
     this.pBezierP1     = bezierP1;
     this.pBezierP2     = bezierP2;
 }
    //private float mainLoopTriggerTime = 1.0f;           // Time over which a main loop is interpolated with itself. [TODO] Should be made relative to main clip duration, as it will behave strangely for small durations.

    /*
     * Awake
     */
    private void Awake()
    {
        animator        = GetComponent <Animator>();
        goToEmotionList = new List <GoToEmotionEntry>();

        currentlyPlayingClips = new List <IFAClip>();

        // Create Playable Graph
        playableGraph = PlayableGraph.Create("ClairePlayableGraph");
        playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
        var playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", animator);

        // Create Top Level Layer Mixer
        AnimationLayerMixerPlayable mixerLayerPlayable = AnimationLayerMixerPlayable.Create(playableGraph, 2);

        playableOutput.SetSourcePlayable(mixerLayerPlayable);

        // Create an Emotion Mixer
        int numberOfClips = 0;

        for (int i = 0; i < emotionObjects.Count; i++)
        {
            for (int j = 0; j < emotionObjects[i].animationGroupList.Count; j++)
            {
                if (emotionObjects[i].animationGroupList[j].main)
                {
                    numberOfClips++;
                }
                if (emotionObjects[i].animationGroupList[j].transitionIn)
                {
                    numberOfClips++;
                }
            }
        }
        mixerEmotionPlayable = AnimationMixerPlayable.Create(playableGraph, numberOfClips);    // Second argument sets number of inputs for clips to connect.

        // Wrap AnimController
        runtimeAnimController = animator.runtimeAnimatorController;
        var runtimeAnimControllerPlayable = AnimatorControllerPlayable.Create(playableGraph, runtimeAnimController);

        // Connect to Top Level Layer Mixer
        playableGraph.Connect(runtimeAnimControllerPlayable, 0, mixerLayerPlayable, 0);
        playableGraph.Connect(mixerEmotionPlayable, 0, mixerLayerPlayable, 1);
        mixerLayerPlayable.SetInputWeight(0, 1.0f);
        mixerLayerPlayable.SetInputWeight(1, 1.0f);
        mixerLayerPlayable.SetLayerMaskFromAvatarMask(1, headMask);
        //mixerLayerPlayable.SetLayerAdditive(1, true);

        // 1. Wraps each clip in a playable and connects them to the emotion mixer
        // 2. Also populate "playablesDict" to later be able to access the AnimationClipPlayables by their Index in the emotionMixer
        // 3. Main animations are not connected directly: Instead another MixerPlayable (mainMixer) is connected.
        //    The main playable is copied and both the original and copy are connected to the new MainMixer.
        //    This is to allow for smoothly looping main animations
        playablesDict = new Dictionary <string, int>();      // String: "Name"+"Index of Emotion Variation"; Int: Index in mixerEmotionPlayable
        int playablesCount     = 0;
        int tempPlayablesCount = 0;

        for (int i = 0; i < emotionObjects.Count; i++)
        {
            tempPlayablesCount = playablesCount;
            for (int j = 0; j < emotionObjects[i].animationGroupList.Count; j++)
            {
                if (emotionObjects[i].animationGroupList[j].main)
                {
                    playablesDict.Add(emotionObjects[i].name + j, playablesCount);
                    AnimationMixerPlayable mainMixer = AnimationMixerPlayable.Create(playableGraph, 2);
                    //var mainMixerBehaviour = ScriptPlayable<IFAMainMixerBehaviour>.Create(playableGraph, 1);                                    // Throwing a behaviour controller between emotionMixer and mainMixer
                    //mainMixerBehaviour.GetBehaviour().constructor2(mainMixer, mainLoopTriggerTime, mainMixerMainIndex, mainMixerCopyIndex);     // To automize looping of the main clip
                    //playableGraph.Connect(mainMixerBehaviour, 0, mixerEmotionPlayable, playablesCount);
                    playableGraph.Connect(mainMixer, 0, mixerEmotionPlayable, playablesCount);
                    playablesCount++;

                    AnimationClipPlayable main = AnimationClipPlayable.Create(playableGraph, emotionObjects[i].animationGroupList[j].main);
                    playableGraph.Connect(main, 0, mainMixer, mainMixerMainIndex);
                    mainMixer.SetInputWeight(mainMixerMainIndex, 1.0f);  // Set first clip to active
                    main.SetDuration(emotionObjects[i].animationGroupList[j].main.length);

                    AnimationClipPlayable mainCopy = AnimationClipPlayable.Create(playableGraph, emotionObjects[i].animationGroupList[j].main);
                    playableGraph.Connect(mainCopy, 0, mainMixer, mainMixerCopyIndex);
                    mainMixer.SetInputWeight(mainMixerCopyIndex, 0.1f);  // Set second clip to inactive
                    mainCopy.SetDuration(emotionObjects[i].animationGroupList[j].main.length);
                }

                if (emotionObjects[i].animationGroupList[j].transitionIn)
                {
                    playablesDict.Add(emotionObjects[i].name + "TransitionIn" + j, playablesCount);
                    AnimationClipPlayable transition = AnimationClipPlayable.Create(playableGraph, emotionObjects[i].animationGroupList[j].transitionIn);
                    playableGraph.Connect(transition, 0, mixerEmotionPlayable, playablesCount);

                    transition.SetDuration(emotionObjects[i].animationGroupList[j].transitionIn.length);
                    playablesCount++;
                }
            }

            // If an emotion has any animationClips, it can be transitioned to
            if (tempPlayablesCount < playablesCount)
            {
                goToEmotionList.Add(new GoToEmotionEntry(emotionObjects[i].name, false, i));
            }
        }

        // Unrelated to Playables; For Display Purposes
        if (GOWithDrawGraphOnImage)
        {
            drawGraphOnImage = GOWithDrawGraphOnImage.GetComponent <DrawGraphOnImage>();
        }
    }