mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 04:42:58 +08:00
Replace polling logic with direct bindable reactions
This commit is contained in:
parent
a88a8b7d8d
commit
a4e0529617
@ -3,9 +3,11 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
@ -24,6 +26,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
/// Includes selection and manipulation support via a <see cref="Components.SelectionHandler{T}"/>.
|
||||
/// </summary>
|
||||
public abstract class BlueprintContainer<T> : CompositeDrawable, IKeyBindingHandler<PlatformAction>
|
||||
where T : class
|
||||
{
|
||||
protected DragBox DragBox { get; private set; }
|
||||
|
||||
@ -39,6 +42,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IEditorChangeHandler changeHandler { get; set; }
|
||||
|
||||
protected readonly BindableList<T> SelectedItems = new BindableList<T>();
|
||||
|
||||
protected BlueprintContainer()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
@ -47,6 +52,24 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SelectedItems.CollectionChanged += (selectedObjects, args) =>
|
||||
{
|
||||
switch (args.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
foreach (var o in args.NewItems)
|
||||
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Select();
|
||||
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
foreach (var o in args.OldItems)
|
||||
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Deselect();
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
SelectionHandler = CreateSelectionHandler();
|
||||
SelectionHandler.DeselectAll = deselectAll;
|
||||
|
||||
|
@ -2,10 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
@ -24,8 +22,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
|
||||
protected readonly HitObjectComposer Composer;
|
||||
|
||||
private readonly BindableList<HitObject> selectedHitObjects = new BindableList<HitObject>();
|
||||
|
||||
protected EditorBlueprintContainer(HitObjectComposer composer)
|
||||
{
|
||||
Composer = composer;
|
||||
@ -34,23 +30,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
selectedHitObjects.BindTo(Beatmap.SelectedHitObjects);
|
||||
selectedHitObjects.CollectionChanged += (selectedObjects, args) =>
|
||||
{
|
||||
switch (args.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
foreach (var o in args.NewItems)
|
||||
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Select();
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
foreach (var o in args.OldItems)
|
||||
SelectionBlueprints.FirstOrDefault(b => b.Item == o)?.Deselect();
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
SelectedItems.BindTo(Beatmap.SelectedHitObjects);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
|
@ -1,11 +1,16 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
|
||||
namespace osu.Game.Skinning.Editor
|
||||
{
|
||||
@ -18,23 +23,51 @@ namespace osu.Game.Skinning.Editor
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(SkinEditor editor)
|
||||
{
|
||||
SelectedItems.BindTo(editor.SelectedComponents);
|
||||
}
|
||||
|
||||
private readonly List<BindableList<ISkinnableComponent>> targetComponents = new List<BindableList<ISkinnableComponent>>();
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
checkForComponents();
|
||||
// track each target container on the current screen.
|
||||
foreach (var targetContainer in target.ChildrenOfType<SkinnableElementTargetContainer>())
|
||||
{
|
||||
var bindableList = new BindableList<ISkinnableComponent> { BindTarget = targetContainer.Components };
|
||||
bindableList.BindCollectionChanged(componentsChanged, true);
|
||||
|
||||
targetComponents.Add(bindableList);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForComponents()
|
||||
private void componentsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
ISkinnableComponent[] skinnableComponents = target.ChildrenOfType<ISkinnableComponent>().ToArray();
|
||||
switch (e.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
foreach (var item in e.NewItems.Cast<ISkinnableComponent>())
|
||||
AddBlueprintFor(item);
|
||||
break;
|
||||
|
||||
foreach (var c in skinnableComponents)
|
||||
AddBlueprintFor(c);
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
foreach (var item in e.OldItems.Cast<ISkinnableComponent>())
|
||||
RemoveBlueprintFor(item);
|
||||
break;
|
||||
|
||||
// We'd hope to eventually be running this in a more sensible way, but this handles situations where new drawables become present (ie. during ongoing gameplay)
|
||||
// or when drawables in the target are loaded asynchronously and may not be immediately available when this BlueprintContainer is loaded.
|
||||
Scheduler.AddDelayed(checkForComponents, 1000);
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
foreach (var item in e.OldItems.Cast<ISkinnableComponent>())
|
||||
RemoveBlueprintFor(item);
|
||||
|
||||
foreach (var item in e.NewItems.Cast<ISkinnableComponent>())
|
||||
AddBlueprintFor(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override SelectionHandler<ISkinnableComponent> CreateSelectionHandler() => new SkinSelectionHandler();
|
||||
|
@ -18,6 +18,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Skinning.Editor
|
||||
{
|
||||
[Cached(typeof(SkinEditor))]
|
||||
public class SkinEditor : FocusedOverlayContainer
|
||||
{
|
||||
public const double TRANSITION_DURATION = 500;
|
||||
@ -28,11 +29,15 @@ namespace osu.Game.Skinning.Editor
|
||||
|
||||
protected override bool StartHidden => true;
|
||||
|
||||
public readonly BindableList<ISkinnableComponent> SelectedComponents = new BindableList<ISkinnableComponent>();
|
||||
|
||||
[Resolved]
|
||||
private SkinManager skins { get; set; }
|
||||
|
||||
private Bindable<Skin> currentSkin;
|
||||
|
||||
private SkinBlueprintContainer blueprintContainer;
|
||||
|
||||
public SkinEditor(Drawable targetScreen)
|
||||
{
|
||||
this.targetScreen = targetScreen;
|
||||
@ -56,7 +61,7 @@ namespace osu.Game.Skinning.Editor
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X
|
||||
},
|
||||
new SkinBlueprintContainer(targetScreen),
|
||||
blueprintContainer = new SkinBlueprintContainer(targetScreen),
|
||||
new SkinComponentToolbox(600)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
@ -109,9 +114,15 @@ namespace osu.Game.Skinning.Editor
|
||||
|
||||
private void placeComponent(Type type)
|
||||
{
|
||||
Drawable instance = (Drawable)Activator.CreateInstance(type);
|
||||
var instance = (Drawable)Activator.CreateInstance(type) as ISkinnableComponent;
|
||||
|
||||
if (instance == null)
|
||||
throw new InvalidOperationException("Attempted to instantiate a component for placement which was not an {typeof(ISkinnableComponent)}.");
|
||||
|
||||
getTarget(SkinnableTarget.MainHUDComponents)?.Add(instance);
|
||||
|
||||
SelectedComponents.Clear();
|
||||
SelectedComponents.Add(instance);
|
||||
}
|
||||
|
||||
private ISkinnableTarget getTarget(SkinnableTarget target)
|
||||
|
Loading…
Reference in New Issue
Block a user