mirror of
https://github.com/ppy/osu.git
synced 2025-02-21 06:05:07 +08:00
Add basic skin editor clipboard implementation
This commit is contained in:
parent
08ed174f61
commit
d653335b6f
@ -7,6 +7,7 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -48,6 +49,9 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
|
|
||||||
private Bindable<Skin> currentSkin = null!;
|
private Bindable<Skin> currentSkin = null!;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
public readonly EditorClipboard Clipboard = new EditorClipboard();
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuGame? game { get; set; }
|
private OsuGame? game { get; set; }
|
||||||
|
|
||||||
@ -78,6 +82,15 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
private EditorMenuItem undoMenuItem = null!;
|
private EditorMenuItem undoMenuItem = null!;
|
||||||
private EditorMenuItem redoMenuItem = null!;
|
private EditorMenuItem redoMenuItem = null!;
|
||||||
|
|
||||||
|
private EditorMenuItem cutMenuItem = null!;
|
||||||
|
private EditorMenuItem copyMenuItem = null!;
|
||||||
|
private EditorMenuItem cloneMenuItem = null!;
|
||||||
|
private EditorMenuItem pasteMenuItem = null!;
|
||||||
|
|
||||||
|
private readonly BindableWithCurrent<bool> canCut = new BindableWithCurrent<bool>();
|
||||||
|
private readonly BindableWithCurrent<bool> canCopy = new BindableWithCurrent<bool>();
|
||||||
|
private readonly BindableWithCurrent<bool> canPaste = new BindableWithCurrent<bool>();
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OnScreenDisplay? onScreenDisplay { get; set; }
|
private OnScreenDisplay? onScreenDisplay { get; set; }
|
||||||
|
|
||||||
@ -143,6 +156,11 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
{
|
{
|
||||||
undoMenuItem = new EditorMenuItem(CommonStrings.Undo, MenuItemType.Standard, Undo),
|
undoMenuItem = new EditorMenuItem(CommonStrings.Undo, MenuItemType.Standard, Undo),
|
||||||
redoMenuItem = new EditorMenuItem(CommonStrings.Redo, MenuItemType.Standard, Redo),
|
redoMenuItem = new EditorMenuItem(CommonStrings.Redo, MenuItemType.Standard, Redo),
|
||||||
|
new EditorMenuItemSpacer(),
|
||||||
|
cutMenuItem = new EditorMenuItem(CommonStrings.Cut, MenuItemType.Standard, Cut),
|
||||||
|
copyMenuItem = new EditorMenuItem(CommonStrings.Copy, MenuItemType.Standard, Copy),
|
||||||
|
pasteMenuItem = new EditorMenuItem(CommonStrings.Paste, MenuItemType.Standard, Paste),
|
||||||
|
cloneMenuItem = new EditorMenuItem(CommonStrings.Clone, MenuItemType.Standard, Clone),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -201,6 +219,21 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
|
canCut.Current.BindValueChanged(cut => cutMenuItem.Action.Disabled = !cut.NewValue, true);
|
||||||
|
canCopy.Current.BindValueChanged(copy =>
|
||||||
|
{
|
||||||
|
copyMenuItem.Action.Disabled = !copy.NewValue;
|
||||||
|
cloneMenuItem.Action.Disabled = !copy.NewValue;
|
||||||
|
}, true);
|
||||||
|
canPaste.Current.BindValueChanged(paste => pasteMenuItem.Action.Disabled = !paste.NewValue, true);
|
||||||
|
|
||||||
|
SelectedComponents.BindCollectionChanged((_, _) =>
|
||||||
|
{
|
||||||
|
canCopy.Value = canCut.Value = SelectedComponents.Any();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
Clipboard.Content.BindValueChanged(content => canPaste.Value = !string.IsNullOrEmpty(content.NewValue), true);
|
||||||
|
|
||||||
Show();
|
Show();
|
||||||
|
|
||||||
game?.RegisterImportHandler(this);
|
game?.RegisterImportHandler(this);
|
||||||
@ -224,6 +257,18 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
{
|
{
|
||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
|
case PlatformAction.Cut:
|
||||||
|
Cut();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case PlatformAction.Copy:
|
||||||
|
Copy();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case PlatformAction.Paste:
|
||||||
|
Paste();
|
||||||
|
return true;
|
||||||
|
|
||||||
case PlatformAction.Undo:
|
case PlatformAction.Undo:
|
||||||
Undo();
|
Undo();
|
||||||
return true;
|
return true;
|
||||||
@ -361,6 +406,50 @@ namespace osu.Game.Overlays.SkinEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void Cut()
|
||||||
|
{
|
||||||
|
Copy();
|
||||||
|
DeleteItems(SelectedComponents.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Copy()
|
||||||
|
{
|
||||||
|
Clipboard.Content.Value = JsonConvert.SerializeObject(SelectedComponents.Cast<Drawable>().Select(s => s.CreateSerialisedInfo()).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Clone()
|
||||||
|
{
|
||||||
|
// Avoid attempting to clone if copying is not available (as it may result in pasting something unexpected).
|
||||||
|
if (!canCopy.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// This is an initial implementation just to get an idea of how people used this function.
|
||||||
|
// There are a couple of differences from osu!stable's implementation which will require more work to match:
|
||||||
|
// - The "clipboard" is not populated during the duplication process.
|
||||||
|
// - The duplicated hitobjects are inserted after the original pattern (add one beat_length and then quantize using beat snap).
|
||||||
|
// - The duplicated hitobjects are selected (but this is also applied for all paste operations so should be changed there).
|
||||||
|
Copy();
|
||||||
|
Paste();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Paste()
|
||||||
|
{
|
||||||
|
var drawableInfo = JsonConvert.DeserializeObject<SerialisedDrawableInfo[]>(Clipboard.Content.Value);
|
||||||
|
|
||||||
|
if (drawableInfo == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var instances = drawableInfo.Select(d => d.CreateInstance())
|
||||||
|
.OfType<ISerialisableDrawable>()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
foreach (var i in instances)
|
||||||
|
placeComponent(i);
|
||||||
|
|
||||||
|
SelectedComponents.Clear();
|
||||||
|
SelectedComponents.AddRange(instances);
|
||||||
|
}
|
||||||
|
|
||||||
protected void Undo() => changeHandler?.RestoreState(-1);
|
protected void Undo() => changeHandler?.RestoreState(-1);
|
||||||
|
|
||||||
protected void Redo() => changeHandler?.RestoreState(1);
|
protected void Redo() => changeHandler?.RestoreState(1);
|
||||||
|
Loading…
Reference in New Issue
Block a user