| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622 | using System;using System.Collections.Generic;using UnityEngine;#if UNITY_EDITORusing UnityEditor;#endifnamespace FairyGUI{    /// <summary>    ///     /// </summary>    public enum FitScreen    {        None,        FitSize,        FitWidthAndSetMiddle,        FitHeightAndSetCenter    }    /// <summary>    ///     /// </summary>    [ExecuteInEditMode]    [AddComponentMenu("FairyGUI/UI Panel")]    public class UIPanel : MonoBehaviour, EMRenderTarget    {        /// <summary>        ///         /// </summary>        public Container container { get; private set; }        /// <summary>        ///         /// </summary>        public string packageName;        /// <summary>        ///         /// </summary>        public string componentName;        /// <summary>        ///         /// </summary>        public FitScreen fitScreen;        /// <summary>        ///         /// </summary>        public int sortingOrder;        [SerializeField]        string packagePath;        [SerializeField]        RenderMode renderMode = RenderMode.ScreenSpaceOverlay;        [SerializeField]        Camera renderCamera = null;        [SerializeField]        Vector3 position;        [SerializeField]        Vector3 scale = new Vector3(1, 1, 1);        [SerializeField]        Vector3 rotation = new Vector3(0, 0, 0);        [SerializeField]        bool fairyBatching = false;        [SerializeField]        bool touchDisabled = false;        [SerializeField]        Vector2 cachedUISize;        [SerializeField]        HitTestMode hitTestMode = HitTestMode.Default;        [SerializeField]        bool setNativeChildrenOrder = false;        [System.NonSerialized]        int screenSizeVer;        [System.NonSerialized]        Rect uiBounds; //Track bounds even when UI is not created, edit mode        GComponent _ui;        [NonSerialized]        bool _created;        List<Renderer> _renders;        void OnEnable()        {            if (Application.isPlaying)            {                if (this.container == null)                {                    CreateContainer();                    if (!string.IsNullOrEmpty(packagePath) && UIPackage.GetByName(packageName) == null)                        UIPackage.AddPackage(packagePath);                }            }            else            {                //不在播放状态时我们不在OnEnable创建,因为Prefab也会调用OnEnable,延迟到Update里创建(Prefab不调用Update)                //每次播放前都会disable/enable一次。。。                if (container != null)//如果不为null,可能是因为Prefab revert, 而不是因为Assembly reload,                    OnDestroy();                EMRenderSupport.Add(this);                screenSizeVer = 0;                uiBounds.position = position;                uiBounds.size = cachedUISize;                if (uiBounds.size == Vector2.zero)                    uiBounds.size = new Vector2(30, 30);            }        }        void OnDisable()        {            if (!Application.isPlaying)                EMRenderSupport.Remove(this);        }        void Start()        {            if (!_created && Application.isPlaying)                CreateUI_PlayMode();        }        void Update()        {            if (screenSizeVer != StageCamera.screenSizeVer)                HandleScreenSizeChanged();        }        void OnDestroy()        {            if (container != null)            {                if (!Application.isPlaying)                    EMRenderSupport.Remove(this);                if (_ui != null)                {                    _ui.Dispose();                    _ui = null;                }                container.Dispose();                container = null;            }            _renders = null;        }        void CreateContainer()        {            if (!Application.isPlaying)            {                Transform t = this.transform;                int cnt = t.childCount;                while (cnt > 0)                {                    GameObject go = t.GetChild(cnt - 1).gameObject;                    if (go.name == "UI(AutoGenerated)")                    {#if (UNITY_2018_3_OR_NEWER && UNITY_EDITOR)                        if (PrefabUtility.IsPartOfPrefabInstance(go))                            PrefabUtility.UnpackPrefabInstance(PrefabUtility.GetOutermostPrefabInstanceRoot(gameObject), PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);#endif                        UnityEngine.Object.DestroyImmediate(go);                    }                    cnt--;                }            }            this.container = new Container(this.gameObject);            this.container.renderMode = renderMode;            this.container.renderCamera = renderCamera;            this.container.touchable = !touchDisabled;            this.container._panelOrder = sortingOrder;            this.container.fairyBatching = fairyBatching;            if (Application.isPlaying)            {                SetSortingOrder(this.sortingOrder, true);                if (this.hitTestMode == HitTestMode.Raycast)                {                    ColliderHitTest hitArea = new ColliderHitTest();                    hitArea.collider = this.gameObject.AddComponent<BoxCollider>();                    this.container.hitArea = hitArea;                }                if (setNativeChildrenOrder)                {                    CacheNativeChildrenRenderers();                    this.container.onUpdate += () =>                    {                        int cnt = _renders.Count;                        int sv = UpdateContext.current.renderingOrder++;                        for (int i = 0; i < cnt; i++)                        {                            Renderer r = _renders[i];                            if (r != null)                                _renders[i].sortingOrder = sv;                        }                    };                }            }        }        /// <summary>        ///         /// </summary>        public GComponent ui        {            get            {                if (!_created && Application.isPlaying)                {                    if (!string.IsNullOrEmpty(packagePath) && UIPackage.GetByName(packageName) == null)                        UIPackage.AddPackage(packagePath);                    CreateUI_PlayMode();                }                return _ui;            }        }        /// <summary>        ///         /// </summary>        public void CreateUI()        {            if (_ui != null)            {                _ui.Dispose();                _ui = null;            }            CreateUI_PlayMode();        }        /// <summary>        /// Change the sorting order of the panel in runtime.        /// </summary>        /// <param name="value">sorting order value</param>        /// <param name="apply">false if you dont want the default sorting behavior. e.g. call Stage.SortWorldSpacePanelsByZOrder later.</param>        public void SetSortingOrder(int value, bool apply)        {            this.sortingOrder = value;            container._panelOrder = value;            if (apply)                Stage.inst.ApplyPanelOrder(container);        }        /// <summary>        ///         /// </summary>        /// <param name="value"></param>        public void SetHitTestMode(HitTestMode value)        {            if (this.hitTestMode != value)            {                this.hitTestMode = value;                BoxCollider collider = this.gameObject.GetComponent<BoxCollider>();                if (this.hitTestMode == HitTestMode.Raycast)                {                    if (collider == null)                        collider = this.gameObject.AddComponent<BoxCollider>();                    ColliderHitTest hitArea = new ColliderHitTest();                    hitArea.collider = collider;                    this.container.hitArea = hitArea;                    if (_ui != null)                        UpdateHitArea();                }                else                {                    this.container.hitArea = null;                    if (collider != null)                        Component.Destroy(collider);                }            }        }        /// <summary>        ///         /// </summary>        public void CacheNativeChildrenRenderers()        {            if (_renders == null)                _renders = new List<Renderer>();            else                _renders.Clear();            Transform t = this.container.cachedTransform;            int cnt = t.childCount;            for (int i = 0; i < cnt; i++)            {                GameObject go = t.GetChild(i).gameObject;                if (go.name != "GComponent")                    _renders.AddRange(go.GetComponentsInChildren<Renderer>(true));            }            cnt = _renders.Count;            for (int i = 0; i < cnt; i++)            {                Renderer r = _renders[i];                if ((r is SkinnedMeshRenderer) || (r is MeshRenderer))                {                    //Set the object rendering in Transparent Queue as UI objects                    if (r.sharedMaterial != null)                        r.sharedMaterial.renderQueue = 3000;                }            }        }        void CreateUI_PlayMode()        {            _created = true;            if (string.IsNullOrEmpty(packageName) || string.IsNullOrEmpty(componentName))                return;            _ui = (GComponent)UIPackage.CreateObject(packageName, componentName);            if (_ui != null)            {                _ui.position = position;                if (scale.x != 0 && scale.y != 0)                    _ui.scale = scale;                _ui.rotationX = rotation.x;                _ui.rotationY = rotation.y;                _ui.rotation = rotation.z;                if (this.container.hitArea != null)                {                    UpdateHitArea();                    _ui.onSizeChanged.Add(UpdateHitArea);                    _ui.onPositionChanged.Add(UpdateHitArea);                }                this.container.AddChildAt(_ui.displayObject, 0);                HandleScreenSizeChanged();            }            else                Debug.LogError("Create " + packageName + "/" + componentName + " failed!");        }        void UpdateHitArea()        {            ColliderHitTest hitArea = this.container.hitArea as ColliderHitTest;            if (hitArea != null)            {                ((BoxCollider)hitArea.collider).center = new Vector3(_ui.xMin + _ui.width / 2, -_ui.yMin - _ui.height / 2);                ((BoxCollider)hitArea.collider).size = _ui.size;            }        }        void CreateUI_EditMode()        {            if (!EMRenderSupport.packageListReady || UIPackage.GetByName(packageName) == null)                return;            DisplayObject.hideFlags = HideFlags.DontSaveInEditor;            GObject obj = UIPackage.CreateObject(packageName, componentName);            if (obj != null && !(obj is GComponent))            {                obj.Dispose();                Debug.LogWarning("Not a GComponnet: " + packageName + "/" + componentName);                return;            }            _ui = (GComponent)obj;            if (_ui != null)            {                _ui.displayObject.gameObject.hideFlags |= HideFlags.HideInHierarchy;                _ui.gameObjectName = "UI(AutoGenerated)";                _ui.position = position;                if (scale.x != 0 && scale.y != 0)                    _ui.scale = scale;                _ui.rotationX = rotation.x;                _ui.rotationY = rotation.y;                _ui.rotation = rotation.z;                this.container.AddChildAt(_ui.displayObject, 0);                cachedUISize = _ui.size;                uiBounds.size = cachedUISize;                HandleScreenSizeChanged();            }        }        void HandleScreenSizeChanged()        {            if (!Application.isPlaying)                DisplayObject.hideFlags = HideFlags.DontSaveInEditor;            screenSizeVer = StageCamera.screenSizeVer;            int width = Screen.width;            int height = Screen.height;            if (this.container != null)            {                Camera cam = container.GetRenderCamera();                if (cam.targetDisplay != 0 && cam.targetDisplay < Display.displays.Length)                {                    width = Display.displays[cam.targetDisplay].renderingWidth;                    height = Display.displays[cam.targetDisplay].renderingHeight;                }                if (this.container.renderMode != RenderMode.WorldSpace)                {                    StageCamera sc = cam.GetComponent<StageCamera>();                    if (sc == null)                        sc = StageCamera.main.GetComponent<StageCamera>();                    this.container.scale = new Vector2(sc.unitsPerPixel * UIContentScaler.scaleFactor, sc.unitsPerPixel * UIContentScaler.scaleFactor);                }            }            width = Mathf.CeilToInt(width / UIContentScaler.scaleFactor);            height = Mathf.CeilToInt(height / UIContentScaler.scaleFactor);            if (_ui != null)            {                switch (fitScreen)                {                    case FitScreen.FitSize:                        _ui.SetSize(width, height);                        _ui.SetXY(0, 0, true);                        break;                    case FitScreen.FitWidthAndSetMiddle:                        _ui.SetSize(width, _ui.sourceHeight);                        _ui.SetXY(0, (int)((height - _ui.sourceHeight) / 2), true);                        break;                    case FitScreen.FitHeightAndSetCenter:                        _ui.SetSize(_ui.sourceWidth, height);                        _ui.SetXY((int)((width - _ui.sourceWidth) / 2), 0, true);                        break;                }                UpdateHitArea();            }            else            {                switch (fitScreen)                {                    case FitScreen.FitSize:                        uiBounds.position = new Vector2(0, 0);                        uiBounds.size = new Vector2(width, height);                        break;                    case FitScreen.FitWidthAndSetMiddle:                        uiBounds.position = new Vector2(0, (int)((height - cachedUISize.y) / 2));                        uiBounds.size = new Vector2(width, cachedUISize.y);                        break;                    case FitScreen.FitHeightAndSetCenter:                        uiBounds.position = new Vector2((int)((width - cachedUISize.x) / 2), 0);                        uiBounds.size = new Vector2(cachedUISize.x, height);                        break;                }            }        }        #region edit mode functions        void OnUpdateSource(object[] data)        {            if (Application.isPlaying)                return;            this.packageName = (string)data[0];            this.packagePath = (string)data[1];            this.componentName = (string)data[2];            if ((bool)data[3])            {                if (container == null)                    return;                if (_ui != null)                {                    _ui.Dispose();                    _ui = null;                }            }        }        public void ApplyModifiedProperties(bool sortingOrderChanged, bool fitScreenChanged)        {            if (container != null)            {                container.renderMode = renderMode;                container.renderCamera = renderCamera;                if (sortingOrderChanged)                {                    container._panelOrder = sortingOrder;                    if (Application.isPlaying)                        SetSortingOrder(sortingOrder, true);                    else                        EMRenderSupport.orderChanged = true;                }                container.fairyBatching = fairyBatching;            }            if (_ui != null)            {                if (fitScreen == FitScreen.None)                    _ui.position = position;                if (scale.x != 0 && scale.y != 0)                    _ui.scale = scale;                _ui.rotationX = rotation.x;                _ui.rotationY = rotation.y;                _ui.rotation = rotation.z;            }            if (fitScreen == FitScreen.None)                uiBounds.position = position;            screenSizeVer = 0;//force HandleScreenSizeChanged be called            if (fitScreenChanged && this.fitScreen == FitScreen.None)            {                if (_ui != null)                    _ui.SetSize(_ui.sourceWidth, _ui.sourceHeight);                uiBounds.size = cachedUISize;            }        }        public void MoveUI(Vector3 delta)        {            if (fitScreen != FitScreen.None)                return;            this.position += delta;            if (_ui != null)                _ui.position = position;            uiBounds.position = position;        }        public Vector3 GetUIWorldPosition()        {            if (_ui != null)                return _ui.displayObject.cachedTransform.position;            else                return this.container.cachedTransform.TransformPoint(uiBounds.position);        }        void OnDrawGizmos()        {            if (Application.isPlaying || this.container == null)                return;            Vector3 pos, size;            if (_ui != null)            {                Gizmos.matrix = _ui.displayObject.cachedTransform.localToWorldMatrix;                pos = new Vector3(_ui.width / 2, -_ui.height / 2, 0);                size = new Vector3(_ui.width, _ui.height, 0);            }            else            {                Gizmos.matrix = this.container.cachedTransform.localToWorldMatrix;                pos = new Vector3(uiBounds.x + uiBounds.width / 2, -uiBounds.y - uiBounds.height / 2, 0);                size = new Vector3(uiBounds.width, uiBounds.height, 0);            }            Gizmos.color = new Color(0, 0, 0, 0);            Gizmos.DrawCube(pos, size);            Gizmos.color = Color.white;            Gizmos.DrawWireCube(pos, size);        }        public int EM_sortingOrder        {            get { return sortingOrder; }        }        public void EM_BeforeUpdate()        {            if (container == null)                CreateContainer();            if (packageName != null && componentName != null && _ui == null)                CreateUI_EditMode();            if (screenSizeVer != StageCamera.screenSizeVer)                HandleScreenSizeChanged();        }        public void EM_Update(UpdateContext context)        {            DisplayObject.hideFlags = HideFlags.DontSaveInEditor;            container.Update(context);            if (setNativeChildrenOrder)            {                CacheNativeChildrenRenderers();                int cnt = _renders.Count;                int sv = context.renderingOrder++;                for (int i = 0; i < cnt; i++)                {                    Renderer r = _renders[i];                    if (r != null)                        r.sortingOrder = sv;                }            }        }        public void EM_Reload()        {            if (_ui != null)            {                _ui.Dispose();                _ui = null;            }        }        #endregion    }}
 |