Xml: introduce helper for attribute parsing.

pull/2966/head
Kim Kulling 2020-08-21 06:45:30 +02:00
parent cb631517a7
commit 7adfe1f2d8
3 changed files with 111 additions and 49 deletions

View File

@ -246,19 +246,18 @@ ai_real ColladaParser::ReadFloatFromTextContent() {
// Reads the contents of the file // Reads the contents of the file
void ColladaParser::ReadContents(XmlNode &node) { void ColladaParser::ReadContents(XmlNode &node) {
for (pugi::xml_node &curNode : node.children()) { for (pugi::xml_node &curNode : node.children()) {
pugi::xml_attribute attr = curNode.attribute("version"); std::string version;
if (attr) { if (XmlParser::getStdStrAttribute(curNode, "version", version)) {
const char *version = attr.as_string();
aiString v; aiString v;
v.Set(version); v.Set(version.c_str());
mAssetMetaData.emplace(AI_METADATA_SOURCE_FORMAT_VERSION, v); mAssetMetaData.emplace(AI_METADATA_SOURCE_FORMAT_VERSION, v);
if (!::strncmp(version, "1.5", 3)) { if (!::strncmp(version.c_str(), "1.5", 3)) {
mFormat = FV_1_5_n; mFormat = FV_1_5_n;
ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n"); ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n");
} else if (!::strncmp(version, "1.4", 3)) { } else if (!::strncmp(version.c_str(), "1.4", 3)) {
mFormat = FV_1_4_n; mFormat = FV_1_4_n;
ASSIMP_LOG_DEBUG("Collada schema version is 1.4.n"); ASSIMP_LOG_DEBUG("Collada schema version is 1.4.n");
} else if (!::strncmp(version, "1.3", 3)) { } else if (!::strncmp(version.c_str(), "1.3", 3)) {
mFormat = FV_1_3_n; mFormat = FV_1_3_n;
ASSIMP_LOG_DEBUG("Collada schema version is 1.3.n"); ASSIMP_LOG_DEBUG("Collada schema version is 1.3.n");
} }
@ -1244,6 +1243,50 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
return; return;
} }
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "color") {
// text content contains 4 floats
const char *content = currentNode.value();
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.r);
SkipSpacesAndLineEnd(&content);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.g);
SkipSpacesAndLineEnd(&content);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.b);
SkipSpacesAndLineEnd(&content);
content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.a);
SkipSpacesAndLineEnd(&content);
} else if (currentName == "texture") {
// get name of source texture/sampler
int attrTex = GetAttribute("texture");
pSampler.mName = mReader->getAttributeValue(attrTex);
// get name of UV source channel. Specification demands it to be there, but some exporters
// don't write it. It will be the default UV channel in case it's missing.
attrTex = TestAttribute("texcoord");
if (attrTex >= 0)
pSampler.mUVChannel = mReader->getAttributeValue(attrTex);
//SkipElement();
// as we've read texture, the color needs to be 1,1,1,1
pColor = aiColor4D(1.f, 1.f, 1.f, 1.f);
} else if (currentName == "technique" ) {
const int _profile = GetAttribute("profile");
const char *profile = mReader->getAttributeValue(_profile);
// Some extensions are quite useful ... ReadSamplerProperties processes
// several extensions in MAYA, OKINO and MAX3D profiles.
if (!::strcmp(profile, "MAYA") || !::strcmp(profile, "MAX3D") || !::strcmp(profile, "OKINO")) {
// get more information on this sampler
ReadSamplerProperties(pSampler);
}
}
}
// Save current element name // Save current element name
const std::string curElem = mReader->getNodeName(); const std::string curElem = mReader->getNodeName();

View File

@ -4,7 +4,6 @@
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -52,22 +52,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
struct find_node_by_name_predicate { struct find_node_by_name_predicate {
std::string mName; std::string mName;
find_node_by_name_predicate(const std::string &name) : find_node_by_name_predicate(const std::string &name) :
mName(name) { mName(name) {
// empty // empty
} }
bool operator()(pugi::xml_node node) const { bool operator()(pugi::xml_node node) const {
return node.name() == mName; return node.name() == mName;
} }
}; };
template<class TNodeType> template <class TNodeType>
struct NodeConverter { struct NodeConverter {
public: public:
static int to_int(TNodeType &node, const char *attribName ) { static int to_int(TNodeType &node, const char *attribName) {
ai_assert(nullptr != attribName); ai_assert(nullptr != attribName);
return node.attribute(attribName).to_int(); return node.attribute(attribName).to_int();
} }
}; };
@ -75,72 +75,73 @@ public:
using XmlNode = pugi::xml_node; using XmlNode = pugi::xml_node;
using XmlAttribute = pugi::xml_attribute; using XmlAttribute = pugi::xml_attribute;
template<class TNodeType> template <class TNodeType>
class TXmlParser { class TXmlParser {
public: public:
TXmlParser() : TXmlParser() :
mDoc(nullptr), mRoot(nullptr), mData() { mDoc(nullptr),
mRoot(nullptr),
mData() {
// empty // empty
} }
~TXmlParser() { ~TXmlParser() {
clear(); clear();
} }
void clear() { void clear() {
mData.resize(0); mData.resize(0);
mRoot = nullptr; mRoot = nullptr;
delete mDoc; delete mDoc;
mDoc = nullptr; mDoc = nullptr;
} }
TNodeType *findNode(const std::string &name) { TNodeType *findNode(const std::string &name) {
if (name.empty()) { if (name.empty()) {
return nullptr; return nullptr;
} }
if (nullptr == mDoc) { if (nullptr == mDoc) {
return nullptr; return nullptr;
} }
find_node_by_name_predicate predicate(name); find_node_by_name_predicate predicate(name);
mCurrent = mDoc->find_node(predicate); mCurrent = mDoc->find_node(predicate);
if (mCurrent.empty()) { if (mCurrent.empty()) {
return nullptr; return nullptr;
} }
return &mCurrent; return &mCurrent;
} }
bool hasNode( const std::string &name ) { bool hasNode(const std::string &name) {
return nullptr != findNode(name); return nullptr != findNode(name);
} }
TNodeType *parse(IOStream *stream) { TNodeType *parse(IOStream *stream) {
if (nullptr == stream) { if (nullptr == stream) {
return nullptr; return nullptr;
} }
mData.resize(stream->FileSize()); mData.resize(stream->FileSize());
stream->Read(&mData[0], mData.size(), 1); stream->Read(&mData[0], mData.size(), 1);
mDoc = new pugi::xml_document(); mDoc = new pugi::xml_document();
pugi::xml_parse_result result = mDoc->load_string(&mData[0]); pugi::xml_parse_result result = mDoc->load_string(&mData[0]);
if (result.status == pugi::status_ok) { if (result.status == pugi::status_ok) {
pugi::xml_node root = *(mDoc->children().begin()); pugi::xml_node root = *(mDoc->children().begin());
mRoot = &root; mRoot = &root;
//mRoot = &mDoc->root();
} }
return mRoot; return mRoot;
} }
pugi::xml_document *getDocument() const { pugi::xml_document *getDocument() const {
return mDoc; return mDoc;
} }
const TNodeType *getRootNode() const { const TNodeType *getRootNode() const {
return mRoot; return mRoot;
} }
TNodeType *getRootNode() { TNodeType *getRootNode() {
@ -157,16 +158,35 @@ public:
return !attr.empty(); return !attr.empty();
} }
private: static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val ) {
pugi::xml_document *mDoc; pugi::xml_attribute attr = xmlNode.attribute(name);
TNodeType *mRoot; if (attr.empty()) {
return false;
}
val = attr.as_int();
return true;
}
static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) {
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_string();
return true;
}
private:
pugi::xml_document *mDoc;
TNodeType *mRoot;
TNodeType mCurrent; TNodeType mCurrent;
std::vector<char> mData; std::vector<char> mData;
}; };
using XmlParser = TXmlParser<pugi::xml_node>; using XmlParser = TXmlParser<pugi::xml_node>;
} // namespace Assimp } // namespace Assimp
#endif // !! INCLUDED_AI_IRRXML_WRAPPER #endif // !! INCLUDED_AI_IRRXML_WRAPPER