Container.cs 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace FairyGUI
  6. {
  7. /// <summary>
  8. ///
  9. /// </summary>
  10. public class Container : DisplayObject
  11. {
  12. /// <summary>
  13. ///
  14. /// </summary>
  15. public RenderMode renderMode;
  16. /// <summary>
  17. ///
  18. /// </summary>
  19. public Camera renderCamera;
  20. /// <summary>
  21. ///
  22. /// </summary>
  23. public bool opaque;
  24. /// <summary>
  25. ///
  26. /// </summary>
  27. public Vector4? clipSoftness;
  28. /// <summary>
  29. ///
  30. /// </summary>
  31. public IHitTest hitArea;
  32. /// <summary>
  33. ///
  34. /// </summary>
  35. public bool touchChildren;
  36. /// <summary>
  37. ///
  38. /// </summary>
  39. public event Action onUpdate;
  40. /// <summary>
  41. ///
  42. /// </summary>
  43. public bool reversedMask;
  44. List<DisplayObject> _children;
  45. DisplayObject _mask;
  46. Rect? _clipRect;
  47. List<DisplayObject> _descendants;
  48. internal int _panelOrder;
  49. internal DisplayObject _lastFocus;
  50. /// <summary>
  51. ///
  52. /// </summary>
  53. public Container()
  54. : base()
  55. {
  56. CreateGameObject("Container");
  57. Init();
  58. }
  59. /// <summary>
  60. ///
  61. /// </summary>
  62. /// <param name="gameObjectName"></param>
  63. public Container(string gameObjectName)
  64. : base()
  65. {
  66. CreateGameObject(gameObjectName);
  67. Init();
  68. }
  69. /// <summary>
  70. ///
  71. /// </summary>
  72. /// <param name="attachTarget"></param>
  73. public Container(GameObject attachTarget)
  74. : base()
  75. {
  76. SetGameObject(attachTarget);
  77. Init();
  78. }
  79. void Init()
  80. {
  81. _children = new List<DisplayObject>();
  82. touchChildren = true;
  83. }
  84. /// <summary>
  85. ///
  86. /// </summary>
  87. public int numChildren
  88. {
  89. get { return _children.Count; }
  90. }
  91. /// <summary>
  92. ///
  93. /// </summary>
  94. /// <param name="child"></param>
  95. /// <returns></returns>
  96. public DisplayObject AddChild(DisplayObject child)
  97. {
  98. AddChildAt(child, _children.Count);
  99. return child;
  100. }
  101. /// <summary>
  102. ///
  103. /// </summary>
  104. /// <param name="child"></param>
  105. /// <param name="index"></param>
  106. /// <returns></returns>
  107. public DisplayObject AddChildAt(DisplayObject child, int index)
  108. {
  109. int count = _children.Count;
  110. if (index >= 0 && index <= count)
  111. {
  112. if (child.parent == this)
  113. {
  114. SetChildIndex(child, index);
  115. }
  116. else
  117. {
  118. child.RemoveFromParent();
  119. if (index == count)
  120. _children.Add(child);
  121. else
  122. _children.Insert(index, child);
  123. child.InternalSetParent(this);
  124. if (stage != null)
  125. {
  126. if (child is Container)
  127. child.BroadcastEvent("onAddedToStage", null);
  128. else
  129. child.DispatchEvent("onAddedToStage", null);
  130. }
  131. InvalidateBatchingState(true);
  132. }
  133. return child;
  134. }
  135. else
  136. {
  137. throw new Exception("Invalid child index");
  138. }
  139. }
  140. /// <summary>
  141. ///
  142. /// </summary>
  143. /// <param name="child"></param>
  144. /// <returns></returns>
  145. public bool Contains(DisplayObject child)
  146. {
  147. return _children.Contains(child);
  148. }
  149. /// <summary>
  150. ///
  151. /// </summary>
  152. /// <param name="index"></param>
  153. /// <returns></returns>
  154. public DisplayObject GetChildAt(int index)
  155. {
  156. return _children[index];
  157. }
  158. /// <summary>
  159. ///
  160. /// </summary>
  161. /// <param name="name"></param>
  162. /// <returns></returns>
  163. public DisplayObject GetChild(string name)
  164. {
  165. int cnt = _children.Count;
  166. for (int i = 0; i < cnt; ++i)
  167. {
  168. if (_children[i].name == name)
  169. return _children[i];
  170. }
  171. return null;
  172. }
  173. /// <summary>
  174. ///
  175. /// </summary>
  176. /// <returns></returns>
  177. public DisplayObject[] GetChildren()
  178. {
  179. return _children.ToArray();
  180. }
  181. /// <summary>
  182. ///
  183. /// </summary>
  184. /// <param name="child"></param>
  185. /// <returns></returns>
  186. public int GetChildIndex(DisplayObject child)
  187. {
  188. return _children.IndexOf(child);
  189. }
  190. /// <summary>
  191. ///
  192. /// </summary>
  193. /// <param name="child"></param>
  194. /// <returns></returns>
  195. public DisplayObject RemoveChild(DisplayObject child)
  196. {
  197. return RemoveChild(child, false);
  198. }
  199. /// <summary>
  200. ///
  201. /// </summary>
  202. /// <param name="child"></param>
  203. /// <param name="dispose"></param>
  204. /// <returns></returns>
  205. public DisplayObject RemoveChild(DisplayObject child, bool dispose)
  206. {
  207. if (child.parent != this)
  208. throw new Exception("obj is not a child");
  209. int i = _children.IndexOf(child);
  210. if (i >= 0)
  211. return RemoveChildAt(i, dispose);
  212. else
  213. return null;
  214. }
  215. /// <summary>
  216. ///
  217. /// </summary>
  218. /// <param name="index"></param>
  219. /// <returns></returns>
  220. public DisplayObject RemoveChildAt(int index)
  221. {
  222. return RemoveChildAt(index, false);
  223. }
  224. /// <summary>
  225. ///
  226. /// </summary>
  227. /// <param name="index"></param>
  228. /// <param name="dispose"></param>
  229. /// <returns></returns>
  230. public DisplayObject RemoveChildAt(int index, bool dispose)
  231. {
  232. if (index >= 0 && index < _children.Count)
  233. {
  234. DisplayObject child = _children[index];
  235. if (stage != null && (child._flags & Flags.Disposed) == 0)
  236. {
  237. if (child is Container)
  238. {
  239. child.BroadcastEvent("onRemovedFromStage", null);
  240. if (child == Stage.inst.focus || ((Container)child).IsAncestorOf(Stage.inst.focus))
  241. Stage.inst._OnFocusRemoving(this);
  242. }
  243. else
  244. {
  245. child.DispatchEvent("onRemovedFromStage", null);
  246. if (child == Stage.inst.focus)
  247. Stage.inst._OnFocusRemoving(this);
  248. }
  249. }
  250. _children.Remove(child);
  251. InvalidateBatchingState(true);
  252. if (!dispose)
  253. child.InternalSetParent(null);
  254. else
  255. child.Dispose();
  256. return child;
  257. }
  258. else
  259. throw new Exception("Invalid child index");
  260. }
  261. /// <summary>
  262. ///
  263. /// </summary>
  264. public void RemoveChildren()
  265. {
  266. RemoveChildren(0, int.MaxValue, false);
  267. }
  268. /// <summary>
  269. ///
  270. /// </summary>
  271. /// <param name="beginIndex"></param>
  272. /// <param name="endIndex"></param>
  273. /// <param name="dispose"></param>
  274. public void RemoveChildren(int beginIndex, int endIndex, bool dispose)
  275. {
  276. if (endIndex < 0 || endIndex >= numChildren)
  277. endIndex = numChildren - 1;
  278. for (int i = beginIndex; i <= endIndex; ++i)
  279. RemoveChildAt(beginIndex, dispose);
  280. }
  281. /// <summary>
  282. ///
  283. /// </summary>
  284. /// <param name="child"></param>
  285. /// <param name="index"></param>
  286. public void SetChildIndex(DisplayObject child, int index)
  287. {
  288. int oldIndex = _children.IndexOf(child);
  289. if (oldIndex == index) return;
  290. if (oldIndex == -1) throw new ArgumentException("Not a child of this container");
  291. _children.RemoveAt(oldIndex);
  292. if (index >= _children.Count)
  293. _children.Add(child);
  294. else
  295. _children.Insert(index, child);
  296. InvalidateBatchingState(true);
  297. }
  298. /// <summary>
  299. ///
  300. /// </summary>
  301. /// <param name="child1"></param>
  302. /// <param name="child2"></param>
  303. public void SwapChildren(DisplayObject child1, DisplayObject child2)
  304. {
  305. int index1 = _children.IndexOf(child1);
  306. int index2 = _children.IndexOf(child2);
  307. if (index1 == -1 || index2 == -1)
  308. throw new Exception("Not a child of this container");
  309. SwapChildrenAt(index1, index2);
  310. }
  311. /// <summary>
  312. ///
  313. /// </summary>
  314. /// <param name="index1"></param>
  315. /// <param name="index2"></param>
  316. public void SwapChildrenAt(int index1, int index2)
  317. {
  318. DisplayObject obj1 = _children[index1];
  319. DisplayObject obj2 = _children[index2];
  320. _children[index1] = obj2;
  321. _children[index2] = obj1;
  322. InvalidateBatchingState(true);
  323. }
  324. /// <summary>
  325. ///
  326. /// </summary>
  327. /// <param name="indice"></param>
  328. /// <param name="objs"></param>
  329. public void ChangeChildrenOrder(IList<int> indice, IList<DisplayObject> objs)
  330. {
  331. int cnt = objs.Count;
  332. for (int i = 0; i < cnt; i++)
  333. {
  334. DisplayObject obj = objs[i];
  335. if (obj.parent != this)
  336. throw new Exception("Not a child of this container");
  337. _children[indice[i]] = obj;
  338. }
  339. InvalidateBatchingState(true);
  340. }
  341. /// <summary>
  342. ///
  343. /// </summary>
  344. /// <returns></returns>
  345. public IEnumerator<DisplayObject> GetDescendants(bool backward)
  346. {
  347. return new DescendantsEnumerator(this, backward);
  348. }
  349. /// <summary>
  350. ///
  351. /// </summary>
  352. public Rect? clipRect
  353. {
  354. get { return _clipRect; }
  355. set
  356. {
  357. if (_clipRect != value)
  358. {
  359. _clipRect = value;
  360. UpdateBatchingFlags();
  361. }
  362. }
  363. }
  364. /// <summary>
  365. ///
  366. /// </summary>
  367. public DisplayObject mask
  368. {
  369. get { return _mask; }
  370. set
  371. {
  372. if (_mask != value)
  373. {
  374. _mask = value;
  375. UpdateBatchingFlags();
  376. }
  377. }
  378. }
  379. /// <summary>
  380. ///
  381. /// </summary>
  382. public void CreateGraphics()
  383. {
  384. if (graphics == null)
  385. {
  386. graphics = new NGraphics(this.gameObject);
  387. graphics.texture = NTexture.Empty;
  388. }
  389. }
  390. public override Rect GetBounds(DisplayObject targetSpace)
  391. {
  392. if (_clipRect != null)
  393. return TransformRect((Rect)_clipRect, targetSpace);
  394. int count = _children.Count;
  395. Rect rect;
  396. if (count == 0)
  397. {
  398. Vector2 v = TransformPoint(Vector2.zero, targetSpace);
  399. rect = Rect.MinMaxRect(v.x, v.y, 0, 0);
  400. }
  401. else if (count == 1)
  402. {
  403. rect = _children[0].GetBounds(targetSpace);
  404. }
  405. else
  406. {
  407. float minX = float.MaxValue, maxX = float.MinValue;
  408. float minY = float.MaxValue, maxY = float.MinValue;
  409. for (int i = 0; i < count; ++i)
  410. {
  411. rect = _children[i].GetBounds(targetSpace);
  412. minX = minX < rect.xMin ? minX : rect.xMin;
  413. maxX = maxX > rect.xMax ? maxX : rect.xMax;
  414. minY = minY < rect.yMin ? minY : rect.yMin;
  415. maxY = maxY > rect.yMax ? maxY : rect.yMax;
  416. }
  417. rect = Rect.MinMaxRect(minX, minY, maxX, maxY);
  418. }
  419. return rect;
  420. }
  421. /// <summary>
  422. ///
  423. /// </summary>
  424. /// <returns></returns>
  425. public Camera GetRenderCamera()
  426. {
  427. if (renderMode == RenderMode.ScreenSpaceOverlay)
  428. return StageCamera.main;
  429. else
  430. {
  431. Camera cam = this.renderCamera;
  432. if (cam == null)
  433. {
  434. if (HitTestContext.cachedMainCamera != null)
  435. cam = HitTestContext.cachedMainCamera;
  436. else
  437. {
  438. cam = Camera.main;
  439. if (cam == null)
  440. cam = StageCamera.main;
  441. }
  442. }
  443. return cam;
  444. }
  445. }
  446. /// <summary>
  447. ///
  448. /// </summary>
  449. /// <param name="stagePoint"></param>
  450. /// <param name="forTouch"></param>
  451. /// <param name="displayIndex"></param>
  452. /// <returns></returns>
  453. public DisplayObject HitTest(Vector2 stagePoint, bool forTouch)
  454. {
  455. if (StageCamera.main == null)
  456. {
  457. if (this is Stage)
  458. return this;
  459. else
  460. return null;
  461. }
  462. HitTestContext.screenPoint = new Vector3(stagePoint.x, Screen.height - stagePoint.y, 0);
  463. if (Display.displays.Length > 1)
  464. {
  465. Vector3 p = Display.RelativeMouseAt(HitTestContext.screenPoint);
  466. if (p != Vector3.zero)
  467. HitTestContext.screenPoint = p;
  468. }
  469. HitTestContext.worldPoint = StageCamera.main.ScreenToWorldPoint(HitTestContext.screenPoint);
  470. HitTestContext.direction = Vector3.back;
  471. HitTestContext.forTouch = forTouch;
  472. HitTestContext.camera = StageCamera.main;
  473. DisplayObject ret = HitTest();
  474. if (ret != null)
  475. return ret;
  476. else if (this is Stage)
  477. return this;
  478. else
  479. return null;
  480. }
  481. override protected DisplayObject HitTest()
  482. {
  483. if ((_flags & Flags.UserGameObject) != 0 && !gameObject.activeInHierarchy)
  484. return null;
  485. if (this.cachedTransform.localScale.x == 0 || this.cachedTransform.localScale.y == 0)
  486. return null;
  487. Camera savedCamera = HitTestContext.camera;
  488. Vector3 savedWorldPoint = HitTestContext.worldPoint;
  489. Vector3 savedDirection = HitTestContext.direction;
  490. DisplayObject target;
  491. if (renderMode != RenderMode.ScreenSpaceOverlay || (_flags & Flags.UserGameObject) != 0)
  492. {
  493. Camera cam = GetRenderCamera();
  494. if (cam.targetDisplay != HitTestContext.screenPoint.z)
  495. return null;
  496. HitTestContext.camera = cam;
  497. if (renderMode == RenderMode.WorldSpace)
  498. {
  499. Vector3 screenPoint = HitTestContext.camera.WorldToScreenPoint(this.cachedTransform.position); //only for query z value
  500. screenPoint.x = HitTestContext.screenPoint.x;
  501. screenPoint.y = HitTestContext.screenPoint.y;
  502. //获得本地z轴在世界坐标的方向
  503. HitTestContext.worldPoint = HitTestContext.camera.ScreenToWorldPoint(screenPoint);
  504. Ray ray = HitTestContext.camera.ScreenPointToRay(screenPoint);
  505. HitTestContext.direction = Vector3.zero - ray.direction;
  506. }
  507. else if (renderMode == RenderMode.ScreenSpaceCamera)
  508. {
  509. HitTestContext.worldPoint = HitTestContext.camera.ScreenToWorldPoint(HitTestContext.screenPoint);
  510. }
  511. }
  512. else
  513. {
  514. if (HitTestContext.camera.targetDisplay != HitTestContext.screenPoint.z && !(this is Stage))
  515. return null;
  516. }
  517. target = HitTest_Container();
  518. HitTestContext.camera = savedCamera;
  519. HitTestContext.worldPoint = savedWorldPoint;
  520. HitTestContext.direction = savedDirection;
  521. return target;
  522. }
  523. DisplayObject HitTest_Container()
  524. {
  525. Vector2 localPoint = WorldToLocal(HitTestContext.worldPoint, HitTestContext.direction);
  526. if (_vertexMatrix != null)
  527. HitTestContext.worldPoint = this.cachedTransform.TransformPoint(new Vector2(localPoint.x, -localPoint.y));
  528. if (hitArea != null)
  529. {
  530. if (!hitArea.HitTest(_contentRect, localPoint))
  531. return null;
  532. if (hitArea is MeshColliderHitTest)
  533. localPoint = ((MeshColliderHitTest)hitArea).lastHit;
  534. }
  535. else
  536. {
  537. if (_clipRect != null && !((Rect)_clipRect).Contains(localPoint))
  538. return null;
  539. }
  540. if (_mask != null)
  541. {
  542. DisplayObject tmp = _mask.InternalHitTestMask();
  543. if (!reversedMask && tmp == null || reversedMask && tmp != null)
  544. return null;
  545. }
  546. DisplayObject target = null;
  547. if (touchChildren)
  548. {
  549. int count = _children.Count;
  550. for (int i = count - 1; i >= 0; --i) // front to back!
  551. {
  552. DisplayObject child = _children[i];
  553. if ((child._flags & Flags.GameObjectDisposed) != 0)
  554. {
  555. child.DisplayDisposedWarning();
  556. continue;
  557. }
  558. if (child == _mask || (child._flags & Flags.TouchDisabled) != 0)
  559. continue;
  560. target = child.InternalHitTest();
  561. if (target != null)
  562. break;
  563. }
  564. }
  565. if (target == null && opaque && (hitArea != null || _contentRect.Contains(localPoint)))
  566. target = this;
  567. return target;
  568. }
  569. /// <summary>
  570. ///
  571. /// </summary>
  572. /// <param name="obj"></param>
  573. /// <returns></returns>
  574. public bool IsAncestorOf(DisplayObject obj)
  575. {
  576. if (obj == null)
  577. return false;
  578. Container p = obj.parent;
  579. while (p != null)
  580. {
  581. if (p == this)
  582. return true;
  583. p = p.parent;
  584. }
  585. return false;
  586. }
  587. /// <summary>
  588. ///
  589. /// </summary>
  590. public bool fairyBatching
  591. {
  592. get { return (_flags & Flags.FairyBatching) != 0; }
  593. set
  594. {
  595. bool oldValue = (_flags & Flags.FairyBatching) != 0;
  596. if (oldValue != value)
  597. {
  598. if (value)
  599. _flags |= Flags.FairyBatching;
  600. else
  601. _flags &= ~Flags.FairyBatching;
  602. UpdateBatchingFlags();
  603. }
  604. }
  605. }
  606. internal void UpdateBatchingFlags()
  607. {
  608. bool oldValue = (_flags & Flags.BatchingRoot) != 0;
  609. bool newValue = (_flags & Flags.FairyBatching) != 0 || _clipRect != null || _mask != null || _paintingMode > 0;
  610. if (newValue)
  611. _flags |= Flags.BatchingRoot;
  612. else
  613. _flags &= ~Flags.BatchingRoot;
  614. if (oldValue != newValue)
  615. {
  616. if (newValue)
  617. _flags |= Flags.BatchingRequested;
  618. else if (_descendants != null)
  619. _descendants.Clear();
  620. InvalidateBatchingState();
  621. }
  622. }
  623. /// <summary>
  624. ///
  625. /// </summary>
  626. /// <param name="childrenChanged"></param>
  627. public void InvalidateBatchingState(bool childrenChanged)
  628. {
  629. if (childrenChanged && (_flags & Flags.BatchingRoot) != 0)
  630. _flags |= Flags.BatchingRequested;
  631. else
  632. {
  633. Container p = this.parent;
  634. while (p != null)
  635. {
  636. if ((p._flags & Flags.BatchingRoot) != 0)
  637. {
  638. p._flags |= Flags.BatchingRequested;
  639. break;
  640. }
  641. p = p.parent;
  642. }
  643. }
  644. }
  645. /// <summary>
  646. ///
  647. /// </summary>
  648. /// <param name="value"></param>
  649. public void SetChildrenLayer(int value)
  650. {
  651. int cnt = _children.Count;
  652. for (int i = 0; i < cnt; i++)
  653. {
  654. DisplayObject child = _children[i];
  655. child._SetLayerDirect(value);
  656. if ((child is Container) && child._paintingMode == 0)
  657. ((Container)child).SetChildrenLayer(value);
  658. }
  659. }
  660. override public void Update(UpdateContext context)
  661. {
  662. if ((_flags & Flags.UserGameObject) != 0 && !gameObject.activeInHierarchy)
  663. return;
  664. base.Update(context);
  665. if (_paintingMode != 0)
  666. {
  667. if ((_flags & Flags.CacheAsBitmap) != 0 && _paintingInfo.flag == 2)
  668. {
  669. if (onUpdate != null)
  670. onUpdate();
  671. return;
  672. }
  673. context.EnterPaintingMode();
  674. }
  675. if (_mask != null)
  676. {
  677. context.EnterClipping(this.id, reversedMask);
  678. if (_mask.graphics != null)
  679. _mask.graphics._PreUpdateMask(context, _mask.id);
  680. }
  681. else if (_clipRect != null)
  682. context.EnterClipping(this.id, this.TransformRect((Rect)_clipRect, null), clipSoftness);
  683. float savedAlpha = context.alpha;
  684. context.alpha *= this.alpha;
  685. bool savedGrayed = context.grayed;
  686. context.grayed = context.grayed || this.grayed;
  687. if ((_flags & Flags.FairyBatching) != 0)
  688. context.batchingDepth++;
  689. if (context.batchingDepth > 0)
  690. {
  691. int cnt = _children.Count;
  692. for (int i = 0; i < cnt; i++)
  693. {
  694. DisplayObject child = _children[i];
  695. if ((child._flags & Flags.GameObjectDisposed) != 0)
  696. {
  697. child.DisplayDisposedWarning();
  698. continue;
  699. }
  700. if (child.visible)
  701. child.Update(context);
  702. }
  703. }
  704. else
  705. {
  706. if (_mask != null)
  707. _mask.renderingOrder = context.renderingOrder++;
  708. int cnt = _children.Count;
  709. for (int i = 0; i < cnt; i++)
  710. {
  711. DisplayObject child = _children[i];
  712. if ((child._flags & Flags.GameObjectDisposed) != 0)
  713. {
  714. child.DisplayDisposedWarning();
  715. continue;
  716. }
  717. if (child.visible)
  718. {
  719. if (!(child.graphics != null && child.graphics._maskFlag == 1)) //if not a mask
  720. child.renderingOrder = context.renderingOrder++;
  721. child.Update(context);
  722. }
  723. }
  724. if (_mask != null)
  725. {
  726. if (_mask.graphics != null)
  727. _mask.graphics._SetStencilEraserOrder(context.renderingOrder++);
  728. }
  729. }
  730. if ((_flags & Flags.FairyBatching) != 0)
  731. {
  732. if (context.batchingDepth == 1)
  733. SetRenderingOrder(context);
  734. context.batchingDepth--;
  735. }
  736. context.alpha = savedAlpha;
  737. context.grayed = savedGrayed;
  738. if (_clipRect != null || _mask != null)
  739. context.LeaveClipping();
  740. if (_paintingMode != 0)
  741. {
  742. context.LeavePaintingMode();
  743. UpdateContext.OnEnd += _paintingInfo.captureDelegate;
  744. }
  745. if (onUpdate != null)
  746. onUpdate();
  747. }
  748. private void SetRenderingOrder(UpdateContext context)
  749. {
  750. if ((_flags & Flags.BatchingRequested) != 0)
  751. DoFairyBatching();
  752. if (_mask != null)
  753. _mask.renderingOrder = context.renderingOrder++;
  754. int cnt = _descendants.Count;
  755. for (int i = 0; i < cnt; i++)
  756. {
  757. DisplayObject child = _descendants[i];
  758. if (!(child.graphics != null && child.graphics._maskFlag == 1))
  759. child.renderingOrder = context.renderingOrder++;
  760. if ((child._flags & Flags.BatchingRoot) != 0)
  761. ((Container)child).SetRenderingOrder(context);
  762. }
  763. if (_mask != null)
  764. {
  765. if (_mask.graphics != null)
  766. _mask.graphics._SetStencilEraserOrder(context.renderingOrder++);
  767. }
  768. }
  769. private void DoFairyBatching()
  770. {
  771. _flags &= ~Flags.BatchingRequested;
  772. if (_descendants == null)
  773. _descendants = new List<DisplayObject>();
  774. else
  775. _descendants.Clear();
  776. CollectChildren(this, false);
  777. int cnt = _descendants.Count;
  778. int i, j, k, m;
  779. object curMat, testMat, lastMat;
  780. DisplayObject current, test;
  781. float[] bound;
  782. for (i = 0; i < cnt; i++)
  783. {
  784. current = _descendants[i];
  785. bound = current._batchingBounds;
  786. curMat = current.material;
  787. if (curMat == null || (current._flags & Flags.SkipBatching) != 0)
  788. continue;
  789. k = -1;
  790. lastMat = null;
  791. m = i;
  792. for (j = i - 1; j >= 0; j--)
  793. {
  794. test = _descendants[j];
  795. if ((test._flags & Flags.SkipBatching) != 0)
  796. break;
  797. testMat = test.material;
  798. if (testMat != null)
  799. {
  800. if (lastMat != testMat)
  801. {
  802. lastMat = testMat;
  803. m = j + 1;
  804. }
  805. if (curMat == testMat)
  806. k = m;
  807. }
  808. if ((bound[0] > test._batchingBounds[0] ? bound[0] : test._batchingBounds[0])
  809. <= (bound[2] < test._batchingBounds[2] ? bound[2] : test._batchingBounds[2])
  810. && (bound[1] > test._batchingBounds[1] ? bound[1] : test._batchingBounds[1])
  811. <= (bound[3] < test._batchingBounds[3] ? bound[3] : test._batchingBounds[3]))
  812. {
  813. if (k == -1)
  814. k = m;
  815. break;
  816. }
  817. }
  818. if (k != -1 && i != k)
  819. {
  820. _descendants.RemoveAt(i);
  821. _descendants.Insert(k, current);
  822. }
  823. }
  824. //Debug.Log("DoFairyBatching " + cnt + "," + this.cachedTransform.GetInstanceID());
  825. }
  826. private void CollectChildren(Container initiator, bool outlineChanged)
  827. {
  828. int count = _children.Count;
  829. for (int i = 0; i < count; i++)
  830. {
  831. DisplayObject child = _children[i];
  832. if (!child.visible)
  833. continue;
  834. if (child._batchingBounds == null)
  835. child._batchingBounds = new float[4];
  836. if (child is Container)
  837. {
  838. Container container = (Container)child;
  839. if ((container._flags & Flags.BatchingRoot) != 0)
  840. {
  841. initiator._descendants.Add(container);
  842. if (outlineChanged || (container._flags & Flags.OutlineChanged) != 0)
  843. {
  844. Rect rect = container.GetBounds(initiator);
  845. container._batchingBounds[0] = rect.xMin;
  846. container._batchingBounds[1] = rect.yMin;
  847. container._batchingBounds[2] = rect.xMax;
  848. container._batchingBounds[3] = rect.yMax;
  849. }
  850. if ((container._flags & Flags.BatchingRequested) != 0)
  851. container.DoFairyBatching();
  852. }
  853. else
  854. container.CollectChildren(initiator, outlineChanged || (container._flags & Flags.OutlineChanged) != 0);
  855. }
  856. else if (child != initiator._mask)
  857. {
  858. if (outlineChanged || (child._flags & Flags.OutlineChanged) != 0)
  859. {
  860. Rect rect = child.GetBounds(initiator);
  861. child._batchingBounds[0] = rect.xMin;
  862. child._batchingBounds[1] = rect.yMin;
  863. child._batchingBounds[2] = rect.xMax;
  864. child._batchingBounds[3] = rect.yMax;
  865. }
  866. initiator._descendants.Add(child);
  867. }
  868. child._flags &= ~Flags.OutlineChanged;
  869. }
  870. }
  871. public override void Dispose()
  872. {
  873. if ((_flags & Flags.Disposed) != 0)
  874. return;
  875. base.Dispose(); //Destroy GameObject tree first, avoid destroying each seperately;
  876. int numChildren = _children.Count;
  877. for (int i = numChildren - 1; i >= 0; --i)
  878. {
  879. DisplayObject obj = _children[i];
  880. obj.InternalSetParent(null); //Avoid RemoveParent call
  881. obj.Dispose();
  882. }
  883. }
  884. /// <summary>
  885. /// If true, when the container is focused, tab navigation is lock inside it.
  886. /// </summary>
  887. public bool tabStopChildren
  888. {
  889. get { return (_flags & Flags.TabStopChildren) != 0; }
  890. set
  891. {
  892. if (value)
  893. _flags |= Flags.TabStopChildren;
  894. else
  895. _flags &= ~Flags.TabStopChildren;
  896. }
  897. }
  898. struct DescendantsEnumerator : IEnumerator<DisplayObject>
  899. {
  900. Container _root;
  901. Container _com;
  902. DisplayObject _current;
  903. int _index;
  904. bool _forward;
  905. public DescendantsEnumerator(Container root, bool backward)
  906. {
  907. _root = root;
  908. _com = _root;
  909. _current = null;
  910. _forward = !backward;
  911. if (_forward)
  912. _index = 0;
  913. else
  914. _index = _com._children.Count - 1;
  915. }
  916. public DisplayObject Current
  917. {
  918. get { return _current; }
  919. }
  920. object IEnumerator.Current
  921. {
  922. get { return _current; }
  923. }
  924. public bool MoveNext()
  925. {
  926. if (_forward)
  927. {
  928. if (_index >= _com._children.Count)
  929. {
  930. if (_com == _root)
  931. {
  932. _current = null;
  933. return false;
  934. }
  935. _current = _com;
  936. _com = _com.parent;
  937. _index = _com.GetChildIndex(_current) + 1;
  938. return true;
  939. }
  940. else
  941. {
  942. DisplayObject obj = _com._children[_index];
  943. if (obj is Container)
  944. {
  945. _com = (Container)obj;
  946. _index = 0;
  947. return MoveNext();
  948. }
  949. _index++;
  950. _current = obj;
  951. return true;
  952. }
  953. }
  954. else
  955. {
  956. if (_index < 0)
  957. {
  958. if (_com == _root)
  959. {
  960. _current = null;
  961. return false;
  962. }
  963. _current = _com;
  964. _com = _com.parent;
  965. _index = _com.GetChildIndex(_current) - 1;
  966. return true;
  967. }
  968. else
  969. {
  970. DisplayObject obj = _com._children[_index];
  971. if (obj is Container)
  972. {
  973. _com = (Container)obj;
  974. _index = _com._children.Count - 1;
  975. return MoveNext();
  976. }
  977. _index--;
  978. _current = obj;
  979. return true;
  980. }
  981. }
  982. }
  983. public void Reset()
  984. {
  985. _com = _root;
  986. _current = null;
  987. _index = 0;
  988. }
  989. public void Dispose()
  990. {
  991. }
  992. }
  993. }
  994. }