BehaviorTreeLayout.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using ELog;
  2. namespace Modules.BehaviorTree
  3. {
  4. public static class BehaviorTreeLayout
  5. {
  6. private const double XGap = 20;
  7. private const double YGap = 10;
  8. private static double rootOrigX;
  9. private static double rootOrigY;
  10. private static double rootOffsetX;
  11. private static double rootOffsetY;
  12. private static TreeNodeViewModel LeftMostOffspring(TreeNodeViewModel treeNode, int currentLevel, int searchLevel)
  13. {
  14. if (currentLevel == searchLevel)
  15. {
  16. return treeNode;
  17. }
  18. for (int i = 0; i < treeNode.Children.Count; ++i)
  19. {
  20. var child = treeNode.Children[i];
  21. child.AncestorModify = treeNode.Modify + treeNode.AncestorModify;
  22. var offspring = LeftMostOffspring(child, currentLevel + 1, searchLevel);
  23. if (offspring == null)
  24. {
  25. continue;
  26. }
  27. return offspring;
  28. }
  29. return null;
  30. }
  31. private static TreeNodeViewModel RightMostOffspring(TreeNodeViewModel treeNode, int currentLevel, int searchLevel)
  32. {
  33. if (currentLevel == searchLevel)
  34. {
  35. return treeNode;
  36. }
  37. for (int i = treeNode.Children.Count - 1; i >= 0; --i)
  38. {
  39. var child = treeNode.Children[i];
  40. child.AncestorModify = treeNode.Modify + treeNode.AncestorModify;
  41. var offspring = RightMostOffspring(child, currentLevel + 1, searchLevel);
  42. if (offspring == null)
  43. {
  44. continue;
  45. }
  46. return offspring;
  47. }
  48. return null;
  49. }
  50. private static void AjustSubTreeGap(TreeNodeViewModel left, TreeNodeViewModel right)
  51. {
  52. double offset = 0;
  53. TreeNodeViewModel tLeft = left;
  54. TreeNodeViewModel tRight = right;
  55. left.AncestorModify = 0;
  56. right.AncestorModify = 0;
  57. for (int i = 0; tLeft != null && tRight != null; ++i)
  58. {
  59. double tGap = (tRight.Prelim + tRight.AncestorModify) - (tLeft.Prelim + tLeft.AncestorModify);
  60. if (XGap + TreeNodeViewModel.Width - tGap > offset)
  61. {
  62. offset = XGap + TreeNodeViewModel.Width - tGap;
  63. }
  64. tLeft = RightMostOffspring(left, 0, i + 1);
  65. tRight = LeftMostOffspring(right, 0, i + 1);
  66. }
  67. right.Modify += offset;
  68. right.Prelim += offset;
  69. }
  70. private static void AjustTreeGap(TreeNodeViewModel treeNode)
  71. {
  72. for (int i = 0; i < treeNode.Children.Count - 1; ++i)
  73. {
  74. for (int j = i + 1; j < treeNode.Children.Count; ++j)
  75. {
  76. var left = treeNode.Children[i];
  77. var right = treeNode.Children[j];
  78. AjustSubTreeGap(left, right);
  79. }
  80. }
  81. }
  82. private static void CalculatePrelimAndModify(TreeNodeViewModel treeNode)
  83. {
  84. foreach (TreeNodeViewModel node in treeNode.Children)
  85. {
  86. CalculatePrelimAndModify(node);
  87. }
  88. double prelim = 0;
  89. double modify = 0;
  90. if (treeNode.IsLeaf)
  91. {
  92. if (treeNode.LeftSibling == null)
  93. {
  94. // 如果没有左邻居,不需要设置modify
  95. prelim = 0;
  96. }
  97. else
  98. {
  99. prelim = treeNode.LeftSibling.Prelim + TreeNodeViewModel.Width + XGap;
  100. }
  101. }
  102. else
  103. {
  104. // 调整子树间的间距
  105. AjustTreeGap(treeNode);
  106. double childrenCenter = (treeNode.FirstChild.Prelim + treeNode.LastChild.Prelim) / 2;
  107. if (treeNode.LeftSibling == null)
  108. {
  109. // 如果没有左邻居,不需要设置modify
  110. prelim = childrenCenter;
  111. }
  112. else
  113. {
  114. prelim = treeNode.LeftSibling.Prelim + TreeNodeViewModel.Width + XGap;
  115. modify = prelim - childrenCenter;
  116. }
  117. }
  118. treeNode.Prelim = prelim;
  119. treeNode.Modify = modify;
  120. Log.Debug("Num: " + treeNode.Num + " Prelim: " + treeNode.Prelim + " Modify: " + treeNode.Modify);
  121. }
  122. private static void CalculateRelativeXAndY(TreeNodeViewModel treeNode, int level, double totalModify)
  123. {
  124. foreach (TreeNodeViewModel node in treeNode.Children)
  125. {
  126. CalculateRelativeXAndY(node, level + 1, treeNode.Modify + totalModify);
  127. }
  128. if (treeNode.IsLeaf)
  129. {
  130. treeNode.X = treeNode.Prelim + totalModify;
  131. }
  132. else
  133. {
  134. treeNode.X = (treeNode.FirstChild.X + treeNode.LastChild.X) / 2;
  135. }
  136. treeNode.Y = level * (TreeNodeViewModel.Height + YGap);
  137. }
  138. private static void FixXAndY(TreeNodeViewModel treeNode)
  139. {
  140. treeNode.X += rootOffsetX;
  141. treeNode.Y += rootOffsetY;
  142. foreach (var node in treeNode.Children)
  143. {
  144. FixXAndY(node);
  145. }
  146. }
  147. public static void ExcuteLayout(TreeNodeViewModel root)
  148. {
  149. if (root == null)
  150. {
  151. return;
  152. }
  153. rootOrigX = root.X;
  154. rootOrigY = root.Y;
  155. CalculatePrelimAndModify(root);
  156. CalculateRelativeXAndY(root, 0, 0);
  157. rootOffsetX = rootOrigX - root.X;
  158. rootOffsetY = rootOrigY - root.Y;
  159. FixXAndY(root);
  160. }
  161. }
  162. }