修改工厂增加大纹理商店

This commit is contained in:
LA
2025-11-11 22:04:33 +08:00
parent 6870ce47f0
commit 24a6617b30
6 changed files with 106 additions and 105 deletions

1
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1 @@
{}

View File

@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
@@ -34,6 +35,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
[Resolved]
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
private Bindable<string> stageName = null!;
private Bindable<double> hitPositonBindable = null!;
public EzKeyArea()
{
RelativeSizeAxes = Axes.Both;
@@ -42,11 +46,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
[BackgroundDependencyLoader]
private void load()
{
stageName = ezSkinConfig.GetBindable<string>(EzSkinSetting.StageName);
hitPositonBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
}
protected override void LoadComplete()
{
base.LoadComplete();
stageName.BindValueChanged(_ => OnSkinChanged());
hitPositonBindable.BindValueChanged(_ => OnConfigChanged());
OnSkinChanged();
}
@@ -73,16 +81,16 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
{
ClearInternal();
upSprite = factory.CreateStage("keybase");
downSprite = factory.CreateStage("keypress");
upSprite = factory.CreateStageKeys("keybase");
downSprite = factory.CreateStageKeys("keypress");
downSprite.Alpha = 0;
container = new Container
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
RelativeSizeAxes = Axes.Both,
Y = (float)hitPositonBindable.Value + 4,
Children = new[]
{
upSprite,
@@ -96,6 +104,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
private void OnConfigChanged()
{
container.Y = (float)hitPositonBindable.Value + 4;
}
private void OnSkinChanged() => loadAnimation();

View File

@@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
[Resolved]
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
private Bindable<string> stageName = null!;
[BackgroundDependencyLoader]
private void load()
{
@@ -35,6 +37,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
hitPositon = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
columnWidth = ezSkinConfig.GetBindable<double>(EzSkinSetting.ColumnWidth);
stageName = ezSkinConfig.GetBindable<string>(EzSkinSetting.StageName);
hitPositon.BindValueChanged(_ => updateSizes());
columnWidth.BindValueChanged(_ => updateSizes());
OnSkinChanged();
@@ -43,13 +46,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
protected override void LoadComplete()
{
base.LoadComplete();
stageName.BindValueChanged(_ => OnSkinChanged());
}
// protected override void Update()
// {
// base.Update();
// updateSizes();
// }
protected override void Update()
{
base.Update();
updateSizes();
}
private void OnSkinChanged()
{
@@ -65,7 +69,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
Child = stageBottom
};
// sprite.Depth = float.MinValue;
AddInternal(sprite);
AddInternal(sprite); // 注释掉以隐藏stage
Schedule(updateSizes);
}

View File

@@ -288,7 +288,7 @@ namespace osu.Game
dependencies.Cache(
NoteFactory = new EzLocalTextureFactory(
EzSkinSettingsManager,
new TextureStore(Host.Renderer),
Host.Renderer,
Storage));
dependencies.Cache(realm = new RealmAccess(Storage, CLIENT_DATABASE_FILENAME, Host.UpdateThread));
@@ -452,7 +452,7 @@ namespace osu.Game
LocalConfig.LookupKeyBindings = l => KeyBindingStore.GetBindingsStringFor(l);
// 添加自动背景捕获组件,启用亚克力效果
base.Content.Add(new osu.Framework.Graphics.Containers.AutoBackgroundCapture());
// base.Content.Add(new AutoBackgroundCapture());
}
private void updateLanguage() => CurrentLanguage.Value = LanguageExtensions.GetLanguageFor(frameworkLocale.Value, localisationParameters.Value);

View File

@@ -61,7 +61,7 @@ namespace osu.Game.Screens
SetDefault(EzSkinSetting.ColumnWidth, 60, 5, 400.0, 1.0);
SetDefault(EzSkinSetting.SpecialFactor, 1.2, 0.5, 2.0, 0.1);
SetDefault(EzSkinSetting.HitPosition, LegacyManiaSkinConfiguration.DEFAULT_HIT_POSITION, 0, 500, 1.0);
SetDefault(EzSkinSetting.HitPosition, 180, 0, 500, 1.0);
SetDefault(EzSkinSetting.VisualHitPosition, 0.0, -100, 100, 1.0);
SetDefault(EzSkinSetting.HitTargetFloatFixed, 6, 0, 10, 0.1);
SetDefault(EzSkinSetting.HitTargetAlpha, 0.6, 0, 1, 0.01);

View File

@@ -11,6 +11,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Rendering;
using osu.Framework.Graphics.Textures;
using osu.Framework.IO.Stores;
using osu.Framework.Logging;
@@ -42,6 +43,7 @@ namespace osu.Game.Screens.LAsEzExtensions
private readonly ConcurrentDictionary<string, Texture> singleTextureCache = new ConcurrentDictionary<string, Texture>();
private readonly TextureStore textureStore;
private readonly LargeTextureStore largeTextureStore;
private readonly EzSkinSettingsManager ezSkinConfig;
private readonly Dictionary<string, TextureLoaderStore> loaderStoreCache = new Dictionary<string, TextureLoaderStore>();
@@ -79,7 +81,7 @@ namespace osu.Game.Screens.LAsEzExtensions
}
public EzLocalTextureFactory(EzSkinSettingsManager ezSkinConfig,
TextureStore textureStore,
IRenderer renderer,
Storage hostStorage)
{
lock (instance_lock)
@@ -94,7 +96,8 @@ namespace osu.Game.Screens.LAsEzExtensions
}
this.ezSkinConfig = ezSkinConfig;
this.textureStore = textureStore;
textureStore = new TextureStore(renderer);
largeTextureStore = new LargeTextureStore(renderer);
const string path = "EzResources/";
@@ -105,6 +108,7 @@ namespace osu.Game.Screens.LAsEzExtensions
textureLoaderStore = new TextureLoaderStore(fileStore);
loaderStoreCache[path] = textureLoaderStore;
textureStore.AddTextureSource(textureLoaderStore);
largeTextureStore.AddTextureSource(textureLoaderStore);
}
initialize();
@@ -125,22 +129,13 @@ namespace osu.Game.Screens.LAsEzExtensions
noteSetName.BindValueChanged(e =>
{
if (!string.IsNullOrEmpty(e.OldValue) && !string.Equals(e.OldValue, e.NewValue, StringComparison.Ordinal))
{
Logger.Log($"[EzLocalTextureFactory] NoteSet changed: {e.OldValue} -> {e.NewValue}, clearing related cache",
LoggingTarget.Runtime, LogLevel.Debug);
clearRelatedCache(e.OldValue, e.NewValue);
}
ForceRefreshCache();
clearRelatedCache(e.OldValue, e.NewValue);
});
stageName.BindValueChanged(e =>
{
if (!string.IsNullOrEmpty(e.OldValue) && !string.Equals(e.OldValue, e.NewValue, StringComparison.Ordinal))
{
Logger.Log($"[EzLocalTextureFactory] Stage changed: {e.OldValue} -> {e.NewValue}, clearing stage cache",
LoggingTarget.Runtime, LogLevel.Debug);
clearStageCache(e.OldValue, e.NewValue);
}
clearStageCache(e.OldValue, e.NewValue);
});
}
@@ -239,9 +234,9 @@ namespace osu.Game.Screens.LAsEzExtensions
});
});
Logger.Log($"[EzLocalTextureFactory] Cleared cache for note set change: {oldNoteSet} -> {newNoteSet} " +
$"(Removed {keysToRemove.Count + newNoteKeysToRemove.Count} texture cache, {pathKeysToRemove.Count + newPathKeysToRemove.Count} path cache, {ratioKeysToRemove.Count + newRatioKeysToRemove.Count} ratio cache)",
LoggingTarget.Runtime, LogLevel.Debug);
// Logger.Log($"[EzLocalTextureFactory] Cleared cache for note set change: {oldNoteSet} -> {newNoteSet} " +
// $"(Removed {keysToRemove.Count + newNoteKeysToRemove.Count} texture cache, {pathKeysToRemove.Count + newPathKeysToRemove.Count} path cache, {ratioKeysToRemove.Count + newRatioKeysToRemove.Count} ratio cache)",
// LoggingTarget.Runtime, LogLevel.Debug);
}
private void clearStageCache(string? oldStage, string newStage)
@@ -380,6 +375,7 @@ namespace osu.Game.Screens.LAsEzExtensions
{
string cacheKey = $"{currentNoteSetName}_{component}";
// 双重检查锁定模式,避免并发时重复创建
if (global_cache.TryGetValue(cacheKey, out var cachedEntry))
{
if (cachedEntry.Textures != null && cachedEntry.Textures.Count > 0)
@@ -391,8 +387,10 @@ namespace osu.Game.Screens.LAsEzExtensions
global_cache.TryRemove(cacheKey, out _);
}
// 使用锁确保同一组件只加载一次
lock (cleanup_lock)
{
// 再次检查,防止在等待锁的过程中其他线程已经加载了
if (global_cache.TryGetValue(cacheKey, out cachedEntry))
{
if (cachedEntry.Textures != null && cachedEntry.Textures.Count > 0)
@@ -404,8 +402,10 @@ namespace osu.Game.Screens.LAsEzExtensions
global_cache.TryRemove(cacheKey, out _);
}
// 加载纹理帧
var frames = loadTextureFrames(component, currentNoteSetName);
// 只缓存有效的帧数据,不缓存空结果
if (frames.Count > 0)
{
var newEntry = new CacheEntry(frames, true);
@@ -523,44 +523,62 @@ namespace osu.Game.Screens.LAsEzExtensions
#region Stage Creation
private bool isStageBody(string componentName)
{
return componentName.Contains("Body", StringComparison.InvariantCultureIgnoreCase);
}
// private bool isStageBody(string componentName)
// {
// return componentName.Contains("Body", StringComparison.InvariantCultureIgnoreCase);
// }
public virtual Drawable CreateStage(string component)
{
bool isBody = isStageBody(component);
// if (!isStageBody(component))
// throw new ArgumentException("CreateStage only handles Body components. Use CreateStageKeys for key components.", nameof(component));
string basePath = $"Stage/{stageName.Value}/Stage";
var container = new Container
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
FillMode = FillMode.Fill,
Y = 0,
AutoSizeAxes = Axes.X,
Height = default_stage_body_height,
Masking = true,
};
addStageComponent(container, $"{basePath}/fivekey/{component}");
addStageComponent(container, $"{basePath}/GrooveLight");
createStageAnimation(container, basePath);
return container;
}
public virtual Container CreateStageKeys(string component)
{
string basePath = $"Stage/{stageName.Value}/Stage";
var container = new Container
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
AutoSizeAxes = Axes.Both,
FillMode = FillMode.Fill,
};
if (isBody)
string baseKeyPath = $"{basePath}/eightkey/{component}";
string[] pathsToTry =
{
container = new Container
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
FillMode = FillMode.Fill,
Y = 0,
AutoSizeAxes = Axes.X,
Height = default_stage_body_height,
Masking = true,
};
$"{baseKeyPath}/KeyBase",
$"{baseKeyPath}/KeyPress",
$"{baseKeyPath}/KeyBase_0",
$"{baseKeyPath}/KeyPress_0",
$"{baseKeyPath}/2KeyBase_0",
$"{baseKeyPath}/2KeyPress_0",
};
addStageComponent(container, $"{basePath}/fivekey/{component}");
addStageComponent(container, $"{basePath}/GrooveLight");
createStageAnimation(container, basePath);
}
else
foreach (string path in pathsToTry)
{
createStageKeys(container, basePath, component);
addStageComponent(container, path);
}
return container;
@@ -571,28 +589,24 @@ namespace osu.Game.Screens.LAsEzExtensions
Texture? texture = loadStageTexture(basePath, frameIndex);
if (texture == null) return;
const int small_texture_threshold = 256;
const int medium_texture_threshold = 384;
const int max_atlas_size = 1024;
bool isStageTexture = isStageTexturePath(basePath);
bool isMediumTexture = Math.Max(texture.Width, texture.Height) > small_texture_threshold &&
Math.Max(texture.Width, texture.Height) <= medium_texture_threshold;
bool isLargeTexture = texture.Width > max_atlas_size || texture.Height > max_atlas_size;
bool isLargeTexture = Math.Max(texture.Width, texture.Height) > medium_texture_threshold;
if (isLargeTexture)
{
Logger.Log($"[EzLocalTextureFactory] Large texture detected: {basePath} ({texture.Width}x{texture.Height}) - bypassing atlas",
LoggingTarget.Runtime, LogLevel.Debug);
}
else if (isStageTexture)
{
Logger.Log($"[EzLocalTextureFactory] Stage texture detected: {basePath} ({texture.Width}x{texture.Height}) - bypassing atlas for performance",
LoggingTarget.Runtime, LogLevel.Debug);
}
else if (isMediumTexture)
{
Logger.Log($"[EzLocalTextureFactory] Medium texture detected: {basePath} ({texture.Width}x{texture.Height}) - bypassing atlas to prevent fragmentation",
LoggingTarget.Runtime, LogLevel.Debug);
// For large textures, try to load from large texture store to bypass atlas
string texturePath = frameIndex < 0
? $"{basePath}.png"
: (frameIndex == 0 ? $"{basePath}.png" : $"{basePath}_{frameIndex}.png");
var largeTexture = largeTextureStore.Get(texturePath);
if (largeTexture != null)
{
texture = largeTexture;
}
}
var sprite = new Sprite
@@ -643,25 +657,6 @@ namespace osu.Game.Screens.LAsEzExtensions
}
}
private void createStageKeys(Container container, string basePath, string component)
{
string baseKeyPath = $"{basePath}/eightkey/{component}";
string[] pathsToTry =
{
$"{baseKeyPath}/KeyBase",
$"{baseKeyPath}/KeyPress",
$"{baseKeyPath}/KeyBase_0",
$"{baseKeyPath}/KeyPress_0",
$"{baseKeyPath}/2KeyBase_0",
$"{baseKeyPath}/2KeyPress_0",
};
foreach (string path in pathsToTry)
{
addStageComponent(container, path);
}
}
private Texture? loadStageTexture(string basePath, int i = -1)
{
string texturePath = i < 0
@@ -813,26 +808,18 @@ namespace osu.Game.Screens.LAsEzExtensions
foreach (string path in stagePaths)
{
try
{
var texture = getCachedTexture($"{path}.png");
if (texture != null)
loadedCount++;
var texture = getCachedTexture($"{path}.png");
if (texture != null)
loadedCount++;
if (loadedCount % 2 == 0)
{
await Task.Delay(10).ConfigureAwait(false);
}
}
catch (Exception ex)
Logger.Log($"[EzLocalTextureFactory] preload stage texture {path}",
LoggingTarget.Runtime, LogLevel.Debug);
if (loadedCount % 2 == 0)
{
Logger.Log($"[EzLocalTextureFactory] Failed to preload stage texture {path}: {ex.Message}",
LoggingTarget.Runtime, LogLevel.Debug);
await Task.Delay(10).ConfigureAwait(false);
}
}
Logger.Log($"[EzLocalTextureFactory] Stage texture preload completed: {loadedCount}/{stagePaths.Count} loaded",
LoggingTarget.Runtime, LogLevel.Debug);
}
catch (Exception ex)
{