Skip to content

Commit

Permalink
Merge pull request #241 from andy840119/karaoke/right-click-to-assign…
Browse files Browse the repository at this point in the history
…-lyric-to-target-singer

Right click to assign lyric to target singer
  • Loading branch information
andy840119 authored Nov 8, 2020
2 parents c9d4682 + 7340e42 commit 0150177
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 14 deletions.
9 changes: 7 additions & 2 deletions osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneSinger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.Cursor;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Karaoke.Beatmaps;
using osu.Game.Rulesets.Karaoke.Edit.Singers;
Expand Down Expand Up @@ -70,7 +71,11 @@ private void load()
Dependencies.CacheAs(editorClock);
Dependencies.Cache(beatDivisor);

base.Content.Add(Content);
base.Content.Add(new OsuContextMenuContainer
{
RelativeSizeAxes = Axes.Both,
Child = Content
});
}

[SetUp]
Expand All @@ -83,7 +88,7 @@ public void SetUp() => Schedule(() =>
public void HoverToSingerArea()
{
// todo : add this step because description is not showing.
AddStep("Move mouse to singer area", () => InputManager.MoveMouseTo(Child, new Vector2(-400,-100)));
AddStep("Move mouse to singer area", () => InputManager.MoveMouseTo(Child, new Vector2(-450,-90)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ protected override void AddBlueprintFor(HitObject hitObject)
if (!(hitObject is Lyric))
return;

// todo : check lyric is at the same singer.

base.AddBlueprintFor(hitObject);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
Expand All @@ -24,6 +25,8 @@ public class LyricTimelineHitObjectBlueprint : TimelineHitObjectBlueprint, IHasC
public LyricTimelineHitObjectBlueprint(HitObject hitObject, Singer singer)
: base(hitObject)
{
this.singer = singer;

// Use tricty way to hide the timeline's component.
InternalChildren.ForEach(x => x.Alpha = 0);

Expand Down Expand Up @@ -52,13 +55,17 @@ public LyricTimelineHitObjectBlueprint(HitObject hitObject, Singer singer)
}
}
});
}

if (hitObject is Lyric lyric)
[BackgroundDependencyLoader]
private void load(SingerManager singerManager)
{
if (HitObject is Lyric lyric)
{
lyric.SingersBindable.BindValueChanged(e =>
{
// Check is lyric contains this singer, or default singer
var isSingerMatch = e.NewValue?.Contains(singer.ID) ?? singer.ID == 0;
var isSingerMatch = singerManager.SingerInLyric(singer, lyric);
if (isSingerMatch)
{
Show();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using Lucene.Net.Support;
using osu.Framework.Allocation;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Screens.Edit.Compose.Components;
using System.Collections.Generic;
using System.Linq;
using static osu.Game.Rulesets.Karaoke.Edit.Components.Timeline.TimelineBlueprintContainer;

namespace osu.Game.Rulesets.Karaoke.Edit.Singers.Components.Timeline
{
internal class LyricTimelineSelectionHandler : TimelineSelectionHandler
{
[Resolved]
private SingerManager singerManager { get; set; }

public override bool HandleMovement(MoveSelectionEvent moveEvent) => false;

protected override IEnumerable<MenuItem> GetContextMenuItemsForSelection(IEnumerable<SelectionBlueprint> selection)
{
// todo : make implementation of singers selection.
var menu = new List<MenuItem>
{
new OsuMenuItem("Test1", MenuItemType.Standard, () => { })
};
return menu.ToArray();
}
=> singerManager.CreateSingerContextMenu(selection.Select(x => x.HitObject).OfType<Lyric>().ToList());
}
}
101 changes: 101 additions & 0 deletions osu.Game.Rulesets.Karaoke/Edit/Singers/SingerManager.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
// Copyright (c) andy840119 <[email protected]>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using Microsoft.EntityFrameworkCore.Internal;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Karaoke.Beatmaps;
using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas;
using osu.Game.Rulesets.Karaoke.Objects;
using osu.Game.Screens.Edit;
using System;
using System.Collections.Generic;
using System.Linq;

namespace osu.Game.Rulesets.Karaoke.Edit.Singers
{
Expand All @@ -16,6 +23,9 @@ public class SingerManager : Component

public readonly BindableList<Singer> Singers = new BindableList<Singer>();

[Resolved(CanBeNull = true)]
private IEditorChangeHandler changeHandler { get; set; }

[Resolved]
private EditorBeatmap beatmap { get; set; }

Expand All @@ -27,5 +37,96 @@ private void load()
Singers.AddRange(karaokeBeatmap.SingerMetadata.Singers);
}
}

public IEnumerable<MenuItem> CreateSingerContextMenu(List<Lyric> lyrics)
{
return Singers.Select(singer => new OsuMenuItem(singer.Name, anySingerInLyric(singer) ? MenuItemType.Highlighted : MenuItemType.Standard, () =>
{
// if only one lyric
if (allSingerInLyric(singer))
{
lyrics.ForEach(lyric => RemoveSingerToLyric(singer, lyric));
}
else
{
lyrics.ForEach(lyric => AddSingerToLyric(singer, lyric));
}
}));

bool anySingerInLyric(Singer singer) => lyrics.Any(lyric => SingerInLyric(singer, lyric));

bool allSingerInLyric(Singer singer) => lyrics.All(lyric => SingerInLyric(singer, lyric));
}

public void AddSingerToLyric(Singer singer, Lyric lyric) => AddSingersToLyrics(new List<Singer> { singer }, new List<Lyric> { lyric });
public void AddSingersToLyrics(List<Singer> singers, List<Lyric> lyrics)
{
if (!(singers?.Any() ?? false))
throw new ArgumentNullException($"{nameof(singers)} cannot be numm or empty.");

if (!(lyrics?.Any() ?? false))
throw new ArgumentNullException($"{nameof(lyrics)} cannot be numm or empty.");

changeHandler?.BeginChange();

foreach (var lyric in lyrics)
{
foreach (var singer in singers)
{
addSingerToLyric(singer, lyric);
}
}

changeHandler?.EndChange();

void addSingerToLyric(Singer singer, Lyric lyric)
{
if (SingerInLyric(singer, lyric))
return;

var existSingerList = lyric.Singers?.ToList() ?? new List<int>();
existSingerList.Add(singer.ID);
lyric.Singers = existSingerList.ToArray();
}
}

public void RemoveSingerToLyric(Singer singer, Lyric lyric) => RemoveSingersToLyrics(new List<Singer> { singer }, new List<Lyric> { lyric });
public void RemoveSingersToLyrics(List<Singer> singers, List<Lyric> lyrics)
{
if (!(singers?.Any() ?? false))
throw new ArgumentNullException($"{nameof(singers)} cannot be numm or empty.");

if (!(lyrics?.Any() ?? false))
throw new ArgumentNullException($"{nameof(lyrics)} cannot be numm or empty.");

changeHandler?.BeginChange();

foreach (var lyric in lyrics)
{
foreach (var singer in singers)
{
removeSingerToLyric(singer, lyric);
}
}

changeHandler?.EndChange();

void removeSingerToLyric(Singer singer, Lyric lyric)
{
if (!SingerInLyric(singer, lyric))
return;

lyric.Singers = lyric.Singers?.Where(x => x != singer.ID).ToArray();
}
}

public bool SingerInLyric(Singer singer, Lyric lyric)
{
// lyric belongs to default singer if no any singer in lyric.
if (lyric.Singers == null || !lyric.Singers.Any())
return singer.ID == 0;

return lyric.Singers?.Contains(singer.ID) ?? false;
}
}
}

0 comments on commit 0150177

Please sign in to comment.