From a1f88a17b1afa97d4e02bd85b6670c807d12de99 Mon Sep 17 00:00:00 2001
From: smoogipoo <smoogipoo@smgi.me>
Date: Tue, 26 Sep 2017 15:44:40 +0900
Subject: [PATCH] Re-namespace and split out timeline parts from the
 SummaryTimeline

---
 .../Timelines/Summary/Parts/BookmarkPart.cs   | 30 +++++++++
 .../Timelines/Summary/Parts/BreakPart.cs      | 31 +++++++++
 .../Summary/Parts/ControlPointPart.cs         | 65 +++++++++++++++++++
 .../Timelines/Summary/Parts/TimelinePart.cs   | 40 ++++++++++++
 .../Visualisations/DurationVisualisation.cs   | 25 +++++++
 .../Visualisations/PointVisualisation.cs      | 24 +++++++
 osu.Game/osu.Game.csproj                      |  6 ++
 7 files changed, 221 insertions(+)
 create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs
 create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs
 create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs
 create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs
 create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs
 create mode 100644 osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs

diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs
new file mode 100644
index 0000000000..5680b85c08
--- /dev/null
+++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs
@@ -0,0 +1,30 @@
+using osu.Framework.Allocation;
+using osu.Game.Beatmaps;
+using osu.Game.Graphics;
+using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
+
+namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
+{
+    /// <summary>
+    /// The part of the timeline that displays bookmarks.
+    /// </summary>
+    internal class BookmarkPart : TimelinePart
+    {
+        protected override void LoadBeatmap(WorkingBeatmap beatmap)
+        {
+            foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks)
+                Add(new BookmarkVisualisation(bookmark));
+        }
+
+        private class BookmarkVisualisation : PointVisualisation
+        {
+            public BookmarkVisualisation(double startTime)
+                : base(startTime)
+            {
+            }
+
+            [BackgroundDependencyLoader]
+            private void load(OsuColour colours) => Colour = colours.Blue;
+        }
+    }
+}
diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs
new file mode 100644
index 0000000000..fefb3d5f10
--- /dev/null
+++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs
@@ -0,0 +1,31 @@
+using osu.Framework.Allocation;
+using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.Timing;
+using osu.Game.Graphics;
+using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
+
+namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
+{
+    /// <summary>
+    /// The part of the timeline that displays breaks in the song.
+    /// </summary>
+    internal class BreakPart : TimelinePart
+    {
+        protected override void LoadBeatmap(WorkingBeatmap beatmap)
+        {
+            foreach (var breakPeriod in beatmap.Beatmap.Breaks)
+                Add(new BreakVisualisation(breakPeriod));
+        }
+
+        private class BreakVisualisation : DurationVisualisation
+        {
+            public BreakVisualisation(BreakPeriod breakPeriod)
+                : base(breakPeriod.StartTime, breakPeriod.EndTime)
+            {
+            }
+
+            [BackgroundDependencyLoader]
+            private void load(OsuColour colours) => Colour = colours.Yellow;
+        }
+    }
+}
diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs
new file mode 100644
index 0000000000..12b3624123
--- /dev/null
+++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs
@@ -0,0 +1,65 @@
+using System.Linq;
+using osu.Framework.Allocation;
+using osu.Framework.Extensions.IEnumerableExtensions;
+using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.ControlPoints;
+using osu.Game.Graphics;
+using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations;
+
+namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
+{
+    /// <summary>
+    /// The part of the timeline that displays the control points.
+    /// </summary>
+    internal class ControlPointPart : TimelinePart
+    {
+        protected override void LoadBeatmap(WorkingBeatmap beatmap)
+        {
+            ControlPointInfo cpi = beatmap.Beatmap.ControlPointInfo;
+
+            cpi.TimingPoints.ForEach(addTimingPoint);
+
+            // Consider all non-timing points as the same type
+            cpi.SoundPoints.Select(c => (ControlPoint)c)
+                .Concat(cpi.EffectPoints)
+                .Concat(cpi.DifficultyPoints)
+                .Distinct()
+                // Non-timing points should not be added where there are timing points
+                .Where(c => cpi.TimingPointAt(c.Time).Time != c.Time)
+                .ForEach(addNonTimingPoint);
+        }
+
+        private void addTimingPoint(ControlPoint controlPoint) => Add(new TimingPointVisualisation(controlPoint));
+        private void addNonTimingPoint(ControlPoint controlPoint) => Add(new NonTimingPointVisualisation(controlPoint));
+
+        private class TimingPointVisualisation : ControlPointVisualisation
+        {
+            public TimingPointVisualisation(ControlPoint controlPoint)
+                : base(controlPoint)
+            {
+            }
+
+            [BackgroundDependencyLoader]
+            private void load(OsuColour colours) => Colour = colours.YellowDark;
+        }
+
+        private class NonTimingPointVisualisation : ControlPointVisualisation
+        {
+            public NonTimingPointVisualisation(ControlPoint controlPoint)
+                : base(controlPoint)
+            {
+            }
+
+            [BackgroundDependencyLoader]
+            private void load(OsuColour colours) => Colour = colours.Green;
+        }
+
+        private abstract class ControlPointVisualisation : PointVisualisation
+        {
+            protected ControlPointVisualisation(ControlPoint controlPoint)
+                : base(controlPoint.Time)
+            {
+            }
+        }
+    }
+}
diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs
new file mode 100644
index 0000000000..30786a80ff
--- /dev/null
+++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs
@@ -0,0 +1,40 @@
+using System;
+using OpenTK;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Game.Beatmaps;
+
+namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
+{
+    /// <summary>
+    /// Represents a part of the summary timeline..
+    /// </summary>
+    internal abstract class TimelinePart : CompositeDrawable
+    {
+        private readonly Container timeline;
+
+        protected TimelinePart()
+        {
+            AddInternal(timeline = new Container { RelativeSizeAxes = Axes.Both });
+        }
+
+        [BackgroundDependencyLoader]
+        private void load(OsuGameBase osuGame)
+        {
+            osuGame.Beatmap.ValueChanged += b =>
+            {
+                timeline.Clear();
+                timeline.RelativeChildSize = new Vector2((float)Math.Max(1, b.Track.Length), 1);
+                LoadBeatmap(b);
+            };
+
+            timeline.RelativeChildSize = new Vector2((float)Math.Max(1, osuGame.Beatmap.Value.Track.Length), 1);
+            LoadBeatmap(osuGame.Beatmap);
+        }
+
+        protected void Add(Drawable visualisation) => timeline.Add(visualisation);
+
+        protected abstract void LoadBeatmap(WorkingBeatmap beatmap);
+    }
+}
diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs
new file mode 100644
index 0000000000..9718e9df5f
--- /dev/null
+++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs
@@ -0,0 +1,25 @@
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+
+namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations
+{
+    /// <summary>
+    /// Represents a spanning point on a <see cref="Timeline"/>.
+    /// </summary>
+    internal class DurationVisualisation : Container
+    {
+        protected DurationVisualisation(double startTime, double endTime)
+        {
+            Masking = true;
+            CornerRadius = 5;
+
+            RelativePositionAxes = Axes.X;
+            RelativeSizeAxes = Axes.Both;
+            X = (float)startTime;
+            Width = (float)(endTime - startTime);
+
+            AddInternal(new Box { RelativeSizeAxes = Axes.Both });
+        }
+    }
+}
diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs
new file mode 100644
index 0000000000..f0eb2ed499
--- /dev/null
+++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs
@@ -0,0 +1,24 @@
+using OpenTK;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Shapes;
+
+namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations
+{
+    /// <summary>
+    /// Represents a singular point on a <see cref="Timeline"/>.
+    /// </summary>
+    internal class PointVisualisation : Box
+    {
+        protected PointVisualisation(double startTime)
+        {
+            Origin = Anchor.TopCentre;
+
+            RelativeSizeAxes = Axes.Y;
+            Width = 1;
+            EdgeSmoothness = new Vector2(1, 0);
+
+            RelativePositionAxes = Axes.X;
+            X = (float)startTime;
+        }
+    }
+}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index e43f6cfd8c..33eaff8ff5 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -606,6 +606,12 @@
     <Compile Include="Screens\Direct\OnlineListing.cs" />
     <Compile Include="Screens\Edit\Editor.cs" />
     <Compile Include="Screens\Edit\Components\SummaryTimeline.cs" />
+    <Compile Include="Screens\Edit\Components\Timelines\Summary\Parts\BreakPart.cs" />
+    <Compile Include="Screens\Edit\Components\Timelines\Summary\Parts\BookmarkPart.cs" />
+    <Compile Include="Screens\Edit\Components\Timelines\Summary\Parts\ControlPointPart.cs" />
+    <Compile Include="Screens\Edit\Components\Timelines\Summary\Parts\TimelinePart.cs" />
+    <Compile Include="Screens\Edit\Components\Timelines\Summary\Visualisations\DurationVisualisation.cs" />
+    <Compile Include="Screens\Edit\Components\Timelines\Summary\Visualisations\PointVisualisation.cs" />
     <Compile Include="Screens\Edit\Menus\EditorMenuBar.cs" />
     <Compile Include="Screens\Edit\Menus\EditorMenuBarItem.cs" />
     <Compile Include="Screens\Edit\Menus\EditorMenuItem.cs" />