1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-13 15:53:51 +08:00

Merge branch 'master'

This commit is contained in:
Huo Yaoyuan 2016-11-06 00:10:38 +08:00
commit c470140d64
36 changed files with 452 additions and 252 deletions

@ -1 +1 @@
Subproject commit 2b9a56e8b3bb6c99bf4c75307639e6726fe8d3ec
Subproject commit ed33cc48996e9b57093c4d057aa0560319495dee

@ -1 +1 @@
Subproject commit c0781d1d557c3e5a00f6cf1780049e382f92c0c8
Subproject commit 5ce263988735b3f15c1195568b65fef40756198c

View File

@ -8,6 +8,7 @@ using osu.Framework.Timing;
using osu.Game.Beatmaps.Objects;
using osu.Game.Beatmaps.Objects.Osu;
using osu.Game.Beatmaps.Objects.Osu.Drawable;
using OpenTK;
namespace osu.Desktop.VisualTests.Tests
{
@ -33,12 +34,14 @@ namespace osu.Desktop.VisualTests.Tests
ourClock.ProcessFrame();
for (int i = 0; i < 20; i++)
const int count = 10;
for (int i = 0; i < count; i++)
{
var h = new Circle
{
StartTime = ourClock.CurrentTime + 1000 + i * 80,
Position = new OpenTK.Vector2(i * 14),
Position = new Vector2((i - count / 2) * 14),
};
Add(new DrawableCircle(h)

View File

@ -6,6 +6,7 @@ using osu.Framework.GameModes.Testing;
using osu.Framework.MathUtils;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.Objects;
using osu.Game.Beatmaps.Objects.Osu;
using osu.Game.GameModes.Play;
@ -38,21 +39,25 @@ namespace osu.Desktop.VisualTests.Tests
objects.Add(new Circle()
{
StartTime = time,
Position = new Vector2(RNG.Next(100, 400), RNG.Next(100, 200))
Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384)),
NewCombo = i % 4 == 0
});
time += 500;
}
var decoder = new ConstructableBeatmapDecoder();
Beatmap b = new Beatmap
{
HitObjects = objects
};
decoder.Process(b);
Add(new Player
{
Beatmap = new WorkingBeatmap
{
Beatmap = new Beatmap
{
HitObjects = objects
}
}
Beatmap = new WorkingBeatmap(b)
});
}

View File

@ -29,7 +29,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");
using (var stream = new StreamReader(ReadFile(beatmaps[0])))
using (var stream = new StreamReader(GetStream(beatmaps[0])))
{
var decoder = BeatmapDecoder.GetDecoder(stream);
firstMap = decoder.Decode(stream);
@ -41,7 +41,7 @@ namespace osu.Desktop.Beatmaps.IO
return beatmaps;
}
public override Stream ReadFile(string name)
public override Stream GetStream(string name)
{
return File.OpenRead(Path.Combine(basePath, name));
}

View File

@ -8,6 +8,7 @@ using osu.Framework.Desktop.Platform;
using osu.Framework.Platform;
using osu.Game.Database;
using osu.Game.IPC;
using osu.Game.GameModes.Play;
namespace osu.Game.Tests.Beatmaps.IO
{
@ -45,7 +46,7 @@ namespace osu.Game.Tests.Beatmaps.IO
var importer = new BeatmapImporter(client);
if (!importer.Import(osz_path).Wait(1000))
Assert.Fail(@"IPC took too long to send");
Assert.Fail(@"IPC took too long to send");
ensureLoaded(osu, 10000);
}
@ -78,7 +79,7 @@ namespace osu.Game.Tests.Beatmaps.IO
@"BeatmapSet did not import to the database");
//ensure we were stored to beatmap database backing...
Assert.IsTrue(resultSets.Count() == 1);
IEnumerable<BeatmapInfo> resultBeatmaps = null;
@ -103,7 +104,7 @@ namespace osu.Game.Tests.Beatmaps.IO
Assert.IsTrue(set.Beatmaps.Count > 0);
var beatmap = osu.Beatmaps.GetBeatmap(set.Beatmaps[0]);
var beatmap = osu.Beatmaps.GetBeatmap(set.Beatmaps.First(b => b.Mode == PlayMode.Osu));
Assert.IsTrue(beatmap.HitObjects.Count > 0);
}

View File

@ -70,7 +70,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{
var reader = new OszArchiveReader(osz);
using (var stream = new StreamReader(
reader.ReadFile("Soleily - Renatus (Deif) [Platter].osu")))
reader.GetStream("Soleily - Renatus (Deif) [Platter].osu")))
{
Assert.AreEqual("osu file format v13", stream.ReadLine().Trim());
}

View File

@ -52,7 +52,7 @@ namespace osu.Game.Beatmaps.Drawable
header.State = PanelSelectedState.Selected;
break;
case BeatmapGroupState.Collapsed:
FadeTo(0.5f, 250);
FadeTo(0.8f, 250);
header.State = PanelSelectedState.NotSelected;
difficulties.Hide();
@ -61,7 +61,7 @@ namespace osu.Game.Beatmaps.Drawable
}
}
public BeatmapGroup(BeatmapSetInfo beatmapSet)
public BeatmapGroup(BeatmapSetInfo beatmapSet, WorkingBeatmap working)
{
this.beatmapSet = beatmapSet;
@ -78,7 +78,7 @@ namespace osu.Game.Beatmaps.Drawable
Direction = FlowDirection.VerticalOnly,
Children = new Framework.Graphics.Drawable[]
{
header = new BeatmapSetHeader(beatmapSet)
header = new BeatmapSetHeader(beatmapSet, working)
{
GainedSelection = headerGainedSelection,
RelativeSizeAxes = Axes.X,

View File

@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps.Drawable
public BeatmapPanel(BeatmapInfo beatmap)
{
Beatmap = beatmap;
Height *= 0.75f;
Height *= 0.60f;
Children = new Framework.Graphics.Drawable[]
{
@ -44,12 +44,20 @@ namespace osu.Game.Beatmaps.Drawable
Padding = new MarginPadding(5),
Direction = FlowDirection.HorizontalOnly,
AutoSizeAxes = Axes.Both,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Children = new Framework.Graphics.Drawable[]
{
new DifficultyIcon(FontAwesome.dot_circle_o, new Color4(159, 198, 0, 255)),
new DifficultyIcon(FontAwesome.dot_circle_o, new Color4(159, 198, 0, 255))
{
Scale = new Vector2(1.8f),
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
},
new FlowContainer
{
Padding = new MarginPadding { Left = 10 },
Padding = new MarginPadding { Left = 5 },
Spacing = new Vector2(0, 5),
Direction = FlowDirection.VerticalOnly,
AutoSizeAxes = Axes.Both,
Children = new Framework.Graphics.Drawable[]
@ -58,17 +66,32 @@ namespace osu.Game.Beatmaps.Drawable
{
Direction = FlowDirection.HorizontalOnly,
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(4, 0),
Children = new[]
{
new SpriteText
{
Font = @"Exo2.0-Medium",
Text = beatmap.Version,
TextSize = 20,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft
},
new SpriteText
{
Text = $" mapped by {(beatmap.Metadata ?? beatmap.BeatmapSet.Metadata).Author}",
Font = @"Exo2.0-Medium",
Text = "mapped by",
TextSize = 16,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft
},
new SpriteText
{
Font = @"Exo2.0-MediumItalic",
Text = $"{(beatmap.Metadata ?? beatmap.BeatmapSet.Metadata).Author}",
TextSize = 16,
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft
},
}
},

View File

@ -31,27 +31,18 @@ namespace osu.Game.Beatmaps.Drawable
Width = 0.8f;
}
public BeatmapSetHeader(BeatmapSetInfo beatmapSet)
public BeatmapSetHeader(BeatmapSetInfo beatmapSet, WorkingBeatmap working)
{
Children = new Framework.Graphics.Drawable[]
{
new Box
working.Background == null ? new Box{ RelativeSizeAxes = Axes.Both, Colour = new Color4(20, 20, 20, 255) } : new Sprite
{
Colour = new Color4(85, 85, 85, 255),
RelativeSizeAxes = Axes.Both,
},
new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Framework.Graphics.Drawable[]
{
new Box // TODO: Gradient
{
Colour = new Color4(0, 0, 0, 100),
RelativeSizeAxes = Axes.Both,
}
}
},
Texture = working.Background,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(0.5f),
Colour = new Color4(200, 200, 200, 255),
},
new FlowContainer
{
Direction = FlowDirection.VerticalOnly,
@ -60,14 +51,15 @@ namespace osu.Game.Beatmaps.Drawable
AutoSizeAxes = Axes.Both,
Children = new[]
{
// TODO: Make these italic
new SpriteText
{
Font = @"Exo2.0-SemiBoldItalic",
Text = beatmapSet.Metadata.Title ?? beatmapSet.Metadata.TitleUnicode,
TextSize = 20
TextSize = 22
},
new SpriteText
{
Font = @"Exo2.0-MediumItalic",
Text = beatmapSet.Metadata.Artist ?? beatmapSet.Metadata.ArtistUnicode,
TextSize = 16
},

View File

@ -10,6 +10,7 @@ using osu.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Beatmaps.Drawable
@ -22,12 +23,14 @@ namespace osu.Game.Beatmaps.Drawable
Masking = true;
CornerRadius = 10;
BorderColour = new Color4(221, 255, 255, 0);
BorderColour = new Color4(221, 255, 255, 255);
RelativeSizeAxes = Axes.X;
Deselected();
}
private PanelSelectedState state;
private PanelSelectedState state = PanelSelectedState.NotSelected;
public PanelSelectedState State
{
@ -52,7 +55,6 @@ namespace osu.Game.Beatmaps.Drawable
protected virtual void Selected()
{
BorderColour = new Color4(BorderColour.R, BorderColour.G, BorderColour.B, 1f);
BorderThickness = 2.5f;
EdgeEffect = new EdgeEffect
@ -66,10 +68,15 @@ namespace osu.Game.Beatmaps.Drawable
protected virtual void Deselected()
{
BorderColour = new Color4(BorderColour.R, BorderColour.G, BorderColour.B, 0);
BorderThickness = 0;
EdgeEffect = new EdgeEffect { Type = EdgeEffectType.None };
EdgeEffect = new EdgeEffect
{
Type = EdgeEffectType.Shadow,
Offset = new Vector2(1),
Radius = 10,
Colour = new Color4(0, 0, 0, 100),
};
}
protected override bool OnClick(InputState state)

View File

@ -1,13 +1,15 @@
using System;
using System.Collections.Generic;
using System.IO;
using osu.Game.Beatmaps.Objects;
using OpenTK.Graphics;
namespace osu.Game.Beatmaps.Formats
{
public abstract class BeatmapDecoder
{
private static Dictionary<string, Type> decoders { get; } = new Dictionary<string, Type>();
public static BeatmapDecoder GetDecoder(TextReader stream)
{
var line = stream.ReadLine().Trim();
@ -20,7 +22,39 @@ namespace osu.Game.Beatmaps.Formats
{
decoders[magic] = typeof(T);
}
public abstract Beatmap Decode(TextReader stream);
public virtual Beatmap Decode(TextReader stream)
{
Beatmap b = ParseFile(stream);
Process(b);
return b;
}
public virtual Beatmap Process(Beatmap beatmap)
{
ApplyColours(beatmap);
return beatmap;
}
protected abstract Beatmap ParseFile(TextReader stream);
public virtual void ApplyColours(Beatmap b)
{
List<Color4> colours = b.ComboColors ?? new List<Color4>() {
new Color4(17, 136, 170, 255),
new Color4(102,136,0, 255),
new Color4(204,102,0, 255),
new Color4(121,9,13, 255),
};
int i = -1;
foreach (HitObject h in b.HitObjects)
{
if (h.NewCombo) i = (i + 1) % colours.Count;
h.Colour = colours[i];
}
}
}
}

View File

@ -0,0 +1,20 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//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;
using System.Text;
using System.Threading.Tasks;
namespace osu.Game.Beatmaps.Formats
{
public class ConstructableBeatmapDecoder : BeatmapDecoder
{
protected override Beatmap ParseFile(TextReader stream)
{
throw new NotImplementedException();
}
}
}

View File

@ -207,7 +207,7 @@ namespace osu.Game.Beatmaps.Formats
});
}
public override Beatmap Decode(TextReader stream)
protected override Beatmap ParseFile(TextReader stream)
{
var beatmap = new Beatmap
{
@ -270,7 +270,9 @@ namespace osu.Game.Beatmaps.Formats
handleColours(beatmap, key, val);
break;
case Section.HitObjects:
beatmap.HitObjects.Add(HitObject.Parse(beatmap.BeatmapInfo.Mode, val));
var h = HitObject.Parse(beatmap.BeatmapInfo.Mode, val);
if (h != null)
beatmap.HitObjects.Add(h);
break;
}
}

View File

@ -1,12 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using osu.Framework.IO.Stores;
using osu.Framework.Platform;
using osu.Game.Database;
namespace osu.Game.Beatmaps.IO
{
public abstract class ArchiveReader : IDisposable
public abstract class ArchiveReader : IDisposable, IResourceStore<byte[]>
{
private class Reader
{
@ -42,8 +43,23 @@ namespace osu.Game.Beatmaps.IO
/// <summary>
/// Opens a stream for reading a specific file from this archive.
/// </summary>
public abstract Stream ReadFile(string name);
public abstract Stream GetStream(string name);
public abstract void Dispose();
public virtual byte[] Get(string name)
{
using (Stream input = GetStream(name))
{
if (input == null)
return null;
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
}
}
}

View File

@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps.IO
.Select(e => e.FileName).ToArray();
if (beatmaps.Length == 0)
throw new FileNotFoundException(@"This directory contains no beatmaps");
using (var stream = new StreamReader(ReadFile(beatmaps[0])))
using (var stream = new StreamReader(GetStream(beatmaps[0])))
{
var decoder = BeatmapDecoder.GetDecoder(stream);
firstMap = decoder.Decode(stream);
@ -45,7 +45,7 @@ namespace osu.Game.Beatmaps.IO
return beatmaps;
}
public override Stream ReadFile(string name)
public override Stream GetStream(string name)
{
ZipEntry entry = archive.Entries.SingleOrDefault(e => e.FileName == name);
if (entry == null)

View File

@ -14,14 +14,18 @@ namespace osu.Game.Beatmaps.Objects
{
public abstract class DrawableHitObject : Container, IStateful<ArmedState>
{
//todo: move to a more central implementation. this logic should not be at a drawable level.
public Action<DrawableHitObject> OnHit;
public Action<DrawableHitObject> OnMiss;
public Func<DrawableHitObject, bool> AllowHit;
public HitObject HitObject;
public DrawableHitObject(HitObject hitObject)
{
HitObject = hitObject;
Depth = -(float)hitObject.StartTime;
}
private ArmedState state;
@ -31,12 +35,29 @@ namespace osu.Game.Beatmaps.Objects
set
{
if (state == value) return;
state = value;
UpdateState(state);
}
}
protected double? HitTime;
protected virtual bool Hit()
{
if (State != ArmedState.Disarmed)
return false;
if (AllowHit?.Invoke(this) == false)
return false;
HitTime = Time;
State = ArmedState.Armed;
return true;
}
protected override void LoadComplete()
{
base.LoadComplete();

View File

@ -4,6 +4,7 @@
using osu.Game.Beatmaps.Objects.Osu;
using osu.Game.Beatmaps.Samples;
using osu.Game.GameModes.Play;
using OpenTK.Graphics;
namespace osu.Game.Beatmaps.Objects
{
@ -15,6 +16,10 @@ namespace osu.Game.Beatmaps.Objects
public double StartTime;
public virtual double EndTime => StartTime;
public bool NewCombo { get; set; }
public Color4 Colour = new Color4(17, 136, 170, 255);
public double Duration => EndTime - StartTime;
public HitSampleInfo Sample;

View File

@ -7,6 +7,5 @@ namespace osu.Game.Beatmaps.Objects.Osu
{
public class Circle : OsuBaseHit
{
public Color4 Colour = new Color4(17, 136, 170, 255);
}
}

View File

@ -8,22 +8,21 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.Transformations;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Input;
using osu.Framework.MathUtils;
using OpenTK;
namespace osu.Game.Beatmaps.Objects.Osu.Drawable
{
public class DrawableCircle : DrawableHitObject
{
private Sprite approachCircle;
private CirclePart circle;
private RingPart ring;
private FlashPart flash;
private ExplodePart explode;
private NumberPart number;
private GlowPart glow;
private CircleLayer circle;
private RingLayer ring;
private FlashLayer flash;
private ExplodeLayer explode;
private NumberLayer number;
private GlowLayer glow;
private OsuBaseHit h;
public DrawableCircle(Circle h) : base(h)
@ -31,28 +30,27 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable
this.h = h;
Origin = Anchor.Centre;
Alpha = 0;
Position = h.Position;
Scale = new Vector2(0.4f);
RelativePositionAxes = Axes.Both;
Position = new Vector2(h.Position.X / 512, h.Position.Y / 384);
Children = new Framework.Graphics.Drawable[]
{
glow = new GlowPart()
{
Colour = h.Colour,
},
circle = new CirclePart()
{
Colour = h.Colour,
Hit = delegate { State = ArmedState.Armed; }
},
number = new NumberPart(),
ring = new RingPart(),
flash = new FlashPart(),
explode = new ExplodePart()
glow = new GlowLayer
{
Colour = h.Colour
},
circle = new CircleLayer
{
Colour = h.Colour,
Hit = Hit,
},
number = new NumberLayer(),
ring = new RingLayer(),
flash = new FlashLayer(),
explode = new ExplodeLayer
{
Colour = h.Colour,
},
approachCircle = new Sprite
{
Anchor = Anchor.Centre,
@ -61,7 +59,8 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable
}
};
Size = new Vector2(100);
//may not be so correct
Size = circle.DrawSize;
}
protected override void Load(BaseGame game)
@ -71,63 +70,82 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable
approachCircle.Texture = game.Textures.Get(@"Play/osu/approachcircle@2x");
}
protected override void LoadComplete()
{
base.LoadComplete();
//force application of the state that was set before we loaded.
UpdateState(State);
}
protected override void UpdateState(ArmedState state)
{
if (!IsLoaded) return;
Flush(); //move to DrawableHitObject
Flush(true); //move to DrawableHitObject
Transforms.Add(new TransformAlpha { StartTime = h.StartTime - 1000, EndTime = h.StartTime - 800, StartValue = 0, EndValue = 1 });
double t = HitTime ?? h.StartTime;
approachCircle.Transforms.Add(new TransformScale { StartTime = h.StartTime - 1000, EndTime = h.StartTime, StartValue = new Vector2(2f), EndValue = new Vector2(0.6f) });
approachCircle.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime, StartValue = 1, EndValue = 0 });
//sane defaults
ring.Alpha = circle.Alpha = number.Alpha = approachCircle.Alpha = glow.Alpha = 1;
explode.Alpha = 0;
Scale = Vector2.One;
glow.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime + 400, StartValue = glow.Alpha, EndValue = 0 });
//always-present transforms
Transforms.Add(new TransformAlpha { StartTime = t - 1000, EndTime = t - 800, StartValue = 0, EndValue = 1 });
approachCircle.Transforms.Add(new TransformScale { StartTime = t - 1000, EndTime = t, StartValue = new Vector2(2f), EndValue = new Vector2(0.6f) });
//set transform delay to t==hitTime
Delay(t - Time, true);
approachCircle.FadeOut();
glow.FadeOut(400);
switch (state)
{
case ArmedState.Disarmed:
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
Delay(h.Duration + 200);
FadeOut(200);
break;
case ArmedState.Armed:
const float flashIn = 30;
const float fadeOut = 800;
const double flash_in = 30;
//Transforms.Add(new TransformScale() { StartTime = h.StartTime, EndTime = h.StartTime + 400, StartValue = Scale, EndValue = Scale * 1.1f });
flash.FadeTo(0.8f, flash_in);
flash.Delay(flash_in);
flash.FadeOut(100);
ring.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 });
circle.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 });
number.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 });
explode.FadeIn(flash_in);
flash.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0.8f });
flash.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn + 100, StartValue = 0.8f, EndValue = 0 });
Delay(flash_in, true);
explode.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 1 });
//after the flash, we can hide some elements that were behind it
ring.FadeOut();
circle.FadeOut();
number.FadeOut();
Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn + fadeOut, StartValue = 1, EndValue = 0 });
Transforms.Add(new TransformScale { StartTime = h.StartTime + h.Duration, EndTime = h.StartTime + h.Duration + 400, StartValue = Scale, EndValue = Scale * 1.5f, Easing = EasingTypes.OutQuad });
FadeOut(800);
ScaleTo(Scale * 1.5f, 400, EasingTypes.OutQuad);
break;
}
}
class NumberPart : Container
private class NumberLayer : Container
{
private Sprite number;
public NumberPart()
public NumberLayer()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Children = new[]
{
number = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Alpha = 1,
}
number = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Alpha = 1
}
};
}
@ -138,39 +156,39 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable
}
}
class GlowPart : Container
private class GlowLayer : Container
{
private Sprite layer3;
private Sprite layer;
public GlowPart()
public GlowLayer()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Children = new[]
{
layer3 = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Additive = true,
Alpha = 0.5f,
}
layer = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
BlendingMode = BlendingMode.Additive,
Alpha = 0.5f
}
};
}
protected override void Load(BaseGame game)
{
base.Load(game);
layer3.Texture = game.Textures.Get(@"Play/osu/ring-glow@2x");
layer.Texture = game.Textures.Get(@"Play/osu/ring-glow@2x");
}
}
class RingPart : Container
private class RingLayer : Container
{
private Sprite ring;
public RingPart()
public RingLayer()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
@ -180,8 +198,8 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable
ring = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
Origin = Anchor.Centre
}
};
}
@ -192,93 +210,62 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable
}
}
class FlashPart : Container
private class FlashLayer : Container
{
public FlashPart()
public FlashLayer()
{
Size = new Vector2(144);
Masking = true;
CornerRadius = Size.X / 2;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Additive = true;
BlendingMode = BlendingMode.Additive;
Alpha = 0;
Children = new Framework.Graphics.Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
RelativeSizeAxes = Axes.Both
}
};
}
}
class ExplodePart : Container
private class ExplodeLayer : Container
{
public ExplodePart()
public ExplodeLayer()
{
Size = new Vector2(144);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Additive = true;
BlendingMode = BlendingMode.Additive;
Alpha = 0;
Children = new Framework.Graphics.Drawable[]
{
new Triangles
{
RelativeSizeAxes = Axes.Both,
},
};
}
class Triangles : Container
{
private Texture tex;
protected override void Load(BaseGame game)
{
base.Load(game);
tex = game.Textures.Get(@"Play/osu/triangle@2x");
for (int i = 0; i < 10; i++)
{
Add(new Sprite
{
Texture = tex,
Origin = Anchor.Centre,
Position = new Vector2(RNG.NextSingle() * DrawSize.X, RNG.NextSingle() * DrawSize.Y),
Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f),
Alpha = RNG.NextSingle() * 0.3f,
});
RelativeSizeAxes = Axes.Both
}
}
protected override void Update()
{
base.Update();
foreach (Framework.Graphics.Drawable d in Children)
d.Position -= new Vector2(0, (float)(d.Scale.X * (Clock.ElapsedFrameTime / 20)));
}
};
}
}
class CirclePart : Container
private class CircleLayer : Container
{
private Sprite disc;
private Triangles triangles;
public Action Hit;
public Func<bool> Hit;
public CirclePart()
public CircleLayer()
{
Size = new Vector2(144);
Masking = true;
@ -292,13 +279,13 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable
disc = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Origin = Anchor.Centre
},
triangles = new Triangles
{
Additive = true,
RelativeSizeAxes = Axes.Both,
},
BlendingMode = BlendingMode.Additive,
RelativeSizeAxes = Axes.Both
}
};
}
@ -313,37 +300,38 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable
Hit?.Invoke();
return true;
}
}
class Triangles : Container
private class Triangles : Container
{
private Texture tex;
protected override void Load(BaseGame game)
{
private Texture tex;
base.Load(game);
protected override void Load(BaseGame game)
tex = game.Textures.Get(@"Play/osu/triangle@2x");
for (int i = 0; i < 10; i++)
{
base.Load(game);
tex = game.Textures.Get(@"Play/osu/triangle@2x");
for (int i = 0; i < 10; i++)
Add(new Sprite
{
Add(new Sprite
{
Texture = tex,
Origin = Anchor.Centre,
Position = new Vector2(RNG.NextSingle() * DrawSize.X, RNG.NextSingle() * DrawSize.Y),
Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f),
Alpha = RNG.NextSingle() * 0.3f,
});
}
Texture = tex,
Origin = Anchor.Centre,
RelativePositionAxes = Axes.Both,
Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()),
Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f),
Alpha = RNG.NextSingle() * 0.3f
});
}
}
protected override void Update()
{
base.Update();
protected override void Update()
{
base.Update();
foreach (Framework.Graphics.Drawable d in Children)
d.Position -= new Vector2(0, (float)(d.Scale.X * (Clock.ElapsedFrameTime / 20)));
}
foreach (Framework.Graphics.Drawable d in Children)
d.Position -= new Vector2(0, (float)(d.Scale.X * (Clock.ElapsedFrameTime / 2880)));
}
}
}

View File

@ -10,7 +10,6 @@ namespace osu.Game.Beatmaps.Objects.Osu
public abstract class OsuBaseHit : HitObject
{
public Vector2 Position { get; set; }
public bool NewCombo { get; set; }
[Flags]
private enum HitObjectType

View File

@ -13,6 +13,11 @@ namespace osu.Game.Beatmaps.Timing
{
public double BeatLength;
public TimingChange(double beatLength)
{
BeatLength = beatLength;
}
public double BPM => 60000 / BeatLength;
}
}

View File

@ -4,6 +4,7 @@
using System;
using System.IO;
using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.IO;
using osu.Game.Database;
@ -12,53 +13,92 @@ namespace osu.Game.Beatmaps
{
public class WorkingBeatmap : IDisposable
{
public BeatmapInfo BeatmapInfo;
public readonly BeatmapInfo BeatmapInfo;
public readonly ArchiveReader Reader;
public readonly BeatmapSetInfo BeatmapSetInfo;
private readonly BeatmapDatabase database;
private ArchiveReader reader => database.GetReader(BeatmapSetInfo);
private Texture background;
private object backgroundLock = new object();
public Texture Background
{
get
{
lock (backgroundLock)
{
if (background != null) return background;
try
{
background = new TextureStore(new RawTextureLoaderStore(reader)).Get(BeatmapInfo.Metadata.BackgroundFile);
}
catch { }
return background;
}
}
set { lock (backgroundLock) background = value; }
}
private Beatmap beatmap;
private object beatmapLock = new object();
public Beatmap Beatmap
{
get
{
if (beatmap != null) return beatmap;
try
lock (beatmapLock)
{
using (var stream = new StreamReader(Reader.ReadFile(BeatmapInfo.Path)))
beatmap = BeatmapDecoder.GetDecoder(stream)?.Decode(stream);
}
catch { }
if (beatmap != null) return beatmap;
return beatmap;
try
{
using (var stream = new StreamReader(reader.GetStream(BeatmapInfo.Path)))
beatmap = BeatmapDecoder.GetDecoder(stream)?.Decode(stream);
}
catch { }
return beatmap;
}
}
set { beatmap = value; }
set { lock (beatmapLock) beatmap = value; }
}
private AudioTrack track;
private object trackLock = new object();
public AudioTrack Track
{
get
{
if (track != null) return track;
try
lock (trackLock)
{
var trackData = Reader.ReadFile(BeatmapInfo.Metadata.AudioFile);
if (trackData != null)
track = new AudioTrackBass(trackData);
}
catch { }
if (track != null) return track;
return track;
try
{
var trackData = reader.GetStream(BeatmapInfo.Metadata.AudioFile);
if (trackData != null)
track = new AudioTrackBass(trackData);
}
catch { }
return track;
}
}
set { track = value; }
set { lock (trackLock) track = value; }
}
public WorkingBeatmap(BeatmapInfo beatmapInfo = null, ArchiveReader reader = null)
public WorkingBeatmap(Beatmap beatmap)
{
this.beatmap = beatmap;
}
public WorkingBeatmap(BeatmapInfo beatmapInfo, BeatmapSetInfo beatmapSetInfo, BeatmapDatabase database)
{
this.BeatmapInfo = beatmapInfo;
Reader = reader;
this.BeatmapSetInfo = beatmapSetInfo;
this.database = database;
}
private bool isDisposed;
@ -68,7 +108,7 @@ namespace osu.Game.Beatmaps
if (!isDisposed)
{
track?.Dispose();
Reader?.Dispose();
reader?.Dispose();
isDisposed = true;
}
}

View File

@ -95,7 +95,7 @@ namespace osu.Game.Database
string[] mapNames = reader.ReadBeatmaps();
foreach (var name in mapNames)
{
using (var stream = new StreamReader(reader.ReadFile(name)))
using (var stream = new StreamReader(reader.GetStream(name)))
{
var decoder = BeatmapDecoder.GetDecoder(stream);
Beatmap beatmap = decoder.Decode(stream);
@ -149,12 +149,10 @@ namespace osu.Game.Database
if (beatmapSetInfo == null)
throw new InvalidOperationException($@"Beatmap set {beatmapInfo.BeatmapSetID} is not in the local database.");
var reader = GetReader(beatmapSetInfo);
if (beatmapInfo.Metadata == null)
beatmapInfo.Metadata = beatmapSetInfo.Metadata;
var working = new WorkingBeatmap(beatmapInfo, reader);
var working = new WorkingBeatmap(beatmapInfo, beatmapSetInfo, this);
previous?.TransferTo(working);

View File

@ -91,7 +91,7 @@ namespace osu.Game.GameModes
Origin = Anchor.Centre,
Colour = getColourFor(GetType()),
Alpha = 1,
Additive = false
BlendingMode = BlendingMode.Additive,
},
textContainer = new Container
{

View File

@ -35,7 +35,7 @@ namespace osu.Game.GameModes.Menu
logo = new OsuLogo()
{
Alpha = 0,
Additive = true,
BlendingMode = BlendingMode.Additive,
Interactive = false,
Colour = Color4.DarkGray,
Ripple = false

View File

@ -83,7 +83,7 @@ namespace osu.Game.GameModes.Menu
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Additive = true,
BlendingMode = BlendingMode.Additive,
Alpha = 0.05f
}
}
@ -93,7 +93,7 @@ namespace osu.Game.GameModes.Menu
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = logo.Size,
Additive = true,
BlendingMode = BlendingMode.Additive,
Alpha = 0.2f,
}
}

View File

@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps.Objects;
using osu.Framework;
using System;
using System.Linq;
namespace osu.Game.GameModes.Play
{
@ -14,6 +15,10 @@ namespace osu.Game.GameModes.Play
{
public Action<HitObject> OnHit;
public Action<HitObject> OnMiss;
protected Playfield Playfield;
public IEnumerable<DrawableHitObject> DrawableObjects => Playfield.Children.Cast<DrawableHitObject>();
}
public abstract class HitRenderer<T> : HitRenderer
@ -31,8 +36,6 @@ namespace osu.Game.GameModes.Play
}
}
private Playfield playfield;
protected abstract Playfield CreatePlayfield();
protected abstract HitObjectConverter<T> Converter { get; }
@ -47,7 +50,7 @@ namespace osu.Game.GameModes.Play
Children = new Drawable[]
{
playfield = CreatePlayfield()
Playfield = CreatePlayfield()
};
loadObjects();
@ -65,7 +68,7 @@ namespace osu.Game.GameModes.Play
drawableObject.OnHit = onHit;
drawableObject.OnMiss = onMiss;
playfield.Add(drawableObject);
Playfield.Add(drawableObject);
}
}

View File

@ -12,26 +12,48 @@ namespace osu.Game.GameModes.Play.Osu
{
public class OsuPlayfield : Playfield
{
public OsuPlayfield()
protected override Container Content => hitObjectContainer;
private Container hitObjectContainer;
public override Vector2 Size
{
Size = new Vector2(512, 384);
Scale = new Vector2(1.6f);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
get
{
var parentSize = Parent.DrawSize;
var aspectSize = parentSize.X * 0.75f < parentSize.Y ? new Vector2(parentSize.X, parentSize.X * 0.75f) : new Vector2(parentSize.Y * 4f / 3f, parentSize.Y);
return new Vector2(aspectSize.X / parentSize.X, aspectSize.Y / parentSize.Y) * base.Size;
}
}
protected override void Load(BaseGame game)
public OsuPlayfield()
{
base.Load(game);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
RelativeSizeAxes = Axes.Both;
Size = new Vector2(0.75f);
Add(new Box()
AddInternal(new Box
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
Alpha = 0.5f
Alpha = 0.5f,
});
AddInternal(hitObjectContainer = new HitObjectContainer
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
});
}
class HitObjectContainer : Container
{
protected override Vector2 ChildScale => new Vector2(0.625f);
}
}
}

View File

@ -240,7 +240,10 @@ namespace osu.Game.GameModes.Play
beatmapSet = database.GetWithChildren<BeatmapSetInfo>(beatmapSet.BeatmapSetID);
beatmapSet.Beatmaps.ForEach(b => database.GetChildren(b));
beatmapSet.Beatmaps = beatmapSet.Beatmaps.OrderBy(b => b.BaseDifficulty.OverallDifficulty).ToList();
var group = new BeatmapGroup(beatmapSet) { SelectionChanged = selectionChanged };
var working = database.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault());
var group = new BeatmapGroup(beatmapSet, working) { SelectionChanged = selectionChanged };
group.Preload(Game, g =>
{

View File

@ -2,7 +2,6 @@
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Objects;
using osu.Game.GameModes.Backgrounds;
using osu.Game.GameModes.Play.Catch;
@ -12,13 +11,15 @@ using osu.Game.GameModes.Play.Taiko;
using osu.Framework;
using osu.Game.Database;
using osu.Framework.Timing;
using osu.Framework.GameModes;
using osu.Framework.Audio.Track;
using osu.Framework.Extensions.IEnumerableExtensions;
namespace osu.Game.GameModes.Play
{
public class Player : OsuGameMode
{
const bool autoplay = false;
protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4");
public BeatmapInfo BeatmapInfo;
@ -124,6 +125,9 @@ namespace osu.Game.GameModes.Play
hitRenderer.OnHit += delegate (HitObject h) { scoreOverlay.OnHit(h); };
hitRenderer.OnMiss += delegate (HitObject h) { scoreOverlay.OnMiss(h); };
if (autoplay)
hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Armed));
Children = new Drawable[]
{
hitRenderer,

View File

@ -10,7 +10,6 @@ using OpenTK.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework;
using System.Threading.Tasks;
using osu.Framework.Graphics.Textures;
namespace osu.Game.Graphics.Background
{
@ -27,8 +26,6 @@ namespace osu.Game.Graphics.Background
Depth = float.MinValue;
}
Texture texture;
protected override void Load(BaseGame game)
{
base.Load(game);

View File

@ -64,9 +64,21 @@ namespace osu.Game
//this completely overrides the framework default. will need to change once we make a proper FontStore.
Fonts = new TextureStore() { ScaleAdjust = 0.01f };
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Regular"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Regular"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-RegularItalic"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBold"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBoldItalic"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Bold"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BoldItalic"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Light"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-LightItalic"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Medium"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-MediumItalic"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Black"));
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BlackItalic"));
API = new APIAccess()
{

View File

@ -44,7 +44,7 @@ namespace osu.Game.Overlays
new ScrollContainer
{
RelativeSizeAxes = Axes.Both,
ScrollDraggerOnLeft = true,
ScrollDraggerAnchor = Anchor.TopLeft,
Children = new[]
{
new FlowContainer

View File

@ -66,7 +66,7 @@ namespace osu.Game.Overlays
HoverBackground = new Box
{
RelativeSizeAxes = Axes.Both,
Additive = true,
BlendingMode = BlendingMode.Additive,
Colour = new Color4(60, 60, 60, 255),
Alpha = 0,
},

View File

@ -66,6 +66,7 @@
<Compile Include="Overlays\DragBar.cs" />
<Compile Include="Overlays\MusicController.cs" />
<Compile Include="Beatmaps\Beatmap.cs" />
<Compile Include="Beatmaps\Formats\ConstructableBeatmapDecoder.cs" />
<Compile Include="Beatmaps\WorkingBeatmap.cs" />
<Compile Include="Beatmaps\Drawable\BeatmapSetHeader.cs" />
<Compile Include="Beatmaps\Drawable\DifficultyIcon.cs" />