1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 01:43:15 +08:00

Make hitobject pieces able to update dynamically

This commit is contained in:
smoogipoo 2019-09-27 18:45:22 +09:00
parent 4fc37d1137
commit bddaead72e
14 changed files with 125 additions and 95 deletions

View File

@ -0,0 +1,25 @@
// 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.
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints
{
/// <summary>
/// A piece of a selection or placement blueprint which visualises an <see cref="OsuHitObject"/>.
/// </summary>
/// <typeparam name="T">The type of <see cref="OsuHitObject"/> which this <see cref="BlueprintPiece{T}"/> visualises.</typeparam>
public abstract class BlueprintPiece<T> : CompositeDrawable
where T : OsuHitObject
{
/// <summary>
/// Updates this <see cref="BlueprintPiece{T}"/> using the properties of a <see cref="OsuHitObject"/>.
/// </summary>
/// <param name="hitObject">The <see cref="OsuHitObject"/> to reference properties from.</param>
public virtual void UpdateFrom(T hitObject)
{
Position = hitObject.Position;
}
}
}

View File

@ -3,7 +3,6 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
@ -11,17 +10,13 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components
{
public class HitCirclePiece : CompositeDrawable
public class HitCirclePiece : BlueprintPiece<HitCircle>
{
private readonly HitCircle hitCircle;
public HitCirclePiece(HitCircle hitCircle)
public HitCirclePiece()
{
this.hitCircle = hitCircle;
Origin = Anchor.Centre;
Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Scale = new Vector2(hitCircle.Scale);
CornerRadius = Size.X / 2;
InternalChild = new RingPiece();
@ -33,14 +28,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components
Colour = colours.Yellow;
}
protected override void Update()
public override void UpdateFrom(HitCircle hitObject)
{
base.Update();
base.UpdateFrom(hitObject);
UpdatePosition();
Scale = new Vector2(hitCircle.Scale);
Scale = new Vector2(hitObject.Scale);
}
protected virtual void UpdatePosition() => Position = hitCircle.StackedPosition;
}
}

View File

@ -13,10 +13,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
{
public new HitCircle HitObject => (HitCircle)base.HitObject;
private readonly HitCirclePiece circlePiece;
public HitCirclePlacementBlueprint()
: base(new HitCircle())
{
InternalChild = new HitCirclePiece(HitObject);
InternalChild = circlePiece = new HitCirclePiece();
}
protected override void LoadComplete()
@ -27,6 +29,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
HitObject.Position = Parent?.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position) ?? Vector2.Zero;
}
protected override void Update()
{
base.Update();
circlePiece.UpdateFrom(HitObject);
}
protected override bool OnClick(ClickEvent e)
{
HitObject.StartTime = EditorClock.CurrentTime;

View File

@ -7,12 +7,21 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
{
public class HitCircleSelectionBlueprint : OsuSelectionBlueprint
public class HitCircleSelectionBlueprint : OsuSelectionBlueprint<HitCircle>
{
private readonly HitCirclePiece circlePiece;
public HitCircleSelectionBlueprint(DrawableHitCircle hitCircle)
: base(hitCircle)
{
InternalChild = new HitCirclePiece((HitCircle)hitCircle.HitObject);
InternalChild = circlePiece = new HitCirclePiece();
}
protected override void Update()
{
base.Update();
circlePiece.UpdateFrom(HitObject);
}
}
}

View File

@ -7,11 +7,12 @@ using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints
{
public class OsuSelectionBlueprint : SelectionBlueprint
public abstract class OsuSelectionBlueprint<T> : SelectionBlueprint
where T : OsuHitObject
{
protected OsuHitObject OsuObject => (OsuHitObject)HitObject.HitObject;
protected new T HitObject => (T)base.HitObject.HitObject;
public OsuSelectionBlueprint(DrawableHitObject hitObject)
protected OsuSelectionBlueprint(DrawableHitObject hitObject)
: base(hitObject)
{
}

View File

@ -14,7 +14,7 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
public class PathControlPointPiece : CompositeDrawable
public class PathControlPointPiece : BlueprintPiece<Slider>
{
private readonly Slider slider;
private readonly int index;

View File

@ -3,7 +3,6 @@
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
@ -12,18 +11,15 @@ using osuTK.Graphics;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
public class SliderBodyPiece : CompositeDrawable
public class SliderBodyPiece : BlueprintPiece<Slider>
{
private readonly Slider slider;
private readonly ManualSliderBody body;
public SliderBodyPiece(Slider slider)
public SliderBodyPiece()
{
this.slider = slider;
InternalChild = body = new ManualSliderBody
{
AccentColour = Color4.Transparent,
AccentColour = Color4.Transparent
};
}
@ -33,17 +29,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
body.BorderColour = colours.Yellow;
}
private void updatePosition() => Position = slider.StackedPosition;
protected override void Update()
public override void UpdateFrom(Slider hitObject)
{
base.Update();
base.UpdateFrom(hitObject);
Position = slider.StackedPosition;
body.PathRadius = slider.Scale * OsuHitObject.OBJECT_RADIUS;
body.PathRadius = hitObject.Scale * OsuHitObject.OBJECT_RADIUS;
var vertices = new List<Vector2>();
slider.Path.GetPathToProgress(vertices, 0, 1);
hitObject.Path.GetPathToProgress(vertices, 0, 1);
body.SetVertices(vertices);

View File

@ -1,35 +0,0 @@
// 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.
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
{
public class SliderCirclePiece : HitCirclePiece
{
private readonly Slider slider;
private readonly SliderPosition position;
public SliderCirclePiece(Slider slider, SliderPosition position)
: base(slider.HeadCircle)
{
this.slider = slider;
this.position = position;
}
protected override void UpdatePosition()
{
switch (position)
{
case SliderPosition.Start:
Position = slider.StackedPosition + slider.Path.PositionAt(0);
break;
case SliderPosition.End:
Position = slider.StackedPosition + slider.Path.PositionAt(1);
break;
}
}
}
}

View File

@ -1,22 +1,33 @@
// 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.
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint
public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint<Slider>
{
public SliderCircleSelectionBlueprint(DrawableOsuHitObject hitObject, Slider slider, SliderPosition position)
: base(hitObject)
private readonly SliderPosition position;
private readonly HitCirclePiece circlePiece;
public SliderCircleSelectionBlueprint(DrawableSlider slider, SliderPosition position)
: base(slider)
{
InternalChild = new SliderCirclePiece(slider, position);
this.position = position;
InternalChild = circlePiece = new HitCirclePiece();
Select();
}
protected override void Update()
{
base.Update();
circlePiece.UpdateFrom(position == SliderPosition.Start ? HitObject.HeadCircle : HitObject.TailCircle);
}
// Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input.
public override bool HandlePositionalInput => false;
}

View File

@ -11,6 +11,7 @@ using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
using osuTK;
using osuTK.Input;
@ -21,6 +22,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
public new Objects.Slider HitObject => (Objects.Slider)base.HitObject;
private SliderBodyPiece bodyPiece;
private HitCirclePiece headCirclePiece;
private HitCirclePiece tailCirclePiece;
private readonly List<Segment> segments = new List<Segment>();
private Vector2 cursor;
@ -38,9 +43,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
InternalChildren = new Drawable[]
{
new SliderBodyPiece(HitObject),
new SliderCirclePiece(HitObject, SliderPosition.Start),
new SliderCirclePiece(HitObject, SliderPosition.End),
bodyPiece = new SliderBodyPiece(),
headCirclePiece = new HitCirclePiece(),
tailCirclePiece = new HitCirclePiece(),
new PathControlPointVisualiser(HitObject),
};
@ -130,6 +135,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
var newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray();
HitObject.Path = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints);
bodyPiece.UpdateFrom(HitObject);
headCirclePiece.UpdateFrom(HitObject.HeadCircle);
tailCirclePiece.UpdateFrom(HitObject.TailCircle);
}
private void setState(PlacementState newState)

View File

@ -9,8 +9,9 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{
public class SliderSelectionBlueprint : OsuSelectionBlueprint
public class SliderSelectionBlueprint : OsuSelectionBlueprint<Slider>
{
private readonly SliderBodyPiece bodyPiece;
private readonly SliderCircleSelectionBlueprint headBlueprint;
public SliderSelectionBlueprint(DrawableSlider slider)
@ -20,13 +21,20 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
InternalChildren = new Drawable[]
{
new SliderBodyPiece(sliderObject),
headBlueprint = new SliderCircleSelectionBlueprint(slider.HeadCircle, sliderObject, SliderPosition.Start),
new SliderCircleSelectionBlueprint(slider.TailCircle, sliderObject, SliderPosition.End),
bodyPiece = new SliderBodyPiece(),
headBlueprint = new SliderCircleSelectionBlueprint(slider, SliderPosition.Start),
new SliderCircleSelectionBlueprint(slider, SliderPosition.End),
new PathControlPointVisualiser(sliderObject),
};
}
protected override void Update()
{
base.Update();
bodyPiece.UpdateFrom(HitObject);
}
public override Vector2 SelectionPoint => headBlueprint.SelectionPoint;
}
}

View File

@ -12,16 +12,13 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components
{
public class SpinnerPiece : CompositeDrawable
public class SpinnerPiece : BlueprintPiece<Spinner>
{
private readonly Spinner spinner;
private readonly CircularContainer circle;
private readonly RingPiece ring;
public SpinnerPiece(Spinner spinner)
public SpinnerPiece()
{
this.spinner = spinner;
Origin = Anchor.Centre;
RelativeSizeAxes = Axes.Both;
@ -43,8 +40,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components
Origin = Anchor.Centre
}
};
ring.Scale = new Vector2(spinner.Scale);
}
[BackgroundDependencyLoader]
@ -53,12 +48,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components
Colour = colours.Yellow;
}
protected override void Update()
public override void UpdateFrom(Spinner hitObject)
{
base.Update();
base.UpdateFrom(hitObject);
Position = spinner.Position;
ring.Scale = new Vector2(spinner.Scale);
ring.Scale = new Vector2(hitObject.Scale);
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => circle.ReceivePositionalInputAt(screenSpacePos);

View File

@ -21,7 +21,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners
public SpinnerPlacementBlueprint()
: base(new Spinner { Position = OsuPlayfield.BASE_SIZE / 2 })
{
InternalChild = piece = new SpinnerPiece(HitObject) { Alpha = 0.5f };
InternalChild = piece = new SpinnerPiece { Alpha = 0.5f };
}
protected override void Update()
{
base.Update();
piece.UpdateFrom(HitObject);
}
protected override bool OnClick(ClickEvent e)

View File

@ -8,14 +8,21 @@ using osuTK;
namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners
{
public class SpinnerSelectionBlueprint : OsuSelectionBlueprint
public class SpinnerSelectionBlueprint : OsuSelectionBlueprint<Spinner>
{
private readonly SpinnerPiece piece;
public SpinnerSelectionBlueprint(DrawableSpinner spinner)
: base(spinner)
{
InternalChild = piece = new SpinnerPiece((Spinner)spinner.HitObject);
InternalChild = piece = new SpinnerPiece();
}
protected override void Update()
{
base.Update();
piece.UpdateFrom(HitObject);
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos);