1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-05 10:53:10 +08:00

Addressed changes

This commit is contained in:
Terochi 2023-04-30 16:10:59 +02:00
parent 949dc1c0f9
commit 8f02bd80f9
3 changed files with 48 additions and 37 deletions

View File

@ -100,10 +100,15 @@ namespace osu.Game.Tests.Visual.Gameplay
InputManager.PressButton(MouseButton.Left); InputManager.PressButton(MouseButton.Left);
}); });
AddStep("Drag to bottom right", AddStep("Drag to bottom right", () =>
() => { InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.TopRight + new Vector2(-box3.ScreenSpaceDrawQuad.Width / 8, box3.ScreenSpaceDrawQuad.Height / 4)); }); {
InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.TopRight + new Vector2(-box3.ScreenSpaceDrawQuad.Width / 8, box3.ScreenSpaceDrawQuad.Height / 4));
});
AddStep("Release button", () => { InputManager.ReleaseButton(MouseButton.Left); }); AddStep("Release button", () =>
{
InputManager.ReleaseButton(MouseButton.Left);
});
AddAssert("First two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box1, box2 })); AddAssert("First two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box1, box2 }));
@ -113,9 +118,15 @@ namespace osu.Game.Tests.Visual.Gameplay
InputManager.PressButton(MouseButton.Left); InputManager.PressButton(MouseButton.Left);
}); });
AddStep("Drag to top left", () => { InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre - new Vector2(box2.ScreenSpaceDrawQuad.Width / 4)); }); AddStep("Drag to top left", () =>
{
InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre - new Vector2(box2.ScreenSpaceDrawQuad.Width / 4));
});
AddStep("Release button", () => { InputManager.ReleaseButton(MouseButton.Left); }); AddStep("Release button", () =>
{
InputManager.ReleaseButton(MouseButton.Left);
});
AddAssert("Last two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box2, box3 })); AddAssert("Last two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box2, box3 }));
@ -139,7 +150,10 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("Three black boxes added", () => targetContainer.Components.OfType<BigBlackBox>().Count(), () => Is.EqualTo(3)); AddAssert("Three black boxes added", () => targetContainer.Components.OfType<BigBlackBox>().Count(), () => Is.EqualTo(3));
AddStep("Store black box blueprints", () => { blueprints = skinEditor.ChildrenOfType<SkinBlueprint>().Where(b => b.Item is BigBlackBox).ToArray(); }); AddStep("Store black box blueprints", () =>
{
blueprints = skinEditor.ChildrenOfType<SkinBlueprint>().Where(b => b.Item is BigBlackBox).ToArray();
});
AddAssert("Selection is black box 1", () => skinEditor.SelectedComponents.Single(), () => Is.EqualTo(blueprints[0].Item)); AddAssert("Selection is black box 1", () => skinEditor.SelectedComponents.Single(), () => Is.EqualTo(blueprints[0].Item));
@ -184,7 +198,6 @@ namespace osu.Game.Tests.Visual.Gameplay
firstTarget = Player.ChildrenOfType<SkinComponentsContainer>().First(); firstTarget = Player.ChildrenOfType<SkinComponentsContainer>().First();
changeHandler = new TestSkinEditorChangeHandler(firstTarget); changeHandler = new TestSkinEditorChangeHandler(firstTarget);
changeHandler.SaveState();
defaultState = changeHandler.GetCurrentState(); defaultState = changeHandler.GetCurrentState();
testComponents = new[] testComponents = new[]
@ -225,7 +238,7 @@ namespace osu.Game.Tests.Visual.Gameplay
void revertAndCheckUnchanged() void revertAndCheckUnchanged()
{ {
AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue));
AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); AddAssert("Current state is same as default", () => defaultState.SequenceEqual(changeHandler.GetCurrentState()));
} }
} }

View File

@ -235,7 +235,10 @@ namespace osu.Game.Overlays.SkinEditor
}, true); }, true);
canPaste.Current.BindValueChanged(paste => pasteMenuItem.Action.Disabled = !paste.NewValue, true); canPaste.Current.BindValueChanged(paste => pasteMenuItem.Action.Disabled = !paste.NewValue, true);
SelectedComponents.BindCollectionChanged((_, _) => canCopy.Value = canCut.Value = SelectedComponents.Any(), true); SelectedComponents.BindCollectionChanged((_, _) =>
{
canCopy.Value = canCut.Value = SelectedComponents.Any();
}, true);
clipboard.Content.BindValueChanged(content => canPaste.Value = !string.IsNullOrEmpty(content.NewValue), true); clipboard.Content.BindValueChanged(content => canPaste.Value = !string.IsNullOrEmpty(content.NewValue), true);
@ -342,7 +345,6 @@ namespace osu.Game.Overlays.SkinEditor
changeHandler = new SkinEditorChangeHandler(skinComponentsContainer); changeHandler = new SkinEditorChangeHandler(skinComponentsContainer);
changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true); changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true);
changeHandler.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true); changeHandler.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true);
changeHandler.SaveState();
content.Child = new SkinBlueprintContainer(skinComponentsContainer); content.Child = new SkinBlueprintContainer(skinComponentsContainer);
@ -477,18 +479,12 @@ namespace osu.Game.Overlays.SkinEditor
protected void Cut() protected void Cut()
{ {
if (!canCut.Value)
return;
Copy(); Copy();
DeleteItems(SelectedComponents.ToArray()); DeleteItems(SelectedComponents.ToArray());
} }
protected void Copy() protected void Copy()
{ {
if (!canCopy.Value)
return;
clipboard.Content.Value = JsonConvert.SerializeObject(SelectedComponents.Cast<Drawable>().Select(s => s.CreateSerialisedInfo()).ToArray()); clipboard.Content.Value = JsonConvert.SerializeObject(SelectedComponents.Cast<Drawable>().Select(s => s.CreateSerialisedInfo()).ToArray());
} }
@ -504,9 +500,6 @@ namespace osu.Game.Overlays.SkinEditor
protected void Paste() protected void Paste()
{ {
if (!canPaste.Value)
return;
changeHandler?.BeginChange(); changeHandler?.BeginChange();
var drawableInfo = JsonConvert.DeserializeObject<SerialisedDrawableInfo[]>(clipboard.Content.Value); var drawableInfo = JsonConvert.DeserializeObject<SerialisedDrawableInfo[]>(clipboard.Content.Value);

View File

@ -34,7 +34,7 @@ namespace osu.Game.Overlays.SkinEditor
return; return;
components = new BindableList<ISerialisableDrawable> { BindTarget = firstTarget.Components }; components = new BindableList<ISerialisableDrawable> { BindTarget = firstTarget.Components };
components.BindCollectionChanged((_, _) => SaveState()); components.BindCollectionChanged((_, _) => SaveState(), true);
} }
protected override void WriteCurrentStateToStream(MemoryStream stream) protected override void WriteCurrentStateToStream(MemoryStream stream)
@ -61,47 +61,52 @@ namespace osu.Game.Overlays.SkinEditor
ISerialisableDrawable[] targetComponents = firstTarget.Components.ToArray(); ISerialisableDrawable[] targetComponents = firstTarget.Components.ToArray();
// Store components based on type for later lookup // Store components based on type for later lookup
var typedComponents = new Dictionary<Type, List<ISerialisableDrawable>>(); var typedComponents = new Dictionary<Type, Stack<Drawable>>();
foreach (var component in targetComponents) for (int i = targetComponents.Length - 1; i >= 0; i--)
{ {
Drawable component = (Drawable)targetComponents[i];
Type lookup = component.GetType(); Type lookup = component.GetType();
if (!typedComponents.TryGetValue(lookup, out List<ISerialisableDrawable>? typeComponents)) if (!typedComponents.TryGetValue(lookup, out Stack<Drawable>? typeComponents))
typedComponents.Add(lookup, typeComponents = new List<ISerialisableDrawable>()); typedComponents.Add(lookup, typeComponents = new Stack<Drawable>());
typeComponents.Add(component); typeComponents.Push(component);
} }
// Remove all components // Remove all components
for (int i = targetComponents.Length - 1; i >= 0; i--) for (int i = targetComponents.Length - 1; i >= 0; i--)
firstTarget.Remove(targetComponents[i], false); firstTarget.Remove(targetComponents[i], false);
// Keeps count of how many components for each type were already revived
Dictionary<Type, int> typedComponentCounter = typedComponents.Keys.ToDictionary(t => t, _ => 0);
foreach (var skinnableInfo in skinnableInfos) foreach (var skinnableInfo in skinnableInfos)
{ {
Type lookup = skinnableInfo.Type; Type lookup = skinnableInfo.Type;
if (!typedComponents.TryGetValue(lookup, out List<ISerialisableDrawable>? typeComponents)) if (!typedComponents.TryGetValue(lookup, out Stack<Drawable>? typeComponents))
{ {
firstTarget.Add((ISerialisableDrawable)skinnableInfo.CreateInstance()); firstTarget.Add((ISerialisableDrawable)skinnableInfo.CreateInstance());
continue; continue;
} }
int typeComponentsUsed = typedComponentCounter[lookup]++; if (typeComponents.TryPop(out Drawable? component))
{
ISerialisableDrawable component;
if (typeComponentsUsed < typeComponents.Count)
// Re-use unused component // Re-use unused component
((Drawable)(component = typeComponents[typeComponentsUsed])).ApplySerialisedInfo(skinnableInfo); component.ApplySerialisedInfo(skinnableInfo);
}
else else
{
// Create new one // Create new one
component = (ISerialisableDrawable)skinnableInfo.CreateInstance(); component = skinnableInfo.CreateInstance();
}
firstTarget.Add(component); firstTarget.Add((ISerialisableDrawable)component);
}
foreach ((Type _, Stack<Drawable> typeComponents) in typedComponents)
{
// Dispose extra components
foreach (var component in typeComponents)
component.Dispose();
} }
} }
} }