/* * Copyright 2014 MovingBlocks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.terasology.logic.behavior.asset; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.abego.treelayout.TreeForTreeLayout; import org.abego.treelayout.TreeLayout; import org.abego.treelayout.util.DefaultConfiguration; import org.abego.treelayout.util.FixedNodeExtentProvider; import org.terasology.assets.AssetData; import org.terasology.logic.behavior.BehaviorNodeComponent; import org.terasology.logic.behavior.BehaviorNodeFactory; import org.terasology.logic.behavior.nui.RenderableNode; import org.terasology.logic.behavior.tree.Node; import java.awt.geom.Rectangle2D; import java.util.Collections; import java.util.List; import java.util.Map; /** */ public class BehaviorTreeData implements AssetData { private Map<Node, RenderableNode> renderableNodes = Maps.newHashMap(); private Node root; private RenderableNode renderableRoot; public void setRoot(Node root) { this.root = root; } public void setRenderableRoot(RenderableNode renderableRoot) { this.renderableRoot = renderableRoot; } public RenderableNode createNode(Node node, BehaviorNodeFactory factory) { BehaviorNodeComponent nodeComponent = factory.getNodeComponent(node); RenderableNode self = new RenderableNode(nodeComponent); self.setNode(node); renderableNodes.put(node, self); return self; } public void createRenderable(BehaviorNodeFactory factory) { renderableRoot = createRenderable(root, factory); } public RenderableNode createRenderable(Node node, BehaviorNodeFactory factory) { return node.visit(null, new Node.Visitor<RenderableNode>() { @Override public RenderableNode visit(RenderableNode parent, Node n) { RenderableNode self = createNode(n, factory); if (parent != null) { parent.withoutModel().insertChild(-1, self); } return self; } }); } public void layout(RenderableNode start) { LayoutTree layoutTree; if (start == null) { layoutTree = new LayoutTree(renderableRoot); } else { layoutTree = new LayoutTree(start); } TreeLayout<RenderableNode> layout = new TreeLayout<>(layoutTree, new FixedNodeExtentProvider<>(10, 5), new DefaultConfiguration<>(4, 2)); Map<RenderableNode, Rectangle2D.Double> bounds = layout.getNodeBounds(); for (Map.Entry<RenderableNode, Rectangle2D.Double> entry : bounds.entrySet()) { RenderableNode node = entry.getKey(); Rectangle2D.Double rect = entry.getValue(); node.setPosition((float) rect.getX(), (float) rect.getY()); } } public boolean hasRenderable() { return renderableRoot != null; } public Node getRoot() { return root; } public List<RenderableNode> getRenderableNodes() { final List<RenderableNode> result = Lists.newArrayList(); root.visit(null, (Node.Visitor<RenderableNode>) (item, node) -> { result.add(renderableNodes.get(node)); return null; }); return result; } public RenderableNode getRenderableNode(Node node) { return renderableNodes.get(node); } private static final class LayoutTree implements TreeForTreeLayout<RenderableNode> { private RenderableNode root; private LayoutTree(RenderableNode root) { this.root = root; } @Override public RenderableNode getRoot() { return root; } @Override public boolean isLeaf(RenderableNode uiWidgets) { return uiWidgets.getChildrenCount() == 0; } @Override public boolean isChildOfParent(RenderableNode node, RenderableNode parentNode) { return parentNode.children().contains(node); } @Override public Iterable<RenderableNode> getChildren(RenderableNode parentNode) { return parentNode.children(); } @Override public Iterable<RenderableNode> getChildrenReverse(RenderableNode parentNode) { List<RenderableNode> list = Lists.newArrayList(parentNode.children()); Collections.reverse(list); return list; } @Override public RenderableNode getFirstChild(RenderableNode parentNode) { return parentNode.getChild(0); } @Override public RenderableNode getLastChild(RenderableNode parentNode) { return parentNode.getChild(Math.max(0, parentNode.getChildrenCount() - 1)); } } }