mirror of
https://github.com/SK-la/Ez2Lazer.git
synced 2026-03-13 11:20:28 +00:00
修复mania皮肤,增加单列判定偏移器
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Ez2.Ez2HUD
|
||||
{
|
||||
public partial class EzColumnHitErrorMeter : HitErrorMeter
|
||||
{
|
||||
[SettingSource("Icon Height", "Icon Height")]
|
||||
public BindableNumber<float> IconHeight { get; } = new BindableNumber<float>(2)
|
||||
{
|
||||
MinValue = 1,
|
||||
MaxValue = 20,
|
||||
Precision = 1f,
|
||||
};
|
||||
|
||||
[SettingSource("Move Height", "Move Height")]
|
||||
public BindableNumber<float> MoveHeight { get; } = new BindableNumber<float>(10)
|
||||
{
|
||||
MinValue = 1,
|
||||
MaxValue = 50,
|
||||
Precision = 1f,
|
||||
};
|
||||
|
||||
[SettingSource("Background Alpha", "Background Alpha")]
|
||||
public BindableNumber<float> BackgroundAlpha { get; } = new BindableNumber<float>(0.2f)
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 1,
|
||||
Precision = 0.1f,
|
||||
};
|
||||
|
||||
private double[] floatingAverages = null!;
|
||||
private Box[] judgementMarkers = null!;
|
||||
private Container[] columns = null!;
|
||||
private float keyCount;
|
||||
|
||||
private OsuConfigManager config = null!;
|
||||
|
||||
[Resolved]
|
||||
private InputCountController controller { get; set; } = null!;
|
||||
|
||||
public EzColumnHitErrorMeter()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
this.config = config;
|
||||
recreateComponents();
|
||||
}
|
||||
|
||||
private void recreateComponents()
|
||||
{
|
||||
keyCount = controller.Triggers.Count;
|
||||
floatingAverages = new double[(int)keyCount];
|
||||
judgementMarkers = new Box[(int)keyCount];
|
||||
|
||||
InternalChild = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding(2),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(0, 0),
|
||||
Children = columns = Enumerable.Range(0, (int)keyCount).Select(index =>
|
||||
{
|
||||
var column = createColumn();
|
||||
var marker = new Box
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Width = (float)config.Get<double>(OsuSetting.ColumnWidth),
|
||||
Height = IconHeight.Value,
|
||||
Colour = Colour4.Gray,
|
||||
Alpha = 0.8f
|
||||
};
|
||||
column.Add(marker);
|
||||
judgementMarkers[index] = marker;
|
||||
return column;
|
||||
}).ToArray()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
controller.Triggers.BindCollectionChanged((_, __) => recreateComponents(), true);
|
||||
|
||||
// 更新标识块高度
|
||||
IconHeight.BindValueChanged(height =>
|
||||
{
|
||||
foreach (var marker in judgementMarkers)
|
||||
marker.Height = height.NewValue;
|
||||
}, true);
|
||||
|
||||
// 更新背景柱状列高度和标识块移动范围
|
||||
MoveHeight.BindValueChanged(height =>
|
||||
{
|
||||
foreach (var column in columns)
|
||||
{
|
||||
var backgroundBox = column.Children.OfType<Box>().FirstOrDefault();
|
||||
|
||||
if (backgroundBox != null)
|
||||
{
|
||||
backgroundBox.Height = height.NewValue;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var marker in judgementMarkers)
|
||||
{
|
||||
marker.Y = Math.Clamp(marker.Y, -height.NewValue / 2, height.NewValue / 2);
|
||||
// 重新计算标识块的相对位置
|
||||
float currentAbsoluteY = marker.Y * height.OldValue;
|
||||
float newRelativeY = currentAbsoluteY / height.NewValue;
|
||||
|
||||
marker.Y = newRelativeY;
|
||||
|
||||
// 更新标识块的移动范围
|
||||
marker.MoveToY(newRelativeY, 800, Easing.OutQuint);
|
||||
}
|
||||
|
||||
Invalidate(Invalidation.DrawSize);
|
||||
}, true);
|
||||
|
||||
// 更新背景透明度
|
||||
BackgroundAlpha.BindValueChanged(alpha =>
|
||||
{
|
||||
foreach (var column in columns)
|
||||
{
|
||||
var backgroundBox = column.Children.OfType<Box>().FirstOrDefault();
|
||||
if (backgroundBox != null)
|
||||
backgroundBox.Alpha = alpha.NewValue;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
private Container createColumn()
|
||||
{
|
||||
var backgroundBox = new Box
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Height = MoveHeight.Value,
|
||||
Width = (float)config.Get<double>(OsuSetting.ColumnWidth),
|
||||
Colour = Colour4.Gray,
|
||||
Alpha = 0.2f
|
||||
};
|
||||
|
||||
return new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
backgroundBox
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnNewJudgement(JudgementResult judgement)
|
||||
{
|
||||
if (!judgement.IsHit || !judgement.Type.IsScorable())
|
||||
return;
|
||||
|
||||
int columnIndex = getColumnIndex(judgement);
|
||||
if (columnIndex < 0 || columnIndex >= keyCount)
|
||||
return;
|
||||
|
||||
floatingAverages[columnIndex] = floatingAverages[columnIndex] * 0.9 + judgement.TimeOffset * 0.1;
|
||||
|
||||
const int marker_move_duration = 800;
|
||||
var marker = judgementMarkers[columnIndex];
|
||||
|
||||
float targetY = getRelativeJudgementPosition(floatingAverages[columnIndex]);
|
||||
|
||||
marker.Y = targetY;
|
||||
|
||||
marker.MoveToY(targetY, marker_move_duration, Easing.OutQuint);
|
||||
|
||||
marker.Colour = GetColourForHitResult(judgement.Type);
|
||||
}
|
||||
|
||||
private float getRelativeJudgementPosition(double value)
|
||||
{
|
||||
float moveRange = MoveHeight.Value;
|
||||
return (float)Math.Clamp((value / HitWindows.WindowFor(HitResult.Miss)) * moveRange, -moveRange, moveRange);
|
||||
}
|
||||
|
||||
private int getColumnIndex(JudgementResult judgement)
|
||||
{
|
||||
if (judgement.HitObject is IHasColumn hasColumn)
|
||||
return hasColumn.Column;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
foreach (var column in columns)
|
||||
{
|
||||
column.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -212,12 +212,23 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2.Ez2HUD
|
||||
resetDisappearTask();
|
||||
}
|
||||
|
||||
private bool hasTriggeredReset;
|
||||
|
||||
private bool shouldDisplayJudgement(AloneShowMenu aloneShowMenu, double timeOffset)
|
||||
{
|
||||
if (!hasTriggeredReset)
|
||||
{
|
||||
resetDisappearTask(); // 第一次判定时触发任务
|
||||
hasTriggeredReset = true;
|
||||
}
|
||||
|
||||
if (timeOffset == 0)
|
||||
return true;
|
||||
|
||||
if (Math.Abs(timeOffset) < Threshold.Value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return aloneShowMenu switch
|
||||
{
|
||||
|
||||
@@ -23,9 +23,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
{
|
||||
private readonly ManiaBeatmap beatmap;
|
||||
|
||||
// private readonly Bindable<float> columnWidth = new Bindable<float>(50);
|
||||
// private readonly Bindable<float> specialFactor = new Bindable<float>(1);
|
||||
|
||||
private readonly OsuConfigManager config;
|
||||
// private readonly ManiaRulesetConfigManager config;
|
||||
|
||||
@@ -38,14 +35,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
this.config = config ?? throw new ArgumentNullException(nameof(config));
|
||||
}
|
||||
|
||||
// [BackgroundDependencyLoader]
|
||||
// private void load(ManiaRulesetConfigManager config)
|
||||
// {
|
||||
// // 将配置中的绑定值转换后绑定到我们自己的绑定变量上
|
||||
// // 假设你的 ManiaRulesetConfigManager 提供了一个 GetBindable<double> 方法:
|
||||
// columnWidth.BindTo(config.GetBindable<double>(ManiaRulesetSetting.ColumnWidth).ConvertToFloatBindable());
|
||||
// }
|
||||
|
||||
// public ManiaEz2SkinTransformer(ISkin skin, IBeatmap beatmap)
|
||||
// : base(skin)
|
||||
// {
|
||||
@@ -61,12 +50,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
// }
|
||||
// }
|
||||
|
||||
// private void calculateColumnWidth(int columnIndex, StageDefinition stage)
|
||||
// {
|
||||
// bool isSpecialColumn = stage.IsSpecialColumn(columnIndex);
|
||||
// width = (float)(46 * (isSpecialColumn ? 1.2 : 1));
|
||||
// }
|
||||
|
||||
public override Drawable? GetDrawableComponent(ISkinComponentLookup lookup)
|
||||
{
|
||||
switch (lookup)
|
||||
@@ -145,6 +128,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
keyCounter.Position = new Vector2(0, -Stage.HIT_TARGET_POSITION - stage_padding_bottom);
|
||||
}
|
||||
|
||||
var columnHitErrorMeter = container.OfType<EzColumnHitErrorMeter>().FirstOrDefault();
|
||||
|
||||
if (columnHitErrorMeter != null)
|
||||
{
|
||||
columnHitErrorMeter.Anchor = Anchor.Centre;
|
||||
columnHitErrorMeter.Origin = Anchor.Centre;
|
||||
columnHitErrorMeter.Position = new Vector2(0, 20);
|
||||
}
|
||||
|
||||
var hitErrorMeter = container.OfType<BarHitErrorMeter>().FirstOrDefault();
|
||||
|
||||
if (hitErrorMeter != null)
|
||||
@@ -175,7 +167,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
new EzComComboCounter(),
|
||||
new EzComComboCounter(),
|
||||
new EzComKeyCounterDisplay(),
|
||||
// new ArgonKeyCounterDisplay(),
|
||||
new EzColumnHitErrorMeter(),
|
||||
new BarHitErrorMeter(),
|
||||
new EzComHitResultScore(),
|
||||
new EzComHitTiming(),
|
||||
|
||||
@@ -1277,12 +1277,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
AddStep("set filter text", () => songSelect!.FilterControl.ChildrenOfType<FilterControl.FilterControlTextBox>().First().Text = "nonono");
|
||||
AddStep("select all", () => InputManager.Keys(PlatformAction.SelectAll));
|
||||
AddStep("press ctrl-x", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ControlLeft);
|
||||
InputManager.Key(Key.X);
|
||||
InputManager.ReleaseKey(Key.ControlLeft);
|
||||
});
|
||||
AddStep("press ctrl/cmd-x", () => InputManager.Keys(PlatformAction.Cut));
|
||||
|
||||
AddAssert("filter text cleared", () => songSelect!.FilterControl.ChildrenOfType<FilterControl.FilterControlTextBox>().First().Text, () => Is.Empty);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Configuration;
|
||||
@@ -190,7 +189,10 @@ namespace osu.Game.Configuration
|
||||
SetDefault(OsuSetting.ScalingPositionX, 0.5f, 0f, 1f, 0.01f);
|
||||
SetDefault(OsuSetting.ScalingPositionY, 0.5f, 0f, 1f, 0.01f);
|
||||
|
||||
SetDefault(OsuSetting.UIScale, 1f, 0.8f, 1.6f, 0.01f);
|
||||
if (RuntimeInfo.IsMobile)
|
||||
SetDefault(OsuSetting.UIScale, 1f, 0.8f, 1.1f, 0.01f);
|
||||
else
|
||||
SetDefault(OsuSetting.UIScale, 1f, 0.8f, 1.6f, 0.01f);
|
||||
|
||||
SetDefault(OsuSetting.UIHoldActivationDelay, 200.0, 0.0, 500.0, 50.0);
|
||||
|
||||
@@ -273,10 +275,6 @@ namespace osu.Game.Configuration
|
||||
|
||||
public override TrackedSettings CreateTrackedSettings()
|
||||
{
|
||||
// these need to be assigned in normal game startup scenarios.
|
||||
Debug.Assert(LookupKeyBindings != null);
|
||||
Debug.Assert(LookupSkinName != null);
|
||||
|
||||
return new TrackedSettings
|
||||
{
|
||||
new TrackedSetting<bool>(OsuSetting.ShowFpsDisplay, state => new SettingDescription(
|
||||
@@ -421,6 +419,7 @@ namespace osu.Game.Configuration
|
||||
IncreaseFirstObjectVisibility,
|
||||
ScoreDisplayMode,
|
||||
SelectEzMode,
|
||||
SelectManiaRulesetSubset,
|
||||
ScalingGameMode,
|
||||
ColumnWidth,
|
||||
SpecialFactor,
|
||||
@@ -469,6 +468,7 @@ namespace osu.Game.Configuration
|
||||
/// The status for the current user to broadcast to other players.
|
||||
/// </summary>
|
||||
UserOnlineStatus,
|
||||
|
||||
MultiplayerRoomFilter,
|
||||
HideCountryFlags,
|
||||
EditorTimelineShowTimingChanges,
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK;
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Overlays.Music
|
||||
{
|
||||
public partial class FilterControl : Container
|
||||
{
|
||||
public Action<FilterCriteria> FilterChanged;
|
||||
|
||||
public readonly FilterTextBox Search;
|
||||
private readonly NowPlayingCollectionDropdown collectionDropdown;
|
||||
|
||||
public FilterControl()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(0f, 10f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Search = new FilterTextBox
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 40,
|
||||
},
|
||||
collectionDropdown = new NowPlayingCollectionDropdown { RelativeSizeAxes = Axes.X }
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Search.Current.BindValueChanged(_ => updateCriteria());
|
||||
collectionDropdown.Current.BindValueChanged(_ => updateCriteria(), true);
|
||||
}
|
||||
|
||||
private void updateCriteria() => FilterChanged?.Invoke(createCriteria());
|
||||
|
||||
private FilterCriteria createCriteria() => new FilterCriteria
|
||||
{
|
||||
SearchText = Search.Current.Value,
|
||||
Collection = collectionDropdown.Current.Value?.Collection
|
||||
};
|
||||
|
||||
public partial class FilterTextBox : BasicSearchTextBox
|
||||
{
|
||||
protected override bool AllowCommit => true;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
|
||||
BackgroundUnfocused = OsuColour.Gray(0.06f);
|
||||
BackgroundFocused = OsuColour.Gray(0.12f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using osu.Game.Collections;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Overlays.Music
|
||||
{
|
||||
public class FilterCriteria
|
||||
{
|
||||
/// <summary>
|
||||
/// The search text.
|
||||
/// </summary>
|
||||
public string SearchText;
|
||||
|
||||
/// <summary>
|
||||
/// The collection to filter beatmaps from.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public Live<BeatmapCollection> Collection;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,5 @@ namespace osu.Game.Rulesets.Mods
|
||||
new DifficultyRange(HitResult.Meh, 151, 136, 121),
|
||||
new DifficultyRange(HitResult.Miss, 188, 173, 158),
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,17 +66,17 @@ namespace osu.Game.Storyboards.Drawables
|
||||
|
||||
Size = new Vector2(640, 480);
|
||||
|
||||
bool onlyHasVideoElements = Storyboard.Layers.SelectMany(l => l.Elements).All(e => e is StoryboardVideo);
|
||||
// 动态计算视频的宽高比
|
||||
bool hasVideoElement = Storyboard.Layers.SelectMany(l => l.Elements).All(e => e is StoryboardVideo);
|
||||
|
||||
// 如果只有视频元素,动态调整宽高
|
||||
if (onlyHasVideoElements)
|
||||
if (hasVideoElement)
|
||||
{
|
||||
Size = Vector2.One; // 填满窗口
|
||||
FillMode = FillMode.Fit; // 保持比例
|
||||
}
|
||||
else
|
||||
{
|
||||
Height = Width * (storyboard.Beatmap.WidescreenStoryboard ? 9 / 16f : 3 / 4f);
|
||||
Width = Height * (storyboard.Beatmap.WidescreenStoryboard ? 16 / 9f : 4 / 3f);
|
||||
}
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
@@ -117,14 +117,33 @@ namespace osu.Game.Storyboards.Drawables
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
// 动态计算视频的宽高比
|
||||
if (Storyboard.Layers.SelectMany(l => l.Elements).FirstOrDefault() is StoryboardVideo videoElement)
|
||||
{
|
||||
if (videoElement.CreateDrawable() is DrawableStoryboardVideo drawableVideo)
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
FillAspectRatio = drawableVideo.DrawSize.X / drawableVideo.DrawSize.Y;
|
||||
if (Parent != null)
|
||||
{
|
||||
float windowAspectRatio = Parent.DrawWidth / Parent.DrawHeight;
|
||||
float videoAspectRatio = drawableVideo.DrawSize.X / drawableVideo.DrawSize.Y;
|
||||
|
||||
if (windowAspectRatio > videoAspectRatio)
|
||||
{
|
||||
// 窗口更高,以宽度为基准调整高度
|
||||
Width = Parent.DrawWidth;
|
||||
Height = Width / videoAspectRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 窗口更宽,以高度为基准调整宽度
|
||||
Height = Parent.DrawHeight;
|
||||
Width = Height * videoAspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user