mirror of
https://github.com/minetest/irrlicht.git
synced 2025-06-28 06:20:21 +02:00
Drop XML implementation, related code and dependent features
This commit is contained in:
@ -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
|
||||
|
||||
|
@ -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
@ -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
@ -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
|
@ -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()
|
||||
|
@ -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_;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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_;
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
|
@ -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_
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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_
|
@ -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
|
||||
|
@ -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("&");
|
||||
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
|
@ -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
|
||||
//! & (&), < (<), > (>), and " (") are automatically replaced.
|
||||
void CXMLWriter::writeText(const wchar_t* text)
|
||||
{
|
||||
if (!File || !text)
|
||||
return;
|
||||
|
||||
static const CXMLWriter::XMLSpecialCharacters XMLWSChar[] =
|
||||
{
|
||||
{ L'&', L"&" },
|
||||
{ L'<', L"<" },
|
||||
{ L'>', L">" },
|
||||
{ L'"', L""" },
|
||||
{ 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
|
||||
//! & (&), < (<), > (>), and " (") are automatically replaced.
|
||||
void CXMLWriterUTF8::writeText(const c8* text)
|
||||
{
|
||||
if (!File || !text)
|
||||
return;
|
||||
|
||||
static const CXMLWriterUTF8::XMLSpecialCharacters XMLWSChar[] =
|
||||
{
|
||||
{ '&', "&" },
|
||||
{ '<', "<" },
|
||||
{ '>', ">" },
|
||||
{ '"', """ },
|
||||
{ '\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_
|
@ -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
|
||||
//! & (&), < (<), > (>), and " (") 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
|
||||
//! & (&), < (<), > (>), and " (") 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
|
||||
|
@ -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_
|
Reference in New Issue
Block a user