SimpleAI
 All Classes Namespaces Files Functions Variables Typedefs Macros Groups Pages
XMLTreeLoader.h
Go to the documentation of this file.
1 
4 #pragma once
5 
7 #include <tinyxml2.h>
9 #include "tree/TreeNodeParser.h"
10 #include "tree/TreeNodeImpl.h"
11 
12 namespace ai {
13 
18 private:
19  TreeNodePtr loadSubTreeFromXML (const IAIFactory& aiFactory, tinyxml2::XMLElement* e) {
20  if (e == nullptr) {
21  return TreeNodePtr();
22  }
23 
24  const char *name = e->Attribute("name", nullptr);
25  if (name == nullptr) {
26  setError("No name given");
27  return TreeNodePtr();
28  }
29 
30  const char *type = e->Attribute("type", nullptr);
31  if (type == nullptr) {
32  setError("No type given for name %s", name);
33  return TreeNodePtr();
34  }
35 
36  TreeNodeParser nodeParser(aiFactory, type);
37  const TreeNodePtr& node = nodeParser.getTreeNode(name);
38  if (!node) {
39  setError("Could not create the tree node for name %s (type: %s)", name, type);
40  return TreeNodePtr();
41  }
42 
43  const char *condition = e->Attribute("condition", nullptr);
44  if (condition == nullptr) {
45  condition = "True";
46  }
47 
48  ConditionParser conditionParser(aiFactory, condition);
49  const ConditionPtr& conditionPtr = conditionParser.getCondition();
50  if (!conditionPtr.get()) {
51  setError("Could not create the condition for %s (name %s, type: %s)", condition, name, type);
52  return TreeNodePtr();
53  }
54 
55  node->setCondition(conditionPtr);
56  return node;
57  }
58 
59  TreeNodePtr loadTreeFromXML (const IAIFactory& aiFactory, tinyxml2::XMLElement* rootNode) {
60  TreeNodePtr root = loadSubTreeFromXML(aiFactory, rootNode);
61  if (!root.get()) {
62  return root;
63  }
64  for (tinyxml2::XMLNode* node = rootNode->FirstChild(); node; node = node->NextSibling()) {
65  tinyxml2::XMLElement* e = node->ToElement();
66  const TreeNodePtr& child = loadSubTreeFromXML(aiFactory, e);
67  if (child.get() == nullptr) {
68  continue;
69  }
70  root->addChild(child);
71  }
72  return root;
73  }
74 
75 public:
76  explicit XMLTreeLoader(const IAIFactory& aiFactory) :
77  ITreeLoader(aiFactory) {
78  }
79 
83  bool init(const std::string& xmlData, const char* rootNodeName = "trees", const char *treeNodeName = "tree") {
84  resetError();
85  tinyxml2::XMLDocument doc(false);
86  const int status = doc.Parse(xmlData.c_str());
87  tinyxml2::XMLElement* rootNode = doc.FirstChildElement(rootNodeName);
88  if (rootNode == nullptr) {
89  return false;
90  }
91  for (tinyxml2::XMLNode* node = rootNode->FirstChild(); node; node = node->NextSibling()) {
92  tinyxml2::XMLElement* e = node->ToElement();
93  if (e == nullptr) {
94  setError("unexpected node type");
95  continue;
96  }
97  if (e->Name() == nullptr) {
98  setError("expected node name but didn't find one");
99  continue;
100  }
101  if (::strcmp(treeNodeName, e->Name())) {
102  setError("unexpected node name - expected 'tree' - got %s", e->Name());
103  continue;
104  }
105  const char *name = e->Attribute("name");
106  if (name == nullptr) {
107  setError("node 'tree' does not have a 'name' attribute");
108  continue;
109  }
110  tinyxml2::XMLNode* rootXMLNode = e->FirstChild();
111  if (rootXMLNode == nullptr) {
112  setError("node 'tree' doesn't have a child (which should e.g. be a selector)");
113  continue;
114  }
115  const TreeNodePtr& root = loadTreeFromXML(_aiFactory, rootXMLNode->ToElement());
116  if (root.get() == nullptr) {
117  setError("could not create the root node");
118  continue;
119  }
120  addTree(name, root);
121  }
122  if (status != tinyxml2::XML_NO_ERROR) {
123  return false;
124  }
125  return getError().empty();
126  }
127 };
128 
129 }
Transforms the string representation of a TreeNode with all its parameters into a TreeNode instance...
Definition: TreeNodeParser.h:22
bool init(const std::string &xmlData, const char *rootNodeName="trees", const char *treeNodeName="tree")
this will initialize the loader once with all the defined behaviours from the given xml data...
Definition: XMLTreeLoader.h:83
void std::string getError() const
Gives access to the last error state of the ITreeLoader.
Definition: ITreeLoader.h:111
bool addTree(const std::string &name, const TreeNodePtr &root)
Register a new TreeNode as behaviour tree with the specified name.
Definition: ITreeLoader.h:77
Definition: IAIFactory.h:39
This class must be extended to load behaviour trees. The contract here is that the parsing only happe...
Definition: ITreeLoader.h:24
Transforms the string representation of a condition with all its sub conditions and parameters into a...
Definition: ConditionParser.h:23
Implementation of ITreeLoader that gets its data from a xml file.
Definition: XMLTreeLoader.h:17