Fix writeScene change in order to write the given node and its descendants, not only the list of children to the scene file.

Add support for loading a scene file as childs of a given node. This will ignore the scene attributes and load all nodes of the scene, storing them as children of a given parent node. The rest will stay as before, including the default behavior to load scene attributes and all nodes directly into the scene manager.
Test cases added for both methods loadScene and saveScene. In order to find a node in the example scene from tutorial 15 I have added a name and ID to one of the scene elements.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3532 dfc29bdd-3216-0410-991c-e03cc46cb475
master
hybrid 2011-01-03 17:54:10 +00:00
parent 080a2ebab3
commit f1cc2dca01
14 changed files with 203 additions and 26 deletions

View File

@ -1468,8 +1468,10 @@ namespace scene
implement the ISceneUserDataSerializer interface and provide it
as parameter here. Otherwise, simply specify 0 as this
parameter.
\param node Node which is taken as the root node of the scene. Pass 0 to add the scene
directly to the scene manager (which is also the default).
\return True if successful. */
virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0) = 0;
virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) = 0;
//! Loads a scene. Note that the current scene is not cleared before.
/** The scene is usually load from an .irr file, an xml based format. .irr files can
@ -1481,8 +1483,10 @@ namespace scene
implement the ISceneUserDataSerializer interface and provide it
as parameter here. Otherwise, simply specify 0 as this
parameter.
\param node Node which is taken as the root node of the scene. Pass 0 to add the scene
directly to the scene manager (which is also the default).
\return True if successful. */
virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0) = 0;
virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) = 0;
//! Get a mesh writer implementation if available
/** Note: You need to drop() the pointer after use again, see IReferenceCounted::drop()

Binary file not shown.

View File

@ -2080,7 +2080,7 @@ bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* us
//! Loads a scene. Note that the current scene is not cleared before.
//! \param filename: Name of the file .
bool CSceneManager::loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer)
bool CSceneManager::loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node)
{
bool ret = false;
io::IReadFile* read = FileSystem->createAndOpenFile(filename);
@ -2090,7 +2090,7 @@ bool CSceneManager::loadScene(const io::path& filename, ISceneUserDataSerializer
}
else
{
ret = loadScene(read, userDataSerializer);
ret = loadScene(read, userDataSerializer, node);
read->drop();
}
@ -2100,7 +2100,7 @@ bool CSceneManager::loadScene(const io::path& filename, ISceneUserDataSerializer
//! Loads a scene. Note that the current scene is not cleared before.
bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer)
bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node)
{
if (!file)
{
@ -2126,7 +2126,7 @@ bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* use
while(reader->read())
{
readSceneNode(reader, 0, userDataSerializer);
readSceneNode(reader, node, userDataSerializer);
}
// restore old collada parameters
@ -2148,8 +2148,16 @@ void CSceneManager::readSceneNode(io::IXMLReader* reader, ISceneNode* parent, IS
scene::ISceneNode* node = 0;
if (!parent && IRR_XML_FORMAT_SCENE==reader->getNodeName())
node = this; // root
bool readAttributes=true;
if (IRR_XML_FORMAT_SCENE==reader->getNodeName())
{
// node==parent on start, which can be scene manager or distinct parent node
if (!parent)
node = this; // root
else
node = parent;
readAttributes = (node==this);
}
else if (parent && IRR_XML_FORMAT_NODE==reader->getNodeName())
{
// find node type and create it
@ -2159,7 +2167,10 @@ void CSceneManager::readSceneNode(io::IXMLReader* reader, ISceneNode* parent, IS
node = SceneNodeFactoryList[i]->addSceneNode(attrName.c_str(), parent);
if (!node)
{
os::Printer::log("Could not create scene node of unknown type", attrName.c_str());
node=addEmptySceneNode(parent);
}
}
// read attributes
@ -2177,7 +2188,7 @@ void CSceneManager::readSceneNode(io::IXMLReader* reader, ISceneNode* parent, IS
}
break;
case io::EXN_ELEMENT:
if (core::stringw(L"attributes")==reader->getNodeName())
if ((core::stringw(L"attributes")==reader->getNodeName()) && readAttributes)
{
// read attributes
io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver);
@ -2189,21 +2200,26 @@ void CSceneManager::readSceneNode(io::IXMLReader* reader, ISceneNode* parent, IS
attr->drop();
}
else
if (core::stringw(L"materials")==reader->getNodeName())
if ((core::stringw(L"materials")==reader->getNodeName()) && readAttributes)
readMaterials(reader, node);
else
if (core::stringw(L"animators")==reader->getNodeName())
if ((core::stringw(L"animators")==reader->getNodeName()) && readAttributes)
readAnimators(reader, node);
else
if (core::stringw(L"userData")==reader->getNodeName())
if ((core::stringw(L"userData")==reader->getNodeName()) && readAttributes)
readUserData(reader, node, userDataSerializer);
else
if ((IRR_XML_FORMAT_NODE==reader->getNodeName()) ||
(IRR_XML_FORMAT_SCENE==reader->getNodeName()))
if (IRR_XML_FORMAT_NODE==reader->getNodeName())
{
readSceneNode(reader, node, userDataSerializer);
}
else
if (IRR_XML_FORMAT_SCENE==reader->getNodeName())
{
// pass on parent value
readSceneNode(reader, parent, userDataSerializer);
}
else
{
os::Printer::log("Found unknown element in irrlicht scene file",
core::stringc(reader->getNodeName()).c_str());
@ -2452,11 +2468,18 @@ void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISc
if (init)
node=tmpNode;
// write children
ISceneNodeList::ConstIterator it = node->getChildren().begin();
for (; it != node->getChildren().end(); ++it)
writeSceneNode(writer, (*it), userDataSerializer, currentPath);
// write children once root node is written
// if parent is not scene manager, we need to write out node first
if (init && (node != this))
{
writeSceneNode(writer, node, userDataSerializer, currentPath);
}
else
{
ISceneNodeList::ConstIterator it = node->getChildren().begin();
for (; it != node->getChildren().end(); ++it)
writeSceneNode(writer, (*it), userDataSerializer, currentPath);
}
attr->drop();

View File

@ -464,10 +464,10 @@ namespace scene
//! Loads a scene. Note that the current scene is not cleared before.
//! \param filename: Name of the file .
virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0);
virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0);
//! Loads a scene. Note that the current scene is not cleared before.
virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0);
virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0);
//! Writes attributes of the scene node.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;

123
tests/ioScene.cpp Normal file
View File

@ -0,0 +1,123 @@
// Copyright (C) 2008-2009 Colin MacDonald
// No rights reserved: this software is in the public domain.
#include "testUtils.h"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
// Tests save scene.
static bool saveScene(void)
{
IrrlichtDevice *device = createDevice( EDT_NULL, dimension2d<u32>(160, 120), 32);
assert(device);
if (!device)
return false;
IVideoDriver* driver = device->getVideoDriver();
ISceneManager * smgr = device->getSceneManager();
ISkinnedMesh* mesh = (ISkinnedMesh*)smgr->getMesh("../media/ninja.b3d");
if (!mesh)
return false;
IAnimatedMeshSceneNode* node1 = smgr->addAnimatedMeshSceneNode(mesh);
if (node1)
{
node1->setPosition(vector3df(-3, -3, 10));
node1->setMaterialFlag(EMF_LIGHTING, false);
node1->setAnimationSpeed(0.f);
node1->setCurrentFrame(10.f);
node1->setDebugDataVisible(irr::scene::EDS_BBOX_BUFFERS);
}
ISkinnedMesh* mesh2 = (ISkinnedMesh*)smgr->getMesh(device->getFileSystem()->getAbsolutePath("../media/dwarf.x"));
if (!mesh2)
return false;
IAnimatedMeshSceneNode* node2 = smgr->addAnimatedMeshSceneNode(mesh2);
if (node2)
{
node2->setPosition(vector3df(33, -93, 120));
node2->setMaterialFlag(EMF_LIGHTING, false);
node2->setAnimationSpeed(10.f);
node2->setCurrentFrame(2.f);
}
IAnimatedMeshSceneNode* node3 = smgr->addAnimatedMeshSceneNode(mesh2, node2);
if (node3)
{
node3->setPosition(vector3df(-88, -300, 150));
node3->setMaterialFlag(EMF_LIGHTING, false);
node3->setAnimationSpeed(0.f);
node3->setCurrentFrame(12.f);
}
smgr->addCameraSceneNode();
smgr->saveScene("results/scene.irr");
bool result = binaryCompareFiles("results/scene.irr", "media/scene.irr");
smgr->saveScene("results/scene2.irr", 0, node3);
result &= binaryCompareFiles("results/scene2.irr", "media/scene2.irr");
device->closeDevice();
device->run();
device->drop();
return result;
}
static bool loadScene(void)
{
IrrlichtDevice *device = createDevice(video::EDT_BURNINGSVIDEO,
core::dimension2du(160,120), 32);
if (!device)
return false;
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
// load scene from example, with correct relative path
device->getFileSystem()->changeWorkingDirectoryTo("results");
smgr->loadScene("../../media/example.irr");
smgr->addCameraSceneNode(0, core::vector3df(0,0,-50));
device->getFileSystem()->changeWorkingDirectoryTo("..");
bool result = false;
device->run();
if (driver->beginScene(true, true, video::SColor(0, 80, 80, 80)))
{
smgr->drawAll();
driver->endScene();
result = takeScreenshotAndCompareAgainstReference(driver, "-loadScene.png", 98.91f);
}
ISceneNode* node = smgr->getSceneNodeFromId(128);
if (!node)
result=false;
else
{
result &= (node->getChildren().size()==0);
assert(result);
device->getSceneManager()->loadScene("media/scene2.irr", 0, node);
result &= (node->getChildren().size()!=0);
assert(result);
}
device->closeDevice();
device->run();
device->drop();
return result;
}
bool ioScene(void)
{
bool result = saveScene();
result &= loadScene();
return result;
}

View File

@ -72,7 +72,7 @@ int main(int argumentCount, char * arguments[])
TEST(vectorPositionDimension2d);
// file system checks (with null driver)
TEST(filesystem);
TEST(archiveReader);
TEST(archiveReader);
TEST(testXML);
TEST(serializeAttributes);
// null driver
@ -97,6 +97,7 @@ int main(int argumentCount, char * arguments[])
TEST(skinnedMesh);
TEST(testGeometryCreator);
TEST(writeImageToFile);
TEST(ioScene);
// all driver checks
TEST(videoDriver);
TEST(drawPixel);

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
tests/media/scene.irr Normal file

Binary file not shown.

BIN
tests/media/scene2.irr Normal file

Binary file not shown.

View File

@ -1,4 +1,4 @@
Tests finished. 60 tests of 60 passed.
Tests finished. 61 tests of 61 passed.
Compiled as DEBUG
Test suite pass at GMT Thu Dec 30 14:45:02 2010
Test suite pass at GMT Mon Jan 03 17:33:16 2011

View File

@ -46,8 +46,11 @@
<Unit filename="b3dAnimation.cpp" />
<Unit filename="burningsVideo.cpp" />
<Unit filename="collisionResponseAnimator.cpp" />
<Unit filename="color.cpp" />
<Unit filename="createImage.cpp" />
<Unit filename="cursorSetVisible.cpp" />
<Unit filename="disambiguateTextures.cpp" />
<Unit filename="draw2DImage.cpp" />
<Unit filename="drawPixel.cpp" />
<Unit filename="drawRectOutline.cpp" />
<Unit filename="enumerateImageManipulators.cpp" />
@ -56,9 +59,15 @@
<Unit filename="filesystem.cpp" />
<Unit filename="flyCircleAnimator.cpp" />
<Unit filename="guiDisabledMenu.cpp" />
<Unit filename="irrArray.cpp" />
<Unit filename="irrCoreEquals.cpp" />
<Unit filename="irrList.cpp" />
<Unit filename="irrMap.cpp" />
<Unit filename="irrString.cpp" />
<Unit filename="lightMaps.cpp" />
<Unit filename="lights.cpp" />
<Unit filename="line2dIntersectWith.cpp" />
<Unit filename="loadTextures.cpp" />
<Unit filename="main.cpp" />
<Unit filename="makeColorKeyTexture.cpp" />
<Unit filename="matrixOps.cpp" />
@ -66,27 +75,35 @@
<Unit filename="meshLoaders.cpp" />
<Unit filename="meshTransform.cpp" />
<Unit filename="mrt.cpp" />
<Unit filename="orthocam.cpp" />
<Unit filename="planeMatrix.cpp" />
<Unit filename="projectionMatrix.cpp" />
<Unit filename="removeCustomAnimator.cpp" />
<Unit filename="renderTargetTexture.cpp" />
<Unit filename="sceneCollisionManager.cpp" />
<Unit filename="sceneNodeAnimator.cpp" />
<Unit filename="serializeAttributes.cpp" />
<Unit filename="skinnedMesh.cpp" />
<Unit filename="softwareDevice.cpp" />
<Unit filename="stencilShadow.cpp" />
<Unit filename="terrainSceneNode.cpp" />
<Unit filename="testaabbox.cpp" />
<Unit filename="testDimension2d.cpp" />
<Unit filename="testGeometryCreator.cpp" />
<Unit filename="testQuaternion.cpp" />
<Unit filename="testS3DVertex.cpp" />
<Unit filename="testUtils.cpp" />
<Unit filename="testVector2d.cpp" />
<Unit filename="testVector3d.cpp" />
<Unit filename="testXML.cpp" />
<Unit filename="textureFeatures.cpp" />
<Unit filename="textureRenderStates.cpp" />
<Unit filename="timer.cpp" />
<Unit filename="transparentMaterials.cpp" />
<Unit filename="vectorPositionDimension2d.cpp" />
<Unit filename="videoDriver.cpp" />
<Unit filename="viewPort.cpp" />
<Unit filename="writeImageToFile.cpp" />
<Unit filename="zipReader.cpp" />
<Extensions>
<code_completion />
<debugger />

View File

@ -100,6 +100,7 @@
<ClCompile Include="filesystem.cpp" />
<ClCompile Include="flyCircleAnimator.cpp" />
<ClCompile Include="guiDisabledMenu.cpp" />
<ClCompile Include="ioScene.cpp" />
<ClCompile Include="irrArray.cpp" />
<ClCompile Include="irrCoreEquals.cpp" />
<ClCompile Include="irrList.cpp" />
@ -158,4 +159,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -248,6 +248,10 @@
RelativePath=".\guiDisabledMenu.cpp"
>
</File>
<File
RelativePath=".\ioScene.cpp"
>
</File>
<File
RelativePath=".\irrArray.cpp"
>

View File

@ -247,6 +247,10 @@
RelativePath=".\guiDisabledMenu.cpp"
>
</File>
<File
RelativePath=".\ioScene.cpp"
>
</File>
<File
RelativePath=".\irrArray.cpp"
>