Merge branch 'master' into taiko-fixes

This commit is contained in:
Dan Balasescu
2017-04-06 16:23:22 +09:00
committed by GitHub
36 changed files with 660 additions and 568 deletions

View File

@ -7,11 +7,11 @@ using osu.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Game.Beatmaps.Samples;
using osu.Game.Modes.Judgements;
using Container = osu.Framework.Graphics.Containers.Container;
using osu.Game.Modes.Objects.Types;
using OpenTK.Graphics;
using osu.Game.Audio;
namespace osu.Game.Modes.Objects.Drawables
{
@ -45,15 +45,15 @@ namespace osu.Game.Modes.Objects.Drawables
UpdateState(state);
if (State == ArmedState.Hit)
PlaySample();
PlaySamples();
}
}
protected SampleChannel Sample;
protected List<SampleChannel> Samples = new List<SampleChannel>();
protected virtual void PlaySample()
protected void PlaySamples()
{
Sample?.Play();
Samples.ForEach(s => s?.Play());
}
[BackgroundDependencyLoader]
@ -156,13 +156,16 @@ namespace osu.Game.Modes.Objects.Drawables
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
SampleType type = HitObject.Sample?.Type ?? SampleType.None;
if (type == SampleType.None)
type = SampleType.Normal;
foreach (SampleInfo sample in HitObject.Samples)
{
SampleChannel channel = audio.Sample.Get($@"Gameplay/{sample.Bank}-{sample.Name}");
SampleSet sampleSet = HitObject.Sample?.Set ?? SampleSet.Normal;
if (channel == null)
continue;
Sample = audio.Sample.Get($@"Gameplay/{sampleSet.ToString().ToLower()}-hit{type.ToString().ToLower()}");
channel.Volume.Value = sample.Volume;
Samples.Add(channel);
}
}
private List<DrawableHitObject<TObject, TJudgement>> nestedHitObjects;

View File

@ -1,9 +1,10 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps.Samples;
using osu.Game.Audio;
using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
using System.Collections.Generic;
namespace osu.Game.Modes.Objects
{
@ -21,15 +22,31 @@ namespace osu.Game.Modes.Objects
public double StartTime { get; set; }
/// <summary>
/// The sample to be played when this HitObject is hit.
/// The samples to be played when this hit object is hit.
/// </summary>
public HitSampleInfo Sample { get; set; }
public List<SampleInfo> Samples = new List<SampleInfo>();
/// <summary>
/// Applies default values to this HitObject.
/// </summary>
/// <param name="difficulty">The difficulty settings to use.</param>
/// <param name="timing">The timing settings to use.</param>
public virtual void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) { }
public virtual void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty)
{
ControlPoint overridePoint;
ControlPoint timingPoint = timing.TimingPointAt(StartTime, out overridePoint);
foreach (var sample in Samples)
{
if (sample.Volume == 0)
sample.Volume = (overridePoint ?? timingPoint)?.SampleVolume ?? 0;
// If the bank is not assigned a name, assign it from the control point
if (!string.IsNullOrEmpty(sample.Bank))
continue;
sample.Bank = (overridePoint ?? timingPoint)?.SampleBank ?? @"normal";
}
}
}
}

View File

@ -2,12 +2,13 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Game.Beatmaps.Samples;
using osu.Game.Modes.Objects.Types;
using System;
using System.Collections.Generic;
using System.Globalization;
using osu.Game.Modes.Objects.Legacy;
using osu.Game.Beatmaps.Formats;
using osu.Game.Audio;
namespace osu.Game.Modes.Objects
{
@ -20,6 +21,10 @@ namespace osu.Game.Modes.Objects
bool combo = type.HasFlag(LegacyHitObjectType.NewCombo);
type &= ~LegacyHitObjectType.NewCombo;
int sampleVolume = 0;
string normalSampleBank = null;
string addSampleBank = null;
HitObject result;
if ((type & LegacyHitObjectType.Circle) > 0)
@ -29,6 +34,9 @@ namespace osu.Game.Modes.Objects
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
NewCombo = combo
};
if (split.Length > 5)
readCustomSampleBanks(split[5], ref normalSampleBank, ref addSampleBank, ref sampleVolume);
}
else if ((type & LegacyHitObjectType.Slider) > 0)
{
@ -84,6 +92,9 @@ namespace osu.Game.Modes.Objects
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
NewCombo = combo
};
if (split.Length > 10)
readCustomSampleBanks(split[10], ref normalSampleBank, ref addSampleBank, ref sampleVolume);
}
else if ((type & LegacyHitObjectType.Spinner) > 0)
{
@ -91,10 +102,17 @@ namespace osu.Game.Modes.Objects
{
EndTime = Convert.ToDouble(split[5], CultureInfo.InvariantCulture)
};
if (split.Length > 6)
readCustomSampleBanks(split[6], ref normalSampleBank, ref addSampleBank, ref sampleVolume);
}
else if ((type & LegacyHitObjectType.Hold) > 0)
{
// Note: Hold is generated by BMS converts
// Todo: Apparently end time is determined by samples??
// Shouldn't need implementation until mania
result = new LegacyHold
{
Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])),
@ -105,15 +123,82 @@ namespace osu.Game.Modes.Objects
throw new InvalidOperationException($@"Unknown hit object type {type}");
result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture);
result.Sample = new HitSampleInfo
{
Type = (SampleType)int.Parse(split[4]),
Set = SampleSet.Soft,
};
// TODO: "addition" field
var soundType = (LegacySoundType)int.Parse(split[4]);
result.Samples.Add(new SampleInfo
{
Bank = normalSampleBank,
Name = SampleInfo.HIT_NORMAL,
Volume = sampleVolume
});
if ((soundType & LegacySoundType.Finish) > 0)
{
result.Samples.Add(new SampleInfo
{
Bank = addSampleBank,
Name = SampleInfo.HIT_FINISH,
Volume = sampleVolume
});
}
if ((soundType & LegacySoundType.Whistle) > 0)
{
result.Samples.Add(new SampleInfo
{
Bank = addSampleBank,
Name = SampleInfo.HIT_WHISTLE,
Volume = sampleVolume
});
}
if ((soundType & LegacySoundType.Clap) > 0)
{
result.Samples.Add(new SampleInfo
{
Bank = addSampleBank,
Name = SampleInfo.HIT_CLAP,
Volume = sampleVolume
});
}
return result;
}
private void readCustomSampleBanks(string str, ref string normalSampleBank, ref string addSampleBank, ref int sampleVolume)
{
if (string.IsNullOrEmpty(str))
return;
string[] split = str.Split(':');
var bank = (OsuLegacyDecoder.LegacySampleBank)Convert.ToInt32(split[0]);
var addbank = (OsuLegacyDecoder.LegacySampleBank)Convert.ToInt32(split[1]);
// Let's not implement this for now, because this doesn't fit nicely into the bank structure
//string sampleFile = split2.Length > 4 ? split2[4] : string.Empty;
string stringBank = bank.ToString().ToLower();
if (stringBank == @"none")
stringBank = null;
string stringAddBank = addbank.ToString().ToLower();
if (stringAddBank == @"none")
stringAddBank = null;
normalSampleBank = stringBank;
addSampleBank = stringAddBank;
sampleVolume = split.Length > 3 ? int.Parse(split[3]) : 0;
}
[Flags]
private enum LegacySoundType
{
None = 0,
Normal = 1,
Whistle = 2,
Finish = 4,
Clap = 8
}
}
}

View File

@ -9,11 +9,18 @@ using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Play;
using osu.Game.Modes.Scoring;
using osu.Framework.Input;
using OpenTK.Input;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
namespace osu.Game.Modes.UI
{
public abstract class HudOverlay : Container
{
private const int duration = 100;
private readonly Container content;
public readonly KeyCounterCollection KeyCounter;
public readonly ComboCounter ComboCounter;
public readonly ScoreCounter ScoreCounter;
@ -21,6 +28,9 @@ namespace osu.Game.Modes.UI
public readonly HealthDisplay HealthDisplay;
private Bindable<bool> showKeyCounter;
private Bindable<bool> showHud;
private static bool hasShownNotificationOnce;
protected abstract KeyCounterCollection CreateKeyCounter();
protected abstract ComboCounter CreateComboCounter();
@ -32,28 +42,53 @@ namespace osu.Game.Modes.UI
{
RelativeSizeAxes = Axes.Both;
Children = new Drawable[]
Add(content = new Container
{
KeyCounter = CreateKeyCounter(),
ComboCounter = CreateComboCounter(),
ScoreCounter = CreateScoreCounter(),
AccuracyCounter = CreateAccuracyCounter(),
HealthDisplay = CreateHealthDisplay(),
};
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
KeyCounter = CreateKeyCounter(),
ComboCounter = CreateComboCounter(),
ScoreCounter = CreateScoreCounter(),
AccuracyCounter = CreateAccuracyCounter(),
HealthDisplay = CreateHealthDisplay(),
}
});
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
[BackgroundDependencyLoader(true)]
private void load(OsuConfigManager config, NotificationManager notificationManager)
{
showKeyCounter = config.GetBindable<bool>(OsuConfig.KeyOverlay);
showKeyCounter.ValueChanged += visibility =>
showKeyCounter.ValueChanged += keyCounterVisibility =>
{
if (visibility)
KeyCounter.Show();
if (keyCounterVisibility)
KeyCounter.FadeIn(duration);
else
KeyCounter.Hide();
KeyCounter.FadeOut(duration);
};
showKeyCounter.TriggerChange();
showHud = config.GetBindable<bool>(OsuConfig.ShowInterface);
showHud.ValueChanged += hudVisibility =>
{
if (hudVisibility)
content.FadeIn(duration);
else
content.FadeOut(duration);
};
showHud.TriggerChange();
if (!showHud && !hasShownNotificationOnce)
{
hasShownNotificationOnce = true;
notificationManager?.Post(new SimpleNotification
{
Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab."
});
}
}
public void BindProcessor(ScoreProcessor processor)
@ -68,5 +103,22 @@ namespace osu.Game.Modes.UI
{
hitRenderer.InputManager.Add(KeyCounter.GetReceptor());
}
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{
if (args.Repeat) return false;
if (state.Keyboard.ShiftPressed)
{
switch (args.Key)
{
case Key.Tab:
showHud.Value = !showHud.Value;
return true;
}
}
return base.OnKeyDown(state, args);
}
}
}