bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, const QString &fname, QString currentPath, bool ignoreErrors) { Q_ASSERT(m_errorDevice); const QChar slash = QLatin1Char('/'); if (!currentPath.isEmpty() && !currentPath.endsWith(slash)) currentPath += slash; QDomDocument document; { QString errorMsg; int errorLine = 0; int errorColumn = 0; if (!document.setContent(inputDevice, &errorMsg, &errorLine, &errorColumn)) { if (ignoreErrors) return true; const QString msg = QString::fromUtf8("RCC Parse Error: '%1' Line: %2 Column: %3 [%4]\n").arg(fname).arg(errorLine).arg(errorColumn).arg(errorMsg); m_errorDevice->write(msg.toUtf8()); return false; } } QDomElement domRoot = document.firstChildElement(m_strings.TAG_RCC).toElement(); if (!domRoot.isNull() && domRoot.tagName() == m_strings.TAG_RCC) { for (QDomNode node = domRoot.firstChild(); !node.isNull(); node = node.nextSibling()) { if (!node.isElement()) continue; QDomElement child = node.toElement(); if (!child.isNull() && child.tagName() == m_strings.TAG_RESOURCE) { QLocale::Language language = QLocale::c().language(); QLocale::Country country = QLocale::c().country(); if (child.hasAttribute(m_strings.ATTRIBUTE_LANG)) { QString attribute = child.attribute(m_strings.ATTRIBUTE_LANG); QLocale lang = QLocale(attribute); language = lang.language(); if (2 == attribute.length()) { // Language only country = QLocale::AnyCountry; } else { country = lang.country(); } } QString prefix; if (child.hasAttribute(m_strings.ATTRIBUTE_PREFIX)) prefix = child.attribute(m_strings.ATTRIBUTE_PREFIX); if (!prefix.startsWith(slash)) prefix.prepend(slash); if (!prefix.endsWith(slash)) prefix += slash; for (QDomNode res = child.firstChild(); !res.isNull(); res = res.nextSibling()) { if (res.isElement() && res.toElement().tagName() == m_strings.TAG_FILE) { QString fileName(res.firstChild().toText().data()); if (fileName.isEmpty()) { const QString msg = QString::fromUtf8("RCC: Warning: Null node in XML of '%1'\n").arg(fname); m_errorDevice->write(msg.toUtf8()); } QString alias; if (res.toElement().hasAttribute(m_strings.ATTRIBUTE_ALIAS)) alias = res.toElement().attribute(m_strings.ATTRIBUTE_ALIAS); else alias = fileName; int compressLevel = m_compressLevel; if (res.toElement().hasAttribute(m_strings.ATTRIBUTE_COMPRESS)) compressLevel = res.toElement().attribute(m_strings.ATTRIBUTE_COMPRESS).toInt(); int compressThreshold = m_compressThreshold; if (res.toElement().hasAttribute(m_strings.ATTRIBUTE_THRESHOLD)) compressThreshold = res.toElement().attribute(m_strings.ATTRIBUTE_THRESHOLD).toInt(); // Special case for -no-compress. Overrides all other settings. if (m_compressLevel == -2) compressLevel = 0; alias = QDir::cleanPath(alias); while (alias.startsWith(QLatin1String("../"))) alias.remove(0, 3); alias = QDir::cleanPath(m_resourceRoot) + prefix + alias; QString absFileName = fileName; if (QDir::isRelativePath(absFileName)) absFileName.prepend(currentPath); QFileInfo file(absFileName); if (!file.exists()) { m_failedResources.push_back(absFileName); const QString msg = QString::fromUtf8("RCC: Error in '%1': Cannot find file '%2'\n").arg(fname).arg(fileName); m_errorDevice->write(msg.toUtf8()); if (ignoreErrors) continue; else return false; } else if (file.isFile()) { const bool arc = addFile(alias, RCCFileInfo(alias.section(slash, -1), file, language, country, RCCFileInfo::NoFlags, compressLevel, compressThreshold) ); if (!arc) m_failedResources.push_back(absFileName); } else { QDir dir; if (file.isDir()) { dir.setPath(file.filePath()); } else { dir.setPath(file.path()); dir.setNameFilters(QStringList(file.fileName())); if (alias.endsWith(file.fileName())) alias = alias.left(alias.length()-file.fileName().length()); } if (!alias.endsWith(slash)) alias += slash; QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories); while (it.hasNext()) { it.next(); QFileInfo child(it.fileInfo()); if (child.fileName() != QLatin1String(".") && child.fileName() != QLatin1String("..")) { const bool arc = addFile(alias + child.fileName(), RCCFileInfo(child.fileName(), child, language, country, RCCFileInfo::NoFlags, compressLevel, compressThreshold) ); if (!arc) m_failedResources.push_back(child.fileName()); } } } } } } } } if (m_root == 0) { const QString msg = QString::fromUtf8("RCC: Warning: No resources in '%1'.\n").arg(fname); m_errorDevice->write(msg.toUtf8()); if (!ignoreErrors && m_format == Binary) { // create dummy entry, otherwise loading qith QResource will crash m_root = new RCCFileInfo(QString(), QFileInfo(), QLocale::C, QLocale::AnyCountry, RCCFileInfo::Directory); } } return true; }
bool LegacyAvatarSerializer::ReadAvatarAppearance(RexLogic::EC_AvatarAppearance& dest, const QDomDocument& source, bool read_mesh) { PROFILE(Avatar_ReadAvatarAppearance); QDomElement avatar = source.firstChildElement("avatar"); if (avatar.isNull()) { RexLogicModule::LogError("No avatar element"); return false; } // Get mesh & skeleton if (read_mesh) { dest.Clear(); QDomElement base_elem = avatar.firstChildElement("base"); if (!base_elem.isNull()) { AvatarAsset mesh; mesh.name_ = base_elem.attribute("mesh").toStdString(); dest.SetMesh(mesh); } // Get skeleton QDomElement skeleton_elem = avatar.firstChildElement("skeleton"); if (!skeleton_elem.isNull()) { AvatarAsset skeleton; skeleton.name_ = skeleton_elem.attribute("name").toStdString(); dest.SetSkeleton(skeleton); } } // Get materials, should be 2 of them uint mat_index = 0; QDomElement material_elem = avatar.firstChildElement("material"); AvatarMaterialVector materials; while (!material_elem.isNull()) { AvatarMaterial material; material.asset_.name_ = material_elem.attribute("name").toStdString(); // Check for texture override QDomElement texture_elem; switch (mat_index) { case 0: texture_elem = avatar.firstChildElement("texture_body"); break; case 1: texture_elem = avatar.firstChildElement("texture_face"); break; } if (!texture_elem.isNull()) { std::string tex_name = texture_elem.attribute("name").toStdString(); if (!tex_name.empty()) { AvatarAsset texture; texture.name_ = tex_name; material.textures_.push_back(texture); } } materials.push_back(material); material_elem = material_elem.nextSiblingElement("material"); ++mat_index; } dest.SetMaterials(materials); // Get main transform QDomElement transform_elem = avatar.firstChildElement("transformation"); if (!transform_elem.isNull()) { Transform trans; trans.position_ = ParseVector3(transform_elem.attribute("position").toStdString()); trans.orientation_ = ParseQuaternion(transform_elem.attribute("rotation").toStdString()); trans.scale_ = ParseVector3(transform_elem.attribute("scale").toStdString()); dest.SetTransform(trans); } // Get attachments QDomElement attachment_elem = avatar.firstChildElement("attachment"); AvatarAttachmentVector attachments; while (!attachment_elem.isNull()) { ReadAttachment(attachments, attachment_elem); attachment_elem = attachment_elem.nextSiblingElement("attachment"); } dest.SetAttachments(attachments); // Get bone modifiers QDomElement bonemodifier_elem = avatar.firstChildElement("dynamic_animation"); BoneModifierSetVector bonemodifiers; while (!bonemodifier_elem.isNull()) { ReadBoneModifierSet(bonemodifiers, bonemodifier_elem); bonemodifier_elem = bonemodifier_elem.nextSiblingElement("dynamic_animation"); } // Get bone modifier parameters QDomElement bonemodifierparam_elem = avatar.firstChildElement("dynamic_animation_parameter"); while (!bonemodifierparam_elem.isNull()) { ReadBoneModifierParameter(bonemodifiers, bonemodifierparam_elem); bonemodifierparam_elem = bonemodifierparam_elem.nextSiblingElement("dynamic_animation_parameter"); } dest.SetBoneModifiers(bonemodifiers); // Get morph modifiers QDomElement morphmodifier_elem = avatar.firstChildElement("morph_modifier"); MorphModifierVector morphmodifiers; while (!morphmodifier_elem.isNull()) { ReadMorphModifier(morphmodifiers, morphmodifier_elem); morphmodifier_elem = morphmodifier_elem.nextSiblingElement("morph_modifier"); } dest.SetMorphModifiers(morphmodifiers); // Get master modifiers QDomElement mastermodifier_elem = avatar.firstChildElement("master_modifier"); MasterModifierVector mastermodifiers; while (!mastermodifier_elem.isNull()) { ReadMasterModifier(mastermodifiers, mastermodifier_elem); mastermodifier_elem = mastermodifier_elem.nextSiblingElement("master_modifier"); } dest.SetMasterModifiers(mastermodifiers); // Get animations QDomElement animation_elem = avatar.firstChildElement("animation"); AnimationDefinitionMap animations; while (!animation_elem.isNull()) { ReadAnimationDefinition(animations, animation_elem); animation_elem = animation_elem.nextSiblingElement("animation"); } dest.SetAnimations(animations); // Get properties QDomElement property_elem = avatar.firstChildElement("property"); while (!property_elem.isNull()) { std::string name = property_elem.attribute("name").toStdString(); std::string value = property_elem.attribute("value").toStdString(); if ((!name.empty()) && (!value.empty())) dest.SetProperty(name, value); property_elem = property_elem.nextSiblingElement("property"); } // Get assetmap (optional, inventory based avatars only) QDomElement assetmap_elem = avatar.firstChildElement("assetmap"); if (!assetmap_elem.isNull()) { AvatarAssetMap new_map; QDomElement asset_elem = assetmap_elem.firstChildElement("asset"); while (!asset_elem.isNull()) { std::string name = asset_elem.attribute("name").toStdString(); std::string id = asset_elem.attribute("id").toStdString(); new_map[name] = id; asset_elem = asset_elem.nextSiblingElement("asset"); } dest.SetAssetMap(new_map); } return true; }
Core::IDocument::OpenResult ResourceFile::load() { m_error_message.clear(); if (m_file_name.isEmpty()) { m_error_message = tr("The file name is empty."); return Core::IDocument::OpenResult::ReadError; } QFile file(m_file_name); if (!file.open(QIODevice::ReadOnly)) { m_error_message = file.errorString(); return Core::IDocument::OpenResult::ReadError; } QByteArray data = file.readAll(); // Detect line ending style m_textFileFormat = Utils::TextFileFormat::detect(data); // we always write UTF-8 when saving m_textFileFormat.codec = QTextCodec::codecForName("UTF-8"); file.close(); clearPrefixList(); QDomDocument doc; QString error_msg; int error_line, error_col; if (!doc.setContent(data, &error_msg, &error_line, &error_col)) { m_error_message = tr("XML error on line %1, col %2: %3") .arg(error_line).arg(error_col).arg(error_msg); return Core::IDocument::OpenResult::CannotHandle; } QDomElement root = doc.firstChildElement(QLatin1String("RCC")); if (root.isNull()) { m_error_message = tr("The <RCC> root element is missing."); return Core::IDocument::OpenResult::CannotHandle; } QDomElement relt = root.firstChildElement(QLatin1String("qresource")); for (; !relt.isNull(); relt = relt.nextSiblingElement(QLatin1String("qresource"))) { QString prefix = fixPrefix(relt.attribute(QLatin1String("prefix"))); if (prefix.isEmpty()) prefix = QString(QLatin1Char('/')); const QString language = relt.attribute(QLatin1String("lang")); const int idx = indexOfPrefix(prefix, language); Prefix * p = 0; if (idx == -1) { p = new Prefix(prefix, language); m_prefix_list.append(p); } else { p = m_prefix_list[idx]; } Q_ASSERT(p); QDomElement felt = relt.firstChildElement(QLatin1String("file")); for (; !felt.isNull(); felt = felt.nextSiblingElement(QLatin1String("file"))) { const QString fileName = absolutePath(felt.text()); const QString alias = felt.attribute(QLatin1String("alias")); File * const file = new File(p, fileName, alias); file->compress = felt.attribute(QLatin1String("compress")); file->threshold = felt.attribute(QLatin1String("threshold")); p->file_list.append(file); } } return Core::IDocument::OpenResult::Success; }