Пример #1
0
        /// <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();
            }
        }
Пример #2
0
        /// <summary>Loads a track from the given track data.</summary>
        public static Track loadFromJson(Timeline timeline, JSObject json)
        {
            // First, is it an indexed array?
            // ["Hello!","I'm Dave"]      <- A basic dialogue track
            var   trackData = json as Json.JSIndexedArray;
            Track track     = null;

            if (trackData == null)
            {
                // Must explicitly define which type it is:
                // { "type":"style", "track":TheTrackData }
                string type = json.String("type");

                if (string.IsNullOrEmpty(type))
                {
                    Timeline.loadFailed(
                        "A track was an object but didn't contain a " +
                        "'type' field to state what kind of track it is.", timeline
                        );
                }

                // How about track data:
                var intenalTrackData = json["track"];

                if (intenalTrackData == null)
                {
                    // Nope!
                    Timeline.loadFailed("A track was an object but didn't contain a 'track' field.", timeline);
                }

                // Try and create a track of the specified type:
                type = type.Trim().ToLower();

                if (type == "style" || type == "css")
                {
                    // Style track.
                    track = new StyleTrack();
                }
                else if (type == "dialogue" || type == "speech" || type == "text")
                {
                    // Dialogue track.
                    track = new DialogueTrack();
                }
                else
                {
                    Timeline.loadFailed("Didn't recognise '" + type + "' as a track type.", timeline);
                }

                // Set it up:
                track.timeline = timeline;

                // Load the track data:
                track.load(intenalTrackData, trackData);

                return(track);
            }
            else if (trackData.length == 0)
            {
                // This is an empty track of unknown type.
                // It's a safe situation so we just return null:
                return(null);
            }

            // Detect what kind of track this is
            // based on the properties of the first entry:
            var firstEntry = trackData[0];

            if (firstEntry == null)
            {
                // Invalid track.
                Timeline.loadFailed("invalid track", timeline);
            }

            // string, "markup", "speakers" => Dialogue track
            if (firstEntry is Json.JSValue || firstEntry["markup"] != null || firstEntry["goto"] != null || firstEntry["audio"] != null ||
                firstEntry["speakers"] != null || firstEntry["speaker"] != null || firstEntry["options"] != null)
            {
                // If it contained goto, then we actually have a block of options in one slide.
                if (firstEntry["goto"] != null)
                {
                    JSIndexedArray td         = new JSIndexedArray();
                    JSObject       firstSlide = new JSObject();
                    firstSlide["options"] = trackData;
                    td.push(firstSlide);
                    trackData = td;
                }

                // Dialogue track.
                track = new DialogueTrack();

                // "selector","style" => Style track
            }
            else if (firstEntry["selector"] != null || firstEntry["style"] != null || firstEntry["animation"] != null)
            {
                // Style track.
                track = new StyleTrack();
            }
            else if (firstEntry["wait-at"] != null)
            {
                // Cue track.
                track = new CueTrack();
            }
            else
            {
                // Fail otherwise:
                Timeline.loadFailed("Unable to recognise this as a track.", timeline);
            }

            track.timeline = timeline;

            // Load it now:
            track.load(trackData, null);

            return(track);
        }