fixes #8
This commit is contained in:
parent
4ea0f58bc7
commit
4456431f25
22 changed files with 334 additions and 127 deletions
|
@ -15,11 +15,11 @@ MonoBehaviour:
|
|||
addTransition: 1
|
||||
propertyName: opacity
|
||||
duration:
|
||||
duration: 0.3
|
||||
duration: 1
|
||||
unit: 2
|
||||
easing: 3
|
||||
delay:
|
||||
duration: 0
|
||||
duration: 1
|
||||
unit: 2
|
||||
from: 0
|
||||
to: 1
|
||||
|
|
25
Assets/SOAP/UI/Fade Out.asset
Normal file
25
Assets/SOAP/UI/Fade Out.asset
Normal file
|
@ -0,0 +1,25 @@
|
|||
%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: 94cc50e7b5f20a817aef3384d0889279, type: 3}
|
||||
m_Name: Fade Out
|
||||
m_EditorClassIdentifier:
|
||||
addTransition: 1
|
||||
propertyName: opacity
|
||||
duration:
|
||||
duration: 1
|
||||
unit: 2
|
||||
easing: 3
|
||||
delay:
|
||||
duration: 1
|
||||
unit: 2
|
||||
from: 1
|
||||
to: 0
|
8
Assets/SOAP/UI/Fade Out.asset.meta
Normal file
8
Assets/SOAP/UI/Fade Out.asset.meta
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fd3397ffea6cbccc5992ef2e70a2ed44
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -14,7 +14,9 @@ MonoBehaviour:
|
|||
m_EditorClassIdentifier:
|
||||
visualTreeAsset: {fileID: 9197481963319205126, guid: bc70bdaaf37609283aac14435c5441a2, type: 3}
|
||||
effects:
|
||||
- timing: 0
|
||||
- uiEvent: 0
|
||||
effect: {fileID: 11400000, guid: 0902dc21238be2bb3ae758e1d5218922, type: 2}
|
||||
- uiEvent: 1
|
||||
effect: {fileID: 11400000, guid: fd3397ffea6cbccc5992ef2e70a2ed44, type: 2}
|
||||
titleId: title
|
||||
contentId: content
|
||||
|
|
|
@ -922,6 +922,9 @@ MonoBehaviour:
|
|||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
oneTimeUse: 0
|
||||
onTarget:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
onInteracted:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
|
@ -1211,7 +1214,6 @@ MonoBehaviour:
|
|||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
camera: {fileID: 330585546}
|
||||
registerChildren: 1
|
||||
--- !u!114 &1281046470
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@ -1227,6 +1229,9 @@ MonoBehaviour:
|
|||
orchestrator: {fileID: 11400000, guid: 994ab04db2c2004abb8272830cb16b26, type: 2}
|
||||
root: {fileID: 1281046468}
|
||||
panelSettings: {fileID: 11400000, guid: 2bc58aab5867867e5b0feeae2df42fd0, type: 2}
|
||||
despawnTimeout:
|
||||
duration: 2
|
||||
unit: 2
|
||||
prefab: {fileID: 0}
|
||||
--- !u!1 &1363717994
|
||||
GameObject:
|
||||
|
@ -2323,6 +2328,34 @@ PrefabInstance:
|
|||
propertyPath: oneTimeUse
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2022912019066975223, guid: 51202e3c62c3d3e1c9bb0ff9c09a608f, type: 3}
|
||||
propertyPath: onTarget.m_PersistentCalls.m_Calls.Array.size
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2022912019066975223, guid: 51202e3c62c3d3e1c9bb0ff9c09a608f, type: 3}
|
||||
propertyPath: onTarget.m_PersistentCalls.m_Calls.Array.data[0].m_Mode
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2022912019066975223, guid: 51202e3c62c3d3e1c9bb0ff9c09a608f, type: 3}
|
||||
propertyPath: onTarget.m_PersistentCalls.m_Calls.Array.data[0].m_Target
|
||||
value:
|
||||
objectReference: {fileID: 1740748263}
|
||||
- target: {fileID: 2022912019066975223, guid: 51202e3c62c3d3e1c9bb0ff9c09a608f, type: 3}
|
||||
propertyPath: onTarget.m_PersistentCalls.m_Calls.Array.data[0].m_CallState
|
||||
value: 2
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2022912019066975223, guid: 51202e3c62c3d3e1c9bb0ff9c09a608f, type: 3}
|
||||
propertyPath: onTarget.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName
|
||||
value: Toggle
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2022912019066975223, guid: 51202e3c62c3d3e1c9bb0ff9c09a608f, type: 3}
|
||||
propertyPath: onTarget.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName
|
||||
value: KitsuneCafe.UI.TestThing, Assembly-CSharp
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2022912019066975223, guid: 51202e3c62c3d3e1c9bb0ff9c09a608f, type: 3}
|
||||
propertyPath: onTarget.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName
|
||||
value: UnityEngine.Object, UnityEngine
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 2368094401510200604, guid: 51202e3c62c3d3e1c9bb0ff9c09a608f, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: -2
|
||||
|
|
19
Assets/Scripts/Extension/VisualElement.cs
Normal file
19
Assets/Scripts/Extension/VisualElement.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using System.Threading;
|
||||
using R3;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KitsuneCafe.Extension
|
||||
{
|
||||
public static class VisualElementExtensions
|
||||
{
|
||||
public static Observable<T> ObserveEvent<T>(this VisualElement target, CancellationToken token = default) where T : EventBase<T>, new()
|
||||
{
|
||||
return Observable.FromEvent<EventCallback<T>, T>(
|
||||
h => e => h(e),
|
||||
e => target.RegisterCallback(e),
|
||||
e => target.UnregisterCallback(e),
|
||||
token
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
2
Assets/Scripts/Extension/VisualElement.cs.meta
Normal file
2
Assets/Scripts/Extension/VisualElement.cs.meta
Normal file
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: aaf4cd39f81ac6dd8b5949c0f4a2f7ef
|
|
@ -80,6 +80,8 @@ namespace KitsuneCafe.Interaction
|
|||
}
|
||||
|
||||
bool IsInteractable { get; }
|
||||
|
||||
virtual void Target(IInteractor interactor) { }
|
||||
IResult<Unit, InteractionError> Interact(IInteractor interactor);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,9 @@ namespace KitsuneCafe.Interaction
|
|||
[SerializeField]
|
||||
private bool oneTimeUse = false;
|
||||
|
||||
[SerializeField]
|
||||
private UnityEvent<IInteractor> onTarget = default;
|
||||
|
||||
[SerializeField]
|
||||
private UnityEvent<IInteractor> onInteracted = default;
|
||||
|
||||
|
@ -16,6 +19,12 @@ namespace KitsuneCafe.Interaction
|
|||
|
||||
public bool IsInteractable => isInteractable;
|
||||
|
||||
|
||||
void IInteractable.Target(IInteractor interactor)
|
||||
{
|
||||
onTarget.Invoke(interactor);
|
||||
}
|
||||
|
||||
public IResult<Unit, InteractionError> Interact(IInteractor interactor)
|
||||
{
|
||||
onInteracted.Invoke(interactor);
|
||||
|
|
|
@ -169,6 +169,8 @@ namespace KitsuneCafe.Player
|
|||
{
|
||||
if (interactable == null) { return; }
|
||||
|
||||
interactable.Target(this);
|
||||
|
||||
if (!interactable.TryGetComponent(out Outline outline))
|
||||
{
|
||||
outline = interactable.gameObject.AddComponent<Outline>();
|
||||
|
|
|
@ -8,9 +8,6 @@ namespace KitsuneCafe.Rendering
|
|||
[SerializeField]
|
||||
private new Transform camera;
|
||||
|
||||
[SerializeField]
|
||||
private bool registerChildren = false;
|
||||
|
||||
private readonly List<Transform> transforms = new();
|
||||
|
||||
private void Reset()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace KitsuneCafe.System
|
||||
{
|
||||
|
@ -26,8 +27,10 @@ namespace KitsuneCafe.System
|
|||
public Duration(long ticks) : this(ticks, TimeUnit.Ticks) { }
|
||||
|
||||
public static implicit operator TimeSpan(Duration duration) => duration.AsTimeSpan();
|
||||
public static implicit operator TimeValue(Duration duration) => duration.AsTimeValue();
|
||||
|
||||
public readonly TimeSpan AsTimeSpan() => new(Value);
|
||||
public readonly TimeValue AsTimeValue() => new(Into(TimeUnit.Seconds));
|
||||
|
||||
public static Duration From(long value, TimeUnit unit)
|
||||
{
|
||||
|
|
|
@ -15,10 +15,7 @@ namespace KitsuneCafe.System
|
|||
|
||||
|
||||
public static implicit operator Duration(SerializableDuration d) => Duration.From(d.duration, d.unit);
|
||||
public static implicit operator TimeValue(SerializableDuration d)
|
||||
{
|
||||
Duration duration = d;
|
||||
return new TimeValue(duration.Into(TimeUnit.Seconds));
|
||||
}
|
||||
public static implicit operator TimeSpan(SerializableDuration d) => Duration.From(d.duration, d.unit);
|
||||
public static implicit operator TimeValue(SerializableDuration d) => Duration.From(d.duration, d.unit);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace KitsuneCafe.UI
|
|||
return new StyleList<T>(new List<T> { value });
|
||||
}
|
||||
|
||||
public Observable<R3.Unit> Execute(VisualElement target, CancellationToken token)
|
||||
public Observable<Unit> Execute(VisualElement target, CancellationToken token)
|
||||
{
|
||||
target.style.transitionProperty = ToStyleList(PropertyName);
|
||||
target.style.transitionDuration = ToStyleList(Duration);
|
||||
|
|
|
@ -4,6 +4,8 @@ using KitsuneCafe.System.Attributes;
|
|||
using R3;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using KitsuneCafe.Extension;
|
||||
using Unit = R3.Unit;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
|
@ -55,25 +57,35 @@ namespace KitsuneCafe.UI
|
|||
To = to;
|
||||
}
|
||||
|
||||
private void DoTransition(VisualElement target)
|
||||
private Observable<Unit> ObserveGeometryChange(VisualElement target, CancellationToken token)
|
||||
{
|
||||
target.style.opacity = From;
|
||||
target.style.opacity = To;
|
||||
return target.ObserveEvent<GeometryChangedEvent>(token)
|
||||
.OnErrorResumeAsFailure()
|
||||
.AsUnitObservable();
|
||||
}
|
||||
|
||||
private Observable<Unit> Defer(VisualElement target, CancellationToken token)
|
||||
{
|
||||
return Observable.Merge(
|
||||
ObserveGeometryChange(target, token),
|
||||
Observable.EveryUpdate(UnityFrameProvider.PostLateUpdate, token)
|
||||
)
|
||||
.Where(_ => target.resolvedStyle.width > 0 && target.resolvedStyle.height > 0)
|
||||
.Take(1);
|
||||
}
|
||||
|
||||
public Observable<R3.Unit> Execute(VisualElement target, CancellationToken token)
|
||||
public Observable<Unit> Execute(VisualElement target, CancellationToken token)
|
||||
{
|
||||
target.style.opacity = From;
|
||||
|
||||
var to = To;
|
||||
return Observable.NextFrame(cancellationToken: token)
|
||||
.Do(_ =>
|
||||
{
|
||||
target.style.opacity = to;
|
||||
})
|
||||
.AsUnitObservable();
|
||||
return Defer(target, token)
|
||||
.Do(_ => target.style.opacity = to)
|
||||
.Select(_ => target.ObserveEvent<TransitionEndEvent>())
|
||||
.Switch()
|
||||
.Where(evt => evt.stylePropertyNames.Contains("opacity"))
|
||||
.Take(1)
|
||||
.TakeUntil(token)
|
||||
.AsUnitObservable();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
143
Assets/Scripts/UI/Orchestration/UiElementInstance.cs
Normal file
143
Assets/Scripts/UI/Orchestration/UiElementInstance.cs
Normal file
|
@ -0,0 +1,143 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using KitsuneCafe.System;
|
||||
using R3;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using Unit = R3.Unit;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
public class UiElementInstance : MonoBehaviour, IDisposable
|
||||
{
|
||||
public UIDocument Document;
|
||||
public PooledObject PooledObject;
|
||||
|
||||
private IUiElement uiElement;
|
||||
private VisualElement visualElement;
|
||||
|
||||
private DisposableBag activeEffects;
|
||||
private IDisposable instance;
|
||||
|
||||
private CancellationTokenSource cts;
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initial configuration of the UIDocument. Called by UISceneManager on spawn/reuse.
|
||||
/// </summary>
|
||||
public void Configure(IUiElement element, PanelSettings settings)
|
||||
{
|
||||
uiElement = element;
|
||||
|
||||
cts = new();
|
||||
|
||||
Document.visualTreeAsset = element.VisualTreeAsset;
|
||||
Document.panelSettings = settings;
|
||||
|
||||
instance = ConfigureWhenReady(element)
|
||||
.Subscribe();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal configuration of the VisualElement. Called when rootVisualElement is ready.
|
||||
/// </summary>
|
||||
private void Configure(IUiElement uiElement, VisualElement visualElement)
|
||||
{
|
||||
this.visualElement = visualElement;
|
||||
|
||||
uiElement.Configure(visualElement);
|
||||
|
||||
Raise(UiEvent.OnCreate, cts.Token)
|
||||
.Subscribe()
|
||||
.AddTo(ref activeEffects);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the UIDocument's rootVisualElement to be ready.
|
||||
/// </summary>
|
||||
private Observable<Unit> ConfigureWhenReady(IUiElement element)
|
||||
{
|
||||
return Observable.EveryValueChanged(Document, d => d.rootVisualElement)
|
||||
.WhereNotNull()
|
||||
.Take(1)
|
||||
.TakeUntil(cts.Token)
|
||||
.Do(root => Configure(element, root))
|
||||
.AsUnitObservable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises effects for a given UI event, returning an Observable that completes when all effects are done.
|
||||
/// </summary>
|
||||
private Observable<Unit> Raise(UiEvent evt, CancellationToken token = default)
|
||||
{
|
||||
var effects = uiElement.GetEffectsFor(evt).ToArray();
|
||||
var obs = new List<Observable<Unit>>(effects.Length);
|
||||
|
||||
foreach (var effect in effects)
|
||||
{
|
||||
if (effect != null)
|
||||
{
|
||||
obs.Add(effect
|
||||
.Instantiate()
|
||||
.Execute(visualElement, token));
|
||||
}
|
||||
}
|
||||
|
||||
return Observable.Merge(obs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forcefully disposes of all active effects and instance lifecycle subscriptions.
|
||||
/// This is for internal cleanup. It does NOT release the object to the pool.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
cts?.Cancel();
|
||||
cts?.Dispose();
|
||||
cts = null;
|
||||
|
||||
// activeEffects.Dispose();
|
||||
activeEffects.Clear();
|
||||
|
||||
instance?.Dispose();
|
||||
|
||||
uiElement = default;
|
||||
visualElement = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the despawn process: runs OnDestroy effects, waits for them to finish,
|
||||
/// then disposes everything and releases the object back to the pool.
|
||||
/// </summary>
|
||||
public Observable<Unit> Despawn(CancellationTokenSource cts = default)
|
||||
{
|
||||
cts ??= new CancellationTokenSource();
|
||||
|
||||
return Raise(UiEvent.OnDestroy, cts.Token)
|
||||
.Do(onCompleted: _ =>
|
||||
{
|
||||
Dispose();
|
||||
PooledObject.Release();
|
||||
},
|
||||
onErrorResume: _ => cts.Cancel())
|
||||
.TakeUntil(cts.Token)
|
||||
.AsUnitObservable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Immediately disposes of effects and releases the object to the pool,
|
||||
/// without awaiting OnDestroy effects.
|
||||
/// </summary>
|
||||
public void DespawnNow()
|
||||
{
|
||||
Dispose();
|
||||
PooledObject.Release();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using UnityEngine.UIElements;
|
||||
using UnityEngine.Pool;
|
||||
using KitsuneCafe.System;
|
||||
using KitsuneCafe.Extension;
|
||||
|
||||
namespace KitsuneCafe.UI
|
||||
{
|
||||
|
@ -15,6 +14,7 @@ namespace KitsuneCafe.UI
|
|||
|
||||
[SerializeField] private Transform root;
|
||||
[SerializeField] private PanelSettings panelSettings;
|
||||
[SerializeField] private SerializableDuration despawnTimeout;
|
||||
[SerializeField] private GameObject prefab;
|
||||
|
||||
private readonly Dictionary<ElementId, GameObject> activeElements = new();
|
||||
|
@ -74,17 +74,24 @@ namespace KitsuneCafe.UI
|
|||
}
|
||||
else
|
||||
{
|
||||
obj = new GameObject("Pooled Object", typeof(UIDocument));
|
||||
obj = new GameObject(
|
||||
"Pooled Object",
|
||||
typeof(UIDocument),
|
||||
typeof(PooledObject),
|
||||
typeof(UiElementInstance)
|
||||
);
|
||||
}
|
||||
|
||||
obj.AddComponent<UiElementInstance>();
|
||||
|
||||
var doc = obj.GetComponent<UIDocument>();
|
||||
doc.panelSettings = panelSettings;
|
||||
|
||||
var poolObj = obj.AddComponent<PooledObject>();
|
||||
var poolObj = obj.GetComponent<PooledObject>();
|
||||
poolObj.objectPool = pool;
|
||||
|
||||
var instance = obj.GetComponent<UiElementInstance>();
|
||||
instance.Document = doc;
|
||||
instance.PooledObject = poolObj;
|
||||
|
||||
obj.transform.SetParent(root);
|
||||
|
||||
return obj;
|
||||
|
@ -110,47 +117,41 @@ namespace KitsuneCafe.UI
|
|||
return GetOrCreatePool(element).Get();
|
||||
}
|
||||
|
||||
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);
|
||||
activeElements[id] = obj;
|
||||
|
||||
var trans = obj.transform;
|
||||
trans.SetParent(root);
|
||||
trans.SetPositionAndRotation(worldPosition, Quaternion.identity);
|
||||
trans.localScale = Vector3.one;
|
||||
|
||||
if (obj.TryGetComponent(out UIDocument doc) && obj.TryGetComponent(out UiElementInstance instance))
|
||||
if (obj.TryGetComponent(out UiElementInstance instance))
|
||||
{
|
||||
doc.visualTreeAsset = element.VisualTreeAsset;
|
||||
doc.panelSettings = panelSettings;
|
||||
Observable.EveryValueChanged(doc, d => d.rootVisualElement)
|
||||
.WhereNotNull()
|
||||
.Select(_ => doc)
|
||||
.Subscribe(doc =>
|
||||
{
|
||||
instance.Configure(element, doc.rootVisualElement);
|
||||
})
|
||||
.AddTo(doc.gameObject);
|
||||
instance.Configure(element, panelSettings);
|
||||
}
|
||||
|
||||
activeElements[id] = obj;
|
||||
}
|
||||
|
||||
// FIXME: track which pool each active element belongs to?
|
||||
private void DespawnElement(ElementId id)
|
||||
{
|
||||
if (activeElements.TryGetValue(id, out GameObject obj))
|
||||
{
|
||||
obj.GetComponent<PooledObject>().Release();
|
||||
activeElements.Remove(id);
|
||||
if (obj.TryGetComponent<UiElementInstance>(out var instance))
|
||||
{
|
||||
instance.Despawn()
|
||||
.Race(Observable.Timer(despawnTimeout).Do(_ => instance.DespawnNow()))
|
||||
.Do(onCompleted: _ => activeElements.Remove(id))
|
||||
.Subscribe()
|
||||
.AddTo(obj);
|
||||
|
||||
}
|
||||
else if (obj.TryGetComponent(out PooledObject poolObj))
|
||||
{
|
||||
poolObj.Release();
|
||||
activeElements.Remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,32 @@ namespace KitsuneCafe.UI
|
|||
[SerializeField]
|
||||
private ModalElement modal;
|
||||
|
||||
private void Start()
|
||||
private ElementId id;
|
||||
|
||||
public void Open()
|
||||
{
|
||||
orchestrator.SpawnElement(modal.Create("test", "fuck !!!! :3"), transform.position + Vector3.up);
|
||||
id = orchestrator.SpawnElement(modal.Create("<3", "fuck !!!! :3"), transform.position + (Vector3.up * 2));
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (id != default)
|
||||
{
|
||||
orchestrator.DespawnElement(id);
|
||||
id = default;
|
||||
}
|
||||
}
|
||||
|
||||
public void Toggle()
|
||||
{
|
||||
if (id != default)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Open();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue