1 // Copyright (C) 2010-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "CSceneLoaderIrr.h"
\r
6 #include "ISceneNodeAnimatorFactory.h"
\r
7 #include "ISceneUserDataSerializer.h"
\r
8 #include "ISceneManager.h"
\r
9 #include "IVideoDriver.h"
\r
10 #include "IFileSystem.h"
\r
19 CSceneLoaderIrr::CSceneLoaderIrr(ISceneManager *smgr, io::IFileSystem* fs)
\r
20 : SceneManager(smgr), FileSystem(fs),
\r
21 IRR_XML_FORMAT_SCENE(L"irr_scene"), IRR_XML_FORMAT_NODE(L"node"), IRR_XML_FORMAT_NODE_ATTR_TYPE(L"type"),
\r
22 IRR_XML_FORMAT_ATTRIBUTES(L"attributes"), IRR_XML_FORMAT_MATERIALS(L"materials"),
\r
23 IRR_XML_FORMAT_ANIMATORS(L"animators"), IRR_XML_FORMAT_USERDATA(L"userData")
\r
29 CSceneLoaderIrr::~CSceneLoaderIrr()
\r
34 //! Returns true if the class might be able to load this file.
\r
35 bool CSceneLoaderIrr::isALoadableFileExtension(const io::path& filename) const
\r
37 return core::hasFileExtension(filename, "irr");
\r
40 //! Returns true if the class might be able to load this file.
\r
41 bool CSceneLoaderIrr::isALoadableFileFormat(io::IReadFile *file) const
\r
43 // todo: check inside the file
\r
47 //! Loads the scene into the scene manager.
\r
48 bool CSceneLoaderIrr::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer,
\r
49 ISceneNode* rootNode)
\r
53 os::Printer::log("Unable to open scene file", ELL_ERROR);
\r
57 io::IXMLReader* reader = FileSystem->createXMLReader(file);
\r
60 os::Printer::log("Scene is not a valid XML file", file->getFileName().c_str(), ELL_ERROR);
\r
64 // TODO: COLLADA_CREATE_SCENE_INSTANCES can be removed when the COLLADA loader is a scene loader
\r
65 bool oldColladaSingleMesh = SceneManager->getParameters()->getAttributeAsBool(COLLADA_CREATE_SCENE_INSTANCES);
\r
66 SceneManager->getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, false);
\r
69 while (reader->read())
\r
71 readSceneNode(reader, rootNode, userDataSerializer);
\r
74 // restore old collada parameters
\r
75 SceneManager->getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, oldColladaSingleMesh);
\r
83 //! Reads the next node
\r
84 void CSceneLoaderIrr::readSceneNode(io::IXMLReader* reader, ISceneNode* parent,
\r
85 ISceneUserDataSerializer* userDataSerializer)
\r
90 scene::ISceneNode* node = 0;
\r
92 if (!parent && IRR_XML_FORMAT_SCENE==reader->getNodeName())
\r
93 node = SceneManager->getRootSceneNode();
\r
94 else if (parent && IRR_XML_FORMAT_NODE==reader->getNodeName())
\r
96 // find node type and create it
\r
97 core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str());
\r
99 node = SceneManager->addSceneNode(attrName.c_str(), parent);
\r
102 os::Printer::log("Could not create scene node of unknown type", attrName.c_str());
\r
108 while(reader->read())
\r
110 bool endreached = false;
\r
112 const wchar_t* name = reader->getNodeName();
\r
114 switch (reader->getNodeType())
\r
116 case io::EXN_ELEMENT_END:
\r
117 if ((IRR_XML_FORMAT_NODE == name) ||
\r
118 (IRR_XML_FORMAT_SCENE == name))
\r
123 case io::EXN_ELEMENT:
\r
124 if (IRR_XML_FORMAT_ATTRIBUTES == name)
\r
127 io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
\r
128 attr->read(reader, true);
\r
131 node->deserializeAttributes(attr);
\r
136 if (IRR_XML_FORMAT_MATERIALS == name)
\r
137 readMaterials(reader, node);
\r
139 if (IRR_XML_FORMAT_ANIMATORS == name)
\r
140 readAnimators(reader, node);
\r
142 if (IRR_XML_FORMAT_USERDATA == name)
\r
143 readUserData(reader, node, userDataSerializer);
\r
145 if ((IRR_XML_FORMAT_NODE == name) ||
\r
146 (IRR_XML_FORMAT_SCENE == name))
\r
148 readSceneNode(reader, node, userDataSerializer);
\r
152 os::Printer::log("Found unknown element in irrlicht scene file",
\r
153 core::stringc(name).c_str());
\r
163 if (node && userDataSerializer)
\r
164 userDataSerializer->OnCreateNode(node);
\r
167 //! reads materials of a node
\r
168 void CSceneLoaderIrr::readMaterials(io::IXMLReader* reader, ISceneNode* node)
\r
172 while(reader->read())
\r
174 const wchar_t* name = reader->getNodeName();
\r
176 switch(reader->getNodeType())
\r
178 case io::EXN_ELEMENT_END:
\r
179 if (IRR_XML_FORMAT_MATERIALS == name)
\r
182 case io::EXN_ELEMENT:
\r
183 if (IRR_XML_FORMAT_ATTRIBUTES == name)
\r
185 // read materials from attribute list
\r
186 io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
\r
187 attr->read(reader);
\r
189 if (node && node->getMaterialCount() > nr)
\r
191 SceneManager->getVideoDriver()->fillMaterialStructureFromAttributes(
\r
192 node->getMaterial(nr), attr);
\r
206 //! reads animators of a node
\r
207 void CSceneLoaderIrr::readAnimators(io::IXMLReader* reader, ISceneNode* node)
\r
209 while(reader->read())
\r
211 const wchar_t* name = reader->getNodeName();
\r
213 switch(reader->getNodeType())
\r
215 case io::EXN_ELEMENT_END:
\r
216 if (IRR_XML_FORMAT_ANIMATORS == name)
\r
219 case io::EXN_ELEMENT:
\r
220 if (IRR_XML_FORMAT_ATTRIBUTES == name)
\r
222 // read animator data from attribute list
\r
223 io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
\r
224 attr->read(reader);
\r
228 core::stringc typeName = attr->getAttributeAsString("Type");
\r
229 ISceneNodeAnimator* anim = SceneManager->createSceneNodeAnimator(typeName.c_str(), node);
\r
233 anim->deserializeAttributes(attr);
\r
248 //! reads user data of a node
\r
249 void CSceneLoaderIrr::readUserData(io::IXMLReader* reader, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer)
\r
251 while(reader->read())
\r
253 const wchar_t* name = reader->getNodeName();
\r
255 switch(reader->getNodeType())
\r
257 case io::EXN_ELEMENT_END:
\r
258 if (IRR_XML_FORMAT_USERDATA == name)
\r
261 case io::EXN_ELEMENT:
\r
262 if (IRR_XML_FORMAT_ATTRIBUTES == name)
\r
264 // read user data from attribute list
\r
265 io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
\r
266 attr->read(reader);
\r
268 if (node && userDataSerializer)
\r
270 userDataSerializer->OnReadUserData(node, attr);
\r