2019-01-24 08:43:03 +00:00
// 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.
2018-11-12 09:32:44 +00:00
using osu.Framework.Allocation ;
using osu.Framework.Graphics ;
2018-11-29 10:29:36 +00:00
using osu.Framework.Input ;
2018-11-13 05:13:29 +00:00
using osu.Framework.Input.Events ;
2018-11-12 09:32:44 +00:00
using osu.Game.Rulesets.Edit ;
using osu.Game.Rulesets.Mania.Objects ;
2018-11-19 09:40:16 +00:00
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces ;
2018-11-12 09:32:44 +00:00
using osu.Game.Rulesets.Mania.UI ;
using osu.Game.Rulesets.UI.Scrolling ;
2018-11-26 01:44:48 +00:00
using osuTK ;
2020-05-13 05:43:50 +00:00
using osuTK.Input ;
2018-11-12 09:32:44 +00:00
namespace osu.Game.Rulesets.Mania.Edit.Blueprints
{
2018-11-29 10:29:36 +00:00
public abstract class ManiaPlacementBlueprint < T > : PlacementBlueprint ,
IRequireHighFrequencyMousePosition // the playfield could be moving behind us
2018-11-12 09:32:44 +00:00
where T : ManiaHitObject
{
protected new T HitObject = > ( T ) base . HitObject ;
2018-11-29 10:29:36 +00:00
protected Column Column ;
2018-11-13 05:13:29 +00:00
/// <summary>
/// The current mouse position, snapped to the closest column.
/// </summary>
protected Vector2 SnappedMousePosition { get ; private set ; }
2018-11-19 09:40:16 +00:00
/// <summary>
/// The width of the closest column to the current mouse position.
/// </summary>
protected float SnappedWidth { get ; private set ; }
2018-11-12 09:32:44 +00:00
[Resolved]
2018-11-12 10:41:06 +00:00
private IManiaHitObjectComposer composer { get ; set ; }
2018-11-12 09:32:44 +00:00
[Resolved]
private IScrollingInfo scrollingInfo { get ; set ; }
2018-11-19 08:59:52 +00:00
protected ManiaPlacementBlueprint ( T hitObject )
2018-11-12 09:32:44 +00:00
: base ( hitObject )
{
RelativeSizeAxes = Axes . None ;
}
2018-11-29 10:29:36 +00:00
protected override bool OnMouseDown ( MouseDownEvent e )
{
2020-05-13 05:43:50 +00:00
if ( e . Button ! = MouseButton . Left )
return false ;
2018-11-29 10:29:36 +00:00
if ( Column = = null )
return base . OnMouseDown ( e ) ;
HitObject . Column = Column . Index ;
2020-05-20 09:46:15 +00:00
BeginPlacement ( true ) ;
2018-11-29 10:29:36 +00:00
return true ;
}
2020-05-20 10:05:03 +00:00
public override void UpdatePosition ( SnapResult result )
2018-11-13 05:13:29 +00:00
{
2020-02-13 00:03:48 +00:00
if ( ! PlacementActive )
2020-05-20 10:05:03 +00:00
Column = ColumnAt ( result . ScreenSpacePosition ) ;
2018-11-19 09:02:01 +00:00
2019-10-03 07:14:42 +00:00
if ( Column = = null ) return ;
2018-11-19 09:05:21 +00:00
2018-11-29 10:29:36 +00:00
SnappedWidth = Column . DrawWidth ;
2018-11-19 08:59:52 +00:00
2018-11-29 05:15:23 +00:00
// Snap to the column
2018-11-29 10:29:36 +00:00
var parentPos = Parent . ToLocalSpace ( Column . ToScreenSpace ( new Vector2 ( Column . DrawWidth / 2 , 0 ) ) ) ;
2020-05-20 10:05:03 +00:00
SnappedMousePosition = new Vector2 ( parentPos . X , Parent . ToLocalSpace ( result . ScreenSpacePosition ) . Y ) ;
2018-11-12 09:32:44 +00:00
}
2018-11-29 10:29:36 +00:00
protected float PositionAt ( double time )
{
var pos = scrollingInfo . Algorithm . PositionAt ( time ,
EditorClock . CurrentTime ,
scrollingInfo . TimeRange . Value ,
Column . HitObjectContainer . DrawHeight ) ;
2019-10-03 09:23:13 +00:00
if ( scrollingInfo . Direction . Value = = ScrollingDirection . Down )
pos = Column . HitObjectContainer . DrawHeight - pos ;
2019-10-03 09:27:39 +00:00
return hitObjectToMousePosition ( Column . HitObjectContainer . ToSpaceOfOtherDrawable ( new Vector2 ( 0 , pos ) , Parent ) ) . Y ;
2018-11-29 10:29:36 +00:00
}
2018-11-12 09:32:44 +00:00
protected Column ColumnAt ( Vector2 screenSpacePosition )
2019-10-03 09:22:06 +00:00
= > composer . ColumnAt ( screenSpacePosition ) ;
2018-11-12 09:32:44 +00:00
2019-10-03 09:27:39 +00:00
/// <summary>
/// Converts a mouse position to a hitobject position.
/// </summary>
/// <remarks>
/// Blueprints are centred on the mouse position, such that the hitobject position is anchored at the top or bottom of the blueprint depending on the scroll direction.
/// </remarks>
/// <param name="mousePosition">The mouse position.</param>
/// <returns>The resulting hitobject position, acnhored at the top or bottom of the blueprint depending on the scroll direction.</returns>
private Vector2 mouseToHitObjectPosition ( Vector2 mousePosition )
2018-11-12 09:32:44 +00:00
{
2019-10-03 09:21:50 +00:00
switch ( scrollingInfo . Direction . Value )
{
case ScrollingDirection . Up :
2020-03-31 06:29:25 +00:00
mousePosition . Y - = DefaultNotePiece . NOTE_HEIGHT / 2 ;
2019-10-03 09:21:50 +00:00
break ;
case ScrollingDirection . Down :
2020-03-31 06:29:25 +00:00
mousePosition . Y + = DefaultNotePiece . NOTE_HEIGHT / 2 ;
2019-10-03 09:21:50 +00:00
break ;
}
2019-10-03 09:27:39 +00:00
return mousePosition ;
}
/// <summary>
/// Converts a hitobject position to a mouse position.
/// </summary>
/// <param name="hitObjectPosition">The hitobject position.</param>
/// <returns>The resulting mouse position, anchored at the centre of the hitobject.</returns>
private Vector2 hitObjectToMousePosition ( Vector2 hitObjectPosition )
{
switch ( scrollingInfo . Direction . Value )
{
case ScrollingDirection . Up :
2020-03-31 06:29:25 +00:00
hitObjectPosition . Y + = DefaultNotePiece . NOTE_HEIGHT / 2 ;
2019-10-03 09:27:39 +00:00
break ;
case ScrollingDirection . Down :
2020-03-31 06:29:25 +00:00
hitObjectPosition . Y - = DefaultNotePiece . NOTE_HEIGHT / 2 ;
2019-10-03 09:27:39 +00:00
break ;
}
2019-10-03 09:21:50 +00:00
2019-10-03 09:27:39 +00:00
return hitObjectPosition ;
2018-11-12 09:32:44 +00:00
}
}
}