コード例 #1
0
    //--------------------------------------------------------------------------


    //==========================================================================
    //Get Roll Speed from command
    //==========================================================================
    public float GetMovement(int command, float RollAngle)
    {
        if (playMode.Equals(PlayMode.Human))
        {
            left  = Input.GetKey("left");
            right = Input.GetKey("right");
        }
        else if (playMode.Equals(PlayMode.AI))
        {
            left  = command == 1;
            right = command == 2;
        }

        if (left)
        {
            rollSpeed = MaxRollSpeed;
        }

        else if (right)
        {
            rollSpeed = -MaxRollSpeed;
        }

        else
        {
            rollSpeed = -Mathf.Sign(RollAngle) *
                        Mathf.Min(MaxRollSpeed, Mathf.Abs(RollAngle));
        }
        return(rollSpeed);
    }
コード例 #2
0
 private bool CheckIfTimerShouldBeActive()
 {
     if (_playMode.Equals(PlayMode.FindBest))
     {
         return(true);
     }
     if ((_cbxRunInterations.Checked || _simulationRunsInBackground) && _nudRemainigIterationCount.Value > _nudRemainigIterationCount.Minimum)
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
コード例 #3
0
 // sends events when the play mode is changed
 public void SetPlayMode(PlayMode playMode)
 {
     if (playMode.Equals(PlayMode.Default))
     {
         _playNext = new DefaultNextSong();
     }
     else
     {
         _playNext = new ShuffleNextSong();
     }
     //PlayModeNotification(new object(), new PlayModeEventArgs(playMode));
 }
コード例 #4
0
ファイル: Main.cs プロジェクト: nmarsden/crawly-unity
    void StartLevel(int selectedLevelNumber, PlayMode playMode)
    {
        // Disable physics
        // Note: otherwise the cell's particle system adversely effects the player on start
        DisablePhysics();

        currentLevelNum     = selectedLevelNumber;
        Time.timeScale      = 1;
        isGameOver          = false;
        isGameCompleted     = false;
        isPaused            = false;
        isOkClicked         = false;
        isShowDeathSequence = false;
        isDemoMode          = playMode.Equals(PlayMode.DEMO);

        // Deactivate camera Fly Around mode (if active)
        cameraController.DeactivateFlyAroundMode();

        // Play Music
        audioController.PlayMusic();

        // -- Levels --
        levels.GetComponent <Levels>().Init(currentLevelNum);

        // -- Arena --
        arena      = new GameObject();
        arena.name = "Arena";
        arena.AddComponent <Arena>();
        arena.GetComponent <Arena>().Init(this);

        // -- Player --
        player      = new GameObject();
        player.name = "Player";
        player.AddComponent <Player>();
        player.GetComponent <Player>().Init(this);
        if (isDemoMode)
        {
            player.GetComponent <Player>().ToggleAutopilotMode();
        }

        // -- Pickups --
        pickups      = new GameObject();
        pickups.name = "Pickups";
        pickups.AddComponent <Pickups>();
        pickups.GetComponent <Pickups>().Init(this);

        // -- Show HUD --
        ShowHUD(playMode);

        // Enable physics after 0.1 seconds (Note: long enough for all objects to have started)
        StartCoroutine(EnablePhysicsAfterSeconds(0.1f));
    }
コード例 #5
0
ファイル: TagarelaEditor.cs プロジェクト: sideways28/tagarela
    void Update()
    {
        if (settings != null)
        {

            if (!tagarela.isPlaying && playMode != PlayMode.stopped)
            {
                if (playMode != PlayMode.currentTime)
                {
                    if (SelectedAudioclip != null)
                    {
                        if (tagarela.audio.clip == null) tagarela.audio.clip = SelectedAudioclip;
                        tagarela.audio.Stop();
                        tagarela.audio.Play();
                    }
                    tagarela.StartTimer();
                }

                tagarela.isPlaying = true;
                updateTimeline = true;
            }

            switch (playMode)
            {
                case PlayMode.all:

                    if (tagarela.getTimer() >= tagarela.settings.animationTime - 0.01f)
                    {
                        tagarela.setTimer(0);
                    }

                    timeNormalized = tagarela.getTimer() / tagarela.settings.animationTime;
                    updateMorphValue = tagarela.getTimer();

                    disableGuiControls = true;
                    updateMorph = true;

                    if (SelectedAudioclip != null && !tagarela.audio.isPlaying)
                    {
                        tagarela.audio.Stop();
                        tagarela.audio.Play();
                    }

                    break;

                case PlayMode.currentTime:
                    if (SelectedAudioclip != null) tagarela.audio.Play();
                    playMode = !guiTimeline.isDragging && !guiTimelineSegment.isDragging ? PlayMode.stopped : playMode;
                    if (tagarela.audio.clip != null && SelectedAudioclip != null)
                    {
                        tagarela.PreviewAudio(updateMorphValue);
                    }
                    else
                    {
                        tagarela.setTimer(updateMorphValue);
                    }
                    disableGuiControls = false;
                    break;

                case PlayMode.segment:

                    float valueA = guiTimelineSegment.KeyframeSet[0].Value;
                    float valueB = guiTimelineSegment.KeyframeSet[1].Value;
                    if (tagarela.getTimer() < valueA)
                    {
                        timeNormalized = 0f;
                        tagarela.setTimer(valueA);
                    }
                    else if (tagarela.getTimer() > valueB)
                    {
                        timeNormalized = 0f;
                        tagarela.setTimer(valueA);
                    }
                    else
                    {
                        timeNormalized = (tagarela.getTimer() - valueA) / tagarela.settings.animationTime;
                    }
                    updateMorphValue = tagarela.getTimer();
                    updateMorph = true;
                    disableGuiControls = true;
                    break;
            }

            if (updateTimeline) UpdateTimeline();
            if (updateMorph) UpdateMorph();

            if (tagarela.isPlaying)
            {
                if (playMode.Equals(PlayMode.stopped))
                {
                    tagarela.isPlaying = false;
                    tagarela.audio.Stop();
                    lastKeyframeSelected = -1;
                    timeNormalized = 0f;
                    updateMorphValue = 0f;
                    updateMorph = false;
                    disableGuiControls = false;
                }
            }
        }
    }
コード例 #6
0
    void Update()
    {
        if (settings != null)
        {
            if (!tagarela.isPlaying && playMode != PlayMode.stopped)
            {
                if (playMode != PlayMode.currentTime)
                {
                    if (SelectedAudioclip != null)
                    {
                        if (tagarela.audio.clip == null)
                        {
                            tagarela.audio.clip = SelectedAudioclip;
                        }
                        tagarela.audio.Stop();
                        tagarela.audio.Play();
                    }
                    tagarela.StartTimer();
                }

                tagarela.isPlaying = true;
                updateTimeline     = true;
            }


            switch (playMode)
            {
            case PlayMode.all:

                if (tagarela.getTimer() >= tagarela.settings.animationTime - 0.01f)
                {
                    tagarela.setTimer(0);
                }

                timeNormalized   = tagarela.getTimer() / tagarela.settings.animationTime;
                updateMorphValue = tagarela.getTimer();

                disableGuiControls = true;
                updateMorph        = true;

                if (SelectedAudioclip != null && !tagarela.audio.isPlaying)
                {
                    tagarela.audio.Stop();
                    tagarela.audio.Play();
                }

                break;

            case PlayMode.currentTime:
                if (SelectedAudioclip != null)
                {
                    tagarela.audio.Play();
                }
                playMode = !guiTimeline.isDragging && !guiTimelineSegment.isDragging ? PlayMode.stopped : playMode;
                if (tagarela.audio.clip != null && SelectedAudioclip != null)
                {
                    tagarela.PreviewAudio(updateMorphValue);
                    //tagarela.LateUpdate();
                }
                else
                {
                    tagarela.setTimer(updateMorphValue);
                }
                disableGuiControls = false;
                break;

            case PlayMode.segment:

                float valueA = guiTimelineSegment.KeyframeSet[0].Value;
                float valueB = guiTimelineSegment.KeyframeSet[1].Value;
                if (tagarela.getTimer() < valueA)
                {
                    timeNormalized = 0f;
                    tagarela.setTimer(valueA);
                }
                else if (tagarela.getTimer() > valueB)
                {
                    timeNormalized = 0f;
                    tagarela.setTimer(valueA);
                }
                else
                {
                    timeNormalized = (tagarela.getTimer() - valueA) / tagarela.settings.animationTime;
                }
                updateMorphValue   = tagarela.getTimer();
                updateMorph        = true;
                disableGuiControls = true;
                break;
            }

            if (updateTimeline)
            {
                UpdateTimeline();
            }
            if (updateMorph)
            {
                UpdateMorph();
            }

            if (tagarela.isPlaying)
            {
                if (playMode.Equals(PlayMode.stopped))
                {
                    tagarela.isPlaying = false;
                    tagarela.audio.Stop();
                    lastKeyframeSelected = -1;
                    timeNormalized       = 0f;
                    updateMorphValue     = 0f;
                    updateMorph          = false;
                    disableGuiControls   = false;
                }
            }
        }
    }
コード例 #7
0
    void OnGUI()
    {
        updateWindow = false;

        GUI.color = Color.white;

        GUI.DrawTexture(new Rect(0, 0, Screen.width, bgEditor.height), bgEditor);
        GUI.DrawTexture(new Rect(13, 14, logoEditor.width, logoEditor.height), logoEditor);

        GUILayout.BeginVertical(styleHeader);
        {
            GUI.color = Color.white;
            switch (dialog)
            {
            case ScreenDialog.InvalidObject:
                GUILayout.Label(log_msg, EditorStyles.boldLabel);
                break;

            case ScreenDialog.AddComponent:
                GUILayout.Label("", EditorStyles.boldLabel);
                GUILayout.Space(15f);

                if (GUILayout.Button("Add LipSync Component!"))
                {
                    //Debug.Log("UnityLipSync -> LipSync Component created on " + LastSelected.name);
                    Selection.activeGameObject.AddComponent(typeof(Tagarela));
                }
                break;

            case ScreenDialog.InitialScreen:

                GUILayout.BeginHorizontal();

                GUILayout.Label("Select Animation", styleFileTitle, GUILayout.Height(22));

                if (GUILayout.Button("Create New Animation", styleBigButtons, new GUILayoutOption[] { GUILayout.Width(150), GUILayout.Height(18) }))
                {
                    TagarelaEditorPopupNewFile popupNewFile = CreateInstance <TagarelaEditorPopupNewFile>();
                    popupNewFile.parent = this;
                    RefreshAudiolist();
                    popupNewFile.audioList = audioList;
                    popupNewFile.tagarela  = tagarela;
                    popupNewFile.ShowAuxWindow();
                }
                GUILayout.Space(8f);
                GUILayout.EndHorizontal();

                scrollViewVector = GUILayout.BeginScrollView(scrollViewVector, styleScrollview);
                {
                    GUILayout.BeginVertical();
                    {
                        GUILayout.Space(15f);

                        if (tagarela.animationFiles.Count > 0)
                        {
                            GUILayout.BeginVertical(styleGrid);
                            {
                                for (int i = tagarela.animationFiles.Count - 1; i >= 0; i--)
                                {
                                    GUILayout.BeginHorizontal();
                                    {
                                        //CLICK TO OPEN FILE
                                        if (GUILayout.Button(tagarela.animationFiles[i].name.ToString(), styleButtonGrid, GUILayout.Height(20)))
                                        {
                                            LoadAnimationFile(tagarela.animationFiles[i]);
                                        }
                                    }
                                    GUILayout.EndHorizontal();
                                }
                            }
                            GUILayout.EndHorizontal();
                        }
                        GUI.color = Color.white;


                        GUILayout.FlexibleSpace();
                    }     //end vertical
                    GUILayout.EndVertical();
                }
                GUILayout.EndScrollView();
                break;

            case ScreenDialog.Timeline:

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label(fileName, styleFileTitle, GUILayout.Height(21));

                    if (GUILayout.Button("Save", styleBigButtons, GUILayout.Width(70)))
                    {
                        string audioName = SelectedAudioclip != null ? SelectedAudioclip.name : "";
                        TagarelaFileManager.Save(fileName, tagarela.smrTotal, guiTimeline.keyframeSet, 0, audioName, tagarela.settings.animationTime);
                    }
                    if (GUILayout.Button("Close", styleBigButtons, GUILayout.Width(70)))
                    {
                        switch (EditorUtility.DisplayDialogComplex("Close", "Do you want to save?        ", "Yes", "No", "Cancel"))
                        {
                        case 0:
                            updateTimeline = true;
                            string audioName = SelectedAudioclip != null ? SelectedAudioclip.name : "";
                            TagarelaFileManager.Save(fileName, tagarela.smrTotal, guiTimeline.keyframeSet, 0, audioName, tagarela.settings.animationTime);

                            if (tagarela != null)
                            {
                                tagarela.Clean();
                            }
                            CleanVars();

                            dialog = ScreenDialog.InitialScreen;
                            break;

                        case 1:
                            if (tagarela != null)
                            {
                                tagarela.Clean();
                            }
                            CleanVars();
                            dialog = ScreenDialog.InitialScreen;
                            break;
                        }
                    }
                }
                GUILayout.EndHorizontal();

                updateMorph = false;

                //######################################################################################

                GUILayout.BeginVertical(styleBgTimeline, GUILayout.Height(bgTimeline.height));
                {
                    GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
                    {
                        if (SelectedAudioclip != null)
                        {
                            GUILayout.Label(SelectedAudioclip.name);
                        }

                        GUILayout.FlexibleSpace();

                        GUILayout.Space(20);

                        GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
                        {
                            if (settings != null)
                            {
                                GUILayout.Label(guiTimeline.selectedValue.ToString("0.000") + " / " + settings.animationTime.ToString("0.000"));
                            }
                        }
                        GUILayout.EndHorizontal();

                        GUILayout.Space(5);
                    }
                    GUILayout.EndHorizontal();


                    //scrollViewTimelineVector = GUILayout.BeginScrollView(scrollViewTimelineVector, styleScrollviewTimeline);
                    //{

                    GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
                    //GUILayout.BeginHorizontal(new GUILayoutOption[] { GUILayout.Width(1040f) });
                    {
                        GUILayout.Box("", new GUIStyle(), GUILayout.ExpandWidth(true));

                        Rect lastRect = GUILayoutUtility.GetLastRect();

                        if (lastRect.width > 1)
                        {
                            guiTimeline.Draw(new Rect(lastRect.x, 124, lastRect.width, 57));
                            if (audioPreviewSpectrum != null)
                            {
                                GUI.DrawTexture(new Rect(lastRect.x, 125, lastRect.width, 40), audioPreviewSpectrum);
                            }
                            guiTimelineSegment.Draw(new Rect(lastRect.x + 2, 125, lastRect.width - 2, 130));
                        }

                        switch (playMode)
                        {
                        case PlayMode.all:
                            GUI.color = new Color(130f / 255f, 170f / 255f, 30f / 255f, 0.3f);
                            GUI.DrawTexture(new Rect(guiTimeline.timeLineRect.x + 1, guiTimeline.timeLineRect.y + 44, (guiTimeline.timeLineRect.width) * timeNormalized, 11), EditorGUIUtility.whiteTexture);
                            break;

                        case PlayMode.segment:
                            GUI.color = new Color(130f / 255f, 170f / 255f, 30f / 255f, 0.3f);
                            GUI.DrawTexture(new Rect(guiTimelineSegment.KeyframeSet[0].IconRect.x + 7, guiTimeline.timeLineRect.y + 44, (guiTimeline.timeLineRect.width - 18) * timeNormalized, 11), EditorGUIUtility.whiteTexture);
                            break;
                        }
                    }
                    GUILayout.EndHorizontal();

                    GUI.color = Color.white;

                    //}
                    //GUILayout.EndScrollView();

                    GUILayout.Space(67);

                    GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
                    {
                        GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
                        {
                            if (guiTimeline.keyframeSet.Count == 1 || disableGuiControls)
                            {
                                GUI.enabled = false;
                            }
                            if (GUILayout.Button(icoRemove, styleBtTimeline, new GUILayoutOption[] { GUILayout.Width(22), GUILayout.Height(20) }))     //btRemove
                            {
                                guiTimeline.RemoveKeyframe(guiTimeline.selectedIndex);
                            }
                            GUI.enabled = true;
                            if (disableGuiControls)
                            {
                                GUI.enabled = false;
                            }
                            if (GUILayout.Button(icoAdd, styleBtTimeline, new GUILayoutOption[] { GUILayout.Width(22), GUILayout.Height(20) }))     //btAdd
                            {
                                TagarelaMorphTarget _morphTargetList = new TagarelaMorphTarget();
                                _morphTargetList.Populate(tagarela.smrTotal);
                                guiTimeline.AddKeyframe(0.0f, _morphTargetList);
                                updateTimeline = true;
                                updateMorph    = true;
                            }
                        }
                        GUILayout.EndHorizontal();


                        GUILayout.FlexibleSpace();

                        if (GUILayout.Button("Sliders to zero", styleBtTimeline, new GUILayoutOption[] { GUILayout.Width(120), GUILayout.Height(20) }))     //btAdd
                        {
                            TagarelaMorphTarget _MorphTarget = guiTimeline.morphSliders;
                            if (_MorphTarget != null)
                            {
                                for (int i = 0; i < _MorphTarget.id.Count; i++)
                                {
                                    _MorphTarget.sliderValue[i] = 0;
                                }
                            }
                            updateTimeline = true;
                        }

                        GUILayout.FlexibleSpace();

                        GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
                        {
                            GUI.enabled = !disableGuiControls;

                            if (GUILayout.Button(icoPlay, styleBtTimeline, new GUILayoutOption[] { GUILayout.Width(22), GUILayout.Height(20) }))
                            {
                                //tagarela.setTimer(0);
                                playMode = PlayMode.all;
                            }

                            GUI.enabled = true;
                            if (!guiTimelineSegment.active || disableGuiControls)
                            {
                                GUI.enabled = false;
                            }
                            if (GUILayout.Button(icoPlaySegment, styleBtTimeline, new GUILayoutOption[] { GUILayout.Width(22), GUILayout.Height(20) }))
                            {
                                tagarela.setTimer(guiTimelineSegment.KeyframeSet[0].Value);
                                playMode = PlayMode.segment;
                            }

                            GUI.enabled = false;
                            if (!playMode.Equals(PlayMode.stopped))
                            {
                                GUI.enabled = true;
                            }
                            if (GUILayout.Button(icoStop, styleBtTimeline, new GUILayoutOption[] { GUILayout.Width(22), GUILayout.Height(20) }))
                            {
                                //tagarela.audio.loop = false;
                                tagarela.setTimer(0f);
                                //tagarela.audio.Stop();
                                playMode = PlayMode.stopped;
                                if (tagarela.audio.isPlaying)
                                {
                                    tagarela.audio.Stop();
                                }
                            }

                            //if don´t have any audio, is a time based animation
                            if (SelectedAudioclip == null)
                            {
                                GUI.enabled = !disableGuiControls;
                                GUILayout.Space(10);
                                if (GUILayout.Button(icoClock, styleBtTimeline, new GUILayoutOption[] { GUILayout.Width(22), GUILayout.Height(20) }))
                                {
                                    TagarelaEditorPopupTimeLength popupAnimLength = CreateInstance <TagarelaEditorPopupTimeLength>();
                                    popupAnimLength.parent        = this;
                                    popupAnimLength.title         = "Time Settings";
                                    popupAnimLength.currentLength = popupAnimLength.newLength = guiTimeline.totalValue;
                                    popupAnimLength.ShowAuxWindow();
                                }
                                ;
                            }

                            GUI.enabled = true;
                        }
                        GUILayout.EndHorizontal();
                    }
                    GUILayout.EndHorizontal();
                }
                GUILayout.EndVertical();

                GUI.enabled      = !disableGuiControls;
                scrollViewVector = GUILayout.BeginScrollView(scrollViewVector, styleScrollview);
                {
                    if (tagarela.smrTotal.Count > 0 && guiTimeline.selectedIndex != -1 && guiTimeline.keyframeSet.Count > 0)
                    {
                        EditorGUILayout.BeginVertical();
                        {
                            //seleciona a lista de acordo com o index selecionado
                            TagarelaMorphTarget _MorphTarget = guiTimeline.morphSliders;
                            GUI.color = GUI.contentColor;
                            if (_MorphTarget != null)
                            {
                                //GUILayout.Space(13f);
                                GUILayout.Space(14);     //space before slider list
                                for (int i = 0; i < _MorphTarget.id.Count; i++)
                                {
                                    EditorGUILayout.BeginHorizontal(styleBgSlider, GUILayout.ExpandWidth(true));
                                    {
                                        float temp_value = _MorphTarget.sliderValue[i];

                                        GUILayout.Label(_MorphTarget.id[i], GUILayout.Width(150));
                                        temp_value = GUILayout.HorizontalSlider(temp_value, 0, 100, GUILayout.ExpandWidth(true));
                                        if (_MorphTarget.sliderValue[i] != temp_value)
                                        {
                                            _MorphTarget.sliderValue[i] = temp_value;

                                            updateTimeline = true;
                                        }
                                    }
                                    EditorGUILayout.EndHorizontal();
                                }
                            }
                        }
                        EditorGUILayout.EndVertical();
                    }

                    if (guiTimeline.refresh)
                    {
                        updateWindow = true;
                    }
                    if (guiTimeline.isDragging)
                    {
                        guiTimelineSegment.isDragging = false;
                        guiTimelineSegment.enabled    = false;

                        if (updateMorphValue != guiTimeline.selectedValue && SelectedAudioclip != null)
                        {
                            playMode         = PlayMode.currentTime;
                            updateMorphValue = guiTimeline.selectedValue;
                        }
                    }

                    if (guiTimeline.enabled && (guiTimeline.selectedIndex == -1 || lastKeyframeSelected != guiTimeline.selectedIndex))
                    {
                        lastKeyframeSelected = guiTimeline.selectedIndex;
                        updateMorphValue     = guiTimeline.selectedValue;
                        updateTimeline       = true;
                    }

                    //if a new keyframe was create or cloned, call a update om mesh list
                    if (guiTimeline.isKeyframeSetChanged)
                    {
                        lastKeyframeSelected             = -1;
                        guiTimeline.isKeyframeSetChanged = false;
                        updateTimeline = true;
                        updateMorph    = true;
                    }

                    if (guiTimelineSegment.refresh)
                    {
                        updateWindow = true;
                    }
                    if (guiTimelineSegment.isDragging)
                    {
                        guiTimeline.isDragging = false;
                        guiTimeline.enabled    = false;

                        if (updateMorphValue != guiTimelineSegment.SelectedValue)
                        {
                            playMode         = PlayMode.currentTime;
                            updateMorphValue = guiTimelineSegment.SelectedValue;
                            updateMorph      = true;
                        }
                    }

                    if (!guiTimelineSegment.isDragging && !guiTimeline.isDragging)
                    {
                        guiTimelineSegment.enabled = true;
                        guiTimeline.enabled        = true;
                    }

                    if (playMode.Equals(PlayMode.all) || playMode.Equals(PlayMode.segment))
                    {
                        guiTimeline.enabled = false;
                    }
                }
                GUILayout.EndScrollView();
                GUI.enabled = true;
                break;
            }
        }
        GUILayout.EndVertical();

        if (updateWindow || tagarela != null && tagarela.isPlaying)
        {
            Repaint();
        }
    }
コード例 #8
0
        private IEnumerator UpdateVals(PlayMode m, Action EndCycle)
        {
            bool    finished  = false;
            bool    forward   = !m.Equals(PlayMode.REVERSE);
            bool    loop      = m.Equals(PlayMode.LOOP_FORWARD) || m.Equals(PlayMode.LOOP_FORWARD_REVERSE);
            decimal startTime = DateTime.Now.Ticks;

            while (!finished && !_interrupt.Equals(StopMode.IMMEDIATE))
            {
                yield return(_timer);

                if (_interrupt.Equals(StopMode.FINISH_CYCLE_REVERSE))
                {
                    _interrupt = 0;
                    loop       = false;
                    // Backtrack forward cycle.
                    if (forward)
                    {
                        forward = false;
                        // Override start time to duration minus what was left to play.
                        startTime = DateTime.Now.Ticks - (_duration * TimeSpan.TicksPerMillisecond
                                                          - (DateTime.Now.Ticks - startTime));
                    }
                }
                float normalizedTime = (float)((DateTime.Now.Ticks - startTime)
                                               / TimeSpan.TicksPerMillisecond / _duration);

                if (normalizedTime > 1f)
                {
                    finished = true;
                }
                float evalTime = forward ? normalizedTime : 1f - normalizedTime;

                foreach (AnimData anim in _anims)
                {
                    // Original values are applied at the end of a cycle.
                    if (anim.interpolate)
                    {
                        anim.Apply(finished ? forward ? anim.max : anim.min
                            : Mathf.Lerp(anim.min, anim.max, anim.curve.Evaluate(evalTime)));
                    }
                    else
                    {
                        anim.Apply(finished ? forward ? anim.curve.Evaluate(1f) : anim.curve.Evaluate(0f)
                            : anim.curve.Evaluate(evalTime));
                    }
                }
                // Override finished behavior.
                if (finished)
                {
                    if (loop)
                    {
                        if (m.Equals(PlayMode.LOOP_FORWARD_REVERSE))
                        {
                            forward = !forward;
                            // Add a reverse cycle to get back to start value.
                            finished = _interrupt.Equals(StopMode.FINISH_CYCLE) && forward ? true : false;
                        }
                        else
                        {
                            finished = _interrupt > 0;
                        }
                        // Callback each loop cycle, except beginning of reverse cycle.
                        if (forward && !finished)
                        {
                            EndCycle?.Invoke();
                        }
                    }
                    else if (m.Equals(PlayMode.FORWARD_REVERSE) && _interrupt == 0 && forward)
                    {
                        // One reverse play for this mode.
                        forward  = !forward;
                        finished = false;
                    }
                    startTime = DateTime.Now.Ticks;
                }
            }
            HasStopped(EndCycle);
        }