using System; using System.Collections; using System.Collections.Generic; using UniRx; using UnityEngine; public interface ISDUIPresentController { void SetRoot (ISDUIElement rootElement); IObservable<ISDUIElement> Show (string elementAddress); IObservable<ISDUIElement> Push (string elementAddress); IObservable<ISDUIElement> Pop (); IObservable<Unit> DismissAll (); } public class SDUIPresentController : ISDUIPresentController { ISDUIPresentModel m_Model; ISDUIPresentView m_View; #region Factory public static SDUIPresentController Create (ISDUIPresentModel model, ISDUIPresentView view) { return new SDUIPresentController (model, view); } #endregion private SDUIPresentController (ISDUIPresentModel model, ISDUIPresentView view) { m_Model = model; m_View = view; m_View.Init (m_Model); } public void SetRoot (ISDUIElement rootElement) { LayoutRect (rootElement, m_Model.ElementSize); rootElement.ElementRect.SetParent (m_View.BodyTransform, false); this.DismissAll () .Subscribe (result => m_Model.Push (rootElement)); } public virtual IObservable<ISDUIElement> Show (string elementAddress) { if (m_Model.IsAnimating) return Observable.Return<ISDUIElement> (null); return ShowElement (elementAddress); } public virtual IObservable<ISDUIElement> Push (string elementAddress) { if (m_Model.IsAnimating) return Observable.Return<ISDUIElement> (null); if (m_Model.ElementCount == 0) return ShowElement (elementAddress); return SDAssetUtils.InstantiateAsync<SDUIElement> (elementAddress, m_View.BodyTransform) .Do (element => { LayoutRect (element, m_Model.ElementSize); m_Model.Push (element); element.Show (); m_Model.IsAnimating = true; }) .ContinueWith (element => m_View.Navigate (element, m_Model.ElementAt (1))) .Finally (() => m_Model.IsAnimating = false); } public virtual IObservable<ISDUIElement> Pop () { if (m_Model.IsAnimating || m_Model.ElementCount == 0) return Observable.Return<ISDUIElement> (null); m_Model.IsAnimating = true; if (m_Model.ElementCount > 1) { return m_View.Back (m_Model.ElementAt (0), m_Model.ElementAt (1)) .Do (_ => m_Model.Pop ()?.Dismiss ()) .Finally (() => m_Model.IsAnimating = false); } return m_View.Hide () .Select (_ => m_Model.Pop ()) .Do (element => element?.Dismiss ()) .Finally (() => m_Model.IsAnimating = false); } public virtual IObservable<Unit> DismissAll () { if (m_Model.IsAnimating || m_Model.ElementCount == 0) return Observable.Return (Unit.Default); m_Model.IsAnimating = true; return m_View.Hide () .Do (result => { while (m_Model.ElementCount > 0) { m_Model.Pop ().Dismiss (); } }) .Finally (() => m_Model.IsAnimating = false); } IObservable<ISDUIElement> ShowElement (string elementAddress) { return SDAssetUtils.InstantiateAsync<SDUIElement> (elementAddress, m_View.BodyTransform) .Do (element => { LayoutRect (element, m_Model.ElementSize); m_Model.Push (element); element.Show (); m_Model.IsAnimating = true; }) .ContinueWith (element => m_View.Show (element)) .Finally (() => m_Model.IsAnimating = false); } void LayoutRect (ISDUIElement element, Vector2 size) { var rect = element.ElementRect; rect.pivot = new Vector2 (0.5f, 1f); rect.anchorMax = new Vector2 (0.5f, 1f); rect.anchorMin = new Vector2 (0.5f, 1f); rect.anchoredPosition = Vector2.zero; rect.sizeDelta = size; } }