// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using System.Collections.Generic; using System.IO; using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.Timeline.GUI; using FlaxEditor.GUI.Timeline.Undo; using FlaxEngine; using FlaxEngine.GUI; namespace FlaxEditor.GUI.Timeline.Tracks { /// /// The timeline media that represents a screen fade animation event. /// /// public class ScreenFadeMedia : Media { private sealed class Proxy : ProxyBase { /// /// Gets or sets the color gradient stops collection. /// [EditorDisplay("Gradient", EditorDisplayAttribute.InlineStyle), EditorOrder(10), Tooltip("The color gradient stops list.")] public List Gradient { get => Media.Gradient.Stops; set => Media.Gradient.Stops = value; } /// public Proxy(ScreenFadeTrack track, ScreenFadeMedia media) : base(track, media) { } } private byte[] _gradientEditingStartData; /// /// The gradient. /// public GradientEditor Gradient; /// /// Initializes a new instance of the class. /// public ScreenFadeMedia() { Gradient = new GradientEditor { AnchorPreset = AnchorPresets.StretchAll, Offsets = Margin.Zero, Parent = this, }; Gradient.Edited += OnGradientEdited; Gradient.EditingStart += OnGradientEditingStart; Gradient.EditingEnd += OnGradientEditingEnd; } private void OnGradientEdited() { Timeline?.MarkAsEdited(); } private void OnGradientEditingStart() { _gradientEditingStartData = EditTrackAction.CaptureData(Track); } private void OnGradientEditingEnd() { var after = EditTrackAction.CaptureData(Track); if (!Utils.ArraysEqual(_gradientEditingStartData, after)) Timeline.AddBatchedUndoAction(new EditTrackAction(Timeline, Track, _gradientEditingStartData, after)); _gradientEditingStartData = null; } /// public override void OnTimelineChanged(Track track) { base.OnTimelineChanged(track); PropertiesEditObject = track != null ? new Proxy((ScreenFadeTrack)track, this) : null; } /// public override void OnTimelineZoomChanged() { base.OnTimelineZoomChanged(); Gradient.SetScale(Timeline.Zoom * Timeline.UnitsPerSecond / Timeline.FramesPerSecond); } /// public override void OnTimelineFpsChanged(float before, float after) { base.OnTimelineFpsChanged(before, after); Gradient.OnTimelineFpsChanged(before, after); } /// public override void OnTimelineContextMenu(ContextMenu.ContextMenu menu, float time, Control controlUnderMouse) { base.OnTimelineContextMenu(menu, time, controlUnderMouse); if (controlUnderMouse is GradientEditor.StopControl stop) { menu.AddButton("Remove gradient stop", OnRemoveGradientStop).Tag = stop.Index; menu.AddSeparator(); } } private void OnRemoveGradientStop(ContextMenuButton button) { var stops = new List(Gradient.Stops); stops.RemoveAt((int)button.Tag); using (new TrackUndoBlock(Track)) Gradient.Stops = stops; } } /// /// The timeline track that represents a screen fade animation. /// /// public class ScreenFadeTrack : SingleMediaTrack { /// /// Gets the archetype. /// /// The archetype. public static TrackArchetype GetArchetype() { return new TrackArchetype { TypeId = 4, Name = "Screen Fade", Create = options => new ScreenFadeTrack(ref options), Load = LoadTrack, Save = SaveTrack, }; } private static void LoadTrack(int version, Track track, BinaryReader stream) { var e = (ScreenFadeTrack)track; var m = e.TrackMedia; m.StartFrame = stream.ReadInt32(); m.DurationFrames = stream.ReadInt32(); var stopsCount = stream.ReadInt32(); var stops = new List(stopsCount); for (int i = 0; i < stopsCount; i++) { GradientEditor.Stop stop; stop.Frame = stream.ReadInt32(); stop.Value = stream.ReadColor(); stops.Add(stop); } m.Gradient.Stops = stops; } private static void SaveTrack(Track track, BinaryWriter stream) { var e = (ScreenFadeTrack)track; if (e.Media.Count != 0) { var m = e.TrackMedia; stream.Write(m.StartFrame); stream.Write(m.DurationFrames); var stops = m.Gradient.Stops; stream.Write(stops.Count); for (int i = 0; i < stops.Count; i++) { var stop = stops[i]; stream.Write(stop.Frame); stream.Write(stop.Value); } } else { stream.Write(0); stream.Write(track.Timeline.DurationFrames); stream.Write(0); } } /// /// Initializes a new instance of the class. /// /// The options. public ScreenFadeTrack(ref TrackCreateOptions options) : base(ref options) { } } }