From e8907b53a8678b52657ea75b46a2fcea017e0ecb Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 22 Jun 2021 12:30:09 +0900 Subject: [PATCH] Add basic banana shower placement tool --- .../Edit/BananaShowerCompositionTool.cs | 20 ++++++ .../BananaShowerPlacementBlueprint.cs | 72 +++++++++++++++++++ .../Blueprints/Components/TimeSpanOutline.cs | 61 ++++++++++++++++ .../Edit/CatchHitObjectComposer.cs | 1 + 4 files changed, 154 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs create mode 100644 osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs create mode 100644 osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs diff --git a/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs new file mode 100644 index 0000000000..be18f223eb --- /dev/null +++ b/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Catch.Edit.Blueprints; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Tools; + +namespace osu.Game.Rulesets.Catch.Edit +{ + public class BananaShowerCompositionTool : HitObjectCompositionTool + { + public BananaShowerCompositionTool() + : base(nameof(BananaShower)) + { + } + + public override PlacementBlueprint CreatePlacementBlueprint() => new BananaShowerPlacementBlueprint(); + } +} diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs new file mode 100644 index 0000000000..843cca3c7b --- /dev/null +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs @@ -0,0 +1,72 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Input.Events; +using osu.Game.Rulesets.Catch.Edit.Blueprints.Components; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Edit; +using osuTK.Input; + +namespace osu.Game.Rulesets.Catch.Edit.Blueprints +{ + public class BananaShowerPlacementBlueprint : CatchPlacementBlueprint + { + private readonly TimeSpanOutline outline; + + public BananaShowerPlacementBlueprint() + { + InternalChild = outline = new TimeSpanOutline(); + } + + protected override void Update() + { + base.Update(); + + outline.UpdateFrom(HitObjectContainer, HitObject); + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + switch (PlacementActive) + { + case PlacementState.Waiting: + if (e.Button != MouseButton.Left) break; + + BeginPlacement(true); + return true; + + case PlacementState.Active: + if (e.Button != MouseButton.Right) break; + + if (HitObject.Duration < 0) + { + HitObject.StartTime = HitObject.EndTime; + HitObject.Duration = -HitObject.Duration; + } + + EndPlacement(HitObject.Duration > 0); + return true; + } + + return base.OnMouseDown(e); + } + + public override void UpdateTimeAndPosition(SnapResult result) + { + base.UpdateTimeAndPosition(result); + + if (!(result.Time is double time)) return; + + switch (PlacementActive) + { + case PlacementState.Waiting: + HitObject.StartTime = time; + break; + + case PlacementState.Active: + HitObject.EndTime = time; + break; + } + } + } +} diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs new file mode 100644 index 0000000000..4e5164e965 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs @@ -0,0 +1,61 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.UI.Scrolling; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components +{ + public class TimeSpanOutline : CompositeDrawable + { + private const float border_width = 4; + + private bool isEmpty = true; + + public TimeSpanOutline() + { + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + RelativeSizeAxes = Axes.X; + + Masking = true; + BorderThickness = border_width; + + // a box is needed to make edge visible + InternalChild = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Transparent + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour osuColour) + { + BorderColour = osuColour.Yellow; + } + + public void UpdateFrom(ScrollingHitObjectContainer hitObjectContainer, BananaShower hitObject) + { + float startY = hitObjectContainer.PositionAtTime(hitObject.StartTime); + float endY = hitObjectContainer.PositionAtTime(hitObject.EndTime); + + Y = Math.Max(startY, endY); + float height = Math.Abs(startY - endY); + + bool wasEmpty = isEmpty; + isEmpty = height == 0; + if (wasEmpty != isEmpty) + this.FadeTo(isEmpty ? 0.5f : 1f, 150); + + Height = Math.Max(height, border_width); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 2099be8864..c11e5eb45b 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Catch.Edit protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] { new FruitCompositionTool(), + new BananaShowerCompositionTool() }; public override SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition)