mirror of
https://github.com/ppy/osu.git
synced 2024-12-17 20:02:58 +08:00
Merge pull request #26313 from OliBomby/grids-4
Add grid placement tool
This commit is contained in:
commit
bfad281f62
126
osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs
Normal file
126
osu.Game.Rulesets.Osu/Edit/Blueprints/GridPlacementBlueprint.cs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// 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.Allocation;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Game.Rulesets.Edit;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||||
|
{
|
||||||
|
public partial class GridPlacementBlueprint : PlacementBlueprint
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private HitObjectComposer? hitObjectComposer { get; set; }
|
||||||
|
|
||||||
|
private OsuGridToolboxGroup gridToolboxGroup = null!;
|
||||||
|
private Vector2 originalOrigin;
|
||||||
|
private float originalSpacing;
|
||||||
|
private float originalRotation;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuGridToolboxGroup gridToolboxGroup)
|
||||||
|
{
|
||||||
|
this.gridToolboxGroup = gridToolboxGroup;
|
||||||
|
originalOrigin = gridToolboxGroup.StartPosition.Value;
|
||||||
|
originalSpacing = gridToolboxGroup.Spacing.Value;
|
||||||
|
originalRotation = gridToolboxGroup.GridLinesRotation.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void EndPlacement(bool commit)
|
||||||
|
{
|
||||||
|
if (!commit && PlacementActive != PlacementState.Finished)
|
||||||
|
{
|
||||||
|
gridToolboxGroup.StartPosition.Value = originalOrigin;
|
||||||
|
gridToolboxGroup.Spacing.Value = originalSpacing;
|
||||||
|
if (!gridToolboxGroup.GridLinesRotation.Disabled)
|
||||||
|
gridToolboxGroup.GridLinesRotation.Value = originalRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.EndPlacement(commit);
|
||||||
|
|
||||||
|
// You typically only place the grid once, so we switch back to the last tool after placement.
|
||||||
|
if (commit && hitObjectComposer is OsuHitObjectComposer osuHitObjectComposer)
|
||||||
|
osuHitObjectComposer.SetLastTool();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnClick(ClickEvent e)
|
||||||
|
{
|
||||||
|
if (e.Button == MouseButton.Left)
|
||||||
|
{
|
||||||
|
switch (PlacementActive)
|
||||||
|
{
|
||||||
|
case PlacementState.Waiting:
|
||||||
|
BeginPlacement(true);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case PlacementState.Active:
|
||||||
|
EndPlacement(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.OnClick(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
|
{
|
||||||
|
if (e.Button == MouseButton.Right)
|
||||||
|
{
|
||||||
|
// Reset the grid to the default values.
|
||||||
|
gridToolboxGroup.StartPosition.Value = gridToolboxGroup.StartPosition.Default;
|
||||||
|
gridToolboxGroup.Spacing.Value = gridToolboxGroup.Spacing.Default;
|
||||||
|
if (!gridToolboxGroup.GridLinesRotation.Disabled)
|
||||||
|
gridToolboxGroup.GridLinesRotation.Value = gridToolboxGroup.GridLinesRotation.Default;
|
||||||
|
EndPlacement(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.OnMouseDown(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnDragStart(DragStartEvent e)
|
||||||
|
{
|
||||||
|
if (e.Button == MouseButton.Left)
|
||||||
|
{
|
||||||
|
BeginPlacement(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.OnDragStart(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDragEnd(DragEndEvent e)
|
||||||
|
{
|
||||||
|
if (PlacementActive == PlacementState.Active)
|
||||||
|
EndPlacement(true);
|
||||||
|
|
||||||
|
base.OnDragEnd(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SnapType SnapType => ~SnapType.GlobalGrids;
|
||||||
|
|
||||||
|
public override void UpdateTimeAndPosition(SnapResult result)
|
||||||
|
{
|
||||||
|
var pos = ToLocalSpace(result.ScreenSpacePosition);
|
||||||
|
|
||||||
|
if (PlacementActive != PlacementState.Active)
|
||||||
|
gridToolboxGroup.StartPosition.Value = pos;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Default to the original spacing and rotation if the distance is too small.
|
||||||
|
if (Vector2.Distance(gridToolboxGroup.StartPosition.Value, pos) < 2)
|
||||||
|
{
|
||||||
|
gridToolboxGroup.Spacing.Value = originalSpacing;
|
||||||
|
if (!gridToolboxGroup.GridLinesRotation.Disabled)
|
||||||
|
gridToolboxGroup.GridLinesRotation.Value = originalRotation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gridToolboxGroup.SetGridFromPoints(gridToolboxGroup.StartPosition.Value, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs
Normal file
29
osu.Game.Rulesets.Osu/Edit/GridFromPointsTool.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Rulesets.Edit;
|
||||||
|
using osu.Game.Rulesets.Edit.Tools;
|
||||||
|
using osu.Game.Rulesets.Osu.Edit.Blueprints;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Edit
|
||||||
|
{
|
||||||
|
public partial class GridFromPointsTool : CompositionTool
|
||||||
|
{
|
||||||
|
public GridFromPointsTool()
|
||||||
|
: base("Grid")
|
||||||
|
{
|
||||||
|
TooltipText = """
|
||||||
|
Left click to set the origin.
|
||||||
|
Left click again to set the spacing and rotation.
|
||||||
|
Right click to reset to default.
|
||||||
|
Click and drag to set the origin, spacing and rotation.
|
||||||
|
""";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.Solid.DraftingCompass };
|
||||||
|
|
||||||
|
public override PlacementBlueprint CreatePlacementBlueprint() => new GridPlacementBlueprint();
|
||||||
|
}
|
||||||
|
}
|
@ -11,12 +11,10 @@ using osu.Framework.Graphics.Shapes;
|
|||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Utils;
|
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
|
||||||
using osu.Game.Rulesets.Osu.UI;
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Edit.Components.RadioButtons;
|
using osu.Game.Screens.Edit.Components.RadioButtons;
|
||||||
@ -40,7 +38,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
MinValue = 0f,
|
MinValue = 0f,
|
||||||
MaxValue = OsuPlayfield.BASE_SIZE.X,
|
MaxValue = OsuPlayfield.BASE_SIZE.X,
|
||||||
Precision = 1f
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -50,7 +47,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
MinValue = 0f,
|
MinValue = 0f,
|
||||||
MaxValue = OsuPlayfield.BASE_SIZE.Y,
|
MaxValue = OsuPlayfield.BASE_SIZE.Y,
|
||||||
Precision = 1f
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -60,7 +56,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
MinValue = 4f,
|
MinValue = 4f,
|
||||||
MaxValue = 128f,
|
MaxValue = 128f,
|
||||||
Precision = 1f
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -70,14 +65,13 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
MinValue = -180f,
|
MinValue = -180f,
|
||||||
MaxValue = 180f,
|
MaxValue = 180f,
|
||||||
Precision = 1f
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read-only bindable representing the grid's origin.
|
/// Read-only bindable representing the grid's origin.
|
||||||
/// Equivalent to <code>new Vector2(StartPositionX, StartPositionY)</code>
|
/// Equivalent to <code>new Vector2(StartPositionX, StartPositionY)</code>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Bindable<Vector2> StartPosition { get; } = new Bindable<Vector2>();
|
public Bindable<Vector2> StartPosition { get; } = new Bindable<Vector2>(OsuPlayfield.BASE_SIZE / 2);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read-only bindable representing the grid's spacing in both the X and Y dimension.
|
/// Read-only bindable representing the grid's spacing in both the X and Y dimension.
|
||||||
@ -93,8 +87,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
private ExpandableSlider<float> gridLinesRotationSlider = null!;
|
private ExpandableSlider<float> gridLinesRotationSlider = null!;
|
||||||
private EditorRadioButtonCollection gridTypeButtons = null!;
|
private EditorRadioButtonCollection gridTypeButtons = null!;
|
||||||
|
|
||||||
private ExpandableButton useSelectedObjectPositionButton = null!;
|
|
||||||
|
|
||||||
public OsuGridToolboxGroup()
|
public OsuGridToolboxGroup()
|
||||||
: base("grid")
|
: base("grid")
|
||||||
{
|
{
|
||||||
@ -102,6 +94,26 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
|
|
||||||
private const float max_automatic_spacing = 64;
|
private const float max_automatic_spacing = 64;
|
||||||
|
|
||||||
|
public void SetGridFromPoints(Vector2 point1, Vector2 point2)
|
||||||
|
{
|
||||||
|
StartPositionX.Value = point1.X;
|
||||||
|
StartPositionY.Value = point1.Y;
|
||||||
|
|
||||||
|
// Get the angle between the two points and normalize to the valid range.
|
||||||
|
if (!GridLinesRotation.Disabled)
|
||||||
|
{
|
||||||
|
float period = GridLinesRotation.MaxValue - GridLinesRotation.MinValue;
|
||||||
|
GridLinesRotation.Value = normalizeRotation(MathHelper.RadiansToDegrees(MathF.Atan2(point2.Y - point1.Y, point2.X - point1.X)), period);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divide the distance so that there is a good density of grid lines.
|
||||||
|
// This matches the maximum grid size of the grid size cycling hotkey.
|
||||||
|
float dist = Vector2.Distance(point1, point2);
|
||||||
|
while (dist >= max_automatic_spacing)
|
||||||
|
dist /= 2;
|
||||||
|
Spacing.Value = dist;
|
||||||
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
@ -117,20 +129,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
Current = StartPositionY,
|
Current = StartPositionY,
|
||||||
KeyboardStep = 1,
|
KeyboardStep = 1,
|
||||||
},
|
},
|
||||||
useSelectedObjectPositionButton = new ExpandableButton
|
|
||||||
{
|
|
||||||
ExpandedLabelText = "Centre on selected object",
|
|
||||||
Action = () =>
|
|
||||||
{
|
|
||||||
if (editorBeatmap.SelectedHitObjects.Count != 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var position = ((IHasPosition)editorBeatmap.SelectedHitObjects.Single()).Position;
|
|
||||||
StartPosition.Value = new Vector2(MathF.Round(position.X), MathF.Round(position.Y));
|
|
||||||
updateEnabledStates();
|
|
||||||
},
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
},
|
|
||||||
spacingSlider = new ExpandableSlider<float>
|
spacingSlider = new ExpandableSlider<float>
|
||||||
{
|
{
|
||||||
Current = Spacing,
|
Current = Spacing,
|
||||||
@ -179,15 +177,15 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
|
|
||||||
StartPositionX.BindValueChanged(x =>
|
StartPositionX.BindValueChanged(x =>
|
||||||
{
|
{
|
||||||
startPositionXSlider.ContractedLabelText = $"X: {x.NewValue:N0}";
|
startPositionXSlider.ContractedLabelText = $"X: {x.NewValue:#,0.##}";
|
||||||
startPositionXSlider.ExpandedLabelText = $"X Offset: {x.NewValue:N0}";
|
startPositionXSlider.ExpandedLabelText = $"X Offset: {x.NewValue:#,0.##}";
|
||||||
StartPosition.Value = new Vector2(x.NewValue, StartPosition.Value.Y);
|
StartPosition.Value = new Vector2(x.NewValue, StartPosition.Value.Y);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
StartPositionY.BindValueChanged(y =>
|
StartPositionY.BindValueChanged(y =>
|
||||||
{
|
{
|
||||||
startPositionYSlider.ContractedLabelText = $"Y: {y.NewValue:N0}";
|
startPositionYSlider.ContractedLabelText = $"Y: {y.NewValue:#,0.##}";
|
||||||
startPositionYSlider.ExpandedLabelText = $"Y Offset: {y.NewValue:N0}";
|
startPositionYSlider.ExpandedLabelText = $"Y Offset: {y.NewValue:#,0.##}";
|
||||||
StartPosition.Value = new Vector2(StartPosition.Value.X, y.NewValue);
|
StartPosition.Value = new Vector2(StartPosition.Value.X, y.NewValue);
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
@ -195,13 +193,12 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
StartPositionX.Value = pos.NewValue.X;
|
StartPositionX.Value = pos.NewValue.X;
|
||||||
StartPositionY.Value = pos.NewValue.Y;
|
StartPositionY.Value = pos.NewValue.Y;
|
||||||
updateEnabledStates();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Spacing.BindValueChanged(spacing =>
|
Spacing.BindValueChanged(spacing =>
|
||||||
{
|
{
|
||||||
spacingSlider.ContractedLabelText = $"S: {spacing.NewValue:N0}";
|
spacingSlider.ContractedLabelText = $"S: {spacing.NewValue:#,0.##}";
|
||||||
spacingSlider.ExpandedLabelText = $"Spacing: {spacing.NewValue:N0}";
|
spacingSlider.ExpandedLabelText = $"Spacing: {spacing.NewValue:#,0.##}";
|
||||||
SpacingVector.Value = new Vector2(spacing.NewValue);
|
SpacingVector.Value = new Vector2(spacing.NewValue);
|
||||||
editorBeatmap.BeatmapInfo.GridSize = (int)spacing.NewValue;
|
editorBeatmap.BeatmapInfo.GridSize = (int)spacing.NewValue;
|
||||||
}, true);
|
}, true);
|
||||||
@ -219,34 +216,29 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
switch (v.NewValue)
|
switch (v.NewValue)
|
||||||
{
|
{
|
||||||
case PositionSnapGridType.Square:
|
case PositionSnapGridType.Square:
|
||||||
GridLinesRotation.Value = ((GridLinesRotation.Value + 405) % 90) - 45;
|
GridLinesRotation.Value = normalizeRotation(GridLinesRotation.Value, 90);
|
||||||
GridLinesRotation.MinValue = -45;
|
GridLinesRotation.MinValue = -45;
|
||||||
GridLinesRotation.MaxValue = 45;
|
GridLinesRotation.MaxValue = 45;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PositionSnapGridType.Triangle:
|
case PositionSnapGridType.Triangle:
|
||||||
GridLinesRotation.Value = ((GridLinesRotation.Value + 390) % 60) - 30;
|
GridLinesRotation.Value = normalizeRotation(GridLinesRotation.Value, 60);
|
||||||
GridLinesRotation.MinValue = -30;
|
GridLinesRotation.MinValue = -30;
|
||||||
GridLinesRotation.MaxValue = 30;
|
GridLinesRotation.MaxValue = 30;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
editorBeatmap.BeatmapReprocessed += updateEnabledStates;
|
|
||||||
editorBeatmap.SelectedHitObjects.BindCollectionChanged((_, _) => updateEnabledStates());
|
|
||||||
expandingContainer?.Expanded.BindValueChanged(v =>
|
expandingContainer?.Expanded.BindValueChanged(v =>
|
||||||
{
|
{
|
||||||
gridTypeButtons.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint);
|
gridTypeButtons.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint);
|
||||||
gridTypeButtons.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None;
|
gridTypeButtons.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None;
|
||||||
updateEnabledStates();
|
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateEnabledStates()
|
private float normalizeRotation(float rotation, float period)
|
||||||
{
|
{
|
||||||
useSelectedObjectPositionButton.Enabled.Value = expandingContainer?.Expanded.Value == true
|
return ((rotation + 360 + period * 0.5f) % period) - period * 0.5f;
|
||||||
&& editorBeatmap.SelectedHitObjects.Count == 1
|
|
||||||
&& !Precision.AlmostEquals(StartPosition.Value, ((IHasPosition)editorBeatmap.SelectedHitObjects.Single()).Position, 0.5f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void nextGridSize()
|
private void nextGridSize()
|
||||||
|
@ -45,7 +45,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
new HitCircleCompositionTool(),
|
new HitCircleCompositionTool(),
|
||||||
new SliderCompositionTool(),
|
new SliderCompositionTool(),
|
||||||
new SpinnerCompositionTool()
|
new SpinnerCompositionTool(),
|
||||||
|
new GridFromPointsTool()
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly Bindable<TernaryState> rectangularGridSnapToggle = new Bindable<TernaryState>();
|
private readonly Bindable<TernaryState> rectangularGridSnapToggle = new Bindable<TernaryState>();
|
||||||
@ -79,13 +80,12 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
// Give a bit of breathing room around the playfield content.
|
// Give a bit of breathing room around the playfield content.
|
||||||
PlayfieldContentContainer.Padding = new MarginPadding(10);
|
PlayfieldContentContainer.Padding = new MarginPadding(10);
|
||||||
|
|
||||||
LayerBelowRuleset.AddRange(new Drawable[]
|
LayerBelowRuleset.Add(
|
||||||
{
|
|
||||||
distanceSnapGridContainer = new Container
|
distanceSnapGridContainer = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
selectedHitObjects = EditorBeatmap.SelectedHitObjects.GetBoundCopy();
|
selectedHitObjects = EditorBeatmap.SelectedHitObjects.GetBoundCopy();
|
||||||
selectedHitObjects.CollectionChanged += (_, _) => updateDistanceSnapGrid();
|
selectedHitObjects.CollectionChanged += (_, _) => updateDistanceSnapGrid();
|
||||||
|
@ -20,13 +20,13 @@ namespace osu.Game.Overlays.Settings
|
|||||||
Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS };
|
Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS };
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalisableString TooltipText { get; set; }
|
|
||||||
|
|
||||||
public IEnumerable<string> Keywords { get; set; } = Array.Empty<string>();
|
public IEnumerable<string> Keywords { get; set; } = Array.Empty<string>();
|
||||||
|
|
||||||
public BindableBool CanBeShown { get; } = new BindableBool(true);
|
public BindableBool CanBeShown { get; } = new BindableBool(true);
|
||||||
IBindable<bool> IConditionalFilterable.CanBeShown => CanBeShown;
|
IBindable<bool> IConditionalFilterable.CanBeShown => CanBeShown;
|
||||||
|
|
||||||
|
public LocalisableString TooltipText { get; set; }
|
||||||
|
|
||||||
public override IEnumerable<LocalisableString> FilterTerms
|
public override IEnumerable<LocalisableString> FilterTerms
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -90,6 +90,9 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
private Bindable<bool> autoSeekOnPlacement;
|
private Bindable<bool> autoSeekOnPlacement;
|
||||||
private readonly Bindable<bool> composerFocusMode = new Bindable<bool>();
|
private readonly Bindable<bool> composerFocusMode = new Bindable<bool>();
|
||||||
|
|
||||||
|
[CanBeNull]
|
||||||
|
private RadioButton lastTool;
|
||||||
|
|
||||||
protected DrawableRuleset<TObject> DrawableRuleset { get; private set; }
|
protected DrawableRuleset<TObject> DrawableRuleset { get; private set; }
|
||||||
|
|
||||||
protected HitObjectComposer(Ruleset ruleset)
|
protected HitObjectComposer(Ruleset ruleset)
|
||||||
@ -213,8 +216,7 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
toolboxCollection.Items = CompositionTools
|
toolboxCollection.Items = (CompositionTools.Prepend(new SelectTool()))
|
||||||
.Prepend(new SelectTool())
|
|
||||||
.Select(t => new HitObjectCompositionToolButton(t, () => toolSelected(t)))
|
.Select(t => new HitObjectCompositionToolButton(t, () => toolSelected(t)))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -231,7 +233,7 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
|
|
||||||
sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates.Select(b => new DrawableTernaryButton(b)));
|
sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates.Select(b => new DrawableTernaryButton(b)));
|
||||||
|
|
||||||
setSelectTool();
|
SetSelectTool();
|
||||||
|
|
||||||
EditorBeatmap.SelectedHitObjects.CollectionChanged += selectionChanged;
|
EditorBeatmap.SelectedHitObjects.CollectionChanged += selectionChanged;
|
||||||
}
|
}
|
||||||
@ -256,7 +258,7 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
{
|
{
|
||||||
// it's important this is performed before the similar code in EditorRadioButton disables the button.
|
// it's important this is performed before the similar code in EditorRadioButton disables the button.
|
||||||
if (!timing.NewValue)
|
if (!timing.NewValue)
|
||||||
setSelectTool();
|
SetSelectTool();
|
||||||
});
|
});
|
||||||
|
|
||||||
EditorBeatmap.HasTiming.BindValueChanged(hasTiming =>
|
EditorBeatmap.HasTiming.BindValueChanged(hasTiming =>
|
||||||
@ -460,14 +462,18 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
if (EditorBeatmap.SelectedHitObjects.Any())
|
if (EditorBeatmap.SelectedHitObjects.Any())
|
||||||
{
|
{
|
||||||
// ensure in selection mode if a selection is made.
|
// ensure in selection mode if a selection is made.
|
||||||
setSelectTool();
|
SetSelectTool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSelectTool() => toolboxCollection.Items.First().Select();
|
public void SetSelectTool() => toolboxCollection.Items.First().Select();
|
||||||
|
|
||||||
|
public void SetLastTool() => (lastTool ?? toolboxCollection.Items.First()).Select();
|
||||||
|
|
||||||
private void toolSelected(CompositionTool tool)
|
private void toolSelected(CompositionTool tool)
|
||||||
{
|
{
|
||||||
|
lastTool = toolboxCollection.Items.OfType<HitObjectCompositionToolButton>().FirstOrDefault(i => i.Tool == BlueprintContainer.CurrentTool);
|
||||||
|
|
||||||
BlueprintContainer.CurrentTool = tool;
|
BlueprintContainer.CurrentTool = tool;
|
||||||
|
|
||||||
if (!(tool is SelectTool))
|
if (!(tool is SelectTool))
|
||||||
|
@ -71,6 +71,11 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
PlacementActive = PlacementState.Finished;
|
PlacementActive = PlacementState.Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines which objects to snap to for the snap result in <see cref="UpdateTimeAndPosition"/>.
|
||||||
|
/// </summary>
|
||||||
|
public virtual SnapType SnapType => SnapType.All;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the time and position of this <see cref="PlacementBlueprint"/> based on the provided snap information.
|
/// Updates the time and position of this <see cref="PlacementBlueprint"/> based on the provided snap information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -297,7 +297,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
|
|
||||||
private void updatePlacementPosition()
|
private void updatePlacementPosition()
|
||||||
{
|
{
|
||||||
var snapResult = Composer.FindSnappedPositionAndTime(InputManager.CurrentState.Mouse.Position);
|
var snapResult = Composer.FindSnappedPositionAndTime(InputManager.CurrentState.Mouse.Position, CurrentPlacement.SnapType);
|
||||||
|
|
||||||
// if no time was found from positional snapping, we should still quantize to the beat.
|
// if no time was found from positional snapping, we should still quantize to the beat.
|
||||||
snapResult.Time ??= Beatmap.SnapTime(EditorClock.CurrentTime, null);
|
snapResult.Time ??= Beatmap.SnapTime(EditorClock.CurrentTime, null);
|
||||||
|
Loading…
Reference in New Issue
Block a user