|
|
@@ -7,14 +7,141 @@ namespace BehaviorTree
|
|
|
{
|
|
|
class BehaviorTreeLayout
|
|
|
{
|
|
|
+ private static double xGap = 20;
|
|
|
+ private static double yGap = 10;
|
|
|
private TreeNodeViewModel root = null;
|
|
|
+
|
|
|
public BehaviorTreeLayout(TreeNodeViewModel root)
|
|
|
{
|
|
|
this.root = root;
|
|
|
}
|
|
|
|
|
|
+ public static double XGap
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return BehaviorTreeLayout.xGap;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ BehaviorTreeLayout.xGap = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static double YGap
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return BehaviorTreeLayout.yGap;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ BehaviorTreeLayout.yGap = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void CountPrelim(TreeNodeViewModel treeNode)
|
|
|
+ {
|
|
|
+
|
|
|
+ if (treeNode.Index == 0)
|
|
|
+ {
|
|
|
+ treeNode.Prelim = treeNode.Index * (treeNode.Width + BehaviorTreeLayout.XGap);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ double childrenCenter = 0;
|
|
|
+ if (treeNode.Children.Count > 0)
|
|
|
+ {
|
|
|
+ int maxIndex = treeNode.Children.Count - 1;
|
|
|
+ childrenCenter = (treeNode.Children[0].Prelim + treeNode.Children[maxIndex].Prelim) / 2;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ childrenCenter = 0;
|
|
|
+ }
|
|
|
+ treeNode.Prelim = childrenCenter;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void CountModify(TreeNodeViewModel treeNode, double prelim)
|
|
|
+ {
|
|
|
+ double childrenCenter = 0;
|
|
|
+ if (treeNode.Children.Count > 0)
|
|
|
+ {
|
|
|
+ int maxIndex = treeNode.Children.Count - 1;
|
|
|
+ childrenCenter = (treeNode.Children[0].Prelim + treeNode.Children[maxIndex].Prelim) / 2;
|
|
|
+ }
|
|
|
+ treeNode.Modify = prelim - childrenCenter;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void CountPrelimAndModify(TreeNodeViewModel treeNode)
|
|
|
+ {
|
|
|
+ CountPrelim(treeNode);
|
|
|
+ CountModify(treeNode, treeNode.Prelim);
|
|
|
+
|
|
|
+ foreach (var node in treeNode.Children)
|
|
|
+ {
|
|
|
+ CountPrelimAndModify(node);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void AjustTwoSubTreeGap(TreeNodeViewModel left, TreeNodeViewModel right)
|
|
|
+ {
|
|
|
+ if (left.IsLeaf || right.IsLeaf)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ double offset = 0;
|
|
|
+ TreeNodeViewModel tLeft = left;
|
|
|
+ TreeNodeViewModel tRight = right;
|
|
|
+ double leftTreeModify = 0;
|
|
|
+ double rightTreeModify = 0;
|
|
|
+ for (int i = 0; ; ++i)
|
|
|
+ {
|
|
|
+ if (tLeft.IsLeaf || tRight.IsLeaf)
|
|
|
+ {
|
|
|
+ right.Modify += offset;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ leftTreeModify += tLeft.Modify;
|
|
|
+ rightTreeModify += tRight.Modify;
|
|
|
+
|
|
|
+ tLeft = tLeft.RightMostChild;
|
|
|
+ tRight = tRight.LeftMostChild;
|
|
|
+
|
|
|
+ double tGap = (tRight.Prelim + rightTreeModify) - (tLeft.Prelim + leftTreeModify);
|
|
|
+ if (tGap - BehaviorTreeLayout.XGap > offset)
|
|
|
+ {
|
|
|
+ offset = tGap - BehaviorTreeLayout.XGap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void AjustTreeGap(TreeNodeViewModel treeNode)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < treeNode.Children.Count - 1; ++i)
|
|
|
+ {
|
|
|
+ TreeNodeViewModel left = treeNode.Children[i];
|
|
|
+ TreeNodeViewModel right = treeNode.Children[i + 1];
|
|
|
+ AjustTwoSubTreeGap(left, right);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ApplyXY(TreeNodeViewModel treeNode)
|
|
|
+ {
|
|
|
+ treeNode.X = treeNode.Prelim;
|
|
|
+ double realModify = treeNode.Prelim - treeNode.Modify;
|
|
|
+ foreach (var node in treeNode.Children)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void ExcuteLayout()
|
|
|
{
|
|
|
+ CountPrelimAndModify(root);
|
|
|
+ AjustTreeGap(root);
|
|
|
+ ApplyXY(root);
|
|
|
}
|
|
|
}
|
|
|
}
|