Merge branch 'master' into FixSkinnedWeightsAfterVertexRemappingOptimization
commit
186d7fd606
|
@ -49,8 +49,8 @@ option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
|
||||||
IF(ASSIMP_HUNTER_ENABLED)
|
IF(ASSIMP_HUNTER_ENABLED)
|
||||||
include("cmake-modules/HunterGate.cmake")
|
include("cmake-modules/HunterGate.cmake")
|
||||||
HunterGate(
|
HunterGate(
|
||||||
URL "https://github.com/cpp-pm/hunter/archive/v0.24.0.tar.gz"
|
URL "https://github.com/cpp-pm/hunter/archive/v0.24.17.tar.gz"
|
||||||
SHA1 "a3d7f4372b1dcd52faa6ff4a3bd5358e1d0e5efd"
|
SHA1 "e6396699e414120e32557fe92db097b7655b760b"
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DASSIMP_USE_HUNTER)
|
add_definitions(-DASSIMP_USE_HUNTER)
|
||||||
|
|
16
Dockerfile
16
Dockerfile
|
@ -1,14 +1,9 @@
|
||||||
FROM ubuntu:14.04
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y ninja-build \
|
||||||
git cmake build-essential software-properties-common
|
git cmake build-essential software-properties-common
|
||||||
|
|
||||||
RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update && apt-get install -y gcc-4.9 g++-4.9 && \
|
RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update
|
||||||
cd /usr/bin && \
|
|
||||||
rm gcc g++ cpp && \
|
|
||||||
ln -s gcc-4.9 gcc && \
|
|
||||||
ln -s g++-4.9 g++ && \
|
|
||||||
ln -s cpp-4.9 cpp
|
|
||||||
|
|
||||||
WORKDIR /opt
|
WORKDIR /opt
|
||||||
|
|
||||||
|
@ -19,7 +14,8 @@ WORKDIR /opt/assimp
|
||||||
|
|
||||||
RUN git checkout master \
|
RUN git checkout master \
|
||||||
&& mkdir build && cd build && \
|
&& mkdir build && cd build && \
|
||||||
cmake \
|
cmake -G 'Ninja' \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DASSIMP_BUILD_ASSIMP_TOOLS=ON \
|
||||||
.. && \
|
.. && \
|
||||||
make && make install
|
ninja -j4 && ninja install
|
||||||
|
|
|
@ -229,14 +229,19 @@ bool MD5Parser::ParseSection(Section &out) {
|
||||||
|
|
||||||
// parse a string, enclosed in quotation marks
|
// parse a string, enclosed in quotation marks
|
||||||
#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \
|
#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \
|
||||||
while ('\"' != *sz) \
|
out.length = 0; \
|
||||||
|
while ('\"' != *sz && '\0' != *sz) \
|
||||||
++sz; \
|
++sz; \
|
||||||
|
if ('\0' != *sz) { \
|
||||||
const char *szStart = ++sz; \
|
const char *szStart = ++sz; \
|
||||||
while ('\"' != *sz) \
|
while ('\"' != *sz && '\0' != *sz) \
|
||||||
++sz; \
|
++sz; \
|
||||||
|
if ('\0' != *sz) { \
|
||||||
const char *szEnd = (sz++); \
|
const char *szEnd = (sz++); \
|
||||||
out.length = (ai_uint32)(szEnd - szStart); \
|
out.length = (ai_uint32)(szEnd - szStart); \
|
||||||
::memcpy(out.data, szStart, out.length); \
|
::memcpy(out.data, szStart, out.length); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
out.data[out.length] = '\0';
|
out.data[out.length] = '\0';
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// .MD5MESH parsing function
|
// .MD5MESH parsing function
|
||||||
|
|
|
@ -274,7 +274,7 @@ void MDLImporter::InternReadFile(const std::string &pFile,
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Check whether we're still inside the valid file range
|
// Check whether we're still inside the valid file range
|
||||||
void MDLImporter::SizeCheck(const void *szPos) {
|
void MDLImporter::SizeCheck(const void *szPos) {
|
||||||
if (!szPos || (const unsigned char *)szPos > this->mBuffer + this->iFileSize) {
|
if (!szPos || (const unsigned char *)szPos > this->mBuffer + this->iFileSize || szPos < this->mBuffer) {
|
||||||
throw DeadlyImportError("Invalid MDL file. The file is too small "
|
throw DeadlyImportError("Invalid MDL file. The file is too small "
|
||||||
"or contains invalid data.");
|
"or contains invalid data.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -703,7 +703,14 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
|
||||||
tex.pcData = bad_texel;
|
tex.pcData = bad_texel;
|
||||||
tex.mHeight = iHeight;
|
tex.mHeight = iHeight;
|
||||||
tex.mWidth = iWidth;
|
tex.mWidth = iWidth;
|
||||||
|
|
||||||
|
try {
|
||||||
ParseTextureColorData(szCurrent, iMasked, &iSkip, &tex);
|
ParseTextureColorData(szCurrent, iMasked, &iSkip, &tex);
|
||||||
|
} catch (...) {
|
||||||
|
// FIX: Important, otherwise the destructor will crash
|
||||||
|
tex.pcData = nullptr;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
// FIX: Important, otherwise the destructor will crash
|
// FIX: Important, otherwise the destructor will crash
|
||||||
tex.pcData = nullptr;
|
tex.pcData = nullptr;
|
||||||
|
|
|
@ -323,7 +323,7 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
aiMesh *pMesh = new aiMesh;
|
std::unique_ptr<aiMesh> pMesh(new aiMesh);
|
||||||
if (!pObjMesh->m_name.empty()) {
|
if (!pObjMesh->m_name.empty()) {
|
||||||
pMesh->mName.Set(pObjMesh->m_name);
|
pMesh->mName.Set(pObjMesh->m_name);
|
||||||
}
|
}
|
||||||
|
@ -385,9 +385,9 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create mesh vertices
|
// Create mesh vertices
|
||||||
createVertexArray(pModel, pData, meshIndex, pMesh, uiIdxCount);
|
createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount);
|
||||||
|
|
||||||
return pMesh;
|
return pMesh.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -498,6 +498,10 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
|
||||||
|
|
||||||
if (vertexIndex) {
|
if (vertexIndex) {
|
||||||
if (!last) {
|
if (!last) {
|
||||||
|
if (pMesh->mNumVertices <= newIndex + 1) {
|
||||||
|
throw DeadlyImportError("OBJ: bad vertex index");
|
||||||
|
}
|
||||||
|
|
||||||
pMesh->mVertices[newIndex + 1] = pMesh->mVertices[newIndex];
|
pMesh->mVertices[newIndex + 1] = pMesh->mVertices[newIndex];
|
||||||
if (!sourceFace->m_normals.empty() && !pModel->mNormals.empty()) {
|
if (!sourceFace->m_normals.empty() && !pModel->mNormals.empty()) {
|
||||||
pMesh->mNormals[newIndex + 1] = pMesh->mNormals[newIndex];
|
pMesh->mNormals[newIndex + 1] = pMesh->mNormals[newIndex];
|
||||||
|
|
|
@ -371,6 +371,15 @@ struct CustomExtension {
|
||||||
CustomExtension& operator=(const CustomExtension&) = default;
|
CustomExtension& operator=(const CustomExtension&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Represents metadata in an glTF2 object
|
||||||
|
struct Extras {
|
||||||
|
std::vector<CustomExtension> mValues;
|
||||||
|
|
||||||
|
inline bool HasExtras() const {
|
||||||
|
return !mValues.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//! Base class for all glTF top-level objects
|
//! Base class for all glTF top-level objects
|
||||||
struct Object {
|
struct Object {
|
||||||
int index; //!< The index of this object within its property container
|
int index; //!< The index of this object within its property container
|
||||||
|
@ -379,7 +388,7 @@ struct Object {
|
||||||
std::string name; //!< The user-defined name of this object
|
std::string name; //!< The user-defined name of this object
|
||||||
|
|
||||||
CustomExtension customExtensions;
|
CustomExtension customExtensions;
|
||||||
CustomExtension extras;
|
Extras extras;
|
||||||
|
|
||||||
//! Objects marked as special are not exported (used to emulate the binary body buffer)
|
//! Objects marked as special are not exported (used to emulate the binary body buffer)
|
||||||
virtual bool IsSpecial() const { return false; }
|
virtual bool IsSpecial() const { return false; }
|
||||||
|
|
|
@ -139,6 +139,18 @@ inline CustomExtension ReadExtensions(const char *name, Value &obj) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Extras ReadExtras(Value &obj) {
|
||||||
|
Extras ret;
|
||||||
|
|
||||||
|
ret.mValues.reserve(obj.MemberCount());
|
||||||
|
for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) {
|
||||||
|
auto &val = it->value;
|
||||||
|
ret.mValues.emplace_back(ReadExtensions(it->name.GetString(), val));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
inline void CopyData(size_t count, const uint8_t *src, size_t src_stride,
|
inline void CopyData(size_t count, const uint8_t *src, size_t src_stride,
|
||||||
uint8_t *dst, size_t dst_stride) {
|
uint8_t *dst, size_t dst_stride) {
|
||||||
if (src_stride == dst_stride) {
|
if (src_stride == dst_stride) {
|
||||||
|
@ -248,7 +260,7 @@ inline void Object::ReadExtensions(Value &val) {
|
||||||
|
|
||||||
inline void Object::ReadExtras(Value &val) {
|
inline void Object::ReadExtras(Value &val) {
|
||||||
if (Value *curExtras = FindObject(val, "extras")) {
|
if (Value *curExtras = FindObject(val, "extras")) {
|
||||||
this->extras = glTF2::ReadExtensions("extras", *curExtras);
|
this->extras = glTF2::ReadExtras(*curExtras);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -654,6 +654,44 @@ namespace glTF2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void WriteExtrasValue(Value &parent, const CustomExtension &value, AssetWriter &w) {
|
||||||
|
Value valueNode;
|
||||||
|
|
||||||
|
if (value.mStringValue.isPresent) {
|
||||||
|
MakeValue(valueNode, value.mStringValue.value.c_str(), w.mAl);
|
||||||
|
} else if (value.mDoubleValue.isPresent) {
|
||||||
|
MakeValue(valueNode, value.mDoubleValue.value, w.mAl);
|
||||||
|
} else if (value.mUint64Value.isPresent) {
|
||||||
|
MakeValue(valueNode, value.mUint64Value.value, w.mAl);
|
||||||
|
} else if (value.mInt64Value.isPresent) {
|
||||||
|
MakeValue(valueNode, value.mInt64Value.value, w.mAl);
|
||||||
|
} else if (value.mBoolValue.isPresent) {
|
||||||
|
MakeValue(valueNode, value.mBoolValue.value, w.mAl);
|
||||||
|
} else if (value.mValues.isPresent) {
|
||||||
|
valueNode.SetObject();
|
||||||
|
for (auto const &subvalue : value.mValues.value) {
|
||||||
|
WriteExtrasValue(valueNode, subvalue, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.AddMember(StringRef(value.name), valueNode, w.mAl);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void WriteExtras(Value &obj, const Extras &extras, AssetWriter &w) {
|
||||||
|
if (!extras.HasExtras()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value extrasNode;
|
||||||
|
extrasNode.SetObject();
|
||||||
|
|
||||||
|
for (auto const &value : extras.mValues) {
|
||||||
|
WriteExtrasValue(extrasNode, value, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.AddMember("extras", extrasNode, w.mAl);
|
||||||
|
}
|
||||||
|
|
||||||
inline void Write(Value& obj, Node& n, AssetWriter& w)
|
inline void Write(Value& obj, Node& n, AssetWriter& w)
|
||||||
{
|
{
|
||||||
if (n.matrix.isPresent) {
|
if (n.matrix.isPresent) {
|
||||||
|
@ -689,6 +727,8 @@ namespace glTF2 {
|
||||||
if(n.skeletons.size()) {
|
if(n.skeletons.size()) {
|
||||||
AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
|
AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WriteExtras(obj, n.extras, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/)
|
inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/)
|
||||||
|
@ -762,7 +802,6 @@ namespace glTF2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline AssetWriter::AssetWriter(Asset& a)
|
inline AssetWriter::AssetWriter(Asset& a)
|
||||||
: mDoc()
|
: mDoc()
|
||||||
, mAsset(a)
|
, mAsset(a)
|
||||||
|
|
|
@ -443,6 +443,61 @@ inline Ref<Accessor> ExportData(Asset &a, std::string &meshName, Ref<Buffer> &bu
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void ExportNodeExtras(const aiMetadataEntry &metadataEntry, aiString name, CustomExtension &value) {
|
||||||
|
|
||||||
|
value.name = name.C_Str();
|
||||||
|
switch (metadataEntry.mType) {
|
||||||
|
case AI_BOOL:
|
||||||
|
value.mBoolValue.value = *static_cast<bool *>(metadataEntry.mData);
|
||||||
|
value.mBoolValue.isPresent = true;
|
||||||
|
break;
|
||||||
|
case AI_INT32:
|
||||||
|
value.mInt64Value.value = *static_cast<int32_t *>(metadataEntry.mData);
|
||||||
|
value.mInt64Value.isPresent = true;
|
||||||
|
break;
|
||||||
|
case AI_UINT64:
|
||||||
|
value.mUint64Value.value = *static_cast<uint64_t *>(metadataEntry.mData);
|
||||||
|
value.mUint64Value.isPresent = true;
|
||||||
|
break;
|
||||||
|
case AI_FLOAT:
|
||||||
|
value.mDoubleValue.value = *static_cast<float *>(metadataEntry.mData);
|
||||||
|
value.mDoubleValue.isPresent = true;
|
||||||
|
break;
|
||||||
|
case AI_DOUBLE:
|
||||||
|
value.mDoubleValue.value = *static_cast<double *>(metadataEntry.mData);
|
||||||
|
value.mDoubleValue.isPresent = true;
|
||||||
|
break;
|
||||||
|
case AI_AISTRING:
|
||||||
|
value.mStringValue.value = static_cast<aiString *>(metadataEntry.mData)->C_Str();
|
||||||
|
value.mStringValue.isPresent = true;
|
||||||
|
break;
|
||||||
|
case AI_AIMETADATA: {
|
||||||
|
const aiMetadata *subMetadata = static_cast<aiMetadata *>(metadataEntry.mData);
|
||||||
|
value.mValues.value.resize(subMetadata->mNumProperties);
|
||||||
|
value.mValues.isPresent = true;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < subMetadata->mNumProperties; ++i) {
|
||||||
|
ExportNodeExtras(subMetadata->mValues[i], subMetadata->mKeys[i], value.mValues.value.at(i));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// AI_AIVECTOR3D not handled
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ExportNodeExtras(const aiMetadata *metadata, Extras &extras) {
|
||||||
|
if (metadata == nullptr || metadata->mNumProperties == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extras.mValues.resize(metadata->mNumProperties);
|
||||||
|
for (unsigned int i = 0; i < metadata->mNumProperties; ++i) {
|
||||||
|
ExportNodeExtras(metadata->mValues[i], metadata->mKeys[i], extras.mValues.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void SetSamplerWrap(SamplerWrap &wrap, aiTextureMapMode map) {
|
inline void SetSamplerWrap(SamplerWrap &wrap, aiTextureMapMode map) {
|
||||||
switch (map) {
|
switch (map) {
|
||||||
case aiTextureMapMode_Clamp:
|
case aiTextureMapMode_Clamp:
|
||||||
|
@ -1375,7 +1430,7 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode *n) {
|
||||||
return node.GetIndex();
|
return node.GetIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Export node and recursively calls ExportNode for all children.
|
* Export node and recursively calls ExportNode for all children.
|
||||||
* Since these nodes are not the root node, we also export the parent Ref<Node>
|
* Since these nodes are not the root node, we also export the parent Ref<Node>
|
||||||
*/
|
*/
|
||||||
|
@ -1386,6 +1441,8 @@ unsigned int glTF2Exporter::ExportNode(const aiNode *n, Ref<Node> &parent) {
|
||||||
node->parent = parent;
|
node->parent = parent;
|
||||||
node->name = name;
|
node->name = name;
|
||||||
|
|
||||||
|
ExportNodeExtras(n->mMetaData, node->extras);
|
||||||
|
|
||||||
if (!n->mTransformation.IsIdentity()) {
|
if (!n->mTransformation.IsIdentity()) {
|
||||||
if (mScene->mNumAnimations > 0 || (mProperties && mProperties->HasPropertyBool("GLTF2_NODE_IN_TRS"))) {
|
if (mScene->mNumAnimations > 0 || (mProperties && mProperties->HasPropertyBool("GLTF2_NODE_IN_TRS"))) {
|
||||||
aiQuaternion quaternion;
|
aiQuaternion quaternion;
|
||||||
|
|
|
@ -1108,11 +1108,9 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseExtras(aiMetadata *metadata, const CustomExtension &extension) {
|
void ParseExtras(aiMetadata* metadata, const Extras& extras) {
|
||||||
if (extension.mValues.isPresent) {
|
for (auto const &value : extras.mValues) {
|
||||||
for (auto const &subExtension : extension.mValues.value) {
|
ParseExtensions(metadata, value);
|
||||||
ParseExtensions(metadata, subExtension);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1134,12 +1132,12 @@ aiNode *glTF2Importer::ImportNode(glTF2::Asset &r, glTF2::Ref<glTF2::Node> &ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.customExtensions || node.extras) {
|
if (node.customExtensions || node.extras.HasExtras()) {
|
||||||
ainode->mMetaData = new aiMetadata;
|
ainode->mMetaData = new aiMetadata;
|
||||||
if (node.customExtensions) {
|
if (node.customExtensions) {
|
||||||
ParseExtensions(ainode->mMetaData, node.customExtensions);
|
ParseExtensions(ainode->mMetaData, node.customExtensions);
|
||||||
}
|
}
|
||||||
if (node.extras) {
|
if (node.extras.HasExtras()) {
|
||||||
ParseExtras(ainode->mMetaData, node.extras);
|
ParseExtras(ainode->mMetaData, node.extras);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
|
||||||
// Executes the post processing step on the given imported data.
|
// Executes the post processing step on the given imported data.
|
||||||
void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) {
|
void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) {
|
||||||
this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
|
this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
|
||||||
|
this->mRemoveEmptyBones = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -172,9 +173,9 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove empty bones
|
// remove empty bones
|
||||||
#ifdef AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES
|
if (mRemoveEmptyBones) {
|
||||||
pMesh->mNumBones = removeEmptyBones(pMesh);
|
pMesh->mNumBones = removeEmptyBones(pMesh);
|
||||||
#endif // AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES
|
}
|
||||||
|
|
||||||
if (!DefaultLogger::isNullLogger()) {
|
if (!DefaultLogger::isNullLogger()) {
|
||||||
ASSIMP_LOG_INFO("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
|
ASSIMP_LOG_INFO("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
|
||||||
|
|
|
@ -133,6 +133,7 @@ public:
|
||||||
|
|
||||||
/** Maximum number of bones influencing any single vertex. */
|
/** Maximum number of bones influencing any single vertex. */
|
||||||
unsigned int mMaxWeights;
|
unsigned int mMaxWeights;
|
||||||
|
bool mRemoveEmptyBones;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* pugixml parser - version 1.12
|
* pugixml parser - version 1.13
|
||||||
* --------------------------------------------------------
|
* --------------------------------------------------------
|
||||||
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||||
* Report bugs and download new versions at https://pugixml.org/
|
* Report bugs and download new versions at https://pugixml.org/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* pugixml parser - version 1.12
|
* pugixml parser - version 1.13
|
||||||
* --------------------------------------------------------
|
* --------------------------------------------------------
|
||||||
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||||
* Report bugs and download new versions at https://pugixml.org/
|
* Report bugs and download new versions at https://pugixml.org/
|
||||||
|
@ -1276,12 +1276,14 @@ PUGI__NS_BEGIN
|
||||||
|
|
||||||
child->parent = parent;
|
child->parent = parent;
|
||||||
|
|
||||||
if (node->next_sibling)
|
xml_node_struct* next = node->next_sibling;
|
||||||
node->next_sibling->prev_sibling_c = child;
|
|
||||||
|
if (next)
|
||||||
|
next->prev_sibling_c = child;
|
||||||
else
|
else
|
||||||
parent->first_child->prev_sibling_c = child;
|
parent->first_child->prev_sibling_c = child;
|
||||||
|
|
||||||
child->next_sibling = node->next_sibling;
|
child->next_sibling = next;
|
||||||
child->prev_sibling_c = node;
|
child->prev_sibling_c = node;
|
||||||
|
|
||||||
node->next_sibling = child;
|
node->next_sibling = child;
|
||||||
|
@ -1293,12 +1295,14 @@ PUGI__NS_BEGIN
|
||||||
|
|
||||||
child->parent = parent;
|
child->parent = parent;
|
||||||
|
|
||||||
if (node->prev_sibling_c->next_sibling)
|
xml_node_struct* prev = node->prev_sibling_c;
|
||||||
node->prev_sibling_c->next_sibling = child;
|
|
||||||
|
if (prev->next_sibling)
|
||||||
|
prev->next_sibling = child;
|
||||||
else
|
else
|
||||||
parent->first_child = child;
|
parent->first_child = child;
|
||||||
|
|
||||||
child->prev_sibling_c = node->prev_sibling_c;
|
child->prev_sibling_c = prev;
|
||||||
child->next_sibling = node;
|
child->next_sibling = node;
|
||||||
|
|
||||||
node->prev_sibling_c = child;
|
node->prev_sibling_c = child;
|
||||||
|
@ -1308,15 +1312,18 @@ PUGI__NS_BEGIN
|
||||||
{
|
{
|
||||||
xml_node_struct* parent = node->parent;
|
xml_node_struct* parent = node->parent;
|
||||||
|
|
||||||
if (node->next_sibling)
|
xml_node_struct* next = node->next_sibling;
|
||||||
node->next_sibling->prev_sibling_c = node->prev_sibling_c;
|
xml_node_struct* prev = node->prev_sibling_c;
|
||||||
else
|
|
||||||
parent->first_child->prev_sibling_c = node->prev_sibling_c;
|
|
||||||
|
|
||||||
if (node->prev_sibling_c->next_sibling)
|
if (next)
|
||||||
node->prev_sibling_c->next_sibling = node->next_sibling;
|
next->prev_sibling_c = prev;
|
||||||
else
|
else
|
||||||
parent->first_child = node->next_sibling;
|
parent->first_child->prev_sibling_c = prev;
|
||||||
|
|
||||||
|
if (prev->next_sibling)
|
||||||
|
prev->next_sibling = next;
|
||||||
|
else
|
||||||
|
parent->first_child = next;
|
||||||
|
|
||||||
node->parent = 0;
|
node->parent = 0;
|
||||||
node->prev_sibling_c = 0;
|
node->prev_sibling_c = 0;
|
||||||
|
@ -1360,39 +1367,46 @@ PUGI__NS_BEGIN
|
||||||
|
|
||||||
inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
|
inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
|
||||||
{
|
{
|
||||||
if (place->next_attribute)
|
xml_attribute_struct* next = place->next_attribute;
|
||||||
place->next_attribute->prev_attribute_c = attr;
|
|
||||||
|
if (next)
|
||||||
|
next->prev_attribute_c = attr;
|
||||||
else
|
else
|
||||||
node->first_attribute->prev_attribute_c = attr;
|
node->first_attribute->prev_attribute_c = attr;
|
||||||
|
|
||||||
attr->next_attribute = place->next_attribute;
|
attr->next_attribute = next;
|
||||||
attr->prev_attribute_c = place;
|
attr->prev_attribute_c = place;
|
||||||
place->next_attribute = attr;
|
place->next_attribute = attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
|
inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
|
||||||
{
|
{
|
||||||
if (place->prev_attribute_c->next_attribute)
|
xml_attribute_struct* prev = place->prev_attribute_c;
|
||||||
place->prev_attribute_c->next_attribute = attr;
|
|
||||||
|
if (prev->next_attribute)
|
||||||
|
prev->next_attribute = attr;
|
||||||
else
|
else
|
||||||
node->first_attribute = attr;
|
node->first_attribute = attr;
|
||||||
|
|
||||||
attr->prev_attribute_c = place->prev_attribute_c;
|
attr->prev_attribute_c = prev;
|
||||||
attr->next_attribute = place;
|
attr->next_attribute = place;
|
||||||
place->prev_attribute_c = attr;
|
place->prev_attribute_c = attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node)
|
inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node)
|
||||||
{
|
{
|
||||||
if (attr->next_attribute)
|
xml_attribute_struct* next = attr->next_attribute;
|
||||||
attr->next_attribute->prev_attribute_c = attr->prev_attribute_c;
|
xml_attribute_struct* prev = attr->prev_attribute_c;
|
||||||
else
|
|
||||||
node->first_attribute->prev_attribute_c = attr->prev_attribute_c;
|
|
||||||
|
|
||||||
if (attr->prev_attribute_c->next_attribute)
|
if (next)
|
||||||
attr->prev_attribute_c->next_attribute = attr->next_attribute;
|
next->prev_attribute_c = prev;
|
||||||
else
|
else
|
||||||
node->first_attribute = attr->next_attribute;
|
node->first_attribute->prev_attribute_c = prev;
|
||||||
|
|
||||||
|
if (prev->next_attribute)
|
||||||
|
prev->next_attribute = next;
|
||||||
|
else
|
||||||
|
node->first_attribute = next;
|
||||||
|
|
||||||
attr->prev_attribute_c = 0;
|
attr->prev_attribute_c = 0;
|
||||||
attr->next_attribute = 0;
|
attr->next_attribute = 0;
|
||||||
|
@ -4707,6 +4721,9 @@ PUGI__NS_BEGIN
|
||||||
// get actual encoding
|
// get actual encoding
|
||||||
xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
|
xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
|
||||||
|
|
||||||
|
// if convert_buffer below throws bad_alloc, we still need to deallocate contents if we own it
|
||||||
|
auto_deleter<void> contents_guard(own ? contents : 0, xml_memory::deallocate);
|
||||||
|
|
||||||
// get private buffer
|
// get private buffer
|
||||||
char_t* buffer = 0;
|
char_t* buffer = 0;
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
|
@ -4714,6 +4731,9 @@ PUGI__NS_BEGIN
|
||||||
// coverity[var_deref_model]
|
// coverity[var_deref_model]
|
||||||
if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory);
|
if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory);
|
||||||
|
|
||||||
|
// after this we either deallocate contents (below) or hold on to it via doc->buffer, so we don't need to guard it
|
||||||
|
contents_guard.release();
|
||||||
|
|
||||||
// delete original buffer if we performed a conversion
|
// delete original buffer if we performed a conversion
|
||||||
if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
|
if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
|
||||||
|
|
||||||
|
@ -5050,7 +5070,7 @@ PUGI__NS_BEGIN
|
||||||
xml_writer_file writer(file);
|
xml_writer_file writer(file);
|
||||||
doc.save(writer, indent, flags, encoding);
|
doc.save(writer, indent, flags, encoding);
|
||||||
|
|
||||||
return ferror(file) == 0;
|
return fflush(file) == 0 && ferror(file) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct name_null_sentry
|
struct name_null_sentry
|
||||||
|
@ -5185,53 +5205,72 @@ namespace pugi
|
||||||
|
|
||||||
PUGI__FN xml_attribute xml_attribute::next_attribute() const
|
PUGI__FN xml_attribute xml_attribute::next_attribute() const
|
||||||
{
|
{
|
||||||
return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute();
|
if (!_attr) return xml_attribute();
|
||||||
|
return xml_attribute(_attr->next_attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN xml_attribute xml_attribute::previous_attribute() const
|
PUGI__FN xml_attribute xml_attribute::previous_attribute() const
|
||||||
{
|
{
|
||||||
return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute();
|
if (!_attr) return xml_attribute();
|
||||||
|
xml_attribute_struct* prev = _attr->prev_attribute_c;
|
||||||
|
return prev->next_attribute ? xml_attribute(prev) : xml_attribute();
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const
|
PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->value) ? _attr->value + 0 : def;
|
if (!_attr) return def;
|
||||||
|
const char_t* value = _attr->value;
|
||||||
|
return value ? value : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN int xml_attribute::as_int(int def) const
|
PUGI__FN int xml_attribute::as_int(int def) const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->value) ? impl::get_value_int(_attr->value) : def;
|
if (!_attr) return def;
|
||||||
|
const char_t* value = _attr->value;
|
||||||
|
return value ? impl::get_value_int(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const
|
PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->value) ? impl::get_value_uint(_attr->value) : def;
|
if (!_attr) return def;
|
||||||
|
const char_t* value = _attr->value;
|
||||||
|
return value ? impl::get_value_uint(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN double xml_attribute::as_double(double def) const
|
PUGI__FN double xml_attribute::as_double(double def) const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->value) ? impl::get_value_double(_attr->value) : def;
|
if (!_attr) return def;
|
||||||
|
const char_t* value = _attr->value;
|
||||||
|
return value ? impl::get_value_double(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN float xml_attribute::as_float(float def) const
|
PUGI__FN float xml_attribute::as_float(float def) const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->value) ? impl::get_value_float(_attr->value) : def;
|
if (!_attr) return def;
|
||||||
|
const char_t* value = _attr->value;
|
||||||
|
return value ? impl::get_value_float(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN bool xml_attribute::as_bool(bool def) const
|
PUGI__FN bool xml_attribute::as_bool(bool def) const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->value) ? impl::get_value_bool(_attr->value) : def;
|
if (!_attr) return def;
|
||||||
|
const char_t* value = _attr->value;
|
||||||
|
return value ? impl::get_value_bool(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PUGIXML_HAS_LONG_LONG
|
#ifdef PUGIXML_HAS_LONG_LONG
|
||||||
PUGI__FN long long xml_attribute::as_llong(long long def) const
|
PUGI__FN long long xml_attribute::as_llong(long long def) const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->value) ? impl::get_value_llong(_attr->value) : def;
|
if (!_attr) return def;
|
||||||
|
const char_t* value = _attr->value;
|
||||||
|
return value ? impl::get_value_llong(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const
|
PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->value) ? impl::get_value_ullong(_attr->value) : def;
|
if (!_attr) return def;
|
||||||
|
const char_t* value = _attr->value;
|
||||||
|
return value ? impl::get_value_ullong(value) : def;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -5242,12 +5281,16 @@ namespace pugi
|
||||||
|
|
||||||
PUGI__FN const char_t* xml_attribute::name() const
|
PUGI__FN const char_t* xml_attribute::name() const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->name) ? _attr->name + 0 : PUGIXML_TEXT("");
|
if (!_attr) return PUGIXML_TEXT("");
|
||||||
|
const char_t* name = _attr->name;
|
||||||
|
return name ? name : PUGIXML_TEXT("");
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN const char_t* xml_attribute::value() const
|
PUGI__FN const char_t* xml_attribute::value() const
|
||||||
{
|
{
|
||||||
return (_attr && _attr->value) ? _attr->value + 0 : PUGIXML_TEXT("");
|
if (!_attr) return PUGIXML_TEXT("");
|
||||||
|
const char_t* value = _attr->value;
|
||||||
|
return value ? value : PUGIXML_TEXT("");
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN size_t xml_attribute::hash_value() const
|
PUGI__FN size_t xml_attribute::hash_value() const
|
||||||
|
@ -5329,6 +5372,13 @@ namespace pugi
|
||||||
return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
|
return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PUGI__FN bool xml_attribute::set_value(const char_t* rhs, size_t sz)
|
||||||
|
{
|
||||||
|
if (!_attr) return false;
|
||||||
|
|
||||||
|
return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, sz);
|
||||||
|
}
|
||||||
|
|
||||||
PUGI__FN bool xml_attribute::set_value(const char_t* rhs)
|
PUGI__FN bool xml_attribute::set_value(const char_t* rhs)
|
||||||
{
|
{
|
||||||
if (!_attr) return false;
|
if (!_attr) return false;
|
||||||
|
@ -5521,7 +5571,9 @@ namespace pugi
|
||||||
|
|
||||||
PUGI__FN const char_t* xml_node::name() const
|
PUGI__FN const char_t* xml_node::name() const
|
||||||
{
|
{
|
||||||
return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT("");
|
if (!_root) return PUGIXML_TEXT("");
|
||||||
|
const char_t* name = _root->name;
|
||||||
|
return name ? name : PUGIXML_TEXT("");
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN xml_node_type xml_node::type() const
|
PUGI__FN xml_node_type xml_node::type() const
|
||||||
|
@ -5531,7 +5583,9 @@ namespace pugi
|
||||||
|
|
||||||
PUGI__FN const char_t* xml_node::value() const
|
PUGI__FN const char_t* xml_node::value() const
|
||||||
{
|
{
|
||||||
return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT("");
|
if (!_root) return PUGIXML_TEXT("");
|
||||||
|
const char_t* value = _root->value;
|
||||||
|
return value ? value : PUGIXML_TEXT("");
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN xml_node xml_node::child(const char_t* name_) const
|
PUGI__FN xml_node xml_node::child(const char_t* name_) const
|
||||||
|
@ -5539,7 +5593,11 @@ namespace pugi
|
||||||
if (!_root) return xml_node();
|
if (!_root) return xml_node();
|
||||||
|
|
||||||
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
||||||
if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
|
{
|
||||||
|
const char_t* iname = i->name;
|
||||||
|
if (iname && impl::strequal(name_, iname))
|
||||||
|
return xml_node(i);
|
||||||
|
}
|
||||||
|
|
||||||
return xml_node();
|
return xml_node();
|
||||||
}
|
}
|
||||||
|
@ -5549,8 +5607,11 @@ namespace pugi
|
||||||
if (!_root) return xml_attribute();
|
if (!_root) return xml_attribute();
|
||||||
|
|
||||||
for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
|
for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
|
||||||
if (i->name && impl::strequal(name_, i->name))
|
{
|
||||||
|
const char_t* iname = i->name;
|
||||||
|
if (iname && impl::strequal(name_, iname))
|
||||||
return xml_attribute(i);
|
return xml_attribute(i);
|
||||||
|
}
|
||||||
|
|
||||||
return xml_attribute();
|
return xml_attribute();
|
||||||
}
|
}
|
||||||
|
@ -5560,7 +5621,11 @@ namespace pugi
|
||||||
if (!_root) return xml_node();
|
if (!_root) return xml_node();
|
||||||
|
|
||||||
for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
|
for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
|
||||||
if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
|
{
|
||||||
|
const char_t* iname = i->name;
|
||||||
|
if (iname && impl::strequal(name_, iname))
|
||||||
|
return xml_node(i);
|
||||||
|
}
|
||||||
|
|
||||||
return xml_node();
|
return xml_node();
|
||||||
}
|
}
|
||||||
|
@ -5575,7 +5640,11 @@ namespace pugi
|
||||||
if (!_root) return xml_node();
|
if (!_root) return xml_node();
|
||||||
|
|
||||||
for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
|
for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
|
||||||
if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
|
{
|
||||||
|
const char_t* iname = i->name;
|
||||||
|
if (iname && impl::strequal(name_, iname))
|
||||||
|
return xml_node(i);
|
||||||
|
}
|
||||||
|
|
||||||
return xml_node();
|
return xml_node();
|
||||||
}
|
}
|
||||||
|
@ -5591,24 +5660,30 @@ namespace pugi
|
||||||
|
|
||||||
// optimistically search from hint up until the end
|
// optimistically search from hint up until the end
|
||||||
for (xml_attribute_struct* i = hint; i; i = i->next_attribute)
|
for (xml_attribute_struct* i = hint; i; i = i->next_attribute)
|
||||||
if (i->name && impl::strequal(name_, i->name))
|
{
|
||||||
|
const char_t* iname = i->name;
|
||||||
|
if (iname && impl::strequal(name_, iname))
|
||||||
{
|
{
|
||||||
// update hint to maximize efficiency of searching for consecutive attributes
|
// update hint to maximize efficiency of searching for consecutive attributes
|
||||||
hint_._attr = i->next_attribute;
|
hint_._attr = i->next_attribute;
|
||||||
|
|
||||||
return xml_attribute(i);
|
return xml_attribute(i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// wrap around and search from the first attribute until the hint
|
// wrap around and search from the first attribute until the hint
|
||||||
// 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails
|
// 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails
|
||||||
for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute)
|
for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute)
|
||||||
if (j->name && impl::strequal(name_, j->name))
|
{
|
||||||
|
const char_t* jname = j->name;
|
||||||
|
if (jname && impl::strequal(name_, jname))
|
||||||
{
|
{
|
||||||
// update hint to maximize efficiency of searching for consecutive attributes
|
// update hint to maximize efficiency of searching for consecutive attributes
|
||||||
hint_._attr = j->next_attribute;
|
hint_._attr = j->next_attribute;
|
||||||
|
|
||||||
return xml_attribute(j);
|
return xml_attribute(j);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return xml_attribute();
|
return xml_attribute();
|
||||||
}
|
}
|
||||||
|
@ -5616,9 +5691,8 @@ namespace pugi
|
||||||
PUGI__FN xml_node xml_node::previous_sibling() const
|
PUGI__FN xml_node xml_node::previous_sibling() const
|
||||||
{
|
{
|
||||||
if (!_root) return xml_node();
|
if (!_root) return xml_node();
|
||||||
|
xml_node_struct* prev = _root->prev_sibling_c;
|
||||||
if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c);
|
return prev->next_sibling ? xml_node(prev) : xml_node();
|
||||||
else return xml_node();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN xml_node xml_node::parent() const
|
PUGI__FN xml_node xml_node::parent() const
|
||||||
|
@ -5645,8 +5719,11 @@ namespace pugi
|
||||||
return _root->value;
|
return _root->value;
|
||||||
|
|
||||||
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
||||||
if (impl::is_text_node(i) && i->value)
|
{
|
||||||
return i->value;
|
const char_t* ivalue = i->value;
|
||||||
|
if (impl::is_text_node(i) && ivalue)
|
||||||
|
return ivalue;
|
||||||
|
}
|
||||||
|
|
||||||
return PUGIXML_TEXT("");
|
return PUGIXML_TEXT("");
|
||||||
}
|
}
|
||||||
|
@ -5658,22 +5735,28 @@ namespace pugi
|
||||||
|
|
||||||
PUGI__FN xml_attribute xml_node::first_attribute() const
|
PUGI__FN xml_attribute xml_node::first_attribute() const
|
||||||
{
|
{
|
||||||
return _root ? xml_attribute(_root->first_attribute) : xml_attribute();
|
if (!_root) return xml_attribute();
|
||||||
|
return xml_attribute(_root->first_attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN xml_attribute xml_node::last_attribute() const
|
PUGI__FN xml_attribute xml_node::last_attribute() const
|
||||||
{
|
{
|
||||||
return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute();
|
if (!_root) return xml_attribute();
|
||||||
|
xml_attribute_struct* first = _root->first_attribute;
|
||||||
|
return first ? xml_attribute(first->prev_attribute_c) : xml_attribute();
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN xml_node xml_node::first_child() const
|
PUGI__FN xml_node xml_node::first_child() const
|
||||||
{
|
{
|
||||||
return _root ? xml_node(_root->first_child) : xml_node();
|
if (!_root) return xml_node();
|
||||||
|
return xml_node(_root->first_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN xml_node xml_node::last_child() const
|
PUGI__FN xml_node xml_node::last_child() const
|
||||||
{
|
{
|
||||||
return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node();
|
if (!_root) return xml_node();
|
||||||
|
xml_node_struct* first = _root->first_child;
|
||||||
|
return first ? xml_node(first->prev_sibling_c) : xml_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN bool xml_node::set_name(const char_t* rhs)
|
PUGI__FN bool xml_node::set_name(const char_t* rhs)
|
||||||
|
@ -5686,6 +5769,16 @@ namespace pugi
|
||||||
return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
|
return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PUGI__FN bool xml_node::set_value(const char_t* rhs, size_t sz)
|
||||||
|
{
|
||||||
|
xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
|
||||||
|
|
||||||
|
if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, sz);
|
||||||
|
}
|
||||||
|
|
||||||
PUGI__FN bool xml_node::set_value(const char_t* rhs)
|
PUGI__FN bool xml_node::set_value(const char_t* rhs)
|
||||||
{
|
{
|
||||||
xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
|
xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
|
||||||
|
@ -6199,12 +6292,22 @@ namespace pugi
|
||||||
if (!_root) return xml_node();
|
if (!_root) return xml_node();
|
||||||
|
|
||||||
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
||||||
if (i->name && impl::strequal(name_, i->name))
|
{
|
||||||
|
const char_t* iname = i->name;
|
||||||
|
if (iname && impl::strequal(name_, iname))
|
||||||
{
|
{
|
||||||
for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
|
for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
|
||||||
if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT("")))
|
{
|
||||||
|
const char_t* aname = a->name;
|
||||||
|
if (aname && impl::strequal(attr_name, aname))
|
||||||
|
{
|
||||||
|
const char_t* avalue = a->value;
|
||||||
|
if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT("")))
|
||||||
return xml_node(i);
|
return xml_node(i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return xml_node();
|
return xml_node();
|
||||||
}
|
}
|
||||||
|
@ -6215,8 +6318,15 @@ namespace pugi
|
||||||
|
|
||||||
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
||||||
for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
|
for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
|
||||||
if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT("")))
|
{
|
||||||
|
const char_t* aname = a->name;
|
||||||
|
if (aname && impl::strequal(attr_name, aname))
|
||||||
|
{
|
||||||
|
const char_t* avalue = a->value;
|
||||||
|
if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT("")))
|
||||||
return xml_node(i);
|
return xml_node(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return xml_node();
|
return xml_node();
|
||||||
}
|
}
|
||||||
|
@ -6230,8 +6340,9 @@ namespace pugi
|
||||||
|
|
||||||
for (xml_node_struct* i = _root; i; i = i->parent)
|
for (xml_node_struct* i = _root; i; i = i->parent)
|
||||||
{
|
{
|
||||||
|
const char_t* iname = i->name;
|
||||||
offset += (i != _root);
|
offset += (i != _root);
|
||||||
offset += i->name ? impl::strlength(i->name) : 0;
|
offset += iname ? impl::strlength(iname) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
string_t result;
|
string_t result;
|
||||||
|
@ -6242,12 +6353,13 @@ namespace pugi
|
||||||
if (j != _root)
|
if (j != _root)
|
||||||
result[--offset] = delimiter;
|
result[--offset] = delimiter;
|
||||||
|
|
||||||
if (j->name)
|
const char_t* jname = j->name;
|
||||||
|
if (jname)
|
||||||
{
|
{
|
||||||
size_t length = impl::strlength(j->name);
|
size_t length = impl::strlength(jname);
|
||||||
|
|
||||||
offset -= length;
|
offset -= length;
|
||||||
memcpy(&result[offset], j->name, length * sizeof(char_t));
|
memcpy(&result[offset], jname, length * sizeof(char_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6285,7 +6397,8 @@ namespace pugi
|
||||||
{
|
{
|
||||||
for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling)
|
for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling)
|
||||||
{
|
{
|
||||||
if (j->name && impl::strequalrange(j->name, path_segment, static_cast<size_t>(path_segment_end - path_segment)))
|
const char_t* jname = j->name;
|
||||||
|
if (jname && impl::strequalrange(jname, path_segment, static_cast<size_t>(path_segment_end - path_segment)))
|
||||||
{
|
{
|
||||||
xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter);
|
xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter);
|
||||||
|
|
||||||
|
@ -6477,68 +6590,84 @@ namespace pugi
|
||||||
PUGI__FN const char_t* xml_text::get() const
|
PUGI__FN const char_t* xml_text::get() const
|
||||||
{
|
{
|
||||||
xml_node_struct* d = _data();
|
xml_node_struct* d = _data();
|
||||||
|
if (!d) return PUGIXML_TEXT("");
|
||||||
return (d && d->value) ? d->value + 0 : PUGIXML_TEXT("");
|
const char_t* value = d->value;
|
||||||
|
return value ? value : PUGIXML_TEXT("");
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN const char_t* xml_text::as_string(const char_t* def) const
|
PUGI__FN const char_t* xml_text::as_string(const char_t* def) const
|
||||||
{
|
{
|
||||||
xml_node_struct* d = _data();
|
xml_node_struct* d = _data();
|
||||||
|
if (!d) return def;
|
||||||
return (d && d->value) ? d->value + 0 : def;
|
const char_t* value = d->value;
|
||||||
|
return value ? value : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN int xml_text::as_int(int def) const
|
PUGI__FN int xml_text::as_int(int def) const
|
||||||
{
|
{
|
||||||
xml_node_struct* d = _data();
|
xml_node_struct* d = _data();
|
||||||
|
if (!d) return def;
|
||||||
return (d && d->value) ? impl::get_value_int(d->value) : def;
|
const char_t* value = d->value;
|
||||||
|
return value ? impl::get_value_int(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const
|
PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const
|
||||||
{
|
{
|
||||||
xml_node_struct* d = _data();
|
xml_node_struct* d = _data();
|
||||||
|
if (!d) return def;
|
||||||
return (d && d->value) ? impl::get_value_uint(d->value) : def;
|
const char_t* value = d->value;
|
||||||
|
return value ? impl::get_value_uint(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN double xml_text::as_double(double def) const
|
PUGI__FN double xml_text::as_double(double def) const
|
||||||
{
|
{
|
||||||
xml_node_struct* d = _data();
|
xml_node_struct* d = _data();
|
||||||
|
if (!d) return def;
|
||||||
return (d && d->value) ? impl::get_value_double(d->value) : def;
|
const char_t* value = d->value;
|
||||||
|
return value ? impl::get_value_double(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN float xml_text::as_float(float def) const
|
PUGI__FN float xml_text::as_float(float def) const
|
||||||
{
|
{
|
||||||
xml_node_struct* d = _data();
|
xml_node_struct* d = _data();
|
||||||
|
if (!d) return def;
|
||||||
return (d && d->value) ? impl::get_value_float(d->value) : def;
|
const char_t* value = d->value;
|
||||||
|
return value ? impl::get_value_float(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN bool xml_text::as_bool(bool def) const
|
PUGI__FN bool xml_text::as_bool(bool def) const
|
||||||
{
|
{
|
||||||
xml_node_struct* d = _data();
|
xml_node_struct* d = _data();
|
||||||
|
if (!d) return def;
|
||||||
return (d && d->value) ? impl::get_value_bool(d->value) : def;
|
const char_t* value = d->value;
|
||||||
|
return value ? impl::get_value_bool(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PUGIXML_HAS_LONG_LONG
|
#ifdef PUGIXML_HAS_LONG_LONG
|
||||||
PUGI__FN long long xml_text::as_llong(long long def) const
|
PUGI__FN long long xml_text::as_llong(long long def) const
|
||||||
{
|
{
|
||||||
xml_node_struct* d = _data();
|
xml_node_struct* d = _data();
|
||||||
|
if (!d) return def;
|
||||||
return (d && d->value) ? impl::get_value_llong(d->value) : def;
|
const char_t* value = d->value;
|
||||||
|
return value ? impl::get_value_llong(value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const
|
PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const
|
||||||
{
|
{
|
||||||
xml_node_struct* d = _data();
|
xml_node_struct* d = _data();
|
||||||
|
if (!d) return def;
|
||||||
return (d && d->value) ? impl::get_value_ullong(d->value) : def;
|
const char_t* value = d->value;
|
||||||
|
return value ? impl::get_value_ullong(value) : def;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PUGI__FN bool xml_text::set(const char_t* rhs, size_t sz)
|
||||||
|
{
|
||||||
|
xml_node_struct* dn = _data_new();
|
||||||
|
|
||||||
|
return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, sz) : false;
|
||||||
|
}
|
||||||
|
|
||||||
PUGI__FN bool xml_text::set(const char_t* rhs)
|
PUGI__FN bool xml_text::set(const char_t* rhs)
|
||||||
{
|
{
|
||||||
xml_node_struct* dn = _data_new();
|
xml_node_struct* dn = _data_new();
|
||||||
|
@ -7294,7 +7423,7 @@ namespace pugi
|
||||||
using impl::auto_deleter; // MSVC7 workaround
|
using impl::auto_deleter; // MSVC7 workaround
|
||||||
auto_deleter<FILE> file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file);
|
auto_deleter<FILE> file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file);
|
||||||
|
|
||||||
return impl::save_file_impl(*this, file.data, indent, flags, encoding);
|
return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const
|
PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const
|
||||||
|
@ -7302,7 +7431,7 @@ namespace pugi
|
||||||
using impl::auto_deleter; // MSVC7 workaround
|
using impl::auto_deleter; // MSVC7 workaround
|
||||||
auto_deleter<FILE> file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file);
|
auto_deleter<FILE> file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file);
|
||||||
|
|
||||||
return impl::save_file_impl(*this, file.data, indent, flags, encoding);
|
return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUGI__FN xml_node xml_document::document_element() const
|
PUGI__FN xml_node xml_document::document_element() const
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* pugixml parser - version 1.12
|
* pugixml parser - version 1.13
|
||||||
* --------------------------------------------------------
|
* --------------------------------------------------------
|
||||||
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||||
* Report bugs and download new versions at https://pugixml.org/
|
* Report bugs and download new versions at https://pugixml.org/
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons
|
// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons
|
||||||
// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits
|
// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits
|
||||||
#ifndef PUGIXML_VERSION
|
#ifndef PUGIXML_VERSION
|
||||||
# define PUGIXML_VERSION 1120 // 1.12
|
# define PUGIXML_VERSION 1130 // 1.13
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Include user configuration file (this can define various configuration macros)
|
// Include user configuration file (this can define various configuration macros)
|
||||||
|
@ -115,6 +115,8 @@
|
||||||
#ifndef PUGIXML_NULL
|
#ifndef PUGIXML_NULL
|
||||||
# if __cplusplus >= 201103
|
# if __cplusplus >= 201103
|
||||||
# define PUGIXML_NULL nullptr
|
# define PUGIXML_NULL nullptr
|
||||||
|
# elif defined(_MSC_VER) && _MSC_VER >= 1600
|
||||||
|
# define PUGIXML_NULL nullptr
|
||||||
# else
|
# else
|
||||||
# define PUGIXML_NULL 0
|
# define PUGIXML_NULL 0
|
||||||
# endif
|
# endif
|
||||||
|
@ -416,6 +418,7 @@ namespace pugi
|
||||||
|
|
||||||
// Set attribute name/value (returns false if attribute is empty or there is not enough memory)
|
// Set attribute name/value (returns false if attribute is empty or there is not enough memory)
|
||||||
bool set_name(const char_t* rhs);
|
bool set_name(const char_t* rhs);
|
||||||
|
bool set_value(const char_t* rhs, size_t sz);
|
||||||
bool set_value(const char_t* rhs);
|
bool set_value(const char_t* rhs);
|
||||||
|
|
||||||
// Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
|
// Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
|
||||||
|
@ -550,6 +553,7 @@ namespace pugi
|
||||||
|
|
||||||
// Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value)
|
// Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value)
|
||||||
bool set_name(const char_t* rhs);
|
bool set_name(const char_t* rhs);
|
||||||
|
bool set_value(const char_t* rhs, size_t sz);
|
||||||
bool set_value(const char_t* rhs);
|
bool set_value(const char_t* rhs);
|
||||||
|
|
||||||
// Add attribute with specified name. Returns added attribute, or empty attribute on errors.
|
// Add attribute with specified name. Returns added attribute, or empty attribute on errors.
|
||||||
|
@ -775,6 +779,7 @@ namespace pugi
|
||||||
bool as_bool(bool def = false) const;
|
bool as_bool(bool def = false) const;
|
||||||
|
|
||||||
// Set text (returns false if object is empty or there is not enough memory)
|
// Set text (returns false if object is empty or there is not enough memory)
|
||||||
|
bool set(const char_t* rhs, size_t sz);
|
||||||
bool set(const char_t* rhs);
|
bool set(const char_t* rhs);
|
||||||
|
|
||||||
// Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
|
// Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
|
||||||
|
|
Loading…
Reference in New Issue