1 #include "Namespace.h"
2
3 #include "scenelib.h"
4 #include <list>
5
6 namespace {
Node_getNamespaced(scene::Node & node)7 inline Namespaced* Node_getNamespaced (scene::Node& node)
8 {
9 return dynamic_cast<Namespaced*> (&node);
10 }
11 }
12
attach(const NameCallback & setName,const NameCallbackCallback & attachObserver)13 void Namespace::attach (const NameCallback& setName, const NameCallbackCallback& attachObserver)
14 {
15 std::pair<Names::iterator, bool> result = m_names.insert(Names::value_type(setName, m_uniqueNames));
16 attachObserver(NameObserver::NameChangedCaller((*result.first).second));
17 }
18
detach(const NameCallback & setName,const NameCallbackCallback & detachObserver)19 void Namespace::detach (const NameCallback& setName, const NameCallbackCallback& detachObserver)
20 {
21 Names::iterator i = m_names.find(setName);
22 detachObserver(NameObserver::NameChangedCaller((*i).second));
23 m_names.erase(i);
24 }
25
makeUnique(const std::string & name,const NameCallback & setName) const26 void Namespace::makeUnique (const std::string& name, const NameCallback& setName) const
27 {
28 char buffer[1024];
29 name_write(buffer, m_uniqueNames.make_unique(name_read(name)));
30 setName(buffer);
31 }
32
mergeNames(const Namespace & other) const33 void Namespace::mergeNames (const Namespace& other) const
34 {
35 typedef std::list<NameCallback> SetNameCallbacks;
36 typedef std::map<std::string, SetNameCallbacks> NameGroups;
37 NameGroups groups;
38
39 UniqueNames uniqueNames(other.m_uniqueNames);
40
41 for (Names::const_iterator i = m_names.begin(); i != m_names.end(); ++i) {
42 groups[(*i).second.getName()].push_back((*i).first);
43 }
44
45 for (NameGroups::iterator i = groups.begin(); i != groups.end(); ++i) {
46 name_t uniqueName(uniqueNames.make_unique(name_read((*i).first)));
47 uniqueNames.insert(uniqueName);
48
49 char buffer[1024];
50 name_write(buffer, uniqueName);
51
52 SetNameCallbacks& setNameCallbacks = (*i).second;
53
54 for (SetNameCallbacks::const_iterator j = setNameCallbacks.begin(); j != setNameCallbacks.end(); ++j) {
55 (*j)(buffer);
56 }
57 }
58 }
59
gatherNamespaced(scene::Node & root)60 void Namespace::gatherNamespaced (scene::Node& root)
61 {
62 // Local helper class
63 class GatherNamespacedWalker: public scene::Traversable::Walker
64 {
65 NamespacedList& _list;
66 public:
67 GatherNamespacedWalker (NamespacedList& list) :
68 _list(list)
69 {
70 }
71
72 bool pre (scene::Node& node) const
73 {
74 Namespaced* namespaced = Node_getNamespaced(node);
75 if (namespaced != NULL) {
76 _list.push_back(namespaced);
77 }
78 return true;
79 }
80 };
81
82 Node_traverseSubgraph(root, GatherNamespacedWalker(_cloned));
83 }
84
mergeClonedNames()85 void Namespace::mergeClonedNames ()
86 {
87 // Temporarily allocate a new Namespace ("cloned")
88 Namespace _clonedNamespace;
89
90 // First, move them into the "cloned" Namespace
91 for (unsigned int i = 0; i < _cloned.size(); i++) {
92 _cloned[i]->setNamespace(_clonedNamespace);
93 }
94
95 // Merge them in
96 _clonedNamespace.mergeNames(*this);
97
98 // Now, move them (back) into this namespace (*this)
99 for (unsigned int i = 0; i < _cloned.size(); i++) {
100 _cloned[i]->setNamespace(*this);
101 }
102
103 // Remove the items from the list, we're done.
104 _cloned.clear();
105 }
106