ui effects working
This commit is contained in:
parent
816a779678
commit
4ea0f58bc7
28 changed files with 327 additions and 137 deletions
|
@ -10,13 +10,16 @@ MonoBehaviour:
|
|||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 94cc50e7b5f20a817aef3384d0889279, type: 3}
|
||||
m_Name: New Transition Effect
|
||||
m_Name: Fade In
|
||||
m_EditorClassIdentifier:
|
||||
propertyName:
|
||||
addTransition: 1
|
||||
propertyName: opacity
|
||||
duration:
|
||||
duration: 0
|
||||
unit: 0
|
||||
easing: 0
|
||||
duration: 0.3
|
||||
unit: 2
|
||||
easing: 3
|
||||
delay:
|
||||
duration: 0
|
||||
unit: 0
|
||||
unit: 2
|
||||
from: 0
|
||||
to: 1
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 630c186ef2ab4b37495b5001d208878f
|
||||
guid: 0902dc21238be2bb3ae758e1d5218922
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
|
@ -9,9 +9,12 @@ MonoBehaviour:
|
|||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 0}
|
||||
m_Script: {fileID: 11500000, guid: 0b01085379e9a10319622dd3dd23f4bd, type: 3}
|
||||
m_Name: Modal
|
||||
m_EditorClassIdentifier: Assembly-CSharp:KitsuneCafe.UI:ModalElementSO
|
||||
m_EditorClassIdentifier:
|
||||
visualTreeAsset: {fileID: 9197481963319205126, guid: bc70bdaaf37609283aac14435c5441a2, type: 3}
|
||||
effects:
|
||||
- timing: 0
|
||||
effect: {fileID: 11400000, guid: 0902dc21238be2bb3ae758e1d5218922, type: 2}
|
||||
titleId: title
|
||||
contentId: content
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1a47b12328bfde496ab2f3847d762a79
|
||||
guid: 71a6f29fae4392a4f97870a52b6adf1e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0b01085379e9a10319622dd3dd23f4bd, type: 3}
|
||||
m_Name: New Modal Element
|
||||
m_EditorClassIdentifier:
|
||||
visualTreeAsset: {fileID: 9197481963319205126, guid: bc70bdaaf37609283aac14435c5441a2, type: 3}
|
||||
titleId: title
|
||||
contentId: content
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 71a6f29fae4392a4f97870a52b6adf1e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
6
Assets/Scripts/Extension/Collection.cs
Normal file
6
Assets/Scripts/Extension/Collection.cs
Normal file
|
@ -0,0 +1,6 @@
|
|||
namespace KitsuneCafe.Extension
|
||||
{
|
||||
public static class CollectionExtension
|
||||
{
|
||||
}
|
||||
}
|
2
Assets/Scripts/Extension/Collection.cs.meta
Normal file
2
Assets/Scripts/Extension/Collection.cs.meta
Normal file
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4134cfdaf5630d9e49cdf518b31bc662
|
|
@ -4,6 +4,7 @@ using System;
|
|||
using KitsuneCafe.System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace KitsuneCafe.Extension
|
||||
{
|
||||
|
@ -177,6 +178,29 @@ namespace KitsuneCafe.Extension
|
|||
{
|
||||
return source.Where(Func.Identity);
|
||||
}
|
||||
|
||||
public static Observable<T> ObserveBool<T>(this T component, Func<T, bool> predicate) where T : MonoBehaviour
|
||||
{
|
||||
if (predicate(component))
|
||||
{
|
||||
return Observable.Return(component);
|
||||
}
|
||||
|
||||
return Observable.EveryValueChanged(component, predicate)
|
||||
.Where(Func.Identity)
|
||||
.Take(1)
|
||||
.Select(_ => component);
|
||||
}
|
||||
|
||||
public static Observable<T> ObserveAwake<T>(this T component) where T : MonoBehaviour
|
||||
{
|
||||
return component.ObserveBool(c => c.didAwake);
|
||||
}
|
||||
|
||||
public static Observable<T> ObserveStart<T>(this T component) where T : MonoBehaviour
|
||||
{
|
||||
return component.ObserveBool(c => c.didStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
40
Assets/Scripts/UI/Effect/AddTransitionEffect.cs
Normal file
40
Assets/Scripts/UI/Effect/AddTransitionEffect.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using R3;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
public readonly struct AddTransitionEffect : IUiEffect
|
||||
{
|
||||
public readonly StylePropertyName PropertyName;
|
||||
public readonly TimeValue Duration;
|
||||
public readonly EasingFunction Easing;
|
||||
public readonly TimeValue Delay;
|
||||
public readonly IUiEffect Effect;
|
||||
|
||||
public AddTransitionEffect(StylePropertyName name, TimeValue duration, EasingFunction easing, TimeValue delay, IUiEffect effect)
|
||||
{
|
||||
PropertyName = name;
|
||||
Duration = duration;
|
||||
Easing = easing;
|
||||
Delay = delay;
|
||||
Effect = effect;
|
||||
}
|
||||
|
||||
private static StyleList<T> ToStyleList<T>(T value)
|
||||
{
|
||||
return new StyleList<T>(new List<T> { value });
|
||||
}
|
||||
|
||||
public Observable<R3.Unit> Execute(VisualElement target, CancellationToken token)
|
||||
{
|
||||
target.style.transitionProperty = ToStyleList(PropertyName);
|
||||
target.style.transitionDuration = ToStyleList(Duration);
|
||||
target.style.transitionTimingFunction = ToStyleList(Easing);
|
||||
target.style.transitionDelay = ToStyleList(Delay);
|
||||
|
||||
return Effect.Execute(target, token);
|
||||
}
|
||||
}
|
||||
}
|
2
Assets/Scripts/UI/Effect/AddTransitionEffect.cs.meta
Normal file
2
Assets/Scripts/UI/Effect/AddTransitionEffect.cs.meta
Normal file
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a0412a2b6dff88311aec68b3fc4dee47
|
|
@ -1,4 +1,6 @@
|
|||
using System.Threading;
|
||||
using KitsuneCafe.System;
|
||||
using KitsuneCafe.System.Attributes;
|
||||
using R3;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
@ -6,44 +8,72 @@ using UnityEngine.UIElements;
|
|||
namespace KitsuneCafe.UI
|
||||
{
|
||||
[CreateAssetMenu(menuName = KitsuneCafeMenu.UiEffect + "Fade")]
|
||||
public class TransitionEffect : BaseUIEffect
|
||||
public class FadeEffect : BaseUiEffect
|
||||
{
|
||||
[SerializeField]
|
||||
private string propertyName;
|
||||
private bool addTransition = false;
|
||||
|
||||
[SerializeField]
|
||||
[SerializeField, ShowIf("addTransition")]
|
||||
private string propertyName = "opacity";
|
||||
|
||||
[SerializeField, ShowIf("addTransition")]
|
||||
private SerializableDuration duration;
|
||||
|
||||
[SerializeField]
|
||||
[SerializeField, ShowIf("addTransition")]
|
||||
private EasingMode easing;
|
||||
|
||||
[SerializeField]
|
||||
[SerializeField, ShowIf("addTransition")]
|
||||
private SerializableDuration delay;
|
||||
|
||||
public override IUIEffect Instantiate()
|
||||
[SerializeField, Range(0f, 1f)]
|
||||
private float from;
|
||||
|
||||
[SerializeField, Range(0f, 1f)]
|
||||
private float to;
|
||||
|
||||
public override IUiEffect Instantiate()
|
||||
{
|
||||
return new TransitionEffectInstance(propertyName, duration, easing, delay);
|
||||
var fade = new FadeEffectInstance(from, to);
|
||||
|
||||
if (addTransition)
|
||||
{
|
||||
return new AddTransitionEffect(propertyName, duration, easing, delay, fade);
|
||||
}
|
||||
|
||||
return fade;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct TransitionEffectInstance : IUIEffect
|
||||
public readonly struct FadeEffectInstance : IUiEffect
|
||||
{
|
||||
public readonly StylePropertyName PropertyName;
|
||||
public readonly TimeValue Duration;
|
||||
public readonly EasingFunction Easing;
|
||||
public readonly TimeValue Delay;
|
||||
public readonly float From;
|
||||
public readonly float To;
|
||||
|
||||
public TransitionEffectInstance(StylePropertyName name, TimeValue duration, EasingFunction easing, TimeValue delay)
|
||||
public FadeEffectInstance(float from, float to)
|
||||
{
|
||||
PropertyName = name;
|
||||
Duration = duration;
|
||||
Easing = easing;
|
||||
Delay = delay;
|
||||
From = from;
|
||||
To = to;
|
||||
}
|
||||
|
||||
public Observable<R3.Unit> Execute(VisualElement target)
|
||||
private void DoTransition(VisualElement target)
|
||||
{
|
||||
return Observable.Empty<R3.Unit>();
|
||||
target.style.opacity = From;
|
||||
target.style.opacity = To;
|
||||
}
|
||||
|
||||
|
||||
public Observable<R3.Unit> Execute(VisualElement target, CancellationToken token)
|
||||
{
|
||||
target.style.opacity = From;
|
||||
|
||||
var to = To;
|
||||
return Observable.NextFrame(cancellationToken: token)
|
||||
.Do(_ =>
|
||||
{
|
||||
target.style.opacity = to;
|
||||
})
|
||||
.AsUnitObservable();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
using R3;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
public interface IUIEffect
|
||||
{
|
||||
Observable<Unit> Execute(VisualElement target);
|
||||
}
|
||||
|
||||
public abstract class BaseUIEffect : ScriptableObject
|
||||
{
|
||||
public abstract IUIEffect Instantiate();
|
||||
}
|
||||
}
|
18
Assets/Scripts/UI/Effect/IUiEffect.cs
Normal file
18
Assets/Scripts/UI/Effect/IUiEffect.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System.Collections;
|
||||
using System.Threading;
|
||||
using R3;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
public interface IUiEffect
|
||||
{
|
||||
Observable<Unit> Execute(VisualElement target, CancellationToken token);
|
||||
}
|
||||
|
||||
public abstract class BaseUiEffect : ScriptableObject
|
||||
{
|
||||
public abstract IUiEffect Instantiate();
|
||||
}
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using KitsuneCafe.System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
public readonly struct ModalElementInstance : IUIElement
|
||||
public readonly struct ModalElementInstance : IUiElement
|
||||
{
|
||||
public readonly string Title;
|
||||
public readonly string Content;
|
||||
|
@ -31,10 +32,15 @@ namespace KitsuneCafe.UI
|
|||
ve.Q<Label>(so.TitleId).text = Title;
|
||||
ve.Q<Label>(so.ContentId).text = Content;
|
||||
}
|
||||
|
||||
public IEnumerable<BaseUiEffect> GetEffectsFor(UiEvent timing)
|
||||
{
|
||||
return so.GetEffectsFor(timing);
|
||||
}
|
||||
}
|
||||
|
||||
[CreateAssetMenu(menuName = KitsuneCafeMenu.UiElement + "Modal")]
|
||||
public class ModalElement : UIElementSO
|
||||
public class ModalElement : UiElementSo
|
||||
{
|
||||
[SerializeField]
|
||||
private string titleId = "title";
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace KitsuneCafe.UI
|
|||
public class Notification : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private UIOrchestrator orchestrator;
|
||||
private UiOrchestrator orchestrator;
|
||||
|
||||
[SerializeField]
|
||||
private ModalElement modal;
|
||||
|
|
|
@ -6,17 +6,17 @@ namespace KitsuneCafe.UI
|
|||
public readonly struct SpawnElementRequest : IEquatable<SpawnElementRequest>
|
||||
{
|
||||
public readonly ElementId Id;
|
||||
public readonly IUIElement Element;
|
||||
public readonly IUiElement Element;
|
||||
public readonly Vector3 Position;
|
||||
|
||||
public SpawnElementRequest(ElementId id, IUIElement element, Vector3 position)
|
||||
public SpawnElementRequest(ElementId id, IUiElement element, Vector3 position)
|
||||
{
|
||||
Id = id;
|
||||
Element = element;
|
||||
Position = position;
|
||||
}
|
||||
|
||||
public static SpawnElementRequest Create(ElementId id, IUIElement element, Vector3 position) => new(id, element, position);
|
||||
public static SpawnElementRequest Create(ElementId id, IUiElement element, Vector3 position) => new(id, element, position);
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
|
|
|
@ -5,13 +5,13 @@ using UnityEngine;
|
|||
namespace KitsuneCafe.UI
|
||||
{
|
||||
[CreateAssetMenu(menuName = KitsuneCafeMenu.Ui + "Orchestrator")]
|
||||
public class UIOrchestrator : ScriptableObject
|
||||
public class UiOrchestrator : ScriptableObject
|
||||
{
|
||||
public event EventHandler<SpawnElementRequest> SpawnRequested = default;
|
||||
public event EventHandler<DespawnElementRequest> DespawnRequested = default;
|
||||
|
||||
|
||||
public ElementId SpawnElement(IUIElement element, Vector3 worldPosition)
|
||||
public ElementId SpawnElement(IUiElement element, Vector3 worldPosition)
|
||||
{
|
||||
var id = ElementId.Create();
|
||||
SpawnRequested.Invoke(this, SpawnElementRequest.Create(id, element, worldPosition));
|
|
@ -5,13 +5,13 @@ using System;
|
|||
using UnityEngine.UIElements;
|
||||
using UnityEngine.Pool;
|
||||
using KitsuneCafe.System;
|
||||
using System.Threading;
|
||||
using KitsuneCafe.Extension;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
public class UISceneManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private UIOrchestrator orchestrator;
|
||||
[SerializeField] private UiOrchestrator orchestrator;
|
||||
|
||||
[SerializeField] private Transform root;
|
||||
[SerializeField] private PanelSettings panelSettings;
|
||||
|
@ -46,7 +46,7 @@ namespace KitsuneCafe.UI
|
|||
d.RegisterTo(destroyCancellationToken);
|
||||
}
|
||||
|
||||
private IObjectPool<GameObject> GetOrCreatePool(IUIElement element)
|
||||
private IObjectPool<GameObject> GetOrCreatePool(IUiElement element)
|
||||
{
|
||||
if (!pools.TryGetValue(element.VisualTreeAsset, out var pool))
|
||||
{
|
||||
|
@ -77,7 +77,7 @@ namespace KitsuneCafe.UI
|
|||
obj = new GameObject("Pooled Object", typeof(UIDocument));
|
||||
}
|
||||
|
||||
obj.transform.SetParent(root);
|
||||
obj.AddComponent<UiElementInstance>();
|
||||
|
||||
var doc = obj.GetComponent<UIDocument>();
|
||||
doc.panelSettings = panelSettings;
|
||||
|
@ -85,6 +85,8 @@ namespace KitsuneCafe.UI
|
|||
var poolObj = obj.AddComponent<PooledObject>();
|
||||
poolObj.objectPool = pool;
|
||||
|
||||
obj.transform.SetParent(root);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -103,12 +105,21 @@ namespace KitsuneCafe.UI
|
|||
Destroy(obj);
|
||||
}
|
||||
|
||||
private GameObject GetUiDocument(IUIElement element)
|
||||
private GameObject GetUiDocument(IUiElement element)
|
||||
{
|
||||
return GetOrCreatePool(element).Get();
|
||||
}
|
||||
|
||||
private void SpawnElement(ElementId id, IUIElement element, Vector3 worldPosition)
|
||||
private Observable<T> ObserveEvent<T>(VisualElement target) where T : EventBase<T>, new()
|
||||
{
|
||||
return Observable.FromEvent<EventCallback<T>, T>(
|
||||
h => e => h(e),
|
||||
e => target.RegisterCallback(e),
|
||||
e => target.UnregisterCallback(e)
|
||||
);
|
||||
}
|
||||
|
||||
private void SpawnElement(ElementId id, IUiElement element, Vector3 worldPosition)
|
||||
{
|
||||
var obj = GetUiDocument(element);
|
||||
|
||||
|
@ -117,33 +128,21 @@ namespace KitsuneCafe.UI
|
|||
trans.SetPositionAndRotation(worldPosition, Quaternion.identity);
|
||||
trans.localScale = Vector3.one;
|
||||
|
||||
if (obj.TryGetComponent<UIDocument>(out var doc))
|
||||
if (obj.TryGetComponent(out UIDocument doc) && obj.TryGetComponent(out UiElementInstance instance))
|
||||
{
|
||||
|
||||
doc.visualTreeAsset = element.VisualTreeAsset;
|
||||
doc.panelSettings = panelSettings;
|
||||
ConfigureWhenReady(doc, element);
|
||||
Observable.EveryValueChanged(doc, d => d.rootVisualElement)
|
||||
.WhereNotNull()
|
||||
.Select(_ => doc)
|
||||
.Subscribe(doc =>
|
||||
{
|
||||
instance.Configure(element, doc.rootVisualElement);
|
||||
})
|
||||
.AddTo(doc.gameObject);
|
||||
}
|
||||
|
||||
activeElements[id] = obj;
|
||||
|
||||
//Observable.Timer(TimeSpan.FromSeconds(3))
|
||||
// .Subscribe(_ => orchestrator.DespawnElement(id))
|
||||
// .AddTo(obj);
|
||||
}
|
||||
|
||||
private void ConfigureWhenReady(UIDocument document, IUIElement element)
|
||||
{
|
||||
var cts = new CancellationTokenSource();
|
||||
Observable.EveryValueChanged(document, d => d.didStart)
|
||||
.Where(started => started)
|
||||
.Take(1)
|
||||
.DoCancelOnCompleted(cts)
|
||||
.Subscribe(f =>
|
||||
{
|
||||
element.Configure(document.rootVisualElement);
|
||||
})
|
||||
.AddTo(document.gameObject);
|
||||
}
|
||||
|
||||
private void DespawnElement(ElementId id)
|
|
@ -5,7 +5,7 @@ namespace KitsuneCafe.UI
|
|||
public class TestThing : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private UIOrchestrator orchestrator;
|
||||
private UiOrchestrator orchestrator;
|
||||
|
||||
[SerializeField]
|
||||
private ModalElement modal;
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
using KitsuneCafe.System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
public interface IUIElement
|
||||
{
|
||||
VisualTreeAsset VisualTreeAsset { get; }
|
||||
|
||||
VisualElement Instantiate();
|
||||
void Configure(VisualElement element);
|
||||
}
|
||||
|
||||
[CreateAssetMenu(menuName = KitsuneCafeMenu.UiElement + "Element")]
|
||||
public abstract class UIElementSO : ScriptableObject, IUIElement
|
||||
{
|
||||
[SerializeField]
|
||||
private VisualTreeAsset visualTreeAsset;
|
||||
public VisualTreeAsset VisualTreeAsset => visualTreeAsset;
|
||||
|
||||
public virtual VisualElement Instantiate()
|
||||
{
|
||||
var instance = visualTreeAsset.CloneTree();
|
||||
Configure(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
public virtual void Configure(VisualElement ve) { }
|
||||
}
|
||||
}
|
56
Assets/Scripts/UI/UiElement.cs
Normal file
56
Assets/Scripts/UI/UiElement.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using KitsuneCafe.System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
public enum UiEvent
|
||||
{
|
||||
OnCreate,
|
||||
OnDestroy
|
||||
}
|
||||
|
||||
public interface IUiElement
|
||||
{
|
||||
VisualTreeAsset VisualTreeAsset { get; }
|
||||
|
||||
void Configure(VisualElement element);
|
||||
|
||||
IEnumerable<BaseUiEffect> GetEffectsFor(UiEvent timing);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct EventEffectPair
|
||||
{
|
||||
[SerializeField]
|
||||
private UiEvent uiEvent;
|
||||
public readonly UiEvent Event => uiEvent;
|
||||
|
||||
[SerializeField]
|
||||
private BaseUiEffect effect;
|
||||
public readonly BaseUiEffect Effect => effect;
|
||||
}
|
||||
|
||||
[CreateAssetMenu(menuName = KitsuneCafeMenu.UiElement + "Element")]
|
||||
public abstract class UiElementSo : ScriptableObject, IUiElement
|
||||
{
|
||||
[SerializeField]
|
||||
private VisualTreeAsset visualTreeAsset;
|
||||
public VisualTreeAsset VisualTreeAsset => visualTreeAsset;
|
||||
|
||||
[SerializeField]
|
||||
private List<EventEffectPair> effects;
|
||||
private ILookup<UiEvent, BaseUiEffect> effectLookup;
|
||||
public ILookup<UiEvent, BaseUiEffect> Effects => effectLookup ??= effects.ToLookup(p => p.Event, p => p.Effect);
|
||||
|
||||
public virtual void Configure(VisualElement ve) { }
|
||||
|
||||
public IEnumerable<BaseUiEffect> GetEffectsFor(UiEvent timing)
|
||||
{
|
||||
return Effects[timing];
|
||||
}
|
||||
}
|
||||
}
|
71
Assets/Scripts/UI/UiElementInstance.cs
Normal file
71
Assets/Scripts/UI/UiElementInstance.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using R3;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
public class UiElementInstance : MonoBehaviour, IDisposable
|
||||
{
|
||||
private IUiElement uiElement;
|
||||
private VisualElement visualElement;
|
||||
|
||||
private readonly CompositeDisposable activeEffects = new();
|
||||
|
||||
private bool configured = false;
|
||||
|
||||
public void Configure(IUiElement uiElement, VisualElement visualElement)
|
||||
{
|
||||
configured = true;
|
||||
this.uiElement = uiElement;
|
||||
this.visualElement = visualElement;
|
||||
|
||||
activeEffects.Clear();
|
||||
|
||||
uiElement.Configure(visualElement);
|
||||
|
||||
Raise(UiEvent.OnCreate);
|
||||
}
|
||||
|
||||
private void Raise(UiEvent evt)
|
||||
{
|
||||
foreach (var effect in uiElement.GetEffectsFor(evt))
|
||||
{
|
||||
// using explicit null comparison because of the way
|
||||
// GameObjects handle being null
|
||||
if (effect != null)
|
||||
{
|
||||
effect.Instantiate()
|
||||
.Execute(visualElement, destroyCancellationToken)
|
||||
.Subscribe()
|
||||
.AddTo(activeEffects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!configured) { return; }
|
||||
|
||||
Raise(UiEvent.OnDestroy);
|
||||
|
||||
activeEffects.Dispose();
|
||||
activeEffects.Clear();
|
||||
|
||||
uiElement = default;
|
||||
visualElement = default;
|
||||
|
||||
configured = false;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
2
Assets/Scripts/UI/UiElementInstance.cs.meta
Normal file
2
Assets/Scripts/UI/UiElementInstance.cs.meta
Normal file
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8f7e084f3ed7b4e5babd039bbd888b29
|
Loading…
Add table
Reference in a new issue