mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 15:16:38 +09:00
Merge remote-tracking branch 'origin/master' into add-scroll-speed-keybinds
# Conflicts: # osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs
This commit is contained in:
@ -11,8 +11,8 @@ namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
public class HitObjectContainer : CompositeDrawable
|
||||
{
|
||||
public virtual IEnumerable<DrawableHitObject> Objects => InternalChildren.Cast<DrawableHitObject>();
|
||||
public virtual IEnumerable<DrawableHitObject> AliveObjects => AliveInternalChildren.Cast<DrawableHitObject>();
|
||||
public IEnumerable<DrawableHitObject> Objects => InternalChildren.Cast<DrawableHitObject>().OrderBy(h => h.HitObject.StartTime);
|
||||
public IEnumerable<DrawableHitObject> AliveObjects => AliveInternalChildren.Cast<DrawableHitObject>().OrderBy(h => h.HitObject.StartTime);
|
||||
|
||||
public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject);
|
||||
public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject);
|
||||
|
@ -57,6 +57,7 @@ namespace osu.Game.Rulesets.UI
|
||||
public abstract IEnumerable<HitObject> Objects { get; }
|
||||
|
||||
private readonly Lazy<Playfield> playfield;
|
||||
|
||||
/// <summary>
|
||||
/// The playfield.
|
||||
/// </summary>
|
||||
@ -72,11 +73,6 @@ namespace osu.Game.Rulesets.UI
|
||||
private IRulesetConfigManager rulesetConfig;
|
||||
private OnScreenDisplay onScreenDisplay;
|
||||
|
||||
private DependencyContainer dependencies;
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
||||
=> dependencies = new DependencyContainer(base.CreateLocalDependencies(parent));
|
||||
|
||||
/// <summary>
|
||||
/// A visual representation of a <see cref="Rulesets.Ruleset"/>.
|
||||
/// </summary>
|
||||
@ -89,18 +85,20 @@ namespace osu.Game.Rulesets.UI
|
||||
Cursor = CreateCursor();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OnScreenDisplay onScreenDisplay, SettingsStore settings)
|
||||
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
this.onScreenDisplay = onScreenDisplay;
|
||||
var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent));
|
||||
|
||||
rulesetConfig = CreateConfig(Ruleset, settings);
|
||||
onScreenDisplay = dependencies.Get<OnScreenDisplay>();
|
||||
|
||||
rulesetConfig = dependencies.Get<RulesetConfigCache>().GetConfigFor(Ruleset);
|
||||
if (rulesetConfig != null)
|
||||
{
|
||||
dependencies.Cache(rulesetConfig);
|
||||
onScreenDisplay?.BeginTracking(this, rulesetConfig);
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public abstract ScoreProcessor CreateScoreProcessor();
|
||||
@ -130,14 +128,11 @@ namespace osu.Game.Rulesets.UI
|
||||
HasReplayLoaded.Value = ReplayInputManager.ReplayInputHandler != null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates the cursor. May be null if the <see cref="RulesetContainer"/> doesn't provide a custom cursor.
|
||||
/// </summary>
|
||||
protected virtual CursorContainer CreateCursor() => null;
|
||||
|
||||
protected virtual IRulesetConfigManager CreateConfig(Ruleset ruleset, SettingsStore settings) => null;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Playfield.
|
||||
/// </summary>
|
||||
@ -160,7 +155,7 @@ namespace osu.Game.Rulesets.UI
|
||||
/// RulesetContainer that applies conversion to Beatmaps. Does not contain a Playfield
|
||||
/// and does not load drawable hit objects.
|
||||
/// <para>
|
||||
/// Should not be derived - derive <see cref="RulesetContainer{TObject}"/> instead.
|
||||
/// Should not be derived - derive <see cref="RulesetContainer{TPlayfield, TObject}"/> instead.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">The type of HitObject contained by this RulesetContainer.</typeparam>
|
||||
@ -194,6 +189,7 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
private Container content;
|
||||
private IEnumerable<Mod> mods;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to assume the beatmap passed into this <see cref="RulesetContainer{TObject}"/> is for the current ruleset.
|
||||
@ -216,13 +212,10 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
KeyBindingInputManager = CreateInputManager();
|
||||
KeyBindingInputManager.RelativeSizeAxes = Axes.Both;
|
||||
|
||||
// Add mods, should always be the last thing applied to give full control to mods
|
||||
applyMods(Mods);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
KeyBindingInputManager.Add(content = new Container
|
||||
{
|
||||
@ -235,6 +228,9 @@ namespace osu.Game.Rulesets.UI
|
||||
if (Cursor != null)
|
||||
KeyBindingInputManager.Add(Cursor);
|
||||
|
||||
// Apply mods
|
||||
applyMods(Mods, config);
|
||||
|
||||
loadObjects();
|
||||
}
|
||||
|
||||
@ -242,13 +238,16 @@ namespace osu.Game.Rulesets.UI
|
||||
/// Applies the active mods to this RulesetContainer.
|
||||
/// </summary>
|
||||
/// <param name="mods"></param>
|
||||
private void applyMods(IEnumerable<Mod> mods)
|
||||
private void applyMods(IEnumerable<Mod> mods, OsuConfigManager config)
|
||||
{
|
||||
if (mods == null)
|
||||
return;
|
||||
|
||||
foreach (var mod in mods.OfType<IApplicableToRulesetContainer<TObject>>())
|
||||
mod.ApplyToRulesetContainer(this);
|
||||
|
||||
foreach (var mod in mods.OfType<IReadFromConfig>())
|
||||
mod.ReadFromConfig(config);
|
||||
}
|
||||
|
||||
public override void SetReplay(Replay replay)
|
||||
|
@ -15,6 +15,7 @@ using osu.Game.Input.Bindings;
|
||||
using osu.Game.Input.Handlers;
|
||||
using osu.Game.Screens.Play;
|
||||
using OpenTK.Input;
|
||||
using static osu.Game.Input.Handlers.ReplayInputHandler;
|
||||
|
||||
namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
@ -29,26 +30,43 @@ namespace osu.Game.Rulesets.UI
|
||||
}
|
||||
}
|
||||
|
||||
protected override InputState CreateInitialState()
|
||||
{
|
||||
var state = base.CreateInitialState();
|
||||
return new RulesetInputManagerInputState<T>
|
||||
{
|
||||
Mouse = state.Mouse,
|
||||
Keyboard = state.Keyboard,
|
||||
Joystick = state.Joystick,
|
||||
LastReplayState = null
|
||||
};
|
||||
}
|
||||
|
||||
protected readonly KeyBindingContainer<T> KeyBindingContainer;
|
||||
|
||||
protected override Container<Drawable> Content => KeyBindingContainer;
|
||||
|
||||
protected RulesetInputManager(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique)
|
||||
{
|
||||
InternalChild = KeyBindingContainer = new RulesetKeyBindingContainer(ruleset, variant, unique);
|
||||
InternalChild = KeyBindingContainer = CreateKeyBindingContainer(ruleset, variant, unique);
|
||||
}
|
||||
|
||||
#region Action mapping (for replays)
|
||||
|
||||
private List<T> lastPressedActions = new List<T>();
|
||||
|
||||
protected override void HandleNewState(InputState state)
|
||||
public override void HandleCustomInput(InputState state, IInput input)
|
||||
{
|
||||
base.HandleNewState(state);
|
||||
if (!(input is ReplayState<T> replayState))
|
||||
{
|
||||
base.HandleCustomInput(state, input);
|
||||
return;
|
||||
}
|
||||
|
||||
var replayState = state as ReplayInputHandler.ReplayState<T>;
|
||||
|
||||
if (replayState == null) return;
|
||||
if (state is RulesetInputManagerInputState<T> inputState)
|
||||
{
|
||||
inputState.LastReplayState = replayState;
|
||||
}
|
||||
|
||||
// Here we handle states specifically coming from a replay source.
|
||||
// These have extra action information rather than keyboard keys or mouse buttons.
|
||||
@ -80,7 +98,7 @@ namespace osu.Game.Rulesets.UI
|
||||
if (replayInputHandler != null) RemoveHandler(replayInputHandler);
|
||||
|
||||
replayInputHandler = value;
|
||||
UseParentState = replayInputHandler == null;
|
||||
UseParentInput = replayInputHandler == null;
|
||||
|
||||
if (replayInputHandler != null)
|
||||
AddHandler(replayInputHandler);
|
||||
@ -123,7 +141,7 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate && validState;
|
||||
|
||||
private bool isAttached => replayInputHandler != null && !UseParentState;
|
||||
private bool isAttached => replayInputHandler != null && !UseParentInput;
|
||||
|
||||
private const int max_catch_up_updates_per_frame = 50;
|
||||
|
||||
@ -249,6 +267,9 @@ namespace osu.Game.Rulesets.UI
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected virtual RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique)
|
||||
=> new RulesetKeyBindingContainer(ruleset, variant, unique);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -267,4 +288,10 @@ namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
void Attach(KeyCounterCollection keyCounter);
|
||||
}
|
||||
|
||||
public class RulesetInputManagerInputState<T> : InputState
|
||||
where T : struct
|
||||
{
|
||||
public ReplayState<T> LastReplayState;
|
||||
}
|
||||
}
|
||||
|
@ -29,17 +29,16 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
/// </summary>
|
||||
protected readonly SortedList<MultiplierControlPoint> ControlPoints = new SortedList<MultiplierControlPoint>();
|
||||
|
||||
private readonly ScrollingDirection direction;
|
||||
public readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Cached initialStateCache = new Cached();
|
||||
|
||||
public ScrollingHitObjectContainer(ScrollingDirection direction)
|
||||
public ScrollingHitObjectContainer()
|
||||
{
|
||||
this.direction = direction;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
TimeRange.ValueChanged += v => initialStateCache.Invalidate();
|
||||
TimeRange.ValueChanged += _ => initialStateCache.Invalidate();
|
||||
Direction.ValueChanged += _ => initialStateCache.Invalidate();
|
||||
}
|
||||
|
||||
private ISpeedChangeVisualiser speedChangeVisualiser;
|
||||
@ -100,7 +99,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
|
||||
if (!initialStateCache.IsValid)
|
||||
{
|
||||
speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize);
|
||||
speedChangeVisualiser.ComputeInitialStates(Objects, Direction, TimeRange, DrawSize);
|
||||
initialStateCache.Validate();
|
||||
}
|
||||
}
|
||||
@ -110,7 +109,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
base.UpdateAfterChildrenLife();
|
||||
|
||||
// We need to calculate this as soon as possible after lifetimes so that hitobjects get the final say in their positions
|
||||
speedChangeVisualiser.UpdatePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize);
|
||||
speedChangeVisualiser.UpdatePositions(AliveObjects, Direction, Time.Current, TimeRange, DrawSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
/// <summary>
|
||||
/// The step increase/decrease of the span of time visible by the length of the scrolling axes.
|
||||
/// </summary>
|
||||
private const double time_span_step = 50;
|
||||
private const double time_span_step = 200;
|
||||
|
||||
/// <summary>
|
||||
/// The span of time that is visible by the length of the scrolling axes.
|
||||
@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
/// </summary>
|
||||
public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects;
|
||||
|
||||
private readonly ScrollingDirection direction;
|
||||
protected readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ScrollingPlayfield"/>.
|
||||
@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null, float? customHeight = null)
|
||||
: base(customWidth, customHeight)
|
||||
{
|
||||
this.direction = direction;
|
||||
Direction.Value = direction;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -81,8 +81,6 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
HitObjects.TimeRange.BindTo(VisibleTimeRange);
|
||||
}
|
||||
|
||||
protected sealed override HitObjectContainer CreateHitObjectContainer() => new ScrollingHitObjectContainer(direction);
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
{
|
||||
if (!UserScrollSpeedAdjustment)
|
||||
@ -102,5 +100,12 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
}
|
||||
|
||||
public bool OnReleased(GlobalAction action) => false;
|
||||
|
||||
protected sealed override HitObjectContainer CreateHitObjectContainer()
|
||||
{
|
||||
var container = new ScrollingHitObjectContainer();
|
||||
container.Direction.BindTo(Direction);
|
||||
return container;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,9 @@ namespace osu.Game.Rulesets.UI.Scrolling.Visualisers
|
||||
/// <returns>A positive value indicating the position at <paramref name="time"/>.</returns>
|
||||
private double positionAt(double time, double timeRange)
|
||||
{
|
||||
if (controlPoints.Count == 0)
|
||||
return time / timeRange;
|
||||
|
||||
double length = 0;
|
||||
|
||||
// We need to consider all timing points until the specified time and not just the currently-active one,
|
||||
|
Reference in New Issue
Block a user