| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704 | using System;using System.Collections.Generic;using UnityEngine;using FairyGUI.Utils;#if FAIRYGUI_TOLUAusing LuaInterface;#endifnamespace FairyGUI{    /// <summary>    /// Component    /// </summary>    public class GComponent : GObject    {        /// <summary>        /// Root container.        /// </summary>        public Container rootContainer { get; private set; }        /// <summary>        /// Content container. If the component is not clipped, then container==rootContainer.        /// </summary>        public Container container { get; protected set; }        /// <summary>        /// ScrollPane of the component. If the component is not scrollable, the value is null.        /// </summary>        public ScrollPane scrollPane { get; private set; }        internal List<GObject> _children;        internal List<Controller> _controllers;        internal List<Transition> _transitions;        internal bool _buildingDisplayList;        protected Margin _margin;        protected bool _trackBounds;        protected bool _boundsChanged;        protected ChildrenRenderOrder _childrenRenderOrder;        protected int _apexIndex;        internal Vector2 _alignOffset;        Vector2 _clipSoftness;        int _sortingChildCount;        Action _buildDelegate;        Controller _applyingController;        EventListener _onDrop;        public GComponent()        {            _children = new List<GObject>();            _controllers = new List<Controller>();            _transitions = new List<Transition>();            _margin = new Margin();            _buildDelegate = BuildNativeDisplayList;        }        override protected void CreateDisplayObject()        {            rootContainer = new Container("GComponent");            rootContainer.gOwner = this;            rootContainer.onUpdate += OnUpdate;            container = rootContainer;            displayObject = rootContainer;        }        override public void Dispose()        {            int cnt = _transitions.Count;            for (int i = 0; i < cnt; ++i)            {                Transition trans = _transitions[i];                trans.Dispose();            }            cnt = _controllers.Count;            for (int i = 0; i < cnt; ++i)            {                Controller c = _controllers[i];                c.Dispose();            }            if (scrollPane != null)                scrollPane.Dispose();            cnt = _children.Count;            for (int i = cnt - 1; i >= 0; --i)            {                GObject obj = _children[i];                obj.InternalSetParent(null); //Avoid GObject.RemoveParent call                obj.Dispose();            }            //因list的dispost无法正常释放loader加载的资源,修改第三方代码            base.Dispose(); //Dispose native tree first, avoid DisplayObject.RemoveFromParent call#if FAIRYGUI_TOLUA            if (_peerTable != null)            {                _peerTable.Dispose();                _peerTable = null;            }#endif#if FAIRYGUI_PUERTS            if (__onDispose != null)                __onDispose();            __onConstruct = null;            __onDispose = null;#endif        }        /// <summary>        /// Dispatched when an object was dragged and dropped to this component.        /// </summary>        public EventListener onDrop        {            get { return _onDrop ?? (_onDrop = new EventListener(this, "onDrop")); }        }        /// <summary>        /// Draw call optimization switch.        /// </summary>        public bool fairyBatching        {            get { return rootContainer.fairyBatching; }            set { rootContainer.fairyBatching = value; }        }        /// <summary>        ///         /// </summary>        /// <param name="childChanged"></param>        public void InvalidateBatchingState(bool childChanged)        {            if (childChanged)                container.InvalidateBatchingState(childChanged);            else                rootContainer.InvalidateBatchingState();        }        /// <summary>        /// If true, mouse/touch events cannot pass through the empty area of the component. Default is true.        /// </summary>        public bool opaque        {            get { return rootContainer.opaque; }            set { rootContainer.opaque = value; }        }        /// <summary>        ///         /// </summary>        /// <value></value>        public Margin margin        {            get { return _margin; }            set            {                _margin = value;                if (rootContainer.clipRect != null && scrollPane == null) //如果scrollPane不为空,则HandleSizeChanged里面的处理会促使ScrollPane处理                    container.SetXY(_margin.left + _alignOffset.x, _margin.top + _alignOffset.y);                HandleSizeChanged();            }        }        /// <summary>        ///         /// </summary>        public ChildrenRenderOrder childrenRenderOrder        {            get { return _childrenRenderOrder; }            set            {                if (_childrenRenderOrder != value)                {                    _childrenRenderOrder = value;                    BuildNativeDisplayList();                }            }        }        /// <summary>        ///         /// </summary>        public int apexIndex        {            get { return _apexIndex; }            set            {                if (_apexIndex != value)                {                    _apexIndex = value;                    if (_childrenRenderOrder == ChildrenRenderOrder.Arch)                        BuildNativeDisplayList();                }            }        }        /// <summary>        /// If true, children can be navigated by TAB from first to last, and repeat        /// </summary>        public bool tabStopChildren        {            get { return rootContainer.tabStopChildren; }            set { rootContainer.tabStopChildren = value; }        }        /// <summary>        /// Add a child to the component. It will be at the frontmost position.        /// </summary>        /// <param name="child">A child object</param>        /// <returns>GObject</returns>        public GObject AddChild(GObject child)        {            AddChildAt(child, _children.Count);            return child;        }        /// <summary>        /// Adds a child to the component at a certain index.        /// </summary>        /// <param name="child">A child object</param>        /// <param name="index">Index</param>        /// <returns>GObject</returns>        virtual public GObject AddChildAt(GObject child, int index)        {            if (index >= 0 && index <= _children.Count)            {                if (child.parent == this)                {                    SetChildIndex(child, index);                }                else                {                    child.RemoveFromParent();                    child.InternalSetParent(this);                    int cnt = _children.Count;                    if (child.sortingOrder != 0)                    {                        _sortingChildCount++;                        index = GetInsertPosForSortingChild(child);                    }                    else if (_sortingChildCount > 0)                    {                        if (index > (cnt - _sortingChildCount))                            index = cnt - _sortingChildCount;                    }                    if (index == cnt)                        _children.Add(child);                    else                        _children.Insert(index, child);                    ChildStateChanged(child);                    SetBoundsChangedFlag();                }                return child;            }            else            {                throw new Exception("Invalid child index: " + index + ">" + _children.Count);            }        }        int GetInsertPosForSortingChild(GObject target)        {            int cnt = _children.Count;            int i;            for (i = 0; i < cnt; i++)            {                GObject child = _children[i];                if (child == target)                    continue;                if (target.sortingOrder < child.sortingOrder)                    break;            }            return i;        }        /// <summary>        /// Removes a child from the component. If the object is not a child, nothing happens.         /// </summary>        /// <param name="child">A child object</param>        /// <returns>GObject</returns>        public GObject RemoveChild(GObject child)        {            return RemoveChild(child, false);        }        /// <summary>        /// Removes a child from the component. If the object is not a child, nothing happens.         /// </summary>        /// <param name="child">A child object</param>        /// <param name="dispose">If true, the child will be disposed right away.</param>        /// <returns>GObject</returns>        public GObject RemoveChild(GObject child, bool dispose)        {            int childIndex = _children.IndexOf(child);            if (childIndex != -1)            {                RemoveChildAt(childIndex, dispose);            }            return child;        }        /// <summary>        /// Removes a child at a certain index. Children above the child will move down.        /// </summary>        /// <param name="index">Index</param>        /// <returns>GObject</returns>        public GObject RemoveChildAt(int index)        {            return RemoveChildAt(index, false);        }        /// <summary>        /// Removes a child at a certain index. Children above the child will move down.        /// </summary>        /// <param name="index">Index</param>        /// <param name="dispose">If true, the child will be disposed right away.</param>        /// <returns>GObject</returns>        virtual public GObject RemoveChildAt(int index, bool dispose)        {            if (index >= 0 && index < numChildren)            {                GObject child = _children[index];                child.InternalSetParent(null);                if (child.sortingOrder != 0)                    _sortingChildCount--;                _children.RemoveAt(index);                child.group = null;                if (child.inContainer)                {                    container.RemoveChild(child.displayObject);                    if (_childrenRenderOrder == ChildrenRenderOrder.Arch)                    {                        UpdateContext.OnBegin -= _buildDelegate;                        UpdateContext.OnBegin += _buildDelegate;                    }                }                if (dispose)                    child.Dispose();                SetBoundsChangedFlag();                return child;            }            else                throw new Exception("Invalid child index: " + index + ">" + numChildren);        }        /// <summary>        /// Remove all children.        /// </summary>        public void RemoveChildren()        {            RemoveChildren(0, -1, false);        }        /// <summary>        /// Removes a range of children from the container (endIndex included).         /// </summary>        /// <param name="beginIndex">Begin index.</param>        /// <param name="endIndex">End index.(Included).</param>        /// <param name="dispose">If true, the child will be disposed right away.</param>        public void RemoveChildren(int beginIndex, int endIndex, bool dispose)        {            if (endIndex < 0 || endIndex >= numChildren)                endIndex = numChildren - 1;            for (int i = beginIndex; i <= endIndex; ++i)                RemoveChildAt(beginIndex, dispose);        }        /// <summary>        /// Returns a child object at a certain index. If index out of bounds, exception raised.        /// </summary>        /// <param name="index">Index</param>        /// <returns>A child object.</returns>        public GObject GetChildAt(int index)        {            if (index >= 0 && index < numChildren)                return _children[index];            else                throw new Exception("Invalid child index: " + index + ">" + numChildren);        }        /// <summary>        /// Returns a child object with a certain name.        /// </summary>        /// <param name="name">Name</param>        /// <returns>A child object. Null if not found.</returns>        public GObject GetChild(string name)        {            int cnt = _children.Count;            for (int i = 0; i < cnt; ++i)            {                if (_children[i].name == name)                    return _children[i];            }            return null;        }        public GObject GetChildByPath(string path)        {            string[] arr = path.Split('.');            int cnt = arr.Length;            GComponent gcom = this;            GObject obj = null;            for (int i = 0; i < cnt; ++i)            {                obj = gcom.GetChild(arr[i]);                if (obj == null)                    break;                if (i != cnt - 1)                {                    if (!(obj is GComponent))                    {                        obj = null;                        break;                    }                    else                        gcom = (GComponent)obj;                }            }            return obj;        }        /// <summary>        /// Returns a visible child object with a certain name.        /// </summary>        /// <param name="name">Name</param>        /// <returns>A child object. Null if not found.</returns>        public GObject GetVisibleChild(string name)        {            int cnt = _children.Count;            for (int i = 0; i < cnt; ++i)            {                GObject child = _children[i];                if (child.internalVisible && child.internalVisible2 && child.name == name)                    return child;            }            return null;        }        /// <summary>        /// Returns a child object belong to a group with a certain name.        /// </summary>        /// <param name="group">A group object</param>        /// <param name="name">Name</param>        /// <returns>A child object. Null if not found.</returns>        public GObject GetChildInGroup(GGroup group, string name)        {            int cnt = _children.Count;            for (int i = 0; i < cnt; ++i)            {                GObject child = _children[i];                if (child.group == group && child.name == name)                    return child;            }            return null;        }        internal GObject GetChildById(string id)        {            int cnt = _children.Count;            for (int i = 0; i < cnt; ++i)            {                if (_children[i].id == id)                    return _children[i];            }            return null;        }        /// <summary>        /// Returns a copy of all children with an array.        /// </summary>        /// <returns>An array contains all children</returns>        public GObject[] GetChildren()        {            return _children.ToArray();        }        /// <summary>        /// Returns the index of a child within the container, or "-1" if it is not found.        /// </summary>        /// <param name="child">A child object</param>        /// <returns>Index of the child. -1 If not found.</returns>        public int GetChildIndex(GObject child)        {            return _children.IndexOf(child);        }        /// <summary>        /// Moves a child to a certain index. Children at and after the replaced position move up.        /// </summary>        /// <param name="child">A Child</param>        /// <param name="index">Index</param>        public void SetChildIndex(GObject child, int index)        {            int oldIndex = _children.IndexOf(child);            if (oldIndex == -1)                throw new ArgumentException("Not a child of this container");            if (child.sortingOrder != 0) //no effect                return;            if (_sortingChildCount > 0)            {                int cnt = _children.Count;                if (index > (cnt - _sortingChildCount - 1))                    index = cnt - _sortingChildCount - 1;            }            _SetChildIndex(child, oldIndex, index);        }        /// <summary>        /// Moves a child to a certain position which is in front of the child previously at given index.        /// 与SetChildIndex不同的是,如果child原来在index的前面,那么child插入的位置是index-1,即保证排在原来占据index的对象的前面。        /// </summary>        /// <param name="child"></param>        /// <param name="index"></param>        public int SetChildIndexBefore(GObject child, int index)        {            int oldIndex = _children.IndexOf(child);            if (oldIndex == -1)                throw new ArgumentException("Not a child of this container");            if (child.sortingOrder != 0) //no effect                return oldIndex;            int cnt = _children.Count;            if (_sortingChildCount > 0)            {                if (index > (cnt - _sortingChildCount - 1))                    index = cnt - _sortingChildCount - 1;            }            if (oldIndex < index)                return _SetChildIndex(child, oldIndex, index - 1);            else                return _SetChildIndex(child, oldIndex, index);        }        int _SetChildIndex(GObject child, int oldIndex, int index)        {            int cnt = _children.Count;            if (index > cnt)                index = cnt;            if (oldIndex == index)                return oldIndex;            _children.RemoveAt(oldIndex);            if (index >= cnt)                _children.Add(child);            else                _children.Insert(index, child);            if (child.inContainer)            {                int displayIndex = 0;                if (_childrenRenderOrder == ChildrenRenderOrder.Ascent)                {                    for (int i = 0; i < index; i++)                    {                        GObject g = _children[i];                        if (g.inContainer)                            displayIndex++;                    }                    container.SetChildIndex(child.displayObject, displayIndex);                }                else if (_childrenRenderOrder == ChildrenRenderOrder.Descent)                {                    for (int i = cnt - 1; i > index; i--)                    {                        GObject g = _children[i];                        if (g.inContainer)                            displayIndex++;                    }                    container.SetChildIndex(child.displayObject, displayIndex);                }                else                {                    UpdateContext.OnBegin -= _buildDelegate;                    UpdateContext.OnBegin += _buildDelegate;                }                SetBoundsChangedFlag();            }            return index;        }        /// <summary>        /// Swaps the indexes of two children.         /// </summary>        /// <param name="child1">A child object</param>        /// <param name="child2">A child object</param>        public void SwapChildren(GObject child1, GObject child2)        {            int index1 = _children.IndexOf(child1);            int index2 = _children.IndexOf(child2);            if (index1 == -1 || index2 == -1)                throw new Exception("Not a child of this container");            SwapChildrenAt(index1, index2);        }        /// <summary>        ///  Swaps the indexes of two children.        /// </summary>        /// <param name="index1">index of first child</param>        /// <param name="index2">index of second child</param>        public void SwapChildrenAt(int index1, int index2)        {            GObject child1 = _children[index1];            GObject child2 = _children[index2];            SetChildIndex(child1, index2);            SetChildIndex(child2, index1);        }        /// <summary>        /// The number of children of this component.        /// </summary>        public int numChildren        {            get { return _children.Count; }        }        /// <summary>        ///         /// </summary>        /// <param name="obj"></param>        /// <returns></returns>        public bool IsAncestorOf(GObject obj)        {            if (obj == null)                return false;            GComponent p = obj.parent;            while (p != null)            {                if (p == this)                    return true;                p = p.parent;            }            return false;        }        /// <summary>        ///         /// </summary>        /// <param name="objs"></param>        public void ChangeChildrenOrder(IList<GObject> objs)        {            int cnt = objs.Count;            for (int i = 0; i < cnt; i++)            {                GObject obj = objs[i];                if (obj.parent != this)                    throw new Exception("Not a child of this container");                _children[i] = obj;            }            BuildNativeDisplayList();            SetBoundsChangedFlag();        }        /// <summary>        /// Adds a controller to the container.        /// </summary>        /// <param name="controller">Controller object</param>        public void AddController(Controller controller)        {            _controllers.Add(controller);            controller.parent = this;            ApplyController(controller);        }        /// <summary>        /// Returns a controller object  at a certain index.        /// </summary>        /// <param name="index">Index</param>        /// <returns>Controller object.</returns>        public Controller GetControllerAt(int index)        {            return _controllers[index];        }        /// <summary>        /// Returns a controller object with a certain name.        /// </summary>        /// <param name="name">Name</param>        /// <returns>Controller object. Null if not found.</returns>        public Controller GetController(string name)        {            int cnt = _controllers.Count;            for (int i = 0; i < cnt; ++i)            {                Controller c = _controllers[i];                if (c.name == name)                    return c;            }            return null;        }        /// <summary>        /// Removes a controller from the container.         /// </summary>        /// <param name="c">Controller object.</param>        public void RemoveController(Controller c)        {            int index = _controllers.IndexOf(c);            if (index == -1)                throw new Exception("controller not exists: " + c.name);            c.parent = null;            _controllers.RemoveAt(index);            int cnt = _children.Count;            for (int i = 0; i < cnt; ++i)            {                GObject child = _children[i];                child.HandleControllerChanged(c);            }        }        /// <summary>        /// Returns controller list.        /// </summary>        /// <returns>Controller list</returns>        public List<Controller> Controllers        {            get { return _controllers; }        }        /// <summary>        /// Returns a transition object  at a certain index.        /// </summary>        /// <param name="index">Index</param>        /// <returns>transition object.</returns>        public Transition GetTransitionAt(int index)        {            return _transitions[index];        }        /// <summary>        /// Returns a transition object at a certain name.         /// </summary>        /// <param name="name">Name</param>        /// <returns>Transition Object</returns>        public Transition GetTransition(string name)        {            int cnt = _transitions.Count;            for (int i = 0; i < cnt; ++i)            {                Transition trans = _transitions[i];                if (trans.name == name)                    return trans;            }            return null;        }        internal void ChildStateChanged(GObject child)        {            if (_buildingDisplayList)                return;            int cnt = _children.Count;            if (child is GGroup)            {                for (int i = 0; i < cnt; ++i)                {                    GObject g = _children[i];                    if (g.group == child)                        ChildStateChanged(g);                }                return;            }            if (child.displayObject == null)                return;            if (child.internalVisible)            {                if (child.displayObject.parent == null)                {                    if (_childrenRenderOrder == ChildrenRenderOrder.Ascent)                    {                        int index = 0;                        for (int i = 0; i < cnt; i++)                        {                            GObject g = _children[i];                            if (g == child)                                break;                            if (g.displayObject != null && g.displayObject.parent != null)                                index++;                        }                        container.AddChildAt(child.displayObject, index);                    }                    else if (_childrenRenderOrder == ChildrenRenderOrder.Descent)                    {                        int index = 0;                        for (int i = cnt - 1; i >= 0; i--)                        {                            GObject g = _children[i];                            if (g == child)                                break;                            if (g.displayObject != null && g.displayObject.parent != null)                                index++;                        }                        container.AddChildAt(child.displayObject, index);                    }                    else                    {                        container.AddChild(child.displayObject);                        UpdateContext.OnBegin -= _buildDelegate;                        UpdateContext.OnBegin += _buildDelegate;                    }                }            }            else            {                if (child.displayObject.parent != null)                {                    container.RemoveChild(child.displayObject);                    if (_childrenRenderOrder == ChildrenRenderOrder.Arch)                    {                        UpdateContext.OnBegin -= _buildDelegate;                        UpdateContext.OnBegin += _buildDelegate;                    }                }            }        }        void BuildNativeDisplayList()        {            if (displayObject == null || displayObject.isDisposed)                return;            int cnt = _children.Count;            if (cnt == 0)                return;            switch (_childrenRenderOrder)            {                case ChildrenRenderOrder.Ascent:                    {                        for (int i = 0; i < cnt; i++)                        {                            GObject child = _children[i];                            if (child.displayObject != null && child.internalVisible)                                container.AddChild(child.displayObject);                        }                    }                    break;                case ChildrenRenderOrder.Descent:                    {                        for (int i = cnt - 1; i >= 0; i--)                        {                            GObject child = _children[i];                            if (child.displayObject != null && child.internalVisible)                                container.AddChild(child.displayObject);                        }                    }                    break;                case ChildrenRenderOrder.Arch:                    {                        int apex = Mathf.Clamp(_apexIndex, 0, cnt);                        for (int i = 0; i < apex; i++)                        {                            GObject child = _children[i];                            if (child.displayObject != null && child.internalVisible)                                container.AddChild(child.displayObject);                        }                        for (int i = cnt - 1; i >= apex; i--)                        {                            GObject child = _children[i];                            if (child.displayObject != null && child.internalVisible)                                container.AddChild(child.displayObject);                        }                    }                    break;            }        }        internal void ApplyController(Controller c)        {            _applyingController = c;            int cnt = _children.Count;            for (int i = 0; i < cnt; ++i)            {                GObject child = _children[i];                child.HandleControllerChanged(c);            }            _applyingController = null;            c.RunActions();        }        void ApplyAllControllers()        {            int cnt = _controllers.Count;            for (int i = 0; i < cnt; ++i)            {                Controller controller = _controllers[i];                ApplyController(controller);            }        }        internal void AdjustRadioGroupDepth(GObject obj, Controller c)        {            int cnt = _children.Count;            int i;            GObject child;            int myIndex = -1, maxIndex = -1;            for (i = 0; i < cnt; i++)            {                child = _children[i];                if (child == obj)                {                    myIndex = i;                }                else if ((child is GButton)                    && ((GButton)child).relatedController == c)                {                    if (i > maxIndex)                        maxIndex = i;                }            }            if (myIndex < maxIndex)            {                if (_applyingController != null)                    _children[maxIndex].HandleControllerChanged(_applyingController);                this.SwapChildrenAt(myIndex, maxIndex);            }        }        /// <summary>        /// If clipping softness is set, clipped containers will have soft border effect.        /// </summary>        public Vector2 clipSoftness        {            get { return _clipSoftness; }            set            {                _clipSoftness = value;                if (scrollPane != null)                    scrollPane.UpdateClipSoft();                else if (_clipSoftness.x > 0 || _clipSoftness.y > 0)                    rootContainer.clipSoftness = new Vector4(value.x, value.y, value.x, value.y);                else                    rootContainer.clipSoftness = null;            }        }        /// <summary>        /// The mask of the component.        /// </summary>        public DisplayObject mask        {            get { return container.mask; }            set            {                container.mask = value;                if (value != null && value.parent != container)                    container.AddChild(value);            }        }        /// <summary>        ///         /// </summary>        public bool reversedMask        {            get { return container.reversedMask; }            set { container.reversedMask = value; }        }        /// <summary>        ///         /// </summary>        public string baseUserData        {            get            {                ByteBuffer buffer = packageItem.rawData;                buffer.Seek(0, 4);                return buffer.ReadS();            }        }        /// <summary>        /// Test if a child is in view.        /// </summary>        /// <param name="child">A child object</param>        /// <returns>True if in view</returns>        public bool IsChildInView(GObject child)        {            if (scrollPane != null)            {                return scrollPane.IsChildInView(child);            }            else if (rootContainer.clipRect != null)            {                return child.x + child.width >= 0 && child.x <= this.width                    && child.y + child.height >= 0 && child.y <= this.height;            }            else                return true;        }        virtual public int GetFirstChildInView()        {            int cnt = _children.Count;            for (int i = 0; i < cnt; ++i)            {                GObject child = _children[i];                if (IsChildInView(child))                    return i;            }            return -1;        }        protected void SetupScroll(ByteBuffer buffer)        {            if (rootContainer == container)            {                container = new Container();                rootContainer.AddChild(container);            }            scrollPane = new ScrollPane(this);            scrollPane.Setup(buffer);        }        protected void SetupOverflow(OverflowType overflow)        {            if (overflow == OverflowType.Hidden)            {                if (rootContainer == container)                {                    container = new Container();                    rootContainer.AddChild(container);                }                UpdateClipRect();                container.SetXY(_margin.left, _margin.top);            }            else if (_margin.left != 0 || _margin.top != 0)            {                if (rootContainer == container)                {                    container = new Container();                    rootContainer.AddChild(container);                }                container.SetXY(_margin.left, _margin.top);            }        }        void UpdateClipRect()        {            if (scrollPane == null)            {                float w = this.width - (_margin.left + _margin.right);                float h = this.height - (_margin.top + _margin.bottom);                rootContainer.clipRect = new Rect(_margin.left, _margin.top, w, h);            }            else                rootContainer.clipRect = new Rect(0, 0, this.width, this.height);        }        override protected void HandleSizeChanged()        {            base.HandleSizeChanged();            if (scrollPane != null)                scrollPane.OnOwnerSizeChanged();            if (rootContainer.clipRect != null)                UpdateClipRect();        }        override protected void HandleGrayedChanged()        {            Controller cc = GetController("grayed");            if (cc != null)                cc.selectedIndex = this.grayed ? 1 : 0;            else                base.HandleGrayedChanged();        }        override public void HandleControllerChanged(Controller c)        {            base.HandleControllerChanged(c);            if (scrollPane != null)                scrollPane.HandleControllerChanged(c);        }        /// <summary>        /// Notify the component the bounds should recaculate.        /// </summary>        public void SetBoundsChangedFlag()        {            if (scrollPane == null && !_trackBounds)                return;            _boundsChanged = true;        }        /// <summary>        /// Make sure the bounds of the component is correct.         /// Bounds of the component is not updated on every changed. For example, you add a new child to the list, children in the list will be rearranged in next frame.        /// If you want to access the correct child position immediatelly, call this function first.        /// </summary>        public void EnsureBoundsCorrect()        {            if (_boundsChanged)                UpdateBounds();        }        virtual protected void UpdateBounds()        {            float ax, ay, aw, ah;            if (_children.Count > 0)            {                ax = int.MaxValue;                ay = int.MaxValue;                float ar = int.MinValue, ab = int.MinValue;                float tmp;                int cnt = _children.Count;                for (int i = 0; i < cnt; ++i)                {                    GObject child = _children[i];                    tmp = child.x;                    if (tmp < ax)                        ax = tmp;                    tmp = child.y;                    if (tmp < ay)                        ay = tmp;                    tmp = child.x + child.actualWidth;                    if (tmp > ar)                        ar = tmp;                    tmp = child.y + child.actualHeight;                    if (tmp > ab)                        ab = tmp;                }                aw = ar - ax;                ah = ab - ay;            }            else            {                ax = 0;                ay = 0;                aw = 0;                ah = 0;            }            SetBounds(ax, ay, aw, ah);        }        protected void SetBounds(float ax, float ay, float aw, float ah)        {            _boundsChanged = false;            if (scrollPane != null)                scrollPane.SetContentSize(Mathf.RoundToInt(ax + aw), Mathf.RoundToInt(ay + ah));        }        /// <summary>        /// Viwe port width of the container.        /// </summary>        public float viewWidth        {            get            {                if (scrollPane != null)                    return scrollPane.viewWidth;                else                    return this.width - _margin.left - _margin.right;            }            set            {                if (scrollPane != null)                    scrollPane.viewWidth = value;                else                    this.width = value + _margin.left + _margin.right;            }        }        /// <summary>        /// View port height of the container.        /// </summary>        public float viewHeight        {            get            {                if (scrollPane != null)                    return scrollPane.viewHeight;                else                    return this.height - _margin.top - _margin.bottom;            }            set            {                if (scrollPane != null)                    scrollPane.viewHeight = value;                else                    this.height = value + _margin.top + _margin.bottom;            }        }        virtual protected internal void GetSnappingPosition(ref float xValue, ref float yValue)        {            int cnt = _children.Count;            if (cnt == 0)                return;            EnsureBoundsCorrect();            GObject obj = null;            int i = 0;            if (yValue != 0)            {                for (; i < cnt; i++)                {                    obj = _children[i];                    if (yValue < obj.y)                    {                        if (i == 0)                        {                            yValue = 0;                            break;                        }                        else                        {                            GObject prev = _children[i - 1];                            if (yValue < prev.y + prev.height / 2) //top half part                                yValue = prev.y;                            else //bottom half part                                yValue = obj.y;                            break;                        }                    }                }                if (i == cnt)                    yValue = obj.y;            }            if (xValue != 0)            {                if (i > 0)                    i--;                for (; i < cnt; i++)                {                    obj = _children[i];                    if (xValue < obj.x)                    {                        if (i == 0)                        {                            xValue = 0;                            break;                        }                        else                        {                            GObject prev = _children[i - 1];                            if (xValue < prev.x + prev.width / 2) // top half part                                xValue = prev.x;                            else//bottom half part                                xValue = obj.x;                            break;                        }                    }                }                if (i == cnt)                    xValue = obj.x;            }        }        internal void ChildSortingOrderChanged(GObject child, int oldValue, int newValue)        {            if (newValue == 0)            {                _sortingChildCount--;                SetChildIndex(child, _children.Count);            }            else            {                if (oldValue == 0)                    _sortingChildCount++;                int oldIndex = _children.IndexOf(child);                int index = GetInsertPosForSortingChild(child);                if (oldIndex < index)                    _SetChildIndex(child, oldIndex, index - 1);                else                    _SetChildIndex(child, oldIndex, index);            }        }        /// <summary>        /// 每帧调用的一个回调。如果你要override,请记住以下两点:        /// 1、记得调用base.onUpdate;        /// 2、不要在方法里进行任何会更改显示列表的操作,例如AddChild、RemoveChild、visible等。        /// </summary>        virtual protected void OnUpdate()        {            if (_boundsChanged)                UpdateBounds();        }        override public void ConstructFromResource()        {            ConstructFromResource(null, 0);        }        internal void ConstructFromResource(List<GObject> objectPool, int poolIndex)        {            this.gameObjectName = packageItem.name;            PackageItem contentItem = packageItem.getBranch();            if (!contentItem.translated)            {                contentItem.translated = true;                TranslationHelper.TranslateComponent(contentItem);            }            ByteBuffer buffer = contentItem.rawData;            buffer.Seek(0, 0);            underConstruct = true;            sourceWidth = buffer.ReadInt();            sourceHeight = buffer.ReadInt();            initWidth = sourceWidth;            initHeight = sourceHeight;            SetSize(sourceWidth, sourceHeight);            if (buffer.ReadBool())            {                minWidth = buffer.ReadInt();                maxWidth = buffer.ReadInt();                minHeight = buffer.ReadInt();                maxHeight = buffer.ReadInt();            }            if (buffer.ReadBool())            {                float f1 = buffer.ReadFloat();                float f2 = buffer.ReadFloat();                SetPivot(f1, f2, buffer.ReadBool());            }            if (buffer.ReadBool())            {                _margin.top = buffer.ReadInt();                _margin.bottom = buffer.ReadInt();                _margin.left = buffer.ReadInt();                _margin.right = buffer.ReadInt();            }            OverflowType overflow = (OverflowType)buffer.ReadByte();            if (overflow == OverflowType.Scroll)            {                int savedPos = buffer.position;                buffer.Seek(0, 7);                SetupScroll(buffer);                buffer.position = savedPos;            }            else                SetupOverflow(overflow);            if (buffer.ReadBool())            {                int i1 = buffer.ReadInt();                int i2 = buffer.ReadInt();                this.clipSoftness = new Vector2(i1, i2);            }            _buildingDisplayList = true;            buffer.Seek(0, 1);            int controllerCount = buffer.ReadShort();            for (int i = 0; i < controllerCount; i++)            {                int nextPos = buffer.ReadShort();                nextPos += buffer.position;                Controller controller = new Controller();                _controllers.Add(controller);                controller.parent = this;                controller.Setup(buffer);                buffer.position = nextPos;            }            buffer.Seek(0, 2);            GObject child;            int childCount = buffer.ReadShort();            for (int i = 0; i < childCount; i++)            {                int dataLen = buffer.ReadShort();                int curPos = buffer.position;                if (objectPool != null)                    child = objectPool[poolIndex + i];                else                {                    buffer.Seek(curPos, 0);                    ObjectType type = (ObjectType)buffer.ReadByte();                    string src = buffer.ReadS();                    string pkgId = buffer.ReadS();                    PackageItem pi = null;                    if (src != null)                    {                        UIPackage pkg;                        if (pkgId != null)                            pkg = UIPackage.GetById(pkgId);                        else                            pkg = contentItem.owner;                        pi = pkg != null ? pkg.GetItem(src) : null;                    }                    if (pi != null)                    {                        child = UIObjectFactory.NewObject(pi);                        child.ConstructFromResource();                    }                    else                        child = UIObjectFactory.NewObject(type);                }                child.underConstruct = true;                child.Setup_BeforeAdd(buffer, curPos);                child.InternalSetParent(this);                _children.Add(child);                buffer.position = curPos + dataLen;            }            buffer.Seek(0, 3);            this.relations.Setup(buffer, true);            buffer.Seek(0, 2);            buffer.Skip(2);            for (int i = 0; i < childCount; i++)            {                int nextPos = buffer.ReadShort();                nextPos += buffer.position;                buffer.Seek(buffer.position, 3);                _children[i].relations.Setup(buffer, false);                buffer.position = nextPos;            }            buffer.Seek(0, 2);            buffer.Skip(2);            for (int i = 0; i < childCount; i++)            {                int nextPos = buffer.ReadShort();                nextPos += buffer.position;                child = _children[i];                child.Setup_AfterAdd(buffer, buffer.position);                child.underConstruct = false;                if (child.displayObject != null)                    child.displayObject.cachedTransform.SetParent(this.displayObject.cachedTransform, false);                buffer.position = nextPos;            }            buffer.Seek(0, 4);            buffer.Skip(2); //customData            this.opaque = buffer.ReadBool();            int maskId = buffer.ReadShort();            if (maskId != -1)            {                container.mask = GetChildAt(maskId).displayObject;                if (buffer.ReadBool())                    container.reversedMask = true;            }            {                string hitTestId = buffer.ReadS();                int i1 = buffer.ReadInt();                int i2 = buffer.ReadInt();                if (hitTestId != null)                {                    PackageItem pi = contentItem.owner.GetItem(hitTestId);                    if (pi != null && pi.pixelHitTestData != null)                        rootContainer.hitArea = new PixelHitTest(pi.pixelHitTestData, i1, i2, sourceWidth, sourceHeight);                }                else if (i1 != 0 && i2 != -1)                {                    rootContainer.hitArea = new ShapeHitTest(this.GetChildAt(i2).displayObject);                }            }            if (buffer.version >= 5)            {                string str = buffer.ReadS();                if (!string.IsNullOrEmpty(str))                    this.onAddedToStage.Add(() => __playSound(str, 1));                string str2 = buffer.ReadS();                if (!string.IsNullOrEmpty(str2))                    this.onRemovedFromStage.Add(() => __playSound(str2, 1));            }            buffer.Seek(0, 5);            int transitionCount = buffer.ReadShort();            for (int i = 0; i < transitionCount; i++)            {                int nextPos = buffer.ReadShort();                nextPos += buffer.position;                Transition trans = new Transition(this);                trans.Setup(buffer);                _transitions.Add(trans);                buffer.position = nextPos;            }            if (_transitions.Count > 0)            {                this.onAddedToStage.Add(__addedToStage);                this.onRemovedFromStage.Add(__removedFromStage);            }            ApplyAllControllers();            _buildingDisplayList = false;            underConstruct = false;            BuildNativeDisplayList();            SetBoundsChangedFlag();            if (contentItem.objectType != ObjectType.Component)                ConstructExtension(buffer);            ConstructFromXML(null);#if FAIRYGUI_TOLUA            CallLua("ctor");#endif#if FAIRYGUI_PUERTS            if (__onConstruct != null)                __onConstruct();#endif        }        virtual protected void ConstructExtension(ByteBuffer buffer)        {        }        /// <summary>        /// Method for extensions to override        /// </summary>        /// <param name="xml"></param>        virtual public void ConstructFromXML(XML xml)        {        }        public override void Setup_AfterAdd(ByteBuffer buffer, int beginPos)        {            base.Setup_AfterAdd(buffer, beginPos);            buffer.Seek(beginPos, 4);            int pageController = buffer.ReadShort();            if (pageController != -1 && scrollPane != null && scrollPane.pageMode)                scrollPane.pageController = parent.GetControllerAt(pageController);            int cnt = buffer.ReadShort();            for (int i = 0; i < cnt; i++)            {                Controller cc = GetController(buffer.ReadS());                string pageId = buffer.ReadS();                if (cc != null)                    cc.selectedPageId = pageId;            }            if (buffer.version >= 2)            {                cnt = buffer.ReadShort();                for (int i = 0; i < cnt; i++)                {                    string target = buffer.ReadS();                    int propertyId = buffer.ReadShort();                    string value = buffer.ReadS();                    GObject obj = this.GetChildByPath(target);                    if (obj != null)                    {                        if (propertyId == 0)                            obj.text = value;                        else if (propertyId == 1)                            obj.icon = value;                    }                }            }        }        void __playSound(string soundRes, float volumeScale)        {            NAudioClip sound = UIPackage.GetItemAssetByURL(soundRes) as NAudioClip;            if (sound != null && sound.nativeClip != null)                Stage.inst.PlayOneShotSound(sound.nativeClip, volumeScale);        }        void __addedToStage()        {            int cnt = _transitions.Count;            for (int i = 0; i < cnt; ++i)                _transitions[i].OnOwnerAddedToStage();        }        void __removedFromStage()        {            int cnt = _transitions.Count;            for (int i = 0; i < cnt; ++i)                _transitions[i].OnOwnerRemovedFromStage();        }#if FAIRYGUI_TOLUA        internal LuaTable _peerTable;        public void SetLuaPeer(LuaTable peerTable)        {            _peerTable = peerTable;        }        [NoToLua]        public bool CallLua(string funcName)        {            if (_peerTable != null)            {                LuaFunction ctor = _peerTable.GetLuaFunction(funcName);                if (ctor != null)                {                    try                    {                        ctor.Call(this);                    }                    catch (Exception err)                    {                        Debug.LogError(err);                    }                                        ctor.Dispose();                    return true;                }            }            return false;        }#endif#if FAIRYGUI_PUERTS        public Action __onConstruct;        public Action __onDispose;#endif    }}
 |