hx3d  1
2D/3D Simple Game Framework
scene_graph.cpp
1 /*
2  Entity Component System: Base Scene Graph.
3  Copyright (C) 2015 Denis BOURGE
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, FiAfth Floor, Boston, MA 02110-1301
18  USA
19 */
20 
21 #include "hx3d/ecs/scene_graph.hpp"
22 #include <stack>
23 
24 namespace hx3d {
25 namespace ecs {
26 
27 SceneGraph::SceneGraph():
28  _root(Make<Node>("/"))
29 {
30  _root->_parent = nullptr;
31  _entityEnabled = false;
32  _indices["/"] = _root;
33 }
34 
35 SceneGraph::~SceneGraph() {}
36 
37 void SceneGraph::setEntityMode(bool enabled) {
38  _entityEnabled = enabled;
39 }
40 
42  return _root;
43 }
44 
45 unsigned int SceneGraph::getNodeCount() {
46  return _root->getChildCount();
47 }
48 
49 void SceneGraph::addIndex(const Ptr<Node>& object) {
50  const std::string& path = object->getPath();
51  for (const auto& pair: _indices) {
52  if (pair.first == object->_name) {
53  Log.Error("SceneGraph: Index `%s` already exists !", path.c_str());
54  return;
55  }
56  }
57 
58  _indices[path] = object;
59 }
60 
62  Log.Info("-- Graph indices");
63  for (const auto& pair: _indices) {
64  Log.Info("\t%s: %s", pair.first.c_str(), pair.second->_name.c_str());
65  }
66 }
67 
69  std::stack<Ptr<Node>> stack;
70  stack.push(_root);
71 
72  while (!stack.empty()) {
73  const Ptr<Node>& node = stack.top();
74  stack.pop();
75 
76  node->draw(batch);
77 
78  for (const Ptr<Node>& child: node->_children) {
79  stack.push(child);
80  }
81  }
82 }
83 
84 void SceneGraph::update(const float delta) {
85  std::stack<Ptr<Node>> stack;
86  stack.push(_root);
87 
88  while (!stack.empty()) {
89  const Ptr<Node>& node = stack.top();
90  stack.pop();
91 
92  node->update(delta);
93 
94  for (const Ptr<Node>& child: node->_children) {
95  stack.push(child);
96  }
97  }
98 
99  if (_entityEnabled) {
100  _engine.update(delta);
101  }
102 }
103 
105 
106 void SceneGraph::remove(const std::string path) {
107 
108  if (_indices.find(path) == _indices.end()) {
109  Log.Error("SceneGraph: Index `%s` does not exists.", path.c_str());
110  return;
111  }
112 
113  if (path == "/") {
114  Log.Error("SceneGraph: Root object can not be removed.");
115  return;
116  }
117 
118  internalRemove(_indices[path]);
119 }
120 
122  std::string path = node->getPath();
123  const Ptr<Node>& parent = node->_parent;
124 
125  for (const Ptr<Node>& child: node->_children) {
126  remove(child->getPath());
127  }
128 
129  for (unsigned int i = 0; i < parent->_children.size(); ++i) {
130  if (parent->_children[i] == node) {
131  parent->_children.erase(parent->_children.begin() + i);
132  }
133  }
134 
135  if (_entityEnabled) {
136  _engine.removeEntity(node);
137  }
138 
139  _indices.erase(path);
140 }
141 
142 Ptr<Node> SceneGraph::pathExists(const std::string path) {
143  if (path.size() == 0 || path[0] != '/') {
144  Log.Error("SceneGraph: ill-formed path: `%s`. Must start with `/`", path.c_str());
145  return nullptr;
146  }
147 
148  std::vector<std::string> folders = split(path, '/');
149  folders.erase(folders.begin());
150 
151  Ptr<Node>& node = _root;
152  while (folders.size() > 0) {
153  const std::string folder = folders[0];
154 
155  if (!node->childNameExists(folder)) {
156  return nullptr;
157  }
158 
159  node = node->template getChild<Node>(folder);
160  folders.erase(folders.begin());
161  }
162 
163  return node;
164 }
165 
166 } /* ecs */
167 } /* hx3d */
void showIndices()
Show the graph indices.
Definition: scene_graph.cpp:61
void setEntityMode(bool enabled)
Activate/Deactivate the entity management mode.
Definition: scene_graph.cpp:37
hx3d framework namespace
Definition: audio.hpp:26
void remove(const std::string path)
Remove a game object from a path.
void addIndex(const Ptr< Node > &object)
Add an index to the graph.
Definition: scene_graph.cpp:49
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Split a string using a delimiter and a container.
Definition: string.cpp:70
void internalRemove(const Ptr< Node > &node)
Remove a node.
Ptr< Node > pathExists(const std::string path)
Test if the path exists and returns the node.
void Error(const std::string fmt,...)
Write an error message.
Definition: log.cpp:72
Ptr< Node > getRoot()
Get the root.
Definition: scene_graph.cpp:41
static hx3d::LogImpl Log
Current log implementation.
Definition: log.hpp:91
void draw(graphics::BaseBatch &batch)
Draw the nodes.
Definition: scene_graph.cpp:68
unsigned int getNodeCount()
Get the number of nodes.
Definition: scene_graph.cpp:45
Draw meshes and texts on screen.
Definition: base_batch.hpp:41
Ptr< T > Make(Args &&...args)
Quick-typing make shared.
Definition: ptr.hpp:52
void update(const float delta)
Update the nodes.
Definition: scene_graph.cpp:84
std::shared_ptr< T > Ptr
Quick-typing shared ptr.
Definition: ptr.hpp:34
void Info(const std::string fmt,...)
Write an info message.
Definition: log.cpp:58