seefood_diet / Assets / Scripts / SDUIPresentController.cs
SDUIPresentController.cs
Raw
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;
    }
}