/// <summary>Advances this instance by the given amount.</summary>
        public void update(float deltaTime)
        {
            if (!started || paused)
            {
                // Awaiting data, usually.
                return;
            }

            if (currentTime == 0f)
            {
                if (deltaTime > 0.5f)
                {
                    // Block slow frames.
                    // This is almost always only ever the very first one
                    return;
                }

                // Clear running:
                firstRunning = null;
                lastRunning  = null;

                // Establish duration:
                float rawDuration = appliedDuration;

                if (rawDuration < 0f)
                {
                    if (duration == null)
                    {
                        // Infer from max end time, or '1' if there is none.
                        rawDuration = maxDefinedDuration;

                        if (rawDuration == 0f)
                        {
                            rawDuration = 1f;
                        }
                    }
                    else
                    {
                        rawDuration = duration.GetDecimal(style == null? null : style.RenderData, null);
                    }
                }

                actualDuration = rawDuration;

                // Starting backwards?
                backwards = (((int)direction & 1) == 1);

                // Update durations for each track:
                for (int i = 0; i < tracks.Length; i++)
                {
                    Track track = tracks[i];

                    if (track == null)
                    {
                        continue;
                    }

                    track.onStart();

                    // Set start/duration:
                    track.setStartAndDuration(rawDuration);

                    // Reset current index:
                    if (backwards)
                    {
                        track.currentSlide = track.slides.Length;
                    }
                    else
                    {
                        track.currentSlide = -1;
                    }
                }

                // Dispatch start:
                dispatch("start");

                // Instant?
                if (actualDuration == 0f)
                {
                    stop(true);

                    return;
                }
            }

            // If we have a timing leader, then current time is..
            if (timingLeader != null)
            {
                currentTime = timingLeader.computedStart;

                if (timingLeader.timing != null)
                {
                    // Get the leaders duration (just in case it has expired):
                    float duration = timingLeader.timing.GetDuration();
                    float current  = timingLeader.timing.GetCurrentTime();

                    currentTime += current;

                    if (duration != -1f && current >= duration)
                    {
                        // It's finished! Quit the timing leader:
                        // (This occurs if the lead time is shorter than the slide's duration).
                        timingLeader.endTimingLead();
                    }
                }
            }
            else
            {
                currentTime += deltaTime;
            }

            if (style != null && !style.Element.isRooted)
            {
                // Immediately stop - the element was removed (don't call the finished event):
                stop(false);

                return;
            }

            // Set ActiveValue by sampling from the curve (if there is one):

            if (progressSampler != null)
            {
                // Map through the progression curve:
                progressSampler.Goto(currentTime / actualDuration, true);
                currentTime = progressSampler.CurrentValue * actualDuration;
            }

            // Advance all tracks to the frame at 'progress'.
            for (int i = 0; i < tracks.Length; i++)
            {
                // Get the track:
                Track track = tracks[i];

                if (track == null || track.slides == null || track.slides.Length == 0)
                {
                    continue;
                }

                int length = track.slides.Length;

                int index = track.currentSlide;

                if (backwards)
                {
                    index--;
                }
                else
                {
                    index++;
                }

                while ((backwards && index >= 0) || (!backwards && index < length))
                {
                    // Get the slide:
                    Slide slideToStart = track.slides[index];

                    if (slideToStart.ignore)
                    {
                        // Skip:
                        if (backwards)
                        {
                            index--;
                        }
                        else
                        {
                            index++;
                        }

                        continue;
                    }

                    // Startable?
                    if (backwards)
                    {
                        if ((1f - slideToStart.computedEnd) >= currentTime)
                        {
                            // Nope!
                            break;
                        }
                    }
                    else if (slideToStart.computedStart >= currentTime)
                    {
                        // Nope!
                        break;
                    }

                    // Add to queue:
                    slideToStart.nextRunning     = null;
                    slideToStart.previousRunning = lastRunning;

                    if (firstRunning == null)
                    {
                        firstRunning = lastRunning = slideToStart;
                    }
                    else
                    {
                        lastRunning.nextRunning = slideToStart;
                        lastRunning             = slideToStart;
                    }

                    // Start it now:
                    slideToStart.start();

                    // Next:
                    track.currentSlide = index;

                    if (paused)
                    {
                        return;
                    }

                    if (backwards)
                    {
                        index--;
                    }
                    else
                    {
                        index++;
                    }
                }
            }

            // Kill any slides which are now done:
            endDoneSlides();

            if (currentTime >= actualDuration)
            {
                // Done!
                completedCycle();
            }
        }
        public virtual void Update(float deltaTime)
        {
            if (Animation == null || Animation.Paused)
            {
                return;
            }

            if (CurrentTime == 0f)
            {
                if (deltaTime > 0.5f)
                {
                    // Block slow frames.
                    // This is almost always only ever the very first one
                    return;
                }

                // Make sure they're the same units.
                if (ValueObject != null && RawStart.GetType() == RawTarget.GetType())
                {
                    // Raw start/end values:
                    StartValue = RawStart.GetRawDecimal();
                    DeltaValue = RawTarget.GetRawDecimal();

                    // Update delta:
                    DeltaValue -= StartValue;
                }
                else
                {
                    // Different units or are non-numeric! Also applies to e.g. "none" -> "x%".
                    // We'll be using pixel values here, but we must use GetDecimal every frame of the animation.

                    // Force it to be a raw decimal:
                    ValueObject = new Css.Units.DecimalUnit(0f);

                    // Write it straight out to the computed style:
                    // (Internally handles any aliases for us)
                    Animation.ComputedStyle[InnerPropertyInfo] = ValueObject;

                    // If it's not an alias, update hostValue:
                    if (!InnerPropertyInfo.IsAlias)
                    {
                        PropertyValueObject = ValueObject;
                    }
                }

                // Setup targets etc.

                // Instant?
                if (Animation.Duration == 0f)
                {
                    Complete();

                    return;
                }
            }

            CurrentTime += deltaTime;

            if (!Animation.Animating.isRooted)
            {
                // Immediately stop - the element was removed (don't call the finished event):
                Stop();

                return;
            }

            // Get the style:
            ComputedStyle computed = Animation.ComputedStyle;

            float progress = CurrentTime / Animation.TotalTime;

            if (progress >= 1f)
            {
                // Done!
                progress = 1f;

                // Make sure we are exactly the right value.
                Complete();

                // Stop there:
                return;
            }

            // Set ActiveValue by sampling from the curve (if there is one):

            if (ProgressSampler != null)
            {
                // Map through the progression curve:
                ProgressSampler.Goto(progress, true);
                progress = ProgressSampler.CurrentValue;
            }

            if (RawStart != ValueObject)
            {
                // Get the current from/to values:
                StartValue = RawStart.GetDecimal(computed.RenderData, InnerPropertyInfo);
                DeltaValue = RawTarget.GetDecimal(computed.RenderData, InnerPropertyInfo);

                // Update delta:
                DeltaValue -= StartValue;
            }

            // Read the value:
            ActiveValue = StartValue + (DeltaValue * progress);

            // Write it out to the CSS value:
            ValueObject.RawValue = ActiveValue;

            if (UpdateCss)
            {
                // And Tell the style it changed:
                // Note that in grouped properties, only the last one actually runs the update.
                computed.ChangeProperty(PropertyInfo, PropertyValueObject);
            }
        }