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