mirror of
https://github.com/ppy/osu.git
synced 2025-02-15 14:23:02 +08:00
Implement mask layering (incomplete)
This commit is contained in:
parent
9b307f0e12
commit
d504a44dfb
@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays
|
||||
{
|
||||
public class HoldNoteMask : HitObjectMask
|
||||
{
|
||||
private readonly BodyPiece body;
|
||||
private readonly DrawableHoldNote holdNote;
|
||||
|
||||
public HoldNoteMask(DrawableHoldNote hold)
|
||||
: base(hold)
|
||||
{
|
||||
holdNote = hold;
|
||||
|
||||
Position = hold.Position;
|
||||
|
||||
var holdObject = hold.HitObject;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new NoteMask(hold.Head),
|
||||
new NoteMask(hold.Tail),
|
||||
body = new BodyPiece()
|
||||
{
|
||||
AccentColour = Color4.Transparent
|
||||
},
|
||||
};
|
||||
|
||||
holdObject.ColumnChanged += _ => Position = hold.Position;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
body.BorderColour = colours.Yellow;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays
|
||||
{
|
||||
public class ManiaHitObjectColumnMaskLayer : HitObjectMaskLayer
|
||||
{
|
||||
public readonly Column Column;
|
||||
|
||||
public ManiaHitObjectColumnMaskLayer(ManiaEditPlayfield playfield, HitObjectComposer composer, Column column)
|
||||
: base(playfield, composer)
|
||||
{
|
||||
Column = column;
|
||||
}
|
||||
|
||||
public void CreateMasks() => AddMasks();
|
||||
|
||||
protected override void AddMasks()
|
||||
{
|
||||
foreach (var obj in Column.HitObjects.Objects)
|
||||
AddMask(obj);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays
|
||||
{
|
||||
public class ManiaHitObjectMaskLayer : HitObjectMaskLayer
|
||||
{
|
||||
public readonly List<ManiaHitObjectStageMaskLayer> Stages;
|
||||
|
||||
public ManiaHitObjectMaskLayer(ManiaEditPlayfield playfield, HitObjectComposer composer)
|
||||
: base(playfield, composer)
|
||||
{
|
||||
Stages = new List<ManiaHitObjectStageMaskLayer>();
|
||||
foreach (var s in ((ManiaEditPlayfield)Playfield).Stages)
|
||||
Stages.Add(new ManiaHitObjectStageMaskLayer((ManiaEditPlayfield)Playfield, Composer, s));
|
||||
}
|
||||
|
||||
protected override void AddMasks()
|
||||
{
|
||||
foreach (var s in Stages)
|
||||
s.CreateMasks();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays
|
||||
{
|
||||
public class ManiaHitObjectStageMaskLayer : HitObjectMaskLayer
|
||||
{
|
||||
public readonly List<ManiaHitObjectColumnMaskLayer> Columns;
|
||||
|
||||
public ManiaHitObjectStageMaskLayer(ManiaEditPlayfield playfield, HitObjectComposer composer, ManiaStage s)
|
||||
: base(playfield, composer)
|
||||
{
|
||||
Columns = new List<ManiaHitObjectColumnMaskLayer>();
|
||||
foreach (var c in s.Columns)
|
||||
Columns.Add(new ManiaHitObjectColumnMaskLayer((ManiaEditPlayfield)Playfield, Composer, c));
|
||||
}
|
||||
|
||||
public void CreateMasks() => AddMasks();
|
||||
|
||||
protected override void AddMasks()
|
||||
{
|
||||
foreach (var c in Columns)
|
||||
c.CreateMasks();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays
|
||||
{
|
||||
public class NoteMask : HitObjectMask
|
||||
{
|
||||
public NoteMask(DrawableNote note)
|
||||
: base(note)
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Position = note.Position;
|
||||
Size = note.Size;
|
||||
Scale = note.Scale;
|
||||
|
||||
AddInternal(new NotePiece());
|
||||
|
||||
note.HitObject.ColumnChanged += _ => Position = note.Position;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
Colour = colours.Yellow;
|
||||
}
|
||||
}
|
||||
}
|
58
osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs
Normal file
58
osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Edit.Screens.Compose;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Layers;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit
|
||||
{
|
||||
public class ManiaHitObjectComposer : HitObjectComposer
|
||||
{
|
||||
public BindableBeatDivisor BeatDivisor;
|
||||
public ManiaHitObjectComposer(Ruleset ruleset, BindableBeatDivisor beatDivisor)
|
||||
: base(ruleset)
|
||||
{
|
||||
BeatDivisor = beatDivisor;
|
||||
}
|
||||
|
||||
protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new ManiaEditRulesetContainer(ruleset, beatmap, BeatDivisor);
|
||||
|
||||
protected override IReadOnlyList<ICompositionTool> CompositionTools => new ICompositionTool[]
|
||||
{
|
||||
new HitObjectCompositionTool<Note>("Note"),
|
||||
new HitObjectCompositionTool<HoldNote>("Hold"),
|
||||
};
|
||||
|
||||
// TODO: According to another proposal, extend this to support multiple layers for mania maps
|
||||
// The logic could be moving all the layers that the beatmap has simultaneously
|
||||
// To avoid using too many resources, this could be changed to simply changing the Alpha to something
|
||||
// between 0.25f to 0.5f for notes that are in other layers (and may be also not selected)
|
||||
// Will also need a tool to navigate through layers
|
||||
// Please ignore the comment above, I just wanted to write my thoughts down so that I do not forget in 2 months when I get around to it
|
||||
|
||||
public override HitObjectMask CreateMaskFor(DrawableHitObject hitObject)
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableNote note:
|
||||
return new NoteMask(note);
|
||||
case DrawableHoldNote holdNote:
|
||||
return new HoldNoteMask(holdNote);
|
||||
}
|
||||
|
||||
return base.CreateMaskFor(hitObject);
|
||||
}
|
||||
|
||||
protected override HitObjectMaskLayer CreateHitObjectMaskLayer() => new ManiaHitObjectMaskLayer((ManiaEditPlayfield)RulesetContainer.Playfield, this);
|
||||
}
|
||||
}
|
@ -18,8 +18,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
/// </summary>
|
||||
public class DrawableHoldNote : DrawableManiaHitObject<HoldNote>, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly DrawableNote head;
|
||||
private readonly DrawableNote tail;
|
||||
public readonly DrawableNote Head;
|
||||
public readonly DrawableNote Tail;
|
||||
|
||||
private readonly GlowPiece glowPiece;
|
||||
private readonly BodyPiece bodyPiece;
|
||||
@ -64,12 +64,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
HoldStartTime = () => holdStartTime
|
||||
})
|
||||
},
|
||||
head = new DrawableHeadNote(this, action)
|
||||
Head = new DrawableHeadNote(this, action)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
},
|
||||
tail = new DrawableTailNote(this, action)
|
||||
Tail = new DrawableTailNote(this, action)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
@ -79,8 +79,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
foreach (var tick in tickContainer)
|
||||
AddNested(tick);
|
||||
|
||||
AddNested(head);
|
||||
AddNested(tail);
|
||||
AddNested(Head);
|
||||
AddNested(Tail);
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
@ -92,8 +92,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
glowPiece.AccentColour = value;
|
||||
bodyPiece.AccentColour = value;
|
||||
head.AccentColour = value;
|
||||
tail.AccentColour = value;
|
||||
Head.AccentColour = value;
|
||||
Tail.AccentColour = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (tail.AllJudged)
|
||||
if (Tail.AllJudged)
|
||||
AddJudgement(new HoldNoteJudgement { Result = HitResult.Perfect });
|
||||
}
|
||||
|
||||
@ -119,12 +119,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
base.Update();
|
||||
|
||||
// Make the body piece not lie under the head note
|
||||
bodyPiece.Y = head.Height;
|
||||
bodyPiece.Height = DrawHeight - head.Height;
|
||||
bodyPiece.Y = Head.Height;
|
||||
bodyPiece.Height = DrawHeight - Head.Height;
|
||||
|
||||
// Make the fullHeightContainer "contain" the height of the tail note, keeping in mind
|
||||
// that the tail note overshoots the height of this hit object
|
||||
fullHeightContainer.Height = DrawHeight + tail.Height;
|
||||
fullHeightContainer.Height = DrawHeight + Tail.Height;
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
@ -156,7 +156,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
holdStartTime = null;
|
||||
|
||||
// If the key has been released too early, the user should not receive full score for the release
|
||||
if (!tail.IsHit)
|
||||
if (!Tail.IsHit)
|
||||
hasBroken = true;
|
||||
|
||||
return true;
|
||||
|
@ -1,14 +1,42 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Mania.Objects.Types;
|
||||
using osu.Game.Rulesets.Edit.Types;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
public abstract class ManiaHitObject : HitObject, IHasColumn
|
||||
public abstract class ManiaHitObject : HitObject, IHasColumn, IHasLayer, IHasXPosition, IHasEditableColumn, IHasEditableLayer
|
||||
{
|
||||
public virtual int Column { get; set; }
|
||||
public event Action<int> ColumnChanged;
|
||||
|
||||
private int column { get; set; }
|
||||
|
||||
public virtual int Column
|
||||
{
|
||||
get => column;
|
||||
set
|
||||
{
|
||||
if (column == value)
|
||||
return;
|
||||
column = value;
|
||||
|
||||
ColumnChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int Layer { get; set; }
|
||||
|
||||
public virtual float X
|
||||
{
|
||||
get => Column;
|
||||
}
|
||||
|
||||
public virtual void OffsetColumn(int offset) => Column += offset;
|
||||
|
||||
public virtual void OffsetLayer(int offset) => Layer += offset;
|
||||
|
||||
protected override HitWindows CreateHitWindows() => new ManiaHitWindows();
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
@ -25,7 +25,11 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
public readonly Bindable<bool> Inverted = new Bindable<bool>(true);
|
||||
|
||||
public List<Column> Columns => stages.SelectMany(x => x.Columns).ToList();
|
||||
|
||||
private readonly List<ManiaStage> stages = new List<ManiaStage>();
|
||||
public IReadOnlyList<ManiaStage> Stages => stages;
|
||||
|
||||
protected virtual bool DisplayJudgements => true;
|
||||
|
||||
public ManiaPlayfield(List<StageDefinition> stageDefinitions)
|
||||
: base(ScrollingDirection.Up)
|
||||
@ -50,7 +54,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
int firstColumnIndex = 0;
|
||||
for (int i = 0; i < stageDefinitions.Count; i++)
|
||||
{
|
||||
var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction);
|
||||
var newStage = CreateStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction);
|
||||
newStage.DisplayJudgements = DisplayJudgements;
|
||||
newStage.VisibleTimeRange.BindTo(VisibleTimeRange);
|
||||
newStage.Inverted.BindTo(Inverted);
|
||||
|
||||
@ -63,7 +68,11 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
}
|
||||
}
|
||||
|
||||
public override void Add(DrawableHitObject h) => getStageByColumn(((ManiaHitObject)h.HitObject).Column).Add(h);
|
||||
public override void Add(DrawableHitObject h)
|
||||
{
|
||||
h.OnJudgement += OnJudgement;
|
||||
getStageByColumn(((ManiaHitObject)h.HitObject).Column).Add(h);
|
||||
}
|
||||
|
||||
public void Add(BarLine barline) => stages.ForEach(s => s.Add(barline));
|
||||
|
||||
@ -88,7 +97,13 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
{
|
||||
if (!judgedObject.DisplayJudgement || !DisplayJudgements)
|
||||
return;
|
||||
|
||||
getStageByColumn(((ManiaHitObject)judgedObject.HitObject).Column).OnJudgement(judgedObject, judgement);
|
||||
}
|
||||
|
||||
protected virtual ManiaStage CreateStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction)
|
||||
=> new ManiaStage(firstColumnIndex, definition, ref normalColumnStartAction, ref specialColumnStartAction);
|
||||
}
|
||||
}
|
||||
|
@ -10,4 +10,7 @@
|
||||
<ItemGroup Label="Project References">
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Objects\Types\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
protected ICompositionTool CurrentTool { get; private set; }
|
||||
|
||||
private RulesetContainer rulesetContainer;
|
||||
protected RulesetContainer RulesetContainer;
|
||||
private readonly List<Container> layerContainers = new List<Container>();
|
||||
|
||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
@ -44,8 +44,8 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
try
|
||||
{
|
||||
rulesetContainer = CreateRulesetContainer(ruleset, beatmap.Value);
|
||||
rulesetContainer.Clock = framedClock;
|
||||
RulesetContainer = CreateRulesetContainer(ruleset, beatmap.Value);
|
||||
RulesetContainer.Clock = framedClock;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Edit
|
||||
};
|
||||
|
||||
var layerAboveRuleset = CreateLayerContainer();
|
||||
layerAboveRuleset.Child = new HitObjectMaskLayer(rulesetContainer.Playfield, this);
|
||||
layerAboveRuleset.Child = CreateHitObjectMaskLayer();
|
||||
|
||||
layerContainers.Add(layerBelowRuleset);
|
||||
layerContainers.Add(layerAboveRuleset);
|
||||
@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Edit
|
||||
Children = new Drawable[]
|
||||
{
|
||||
layerBelowRuleset,
|
||||
rulesetContainer,
|
||||
RulesetContainer,
|
||||
layerAboveRuleset
|
||||
}
|
||||
}
|
||||
@ -116,13 +116,14 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
layerContainers.ForEach(l =>
|
||||
{
|
||||
l.Anchor = rulesetContainer.Playfield.Anchor;
|
||||
l.Origin = rulesetContainer.Playfield.Origin;
|
||||
l.Position = rulesetContainer.Playfield.Position;
|
||||
l.Size = rulesetContainer.Playfield.Size;
|
||||
l.Anchor = RulesetContainer.Playfield.Anchor;
|
||||
l.Origin = RulesetContainer.Playfield.Origin;
|
||||
l.Position = RulesetContainer.Playfield.Position;
|
||||
l.Size = RulesetContainer.Playfield.Size;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool;
|
||||
|
||||
protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap);
|
||||
@ -141,6 +142,11 @@ namespace osu.Game.Rulesets.Edit
|
||||
/// </summary>
|
||||
public virtual MaskSelection CreateMaskSelection() => new MaskSelection();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="HitObjectMaskLayer"/> depending on the ruleset.
|
||||
/// </summary>
|
||||
protected virtual HitObjectMaskLayer CreateHitObjectMaskLayer() => new HitObjectMaskLayer(RulesetContainer.Playfield, this);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ScalableContainer"/> which provides a layer above or below the <see cref="Playfield"/>.
|
||||
/// </summary>
|
||||
|
@ -33,11 +33,21 @@ namespace osu.Game.Rulesets.Edit
|
||||
/// </summary>
|
||||
public event Action<HitObjectMask, InputState> SelectionRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when this <see cref="HitObjectMask"/> has started drag.
|
||||
/// </summary>
|
||||
public event Action<HitObjectMask, InputState> DragStarted;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when this <see cref="HitObjectMask"/> has requested drag.
|
||||
/// </summary>
|
||||
public event Action<HitObjectMask, InputState> DragRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when this <see cref="HitObjectMask"/> has ended drag.
|
||||
/// </summary>
|
||||
public event Action<HitObjectMask, InputState> DragEnded;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DrawableHitObject"/> which this <see cref="HitObjectMask"/> applies to.
|
||||
/// </summary>
|
||||
@ -120,7 +130,11 @@ namespace osu.Game.Rulesets.Edit
|
||||
return base.OnClick(state);
|
||||
}
|
||||
|
||||
protected override bool OnDragStart(InputState state) => true;
|
||||
protected override bool OnDragStart(InputState state)
|
||||
{
|
||||
DragStarted?.Invoke(this, state);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDrag(InputState state)
|
||||
{
|
||||
@ -128,6 +142,12 @@ namespace osu.Game.Rulesets.Edit
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDragEnd(InputState state)
|
||||
{
|
||||
DragEnded?.Invoke(this, state);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The screen-space point that causes this <see cref="HitObjectMask"/> to be selected.
|
||||
/// </summary>
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Tools
|
||||
@ -8,6 +10,18 @@ namespace osu.Game.Rulesets.Edit.Tools
|
||||
public class HitObjectCompositionTool<T> : ICompositionTool
|
||||
where T : HitObject
|
||||
{
|
||||
public string Name => typeof(T).Name;
|
||||
public string Name { get; } = typeof(T).Name;
|
||||
|
||||
public Action<InputState, MouseDownEventArgs, bool> OnMouseDown { get; }
|
||||
public Action<InputState, MouseDownEventArgs, bool> OnMouseUp { get; }
|
||||
|
||||
public HitObjectCompositionTool()
|
||||
{
|
||||
}
|
||||
|
||||
public HitObjectCompositionTool(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,16 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Input;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Tools
|
||||
{
|
||||
public interface ICompositionTool
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
Action<InputState, MouseDownEventArgs, bool> OnMouseDown { get; }
|
||||
Action<InputState, MouseDownEventArgs, bool> OnMouseUp { get; }
|
||||
}
|
||||
}
|
||||
|
12
osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs
Normal file
12
osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Types
|
||||
{
|
||||
public interface IHasEditableColumn : IHasColumn
|
||||
{
|
||||
void OffsetColumn(int offset);
|
||||
}
|
||||
}
|
12
osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs
Normal file
12
osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Types
|
||||
{
|
||||
public interface IHasEditableLayer : IHasLayer
|
||||
{
|
||||
void OffsetLayer(int offset);
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Types
|
||||
namespace osu.Game.Rulesets.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of hit object which lies in one of a number of predetermined columns.
|
@ -14,17 +14,17 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
{
|
||||
public class HitObjectMaskLayer : CompositeDrawable
|
||||
{
|
||||
private readonly Playfield playfield;
|
||||
private readonly HitObjectComposer composer;
|
||||
protected readonly Playfield Playfield;
|
||||
protected readonly HitObjectComposer Composer;
|
||||
|
||||
private MaskContainer maskContainer;
|
||||
|
||||
public HitObjectMaskLayer(Playfield playfield, HitObjectComposer composer)
|
||||
{
|
||||
// we need the playfield as HitObjects may not be initialised until its BDL.
|
||||
this.playfield = playfield;
|
||||
this.Playfield = playfield;
|
||||
|
||||
this.composer = composer;
|
||||
this.Composer = composer;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
@ -34,12 +34,14 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
{
|
||||
maskContainer = new MaskContainer();
|
||||
|
||||
var maskSelection = composer.CreateMaskSelection();
|
||||
var maskSelection = Composer.CreateMaskSelection();
|
||||
|
||||
maskContainer.MaskSelected += maskSelection.HandleSelected;
|
||||
maskContainer.MaskDeselected += maskSelection.HandleDeselected;
|
||||
maskContainer.MaskSelectionRequested += maskSelection.HandleSelectionRequested;
|
||||
maskContainer.MaskDragStarted += maskSelection.HandleDragStart;
|
||||
maskContainer.MaskDragRequested += maskSelection.HandleDrag;
|
||||
maskContainer.MaskDragEnded += maskSelection.HandleDragEnd;
|
||||
|
||||
maskSelection.DeselectAll = maskContainer.DeselectAll;
|
||||
|
||||
@ -53,9 +55,13 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
maskContainer,
|
||||
dragLayer.CreateProxy()
|
||||
};
|
||||
AddMasks();
|
||||
}
|
||||
|
||||
foreach (var obj in playfield.HitObjects.Objects)
|
||||
addMask(obj);
|
||||
protected virtual void AddMasks()
|
||||
{
|
||||
foreach (var obj in Playfield.HitObjects.Objects)
|
||||
AddMask(obj);
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
@ -68,9 +74,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
/// Adds a mask for a <see cref="DrawableHitObject"/> which adds movement support.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to create a mask for.</param>
|
||||
private void addMask(DrawableHitObject hitObject)
|
||||
protected void AddMask(DrawableHitObject hitObject)
|
||||
{
|
||||
var mask = composer.CreateMaskFor(hitObject);
|
||||
var mask = Composer.CreateMaskFor(hitObject);
|
||||
if (mask == null)
|
||||
return;
|
||||
|
||||
|
@ -29,11 +29,21 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
/// </summary>
|
||||
public event Action<HitObjectMask, InputState> MaskSelectionRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when any <see cref="HitObjectMask"/> starts drag.
|
||||
/// </summary>
|
||||
public event Action<HitObjectMask, InputState> MaskDragStarted;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when any <see cref="HitObjectMask"/> requests drag.
|
||||
/// </summary>
|
||||
public event Action<HitObjectMask, InputState> MaskDragRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when any <see cref="HitObjectMask"/> ends drag.
|
||||
/// </summary>
|
||||
public event Action<HitObjectMask, InputState> MaskDragEnded;
|
||||
|
||||
private IEnumerable<HitObjectMask> aliveMasks => AliveInternalChildren.Cast<HitObjectMask>();
|
||||
|
||||
public MaskContainer()
|
||||
@ -50,7 +60,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
drawable.Selected += onMaskSelected;
|
||||
drawable.Deselected += onMaskDeselected;
|
||||
drawable.SelectionRequested += onSelectionRequested;
|
||||
drawable.DragStarted += onDragStarted;
|
||||
drawable.DragRequested += onDragRequested;
|
||||
drawable.DragEnded += onDragEnded;
|
||||
}
|
||||
|
||||
public override bool Remove(HitObjectMask drawable)
|
||||
@ -64,7 +76,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
drawable.Selected -= onMaskSelected;
|
||||
drawable.Deselected -= onMaskDeselected;
|
||||
drawable.SelectionRequested -= onSelectionRequested;
|
||||
drawable.DragStarted -= onDragStarted;
|
||||
drawable.DragRequested -= onDragRequested;
|
||||
drawable.DragEnded -= onDragEnded;
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -103,7 +117,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
}
|
||||
|
||||
private void onSelectionRequested(HitObjectMask mask, InputState state) => MaskSelectionRequested?.Invoke(mask, state);
|
||||
private void onDragStarted(HitObjectMask mask, InputState state) => MaskDragStarted?.Invoke(mask, state);
|
||||
private void onDragRequested(HitObjectMask mask, InputState state) => MaskDragRequested?.Invoke(mask, state);
|
||||
private void onDragEnded(HitObjectMask mask, InputState state) => MaskDragEnded?.Invoke(mask, state);
|
||||
|
||||
protected override int Compare(Drawable x, Drawable y)
|
||||
{
|
||||
|
@ -25,6 +25,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
private readonly List<HitObjectMask> selectedMasks;
|
||||
|
||||
private Drawable outline;
|
||||
private Vector2 startingPosition;
|
||||
|
||||
public MaskSelection()
|
||||
{
|
||||
@ -54,6 +55,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
|
||||
#region User Input Handling
|
||||
|
||||
public void HandleDragStart(HitObjectMask m, InputState state) => startingPosition = state.Mouse.Position;
|
||||
public void HandleDrag(HitObjectMask m, InputState state)
|
||||
{
|
||||
// Todo: Various forms of snapping
|
||||
@ -65,9 +67,17 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers
|
||||
case IHasEditablePosition editablePosition:
|
||||
editablePosition.OffsetPosition(state.Mouse.Delta);
|
||||
break;
|
||||
case IHasEditableColumn editableColumn:
|
||||
if (IsDragged)
|
||||
editableColumn.OffsetColumn((int)((startingPosition.X - state.Mouse.Position.X) / m.Width)); // Perform snapping, needs fixing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void HandleDragEnd(HitObjectMask m, InputState state)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user