From a504c73f33fd340f35a018448fc657fb916d3612 Mon Sep 17 00:00:00 2001 From: Damnae Date: Thu, 9 Feb 2017 15:09:48 +0100 Subject: [PATCH 01/27] Load beatmap data from an optional osb file. --- .../Beatmaps/IO/LegacyFilesystemReader.cs | 7 ++++++ osu.Game/Beatmaps/Formats/BeatmapDecoder.cs | 25 ++++++++++++++++++- .../Formats/ConstructableBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 16 +----------- osu.Game/Beatmaps/IO/ArchiveReader.cs | 4 +++ osu.Game/Beatmaps/IO/OszArchiveReader.cs | 10 +++++++- osu.Game/Beatmaps/WorkingBeatmap.cs | 19 +++++++++++--- osu.Game/Database/BeatmapDatabase.cs | 5 ++-- osu.Game/Database/BeatmapSetInfo.cs | 2 ++ osu.Game/Screens/Play/Player.cs | 2 +- 10 files changed, 68 insertions(+), 24 deletions(-) diff --git a/osu.Desktop/Beatmaps/IO/LegacyFilesystemReader.cs b/osu.Desktop/Beatmaps/IO/LegacyFilesystemReader.cs index 9b699a3d76..420141e9a1 100644 --- a/osu.Desktop/Beatmaps/IO/LegacyFilesystemReader.cs +++ b/osu.Desktop/Beatmaps/IO/LegacyFilesystemReader.cs @@ -21,6 +21,7 @@ namespace osu.Desktop.Beatmaps.IO private string basePath { get; set; } private string[] beatmaps { get; set; } + private string storyboard { get; set; } private Beatmap firstMap { get; set; } public LegacyFilesystemReader(string path) @@ -29,6 +30,7 @@ namespace osu.Desktop.Beatmaps.IO beatmaps = Directory.GetFiles(basePath, @"*.osu").Select(f => Path.GetFileName(f)).ToArray(); if (beatmaps.Length == 0) throw new FileNotFoundException(@"This directory contains no beatmaps"); + storyboard = Directory.GetFiles(basePath, @"*.osb").Select(f => Path.GetFileName(f)).FirstOrDefault(); using (var stream = new StreamReader(GetStream(beatmaps[0]))) { var decoder = BeatmapDecoder.GetDecoder(stream); @@ -41,6 +43,11 @@ namespace osu.Desktop.Beatmaps.IO return beatmaps; } + public override string ReadStoryboard() + { + return storyboard; + } + public override Stream GetStream(string name) { return File.OpenRead(Path.Combine(basePath, name)); diff --git a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs index ba99b206b5..4846cf376d 100644 --- a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs @@ -7,6 +7,8 @@ using System.IO; using osu.Game.Modes.Objects; using OpenTK.Graphics; using osu.Game.Graphics; +using osu.Game.Beatmaps.Timing; +using osu.Game.Database; namespace osu.Game.Beatmaps.Formats { @@ -34,6 +36,11 @@ namespace osu.Game.Beatmaps.Formats return b; } + public virtual void Decode(TextReader stream, Beatmap beatmap) + { + ParseFile(stream, beatmap); + } + public virtual Beatmap Process(Beatmap beatmap) { ApplyColours(beatmap); @@ -41,7 +48,23 @@ namespace osu.Game.Beatmaps.Formats return beatmap; } - protected abstract Beatmap ParseFile(TextReader stream); + protected virtual Beatmap ParseFile(TextReader stream) + { + var beatmap = new Beatmap + { + HitObjects = new List(), + ControlPoints = new List(), + ComboColors = new List(), + BeatmapInfo = new BeatmapInfo + { + Metadata = new BeatmapMetadata(), + BaseDifficulty = new BaseDifficulty(), + }, + }; + ParseFile(stream, beatmap); + return beatmap; + } + protected abstract void ParseFile(TextReader stream, Beatmap beatmap); public virtual void ApplyColours(Beatmap b) { diff --git a/osu.Game/Beatmaps/Formats/ConstructableBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/ConstructableBeatmapDecoder.cs index 6f81cae00f..f80c673e89 100644 --- a/osu.Game/Beatmaps/Formats/ConstructableBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/ConstructableBeatmapDecoder.cs @@ -12,7 +12,7 @@ namespace osu.Game.Beatmaps.Formats { public class ConstructableBeatmapDecoder : BeatmapDecoder { - protected override Beatmap ParseFile(TextReader stream) + protected override void ParseFile(TextReader stream, Beatmap beatmap) { throw new NotImplementedException(); } diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 29bb7ca32b..c32c3fe2f1 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -233,20 +233,8 @@ namespace osu.Game.Beatmaps.Formats }); } - protected override Beatmap ParseFile(TextReader stream) + protected override void ParseFile(TextReader stream, Beatmap beatmap) { - var beatmap = new Beatmap - { - HitObjects = new List(), - ControlPoints = new List(), - ComboColors = new List(), - BeatmapInfo = new BeatmapInfo - { - Metadata = new BeatmapMetadata(), - BaseDifficulty = new BaseDifficulty(), - }, - }; - HitObjectParser parser = null; var section = Section.None; @@ -309,8 +297,6 @@ namespace osu.Game.Beatmaps.Formats break; } } - - return beatmap; } } } diff --git a/osu.Game/Beatmaps/IO/ArchiveReader.cs b/osu.Game/Beatmaps/IO/ArchiveReader.cs index 8ae495a1fe..a944e7589a 100644 --- a/osu.Game/Beatmaps/IO/ArchiveReader.cs +++ b/osu.Game/Beatmaps/IO/ArchiveReader.cs @@ -44,6 +44,10 @@ namespace osu.Game.Beatmaps.IO /// public abstract string[] ReadBeatmaps(); /// + /// Gets the storyboard file name. + /// + public abstract string ReadStoryboard(); + /// /// Opens a stream for reading a specific file from this archive. /// public abstract Stream GetStream(string name); diff --git a/osu.Game/Beatmaps/IO/OszArchiveReader.cs b/osu.Game/Beatmaps/IO/OszArchiveReader.cs index 4b35805373..f9b7fb2cf8 100644 --- a/osu.Game/Beatmaps/IO/OszArchiveReader.cs +++ b/osu.Game/Beatmaps/IO/OszArchiveReader.cs @@ -26,8 +26,9 @@ namespace osu.Game.Beatmaps.IO private Stream archiveStream; private ZipFile archive; private string[] beatmaps; + private string storyboard; private Beatmap firstMap; - + public OszArchiveReader(Stream archiveStream) { this.archiveStream = archiveStream; @@ -36,6 +37,8 @@ namespace osu.Game.Beatmaps.IO .Select(e => e.FileName).ToArray(); if (beatmaps.Length == 0) throw new FileNotFoundException(@"This directory contains no beatmaps"); + storyboard = archive.Entries.Where(e => e.FileName.EndsWith(@".osb")) + .Select(e => e.FileName).FirstOrDefault(); using (var stream = new StreamReader(GetStream(beatmaps[0]))) { var decoder = BeatmapDecoder.GetDecoder(stream); @@ -48,6 +51,11 @@ namespace osu.Game.Beatmaps.IO return beatmaps; } + public override string ReadStoryboard() + { + return storyboard; + } + public override Stream GetStream(string name) { ZipEntry entry = archive.Entries.SingleOrDefault(e => e.FileName == name); diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 019674c3ad..674ab76802 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -18,6 +18,8 @@ namespace osu.Game.Beatmaps public readonly BeatmapSetInfo BeatmapSetInfo; private readonly BeatmapDatabase database; + public readonly bool WithStoryboard; + private ArchiveReader getReader() => database?.GetReader(BeatmapSetInfo); private Texture background; @@ -58,8 +60,18 @@ namespace osu.Game.Beatmaps try { using (var reader = getReader()) - using (var stream = new StreamReader(reader.GetStream(BeatmapInfo.Path))) - beatmap = BeatmapDecoder.GetDecoder(stream)?.Decode(stream); + { + BeatmapDecoder decoder; + using (var stream = new StreamReader(reader.GetStream(BeatmapInfo.Path))) + { + decoder = BeatmapDecoder.GetDecoder(stream); + beatmap = decoder?.Decode(stream); + } + + if (WithStoryboard && beatmap != null && BeatmapSetInfo.StoryboardFile != null) + using (var stream = new StreamReader(reader.GetStream(BeatmapSetInfo.StoryboardFile))) + decoder?.Decode(stream, beatmap); + } } catch { } @@ -103,11 +115,12 @@ namespace osu.Game.Beatmaps this.beatmap = beatmap; } - public WorkingBeatmap(BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, BeatmapDatabase database) + public WorkingBeatmap(BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, BeatmapDatabase database, bool withStoryboard = false) { BeatmapInfo = beatmapInfo; BeatmapSetInfo = beatmapSetInfo; this.database = database; + this.WithStoryboard = withStoryboard; } private bool isDisposed; diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index dff76479e8..1b678b2148 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -137,6 +137,7 @@ namespace osu.Game.Database beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } } + beatmapSet.StoryboardFile = reader.ReadStoryboard(); } Import(new[] { beatmapSet }); @@ -169,7 +170,7 @@ namespace osu.Game.Database return Query().FirstOrDefault(s => s.OnlineBeatmapSetID == id); } - public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo, WorkingBeatmap previous = null) + public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo, WorkingBeatmap previous = null, bool withStoryboard = false) { var beatmapSetInfo = Query().FirstOrDefault(s => s.ID == beatmapInfo.BeatmapSetInfoID); @@ -182,7 +183,7 @@ namespace osu.Game.Database if (beatmapInfo.Metadata == null) beatmapInfo.Metadata = beatmapSetInfo.Metadata; - var working = new WorkingBeatmap(beatmapInfo, beatmapSetInfo, this); + var working = new WorkingBeatmap(beatmapInfo, beatmapSetInfo, this, withStoryboard); previous?.TransferTo(working); diff --git a/osu.Game/Database/BeatmapSetInfo.cs b/osu.Game/Database/BeatmapSetInfo.cs index f556c3546a..a9c3f03a49 100644 --- a/osu.Game/Database/BeatmapSetInfo.cs +++ b/osu.Game/Database/BeatmapSetInfo.cs @@ -27,6 +27,8 @@ namespace osu.Game.Database public string Hash { get; set; } public string Path { get; set; } + + public string StoryboardFile { get; set; } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a9584a1f10..36ea7c5b49 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -74,7 +74,7 @@ namespace osu.Game.Screens.Play try { if (Beatmap == null) - Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo); + Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo, withStoryboard: true); } catch { From 77ee161be8afa156dc8c95d22ed3c0111cad94bf Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 10 Feb 2017 06:16:23 +0100 Subject: [PATCH 02/27] Add follow points. --- .../Objects/Drawables/FollowPoint.cs | 64 +++++++++++++++++ osu.Game.Modes.Osu/UI/OsuPlayfield.cs | 71 ++++++++++++++++++- osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj | 1 + osu.Game/Modes/UI/HitRenderer.cs | 1 + osu.Game/Modes/UI/Playfield.cs | 6 +- 5 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs diff --git a/osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs b/osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs new file mode 100644 index 0000000000..22ffead4d9 --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs @@ -0,0 +1,64 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Transformations; + +namespace osu.Game.Modes.Osu.Objects.Drawables +{ + public class FollowPoint : Container + { + private Sprite followPoint; + + public double StartTime; + public double EndTime; + public Vector2 EndPosition; + + public FollowPoint() + { + Origin = Anchor.Centre; + Alpha = 0; + + Children = new Drawable[] + { + followPoint = new Sprite + { + Size = new Vector2(12f), + Origin = Anchor.Centre, + BlendingMode = BlendingMode.Additive, + Alpha = 0.5f + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + DelayReset(); + + Delay(StartTime); + FadeIn(DrawableOsuHitObject.TIME_FADEIN); + ScaleTo(1.5f); + ScaleTo(1, DrawableOsuHitObject.TIME_FADEIN, EasingTypes.Out); + MoveTo(EndPosition, DrawableOsuHitObject.TIME_FADEIN, EasingTypes.Out); + + Delay(EndTime - StartTime); + FadeOut(DrawableOsuHitObject.TIME_FADEIN); + + Delay(DrawableOsuHitObject.TIME_FADEIN); + Expire(true); + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + followPoint.Texture = textures.Get(@"Play/osu/ring-glow"); + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs index 49c6869189..1be73a0452 100644 --- a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs @@ -1,13 +1,16 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects; using osu.Game.Modes.Osu.Objects.Drawables; using osu.Game.Modes.UI; -using OpenTK; +using System; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Modes.Osu.UI { @@ -15,6 +18,7 @@ namespace osu.Game.Modes.Osu.UI { private Container approachCircles; private Container judgementLayer; + private Container followPointsLayer; public override Vector2 Size { @@ -36,11 +40,16 @@ namespace osu.Game.Modes.Osu.UI Add(new Drawable[] { - judgementLayer = new Container + followPointsLayer = new Container { RelativeSizeAxes = Axes.Both, Depth = 1, }, + judgementLayer = new Container + { + RelativeSizeAxes = Axes.Both, + Depth = 0, + }, approachCircles = new Container { RelativeSizeAxes = Axes.Both, @@ -63,11 +72,69 @@ namespace osu.Game.Modes.Osu.UI base.Add(h); } + public override void PostProcess() + { + AddFollowPoints(); + } + private void judgement(DrawableHitObject h, JudgementInfo j) { HitExplosion explosion = new HitExplosion((OsuJudgementInfo)j, (OsuHitObject)h.HitObject); judgementLayer.Add(explosion); } + + public void AddFollowPoints(int startIndex = 0, int endIndex = -1) + { + var followLineDistance = 32; + var followLinePreEmpt = 800; + + var hitObjects = new List(HitObjects.Children + .Select(d => (OsuHitObject)d.HitObject) + .OrderBy(h => h.StartTime)); + + if (endIndex < 0) + endIndex = hitObjects.Count - 1; + + for (int i = startIndex + 1; i <= endIndex; i++) + { + var prevHitObject = hitObjects[i - 1]; + var currHitObject = hitObjects[i]; + + if (prevHitObject.StartTime > currHitObject.StartTime) + throw new Exception(); + + if (!currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner)) + { + Vector2 startPosition = prevHitObject.EndPosition; + Vector2 endPosition = currHitObject.Position; + double startTime = prevHitObject.EndTime; + double endTime = currHitObject.StartTime; + + Vector2 distanceVector = endPosition - startPosition; + int distance = (int)distanceVector.Length; + float rotation = (float)Math.Atan2(distanceVector.Y, distanceVector.X); + double duration = endTime - startTime; + + for (int d = (int)(followLineDistance * 1.5); d < distance - followLineDistance; d += followLineDistance) + { + float fraction = ((float)d / distance); + Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; + Vector2 pointEndPosition = startPosition + fraction * distanceVector; + double fadeOutTime = startTime + fraction * duration; + double fadeInTime = fadeOutTime - followLinePreEmpt; + + followPointsLayer.Add(new FollowPoint() + { + StartTime = fadeInTime, + EndTime = fadeOutTime, + Position = pointStartPosition, + EndPosition = pointEndPosition, + Rotation = rotation, + }); + } + } + } + } } } \ No newline at end of file diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj index a9a346f563..88d25cb8f4 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj @@ -47,6 +47,7 @@ + diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index aa2af83cb4..14d9599be6 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -83,6 +83,7 @@ namespace osu.Game.Modes.UI Playfield.Add(drawableObject); } + Playfield.PostProcess(); } private void onJudgement(DrawableHitObject o, JudgementInfo j) => TriggerOnJudgement(j); diff --git a/osu.Game/Modes/UI/Playfield.cs b/osu.Game/Modes/UI/Playfield.cs index 748c71a8b3..91eddce73c 100644 --- a/osu.Game/Modes/UI/Playfield.cs +++ b/osu.Game/Modes/UI/Playfield.cs @@ -1,10 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; -using OpenTK; namespace osu.Game.Modes.UI { @@ -32,6 +32,10 @@ namespace osu.Game.Modes.UI }); } + public virtual void PostProcess() + { + } + public class ScaledContainer : Container { protected override Vector2 DrawScale => new Vector2(DrawSize.X / 512); From 4e6b6ab794c54d5e3f50382c60f5ddeeb0b76c00 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 10 Feb 2017 08:10:24 +0100 Subject: [PATCH 03/27] Abstract follow points into a separate class. --- .../{ => Connections}/FollowPoint.cs | 2 +- .../Connections/FollowPointConnection.cs | 65 +++++++++++++++++++ .../Connections/HitObjectConnection.cs | 14 ++++ osu.Game.Modes.Osu/UI/OsuPlayfield.cs | 63 ++---------------- osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj | 4 +- 5 files changed, 87 insertions(+), 61 deletions(-) rename osu.Game.Modes.Osu/Objects/Drawables/{ => Connections}/FollowPoint.cs (93%) create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs diff --git a/osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs similarity index 93% rename from osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs rename to osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs index 22ffead4d9..b0b63d17b9 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/FollowPoint.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Transformations; -namespace osu.Game.Modes.Osu.Objects.Drawables +namespace osu.Game.Modes.Osu.Objects.Drawables.Connections { public class FollowPoint : Container { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs new file mode 100644 index 0000000000..78c875d874 --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -0,0 +1,65 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Osu.Objects.Drawables.Connections; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Modes.Osu.Objects.Drawables +{ + public class FollowPointConnection : HitObjectConnection + { + public int PointDistance = 32; + public int PreEmpt = 800; + + public override void AddConnections(IEnumerable drawableHitObjects, int startIndex = 0, int endIndex = -1) + { + var hitObjects = new List(drawableHitObjects + .Select(d => (OsuHitObject)d.HitObject) + .OrderBy(h => h.StartTime)); + + if (endIndex < 0) + endIndex = hitObjects.Count - 1; + + for (int i = startIndex + 1; i <= endIndex; i++) + { + var prevHitObject = hitObjects[i - 1]; + var currHitObject = hitObjects[i]; + + if (!currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner)) + { + Vector2 startPosition = prevHitObject.EndPosition; + Vector2 endPosition = currHitObject.Position; + double startTime = prevHitObject.EndTime; + double endTime = currHitObject.StartTime; + + Vector2 distanceVector = endPosition - startPosition; + int distance = (int)distanceVector.Length; + float rotation = (float)Math.Atan2(distanceVector.Y, distanceVector.X); + double duration = endTime - startTime; + + for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance) + { + float fraction = ((float)d / distance); + Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; + Vector2 pointEndPosition = startPosition + fraction * distanceVector; + double fadeOutTime = startTime + fraction * duration; + double fadeInTime = fadeOutTime - PreEmpt; + + Add(new FollowPoint() + { + StartTime = fadeInTime, + EndTime = fadeOutTime, + Position = pointStartPosition, + EndPosition = pointEndPosition, + Rotation = rotation, + }); + } + } + } + } + } +} diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs new file mode 100644 index 0000000000..d8c91f23df --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Containers; +using osu.Game.Modes.Objects.Drawables; +using System.Collections.Generic; + +namespace osu.Game.Modes.Osu.Objects.Drawables.Connections +{ + public abstract class HitObjectConnection : Container + { + public abstract void AddConnections(IEnumerable drawableHitObjects, int startIndex = 0, int endIndex = -1); + } +} diff --git a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs index 1be73a0452..ef7b36b0bd 100644 --- a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs @@ -7,10 +7,8 @@ using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects; using osu.Game.Modes.Osu.Objects.Drawables; +using osu.Game.Modes.Osu.Objects.Drawables.Connections; using osu.Game.Modes.UI; -using System; -using System.Collections.Generic; -using System.Linq; namespace osu.Game.Modes.Osu.UI { @@ -18,7 +16,7 @@ namespace osu.Game.Modes.Osu.UI { private Container approachCircles; private Container judgementLayer; - private Container followPointsLayer; + private HitObjectConnection hitObjectConnection; public override Vector2 Size { @@ -40,7 +38,7 @@ namespace osu.Game.Modes.Osu.UI Add(new Drawable[] { - followPointsLayer = new Container + hitObjectConnection = new FollowPointConnection { RelativeSizeAxes = Axes.Both, Depth = 1, @@ -74,7 +72,7 @@ namespace osu.Game.Modes.Osu.UI public override void PostProcess() { - AddFollowPoints(); + hitObjectConnection.AddConnections(HitObjects.Children); } private void judgement(DrawableHitObject h, JudgementInfo j) @@ -83,58 +81,5 @@ namespace osu.Game.Modes.Osu.UI judgementLayer.Add(explosion); } - - public void AddFollowPoints(int startIndex = 0, int endIndex = -1) - { - var followLineDistance = 32; - var followLinePreEmpt = 800; - - var hitObjects = new List(HitObjects.Children - .Select(d => (OsuHitObject)d.HitObject) - .OrderBy(h => h.StartTime)); - - if (endIndex < 0) - endIndex = hitObjects.Count - 1; - - for (int i = startIndex + 1; i <= endIndex; i++) - { - var prevHitObject = hitObjects[i - 1]; - var currHitObject = hitObjects[i]; - - if (prevHitObject.StartTime > currHitObject.StartTime) - throw new Exception(); - - if (!currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner)) - { - Vector2 startPosition = prevHitObject.EndPosition; - Vector2 endPosition = currHitObject.Position; - double startTime = prevHitObject.EndTime; - double endTime = currHitObject.StartTime; - - Vector2 distanceVector = endPosition - startPosition; - int distance = (int)distanceVector.Length; - float rotation = (float)Math.Atan2(distanceVector.Y, distanceVector.X); - double duration = endTime - startTime; - - for (int d = (int)(followLineDistance * 1.5); d < distance - followLineDistance; d += followLineDistance) - { - float fraction = ((float)d / distance); - Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; - Vector2 pointEndPosition = startPosition + fraction * distanceVector; - double fadeOutTime = startTime + fraction * duration; - double fadeInTime = fadeOutTime - followLinePreEmpt; - - followPointsLayer.Add(new FollowPoint() - { - StartTime = fadeInTime, - EndTime = fadeOutTime, - Position = pointStartPosition, - EndPosition = pointEndPosition, - Rotation = rotation, - }); - } - } - } - } } } \ No newline at end of file diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj index 88d25cb8f4..567eec593c 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj @@ -44,10 +44,12 @@ + + - + From 6f37c028681e95560e7830076eb548601995f2c3 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 10 Feb 2017 10:02:37 +0100 Subject: [PATCH 04/27] Fix followpoints needing a DelayReset. --- .../Objects/Drawables/Connections/FollowPoint.cs | 2 -- osu.Game/Screens/Play/Player.cs | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs index b0b63d17b9..72a5358efb 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -40,8 +40,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Connections { base.LoadComplete(); - DelayReset(); - Delay(StartTime); FadeIn(DrawableOsuHitObject.TIME_FADEIN); ScaleTo(1.5f); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a9584a1f10..a1effa242a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -237,11 +237,10 @@ namespace osu.Game.Screens.Play { base.LoadComplete(); - Delay(250, true); + Content.Delay(250); Content.FadeIn(250); - Delay(500, true); - + Delay(500); Schedule(() => { sourceClock.Start(); From ec64455573557c1da2e61b019a034c933d8a7f8e Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 10 Feb 2017 10:24:31 +0100 Subject: [PATCH 05/27] Add xml-doc. --- .../Objects/Drawables/Connections/FollowPointConnection.cs | 7 +++++++ .../Objects/Drawables/Connections/HitObjectConnection.cs | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 78c875d874..60ae997a77 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -12,7 +12,14 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { public class FollowPointConnection : HitObjectConnection { + /// + /// Determines how much space there is between points. + /// public int PointDistance = 32; + + /// + /// Follow points to the next hitobject start appearing for this many milliseconds before an hitobject's end time. + /// public int PreEmpt = 800; public override void AddConnections(IEnumerable drawableHitObjects, int startIndex = 0, int endIndex = -1) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs index d8c91f23df..3ef4b4aa29 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs @@ -9,6 +9,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Connections { public abstract class HitObjectConnection : Container { + /// + /// Create drawables inside this container, connecting hitobjects visually, for example with follow points. + /// + /// The drawables hit objects to create connections for + /// Start index into the drawableHitObjects enumeration. + /// End index into the drawableHitObjects enumeration. Use -1 to draw connections until the end. public abstract void AddConnections(IEnumerable drawableHitObjects, int startIndex = 0, int endIndex = -1); } } From 2d155f6a5c0c86f6eb929b750a1c07902a029bb9 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 10 Feb 2017 10:48:25 +0100 Subject: [PATCH 06/27] Bring back the delay to what it was before. --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a1effa242a..6eda0ec9ca 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -240,7 +240,7 @@ namespace osu.Game.Screens.Play Content.Delay(250); Content.FadeIn(250); - Delay(500); + Delay(750); Schedule(() => { sourceClock.Start(); From 4162ef72d44ea4c9bebec180db0b67546b520652 Mon Sep 17 00:00:00 2001 From: Damnae Date: Sun, 12 Feb 2017 06:02:45 +0100 Subject: [PATCH 07/27] Remove start/end index. --- .../Objects/Drawables/Connections/FollowPointConnection.cs | 7 ++----- .../Objects/Drawables/Connections/HitObjectConnection.cs | 4 +--- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 60ae997a77..3af77e41f8 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -22,16 +22,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables /// public int PreEmpt = 800; - public override void AddConnections(IEnumerable drawableHitObjects, int startIndex = 0, int endIndex = -1) + public override void AddConnections(IEnumerable drawableHitObjects) { var hitObjects = new List(drawableHitObjects .Select(d => (OsuHitObject)d.HitObject) .OrderBy(h => h.StartTime)); - if (endIndex < 0) - endIndex = hitObjects.Count - 1; - - for (int i = startIndex + 1; i <= endIndex; i++) + for (int i = 1; i <= hitObjects.Count - 1; i++) { var prevHitObject = hitObjects[i - 1]; var currHitObject = hitObjects[i]; diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs index 3ef4b4aa29..e2131504cf 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs @@ -13,8 +13,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Connections /// Create drawables inside this container, connecting hitobjects visually, for example with follow points. /// /// The drawables hit objects to create connections for - /// Start index into the drawableHitObjects enumeration. - /// End index into the drawableHitObjects enumeration. Use -1 to draw connections until the end. - public abstract void AddConnections(IEnumerable drawableHitObjects, int startIndex = 0, int endIndex = -1); + public abstract void AddConnections(IEnumerable drawableHitObjects); } } From d7be9539d1a18cec2ec45b10871e4853461cb80c Mon Sep 17 00:00:00 2001 From: Damnae Date: Sun, 12 Feb 2017 07:29:36 +0100 Subject: [PATCH 08/27] Create connections from HitObjects instead of DrawableHitObjects. --- ...ectConnection.cs => ConnectionRenderer.cs} | 11 ++++++----- ...ntConnection.cs => FollowPointRenderer.cs} | 19 ++++++------------- osu.Game.Modes.Osu/UI/OsuPlayfield.cs | 13 ++++++++----- osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj | 4 ++-- 4 files changed, 22 insertions(+), 25 deletions(-) rename osu.Game.Modes.Osu/Objects/Drawables/Connections/{HitObjectConnection.cs => ConnectionRenderer.cs} (52%) rename osu.Game.Modes.Osu/Objects/Drawables/Connections/{FollowPointConnection.cs => FollowPointRenderer.cs} (75%) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs similarity index 52% rename from osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs rename to osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs index e2131504cf..d35a731feb 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/HitObjectConnection.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs @@ -2,17 +2,18 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; -using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Objects; using System.Collections.Generic; namespace osu.Game.Modes.Osu.Objects.Drawables.Connections { - public abstract class HitObjectConnection : Container + public abstract class ConnectionRenderer : Container + where T : HitObject { /// - /// Create drawables inside this container, connecting hitobjects visually, for example with follow points. + /// Create drawables inside this container, connecting hit objects visually, for example with follow points. /// - /// The drawables hit objects to create connections for - public abstract void AddConnections(IEnumerable drawableHitObjects); + /// Hit objects to create connections for + public abstract void AddConnections(IEnumerable hitObjects); } } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs similarity index 75% rename from osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs rename to osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 3af77e41f8..469ce390d0 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -2,15 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects.Drawables.Connections; using System; using System.Collections.Generic; -using System.Linq; namespace osu.Game.Modes.Osu.Objects.Drawables { - public class FollowPointConnection : HitObjectConnection + public class FollowPointRenderer : ConnectionRenderer { /// /// Determines how much space there is between points. @@ -22,18 +20,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables /// public int PreEmpt = 800; - public override void AddConnections(IEnumerable drawableHitObjects) + public override void AddConnections(IEnumerable hitObjects) { - var hitObjects = new List(drawableHitObjects - .Select(d => (OsuHitObject)d.HitObject) - .OrderBy(h => h.StartTime)); - - for (int i = 1; i <= hitObjects.Count - 1; i++) + OsuHitObject prevHitObject = null; + foreach (var currHitObject in hitObjects) { - var prevHitObject = hitObjects[i - 1]; - var currHitObject = hitObjects[i]; - - if (!currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner)) + if (prevHitObject != null && !currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner)) { Vector2 startPosition = prevHitObject.EndPosition; Vector2 endPosition = currHitObject.Position; @@ -63,6 +55,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables }); } } + prevHitObject = currHitObject; } } } diff --git a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs index ef7b36b0bd..f2fafc8883 100644 --- a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs @@ -9,6 +9,7 @@ using osu.Game.Modes.Osu.Objects; using osu.Game.Modes.Osu.Objects.Drawables; using osu.Game.Modes.Osu.Objects.Drawables.Connections; using osu.Game.Modes.UI; +using System.Linq; namespace osu.Game.Modes.Osu.UI { @@ -16,7 +17,7 @@ namespace osu.Game.Modes.Osu.UI { private Container approachCircles; private Container judgementLayer; - private HitObjectConnection hitObjectConnection; + private ConnectionRenderer connectionLayer; public override Vector2 Size { @@ -38,15 +39,15 @@ namespace osu.Game.Modes.Osu.UI Add(new Drawable[] { - hitObjectConnection = new FollowPointConnection + connectionLayer = new FollowPointRenderer { RelativeSizeAxes = Axes.Both, - Depth = 1, + Depth = 2, }, judgementLayer = new Container { RelativeSizeAxes = Axes.Both, - Depth = 0, + Depth = 1, }, approachCircles = new Container { @@ -72,7 +73,9 @@ namespace osu.Game.Modes.Osu.UI public override void PostProcess() { - hitObjectConnection.AddConnections(HitObjects.Children); + connectionLayer.AddConnections(HitObjects.Children + .Select(d => (OsuHitObject)d.HitObject) + .OrderBy(h => h.StartTime)); } private void judgement(DrawableHitObject h, JudgementInfo j) diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj index 567eec593c..d8c381a648 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj @@ -44,8 +44,8 @@ - - + + From de2791e179322aa97aad4f8f9da193add759b5ff Mon Sep 17 00:00:00 2001 From: Damnae Date: Sun, 12 Feb 2017 08:19:52 +0100 Subject: [PATCH 09/27] Better looking follow points. --- .../Drawables/Connections/FollowPoint.cs | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs index 72a5358efb..bc24186e14 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -2,36 +2,47 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Framework.Allocation; +using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Transformations; +using osu.Game.Graphics; namespace osu.Game.Modes.Osu.Objects.Drawables.Connections { public class FollowPoint : Container { - private Sprite followPoint; - public double StartTime; public double EndTime; public Vector2 EndPosition; + const float width = 8; + public FollowPoint() { Origin = Anchor.Centre; Alpha = 0; + Masking = true; + AutoSizeAxes = Axes.Both; + CornerRadius = width / 2; + EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Glow, + Colour = Color4.White.Opacity(0.2f), + Radius = 4, + }; + Children = new Drawable[] { - followPoint = new Sprite + new Box { - Size = new Vector2(12f), - Origin = Anchor.Centre, + Size = new Vector2(width), BlendingMode = BlendingMode.Additive, - Alpha = 0.5f + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Alpha = 0.5f, }, }; } @@ -52,11 +63,5 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Connections Delay(DrawableOsuHitObject.TIME_FADEIN); Expire(true); } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - followPoint.Texture = textures.Get(@"Play/osu/ring-glow"); - } } } \ No newline at end of file From daa14bfec8be065464c8f22ecdf7e845b7282f53 Mon Sep 17 00:00:00 2001 From: Damnae Date: Sun, 12 Feb 2017 08:31:43 +0100 Subject: [PATCH 10/27] Replace AddConnections by a HitObjects property. --- .../Connections/ConnectionRenderer.cs | 8 ++-- .../Connections/FollowPointRenderer.cs | 43 +++++++++++++++++-- osu.Game.Modes.Osu/UI/OsuPlayfield.cs | 4 +- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs index d35a731feb..a680c847ac 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs @@ -7,13 +7,15 @@ using System.Collections.Generic; namespace osu.Game.Modes.Osu.Objects.Drawables.Connections { + /// + /// Connects hit objects visually, for example with follow points. + /// public abstract class ConnectionRenderer : Container where T : HitObject { /// - /// Create drawables inside this container, connecting hit objects visually, for example with follow points. + /// Hit objects to create connections for /// - /// Hit objects to create connections for - public abstract void AddConnections(IEnumerable hitObjects); + public abstract IEnumerable HitObjects { get; set; } } } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 469ce390d0..b57f0881bc 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -10,18 +10,53 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { public class FollowPointRenderer : ConnectionRenderer { + private int pointDistance = 32; /// /// Determines how much space there is between points. /// - public int PointDistance = 32; + public int PointDistance + { + get { return pointDistance; } + set + { + if (pointDistance == value) return; + pointDistance = value; + update(); + } + } + private int preEmpt = 800; /// /// Follow points to the next hitobject start appearing for this many milliseconds before an hitobject's end time. /// - public int PreEmpt = 800; - - public override void AddConnections(IEnumerable hitObjects) + public int PreEmpt { + get { return preEmpt; } + set + { + if (preEmpt == value) return; + preEmpt = value; + update(); + } + } + + private IEnumerable hitObjects; + public override IEnumerable HitObjects + { + get { return hitObjects; } + set + { + hitObjects = value; + update(); + } + } + + private void update() + { + Clear(); + if (hitObjects == null) + return; + OsuHitObject prevHitObject = null; foreach (var currHitObject in hitObjects) { diff --git a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs index f2fafc8883..b6daffbb8b 100644 --- a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs @@ -73,9 +73,9 @@ namespace osu.Game.Modes.Osu.UI public override void PostProcess() { - connectionLayer.AddConnections(HitObjects.Children + connectionLayer.HitObjects = HitObjects.Children .Select(d => (OsuHitObject)d.HitObject) - .OrderBy(h => h.StartTime)); + .OrderBy(h => h.StartTime); } private void judgement(DrawableHitObject h, JudgementInfo j) From a073b1db0d89dd0d2a2518f731b6677f82aa60a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Feb 2017 01:02:44 +0900 Subject: [PATCH 11/27] very simple build automation. --- .gitignore | 3 +- osu.Desktop.Deploy/App.config | 6 + osu.Desktop.Deploy/Program.cs | 124 ++++++++++++++++++ osu.Desktop.Deploy/Properties/AssemblyInfo.cs | 36 +++++ osu.Desktop.Deploy/osu.Desktop.Deploy.csproj | 108 +++++++++++++++ osu.Desktop.Deploy/packages.config | 8 ++ osu.Desktop/Properties/AssemblyInfo.cs | 4 +- osu.Desktop/osu.nuspec | 25 ++++ osu.sln | 34 +++++ 9 files changed, 345 insertions(+), 3 deletions(-) create mode 100644 osu.Desktop.Deploy/App.config create mode 100644 osu.Desktop.Deploy/Program.cs create mode 100644 osu.Desktop.Deploy/Properties/AssemblyInfo.cs create mode 100644 osu.Desktop.Deploy/osu.Desktop.Deploy.csproj create mode 100644 osu.Desktop.Deploy/packages.config create mode 100644 osu.Desktop/osu.nuspec diff --git a/.gitignore b/.gitignore index aa8061f0c9..7097de6024 100644 --- a/.gitignore +++ b/.gitignore @@ -255,4 +255,5 @@ paket-files/ # Python Tools for Visual Studio (PTVS) __pycache__/ -*.pyc \ No newline at end of file +*.pyc +Staging/ diff --git a/osu.Desktop.Deploy/App.config b/osu.Desktop.Deploy/App.config new file mode 100644 index 0000000000..d740e88600 --- /dev/null +++ b/osu.Desktop.Deploy/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/osu.Desktop.Deploy/Program.cs b/osu.Desktop.Deploy/Program.cs new file mode 100644 index 0000000000..902014ab65 --- /dev/null +++ b/osu.Desktop.Deploy/Program.cs @@ -0,0 +1,124 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; + +namespace osu.Desktop.Deploy +{ + class Program + { + static string NUGET_PATH = @"packages\NuGet.CommandLine.3.5.0\tools\NuGet.exe"; + static string SQUIRREL_PATH = @"packages\squirrel.windows.1.5.2\tools\Squirrel.exe"; + static string MSBUILD_PATH = @"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"; + + static string STAGING_FOLDER = "Staging"; + static string PROJECT_NAME = "osu.Desktop"; + + static string CODE_SIGNING_CMD => $"/a /f {CODE_SIGNING_CERT} /p {codeSigningPassword} /t http://timestamp.comodoca.com/authenticode"; + static string IconPath => Path.Combine(SolutionPath, PROJECT_NAME, "lazer.ico"); + + static internal string HomeDir { get { return Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); } } + static internal string CODE_SIGNING_CERT => Path.Combine(HomeDir, "deanherbert.pfx"); + + static string SolutionPath => Environment.CurrentDirectory; + static string StagingPath => Path.Combine(SolutionPath, STAGING_FOLDER); + + static string codeSigningPassword; + + static void Main(string[] args) + { + FindSolutionPath(); + + if (Directory.Exists(STAGING_FOLDER)) + Directory.Delete(STAGING_FOLDER, true); + Directory.CreateDirectory(STAGING_FOLDER); + + string verBase = DateTime.Now.ToString("yyyy.Md."); + + int increment = 0; + + while (Directory.GetFiles("Releases", $"*{verBase}{increment}*").Count() > 0) + increment++; + + string ver = $"{verBase}{increment}"; + + Console.Write(ver); + + ver += Console.ReadLine(); + + Console.WriteLine("Enter code signing password:"); + + codeSigningPassword = Console.ReadLine(); + + Console.WriteLine("Restoring NuGet packages..."); + RunCommand(NUGET_PATH, "restore " + SolutionPath); + + Console.WriteLine("Running build process..."); + RunCommand(MSBUILD_PATH, $"/v:quiet /m /t:Client\\{PROJECT_NAME.Replace('.', '_')} /p:OutputPath={StagingPath};Configuration=Release osu.sln"); + + Console.WriteLine("Creating NuGet deployment package..."); + RunCommand(NUGET_PATH, $"pack osu.Desktop\\osu.nuspec -Version {ver} -Properties Configuration=Deploy -OutputDirectory {StagingPath} -BasePath {StagingPath}"); + + Console.WriteLine("Releasifying package..."); + RunCommand(SQUIRREL_PATH, $"--releasify {StagingPath}\\osulazer.{ver}.nupkg --setupIcon {IconPath} --icon {IconPath} -n \"{CODE_SIGNING_CMD}\" --no-msi"); + + File.Copy("Releases\\Setup.exe", "Releases\\install.exe", true); + File.Delete("Releases\\Setup.exe"); + + Console.WriteLine("Done!"); + + Console.ReadLine(); + } + + /// + /// Find the base path of the osu! solution (git checkout location) + /// + private static void FindSolutionPath() + { + string path = Path.GetDirectoryName(Environment.CommandLine.Replace("\"", "").Trim()); + + if (string.IsNullOrEmpty(path)) + path = Environment.CurrentDirectory; + + while (!File.Exists(path + "\\osu.sln")) + path = path.Remove(path.LastIndexOf('\\')); + path += "\\"; + + Environment.CurrentDirectory = path; + } + + private static bool RunCommand(string command, string args) + { + var psi = new ProcessStartInfo(command, args); + if (psi != null) + { + psi.WorkingDirectory = SolutionPath; + psi.CreateNoWindow = true; + psi.RedirectStandardOutput = true; + psi.UseShellExecute = false; + psi.WindowStyle = ProcessWindowStyle.Hidden; + Process p = Process.Start(psi); + string output = p.StandardOutput.ReadToEnd(); + if (p.ExitCode != 0) + { + Console.WriteLine(output); + Error($"Command {command} {args} failed!"); + return false; + } + + return true; + } + + return false; + } + + private static void Error(string p) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("ERROR: " + p); + + Console.ReadLine(); + Environment.Exit(-1); + } + } +} diff --git a/osu.Desktop.Deploy/Properties/AssemblyInfo.cs b/osu.Desktop.Deploy/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..c71d82df00 --- /dev/null +++ b/osu.Desktop.Deploy/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("osu.Desktop.Deploy")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("osu.Desktop.Deploy")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("baea2f74-0315-4667-84e0-acac0b4bf785")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj new file mode 100644 index 0000000000..3d4b86fc93 --- /dev/null +++ b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj @@ -0,0 +1,108 @@ + + + + + Debug + AnyCPU + {BAEA2F74-0315-4667-84E0-ACAC0B4BF785} + Exe + Properties + osu.Desktop.Deploy + osu.Desktop.Deploy + v4.5.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.dll + True + + + ..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.MsDelta.dll + True + + + ..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.PatchApi.dll + True + + + ..\packages\squirrel.windows.1.5.2\lib\Net45\ICSharpCode.SharpZipLib.dll + True + + + ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll + True + + + ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll + True + + + ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll + True + + + ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll + True + + + ..\packages\squirrel.windows.1.5.2\lib\Net45\NuGet.Squirrel.dll + True + + + ..\packages\Splat.1.6.2\lib\Net45\Splat.dll + True + + + ..\packages\squirrel.windows.1.5.2\lib\Net45\Squirrel.dll + True + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Desktop.Deploy/packages.config b/osu.Desktop.Deploy/packages.config new file mode 100644 index 0000000000..466190ccab --- /dev/null +++ b/osu.Desktop.Deploy/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/osu.Desktop/Properties/AssemblyInfo.cs b/osu.Desktop/Properties/AssemblyInfo.cs index 1f234d2993..825bf6c184 100644 --- a/osu.Desktop/Properties/AssemblyInfo.cs +++ b/osu.Desktop/Properties/AssemblyInfo.cs @@ -22,5 +22,5 @@ using System.Runtime.InteropServices; // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("55e28cb2-7b6c-4595-8dcc-9871d8aad7e9")] -[assembly: AssemblyVersion("0.0.5")] -[assembly: AssemblyFileVersion("0.0.5")] +[assembly: AssemblyVersion("2017.212.0")] +[assembly: AssemblyFileVersion("2017.212.0")] diff --git a/osu.Desktop/osu.nuspec b/osu.Desktop/osu.nuspec new file mode 100644 index 0000000000..93aaebfe6f --- /dev/null +++ b/osu.Desktop/osu.nuspec @@ -0,0 +1,25 @@ + + + + osulazer + 0.0.0 + osulazer + ppy Pty Ltd + Dean Herbert + https://osu.ppy.sh/ + https://puu.sh/tYyXZ/9a01a5d1b0.ico + false + click the circles. to the beat. + click the circles. + testing + Copyright ppy Pty Ltd 2007-2017 + en-AU + + + + + + + + + diff --git a/osu.sln b/osu.sln index 588cabf6b6..735c19b699 100644 --- a/osu.sln +++ b/osu.sln @@ -31,60 +31,93 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Modes.Mania", "osu EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Desktop.Tests", "osu.Desktop.Tests\osu.Desktop.Tests.csproj", "{230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Desktop.Deploy", "osu.Desktop.Deploy\osu.Desktop.Deploy.csproj", "{BAEA2F74-0315-4667-84E0-ACAC0B4BF785}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Release (Deploy)|Any CPU = Release (Deploy)|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release (Deploy)|Any CPU.ActiveCfg = Deploy|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release (Deploy)|Any CPU.Build.0 = Deploy|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU {C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Release|Any CPU.ActiveCfg = Release|Any CPU {C76BF5B3-985E-4D39-95FE-97C9C879B83A}.Release|Any CPU.Build.0 = Release|Any CPU {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}.Release|Any CPU.ActiveCfg = Release|Any CPU {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}.Release|Any CPU.Build.0 = Release|Any CPU {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.ActiveCfg = Release|Any CPU {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.Build.0 = Release|Any CPU {65DC628F-A640-4111-AB35-3A5652BC1E17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {65DC628F-A640-4111-AB35-3A5652BC1E17}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65DC628F-A640-4111-AB35-3A5652BC1E17}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {65DC628F-A640-4111-AB35-3A5652BC1E17}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {65DC628F-A640-4111-AB35-3A5652BC1E17}.Release|Any CPU.ActiveCfg = Release|Any CPU {65DC628F-A640-4111-AB35-3A5652BC1E17}.Release|Any CPU.Build.0 = Release|Any CPU {69051C69-12AE-4E7D-A3E6-460D2E282312}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {69051C69-12AE-4E7D-A3E6-460D2E282312}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69051C69-12AE-4E7D-A3E6-460D2E282312}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {69051C69-12AE-4E7D-A3E6-460D2E282312}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {69051C69-12AE-4E7D-A3E6-460D2E282312}.Release|Any CPU.ActiveCfg = Release|Any CPU {69051C69-12AE-4E7D-A3E6-460D2E282312}.Release|Any CPU.Build.0 = Release|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.ActiveCfg = Release|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.Build.0 = Release|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU {230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU {230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D}.Release|Any CPU.ActiveCfg = Release|Any CPU {230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D}.Release|Any CPU.Build.0 = Release|Any CPU + {BAEA2F74-0315-4667-84E0-ACAC0B4BF785}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAEA2F74-0315-4667-84E0-ACAC0B4BF785}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAEA2F74-0315-4667-84E0-ACAC0B4BF785}.Release (Deploy)|Any CPU.ActiveCfg = Release|Any CPU + {BAEA2F74-0315-4667-84E0-ACAC0B4BF785}.Release (Deploy)|Any CPU.Build.0 = Release|Any CPU + {BAEA2F74-0315-4667-84E0-ACAC0B4BF785}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAEA2F74-0315-4667-84E0-ACAC0B4BF785}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -102,6 +135,7 @@ Global {F167E17A-7DE6-4AF5-B920-A5112296C695} = {0D37A2AD-80A4-464F-A1DE-1560B70F1CE3} {48F4582B-7687-4621-9CBE-5C24197CB536} = {0D37A2AD-80A4-464F-A1DE-1560B70F1CE3} {230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D} = {0D37A2AD-80A4-464F-A1DE-1560B70F1CE3} + {BAEA2F74-0315-4667-84E0-ACAC0B4BF785} = {0D37A2AD-80A4-464F-A1DE-1560B70F1CE3} EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 From cef3454e9badc7840d7ee662982e7d28192683de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Feb 2017 10:06:19 +0900 Subject: [PATCH 12/27] Formatting and improvements. --- osu.Desktop.Deploy/Program.cs | 107 +++++++++++-------- osu.Desktop.Deploy/osu.Desktop.Deploy.csproj | 6 +- osu.sln | 27 ----- 3 files changed, 64 insertions(+), 76 deletions(-) diff --git a/osu.Desktop.Deploy/Program.cs b/osu.Desktop.Deploy/Program.cs index 902014ab65..955f57765e 100644 --- a/osu.Desktop.Deploy/Program.cs +++ b/osu.Desktop.Deploy/Program.cs @@ -1,43 +1,62 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System; using System.Diagnostics; using System.IO; using System.Linq; namespace osu.Desktop.Deploy { - class Program + internal static class Program { - static string NUGET_PATH = @"packages\NuGet.CommandLine.3.5.0\tools\NuGet.exe"; - static string SQUIRREL_PATH = @"packages\squirrel.windows.1.5.2\tools\Squirrel.exe"; - static string MSBUILD_PATH = @"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"; + private const string nuget_path = @"packages\NuGet.CommandLine.3.5.0\tools\NuGet.exe"; + private const string squirrel_path = @"packages\squirrel.windows.1.5.2\tools\Squirrel.exe"; + private const string msbuild_path = @"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"; - static string STAGING_FOLDER = "Staging"; - static string PROJECT_NAME = "osu.Desktop"; + public static string StagingFolder = "Staging"; + public static string ReleasesFolder = "Releases"; - static string CODE_SIGNING_CMD => $"/a /f {CODE_SIGNING_CERT} /p {codeSigningPassword} /t http://timestamp.comodoca.com/authenticode"; - static string IconPath => Path.Combine(SolutionPath, PROJECT_NAME, "lazer.ico"); + public static string ProjectName = "osu.Desktop"; + public static string CodeSigningCert => Path.Combine(homeDir, "deanherbert.pfx"); - static internal string HomeDir { get { return Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); } } - static internal string CODE_SIGNING_CERT => Path.Combine(HomeDir, "deanherbert.pfx"); + private static string codeSigningCmd => $"/a /f {CodeSigningCert} /p {codeSigningPassword} /t http://timestamp.comodoca.com/authenticode"; - static string SolutionPath => Environment.CurrentDirectory; - static string StagingPath => Path.Combine(SolutionPath, STAGING_FOLDER); + private static string homeDir => Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - static string codeSigningPassword; + private static string solutionPath => Environment.CurrentDirectory; + private static string stagingPath => Path.Combine(solutionPath, StagingFolder); + private static string iconPath => Path.Combine(solutionPath, ProjectName, "lazer.ico"); - static void Main(string[] args) + private static string codeSigningPassword; + + public static void Main(string[] args) { - FindSolutionPath(); + findSolutionPath(); - if (Directory.Exists(STAGING_FOLDER)) - Directory.Delete(STAGING_FOLDER, true); - Directory.CreateDirectory(STAGING_FOLDER); + if (Directory.Exists(StagingFolder)) + Directory.Delete(StagingFolder, true); + Directory.CreateDirectory(StagingFolder); string verBase = DateTime.Now.ToString("yyyy.Md."); int increment = 0; - while (Directory.GetFiles("Releases", $"*{verBase}{increment}*").Count() > 0) + if (!Directory.Exists(ReleasesFolder)) + { + Console.WriteLine("WARNING: No files found in the release directory. Make sure you want this."); + Directory.CreateDirectory(ReleasesFolder); + } + else + { + Console.WriteLine("Existing releases:"); + foreach (var l in File.ReadAllLines(Path.Combine(ReleasesFolder, "RELEASES"))) + Console.WriteLine(l); + Console.WriteLine(); + } + + //increment build number until we have a unique one. + while (Directory.GetFiles(ReleasesFolder, $"*{verBase}{increment}*").Any()) increment++; string ver = $"{verBase}{increment}"; @@ -51,19 +70,20 @@ namespace osu.Desktop.Deploy codeSigningPassword = Console.ReadLine(); Console.WriteLine("Restoring NuGet packages..."); - RunCommand(NUGET_PATH, "restore " + SolutionPath); + runCommand(nuget_path, "restore " + solutionPath); Console.WriteLine("Running build process..."); - RunCommand(MSBUILD_PATH, $"/v:quiet /m /t:Client\\{PROJECT_NAME.Replace('.', '_')} /p:OutputPath={StagingPath};Configuration=Release osu.sln"); + runCommand(msbuild_path, $"/v:quiet /m /t:Client\\{ProjectName.Replace('.', '_')} /p:OutputPath={stagingPath};Configuration=Release osu.sln"); Console.WriteLine("Creating NuGet deployment package..."); - RunCommand(NUGET_PATH, $"pack osu.Desktop\\osu.nuspec -Version {ver} -Properties Configuration=Deploy -OutputDirectory {StagingPath} -BasePath {StagingPath}"); + runCommand(nuget_path, $"pack osu.Desktop\\osu.nuspec -Version {ver} -Properties Configuration=Deploy -OutputDirectory {stagingPath} -BasePath {stagingPath}"); Console.WriteLine("Releasifying package..."); - RunCommand(SQUIRREL_PATH, $"--releasify {StagingPath}\\osulazer.{ver}.nupkg --setupIcon {IconPath} --icon {IconPath} -n \"{CODE_SIGNING_CMD}\" --no-msi"); + runCommand(squirrel_path, $"--releasify {stagingPath}\\osulazer.{ver}.nupkg --setupIcon {iconPath} --icon {iconPath} -n \"{codeSigningCmd}\" --no-msi"); - File.Copy("Releases\\Setup.exe", "Releases\\install.exe", true); - File.Delete("Releases\\Setup.exe"); + //rename setup to install. + File.Copy(Path.Combine(ReleasesFolder, "Setup.exe"), Path.Combine(ReleasesFolder, "install.exe"), true); + File.Delete(Path.Combine(ReleasesFolder, "Setup.exe")); Console.WriteLine("Done!"); @@ -73,7 +93,7 @@ namespace osu.Desktop.Deploy /// /// Find the base path of the osu! solution (git checkout location) /// - private static void FindSolutionPath() + private static void findSolutionPath() { string path = Path.GetDirectoryName(Environment.CommandLine.Replace("\"", "").Trim()); @@ -87,32 +107,27 @@ namespace osu.Desktop.Deploy Environment.CurrentDirectory = path; } - private static bool RunCommand(string command, string args) + private static bool runCommand(string command, string args) { - var psi = new ProcessStartInfo(command, args); - if (psi != null) + var psi = new ProcessStartInfo(command, args) { - psi.WorkingDirectory = SolutionPath; - psi.CreateNoWindow = true; - psi.RedirectStandardOutput = true; - psi.UseShellExecute = false; - psi.WindowStyle = ProcessWindowStyle.Hidden; - Process p = Process.Start(psi); - string output = p.StandardOutput.ReadToEnd(); - if (p.ExitCode != 0) - { - Console.WriteLine(output); - Error($"Command {command} {args} failed!"); - return false; - } + WorkingDirectory = solutionPath, + CreateNoWindow = true, + RedirectStandardOutput = true, + UseShellExecute = false, + WindowStyle = ProcessWindowStyle.Hidden + }; - return true; - } + Process p = Process.Start(psi); + string output = p.StandardOutput.ReadToEnd(); + if (p.ExitCode == 0) return true; + Console.WriteLine(output); + error($"Command {command} {args} failed!"); return false; } - private static void Error(string p) + private static void error(string p) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("ERROR: " + p); diff --git a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj index 3d4b86fc93..19bb226f71 100644 --- a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj +++ b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj @@ -32,6 +32,9 @@ prompt 4 + + osu.Desktop.Deploy.Program + ..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.dll @@ -94,9 +97,6 @@ - - - diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj index 2c88548c3e..7a5bd59074 100644 --- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj +++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj @@ -100,6 +100,9 @@ + + osu.licenseheader + diff --git a/osu.Desktop.Tests/packages.config b/osu.Desktop.Tests/packages.config index 05b53c019c..76b22db9d4 100644 --- a/osu.Desktop.Tests/packages.config +++ b/osu.Desktop.Tests/packages.config @@ -1,4 +1,8 @@  + diff --git a/osu.Desktop.VisualTests/OpenTK.dll.config b/osu.Desktop.VisualTests/OpenTK.dll.config index 1dd145f0c4..627e9f6009 100644 --- a/osu.Desktop.VisualTests/OpenTK.dll.config +++ b/osu.Desktop.VisualTests/OpenTK.dll.config @@ -1,8 +1,7 @@ - diff --git a/osu.Desktop.VisualTests/app.config b/osu.Desktop.VisualTests/app.config index 9bad888bf3..b9af3fdc80 100644 --- a/osu.Desktop.VisualTests/app.config +++ b/osu.Desktop.VisualTests/app.config @@ -1,9 +1,8 @@  - diff --git a/osu.Desktop.VisualTests/packages.config b/osu.Desktop.VisualTests/packages.config index 75affafd35..82404c059e 100644 --- a/osu.Desktop.VisualTests/packages.config +++ b/osu.Desktop.VisualTests/packages.config @@ -1,6 +1,6 @@  diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 17a4f5de70..e3cffc1804 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -1,4 +1,7 @@ -using osu.Framework.Allocation; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; diff --git a/osu.Desktop/Properties/AssemblyInfo.cs b/osu.Desktop/Properties/AssemblyInfo.cs index 1f234d2993..8784aa1ee0 100644 --- a/osu.Desktop/Properties/AssemblyInfo.cs +++ b/osu.Desktop/Properties/AssemblyInfo.cs @@ -1,4 +1,7 @@ -using System.Reflection; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/osu.Desktop/app.config b/osu.Desktop/app.config index 44ccc4b77a..b9af3fdc80 100644 --- a/osu.Desktop/app.config +++ b/osu.Desktop/app.config @@ -1,4 +1,8 @@  + diff --git a/osu.Desktop/packages.config b/osu.Desktop/packages.config index 8d1361bd0a..5fc8e82bfd 100644 --- a/osu.Desktop/packages.config +++ b/osu.Desktop/packages.config @@ -1,4 +1,8 @@  + diff --git a/osu.Game.Modes.Catch/OpenTK.dll.config b/osu.Game.Modes.Catch/OpenTK.dll.config index 1dd145f0c4..627e9f6009 100644 --- a/osu.Game.Modes.Catch/OpenTK.dll.config +++ b/osu.Game.Modes.Catch/OpenTK.dll.config @@ -1,8 +1,7 @@ - diff --git a/osu.Game.Modes.Catch/packages.config b/osu.Game.Modes.Catch/packages.config index 3c9e7e3fdc..d53e65896a 100644 --- a/osu.Game.Modes.Catch/packages.config +++ b/osu.Game.Modes.Catch/packages.config @@ -1,9 +1,8 @@  - \ No newline at end of file diff --git a/osu.Game.Modes.Mania/OpenTK.dll.config b/osu.Game.Modes.Mania/OpenTK.dll.config index 1dd145f0c4..627e9f6009 100644 --- a/osu.Game.Modes.Mania/OpenTK.dll.config +++ b/osu.Game.Modes.Mania/OpenTK.dll.config @@ -1,8 +1,7 @@ - diff --git a/osu.Game.Modes.Mania/app.config b/osu.Game.Modes.Mania/app.config index 9bad888bf3..b9af3fdc80 100644 --- a/osu.Game.Modes.Mania/app.config +++ b/osu.Game.Modes.Mania/app.config @@ -1,9 +1,8 @@  - diff --git a/osu.Game.Modes.Mania/packages.config b/osu.Game.Modes.Mania/packages.config index 3c9e7e3fdc..d53e65896a 100644 --- a/osu.Game.Modes.Mania/packages.config +++ b/osu.Game.Modes.Mania/packages.config @@ -1,9 +1,8 @@  - \ No newline at end of file diff --git a/osu.Game.Modes.Osu/OpenTK.dll.config b/osu.Game.Modes.Osu/OpenTK.dll.config index 1dd145f0c4..627e9f6009 100644 --- a/osu.Game.Modes.Osu/OpenTK.dll.config +++ b/osu.Game.Modes.Osu/OpenTK.dll.config @@ -1,8 +1,7 @@ - diff --git a/osu.Game.Modes.Osu/app.config b/osu.Game.Modes.Osu/app.config index c42343ec69..d9da887349 100644 --- a/osu.Game.Modes.Osu/app.config +++ b/osu.Game.Modes.Osu/app.config @@ -1,9 +1,8 @@ - diff --git a/osu.Game.Modes.Osu/packages.config b/osu.Game.Modes.Osu/packages.config index 591ae8cd7f..d06cd15869 100644 --- a/osu.Game.Modes.Osu/packages.config +++ b/osu.Game.Modes.Osu/packages.config @@ -1,10 +1,8 @@  - - \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/OpenTK.dll.config b/osu.Game.Modes.Taiko/OpenTK.dll.config index 1dd145f0c4..627e9f6009 100644 --- a/osu.Game.Modes.Taiko/OpenTK.dll.config +++ b/osu.Game.Modes.Taiko/OpenTK.dll.config @@ -1,8 +1,7 @@ - diff --git a/osu.Game.Modes.Taiko/packages.config b/osu.Game.Modes.Taiko/packages.config index 3c9e7e3fdc..d53e65896a 100644 --- a/osu.Game.Modes.Taiko/packages.config +++ b/osu.Game.Modes.Taiko/packages.config @@ -1,9 +1,8 @@  - \ No newline at end of file diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs index 9a988d6eff..6613b5c370 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using System.IO; using NUnit.Framework; using OpenTK; diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 165181a332..6a162a4ab9 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index 037c0185b8..3d706a8026 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using System.IO; using NUnit.Framework; using osu.Game.Beatmaps.IO; diff --git a/osu.Game.Tests/OpenTK.dll.config b/osu.Game.Tests/OpenTK.dll.config index 5620e3d9e2..627e9f6009 100644 --- a/osu.Game.Tests/OpenTK.dll.config +++ b/osu.Game.Tests/OpenTK.dll.config @@ -1,3 +1,7 @@ + diff --git a/osu.Game.Tests/Resources/Resource.cs b/osu.Game.Tests/Resources/Resource.cs index 21945ac504..6c66b6818b 100644 --- a/osu.Game.Tests/Resources/Resource.cs +++ b/osu.Game.Tests/Resources/Resource.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using System.IO; using System.Reflection; diff --git a/osu.Game.Tests/app.config b/osu.Game.Tests/app.config index 44ccc4b77a..b9af3fdc80 100644 --- a/osu.Game.Tests/app.config +++ b/osu.Game.Tests/app.config @@ -1,4 +1,8 @@  + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index c6f0c6fa55..f555615f09 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -55,6 +55,9 @@ + + osu.licenseheader + diff --git a/osu.Game.Tests/packages.config b/osu.Game.Tests/packages.config index f9151f1eaa..b9f1a2c8cd 100644 --- a/osu.Game.Tests/packages.config +++ b/osu.Game.Tests/packages.config @@ -1,4 +1,8 @@  + diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index 55c37cb71d..5ff63ead2a 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -20,6 +20,8 @@ namespace osu.Game.Graphics.Backgrounds public Background(string textureName = @"") { + CacheDrawnFrameBuffer = true; + this.textureName = textureName; RelativeSizeAxes = Axes.Both; Depth = float.MaxValue; diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index 13fbbb16e0..bc8be25035 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Options/OptionEnumDropDown.cs b/osu.Game/Overlays/Options/OptionEnumDropDown.cs index 81438fd59e..044e704d3a 100644 --- a/osu.Game/Overlays/Options/OptionEnumDropDown.cs +++ b/osu.Game/Overlays/Options/OptionEnumDropDown.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs index 65b50542ce..e7b0ba1566 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs @@ -78,7 +78,6 @@ namespace osu.Game.Screens.Backgrounds public BeatmapBackground(WorkingBeatmap beatmap) { this.beatmap = beatmap; - CacheDrawnFrameBuffer = true; } [BackgroundDependencyLoader] diff --git a/osu.Game/packages.config b/osu.Game/packages.config index 98448d402f..0249d173ac 100644 --- a/osu.Game/packages.config +++ b/osu.Game/packages.config @@ -1,9 +1,8 @@  - diff --git a/osu.licenseheader b/osu.licenseheader index 94a06a7e14..30ea2f9ad9 100644 --- a/osu.licenseheader +++ b/osu.licenseheader @@ -4,6 +4,6 @@ extensions: .xml .config .xsd +--> \ No newline at end of file