Drop XML implementation, related code and dependent features

This commit is contained in:
sfan5
2021-07-07 16:52:49 +02:00
parent ecb30e3d96
commit 729c214c00
60 changed files with 10 additions and 15350 deletions

View File

@ -5,13 +5,8 @@
#include "CAttributes.h"
#include "CAttributeImpl.h"
#include "ITexture.h"
#include "IXMLWriter.h"
#include "IVideoDriver.h"
#ifndef _IRR_COMPILE_WITH_XML_
#include "CXMLReader.h" // for noXML
#endif
namespace irr
{
namespace io
@ -1381,278 +1376,6 @@ void CAttributes::setAttribute(s32 index, void* userPointer)
}
//! Reads attributes from a xml file.
//! \param readCurrentElementOnly: If set to true, reading only works if current element has the name 'attributes'.
//! IF set to false, the first appearing list attributes are read.
bool CAttributes::read(io::IXMLReader* reader, bool readCurrentElementOnly,
const wchar_t* nonDefaultElementName)
{
#ifdef _IRR_COMPILE_WITH_XML_
if (!reader)
return false;
clear();
core::stringw elementName = L"attributes";
if (nonDefaultElementName)
elementName = nonDefaultElementName;
if (readCurrentElementOnly)
{
if (elementName != reader->getNodeName())
return false;
}
while(reader->read())
{
switch(reader->getNodeType())
{
case io::EXN_ELEMENT:
readAttributeFromXML(reader);
break;
case io::EXN_ELEMENT_END:
if (elementName == reader->getNodeName())
return true;
break;
default:
break;
}
}
return true;
#else
noXML();
return false;
#endif
}
void CAttributes::readAttributeFromXML(const io::IXMLReader* reader)
{
#ifdef _IRR_COMPILE_WITH_XML_
core::stringw element = reader->getNodeName();
core::stringc name = reader->getAttributeValue(L"name");
if (element == L"enum")
{
addEnum(name.c_str(), 0, 0);
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"binary")
{
addBinary(name.c_str(), 0, 0);
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"color")
{
addColor(name.c_str(), video::SColor());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"colorf")
{
addColorf(name.c_str(), video::SColorf());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"float")
{
addFloat(name.c_str(), 0);
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"int")
{
addInt(name.c_str(), 0);
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"bool")
{
addBool(name.c_str(), 0);
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"string")
{
addString(name.c_str(), L"");
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"texture")
{
addTexture(name.c_str(), 0);
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"vector3d")
{
addVector3d(name.c_str(), core::vector3df());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"vector2d")
{
addVector2d(name.c_str(), core::vector2df());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"position")
{
addPosition2d(name.c_str(), core::position2di());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"rect")
{
addRect(name.c_str(), core::rect<s32>());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"matrix")
{
addMatrix(name.c_str(), core::matrix4());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"quaternion")
{
addQuaternion(name.c_str(), core::quaternion());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"box3d")
{
addBox3d(name.c_str(), core::aabbox3df());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"plane")
{
addPlane3d(name.c_str(), core::plane3df());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"triangle")
{
addTriangle3d(name.c_str(), core::triangle3df());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"line2d")
{
addLine2d(name.c_str(), core::line2df());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"line3d")
{
addLine3d(name.c_str(), core::line3df());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
else
if (element == L"stringwarray")
{
core::array<core::stringw> tmpArray;
const s32 count = reader->getAttributeValueAsInt(L"count");
s32 n=0;
const core::stringw tmpName(L"value");
for (; n<count; ++n)
{
tmpArray.push_back(reader->getAttributeValue((tmpName+core::stringw(n)).c_str()));
}
addArray(name.c_str(),tmpArray);
}
else
if (element == L"userPointer")
{
// It's debatable if a pointer should be set or not, but it's more likely that adding it now would wreck user-applications.
// Also it probably doesn't makes sense setting this to a value when it comes from file.
}
else
if (element == L"dimension2d")
{
addDimension2d(name.c_str(), core::dimension2d<u32>());
Attributes.getLast()->setString(reader->getAttributeValue(L"value"));
}
#else
noXML();
#endif
}
//! Write these attributes into a xml file
bool CAttributes::write(io::IXMLWriter* writer, bool writeXMLHeader,
const wchar_t* nonDefaultElementName)
{
#ifdef _IRR_COMPILE_WITH_XML_
if (!writer)
return false;
if (writeXMLHeader)
writer->writeXMLHeader();
core::stringw elementName = L"attributes";
if (nonDefaultElementName)
elementName = nonDefaultElementName;
writer->writeElement(elementName.c_str(), false);
writer->writeLineBreak();
s32 i=0;
for (; i<(s32)Attributes.size(); ++i)
{
if ( Attributes[i]->getType() == EAT_STRINGWARRAY )
{
core::array<core::stringw> arraynames, arrayvalues;
core::array<core::stringw> arrayinput = Attributes[i]->getArray();
// build arrays
// name
arraynames.push_back(core::stringw(L"name"));
arrayvalues.push_back(core::stringw(Attributes[i]->Name.c_str()) );
// count
arraynames.push_back(core::stringw(L"count"));
arrayvalues.push_back(core::stringw((s32)arrayinput.size()));
// array...
u32 n=0;
const core::stringw tmpName(L"value");
for (; n < arrayinput.size(); ++n)
{
arraynames.push_back((tmpName+core::stringw(n)).c_str());
arrayvalues.push_back(arrayinput[n]);
}
// write them
writer->writeElement( Attributes[i]->getTypeString(), true, arraynames, arrayvalues);
}
else
{
writer->writeElement(
Attributes[i]->getTypeString(), true,
L"name", core::stringw(Attributes[i]->Name.c_str()).c_str(),
L"value", Attributes[i]->getStringW().c_str() );
}
writer->writeLineBreak();
}
writer->writeClosingTag(elementName.c_str());
writer->writeLineBreak();
return true;
#else
noXML();
return false;
#endif
}
} // end namespace io
} // end namespace irr

View File

@ -62,15 +62,6 @@ public:
//! Removes all attributes
virtual void clear() _IRR_OVERRIDE_;
//! Reads attributes from a xml file.
//! \param readCurrentElementOnly: If set to true, reading only works if current element has the name 'attributes'.
//! IF set to false, the first appearing list attributes are read.
virtual bool read(io::IXMLReader* reader, bool readCurrentElementOnly=false,
const wchar_t* nonDefaultElementName = 0) _IRR_OVERRIDE_;
//! Write these attributes into a xml file
virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false, const wchar_t* nonDefaultElementName=0) _IRR_OVERRIDE_;
/*
@ -722,8 +713,6 @@ public:
protected:
void readAttributeFromXML(const io::IXMLReader* reader);
core::array<IAttribute*> Attributes;
IAttribute* getAttributeP(const c8* attributeName) const;

File diff suppressed because it is too large Load Diff

View File

@ -1,410 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__
#define __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "IFileSystem.h"
#include "IVideoDriver.h"
#include "irrString.h"
#include "SMesh.h"
#include "SMeshBuffer.h"
#include "ISceneManager.h"
#include "irrMap.h"
#include "CAttributes.h"
namespace irr
{
namespace scene
{
#ifdef _DEBUG
//#define COLLADA_READER_DEBUG
#endif
class IColladaPrefab;
enum ECOLLADA_PARAM_NAME
{
ECPN_COLOR = 0,
ECPN_AMBIENT,
ECPN_DIFFUSE,
ECPN_SPECULAR,
ECPN_SHININESS,
ECPN_TRANSPARENCY,
ECPN_YFOV,
ECPN_ZNEAR,
ECPN_ZFAR,
ECPN_COUNT
};
enum ECOLLADA_PARAM_TYPE
{
ECPT_FLOAT = 0,
ECPT_FLOAT2,
ECPT_FLOAT3,
ECPT_FLOAT4,
ECPT_COUNT
};
//! Collada Parameter
struct SColladaParam
{
SColladaParam()
: Name(ECPN_COUNT), Type(ECPT_COUNT)
{
for (int i=0; i<4; ++i) Floats[i] = 0;
}
ECOLLADA_PARAM_NAME Name;
ECOLLADA_PARAM_TYPE Type;
f32 Floats[4];
};
enum ECOLLADA_INPUT_SEMANTIC
{
ECIS_POSITION = 0,
ECIS_VERTEX,
ECIS_NORMAL,
ECIS_TEXCOORD,
ECIS_UV,
ECIS_TANGENT,
ECIS_IMAGE,
ECIS_TEXTURE,
ECIS_COLOR,
ECIS_COUNT
};
//! Collada Input
struct SColladaInput
{
SColladaInput()
: Semantic(ECIS_COUNT), Data(0), Offset(0), Set(0), Stride(1)
{
}
ECOLLADA_INPUT_SEMANTIC Semantic;
core::stringc Source;
f32* Data;
u32 Offset;
u32 Set;
u32 Stride;
};
//! Collada images
struct SColladaImage
{
core::stringc Id;
core::stringc Source;
core::dimension2du Dimension;
bool SourceIsFilename;
};
//! Collada texture
struct SColladaTexture
{
video::ITexture* Texture;
core::stringc Id;
};
//! Collada material
struct SColladaMaterial
{
video::SMaterial Mat;
core::stringc Id;
core::stringc InstanceEffectId;
f32 Transparency;
inline bool operator< (const SColladaMaterial & other) const
{
return Id < other.Id;
}
};
//! Collada effect (materials, shaders, and programs)
struct SColladaEffect
{
core::stringc Id;
f32 Transparency;
core::array<core::stringc> Textures;
video::SMaterial Mat;
// TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct.
io::IAttributes * Parameters;
inline bool operator< (const SColladaEffect & other) const
{
return Id < other.Id;
}
};
struct SNumberArray // for storing float and int arrays
{
core::stringc Name;
core::array<f32> Data;
};
struct SAccessor
{
SAccessor()
: Count(0), Offset(0), Stride(1) {}
// I don't store the source of the accessor here because I assume
// it to use the array of the source this accessor is located in.
int Count;
int Offset;
int Stride;
core::array<SColladaParam> Parameters; // parameters defining the accessor
};
struct SSource
{
core::stringc Id;
SNumberArray Array;
core::array<SAccessor> Accessors;
};
class CScenePrefab;
//! Meshloader capable of loading COLLADA meshes and scene descriptions into Irrlicht.
class CColladaFileLoader : public IMeshLoader
{
public:
//! Constructor
CColladaFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
//! destructor
virtual ~CColladaFileLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".cob")
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_OVERRIDE_;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_OVERRIDE_;
private:
//! skips an (unknown) section in the collada document
void skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping);
//! reads the <COLLADA> section and its content
void readColladaSection(io::IXMLReaderUTF8* reader);
//! reads a <library> section and its content
void readLibrarySection(io::IXMLReaderUTF8* reader);
//! reads a <visual_scene> element and stores it as a prefab
void readVisualScene(io::IXMLReaderUTF8* reader);
//! reads a <scene> section and its content
void readSceneSection(io::IXMLReaderUTF8* reader);
//! reads a <asset> section and its content
void readAssetSection(io::IXMLReaderUTF8* reader);
//! reads a <node> section and its content
//! if a prefab pointer is passed the nodes are created as scene prefabs children of that prefab
void readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p=0);
//! reads a <lookat> element and its content and creates a matrix from it
core::matrix4 readLookAtNode(io::IXMLReaderUTF8* reader);
//! reads a <matrix> element and its content and creates a matrix from it
core::matrix4 readMatrixNode(io::IXMLReaderUTF8* reader);
//! reads a <perspective> element and its content and creates a matrix from it
core::matrix4 readPerspectiveNode(io::IXMLReaderUTF8* reader);
//! reads a <rotate> element and its content and creates a matrix from it
core::matrix4 readRotateNode(io::IXMLReaderUTF8* reader);
//! reads a <skew> element and its content and creates a matrix from it
core::matrix4 readSkewNode(io::IXMLReaderUTF8* reader);
//! reads a <boundingbox> element and its content and stores it in bbox
void readBboxNode(io::IXMLReaderUTF8* reader, core::aabbox3df& bbox);
//! reads a <scale> element and its content and creates a matrix from it
core::matrix4 readScaleNode(io::IXMLReaderUTF8* reader);
//! reads a <translate> element and its content and creates a matrix from it
core::matrix4 readTranslateNode(io::IXMLReaderUTF8* reader);
//! reads a <color> element
video::SColorf readColorNode(io::IXMLReaderUTF8* reader);
//! reads a <float> element
f32 readFloatNode(io::IXMLReaderUTF8* reader);
//! reads a <instance> node
void readInstanceNode(io::IXMLReaderUTF8* reader,
scene::ISceneNode* parent, scene::ISceneNode** outNode,
CScenePrefab* p=0, const core::stringc& type=core::stringc());
//! creates a scene node from Prefabs (with name given in 'url')
void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0,
CScenePrefab* p=0, const core::stringc& url="",
const core::stringc& type=core::stringc());
//! reads a <light> element and stores it as prefab
void readLightPrefab(io::IXMLReaderUTF8* reader);
//! reads a <camera> element and stores it as prefab
void readCameraPrefab(io::IXMLReaderUTF8* reader);
//! reads a <image> element and stores it in the image section
void readImage(io::IXMLReaderUTF8* reader);
//! reads a <texture> element and stores it in the texture section
void readTexture(io::IXMLReaderUTF8* reader);
//! reads a <material> element and stores it in the material section
void readMaterial(io::IXMLReaderUTF8* reader);
//! reads a <effect> element and stores it in the effects section
void readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect = 0);
//! reads a <geometry> element and stores it as mesh if possible
void readGeometry(io::IXMLReaderUTF8* reader);
//! parses a float from a char pointer and moves the pointer to
//! the end of the parsed float
inline f32 readFloat(const c8** p);
//! parses an int from a char pointer and moves the pointer to
//! the end of the parsed float
inline s32 readInt(const c8** p);
//! places pointer to next begin of a token
void findNextNoneWhiteSpace(const c8** p);
//! reads floats from inside of xml element until end of xml element
void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count);
//! reads ints from inside of xml element until end of xml element
void readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count);
//! clears all loaded data
void clearData();
//! parses all collada parameters inside an element and stores them in ColladaParameters
void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
//! returns a collada parameter or none if not found
SColladaParam* getColladaParameter(ECOLLADA_PARAM_NAME name);
//! parses all collada inputs inside an element and stores them in Inputs. Reads
//! until first tag which is not an input tag or the end of the parent is reached
void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
//! reads a collada input tag and adds it to the input parameter
void readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs);
//! returns a collada input or none if not found
SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input);
//! read Collada Id, uses id or name if id is missing
core::stringc readId(io::IXMLReaderUTF8* reader);
//! changes the XML URI into an internal id
void uriToId(core::stringc& str);
//! reads a polygons section and creates a mesh from it
void readPolygonSection(io::IXMLReaderUTF8* reader,
core::array<SSource>& sources, scene::SMesh* mesh,
const core::stringc& geometryId);
//! finds a material, possible instancing it
const SColladaMaterial * findMaterial(const core::stringc & materialName);
//! reads and bind materials as given by the symbol->target bind mapping
void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id);
//! create an Irrlicht texture from the SColladaImage
video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect);
//! read a parameter and value
void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters);
//! Flip z axis in matrix around to convert between right-handed and left-handed coordinate system.
//! Note that function is symmetric (no difference if called before or after a transpose).
core::matrix4 flipZAxis(const core::matrix4& m);
//! replace escape characters with the unescaped ones
void unescape(irr::core::stringc& uri);
scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
scene::IAnimatedMesh* DummyMesh;
core::stringc CurrentlyLoadingMesh;
scene::IAnimatedMesh* FirstLoadedMesh;
io::path FirstLoadedMeshName;
s32 LoadedMeshCount;
u32 Version;
bool FlipAxis;
core::array<IColladaPrefab*> Prefabs;
core::array<SColladaParam> ColladaParameters;
core::array<SColladaImage> Images;
core::array<SColladaTexture> Textures;
core::array<SColladaMaterial> Materials;
core::array<SColladaInput> Inputs;
core::array<SColladaEffect> Effects;
//! meshbuffer reference ("geomid/matname") -> index into MeshesToBind
core::map<core::stringc,u32> MaterialsToBind;
//! Array of buffers for each material binding
core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind;
bool CreateInstances;
struct EscapeCharacterURL
{
EscapeCharacterURL(irr::c8 c, const irr::c8* e)
: Character(c)
{
Escape = e;
}
irr::c8 Character; // unescaped (like ' ')
irr::core::stringc Escape; // escaped (like '%20')
};
irr::core::array<EscapeCharacterURL> EscapeCharsAnyURI;
};
//! following class is for holding and createing instances of library objects,
//! named prefabs in this loader.
class IColladaPrefab : public virtual IReferenceCounted
{
public:
//! creates an instance of this prefab
virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,
scene::ISceneManager* mgr) = 0;
//! returns id of this prefab
virtual const core::stringc& getId() = 0;
};
} // end namespace scene
} // end namespace irr
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,282 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
#define __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
#include "IColladaMeshWriter.h"
#include "S3DVertex.h"
#include "irrMap.h"
#include "IVideoDriver.h"
#include "IXMLWriter.h"
namespace irr
{
namespace io
{
class IFileSystem;
}
namespace scene
{
//! Callback interface for properties which can be used to influence collada writing
// (Implementer note: keep namespace labels here to make it easier for users copying this one)
class CColladaMeshWriterProperties : public virtual IColladaMeshWriterProperties
{
public:
//! Which lighting model should be used in the technique (FX) section when exporting effects (materials)
virtual irr::scene::E_COLLADA_TECHNIQUE_FX getTechniqueFx(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
//! Which texture index should be used when writing the texture of the given sampler color.
virtual irr::s32 getTextureIdx(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const _IRR_OVERRIDE_;
//! Return which color from Irrlicht should be used for the color requested by collada
virtual irr::scene::E_COLLADA_IRR_COLOR getColorMapping(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const _IRR_OVERRIDE_;
//! Return custom colors for certain color types requested by collada.
virtual irr::video::SColor getCustomColor(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const _IRR_OVERRIDE_;
//! Return the settings for transparence
virtual irr::scene::E_COLLADA_TRANSPARENT_FX getTransparentFx(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
//! Transparency value for that material.
virtual irr::f32 getTransparency(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
//! Reflectivity value for that material
virtual irr::f32 getReflectivity(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
//! Return index of refraction for that material
virtual irr::f32 getIndexOfRefraction(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
//! Should node be used in scene export? By default all visible nodes are exported.
virtual bool isExportable(const irr::scene::ISceneNode * node) const _IRR_OVERRIDE_;
//! Return the mesh for the given nod. If it has no mesh or shouldn't export it's mesh return 0.
virtual irr::scene::IMesh* getMesh(irr::scene::ISceneNode * node) _IRR_OVERRIDE_;
//! Return if the node has it's own material overwriting the mesh-materials
virtual bool useNodeMaterial(const scene::ISceneNode* node) const _IRR_OVERRIDE_;
};
class CColladaMeshWriterNames : public virtual IColladaMeshWriterNames
{
public:
CColladaMeshWriterNames(IColladaMeshWriter * writer);
virtual irr::core::stringc nameForMesh(const scene::IMesh* mesh, int instance) _IRR_OVERRIDE_;
virtual irr::core::stringc nameForNode(const scene::ISceneNode* node) _IRR_OVERRIDE_;
virtual irr::core::stringc nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) _IRR_OVERRIDE_;
protected:
irr::core::stringc nameForPtr(const void* ptr) const;
private:
IColladaMeshWriter * ColladaMeshWriter;
};
//! class to write meshes, implementing a COLLADA (.dae, .xml) writer
/** This writer implementation has been originally developed for irrEdit and then
merged out to the Irrlicht Engine */
class CColladaMeshWriter : public IColladaMeshWriter
{
public:
CColladaMeshWriter(ISceneManager * smgr, video::IVideoDriver* driver, io::IFileSystem* fs);
virtual ~CColladaMeshWriter();
//! Returns the type of the mesh writer
virtual EMESH_WRITER_TYPE getType() const _IRR_OVERRIDE_;
//! writes a scene starting with the given node
virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root, int writeRoot) _IRR_OVERRIDE_;
//! writes a mesh
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE) _IRR_OVERRIDE_;
// Restrict the characters of oldString a set of allowed characters in xs:NCName and add the prefix.
virtual irr::core::stringc toNCName(const irr::core::stringc& oldString, const irr::core::stringc& prefix=irr::core::stringc("_NC_")) const _IRR_OVERRIDE_;
//! After export you can find out which name had been used for writing the geometry for this node.
virtual const irr::core::stringc* findGeometryNameForNode(ISceneNode* node) _IRR_OVERRIDE_;
protected:
void reset();
bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const;
void writeUv(const irr::core::vector2df& vec);
void writeVector(const irr::core::vector3df& vec);
void writeColor(const irr::video::SColorf& colorf, bool writeAlpha=true);
inline irr::core::stringc toString(const irr::video::ECOLOR_FORMAT format) const;
inline irr::core::stringc toString(const irr::video::E_TEXTURE_CLAMP clamp) const;
inline irr::core::stringc toString(const irr::scene::E_COLLADA_TRANSPARENT_FX opaque) const;
inline irr::core::stringc toRef(const irr::core::stringc& source) const;
bool isCamera(const scene::ISceneNode* node) const;
irr::core::stringc nameForMesh(const scene::IMesh* mesh, int instance) const;
irr::core::stringc nameForNode(const scene::ISceneNode* node) const;
irr::core::stringc nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
irr::core::stringc nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const;
irr::core::stringc findCachedMaterialName(const irr::video::SMaterial& material) const;
irr::core::stringc minTexfilterToString(bool bilinear, bool trilinear) const;
irr::core::stringc magTexfilterToString(bool bilinear, bool trilinear) const;
irr::core::stringc pathToURI(const irr::io::path& path) const;
inline bool isXmlNameStartChar(c8 c) const;
inline bool isXmlNameChar(c8 c) const;
s32 getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs);
video::SColor getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType);
void writeAsset();
void makeMeshNames(irr::scene::ISceneNode * node);
void writeNodeMaterials(irr::scene::ISceneNode * node);
void writeNodeEffects(irr::scene::ISceneNode * node);
void writeNodeLights(irr::scene::ISceneNode * node);
void writeNodeCameras(irr::scene::ISceneNode * node);
void writeAllMeshGeometries();
void writeSceneNode(irr::scene::ISceneNode * node);
void writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringc> * materialNamesOut=0);
void writeMeshEffects(scene::IMesh* mesh);
void writeMaterialEffect(const irr::core::stringc& materialname, const video::SMaterial & material);
void writeMeshGeometry(const irr::core::stringc& meshname, scene::IMesh* mesh);
void writeMeshInstanceGeometry(const irr::core::stringc& meshname, scene::IMesh* mesh, scene::ISceneNode* node=0);
void writeMaterial(const irr::core::stringc& materialname);
void writeLightInstance(const irr::core::stringc& lightName);
void writeCameraInstance(const irr::core::stringc& cameraName);
void writeLibraryImages();
void writeColorFx(const video::SMaterial & material, const c8 * colorname, E_COLLADA_COLOR_SAMPLER cs, const c8* attr1Name=0, const c8* attr1Value=0);
void writeAmbientLightElement(const video::SColorf & col);
void writeColorElement(const video::SColor & col, bool writeAlpha=true);
void writeColorElement(const video::SColorf & col, bool writeAlpha=true);
void writeTextureSampler(s32 textureIdx);
void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
void writeNode(const c8 * nodeName, const c8 * content);
void writeFloatElement(irr::f32 value);
void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle);
void writeScaleElement(const irr::core::vector3df& scale);
void writeTranslateElement(const irr::core::vector3df& translate);
void writeLookAtElement(const irr::core::vector3df& eyePos, const irr::core::vector3df& targetPos, const irr::core::vector3df& upVector);
void writeMatrixElement(const irr::core::matrix4& matrix);
struct SComponentGlobalStartPos
{
SComponentGlobalStartPos() : PosStartIndex(0),
NormalStartIndex(0),
TCoord0StartIndex(0),
TCoord1StartIndex(0)
{ }
u32 PosStartIndex;
u32 NormalStartIndex;
u32 TCoord0StartIndex;
u32 TCoord1StartIndex;
};
io::IFileSystem* FileSystem;
video::IVideoDriver* VideoDriver;
io::IXMLWriterUTF8* Writer;
core::array<video::ITexture*> LibraryImages;
io::path Directory;
// Helper struct for creating geometry copies for the ECGI_PER_MESH_AND_MATERIAL settings.
struct SGeometryMeshMaterials
{
bool equals(const core::array<irr::core::stringc>& names) const
{
if ( names.size() != MaterialNames.size() )
return false;
for ( irr::u32 i=0; i<MaterialNames.size(); ++i )
if ( names[i] != MaterialNames[i] )
return false;
return true;
}
irr::core::stringc GeometryName; // replacing the usual ColladaMesh::Name
core::array<irr::core::stringc> MaterialNames; // Material names exported for this instance
core::array<const ISceneNode*> MaterialOwners; // Nodes using this specific mesh-material combination
};
// Check per mesh-ptr if stuff has been written for this mesh already
struct SColladaMesh
{
SColladaMesh() : MaterialsWritten(false), EffectsWritten(false)
{
}
SGeometryMeshMaterials * findGeometryMeshMaterials(const irr::core::array<irr::core::stringc> materialNames)
{
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
{
if ( GeometryMeshMaterials[i].equals(materialNames) )
return &(GeometryMeshMaterials[i]);
}
return NULL;
}
const irr::core::stringc& findGeometryNameForNode(const ISceneNode* node) const
{
if ( GeometryMeshMaterials.size() < 2 )
return Name;
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
{
if ( GeometryMeshMaterials[i].MaterialOwners.linear_search(node) >= 0 )
return GeometryMeshMaterials[i].GeometryName;
}
return Name; // (shouldn't get here usually)
}
irr::core::stringc Name;
bool MaterialsWritten; // just an optimization doing that here in addition to the MaterialsWritten map
bool EffectsWritten; // just an optimization doing that here in addition to the EffectsWritten map
core::array<SGeometryMeshMaterials> GeometryMeshMaterials;
};
typedef core::map<IMesh*, SColladaMesh>::Node MeshNode;
core::map<IMesh*, SColladaMesh> Meshes;
// structure for the lights library
struct SColladaLight
{
SColladaLight() {}
irr::core::stringc Name;
};
typedef core::map<ISceneNode*, SColladaLight>::Node LightNode;
core::map<ISceneNode*, SColladaLight> LightNodes;
// structure for the camera library
typedef core::map<ISceneNode*, irr::core::stringc>::Node CameraNode;
core::map<ISceneNode*, irr::core::stringc> CameraNodes;
// Check per name if stuff has been written already
// TODO: second parameter not needed, we just don't have a core::set class yet in Irrlicht
core::map<irr::core::stringc, bool> MaterialsWritten;
core::map<irr::core::stringc, bool> EffectsWritten;
// Cache material names
struct MaterialName
{
MaterialName(const irr::video::SMaterial & material, const irr::core::stringc& name)
: Material(material), Name(name)
{}
irr::video::SMaterial Material;
irr::core::stringc Name;
};
irr::core::array< MaterialName > MaterialNameCache;
irr::core::stringc WriteBuffer; // use for writing short strings to avoid regular memory allocations
struct EscapeCharacterURL
{
EscapeCharacterURL(irr::c8 c, const irr::c8* e)
: Character(c)
{
Escape = e;
}
irr::c8 Character; // unescaped (like ' ')
irr::core::stringc Escape; // escaped (like '%20')
};
irr::core::array<EscapeCharacterURL> EscapeCharsAnyURI;
};
} // end namespace
} // end namespace
#endif

View File

@ -14,8 +14,6 @@
#include "CTarReader.h"
#include "CWADReader.h"
#include "CFileList.h"
#include "CXMLReader.h"
#include "CXMLWriter.h"
#include "stdio.h"
#include "os.h"
#include "CAttributes.h"
@ -981,133 +979,6 @@ bool CFileSystem::existFile(const io::path& filename) const
}
//! Creates a XML Reader from a file.
IXMLReader* CFileSystem::createXMLReader(const io::path& filename)
{
#ifdef _IRR_COMPILE_WITH_XML_
IReadFile* file = createAndOpenFile(filename);
if (!file)
return 0;
IXMLReader* reader = createXMLReader(file);
file->drop();
return reader;
#else
noXML();
return 0;
#endif
}
//! Creates a XML Reader from a file.
IXMLReader* CFileSystem::createXMLReader(IReadFile* file)
{
#ifdef _IRR_COMPILE_WITH_XML_
if (!file)
return 0;
return createIXMLReader(file);
#else
noXML();
return 0;
#endif
}
//! Creates a XML Reader from a file.
IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(const io::path& filename)
{
#ifdef _IRR_COMPILE_WITH_XML_
IReadFile* file = createAndOpenFile(filename);
if (!file)
return 0;
IXMLReaderUTF8* reader = createIXMLReaderUTF8(file);
file->drop();
return reader;
#else
noXML();
return 0;
#endif
}
//! Creates a XML Reader from a file.
IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(IReadFile* file)
{
#ifdef _IRR_COMPILE_WITH_XML_
if (!file)
return 0;
return createIXMLReaderUTF8(file);
#else
noXML();
return 0;
#endif
}
//! Creates a XML Writer from a file.
IXMLWriter* CFileSystem::createXMLWriter(const io::path& filename)
{
#ifdef _IRR_COMPILE_WITH_XML_
IWriteFile* file = createAndWriteFile(filename);
IXMLWriter* writer = 0;
if (file)
{
writer = createXMLWriter(file);
file->drop();
}
return writer;
#else
noXML();
return 0;
#endif
}
//! Creates a XML Writer from a file.
IXMLWriter* CFileSystem::createXMLWriter(IWriteFile* file)
{
#ifdef _IRR_COMPILE_WITH_XML_
return createIXMLWriter(file);
#else
noXML();
return 0;
#endif
}
//! Creates a XML Writer from a file.
IXMLWriterUTF8* CFileSystem::createXMLWriterUTF8(const io::path& filename)
{
#ifdef _IRR_COMPILE_WITH_XML_
IWriteFile* file = createAndWriteFile(filename);
IXMLWriterUTF8* writer = 0;
if (file)
{
writer = createXMLWriterUTF8(file);
file->drop();
}
return writer;
#else
noXML();
return 0;
#endif
}
//! Creates a XML Writer from a file.
IXMLWriterUTF8* CFileSystem::createXMLWriterUTF8(IWriteFile* file)
{
#ifdef _IRR_COMPILE_WITH_XML_
return createIXMLWriterUTF8(file);
#else
noXML();
return 0;
#endif
}
//! creates a filesystem which is able to open files from the ordinary file system,
//! and out of zipfiles, which are able to be added to the filesystem.
IFileSystem* createFileSystem()

View File

@ -127,30 +127,6 @@ public:
//! determines if a file exists and would be able to be opened.
virtual bool existFile(const io::path& filename) const _IRR_OVERRIDE_;
//! Creates a XML Reader from a file.
virtual IXMLReader* createXMLReader(const io::path& filename) _IRR_OVERRIDE_;
//! Creates a XML Reader from a file.
virtual IXMLReader* createXMLReader(IReadFile* file) _IRR_OVERRIDE_;
//! Creates a XML Reader from a file.
virtual IXMLReaderUTF8* createXMLReaderUTF8(const io::path& filename) _IRR_OVERRIDE_;
//! Creates a XML Reader from a file.
virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file) _IRR_OVERRIDE_;
//! Creates a XML Writer from a file.
virtual IXMLWriter* createXMLWriter(const io::path& filename) _IRR_OVERRIDE_;
//! Creates a XML Writer from a file.
virtual IXMLWriter* createXMLWriter(IWriteFile* file) _IRR_OVERRIDE_;
//! Creates a XML Writer from a file which will write ASCII/UTF-8 characters (char*).
virtual IXMLWriterUTF8* createXMLWriterUTF8(const path& filename) _IRR_OVERRIDE_;
//! Creates a XML Writer from a file which will write ASCII/UTF-8 characters (char*).
virtual IXMLWriterUTF8* createXMLWriterUTF8(IWriteFile* file) _IRR_OVERRIDE_;
//! Creates a new empty collection of attributes, usable for serialization and more.
virtual IAttributes* createEmptyAttributes(video::IVideoDriver* driver) _IRR_OVERRIDE_;

View File

@ -39,7 +39,6 @@
#include "CDefaultGUIElementFactory.h"
#include "IWriteFile.h"
#include "IXMLWriter.h"
#include "BuiltInFont.h"
#include "os.h"
@ -49,10 +48,6 @@ namespace irr
namespace gui
{
const wchar_t IRR_XML_FORMAT_GUI_ENV[] = L"irr_gui";
const wchar_t IRR_XML_FORMAT_GUI_ELEMENT[] = L"element";
const wchar_t IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE[] = L"type";
const io::path CGUIEnvironment::DefaultFontName = "#DefaultFont";
//! constructor
@ -788,22 +783,7 @@ bool CGUIEnvironment::saveGUI(const io::path& filename, IGUIElement* start)
//! Saves the current gui into a file.
bool CGUIEnvironment::saveGUI(io::IWriteFile* file, IGUIElement* start)
{
if (!file)
{
return false;
}
io::IXMLWriter* writer = FileSystem->createXMLWriter(file);
if (!writer)
{
return false;
}
writer->writeXMLHeader();
writeGUIElement(writer, start ? start : this);
writer->drop();
return true;
return false;
}
@ -828,170 +808,7 @@ bool CGUIEnvironment::loadGUI(const io::path& filename, IGUIElement* parent)
//! Loads the gui. Note that the current gui is not cleared before.
bool CGUIEnvironment::loadGUI(io::IReadFile* file, IGUIElement* parent)
{
if (!file)
{
os::Printer::log("Unable to open GUI file", ELL_ERROR);
return false;
}
io::IXMLReader* reader = FileSystem->createXMLReader(file);
if (!reader)
{
os::Printer::log("GUI is not a valid XML file", file->getFileName(), ELL_ERROR);
return false;
}
// read file
while(reader->read())
{
readGUIElement(reader, parent);
}
// finish up
reader->drop();
return true;
}
//! reads an element
void CGUIEnvironment::readGUIElement(io::IXMLReader* reader, IGUIElement* node)
{
if (!reader)
return;
io::EXML_NODE nodeType = reader->getNodeType();
if (nodeType == io::EXN_NONE || nodeType == io::EXN_UNKNOWN || nodeType == io::EXN_ELEMENT_END)
return;
IGUIElement* deferedNode = 0;
if (!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName()))
{
// GuiEnvironment always must be this as it would serialize into a wrong element otherwise.
// So we use the given node next time
if ( node && node != this )
deferedNode = node;
node = this; // root
}
else if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()))
{
// find node type and create it
const core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE);
node = addGUIElement(attrName.c_str(), node);
if (!node)
os::Printer::log("Could not create GUI element of unknown type", attrName.c_str());
}
// read attributes
while(reader->read())
{
bool endreached = false;
switch (reader->getNodeType())
{
case io::EXN_ELEMENT_END:
if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) ||
!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName()))
{
endreached = true;
}
break;
case io::EXN_ELEMENT:
if (!wcscmp(L"attributes", reader->getNodeName()))
{
// read attributes
io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver);
attr->read(reader, true);
if (node)
node->deserializeAttributes(attr);
attr->drop();
}
else
if (!wcscmp(IRR_XML_FORMAT_GUI_ELEMENT, reader->getNodeName()) ||
!wcscmp(IRR_XML_FORMAT_GUI_ENV, reader->getNodeName()))
{
if ( deferedNode )
readGUIElement(reader, deferedNode);
else
readGUIElement(reader, node);
}
else
{
os::Printer::log("Found unknown element in irrlicht GUI file",
core::stringc(reader->getNodeName()).c_str());
}
break;
default:
break;
}
if (endreached)
break;
}
}
//! writes an element
void CGUIEnvironment::writeGUIElement(io::IXMLWriter* writer, IGUIElement* node)
{
if (!writer || !node )
return;
const wchar_t* name = 0;
// write properties
io::IAttributes* attr = FileSystem->createEmptyAttributes();
node->serializeAttributes(attr);
// all gui elements must have at least one attribute
// if they have nothing then we ignore them.
if (attr->getAttributeCount() != 0)
{
if (node == this)
{
name = IRR_XML_FORMAT_GUI_ENV;
writer->writeElement(name, false);
}
else
{
name = IRR_XML_FORMAT_GUI_ELEMENT;
writer->writeElement(name, false, IRR_XML_FORMAT_GUI_ELEMENT_ATTR_TYPE,
core::stringw(node->getTypeName()).c_str());
}
writer->writeLineBreak();
attr->write(writer);
}
// write children
core::list<IGUIElement*>::ConstIterator it = node->getChildren().begin();
for (; it != node->getChildren().end(); ++it)
{
if (!(*it)->isSubElement())
{
writer->writeLineBreak();
writeGUIElement(writer, (*it));
}
}
// write closing brace if required
if (attr->getAttributeCount() != 0)
{
writer->writeClosingTag(name);
writer->writeLineBreak();
}
attr->drop();
return false;
}
@ -1460,35 +1277,7 @@ IGUIFont* CGUIEnvironment::getFont(const io::path& filename)
}
IGUIFont* ifont=0;
io::IXMLReader *xml = FileSystem->createXMLReader(filename );
if (xml)
{
// this is an XML font, but we need to know what type
EGUI_FONT_TYPE t = EGFT_CUSTOM;
bool found=false;
while(!found && xml->read())
{
if (xml->getNodeType() == io::EXN_ELEMENT)
{
if (core::stringw(L"font") == xml->getNodeName())
{
if (core::stringw(L"vector") == xml->getAttributeValue(L"type"))
{
t = EGFT_VECTOR;
found=true;
}
else if (core::stringw(L"bitmap") == xml->getAttributeValue(L"type"))
{
t = EGFT_BITMAP;
found=true;
}
else found=true;
}
}
}
if (t==EGFT_BITMAP)
#if 0
{
CGUIFont* font = new CGUIFont(this, filename);
ifont = (IGUIFont*)font;
@ -1503,17 +1292,7 @@ IGUIFont* CGUIEnvironment::getFont(const io::path& filename)
ifont = 0;
}
}
else if (t==EGFT_VECTOR)
{
// todo: vector fonts
os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.NamedPath, ELL_ERROR);
//CGUIFontVector* font = new CGUIFontVector(Driver);
//ifont = (IGUIFont*)font;
//if (!font->load(xml))
}
xml->drop();
}
#endif
if (!ifont)

View File

@ -254,12 +254,6 @@ public:
//! Reads attributes of the environment.
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) _IRR_OVERRIDE_;
//! writes an element
virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* node) _IRR_OVERRIDE_;
//! reads an element
virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node) _IRR_OVERRIDE_;
//! Find the next element which would be selected when pressing the tab-key
virtual IGUIElement* getNextElement(bool reverse=false, bool group=false) _IRR_OVERRIDE_;

View File

@ -8,7 +8,6 @@
#include "os.h"
#include "coreutil.h"
#include "IGUIEnvironment.h"
#include "IXMLReader.h"
#include "IReadFile.h"
#include "IVideoDriver.h"
#include "IGUISpriteBank.h"
@ -63,6 +62,7 @@ CGUIFont::~CGUIFont()
}
#if 0
//! loads a font file from xml
bool CGUIFont::load(io::IXMLReader* xml, const io::path& directory)
{
@ -195,6 +195,7 @@ bool CGUIFont::load(io::IXMLReader* xml, const io::path& directory)
return true;
}
#endif
void CGUIFont::setMaxHeight()

View File

@ -11,7 +11,6 @@
#include "IGUIFontBitmap.h"
#include "irrString.h"
#include "irrMap.h"
#include "IXMLReader.h"
#include "IReadFile.h"
#include "irrArray.h"
@ -45,10 +44,6 @@ public:
//! loads a font from a texture file
bool load(io::IReadFile* file);
//! loads a font from an XML file
//\param directory Directory in which the bitmaps can be found
bool load(io::IXMLReader* xml, const io::path& directory);
//! draws an text and clips it to the specified rectangle if wanted
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
video::SColor color, bool hcenter=false,

View File

@ -1,556 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
#include "CIrrMeshFileLoader.h"
#include "os.h"
#include "IXMLReader.h"
#include "SAnimatedMesh.h"
#include "fast_atof.h"
#include "IReadFile.h"
#include "IAttributes.h"
#include "IMeshSceneNode.h"
#include "CDynamicMeshBuffer.h"
#include "SMeshBufferLightMap.h"
namespace irr
{
namespace scene
{
//! Constructor
CIrrMeshFileLoader::CIrrMeshFileLoader(scene::ISceneManager* smgr,
io::IFileSystem* fs)
: SceneManager(smgr), FileSystem(fs)
{
#ifdef _DEBUG
setDebugName("CIrrMeshFileLoader");
#endif
}
//! Returns true if the file maybe is able to be loaded by this class.
/** This decision should be based only on the file extension (e.g. ".cob") */
bool CIrrMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "xml", "irrmesh" );
}
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* CIrrMeshFileLoader::createMesh(io::IReadFile* file)
{
io::IXMLReader* reader = FileSystem->createXMLReader(file);
if (!reader)
return 0;
// read until mesh section, skip other parts
const core::stringc meshTagName = "mesh";
IAnimatedMesh* mesh = 0;
while(reader->read())
{
if (reader->getNodeType() == io::EXN_ELEMENT)
{
if (meshTagName == reader->getNodeName())
{
mesh = readMesh(reader);
break;
}
else
skipSection(reader, true); // unknown section
}
}
reader->drop();
return mesh;
}
//! reads a mesh sections and creates a mesh from it
IAnimatedMesh* CIrrMeshFileLoader::readMesh(io::IXMLReader* reader)
{
SAnimatedMesh* animatedmesh = new SAnimatedMesh();
SMesh* mesh = new SMesh();
animatedmesh->addMesh(mesh);
mesh->drop();
core::stringc bbSectionName = "boundingBox";
core::stringc bufferSectionName = "buffer";
core::stringc meshSectionName = "mesh";
if (!reader->isEmptyElement())
while(reader->read())
{
if (reader->getNodeType() == io::EXN_ELEMENT)
{
const wchar_t* nodeName = reader->getNodeName();
if (bbSectionName == nodeName)
{
// inside a bounding box, ignore it for now because
// we are calculating this anyway ourselves later.
}
else
if (bufferSectionName == nodeName)
{
// we've got a mesh buffer
IMeshBuffer* buffer = readMeshBuffer(reader);
if (buffer)
{
mesh->addMeshBuffer(buffer);
buffer->drop();
}
}
else
skipSection(reader, true); // unknown section
} // end if node type is element
else
if (reader->getNodeType() == io::EXN_ELEMENT_END)
{
if (meshSectionName == reader->getNodeName())
{
// end of mesh section reached, cancel out
break;
}
}
} // end while reader->read();
mesh->recalculateBoundingBox();
animatedmesh->recalculateBoundingBox();
return animatedmesh;
}
//! reads a mesh sections and creates a mesh buffer from it
IMeshBuffer* CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader)
{
CDynamicMeshBuffer* buffer = 0;
core::stringc verticesSectionName = "vertices";
core::stringc bbSectionName = "boundingBox";
core::stringc materialSectionName = "material";
core::stringc indicesSectionName = "indices";
core::stringc bufferSectionName = "buffer";
bool insideVertexSection = false;
bool insideIndexSection = false;
int vertexCount = 0;
int indexCount = 0;
video::SMaterial material;
if (!reader->isEmptyElement())
while(reader->read())
{
if (reader->getNodeType() == io::EXN_ELEMENT)
{
const wchar_t* nodeName = reader->getNodeName();
if (bbSectionName == nodeName)
{
// inside a bounding box, ignore it for now because
// we are calculating this anyway ourselves later.
}
else
if (materialSectionName == nodeName)
{
//we've got a material
material = video::SMaterial(); // reset
io::IAttributes* attributes = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
attributes->read(reader, true, L"material");
SceneManager->getVideoDriver()->fillMaterialStructureFromAttributes(material, attributes);
attributes->drop();
}
else
if (verticesSectionName == nodeName)
{
// vertices section
const core::stringc vertexTypeName1 = "standard";
const core::stringc vertexTypeName2 = "2tcoords";
const core::stringc vertexTypeName3 = "tangents";
const wchar_t* vertexType = reader->getAttributeValue(L"type");
vertexCount = reader->getAttributeValueAsInt(L"vertexCount");
insideVertexSection = true;
video::E_INDEX_TYPE itype = (vertexCount > 65536)?irr::video::EIT_32BIT:irr::video::EIT_16BIT;
if (vertexTypeName1 == vertexType)
{
buffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, itype);
}
else
if (vertexTypeName2 == vertexType)
{
buffer = new CDynamicMeshBuffer(irr::video::EVT_2TCOORDS, itype);
}
else
if (vertexTypeName3 == vertexType)
{
buffer = new CDynamicMeshBuffer(irr::video::EVT_TANGENTS, itype);
}
buffer->getVertexBuffer().reallocate(vertexCount);
buffer->Material = material;
}
else
if (indicesSectionName == nodeName)
{
// indices section
indexCount = reader->getAttributeValueAsInt(L"indexCount");
insideIndexSection = true;
}
} // end if node type is element
else
if (reader->getNodeType() == io::EXN_TEXT)
{
// read vertex data
if (insideVertexSection)
{
readMeshBuffer(reader, vertexCount, buffer);
insideVertexSection = false;
} // end reading vertex array
else
if (insideIndexSection)
{
readIndices(reader, indexCount, buffer->getIndexBuffer());
insideIndexSection = false;
}
} // end if node type is text
else
if (reader->getNodeType() == io::EXN_ELEMENT_END)
{
if (bufferSectionName == reader->getNodeName())
{
// end of buffer section reached, cancel out
break;
}
}
} // end while reader->read();
if (buffer)
buffer->recalculateBoundingBox();
return buffer;
}
//! read indices
void CIrrMeshFileLoader::readIndices(io::IXMLReader* reader, int indexCount, IIndexBuffer& indices)
{
indices.reallocate(indexCount);
core::stringc data = reader->getNodeData();
const c8* p = &data[0];
for (int i=0; i<indexCount && *p; ++i)
{
findNextNoneWhiteSpace(&p);
indices.push_back(readInt(&p));
}
}
void CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader, int vertexCount, CDynamicMeshBuffer* sbuffer)
{
core::stringc data = reader->getNodeData();
const c8* p = &data[0];
scene::IVertexBuffer& Vertices = sbuffer->getVertexBuffer();
video::E_VERTEX_TYPE vType = Vertices.getType();
if (sbuffer)
{
for (int i=0; i<vertexCount && *p; ++i)
{
switch(vType)
{
case video::EVT_STANDARD:
{
video::S3DVertex vtx;
// position
findNextNoneWhiteSpace(&p);
vtx.Pos.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Z = readFloat(&p);
// normal
findNextNoneWhiteSpace(&p);
vtx.Normal.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Z = readFloat(&p);
// color
u32 col;
findNextNoneWhiteSpace(&p);
sscanf(p, "%08x", &col);
vtx.Color.set(col);
skipCurrentNoneWhiteSpace(&p);
// tcoord1
findNextNoneWhiteSpace(&p);
vtx.TCoords.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.TCoords.Y = readFloat(&p);
Vertices.push_back(vtx);
}
break;
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords vtx;
// position
findNextNoneWhiteSpace(&p);
vtx.Pos.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Z = readFloat(&p);
// normal
findNextNoneWhiteSpace(&p);
vtx.Normal.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Z = readFloat(&p);
// color
u32 col;
findNextNoneWhiteSpace(&p);
sscanf(p, "%08x", &col);
vtx.Color.set(col);
skipCurrentNoneWhiteSpace(&p);
// tcoord1
findNextNoneWhiteSpace(&p);
vtx.TCoords.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.TCoords.Y = readFloat(&p);
// tcoord2
findNextNoneWhiteSpace(&p);
vtx.TCoords2.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.TCoords2.Y = readFloat(&p);
Vertices.push_back(vtx);
}
break;
case video::EVT_TANGENTS:
{
video::S3DVertexTangents vtx;
// position
findNextNoneWhiteSpace(&p);
vtx.Pos.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Z = readFloat(&p);
// normal
findNextNoneWhiteSpace(&p);
vtx.Normal.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Z = readFloat(&p);
// color
u32 col;
findNextNoneWhiteSpace(&p);
sscanf(p, "%08x", &col);
vtx.Color.set(col);
skipCurrentNoneWhiteSpace(&p);
// tcoord1
findNextNoneWhiteSpace(&p);
vtx.TCoords.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.TCoords.Y = readFloat(&p);
// tangent
findNextNoneWhiteSpace(&p);
vtx.Tangent.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Tangent.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Tangent.Z = readFloat(&p);
// binormal
findNextNoneWhiteSpace(&p);
vtx.Binormal.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Binormal.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Binormal.Z = readFloat(&p);
Vertices.push_back(vtx);
}
break;
};
}
}
}
//! skips an (unknown) section in the irrmesh document
void CIrrMeshFileLoader::skipSection(io::IXMLReader* reader, bool reportSkipping)
{
#ifdef _DEBUG
os::Printer::log("irrMesh skipping section", core::stringc(reader->getNodeName()).c_str());
#endif
// skip if this element is empty anyway.
if (reader->isEmptyElement())
return;
// read until we've reached the last element in this section
u32 tagCounter = 1;
while(tagCounter && reader->read())
{
if (reader->getNodeType() == io::EXN_ELEMENT &&
!reader->isEmptyElement())
{
#ifdef _DEBUG
if (reportSkipping)
os::Printer::log("irrMesh unknown element:", core::stringc(reader->getNodeName()).c_str());
#endif
++tagCounter;
}
else
if (reader->getNodeType() == io::EXN_ELEMENT_END)
--tagCounter;
}
}
//! parses a float from a char pointer and moves the pointer
//! to the end of the parsed float
inline f32 CIrrMeshFileLoader::readFloat(const c8** p)
{
f32 ftmp;
*p = core::fast_atof_move(*p, ftmp);
return ftmp;
}
//! parses an int from a char pointer and moves the pointer to
//! the end of the parsed float
inline s32 CIrrMeshFileLoader::readInt(const c8** p)
{
return (s32)readFloat(p);
}
//! places pointer to next begin of a token
void CIrrMeshFileLoader::skipCurrentNoneWhiteSpace(const c8** start)
{
const c8* p = *start;
while(*p && !(*p==' ' || *p=='\n' || *p=='\r' || *p=='\t'))
++p;
// TODO: skip comments <!-- -->
*start = p;
}
//! places pointer to next begin of a token
void CIrrMeshFileLoader::findNextNoneWhiteSpace(const c8** start)
{
const c8* p = *start;
while(*p && (*p==' ' || *p=='\n' || *p=='\r' || *p=='\t'))
++p;
// TODO: skip comments <!-- -->
*start = p;
}
//! reads floats from inside of xml element until end of xml element
void CIrrMeshFileLoader::readFloatsInsideElement(io::IXMLReader* reader, f32* floats, u32 count)
{
if (reader->isEmptyElement())
return;
while(reader->read())
{
// TODO: check for comments inside the element
// and ignore them.
if (reader->getNodeType() == io::EXN_TEXT)
{
// parse float data
core::stringc data = reader->getNodeData();
const c8* p = &data[0];
for (u32 i=0; i<count; ++i)
{
findNextNoneWhiteSpace(&p);
if (*p)
floats[i] = readFloat(&p);
else
floats[i] = 0.0f;
}
}
else
if (reader->getNodeType() == io::EXN_ELEMENT_END)
break; // end parsing text
}
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_IRR_MESH_LOADER_

View File

@ -1,90 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_IRR_MESH_FILE_LOADER_H_INCLUDED__
#define __C_IRR_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "IFileSystem.h"
#include "IVideoDriver.h"
#include "irrString.h"
#include "SMesh.h"
#include "SMeshBuffer.h"
#include "CDynamicMeshBuffer.h"
#include "ISceneManager.h"
namespace irr
{
namespace scene
{
//! Meshloader capable of loading .irrmesh meshes, the Irrlicht Engine mesh format for static meshes
class CIrrMeshFileLoader : public IMeshLoader
{
public:
//! Constructor
CIrrMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".cob")
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_OVERRIDE_;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file) _IRR_OVERRIDE_;
private:
//! reads a mesh sections and creates a mesh from it
IAnimatedMesh* readMesh(io::IXMLReader* reader);
//! reads a mesh sections and creates a mesh buffer from it
IMeshBuffer* readMeshBuffer(io::IXMLReader* reader);
//! skips an (unknown) section in the irrmesh file
void skipSection(io::IXMLReader* reader, bool reportSkipping);
//! reads a <material> element and stores it in the material section
void readMaterial(io::IXMLReader* reader);
//! parses a float from a char pointer and moves the pointer to
//! the end of the parsed float
inline f32 readFloat(const c8** p);
//! parses an int from a char pointer and moves the pointer to
//! the end of the parsed float
inline s32 readInt(const c8** p);
//! places pointer to next begin of a token
void findNextNoneWhiteSpace(const c8** p);
//! places pointer to next begin of a token
void skipCurrentNoneWhiteSpace(const c8** p);
//! reads floats from inside of xml element until end of xml element
void readFloatsInsideElement(io::IXMLReader* reader, f32* floats, u32 count);
//! read the mesh buffers
void readMeshBuffer(io::IXMLReader* reader, int vertexCount, CDynamicMeshBuffer* sbuffer);
//! read indices
void readIndices(io::IXMLReader* reader, int indexCount, IIndexBuffer& indices);
// member variables
scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,312 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
#include "CIrrMeshWriter.h"
#include "os.h"
#include "IWriteFile.h"
#include "IXMLWriter.h"
#include "IMesh.h"
#include "IAttributes.h"
namespace irr
{
namespace scene
{
CIrrMeshWriter::CIrrMeshWriter(video::IVideoDriver* driver,
io::IFileSystem* fs)
: FileSystem(fs), VideoDriver(driver), Writer(0)
{
#ifdef _DEBUG
setDebugName("CIrrMeshWriter");
#endif
if (VideoDriver)
VideoDriver->grab();
if (FileSystem)
FileSystem->grab();
}
CIrrMeshWriter::~CIrrMeshWriter()
{
if (VideoDriver)
VideoDriver->drop();
if (FileSystem)
FileSystem->drop();
}
//! Returns the type of the mesh writer
EMESH_WRITER_TYPE CIrrMeshWriter::getType() const
{
return EMWT_IRR_MESH;
}
//! writes a mesh
bool CIrrMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
{
if (!file)
return false;
Writer = FileSystem->createXMLWriter(file);
if (!Writer)
{
os::Printer::log("Could not write file", file->getFileName());
return false;
}
os::Printer::log("Writing mesh", file->getFileName());
// write IRR MESH header
Writer->writeXMLHeader();
Writer->writeElement(L"mesh", false,
L"xmlns", L"http://irrlicht.sourceforge.net/IRRMESH_09_2007",
L"version", L"1.0");
Writer->writeLineBreak();
// add some informational comment. Add a space after and before the comment
// tags so that some braindead xml parsers (AS anyone?) are able to parse this too.
core::stringw infoComment = L" This file contains a static mesh in the Irrlicht Engine format with ";
infoComment += core::stringw(mesh->getMeshBufferCount());
infoComment += L" materials.";
Writer->writeComment(infoComment.c_str());
Writer->writeLineBreak();
// write mesh bounding box
writeBoundingBox(mesh->getBoundingBox());
Writer->writeLineBreak();
// write mesh buffers
for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
if (buffer)
{
writeMeshBuffer(buffer);
Writer->writeLineBreak();
}
}
Writer->writeClosingTag(L"mesh");
Writer->drop();
return true;
}
void CIrrMeshWriter::writeBoundingBox(const core::aabbox3df& box)
{
Writer->writeElement(L"boundingBox", true,
L"minEdge", getVectorAsStringLine(box.MinEdge).c_str(),
L"maxEdge", getVectorAsStringLine(box.MaxEdge).c_str());
}
core::stringw CIrrMeshWriter::getVectorAsStringLine(const core::vector3df& v) const
{
core::stringw str;
str = core::stringw(v.X);
str += L" ";
str += core::stringw(v.Y);
str += L" ";
str += core::stringw(v.Z);
return str;
}
core::stringw CIrrMeshWriter::getVectorAsStringLine(const core::vector2df& v) const
{
core::stringw str;
str = core::stringw(v.X);
str += L" ";
str += core::stringw(v.Y);
return str;
}
void CIrrMeshWriter::writeMeshBuffer(const scene::IMeshBuffer* buffer)
{
Writer->writeElement(L"buffer", false);
Writer->writeLineBreak();
// write bounding box
writeBoundingBox(buffer->getBoundingBox());
Writer->writeLineBreak();
// write material
writeMaterial(buffer->getMaterial());
// write vertices
const core::stringw vertexTypeStr = video::sBuiltInVertexTypeNames[buffer->getVertexType()];
Writer->writeElement(L"vertices", false,
L"type", vertexTypeStr.c_str(),
L"vertexCount", core::stringw(buffer->getVertexCount()).c_str());
Writer->writeLineBreak();
u32 vertexCount = buffer->getVertexCount();
switch(buffer->getVertexType())
{
case video::EVT_STANDARD:
{
video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
core::stringw str = getVectorAsStringLine(vtx[j].Pos);
str += L" ";
str += getVectorAsStringLine(vtx[j].Normal);
char tmp[12];
sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue());
str += tmp;
str += getVectorAsStringLine(vtx[j].TCoords);
Writer->writeText(str.c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
core::stringw str = getVectorAsStringLine(vtx[j].Pos);
str += L" ";
str += getVectorAsStringLine(vtx[j].Normal);
char tmp[12];
sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue());
str += tmp;
str += getVectorAsStringLine(vtx[j].TCoords);
str += L" ";
str += getVectorAsStringLine(vtx[j].TCoords2);
Writer->writeText(str.c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_TANGENTS:
{
video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
core::stringw str = getVectorAsStringLine(vtx[j].Pos);
str += L" ";
str += getVectorAsStringLine(vtx[j].Normal);
char tmp[12];
sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue());
str += tmp;
str += getVectorAsStringLine(vtx[j].TCoords);
str += L" ";
str += getVectorAsStringLine(vtx[j].Tangent);
str += L" ";
str += getVectorAsStringLine(vtx[j].Binormal);
Writer->writeText(str.c_str());
Writer->writeLineBreak();
}
}
break;
}
Writer->writeClosingTag(L"vertices");
Writer->writeLineBreak();
// write indices
Writer->writeElement(L"indices", false,
L"indexCount", core::stringw(buffer->getIndexCount()).c_str());
Writer->writeLineBreak();
int indexCount = (int)buffer->getIndexCount();
video::E_INDEX_TYPE iType = buffer->getIndexType();
const u16* idx16 = buffer->getIndices();
const u32* idx32 = (u32*) buffer->getIndices();
const int maxIndicesPerLine = 25;
for (int i=0; i<indexCount; ++i)
{
if(iType == video::EIT_16BIT)
{
core::stringw str((int)idx16[i]);
Writer->writeText(str.c_str());
}
else
{
core::stringw str((int)idx32[i]);
Writer->writeText(str.c_str());
}
if (i % maxIndicesPerLine == maxIndicesPerLine-1)
Writer->writeLineBreak();
else
Writer->writeText(L" ");
}
if ((indexCount-1) % maxIndicesPerLine != maxIndicesPerLine-1)
Writer->writeLineBreak();
Writer->writeClosingTag(L"indices");
Writer->writeLineBreak();
// close buffer tag
Writer->writeClosingTag(L"buffer");
}
void CIrrMeshWriter::writeMaterial(const video::SMaterial& material)
{
// simply use irrlichts built-in attribute serialization capabilities here:
io::IAttributes* attributes =
VideoDriver->createAttributesFromMaterial(material);
if (attributes)
{
attributes->write(Writer, false, L"material");
attributes->drop();
}
}
} // end namespace
} // end namespace
#endif

View File

@ -1,61 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __IRR_IRR_MESH_WRITER_H_INCLUDED__
#define __IRR_IRR_MESH_WRITER_H_INCLUDED__
#include "IMeshWriter.h"
#include "S3DVertex.h"
#include "IVideoDriver.h"
#include "IFileSystem.h"
#include "IXMLWriter.h"
namespace irr
{
namespace scene
{
class IMeshBuffer;
//! class to write meshes, implementing a IrrMesh (.irrmesh, .xml) writer
/** This writer implementation has been originally developed for irrEdit and then
merged out to the Irrlicht Engine */
class CIrrMeshWriter : public IMeshWriter
{
public:
CIrrMeshWriter(video::IVideoDriver* driver, io::IFileSystem* fs);
virtual ~CIrrMeshWriter();
//! Returns the type of the mesh writer
virtual EMESH_WRITER_TYPE getType() const _IRR_OVERRIDE_;
//! writes a mesh
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE) _IRR_OVERRIDE_;
protected:
void writeBoundingBox(const core::aabbox3df& box);
void writeMeshBuffer(const scene::IMeshBuffer* buffer);
void writeMaterial(const video::SMaterial& material);
core::stringw getVectorAsStringLine(const core::vector3df& v) const;
core::stringw getVectorAsStringLine(const core::vector2df& v) const;
// member variables:
io::IFileSystem* FileSystem;
video::IVideoDriver* VideoDriver;
io::IXMLWriter* Writer;
};
} // end namespace
} // end namespace
#endif

View File

@ -110,14 +110,12 @@ set(IRRMESHLOADER
C3DSMeshFileLoader.cpp
COgreMeshFileLoader.cpp
COBJMeshFileLoader.cpp
CColladaFileLoader.cpp
CCSMLoader.cpp
CDMFLoader.cpp
CLMTSMeshFileLoader.cpp
CMY3DMeshFileLoader.cpp
COCTLoader.cpp
CXMeshFileLoader.cpp
CIrrMeshFileLoader.cpp
CSTLMeshFileLoader.cpp
CLWOMeshFileLoader.cpp
CPLYMeshFileLoader.cpp
@ -126,8 +124,6 @@ set(IRRMESHLOADER
)
set(IRRMESHWRITER
CColladaMeshWriter.cpp
CIrrMeshWriter.cpp
CSTLMeshWriter.cpp
COBJMeshWriter.cpp
CPLYMeshWriter.cpp
@ -176,7 +172,6 @@ add_library(IRROBJ OBJECT
CMeshCache.cpp
CDefaultSceneNodeAnimatorFactory.cpp
CDefaultSceneNodeFactory.cpp
CSceneLoaderIrr.cpp
)
add_library(IRRPARTICLEOBJ OBJECT
@ -318,15 +313,12 @@ add_library(IRRIOOBJ OBJECT
CMemoryFile.cpp
CReadFile.cpp
CWriteFile.cpp
CXMLReader.cpp
CXMLWriter.cpp
CWADReader.cpp
CZipReader.cpp
CPakReader.cpp
CNPKReader.cpp
CTarReader.cpp
CMountPointReader.cpp
irrXML.cpp
CAttributes.cpp
)

View File

@ -1,284 +0,0 @@
// Copyright (C) 2010-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CSceneLoaderIrr.h"
#include "ISceneNodeAnimatorFactory.h"
#include "ISceneUserDataSerializer.h"
#include "ISceneManager.h"
#include "IVideoDriver.h"
#include "IFileSystem.h"
#include "os.h"
namespace irr
{
namespace scene
{
//! Constructor
CSceneLoaderIrr::CSceneLoaderIrr(ISceneManager *smgr, io::IFileSystem* fs)
: SceneManager(smgr), FileSystem(fs),
IRR_XML_FORMAT_SCENE(L"irr_scene"), IRR_XML_FORMAT_NODE(L"node"), IRR_XML_FORMAT_NODE_ATTR_TYPE(L"type"),
IRR_XML_FORMAT_ATTRIBUTES(L"attributes"), IRR_XML_FORMAT_MATERIALS(L"materials"),
IRR_XML_FORMAT_ANIMATORS(L"animators"), IRR_XML_FORMAT_USERDATA(L"userData")
{
}
//! Destructor
CSceneLoaderIrr::~CSceneLoaderIrr()
{
}
//! Returns true if the class might be able to load this file.
bool CSceneLoaderIrr::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension(filename, "irr");
}
//! Returns true if the class might be able to load this file.
bool CSceneLoaderIrr::isALoadableFileFormat(io::IReadFile *file) const
{
// todo: check inside the file
return true;
}
//! Loads the scene into the scene manager.
bool CSceneLoaderIrr::loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer,
ISceneNode* rootNode)
{
if (!file)
{
os::Printer::log("Unable to open scene file", ELL_ERROR);
return false;
}
io::IXMLReader* reader = FileSystem->createXMLReader(file);
if (!reader)
{
os::Printer::log("Scene is not a valid XML file", file->getFileName().c_str(), ELL_ERROR);
return false;
}
// TODO: COLLADA_CREATE_SCENE_INSTANCES can be removed when the COLLADA loader is a scene loader
bool oldColladaSingleMesh = SceneManager->getParameters()->getAttributeAsBool(COLLADA_CREATE_SCENE_INSTANCES);
SceneManager->getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, false);
// read file
while (reader->read())
{
readSceneNode(reader, rootNode, userDataSerializer);
}
// restore old collada parameters
SceneManager->getParameters()->setAttribute(COLLADA_CREATE_SCENE_INSTANCES, oldColladaSingleMesh);
// clean up
reader->drop();
return true;
}
//! Reads the next node
void CSceneLoaderIrr::readSceneNode(io::IXMLReader* reader, ISceneNode* parent,
ISceneUserDataSerializer* userDataSerializer)
{
if (!reader)
return;
scene::ISceneNode* node = 0;
if (!parent && IRR_XML_FORMAT_SCENE==reader->getNodeName())
node = SceneManager->getRootSceneNode();
else if (parent && IRR_XML_FORMAT_NODE==reader->getNodeName())
{
// find node type and create it
core::stringc attrName = reader->getAttributeValue(IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str());
node = SceneManager->addSceneNode(attrName.c_str(), parent);
if (!node)
os::Printer::log("Could not create scene node of unknown type", attrName.c_str());
}
else
node=parent;
// read attributes
while(reader->read())
{
bool endreached = false;
const wchar_t* name = reader->getNodeName();
switch (reader->getNodeType())
{
case io::EXN_ELEMENT_END:
if ((IRR_XML_FORMAT_NODE == name) ||
(IRR_XML_FORMAT_SCENE == name))
{
endreached = true;
}
break;
case io::EXN_ELEMENT:
if (IRR_XML_FORMAT_ATTRIBUTES == name)
{
// read attributes
io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
attr->read(reader, true);
if (node)
node->deserializeAttributes(attr);
attr->drop();
}
else
if (IRR_XML_FORMAT_MATERIALS == name)
readMaterials(reader, node);
else
if (IRR_XML_FORMAT_ANIMATORS == name)
readAnimators(reader, node);
else
if (IRR_XML_FORMAT_USERDATA == name)
readUserData(reader, node, userDataSerializer);
else
if ((IRR_XML_FORMAT_NODE == name) ||
(IRR_XML_FORMAT_SCENE == name))
{
readSceneNode(reader, node, userDataSerializer);
}
else
{
os::Printer::log("Found unknown element in irrlicht scene file",
core::stringc(name).c_str());
}
break;
default:
break;
}
if (endreached)
break;
}
if (node && userDataSerializer)
userDataSerializer->OnCreateNode(node);
}
//! reads materials of a node
void CSceneLoaderIrr::readMaterials(io::IXMLReader* reader, ISceneNode* node)
{
u32 nr = 0;
while(reader->read())
{
const wchar_t* name = reader->getNodeName();
switch(reader->getNodeType())
{
case io::EXN_ELEMENT_END:
if (IRR_XML_FORMAT_MATERIALS == name)
return;
break;
case io::EXN_ELEMENT:
if (IRR_XML_FORMAT_ATTRIBUTES == name)
{
// read materials from attribute list
io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
attr->read(reader);
if (node && node->getMaterialCount() > nr)
{
SceneManager->getVideoDriver()->fillMaterialStructureFromAttributes(
node->getMaterial(nr), attr);
}
attr->drop();
++nr;
}
break;
default:
break;
}
}
}
//! reads animators of a node
void CSceneLoaderIrr::readAnimators(io::IXMLReader* reader, ISceneNode* node)
{
while(reader->read())
{
const wchar_t* name = reader->getNodeName();
switch(reader->getNodeType())
{
case io::EXN_ELEMENT_END:
if (IRR_XML_FORMAT_ANIMATORS == name)
return;
break;
case io::EXN_ELEMENT:
if (IRR_XML_FORMAT_ATTRIBUTES == name)
{
// read animator data from attribute list
io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
attr->read(reader);
if (node)
{
core::stringc typeName = attr->getAttributeAsString("Type");
ISceneNodeAnimator* anim = SceneManager->createSceneNodeAnimator(typeName.c_str(), node);
if (anim)
{
anim->deserializeAttributes(attr);
anim->drop();
}
}
attr->drop();
}
break;
default:
break;
}
}
}
//! reads user data of a node
void CSceneLoaderIrr::readUserData(io::IXMLReader* reader, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer)
{
while(reader->read())
{
const wchar_t* name = reader->getNodeName();
switch(reader->getNodeType())
{
case io::EXN_ELEMENT_END:
if (IRR_XML_FORMAT_USERDATA == name)
return;
break;
case io::EXN_ELEMENT:
if (IRR_XML_FORMAT_ATTRIBUTES == name)
{
// read user data from attribute list
io::IAttributes* attr = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
attr->read(reader);
if (node && userDataSerializer)
{
userDataSerializer->OnReadUserData(node, attr);
}
attr->drop();
}
break;
default:
break;
}
}
}
} // scene
} // irr

View File

@ -1,83 +0,0 @@
// Copyright (C) 2010-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_SCENE_LOADER_IRR_H_INCLUDED__
#define __C_SCENE_LOADER_IRR_H_INCLUDED__
#include "ISceneLoader.h"
#include "IXMLReader.h"
namespace irr
{
namespace io
{
class IFileSystem;
}
namespace scene
{
class ISceneManager;
//! Class which can load a scene into the scene manager.
class CSceneLoaderIrr : public virtual ISceneLoader
{
public:
//! Constructor
CSceneLoaderIrr(ISceneManager *smgr, io::IFileSystem* fs);
//! Destructor
virtual ~CSceneLoaderIrr();
//! Returns true if the class might be able to load this file.
virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_OVERRIDE_;
//! Returns true if the class might be able to load this file.
virtual bool isALoadableFileFormat(io::IReadFile *file) const _IRR_OVERRIDE_;
//! Loads the scene into the scene manager.
virtual bool loadScene(io::IReadFile* file,
ISceneUserDataSerializer* userDataSerializer=0,
ISceneNode* rootNode=0) _IRR_OVERRIDE_;
private:
//! Recursively reads nodes from the xml file
void readSceneNode(io::IXMLReader* reader, ISceneNode* parent,
ISceneUserDataSerializer* userDataSerializer);
//! read a node's materials
void readMaterials(io::IXMLReader* reader, ISceneNode* node);
//! read a node's animators
void readAnimators(io::IXMLReader* reader, ISceneNode* node);
//! read any other data into the user serializer
void readUserData(io::IXMLReader* reader, ISceneNode* node,
ISceneUserDataSerializer* userDataSerializer);
ISceneManager *SceneManager;
io::IFileSystem *FileSystem;
//! constants for reading and writing XML.
//! Not made static due to portability problems.
// TODO: move to own header
const core::stringw IRR_XML_FORMAT_SCENE;
const core::stringw IRR_XML_FORMAT_NODE;
const core::stringw IRR_XML_FORMAT_NODE_ATTR_TYPE;
const core::stringw IRR_XML_FORMAT_ATTRIBUTES;
const core::stringw IRR_XML_FORMAT_MATERIALS;
const core::stringw IRR_XML_FORMAT_ANIMATORS;
const core::stringw IRR_XML_FORMAT_USERDATA;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -8,7 +8,6 @@
#include "IFileSystem.h"
#include "SAnimatedMesh.h"
#include "CMeshCache.h"
#include "IXMLWriter.h"
#include "ISceneUserDataSerializer.h"
#include "IGUIEnvironment.h"
#include "IMaterialRenderer.h"
@ -26,10 +25,6 @@
#include "CSkinnedMesh.h"
#endif
#ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
#include "CIrrMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
#include "CBSPMeshFileLoader.h"
#endif
@ -70,10 +65,6 @@
#include "CMY3DMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
#include "CColladaFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
#include "CDMFLoader.h"
#endif
@ -110,18 +101,6 @@
#include "CSMFMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
#include "CSceneLoaderIrr.h"
#endif
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
#include "CColladaMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
#include "CIrrMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_STL_WRITER_
#include "CSTLMeshWriter.h"
#endif
@ -219,8 +198,7 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
: ISceneNode(0, 0), Driver(driver), FileSystem(fs), GUIEnvironment(gui),
CursorControl(cursorControl), CollisionManager(0),
ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), Parameters(0),
MeshCache(cache), CurrentRenderPass(ESNRP_NONE), LightManager(0),
IRR_XML_FORMAT_SCENE(L"irr_scene"), IRR_XML_FORMAT_NODE(L"node"), IRR_XML_FORMAT_NODE_ATTR_TYPE(L"type")
MeshCache(cache), CurrentRenderPass(ESNRP_NONE), LightManager(0)
{
#ifdef _DEBUG
ISceneManager::setDebugName("CSceneManager ISceneManager");
@ -304,15 +282,9 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
MeshLoaderList.push_back(new CMD2MeshFileLoader());
#endif
#ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
MeshLoaderList.push_back(new CIrrMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
MeshLoaderList.push_back(new CBSPMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
MeshLoaderList.push_back(new CColladaFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_3DS_LOADER_
MeshLoaderList.push_back(new C3DSMeshFileLoader(this, FileSystem));
#endif
@ -329,11 +301,6 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
MeshLoaderList.push_back(new CB3DMeshFileLoader(this));
#endif
// scene loaders
#ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
SceneLoaderList.push_back(new CSceneLoaderIrr(this, FileSystem));
#endif
// factories
ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this);
registerSceneNodeFactory(factory);
@ -2298,44 +2265,7 @@ bool CSceneManager::saveScene(const io::path& filename, ISceneUserDataSerializer
//! Saves the current scene into a file.
bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node)
{
if (!file)
{
return false;
}
bool result=false;
io::IXMLWriter* writer = FileSystem->createXMLWriter(file);
if (!writer)
{
os::Printer::log("Unable to create XML writer", file->getFileName(), ELL_ERROR);
}
else
{
result = saveScene(writer, FileSystem->getFileDir(FileSystem->getAbsolutePath(file->getFileName())), userDataSerializer, node);
writer->drop();
}
return result;
}
//! Saves the current scene into a file.
bool CSceneManager::saveScene(io::IXMLWriter* writer, const io::path& currentPath, ISceneUserDataSerializer* userDataSerializer, ISceneNode* node)
{
if (!writer)
return false;
if (!node)
node=this;
char* oldLocale = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC, "C"); // float number should to be saved with dots in this format independent of current locale settings.
writer->writeXMLHeader();
writeSceneNode(writer, node, userDataSerializer, currentPath.c_str(), true);
setlocale(LC_NUMERIC, oldLocale);
return true;
return false;
}
@ -2380,139 +2310,6 @@ bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* use
}
//! writes a scene node
void CSceneManager::writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer,
const fschar_t* currentPath, bool init)
{
if (!writer || !node || node->isDebugObject())
return;
const wchar_t* name;
ISceneNode* tmpNode=node;
if (init)
{
name = IRR_XML_FORMAT_SCENE.c_str();
writer->writeElement(name, false);
node=this;
}
else
{
name = IRR_XML_FORMAT_NODE.c_str();
writer->writeElement(name, false, IRR_XML_FORMAT_NODE_ATTR_TYPE.c_str(),
core::stringw(getSceneNodeTypeName(node->getType())).c_str());
}
writer->writeLineBreak();
// write properties
io::IAttributes* attr = FileSystem->createEmptyAttributes(Driver);
io::SAttributeReadWriteOptions options;
if (currentPath)
{
options.Filename=currentPath;
options.Flags|=io::EARWF_USE_RELATIVE_PATHS;
}
node->serializeAttributes(attr, &options);
if (attr->getAttributeCount() != 0)
{
attr->write(writer);
writer->writeLineBreak();
}
// write materials
if (node->getMaterialCount() && Driver)
{
const wchar_t* materialElement = L"materials";
writer->writeElement(materialElement);
writer->writeLineBreak();
for (u32 i=0; i < node->getMaterialCount(); ++i)
{
io::IAttributes* tmp_attr =
Driver->createAttributesFromMaterial(node->getMaterial(i), &options);
tmp_attr->write(writer);
tmp_attr->drop();
}
writer->writeClosingTag(materialElement);
writer->writeLineBreak();
}
// write animators
if (!node->getAnimators().empty())
{
const wchar_t* animatorElement = L"animators";
writer->writeElement(animatorElement);
writer->writeLineBreak();
ISceneNodeAnimatorList::ConstIterator it = node->getAnimators().begin();
for (; it != node->getAnimators().end(); ++it)
{
attr->clear();
attr->addString("Type", getAnimatorTypeName((*it)->getType()));
(*it)->serializeAttributes(attr);
attr->write(writer);
}
writer->writeClosingTag(animatorElement);
writer->writeLineBreak();
}
// write possible user data
if (userDataSerializer)
{
io::IAttributes* userData = userDataSerializer->createUserData(node);
if (userData)
{
const wchar_t* userDataElement = L"userData";
writer->writeLineBreak();
writer->writeElement(userDataElement);
writer->writeLineBreak();
userData->write(writer);
writer->writeClosingTag(userDataElement);
writer->writeLineBreak();
writer->writeLineBreak();
userData->drop();
}
}
// reset to actual root node
if (init)
node=tmpNode;
// 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();
writer->writeClosingTag(name);
writer->writeLineBreak();
writer->writeLineBreak();
}
//! Returns a typename from a scene node type or null if not found
const c8* CSceneManager::getSceneNodeTypeName(ESCENE_NODE_TYPE type)
{
@ -2648,17 +2445,8 @@ IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type)
switch(type)
{
case EMWT_IRR_MESH:
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
return new CIrrMeshWriter(Driver, FileSystem);
#else
return 0;
#endif
case EMWT_COLLADA:
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
return new CColladaMeshWriter(this, Driver, FileSystem);
#else
return 0;
#endif
case EMWT_STL:
#ifdef _IRR_COMPILE_WITH_STL_WRITER_
return new CSTLMeshWriter(this);

View File

@ -492,9 +492,6 @@ namespace scene
//! Saves the current scene into a file.
virtual bool saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) _IRR_OVERRIDE_;
//! Saves the current scene into a file.
virtual bool saveScene(io::IXMLWriter* writer, const io::path& currentPath, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* node=0) _IRR_OVERRIDE_;
//! Loads a scene. Note that the current scene is not cleared before.
virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0, ISceneNode* rootNode=0) _IRR_OVERRIDE_;
@ -542,9 +539,6 @@ namespace scene
//! clears the deletion list
void clearDeletionList();
//! writes a scene node
void writeSceneNode(io::IXMLWriter* writer, ISceneNode* node, ISceneUserDataSerializer* userDataSerializer, const fschar_t* currentPath=0, bool init=false);
struct DefaultNodeEntry
{
DefaultNodeEntry(ISceneNode* n) :
@ -660,12 +654,6 @@ namespace scene
//! over the scene lighting and rendering.
ILightManager* LightManager;
//! constants for reading and writing XML.
//! Not made static due to portability problems.
const core::stringw IRR_XML_FORMAT_SCENE;
const core::stringw IRR_XML_FORMAT_NODE;
const core::stringw IRR_XML_FORMAT_NODE_ATTR_TYPE;
IGeometryCreator* GeometryCreator;
};

View File

@ -1,84 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CXMLReader.h"
#ifdef _IRR_COMPILE_WITH_XML_
#include "CXMLReaderImpl.h"
#include "IReadFile.h"
namespace irr
{
namespace io
{
//! Irrlicht implementation of the file read callback for the xml parser
class CIrrXMLFileReadCallBack : public IFileReadCallBack
{
public:
//! construct from FILE pointer
CIrrXMLFileReadCallBack(IReadFile* file)
: ReadFile(file)
{
ReadFile->grab();
}
//! destructor
virtual ~CIrrXMLFileReadCallBack()
{
ReadFile->drop();
}
//! Reads an amount of bytes from the file.
virtual int read(void* buffer, int sizeToRead) _IRR_OVERRIDE_
{
return (int)ReadFile->read(buffer, sizeToRead);
}
//! Returns size of file in bytes
virtual long getSize() const _IRR_OVERRIDE_
{
return ReadFile->getSize();
}
private:
IReadFile* ReadFile;
}; // end class CMyXMLFileReadCallBack
// now create an implementation for IXMLReader using irrXML.
//! Creates an instance of a wide character xml parser.
IXMLReader* createIXMLReader(IReadFile* file)
{
if (!file)
return 0;
return new CXMLReaderImpl<wchar_t, IReferenceCounted>(new CIrrXMLFileReadCallBack(file));
}
//! Creates an instance of an UFT-8 or ASCII character xml parser.
IXMLReaderUTF8* createIXMLReaderUTF8(IReadFile* file)
{
if (!file)
return 0;
return new CXMLReaderImpl<char, IReferenceCounted>(new CIrrXMLFileReadCallBack(file));
}
} // end namespace
} // end namespace
#else // not _IRR_COMPILE_WITH_XML_
#include "os.h"
namespace irr
{
void noXML()
{
irr::os::Printer::log("XML support disabled in IrrCompileConfig.", irr::ELL_ERROR);
}
} // end namespace
#endif // _IRR_COMPILE_WITH_XML_

View File

@ -1,30 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_XML_READER_H_INCLUDED__
#define __C_XML_READER_H_INCLUDED__
#include "IXMLReader.h"
namespace irr
{
#ifdef _IRR_COMPILE_WITH_XML_
namespace io
{
class IReadFile;
//! creates an IXMLReader
IXMLReader* createIXMLReader(IReadFile* file);
//! creates an IXMLReader
IXMLReaderUTF8* createIXMLReaderUTF8(IReadFile* file);
} // end namespace irr
#else // _IRR_COMPILE_WITH_XML_
//! print a message that Irrlicht is compiled without _IRR_COMPILE_WITH_XML_
void noXML();
#endif // _IRR_COMPILE_WITH_XML_
} // end namespace io
#endif

View File

@ -1,821 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
#ifndef __ICXML_READER_IMPL_H_INCLUDED__
#define __ICXML_READER_IMPL_H_INCLUDED__
#include "irrXML.h"
#include "irrString.h"
#include "irrArray.h"
#include "fast_atof.h"
#ifdef _DEBUG
#define IRR_DEBUGPRINT(x) printf((x));
#else // _DEBUG
#define IRR_DEBUGPRINT(x)
#endif // _DEBUG
namespace irr
{
namespace io
{
//! implementation of the IrrXMLReader
template<class char_type, class superclass>
class CXMLReaderImpl : public IIrrXMLReader<char_type, superclass>
{
public:
//! Constructor
CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true)
: IgnoreWhitespaceText(true), TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE),
SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII), IsEmptyElement(false)
{
if (!callback)
return;
storeTargetFormat();
// read whole xml file
readFile(callback);
// clean up
if (deleteCallBack)
delete callback;
// create list with special characters
createSpecialCharacterList();
// set pointer to text begin
P = TextBegin;
}
//! Destructor
virtual ~CXMLReaderImpl()
{
delete [] TextData;
}
//! Reads forward to the next xml node.
//! \return Returns false, if there was no further node.
virtual bool read() _IRR_OVERRIDE_
{
// if not end reached, parse the node
if (P && ((unsigned int)(P - TextBegin) < TextSize - 1) && (*P != 0))
{
return parseCurrentNode();
}
return false;
}
//! Returns the type of the current XML node.
virtual EXML_NODE getNodeType() const _IRR_OVERRIDE_
{
return CurrentNodeType;
}
//! Returns attribute count of the current XML node.
virtual unsigned int getAttributeCount() const _IRR_OVERRIDE_
{
return Attributes.size();
}
//! Returns name of an attribute.
virtual const char_type* getAttributeName(int idx) const _IRR_OVERRIDE_
{
if ((u32)idx >= Attributes.size())
return 0;
return Attributes[idx].Name.c_str();
}
//! Returns the value of an attribute.
virtual const char_type* getAttributeValue(int idx) const _IRR_OVERRIDE_
{
if ((unsigned int)idx >= Attributes.size())
return 0;
return Attributes[idx].Value.c_str();
}
//! Returns the value of an attribute.
virtual const char_type* getAttributeValue(const char_type* name) const _IRR_OVERRIDE_
{
const SAttribute* attr = getAttributeByName(name);
if (!attr)
return 0;
return attr->Value.c_str();
}
//! Returns the value of an attribute
virtual const char_type* getAttributeValueSafe(const char_type* name) const _IRR_OVERRIDE_
{
const SAttribute* attr = getAttributeByName(name);
if (!attr)
return EmptyString.c_str();
return attr->Value.c_str();
}
//! Returns the value of an attribute as integer.
virtual int getAttributeValueAsInt(const char_type* name, int defaultNotFound) const _IRR_OVERRIDE_
{
const SAttribute* attr = getAttributeByName(name);
if (!attr)
return defaultNotFound;
core::stringc c(attr->Value.c_str());
return core::strtol10(c.c_str());
}
//! Returns the value of an attribute as integer.
virtual int getAttributeValueAsInt(int idx, int defaultNotFound) const _IRR_OVERRIDE_
{
const char_type* attrvalue = getAttributeValue(idx);
if (!attrvalue)
return defaultNotFound;
core::stringc c(attrvalue);
return core::strtol10(c.c_str());
}
//! Returns the value of an attribute as float.
virtual float getAttributeValueAsFloat(const char_type* name, float defaultNotFound) const _IRR_OVERRIDE_
{
const SAttribute* attr = getAttributeByName(name);
if (!attr)
return defaultNotFound;
core::stringc c = attr->Value.c_str();
return core::fast_atof(c.c_str());
}
//! Returns the value of an attribute as float.
virtual float getAttributeValueAsFloat(int idx, float defaultNotFound) const _IRR_OVERRIDE_
{
const char_type* attrvalue = getAttributeValue(idx);
if (!attrvalue)
return defaultNotFound;
core::stringc c = attrvalue;
return core::fast_atof(c.c_str());
}
//! Returns the name of the current node.
virtual const char_type* getNodeName() const _IRR_OVERRIDE_
{
return NodeName.c_str();
}
//! Returns data of the current node.
virtual const char_type* getNodeData() const _IRR_OVERRIDE_
{
return NodeName.c_str();
}
//! Returns if an element is an empty element, like <foo />
virtual bool isEmptyElement() const _IRR_OVERRIDE_
{
return IsEmptyElement;
}
//! Returns format of the source xml file.
virtual ETEXT_FORMAT getSourceFormat() const _IRR_OVERRIDE_
{
return SourceFormat;
}
//! Returns format of the strings returned by the parser.
virtual ETEXT_FORMAT getParserFormat() const _IRR_OVERRIDE_
{
return TargetFormat;
}
private:
// Reads the current xml node
// return false if no further node is found
bool parseCurrentNode()
{
char_type* start = P;
// more forward until '<' found
while(*P != L'<' && *P)
++P;
// not a node, so return false
if (!*P)
return false;
if (P - start > 0)
{
// we found some text, store it
if (setText(start, P))
return true;
}
++P;
// based on current token, parse and report next element
switch(*P)
{
case L'/':
parseClosingXMLElement();
break;
case L'?':
ignoreDefinition();
break;
case L'!':
if (!parseCDATA())
parseComment();
break;
default:
parseOpeningXMLElement();
break;
}
return true;
}
//! sets the state that text was found. Returns true if set should be set
bool setText(char_type* start, char_type* end)
{
// By default xml preserves all whitespace. But Irrlicht dropped some whitespace by default
// in the past which did lead to OS dependent behavior. We just ignore all whitespace for now
// as it's the closest to fixing behavior without breaking downward compatibility too much.
if ( IgnoreWhitespaceText )
{
char_type* p = start;
for(; p != end; ++p)
if (!isWhiteSpace(*p))
break;
if (p == end)
return false;
}
// set current text to the parsed text, and replace xml special characters
core::string<char_type> s(start, (int)(end - start));
NodeName = replaceSpecialCharacters(s);
// current XML node type is text
CurrentNodeType = EXN_TEXT;
return true;
}
//! ignores an xml definition like <?xml something />
void ignoreDefinition()
{
CurrentNodeType = EXN_UNKNOWN;
// move until end marked with '>' reached
while(*P != L'>')
++P;
++P;
}
//! parses a comment
void parseComment()
{
CurrentNodeType = EXN_COMMENT;
P += 1;
char_type *pCommentBegin = P;
int count = 1;
// move until end of comment reached
while(count)
{
if (*P == L'>')
--count;
else
if (*P == L'<')
++count;
++P;
}
P -= 3;
NodeName = core::string<char_type>(pCommentBegin+2, (int)(P - pCommentBegin-2));
P += 3;
}
//! parses an opening xml element and reads attributes
void parseOpeningXMLElement()
{
CurrentNodeType = EXN_ELEMENT;
IsEmptyElement = false;
Attributes.clear();
// find name
const char_type* startName = P;
// find end of element
while(*P != L'>' && !isWhiteSpace(*P))
++P;
const char_type* endName = P;
// find Attributes
while(*P != L'>')
{
if (isWhiteSpace(*P))
++P;
else
{
if (*P != L'/')
{
// we've got an attribute
// read the attribute names
const char_type* attributeNameBegin = P;
while(!isWhiteSpace(*P) && *P != L'=')
++P;
const char_type* attributeNameEnd = P;
++P;
// read the attribute value
// check for quotes and single quotes, thx to murphy
while( (*P != L'\"') && (*P != L'\'') && *P)
++P;
if (!*P) // malformatted xml file
return;
const char_type attributeQuoteChar = *P;
++P;
const char_type* attributeValueBegin = P;
while(*P != attributeQuoteChar && *P)
++P;
if (!*P) // malformatted xml file
return;
const char_type* attributeValueEnd = P;
++P;
SAttribute attr;
attr.Name = core::string<char_type>(attributeNameBegin,
(int)(attributeNameEnd - attributeNameBegin));
core::string<char_type> s(attributeValueBegin,
(int)(attributeValueEnd - attributeValueBegin));
attr.Value = replaceSpecialCharacters(s);
Attributes.push_back(attr);
}
else
{
// tag is closed directly
++P;
IsEmptyElement = true;
break;
}
}
}
// check if this tag is closing directly
if (endName > startName && *(endName-1) == L'/')
{
// directly closing tag
IsEmptyElement = true;
endName--;
}
NodeName = core::string<char_type>(startName, (int)(endName - startName));
++P;
}
//! parses an closing xml tag
void parseClosingXMLElement()
{
CurrentNodeType = EXN_ELEMENT_END;
IsEmptyElement = false;
Attributes.clear();
++P;
const char_type* pBeginClose = P;
while(*P != L'>')
++P;
NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose));
++P;
}
//! parses a possible CDATA section, returns false if begin was not a CDATA section
bool parseCDATA()
{
if (*(P+1) != L'[')
return false;
CurrentNodeType = EXN_CDATA;
// skip '<![CDATA['
int count=0;
while( *P && count<8 )
{
++P;
++count;
}
if (!*P)
return true;
char_type *cDataBegin = P;
char_type *cDataEnd = 0;
// find end of CDATA
while(*P && !cDataEnd)
{
if (*P == L'>' &&
(*(P-1) == L']') &&
(*(P-2) == L']'))
{
cDataEnd = P - 2;
}
++P;
}
if ( cDataEnd )
NodeName = core::string<char_type>(cDataBegin, (int)(cDataEnd - cDataBegin));
else
NodeName = "";
return true;
}
// structure for storing attribute-name pairs
struct SAttribute
{
core::string<char_type> Name;
core::string<char_type> Value;
};
// finds a current attribute by name, returns 0 if not found
const SAttribute* getAttributeByName(const char_type* name) const
{
if (!name)
return 0;
core::string<char_type> n = name;
for (int i=0; i<(int)Attributes.size(); ++i)
if (Attributes[i].Name == n)
return &Attributes[i];
return 0;
}
// replaces xml special characters in a string and creates a new one
core::string<char_type> replaceSpecialCharacters(
const core::string<char_type>& origstr)
{
int pos = origstr.findFirst(L'&');
int oldPos = 0;
if (pos == -1)
return origstr;
core::string<char_type> newstr;
while(pos != -1 && pos < (int)origstr.size()-2)
{
// check if it is one of the special characters
int specialChar = -1;
for (int i=0; i<(int)SpecialCharacters.size(); ++i)
{
const char_type* p = &origstr.c_str()[pos]+1;
if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1))
{
specialChar = i;
break;
}
}
if (specialChar != -1)
{
newstr.append(origstr.subString(oldPos, pos - oldPos));
newstr.append(SpecialCharacters[specialChar][0]);
pos += SpecialCharacters[specialChar].size();
}
else
{
newstr.append(origstr.subString(oldPos, pos - oldPos + 1));
pos += 1;
}
// find next &
oldPos = pos;
pos = origstr.findNext(L'&', pos);
}
if (oldPos < (int)origstr.size()-1)
newstr.append(origstr.subString(oldPos, origstr.size()-oldPos));
return newstr;
}
//! reads the xml file and converts it into the wanted character format.
bool readFile(IFileReadCallBack* callback)
{
long size = callback->getSize();
if (size<0)
return false;
// We need four terminating 0's at the end.
// For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4.
size += 4;
char* data8 = new char[size];
if (!callback->read(data8, size-4))
{
delete [] data8;
return false;
}
// add zeros at end
memset(data8+size-4, 0, 4);
char16* data16 = reinterpret_cast<char16*>(data8);
char32* data32 = reinterpret_cast<char32*>(data8);
// now we need to convert the data to the desired target format
// based on the byte order mark.
const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF;
const u16 UTF16_BE = 0xFFFE;
const u16 UTF16_LE = 0xFEFF;
const u32 UTF32_BE = 0xFFFE0000;
const u32 UTF32_LE = 0x0000FEFF;
// check source for all utf versions and convert to target data format
if (size >= 4 && data32[0]
== static_cast<char32>(UTF32_BE))
{
// UTF-32, big endian
SourceFormat = ETF_UTF32_BE;
convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header
}
else
if (size >= 4 && data32[0] == static_cast<char32>(UTF32_LE))
{
// UTF-32, little endian
SourceFormat = ETF_UTF32_LE;
convertTextData(data32+1, data8, (size/4)-1); // data32+1 because we need to skip the header
}
else
if (size >= 2 && data16[0] == UTF16_BE)
{
// UTF-16, big endian
SourceFormat = ETF_UTF16_BE;
convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header
}
else
if (size >= 2 && data16[0] == UTF16_LE)
{
// UTF-16, little endian
SourceFormat = ETF_UTF16_LE;
convertTextData(data16+1, data8, (size/2)-1); // data16+1 because we need to skip the header
}
else
if (size >= 3 && memcmp(data8,UTF8,3)==0)
{
// UTF-8
SourceFormat = ETF_UTF8;
convertTextData(data8+3, data8, size-3); // data8+3 because we need to skip the header
}
else
{
// ASCII
SourceFormat = ETF_ASCII;
convertTextData(data8, data8, size);
}
return true;
}
//! converts the text file into the desired format.
/** \param source: begin of the text (without byte order mark)
\param pointerToStore: pointer to text data block which can be
stored or deleted based on the nesessary conversion.
\param sizeWithoutHeader: Text size in characters without header
*/
template<class src_char_type>
void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader)
{
// convert little to big endian if necessary
if (sizeof(src_char_type) > 1 &&
isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat))
convertToLittleEndian(source);
// check if conversion is necessary:
if (sizeof(src_char_type) == sizeof(char_type))
{
// no need to convert
TextBegin = (char_type*)source;
TextData = (char_type*)pointerToStore;
TextSize = sizeWithoutHeader;
}
else
{
// convert source into target data format.
// TODO: implement a real conversion. This one just
// copies bytes. This is a problem when there are
// unicode symbols using more than one character.
TextData = new char_type[sizeWithoutHeader];
if ( sizeof(src_char_type) == 1 )
{
// we have to cast away negative numbers or results might add the sign instead of just doing a copy
for (int i=0; i<sizeWithoutHeader; ++i)
{
TextData[i] = static_cast<char_type>(static_cast<unsigned char>(source[i]));
}
}
else
{
for (int i=0; i<sizeWithoutHeader; ++i)
TextData[i] = static_cast<char_type>(source[i]);
}
TextBegin = TextData;
TextSize = sizeWithoutHeader;
// delete original data because no longer needed
delete [] pointerToStore;
}
}
//! converts whole text buffer to little endian
template<class src_char_type>
void convertToLittleEndian(src_char_type* t)
{
if (sizeof(src_char_type) == 4)
{
// 32 bit
while(*t)
{
*t = ((*t & 0xff000000) >> 24) |
((*t & 0x00ff0000) >> 8) |
((*t & 0x0000ff00) << 8) |
((*t & 0x000000ff) << 24);
++t;
}
}
else
{
// 16 bit
while(*t)
{
*t = (*t >> 8) | (*t << 8);
++t;
}
}
}
//! returns if a format is little endian
inline bool isLittleEndian(ETEXT_FORMAT f)
{
return f == ETF_ASCII ||
f == ETF_UTF8 ||
f == ETF_UTF16_LE ||
f == ETF_UTF32_LE;
}
//! returns true if a character is whitespace
inline bool isWhiteSpace(char_type c)
{
return (c==' ' || c=='\t' || c=='\n' || c=='\r');
}
//! generates a list with xml special characters
void createSpecialCharacterList()
{
// list of strings containing special symbols,
// the first character is the special character,
// the following is the symbol string without trailing &.
SpecialCharacters.push_back("&amp;");
SpecialCharacters.push_back("<lt;");
SpecialCharacters.push_back(">gt;");
SpecialCharacters.push_back("\"quot;");
SpecialCharacters.push_back("'apos;");
}
//! compares the first n characters of the strings
bool equalsn(const char_type* str1, const char_type* str2, int len)
{
int i;
for(i=0; str1[i] && str2[i] && i < len; ++i)
if (str1[i] != str2[i])
return false;
// if one (or both) of the strings was smaller then they
// are only equal if they have the same length
return (i == len) || (str1[i] == 0 && str2[i] == 0);
}
//! stores the target text format
void storeTargetFormat()
{
// get target format. We could have done this using template specialization,
// but VisualStudio 6 don't like it and we want to support it.
switch(sizeof(char_type))
{
case 1:
TargetFormat = ETF_UTF8;
break;
case 2:
TargetFormat = ETF_UTF16_LE;
break;
case 4:
TargetFormat = ETF_UTF32_LE;
break;
default:
TargetFormat = ETF_ASCII; // should never happen.
}
}
// instance variables:
bool IgnoreWhitespaceText; // do not return EXN_TEXT nodes for pure whitespace
char_type* TextData; // data block of the text file
char_type* P; // current point in text to parse
char_type* TextBegin; // start of text to parse
unsigned int TextSize; // size of text to parse in characters, not bytes
EXML_NODE CurrentNodeType; // type of the currently parsed node
ETEXT_FORMAT SourceFormat; // source format of the xml file
ETEXT_FORMAT TargetFormat; // output format of this parser
core::string<char_type> NodeName; // name of the node currently in - also used for text
core::string<char_type> EmptyString; // empty string to be returned by getSafe() methods
bool IsEmptyElement; // is the currently parsed node empty?
core::array< core::string<char_type> > SpecialCharacters; // see createSpecialCharacterList()
core::array<SAttribute> Attributes; // attributes of current element
}; // end CXMLReaderImpl
} // end namespace
} // end namespace
#endif

View File

@ -1,472 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CXMLWriter.h"
#ifdef _IRR_COMPILE_WITH_XML_
#include <wchar.h>
#include "irrString.h"
#include "IrrCompileConfig.h"
namespace irr
{
namespace io
{
//! creates an IXMLReader
IXMLWriter* createIXMLWriter(IWriteFile* file)
{
return new CXMLWriter(file);
}
//! creates an IXMLReader
IXMLWriterUTF8* createIXMLWriterUTF8(IWriteFile* file)
{
return new CXMLWriterUTF8(file);
}
//! Constructor
CXMLWriter::CXMLWriter(IWriteFile* file)
: CXMLWriterCommon(file)
{
#ifdef _DEBUG
setDebugName("CXMLWriter");
#endif
}
//! Writes a xml 1.0 header like <?xml version="1.0"?>
void CXMLWriter::writeXMLHeader()
{
if (!File)
return;
if (sizeof(wchar_t)==2)
{
const u16 h = 0xFEFF;
File->write(&h, 2);
}
else
{
const u32 h = 0x0000FEFF;
File->write(&h, sizeof(wchar_t));
}
const wchar_t* const p = L"<?xml version=\"1.0\"?>";
File->write(p, wcslen(p)*sizeof(wchar_t));
writeLineBreak();
TextWrittenLast = false;
}
//! Writes an xml element with maximal 5 attributes
void CXMLWriter::writeElement(const wchar_t* name, bool empty,
const wchar_t* attr1Name, const wchar_t* attr1Value,
const wchar_t* attr2Name, const wchar_t* attr2Value,
const wchar_t* attr3Name, const wchar_t* attr3Value,
const wchar_t* attr4Name, const wchar_t* attr4Value,
const wchar_t* attr5Name, const wchar_t* attr5Value)
{
if (!File || !name)
return;
if (Tabs > 0)
{
for (int i=0; i<Tabs; ++i)
File->write(L"\t", sizeof(wchar_t));
}
// write name
File->write(L"<", sizeof(wchar_t));
File->write(name, wcslen(name)*sizeof(wchar_t));
// write attributes
writeAttribute(attr1Name, attr1Value);
writeAttribute(attr2Name, attr2Value);
writeAttribute(attr3Name, attr3Value);
writeAttribute(attr4Name, attr4Value);
writeAttribute(attr5Name, attr5Value);
// write closing tag
if (empty)
File->write(L" />", 3*sizeof(wchar_t));
else
{
File->write(L">", sizeof(wchar_t));
++Tabs;
}
TextWrittenLast = false;
}
//! Writes an xml element with any number of attributes
void CXMLWriter::writeElement(const wchar_t* name, bool empty,
core::array<core::stringw> &names,
core::array<core::stringw> &values)
{
if (!File || !name)
return;
if (Tabs > 0)
{
for (int i=0; i<Tabs; ++i)
File->write(L"\t", sizeof(wchar_t));
}
// write name
File->write(L"<", sizeof(wchar_t));
File->write(name, wcslen(name)*sizeof(wchar_t));
// write attributes
u32 i=0;
for (; i < names.size() && i < values.size(); ++i)
writeAttribute(names[i].c_str(), values[i].c_str());
// write closing tag
if (empty)
File->write(L" />", 3*sizeof(wchar_t));
else
{
File->write(L">", sizeof(wchar_t));
++Tabs;
}
TextWrittenLast = false;
}
void CXMLWriter::writeAttribute(const wchar_t* name, const wchar_t* value)
{
if (!name || !value)
return;
File->write(L" ", sizeof(wchar_t));
File->write(name, wcslen(name)*sizeof(wchar_t));
File->write(L"=\"", 2*sizeof(wchar_t));
writeText(value);
File->write(L"\"", sizeof(wchar_t));
}
//! Writes a comment into the xml file
void CXMLWriter::writeComment(const wchar_t* comment)
{
if (!File || !comment)
return;
File->write(L"<!--", 4*sizeof(wchar_t));
writeText(comment);
File->write(L"-->", 3*sizeof(wchar_t));
}
//! Writes the closing tag for an element. Like </foo>
void CXMLWriter::writeClosingTag(const wchar_t* name)
{
if (!File || !name)
return;
--Tabs;
if (Tabs > 0 && !TextWrittenLast)
{
for (int i=0; i<Tabs; ++i)
File->write(L"\t", sizeof(wchar_t));
}
File->write(L"</", 2*sizeof(wchar_t));
File->write(name, wcslen(name)*sizeof(wchar_t));
File->write(L">", sizeof(wchar_t));
TextWrittenLast = false;
}
//! Writes a text into the file. All occurrences of special characters like
//! & (&amp;), < (&lt;), > (&gt;), and " (&quot;) are automatically replaced.
void CXMLWriter::writeText(const wchar_t* text)
{
if (!File || !text)
return;
static const CXMLWriter::XMLSpecialCharacters XMLWSChar[] =
{
{ L'&', L"&amp;" },
{ L'<', L"&lt;" },
{ L'>', L"&gt;" },
{ L'"', L"&quot;" },
{ L'\0', 0 }
};
// TODO: we have to get rid of that reserve call as well as it slows down xml-writing seriously.
// Making a member-variable would work, but a lot of memory would stay around after writing.
// So the correct solution is probably using fixed block here and always write when that is full.
core::stringw s;
s.reserve(wcslen(text)+1);
const wchar_t* p = text;
while(*p)
{
// check if it is matching
bool found = false;
for (s32 i=0; XMLWSChar[i].Character != '\0'; ++i)
if (*p == XMLWSChar[i].Character)
{
s.append(XMLWSChar[i].Symbol);
found = true;
break;
}
if (!found)
s.append(*p);
++p;
}
// write new string
File->write(s.c_str(), s.size()*sizeof(wchar_t));
TextWrittenLast = true;
}
//! Writes a line break
void CXMLWriter::writeLineBreak()
{
if (!File)
return;
#if defined(_IRR_OSX_PLATFORM_)
File->write(L"\r", sizeof(wchar_t));
#elif defined(_IRR_WINDOWS_API_)
File->write(L"\r\n", 2*sizeof(wchar_t));
#else
File->write(L"\n", sizeof(wchar_t));
#endif
}
//! Constructor
CXMLWriterUTF8::CXMLWriterUTF8(IWriteFile* file)
: CXMLWriterCommon(file)
{
#ifdef _DEBUG
setDebugName("CXMLWriter");
#endif
}
//! Writes a xml 1.0 header like <?xml version="1.0"?>
void CXMLWriterUTF8::writeXMLHeader()
{
if (!File)
return;
// No BOM as it's not necessarily utf8
const c8* const p = "<?xml version=\"1.0\"?>";
File->write(p, strlen(p) * sizeof(c8));
writeLineBreak();
TextWrittenLast = false;
}
//! Writes an xml element with maximal 5 attributes
void CXMLWriterUTF8::writeElement(const c8* name, bool empty,
const c8* attr1Name, const c8* attr1Value,
const c8* attr2Name, const c8* attr2Value,
const c8* attr3Name, const c8* attr3Value,
const c8* attr4Name, const c8* attr4Value,
const c8* attr5Name, const c8* attr5Value)
{
if (!File || !name)
return;
if (Tabs > 0)
{
for (int i=0; i<Tabs; ++i)
File->write("\t", sizeof(c8));
}
// write name
File->write("<", sizeof(c8));
File->write(name, strlen(name)*sizeof(c8));
// write attributes
writeAttribute(attr1Name, attr1Value);
writeAttribute(attr2Name, attr2Value);
writeAttribute(attr3Name, attr3Value);
writeAttribute(attr4Name, attr4Value);
writeAttribute(attr5Name, attr5Value);
// write closing tag
if (empty)
File->write(" />", 3*sizeof(c8));
else
{
File->write(">", sizeof(c8));
++Tabs;
}
TextWrittenLast = false;
}
//! Writes an xml element with any number of attributes
void CXMLWriterUTF8::writeElement(const c8* name, bool empty,
core::array<core::stringc> &names,
core::array<core::stringc> &values)
{
if (!File || !name)
return;
if (Tabs > 0)
{
for (int i=0; i<Tabs; ++i)
File->write("\t", sizeof(c8));
}
// write name
File->write("<", sizeof(c8));
File->write(name, strlen(name)*sizeof(c8));
// write attributes
u32 i=0;
for (; i < names.size() && i < values.size(); ++i)
writeAttribute(names[i].c_str(), values[i].c_str());
// write closing tag
if (empty)
File->write(" />", 3*sizeof(c8));
else
{
File->write(">", sizeof(c8));
++Tabs;
}
TextWrittenLast = false;
}
void CXMLWriterUTF8::writeAttribute(const c8* name, const c8* value)
{
if (!name || !value)
return;
File->write(" ", sizeof(c8));
File->write(name, strlen(name)*sizeof(c8));
File->write("=\"", 2*sizeof(c8));
writeText(value);
File->write("\"", sizeof(c8));
}
//! Writes a comment into the xml file
void CXMLWriterUTF8::writeComment(const c8* comment)
{
if (!File || !comment)
return;
File->write("<!--", 4*sizeof(c8));
writeText(comment);
File->write("-->", 3*sizeof(c8));
}
//! Writes the closing tag for an element. Like </foo>
void CXMLWriterUTF8::writeClosingTag(const c8* name)
{
if (!File || !name)
return;
--Tabs;
if (Tabs > 0 && !TextWrittenLast)
{
for (int i=0; i<Tabs; ++i)
File->write("\t", sizeof(c8));
}
File->write("</", 2*sizeof(c8));
File->write(name, strlen(name)*sizeof(c8));
File->write(">", sizeof(c8));
TextWrittenLast = false;
}
//! Writes a text into the file. All occurrences of special characters like
//! & (&amp;), < (&lt;), > (&gt;), and " (&quot;) are automatically replaced.
void CXMLWriterUTF8::writeText(const c8* text)
{
if (!File || !text)
return;
static const CXMLWriterUTF8::XMLSpecialCharacters XMLWSChar[] =
{
{ '&', "&amp;" },
{ '<', "&lt;" },
{ '>', "&gt;" },
{ '"', "&quot;" },
{ '\0', 0 }
};
// TODO: we have to get rid of that reserve call as well as it slows down xml-writing seriously.
// Making a member-variable would work, but a lot of memory would stay around after writing.
// So the correct solution is probably using fixed block here and always write when that is full.
core::stringc s;
s.reserve(strlen(text)+1);
const c8* p = text;
while(*p)
{
// check if it is matching
bool found = false;
for (s32 i=0; XMLWSChar[i].Character != '\0'; ++i)
if (*p == XMLWSChar[i].Character)
{
s.append(XMLWSChar[i].Symbol);
found = true;
break;
}
if (!found)
s.append(*p);
++p;
}
// write new string
File->write(s.c_str(), s.size()*sizeof(c8));
TextWrittenLast = true;
}
//! Writes a line break
void CXMLWriterUTF8::writeLineBreak()
{
if (!File)
return;
#if defined(_IRR_OSX_PLATFORM_)
File->write("\r", sizeof(c8));
#elif defined(_IRR_WINDOWS_API_)
File->write("\r\n", 2*sizeof(c8));
#else
File->write("\n", sizeof(c8));
#endif
}
} // end namespace irr
} // end namespace io
#endif // _IRR_COMPILE_WITH_XML_

View File

@ -1,156 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_XML_WRITER_H_INCLUDED__
#define __C_XML_WRITER_H_INCLUDED__
#include "IXMLWriter.h"
#ifdef _IRR_COMPILE_WITH_XML_
#include <wchar.h>
#include "IWriteFile.h"
namespace irr
{
namespace io
{
//! creates an IXMLReader
IXMLWriter* createIXMLWriter(IWriteFile* file);
//! creates an IXMLReader
IXMLWriterUTF8* createIXMLWriterUTF8(IWriteFile* file);
// Stuff needed by implementations for all character types
// TODO: With some more work it could maybe become a pure template based thing like CXMLReaderImpl
// and replace the type based writer implementations. Sorry, too lazy for now :-/
template<class char_type>
class CXMLWriterCommon
{
public:
//! Constructor
CXMLWriterCommon(IWriteFile* file): File(file), Tabs(0), TextWrittenLast(false)
{
if (File)
File->grab();
}
//! Destructor
virtual ~CXMLWriterCommon()
{
if (File)
File->drop();
}
struct XMLSpecialCharacters
{
char_type Character;
const char_type* Symbol;
};
protected:
IWriteFile* File;
s32 Tabs;
bool TextWrittenLast;
};
//! Implementation providing methods for making it easier to write XML files.
class CXMLWriter : public IXMLWriter, public CXMLWriterCommon<wchar_t>
{
public:
//! Constructor
CXMLWriter(IWriteFile* file);
//! Destructor
virtual ~CXMLWriter() {}
//! Writes a xml 1.0 header like <?xml version="1.0"?>
virtual void writeXMLHeader() _IRR_OVERRIDE_;
//! Writes an xml element with maximal 5 attributes
virtual void writeElement(const wchar_t* name, bool empty=false,
const wchar_t* attr1Name = 0, const wchar_t* attr1Value = 0,
const wchar_t* attr2Name = 0, const wchar_t* attr2Value = 0,
const wchar_t* attr3Name = 0, const wchar_t* attr3Value = 0,
const wchar_t* attr4Name = 0, const wchar_t* attr4Value = 0,
const wchar_t* attr5Name = 0, const wchar_t* attr5Value = 0) _IRR_OVERRIDE_;
//! Writes an xml element with any number of attributes
virtual void writeElement(const wchar_t* name, bool empty,
core::array<core::stringw> &names, core::array<core::stringw> &values) _IRR_OVERRIDE_;
//! Writes a comment into the xml file
virtual void writeComment(const wchar_t* comment) _IRR_OVERRIDE_;
//! Writes the closing tag for an element. Like </foo>
virtual void writeClosingTag(const wchar_t* name) _IRR_OVERRIDE_;
//! Writes a text into the file. All occurrences of special characters like
//! & (&amp;), < (&lt;), > (&gt;), and " (&quot;) are automatically replaced.
virtual void writeText(const wchar_t* text) _IRR_OVERRIDE_;
//! Writes a line break
virtual void writeLineBreak() _IRR_OVERRIDE_;
private:
void writeAttribute(const wchar_t* att, const wchar_t* name);
};
//! Implementation providing methods for making it easier to write XML files.
class CXMLWriterUTF8 : public IXMLWriterUTF8, public CXMLWriterCommon<c8>
{
public:
//! Constructor
CXMLWriterUTF8(IWriteFile* file);
//! Destructor
virtual ~CXMLWriterUTF8() {}
//! Writes a xml 1.0 header like <?xml version="1.0"?>
virtual void writeXMLHeader() _IRR_OVERRIDE_;
//! Writes an xml element with maximal 5 attributes
virtual void writeElement(const c8* name, bool empty=false,
const c8* attr1Name = 0, const c8* attr1Value = 0,
const c8* attr2Name = 0, const c8* attr2Value = 0,
const c8* attr3Name = 0, const c8* attr3Value = 0,
const c8* attr4Name = 0, const c8* attr4Value = 0,
const c8* attr5Name = 0, const c8* attr5Value = 0) _IRR_OVERRIDE_;
//! Writes an xml element with any number of attributes
virtual void writeElement(const c8* name, bool empty,
core::array<core::stringc> &names, core::array<core::stringc> &values) _IRR_OVERRIDE_;
//! Writes a comment into the xml file
virtual void writeComment(const c8* comment) _IRR_OVERRIDE_;
//! Writes the closing tag for an element. Like </foo>
virtual void writeClosingTag(const c8* name) _IRR_OVERRIDE_;
//! Writes a text into the file. All occurrences of special characters like
//! & (&amp;), < (&lt;), > (&gt;), and " (&quot;) are automatically replaced.
virtual void writeText(const c8* text) _IRR_OVERRIDE_;
//! Writes a line break
virtual void writeLineBreak() _IRR_OVERRIDE_;
private:
void writeAttribute(const c8* att, const c8* name);
};
} // end namespace irr
} // end namespace io
#endif // _IRR_COMPILE_WITH_XML_
#endif

View File

@ -1,185 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
#include "irrXML.h"
#ifdef _IRR_COMPILE_WITH_XML_
#include "irrString.h"
#include "irrArray.h"
#include "fast_atof.h"
#include "CXMLReaderImpl.h"
namespace irr
{
namespace io
{
//! Implementation of the file read callback for ordinary files
class CFileReadCallBack : public IFileReadCallBack
{
public:
//! construct from filename
CFileReadCallBack(const char* filename)
: File(0), Size(-1), Close(true)
{
// open file
File = fopen(filename, "rb");
if (File)
getFileSize();
}
//! construct from FILE pointer
CFileReadCallBack(FILE* file)
: File(file), Size(-1), Close(false)
{
if (File)
getFileSize();
}
//! destructor
virtual ~CFileReadCallBack()
{
if (Close && File)
fclose(File);
}
//! Reads an amount of bytes from the file.
virtual int read(void* buffer, int sizeToRead) _IRR_OVERRIDE_
{
if (!File)
return 0;
return (int)fread(buffer, 1, sizeToRead, File);
}
//! Returns size of file in bytes
virtual long getSize() const _IRR_OVERRIDE_
{
return Size;
}
private:
//! retrieves the file size of the open file
void getFileSize()
{
fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);
}
FILE* File;
long Size;
bool Close;
}; // end class CFileReadCallBack
// FACTORY FUNCTIONS:
//! Creates an instance of an UFT-8 or ASCII character xml parser.
IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(const char* filename)
{
return createIrrXMLReader(new CFileReadCallBack(filename), true);
}
//! Creates an instance of an UFT-8 or ASCII character xml parser.
IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(FILE* file)
{
return createIrrXMLReader(new CFileReadCallBack(file), true);
}
//! Creates an instance of an UFT-8 or ASCII character xml parser.
IRRLICHT_API IrrXMLReader* IRRCALLCONV createIrrXMLReader(IFileReadCallBack* callback,
bool deleteCallback)
{
if (callback && (callback->getSize() >= 0))
{
return new CXMLReaderImpl<char, IXMLBase>(callback, deleteCallback);
}
else
{
if(callback && deleteCallback)
delete callback;
return 0;
}
}
//! Creates an instance of an UTF-16 xml parser.
IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(const char* filename)
{
return createIrrXMLReaderUTF16(new CFileReadCallBack(filename), true);
}
//! Creates an instance of an UTF-16 xml parser.
IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(FILE* file)
{
return createIrrXMLReaderUTF16(new CFileReadCallBack(file), true);
}
//! Creates an instance of an UTF-16 xml parser.
IRRLICHT_API IrrXMLReaderUTF16* IRRCALLCONV createIrrXMLReaderUTF16(IFileReadCallBack* callback,
bool deleteCallback)
{
if (callback && (callback->getSize() >= 0))
{
return new CXMLReaderImpl<char16, IXMLBase>(callback, deleteCallback);
}
else
{
if(callback && deleteCallback)
delete callback;
return 0;
}
}
//! Creates an instance of an UTF-32 xml parser.
IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(const char* filename)
{
return createIrrXMLReaderUTF32(new CFileReadCallBack(filename), true);
}
//! Creates an instance of an UTF-32 xml parser.
IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(FILE* file)
{
return createIrrXMLReaderUTF32(new CFileReadCallBack(file), true);
}
//! Creates an instance of an UTF-32 xml parser.
IRRLICHT_API IrrXMLReaderUTF32* IRRCALLCONV createIrrXMLReaderUTF32(
IFileReadCallBack* callback, bool deleteCallback)
{
if (callback && (callback->getSize() >= 0))
{
return new CXMLReaderImpl<char32, IXMLBase>(callback, deleteCallback);
}
else
{
if(callback && deleteCallback)
delete callback;
return 0;
}
}
} // end namespace io
} // end namespace irr
#endif // _IRR_COMPILE_WITH_XML_