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_Enabled: 1
|
||||||
m_EditorHideFlags: 0
|
m_EditorHideFlags: 0
|
||||||
m_Script: {fileID: 11500000, guid: 94cc50e7b5f20a817aef3384d0889279, type: 3}
|
m_Script: {fileID: 11500000, guid: 94cc50e7b5f20a817aef3384d0889279, type: 3}
|
||||||
m_Name: New Transition Effect
|
m_Name: Fade In
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
propertyName:
|
addTransition: 1
|
||||||
|
propertyName: opacity
|
||||||
duration:
|
duration:
|
||||||
duration: 0
|
duration: 0.3
|
||||||
unit: 0
|
unit: 2
|
||||||
easing: 0
|
easing: 3
|
||||||
delay:
|
delay:
|
||||||
duration: 0
|
duration: 0
|
||||||
unit: 0
|
unit: 2
|
||||||
|
from: 0
|
||||||
|
to: 1
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 630c186ef2ab4b37495b5001d208878f
|
guid: 0902dc21238be2bb3ae758e1d5218922
|
||||||
NativeFormatImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 11400000
|
mainObjectFileID: 11400000
|
|
@ -9,9 +9,12 @@ MonoBehaviour:
|
||||||
m_GameObject: {fileID: 0}
|
m_GameObject: {fileID: 0}
|
||||||
m_Enabled: 1
|
m_Enabled: 1
|
||||||
m_EditorHideFlags: 0
|
m_EditorHideFlags: 0
|
||||||
m_Script: {fileID: 0}
|
m_Script: {fileID: 11500000, guid: 0b01085379e9a10319622dd3dd23f4bd, type: 3}
|
||||||
m_Name: Modal
|
m_Name: Modal
|
||||||
m_EditorClassIdentifier: Assembly-CSharp:KitsuneCafe.UI:ModalElementSO
|
m_EditorClassIdentifier:
|
||||||
visualTreeAsset: {fileID: 9197481963319205126, guid: bc70bdaaf37609283aac14435c5441a2, type: 3}
|
visualTreeAsset: {fileID: 9197481963319205126, guid: bc70bdaaf37609283aac14435c5441a2, type: 3}
|
||||||
|
effects:
|
||||||
|
- timing: 0
|
||||||
|
effect: {fileID: 11400000, guid: 0902dc21238be2bb3ae758e1d5218922, type: 2}
|
||||||
titleId: title
|
titleId: title
|
||||||
contentId: content
|
contentId: content
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 1a47b12328bfde496ab2f3847d762a79
|
guid: 71a6f29fae4392a4f97870a52b6adf1e
|
||||||
NativeFormatImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 11400000
|
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 KitsuneCafe.System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using UnityEngine.Rendering.Universal;
|
||||||
|
|
||||||
namespace KitsuneCafe.Extension
|
namespace KitsuneCafe.Extension
|
||||||
{
|
{
|
||||||
|
@ -177,6 +178,29 @@ namespace KitsuneCafe.Extension
|
||||||
{
|
{
|
||||||
return source.Where(Func.Identity);
|
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;
|
||||||
|
using KitsuneCafe.System.Attributes;
|
||||||
using R3;
|
using R3;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
|
@ -6,44 +8,72 @@ using UnityEngine.UIElements;
|
||||||
namespace KitsuneCafe.UI
|
namespace KitsuneCafe.UI
|
||||||
{
|
{
|
||||||
[CreateAssetMenu(menuName = KitsuneCafeMenu.UiEffect + "Fade")]
|
[CreateAssetMenu(menuName = KitsuneCafeMenu.UiEffect + "Fade")]
|
||||||
public class TransitionEffect : BaseUIEffect
|
public class FadeEffect : BaseUiEffect
|
||||||
{
|
{
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private string propertyName;
|
private bool addTransition = false;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField, ShowIf("addTransition")]
|
||||||
|
private string propertyName = "opacity";
|
||||||
|
|
||||||
|
[SerializeField, ShowIf("addTransition")]
|
||||||
private SerializableDuration duration;
|
private SerializableDuration duration;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField, ShowIf("addTransition")]
|
||||||
private EasingMode easing;
|
private EasingMode easing;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField, ShowIf("addTransition")]
|
||||||
private SerializableDuration delay;
|
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 float From;
|
||||||
public readonly TimeValue Duration;
|
public readonly float To;
|
||||||
public readonly EasingFunction Easing;
|
|
||||||
public readonly TimeValue Delay;
|
|
||||||
|
|
||||||
public TransitionEffectInstance(StylePropertyName name, TimeValue duration, EasingFunction easing, TimeValue delay)
|
public FadeEffectInstance(float from, float to)
|
||||||
{
|
{
|
||||||
PropertyName = name;
|
From = from;
|
||||||
Duration = duration;
|
To = to;
|
||||||
Easing = easing;
|
|
||||||
Delay = delay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 KitsuneCafe.System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
namespace KitsuneCafe.UI
|
namespace KitsuneCafe.UI
|
||||||
{
|
{
|
||||||
public readonly struct ModalElementInstance : IUIElement
|
public readonly struct ModalElementInstance : IUiElement
|
||||||
{
|
{
|
||||||
public readonly string Title;
|
public readonly string Title;
|
||||||
public readonly string Content;
|
public readonly string Content;
|
||||||
|
@ -31,10 +32,15 @@ namespace KitsuneCafe.UI
|
||||||
ve.Q<Label>(so.TitleId).text = Title;
|
ve.Q<Label>(so.TitleId).text = Title;
|
||||||
ve.Q<Label>(so.ContentId).text = Content;
|
ve.Q<Label>(so.ContentId).text = Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseUiEffect> GetEffectsFor(UiEvent timing)
|
||||||
|
{
|
||||||
|
return so.GetEffectsFor(timing);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[CreateAssetMenu(menuName = KitsuneCafeMenu.UiElement + "Modal")]
|
[CreateAssetMenu(menuName = KitsuneCafeMenu.UiElement + "Modal")]
|
||||||
public class ModalElement : UIElementSO
|
public class ModalElement : UiElementSo
|
||||||
{
|
{
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private string titleId = "title";
|
private string titleId = "title";
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace KitsuneCafe.UI
|
||||||
public class Notification : MonoBehaviour
|
public class Notification : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private UIOrchestrator orchestrator;
|
private UiOrchestrator orchestrator;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private ModalElement modal;
|
private ModalElement modal;
|
||||||
|
|
|
@ -6,17 +6,17 @@ namespace KitsuneCafe.UI
|
||||||
public readonly struct SpawnElementRequest : IEquatable<SpawnElementRequest>
|
public readonly struct SpawnElementRequest : IEquatable<SpawnElementRequest>
|
||||||
{
|
{
|
||||||
public readonly ElementId Id;
|
public readonly ElementId Id;
|
||||||
public readonly IUIElement Element;
|
public readonly IUiElement Element;
|
||||||
public readonly Vector3 Position;
|
public readonly Vector3 Position;
|
||||||
|
|
||||||
public SpawnElementRequest(ElementId id, IUIElement element, Vector3 position)
|
public SpawnElementRequest(ElementId id, IUiElement element, Vector3 position)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
Element = element;
|
Element = element;
|
||||||
Position = position;
|
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)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,13 +5,13 @@ using UnityEngine;
|
||||||
namespace KitsuneCafe.UI
|
namespace KitsuneCafe.UI
|
||||||
{
|
{
|
||||||
[CreateAssetMenu(menuName = KitsuneCafeMenu.Ui + "Orchestrator")]
|
[CreateAssetMenu(menuName = KitsuneCafeMenu.Ui + "Orchestrator")]
|
||||||
public class UIOrchestrator : ScriptableObject
|
public class UiOrchestrator : ScriptableObject
|
||||||
{
|
{
|
||||||
public event EventHandler<SpawnElementRequest> SpawnRequested = default;
|
public event EventHandler<SpawnElementRequest> SpawnRequested = default;
|
||||||
public event EventHandler<DespawnElementRequest> DespawnRequested = 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();
|
var id = ElementId.Create();
|
||||||
SpawnRequested.Invoke(this, SpawnElementRequest.Create(id, element, worldPosition));
|
SpawnRequested.Invoke(this, SpawnElementRequest.Create(id, element, worldPosition));
|
|
@ -5,13 +5,13 @@ using System;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
using UnityEngine.Pool;
|
using UnityEngine.Pool;
|
||||||
using KitsuneCafe.System;
|
using KitsuneCafe.System;
|
||||||
using System.Threading;
|
using KitsuneCafe.Extension;
|
||||||
|
|
||||||
namespace KitsuneCafe.UI
|
namespace KitsuneCafe.UI
|
||||||
{
|
{
|
||||||
public class UISceneManager : MonoBehaviour
|
public class UISceneManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField] private UIOrchestrator orchestrator;
|
[SerializeField] private UiOrchestrator orchestrator;
|
||||||
|
|
||||||
[SerializeField] private Transform root;
|
[SerializeField] private Transform root;
|
||||||
[SerializeField] private PanelSettings panelSettings;
|
[SerializeField] private PanelSettings panelSettings;
|
||||||
|
@ -46,7 +46,7 @@ namespace KitsuneCafe.UI
|
||||||
d.RegisterTo(destroyCancellationToken);
|
d.RegisterTo(destroyCancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IObjectPool<GameObject> GetOrCreatePool(IUIElement element)
|
private IObjectPool<GameObject> GetOrCreatePool(IUiElement element)
|
||||||
{
|
{
|
||||||
if (!pools.TryGetValue(element.VisualTreeAsset, out var pool))
|
if (!pools.TryGetValue(element.VisualTreeAsset, out var pool))
|
||||||
{
|
{
|
||||||
|
@ -77,7 +77,7 @@ namespace KitsuneCafe.UI
|
||||||
obj = new GameObject("Pooled Object", typeof(UIDocument));
|
obj = new GameObject("Pooled Object", typeof(UIDocument));
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.transform.SetParent(root);
|
obj.AddComponent<UiElementInstance>();
|
||||||
|
|
||||||
var doc = obj.GetComponent<UIDocument>();
|
var doc = obj.GetComponent<UIDocument>();
|
||||||
doc.panelSettings = panelSettings;
|
doc.panelSettings = panelSettings;
|
||||||
|
@ -85,6 +85,8 @@ namespace KitsuneCafe.UI
|
||||||
var poolObj = obj.AddComponent<PooledObject>();
|
var poolObj = obj.AddComponent<PooledObject>();
|
||||||
poolObj.objectPool = pool;
|
poolObj.objectPool = pool;
|
||||||
|
|
||||||
|
obj.transform.SetParent(root);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,12 +105,21 @@ namespace KitsuneCafe.UI
|
||||||
Destroy(obj);
|
Destroy(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GameObject GetUiDocument(IUIElement element)
|
private GameObject GetUiDocument(IUiElement element)
|
||||||
{
|
{
|
||||||
return GetOrCreatePool(element).Get();
|
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);
|
var obj = GetUiDocument(element);
|
||||||
|
|
||||||
|
@ -117,33 +128,21 @@ namespace KitsuneCafe.UI
|
||||||
trans.SetPositionAndRotation(worldPosition, Quaternion.identity);
|
trans.SetPositionAndRotation(worldPosition, Quaternion.identity);
|
||||||
trans.localScale = Vector3.one;
|
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.visualTreeAsset = element.VisualTreeAsset;
|
||||||
doc.panelSettings = panelSettings;
|
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;
|
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)
|
private void DespawnElement(ElementId id)
|
|
@ -5,7 +5,7 @@ namespace KitsuneCafe.UI
|
||||||
public class TestThing : MonoBehaviour
|
public class TestThing : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private UIOrchestrator orchestrator;
|
private UiOrchestrator orchestrator;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private ModalElement modal;
|
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