mirror of
https://github.com/SK-la/Ez2Lazer.git
synced 2026-03-13 11:20:28 +00:00
每列单例 watcher, O(columns)订阅,降低峰值GC,但invalidation显著升高,整体愿意接受
This commit is contained in:
@@ -11,7 +11,7 @@ namespace osu.Game.Benchmarks
|
|||||||
{
|
{
|
||||||
public class BenchmarkHitObject : BenchmarkTest
|
public class BenchmarkHitObject : BenchmarkTest
|
||||||
{
|
{
|
||||||
[Params(1, 100, 1000)]
|
[Params(1, 1000, 5000)]
|
||||||
public int Count { get; set; }
|
public int Count { get; set; }
|
||||||
|
|
||||||
[Params(false, true)]
|
[Params(false, true)]
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
direction.BindTo(scrollingInfo.Direction);
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
direction.BindValueChanged(onDirectionChanged, true);
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
accentColour = column.AccentColour.GetBoundCopy();
|
// Use shared column bindable to prevent per-instance allocation via GetBoundCopy().
|
||||||
|
accentColour = column.AccentColour;
|
||||||
accentColour.BindValueChanged(colour =>
|
accentColour.BindValueChanged(colour =>
|
||||||
{
|
{
|
||||||
largeFaint.Colour = Interpolation.ValueAt(0.8f, colour.NewValue, Color4.White, 0, 1);
|
largeFaint.Colour = Interpolation.ValueAt(0.8f, colour.NewValue, Color4.White, 0, 1);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
private Circle hitTargetLine = null!;
|
private Circle hitTargetLine = null!;
|
||||||
|
|
||||||
private CircularContainer? topIcon;
|
private CircularContainer? topIcon;
|
||||||
|
private Box? topIconBox;
|
||||||
private Bindable<Color4> accentColour = null!;
|
private Bindable<Color4> accentColour = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
@@ -123,7 +124,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
direction.BindTo(scrollingInfo.Direction);
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
direction.BindValueChanged(onDirectionChanged, true);
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
accentColour = column.AccentColour.GetBoundCopy();
|
// Use the column's shared bindable to avoid per-instance allocations from GetBoundCopy()
|
||||||
|
accentColour = column.AccentColour;
|
||||||
accentColour.BindValueChanged(colour =>
|
accentColour.BindValueChanged(colour =>
|
||||||
{
|
{
|
||||||
background.Colour = colour.NewValue.Darken(0.2f);
|
background.Colour = colour.NewValue.Darken(0.2f);
|
||||||
@@ -142,13 +144,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
|
|
||||||
double bpm = beatmap.BeatmapInfo.BPM * gameplayClock.GetTrueGameplayRate();
|
double bpm = beatmap.BeatmapInfo.BPM * gameplayClock.GetTrueGameplayRate();
|
||||||
beatInterval = 60000 / bpm;
|
beatInterval = 60000 / bpm;
|
||||||
|
// cache reference to inner box to avoid LINQ allocations during Update
|
||||||
|
topIconBox = topIcon?.Children.OfType<Box>().FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
if (topIcon == null || !topIcon.Children.Any())
|
if (topIconBox == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
double progress = (gameplayClock.CurrentTime % beatInterval) / beatInterval;
|
double progress = (gameplayClock.CurrentTime % beatInterval) / beatInterval;
|
||||||
@@ -156,7 +160,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
if (progress < gameplayClock.ElapsedFrameTime / beatInterval)
|
if (progress < gameplayClock.ElapsedFrameTime / beatInterval)
|
||||||
{
|
{
|
||||||
double fadeTime = Math.Max(1, beatInterval / 2);
|
double fadeTime = Math.Max(1, beatInterval / 2);
|
||||||
var box = topIcon.Children.OfType<Box>().FirstOrDefault();
|
var box = topIconBox;
|
||||||
|
|
||||||
box?.FadeTo(1, fadeTime)
|
box?.FadeTo(1, fadeTime)
|
||||||
.Then()
|
.Then()
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
|
|
||||||
private Container<Circle> bottomIcon = null!;
|
private Container<Circle> bottomIcon = null!;
|
||||||
private CircularContainer topIcon = null!;
|
private CircularContainer topIcon = null!;
|
||||||
|
private Box? topIconBox;
|
||||||
private Bindable<Color4> accentColour = null!;
|
private Bindable<Color4> accentColour = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
@@ -162,12 +163,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
|
|
||||||
// double bpm = beatmap.BeatmapInfo.BPM;
|
// double bpm = beatmap.BeatmapInfo.BPM;
|
||||||
double bpm = beatmap.ControlPointInfo.TimingPointAt(gameplayClock.CurrentTime).BPM * gameplayClock.GetTrueGameplayRate();
|
double bpm = beatmap.ControlPointInfo.TimingPointAt(gameplayClock.CurrentTime).BPM * gameplayClock.GetTrueGameplayRate();
|
||||||
applyBlinkingEffect(topIcon, bpm);
|
// cache inner box once to avoid repeated LINQ allocation inside scheduled callback
|
||||||
|
topIconBox = topIcon.Children.OfType<Box>().FirstOrDefault();
|
||||||
|
applyBlinkingEffect(topIconBox, bpm);
|
||||||
|
|
||||||
direction.BindTo(scrollingInfo.Direction);
|
direction.BindTo(scrollingInfo.Direction);
|
||||||
direction.BindValueChanged(onDirectionChanged, true);
|
direction.BindValueChanged(onDirectionChanged, true);
|
||||||
|
|
||||||
accentColour = column.AccentColour.GetBoundCopy();
|
// Use the column's shared bindable to avoid per-instance allocations from GetBoundCopy()
|
||||||
|
accentColour = column.AccentColour;
|
||||||
accentColour.BindValueChanged(colour =>
|
accentColour.BindValueChanged(colour =>
|
||||||
{
|
{
|
||||||
background.Colour = colour.NewValue.Darken(0.2f);
|
background.Colour = colour.NewValue.Darken(0.2f);
|
||||||
@@ -178,13 +182,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
column.TopLevelContainer.Add(CreateProxy());
|
column.TopLevelContainer.Add(CreateProxy());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyBlinkingEffect(CircularContainer container, double bpm)
|
private void applyBlinkingEffect(Box? box, double bpm)
|
||||||
{
|
{
|
||||||
|
if (box == null) return;
|
||||||
|
|
||||||
double interval = 60000 / bpm;
|
double interval = 60000 / bpm;
|
||||||
|
|
||||||
Scheduler.AddDelayed(() =>
|
Scheduler.AddDelayed(() =>
|
||||||
{
|
{
|
||||||
container.Children.OfType<Box>().First().FadeTo(1, interval / 2).Then().FadeTo(0, interval / 2);
|
box.FadeTo(1, interval / 2).Then().FadeTo(0, interval / 2);
|
||||||
}, interval, true);
|
}, interval, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
||||||
|
|
||||||
private readonly Circle colouredBox;
|
private readonly Circle colouredBox;
|
||||||
|
private Drawable iconContainer = null!;
|
||||||
|
|
||||||
public Ez2NotePiece()
|
public Ez2NotePiece()
|
||||||
{
|
{
|
||||||
@@ -35,6 +36,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
CornerRadius = CORNER_RADIUS;
|
CornerRadius = CORNER_RADIUS;
|
||||||
// Masking = true;
|
// Masking = true;
|
||||||
|
|
||||||
|
iconContainer = CreateIcon();
|
||||||
|
|
||||||
InternalChildren = new[]
|
InternalChildren = new[]
|
||||||
{
|
{
|
||||||
new Container
|
new Container
|
||||||
@@ -83,7 +86,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 0,
|
Height = 0,
|
||||||
},
|
},
|
||||||
CreateIcon(),
|
iconContainer,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +102,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
|||||||
// NoteHeight = (float)config.Get<double>(ManiaRulesetSetting.ColumnWidth);
|
// NoteHeight = (float)config.Get<double>(ManiaRulesetSetting.ColumnWidth);
|
||||||
// specialFactor = (float)config.Get<double>(ManiaRulesetSetting.SpecialFactor);
|
// specialFactor = (float)config.Get<double>(ManiaRulesetSetting.SpecialFactor);
|
||||||
|
|
||||||
CreateIcon().Size = new Vector2(DrawWidth / NoteHeight * 0.7f);
|
if (iconContainer != null)
|
||||||
|
iconContainer.Size = new Vector2(DrawWidth / NoteHeight * 0.7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual Drawable CreateIcon() => new Container
|
protected virtual Drawable CreateIcon() => new Container
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
|||||||
// 计算 drawSeparator 结果(基于不变的列数和列索引)
|
// 计算 drawSeparator 结果(基于不变的列数和列索引)
|
||||||
shouldDrawSeparator = drawSeparatorImpl(Column.Index, stageDefinition);
|
shouldDrawSeparator = drawSeparatorImpl(Column.Index, stageDefinition);
|
||||||
|
|
||||||
accentColour = new Bindable<Color4>(ezSkinConfig.GetColumnColor(stageDefinition.Columns, Column.Index));
|
// 使用 Column 提供的共享 bindable,避免为每个列背景构建新的 Bindable 实例
|
||||||
|
accentColour = Column.AccentColour;
|
||||||
accentColour.BindValueChanged(colour =>
|
accentColour.BindValueChanged(colour =>
|
||||||
{
|
{
|
||||||
var baseCol = colour.NewValue;
|
var baseCol = colour.NewValue;
|
||||||
@@ -104,7 +105,18 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
if (Column.BackgroundContainer.Children.OfType<Box>().All(b => b.Name != "Separator"))
|
bool hasSeparator = false;
|
||||||
|
|
||||||
|
foreach (var child in Column.BackgroundContainer.Children)
|
||||||
|
{
|
||||||
|
if (child is Box b && b.Name == "Separator")
|
||||||
|
{
|
||||||
|
hasSeparator = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasSeparator)
|
||||||
Column.BackgroundContainer.Add(separator);
|
Column.BackgroundContainer.Add(separator);
|
||||||
|
|
||||||
if (!Column.BackgroundContainer.Children.Contains(hitOverlay))
|
if (!Column.BackgroundContainer.Children.Contains(hitOverlay))
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@@ -101,9 +104,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
|||||||
NoteSetName = Column.NoteSetBindable;
|
NoteSetName = Column.NoteSetBindable;
|
||||||
NoteSize = Column.NoteSizeBindable;
|
NoteSize = Column.NoteSizeBindable;
|
||||||
|
|
||||||
Column.NoteSetChanged += OnNoteSetChanged;
|
// Use a per-column watcher to avoid creating an event handler delegate per-note.
|
||||||
Column.NoteColourChanged += OnColourChanged;
|
ColumnWatcher.GetOrCreate(Column).Add(this);
|
||||||
Column.NoteSizeChanged += OnNoteSizeChanged;
|
|
||||||
|
|
||||||
UpdateSize();
|
UpdateSize();
|
||||||
}
|
}
|
||||||
@@ -153,7 +155,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
|||||||
sideLine.UpdateGlowEffect(NoteColor);
|
sideLine.UpdateGlowEffect(NoteColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnColourChanged()
|
private void OnColourChanged()
|
||||||
@@ -197,13 +198,122 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
|||||||
{
|
{
|
||||||
if (isDisposing)
|
if (isDisposing)
|
||||||
{
|
{
|
||||||
Column.NoteSetChanged -= OnNoteSetChanged;
|
ColumnWatcher.Remove(Column, this);
|
||||||
Column.NoteColourChanged -= OnColourChanged;
|
|
||||||
Column.NoteSizeChanged -= OnNoteSizeChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Forwarders used by ColumnWatcher when broadcasting per-column changes to instances.
|
||||||
|
internal void ForwardOnNoteSetChanged(ValueChangedEvent<string> e) => OnNoteSetChanged(e);
|
||||||
|
internal void ForwardOnColourChanged() => OnColourChanged();
|
||||||
|
internal void ForwardOnNoteSizeChanged() => OnNoteSizeChanged();
|
||||||
|
|
||||||
|
private class ColumnWatcher
|
||||||
|
{
|
||||||
|
private readonly Column column;
|
||||||
|
private readonly List<WeakReference<EzNoteBase>> notes = new List<WeakReference<EzNoteBase>>();
|
||||||
|
|
||||||
|
public ColumnWatcher(Column column)
|
||||||
|
{
|
||||||
|
this.column = column;
|
||||||
|
column.NoteSetChanged += onNoteSetChanged;
|
||||||
|
column.NoteColourChanged += onNoteColourChanged;
|
||||||
|
column.NoteSizeChanged += onNoteSizeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(EzNoteBase note)
|
||||||
|
{
|
||||||
|
// store weak reference to avoid preventing note GC if removed elsewhere
|
||||||
|
notes.Add(new WeakReference<EzNoteBase>(note));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(EzNoteBase note)
|
||||||
|
{
|
||||||
|
notes.RemoveAll(wr => !wr.TryGetTarget(out var target) || ReferenceEquals(target, note));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onNoteSetChanged(ValueChangedEvent<string> e)
|
||||||
|
{
|
||||||
|
// iterate backwards and remove dead weak references in-place to avoid
|
||||||
|
// allocating a large temporary array when the column has many notes.
|
||||||
|
for (int i = notes.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var wr = notes[i];
|
||||||
|
if (wr.TryGetTarget(out var target))
|
||||||
|
target.ForwardOnNoteSetChanged(e);
|
||||||
|
else
|
||||||
|
notes.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onNoteColourChanged()
|
||||||
|
{
|
||||||
|
for (int i = notes.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var wr = notes[i];
|
||||||
|
if (wr.TryGetTarget(out var target))
|
||||||
|
target.ForwardOnColourChanged();
|
||||||
|
else
|
||||||
|
notes.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onNoteSizeChanged()
|
||||||
|
{
|
||||||
|
for (int i = notes.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var wr = notes[i];
|
||||||
|
if (wr.TryGetTarget(out var target))
|
||||||
|
target.ForwardOnNoteSizeChanged();
|
||||||
|
else
|
||||||
|
notes.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unsubscribe()
|
||||||
|
{
|
||||||
|
column.NoteSetChanged -= onNoteSetChanged;
|
||||||
|
column.NoteColourChanged -= onNoteColourChanged;
|
||||||
|
column.NoteSizeChanged -= onNoteSizeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEmpty => notes.All(wr => !wr.TryGetTarget(out _));
|
||||||
|
|
||||||
|
private static readonly Dictionary<Column, ColumnWatcher> watchers = new Dictionary<Column, ColumnWatcher>();
|
||||||
|
private static readonly object watcher_lock = new object();
|
||||||
|
|
||||||
|
public static ColumnWatcher GetOrCreate(Column c)
|
||||||
|
{
|
||||||
|
lock (watcher_lock)
|
||||||
|
{
|
||||||
|
if (!watchers.TryGetValue(c, out var w))
|
||||||
|
{
|
||||||
|
w = new ColumnWatcher(c);
|
||||||
|
watchers[c] = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Remove(Column c, EzNoteBase note)
|
||||||
|
{
|
||||||
|
lock (watcher_lock)
|
||||||
|
{
|
||||||
|
if (!watchers.TryGetValue(c, out var w))
|
||||||
|
return;
|
||||||
|
|
||||||
|
w.Remove(note);
|
||||||
|
|
||||||
|
if (w.IsEmpty)
|
||||||
|
{
|
||||||
|
w.Unsubscribe();
|
||||||
|
watchers.Remove(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
osu.sln
3
osu.sln
@@ -128,7 +128,6 @@ Global
|
|||||||
{F5037F74-E137-4940-8CE7-4D3E5DF0FB39}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{F5037F74-E137-4940-8CE7-4D3E5DF0FB39}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F5037F74-E137-4940-8CE7-4D3E5DF0FB39}.Release|Any CPU.Build.0 = Release|Any CPU
|
{F5037F74-E137-4940-8CE7-4D3E5DF0FB39}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.Build.0 = Release|Any CPU
|
{5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
{5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
@@ -136,9 +135,7 @@ Global
|
|||||||
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Release|Any CPU.Build.0 = Release|Any CPU
|
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Release|Any CPU.Build.0 = Release|Any CPU
|
{E8F3B2C4-9D7A-4E6B-8C2F-7A9B12345678}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
|||||||
Reference in New Issue
Block a user