Example #1
0
 private void TrimEndTime_KeyDown(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
 {
     if (e.Key == Windows.System.VirtualKey.Enter)
     {
         CutRange.Focus(FocusState.Programmatic);
     }
 }
Example #2
0
        private void CutRange_ValueChanged(object sender, Microsoft.Toolkit.Uwp.UI.Controls.RangeChangedEventArgs e)
        {
            TrimStartTime.LostFocus -= TrimStartTime_LostFocus;
            TrimEndTime.LostFocus   -= TrimEndTime_LostFocus;
            CutRange.Focus(FocusState.Programmatic);
            TrimStartTime.LostFocus += TrimStartTime_LostFocus;
            TrimEndTime.LostFocus   += TrimEndTime_LostFocus;

            if (e.ChangedRangeProperty == Microsoft.Toolkit.Uwp.UI.Controls.RangeSelectorProperty.MaximumValue)
            {
                UpdatePreviewVideoOnDisplay(true, CutRange.RangeMax, null);
            }
            else
            {
                UpdatePreviewVideoOnDisplay(false, null, CutRange.RangeMin);
            }
        }
    /// <summary>
    /// This method doesn't say the specific cut, but it constraints
    /// the time for searching interesting events. It is mostly
    /// dependent on current emotion.
    /// </summary>
    public CutRange EvaluateCutRangeForEvent(EmotionEvent e)
    {
        CutRange        range = new CutRange();
        EmotionSpectrum emotionAtEventTime = emotionEngine.GetSpectrum(e.timestamp);
        CoreEmotion     coreEmotion        = EmotionEngine.FindMainEmotion(emotionAtEventTime);

        // In seconds
        switch (coreEmotion)
        {
        case CoreEmotion.Joy:
            range.minCutTime = ProceduralEngine.RandomRange(1f, 2f);
            range.maxCutTime = ProceduralEngine.RandomRange(7f, 8f);
            break;

        case CoreEmotion.Trust:
            range.minCutTime = ProceduralEngine.RandomRange(2f, 5f);
            range.maxCutTime = ProceduralEngine.RandomRange(7f, 10f);
            break;

        case CoreEmotion.Fear:
            range.minCutTime = ProceduralEngine.RandomRange(1f, 2f);
            range.maxCutTime = ProceduralEngine.RandomRange(4f, 6f);
            break;

        case CoreEmotion.Surprise:
            range.minCutTime = ProceduralEngine.RandomRange(1.5f, 2f);
            range.maxCutTime = ProceduralEngine.RandomRange(2f, 4f);
            break;

        case CoreEmotion.Sadness:
            range.minCutTime = ProceduralEngine.RandomRange(1f, 1.5f);
            range.maxCutTime = ProceduralEngine.RandomRange(2f, 4f);
            break;

        case CoreEmotion.Disgust:
            range.minCutTime = ProceduralEngine.RandomRange(1f, 2f);
            range.maxCutTime = ProceduralEngine.RandomRange(3f, 4f);
            break;

        case CoreEmotion.Anger:
            range.minCutTime = ProceduralEngine.RandomRange(.3f, 1f);
            range.maxCutTime = ProceduralEngine.RandomRange(1f, 3f);
            break;

        case CoreEmotion.Anticipation:
            range.minCutTime = ProceduralEngine.RandomRange(2f, 4f);
            range.maxCutTime = ProceduralEngine.RandomRange(4f, 5f);
            break;
        }

        switch (e.type)
        {
        case EmotionEvent.EmotionEventType.Start:
            // Longer cuts when showing for first time
            range.minCutTime *= e.chunkDelimitsSegment ? 1f : .75f;
            range.maxCutTime *= e.chunkDelimitsSegment ? 1f : .75f;
            break;

        case EmotionEvent.EmotionEventType.End:
            // Longer cuts when something disappears for good
            range.minCutTime *= e.chunkDelimitsSegment ? 1.5f : 1f;
            range.maxCutTime *= e.chunkDelimitsSegment ? 1.5f : 1f;
            break;

        case EmotionEvent.EmotionEventType.LocalMaximum:
            range.minCutTime *= 1f;
            range.maxCutTime *= 1f;
            break;

        case EmotionEvent.EmotionEventType.LocalMinimum:
            range.minCutTime *= 2f;
            range.maxCutTime *= 2f;
            break;
        }

        TrackChunkData structureData = emotionEngine.GetCurrentStructureData(e.timestamp);

        if (structureData != null)
        {
            // More intense -> shorter
            float normalizedStructuralIntensity = Mathf.Pow(structureData.GetIntensity(e.timestamp), 2f);
            range.minCutTime *= 1.35f - normalizedStructuralIntensity * .5f;
            range.maxCutTime *= 1.35f - normalizedStructuralIntensity * .5f;

            // TODO: decide if we need further modifications of cut time based on type.
            // Intensity curve should cover most I think
            StructureType currentStructure = emotionEngine.GetStructureAtTime(e.timestamp);

            switch (currentStructure)
            {
            case StructureType.None:
                break;

            case StructureType.Sustain:
                break;

            case StructureType.Increasing:
                break;

            case StructureType.Decreasing:
                break;
            }
        }

        range.minCutTime = Mathf.Max(0.01f, range.minCutTime);
        range.maxCutTime = Mathf.Max(0.02f, range.maxCutTime);

        float tmp = range.minCutTime;

        range.minCutTime = Mathf.Min(range.minCutTime, range.maxCutTime);
        range.maxCutTime = Mathf.Max(tmp, range.maxCutTime);

        // Normalize times
        range.minCutTime /= ProceduralEngine.Instance.Duration;
        range.maxCutTime /= ProceduralEngine.Instance.Duration;
        return(range);
    }
    /// <summary>
    /// This method has two main responsibilities:
    /// - Decide when to cut
    /// - Decide what shot to take
    /// It is tied to a specific event, so that the chaining of shots is possible
    /// </summary>
    protected ShotInformation TryFindCut(EmotionEvent startEvent)
    {
        ShotInformation shot = new ShotInformation();

        shot.valid             = false;
        shot.selectedCamera    = null;
        shot.type              = TransitionType.Cut; // TODO: for now...
        shot.strategy          = null;
        shot.interestPoint     = null;
        shot.sampledStrategies = new List <KeyValuePair <ProceduralCameraStrategy, float> >();
        shot.startEvent        = startEvent;

        // Make sure we don't lag
        float timestamp = Mathf.Max(startEvent.timestamp, ProceduralEngine.Instance.CurrentTimeNormalized);

        CutRange searchRange = EvaluateCutRangeForEvent(startEvent);
        float    minT        = timestamp + searchRange.minCutTime;
        float    maxT        = timestamp + searchRange.maxCutTime * (1f + nextShotTries * .1f); // Increase search range when it fails

        List <EmotionEventGroup> searchEvents = ProceduralEngine.Instance.EventDispatcher.GetFutureEventGroups(minT, maxT);

        if (searchEvents.Count == 0)
        {
            Debug.Log("Could not find event groups... " + minT + ", " + maxT);
            return(shot);
        }

        EmotionEventGroup selectedGroup = null;
        bool structural = false;

        foreach (EmotionEventGroup g in searchEvents)
        {
            if (g.ContainsStructuralEvent())
            {
                selectedGroup = g;
                structural    = true;
            }
        }

        if (selectedGroup == null)
        {
            selectedGroup = ProceduralEngine.SelectRandomWeighted(searchEvents, x => x.GetPriority());
        }

        // We found a subset of interesting events, now we can pick something in here
        if (selectedGroup != null && selectedGroup.events.Count > 0)
        {
            EmotionEvent selectedEvent;

            if (structural)
            {
                selectedEvent = selectedGroup.GetStructuralEvent();
            }
            else
            {
                selectedEvent = ProceduralEngine.SelectRandomWeighted(selectedGroup.events, x => GetEventPriority(x));
            }

            shot.duration = (selectedEvent.timestamp - timestamp);
            shot.selectedNextEventTrigger = selectedEvent;

            // Try cutting before, but not after
            float margin        = emotionEngine.BeatDurationNormalized * .5f;
            float fuzzyDuration = shot.duration - ProceduralEngine.RandomRange(0f, margin);

            if (fuzzyDuration > searchRange.minCutTime && fuzzyDuration < searchRange.maxCutTime)
            {
                shot.duration = fuzzyDuration;
            }

            shot.valid = true;
        }

        return(shot);
    }