diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index c55ff49d4..a1c56811f 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -325,35 +325,96 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) LLNotificationsUtil::add("AIXMLImportParseError", args); return; } - LLXmlTreeNode* root = xml.getRoot(); - if (!root) - { - llwarns << "No root node found in wearable import file: " << filename << llendl; + LLXmlTreeNode* root = xml.getRoot(); + if (!root) + { + llwarns << "No root node found in wearable import file: " << filename << llendl; LLNotificationsUtil::add("AIXMLImportParseError", args); - return; - } + return; + } - //------------------------------------------------------------------------- - // (root) - //------------------------------------------------------------------------- - if (!root->hasName("linden_genepool")) - { - llwarns << "Invalid wearable import file (missing linden_genepool header): " << filename << llendl; + //------------------------------------------------------------------------- + // (root) + //------------------------------------------------------------------------- + if (!root->hasName("linden_genepool")) + { + llwarns << "Invalid wearable import file (missing linden_genepool header): " << filename << llendl; LLNotificationsUtil::add("AIXMLImportRootTypeError", args); return; - } + } static LLStdStringHandle const version_string = LLXmlTree::addAttributeString("version"); std::string version; if (!root->getFastAttributeString(version_string, version) || (version != "1.0")) { - llwarns << "Invalid linden_genepool version: " << version << " in file: " << filename << llendl; + llwarns << "Invalid or incompatible linden_genepool version: " << version << " in file: " << filename << llendl; + args["TAG"] = "version"; + args["VERSIONMAJOR"] = "1"; + LLNotificationsUtil::add("AIXMLImportRootVersionError", args); + return; + } + static LLStdStringHandle const metaversion_string = LLXmlTree::addAttributeString("metaversion"); + std::string metaversion; + U32 metaversion_major; + if (!root->getFastAttributeString(metaversion_string, metaversion)) + { + llwarns << "Invalid linden_genepool metaversion: " << metaversion << " in file: " << filename << llendl; + metaversion_major = 0; + } + else if (!LLStringUtil::convertToU32(metaversion, metaversion_major) || metaversion_major > 1) + { + llwarns << "Invalid or incompatible linden_genepool metaversion: " << metaversion << " in file: " << filename << llendl; + args["TAG"] = "metaversion"; + args["VERSIONMAJOR"] = "1"; LLNotificationsUtil::add("AIXMLImportRootVersionError", args); return; } - //------------------------------------------------------------------------- + //------------------------------------------------------------------------- + // + //------------------------------------------------------------------------- + std::string gridnick; + LLDate date; + bool different_grid = false; // By default assume it was exported on the same grid as we're on now. + bool mixed_grids = false; // Set to true if two different grids (might) share UUIDs. Currently only "secondlife" and "secondlife_beta". + if (metaversion_major >= 1) + { + static LLStdStringHandle const gridnick_string = LLXmlTree::addAttributeString("gridnick"); + static LLStdStringHandle const date_string = LLXmlTree::addAttributeString("date"); + std::string date_s; + bool invalid = true; + LLXmlTreeNode* meta_node = root->getChildByName("meta"); + if (!meta_node) + { + llwarns << "No meta (1) in wearable import file: " << filename << llendl; + } + else if (!meta_node->getFastAttributeString(gridnick_string, gridnick)) + { + llwarns << "meta tag in file: " << filename << " is missing the 'gridnick' parameter." << llendl; + } + else if (!meta_node->getFastAttributeString(date_string, date_s) || !date.fromString(date_s)) + { + llwarns << "meta tag in file: " << filename << " is missing or invalid 'date' parameter." << llendl; + } + else + { + invalid = false; + std::string current_gridnick = gHippoGridManager->getConnectedGrid()->getGridNick(); + different_grid = gridnick != current_gridnick; + mixed_grids = (gridnick == "secondlife" && current_gridnick == "secondlife_beta") || + (gridnick == "secondlife_beta" && current_gridnick == "secondlife"); + } + if (invalid) + { + LLNotificationsUtil::add("AIXMLImportInvalidError", args); + return; + } + } + + static LLStdStringHandle const name_string = LLXmlTree::addAttributeString("name"); + + //------------------------------------------------------------------------- // - //------------------------------------------------------------------------- + //------------------------------------------------------------------------- LLXmlTreeNode* archetype_node = root->getChildByName("archetype"); if (!archetype_node) { @@ -361,13 +422,62 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) LLNotificationsUtil::add("AIXMLImportInvalidError", args); return; } + // Legacy that name="" exists. Using it as human (only) readable type label of contents. Don't use it for anything else because it might not be set. + std::string label = "???"; + if (metaversion_major >= 1) + { + if (!archetype_node->getFastAttributeString(name_string, label)) + { + llwarns << "archetype tag in file: " << filename << " is missing the 'name' parameter." << llendl; + } + } + + //------------------------------------------------------------------------- + // + //------------------------------------------------------------------------- + std::string path; + std::string wearable_name; + std::string wearable_description; + if (metaversion_major >= 1) + { + static LLStdStringHandle const path_string = LLXmlTree::addAttributeString("path"); + static LLStdStringHandle const description_string = LLXmlTree::addAttributeString("description"); + bool invalid = true; + LLXmlTreeNode* meta_node = archetype_node->getChildByName("meta"); + if (!meta_node) + { + llwarns << "No meta (2) in wearable import file: " << filename << llendl; + } + else if (!meta_node->getFastAttributeString(path_string, path)) + { + llwarns << "meta tag in file: " << filename << " is missing the 'path' parameter." << llendl; + } + else if (!meta_node->getFastAttributeString(name_string, wearable_name)) + { + llwarns << "meta tag in file: " << filename << " is missing the 'name' parameter." << llendl; + } + else if (!meta_node->getFastAttributeString(description_string, wearable_description)) + { + llwarns << "meta tag in file: " << filename << " is missing the 'description' parameter." << llendl; + } + else + { + invalid = false; + } + if (invalid) + { + LLNotificationsUtil::add("AIXMLImportInvalidError", args); + return; + } + } // Parse the XML content. static LLStdStringHandle const id_string = LLXmlTree::addAttributeString("id"); static LLStdStringHandle const value_string = LLXmlTree::addAttributeString("value"); static LLStdStringHandle const te_string = LLXmlTree::addAttributeString("te"); static LLStdStringHandle const uuid_string = LLXmlTree::addAttributeString("uuid"); - bool found = false; + bool found_param = false; + bool found_texture = false; for(LLXmlTreeNode* child = archetype_node->getFirstChild(); child; child = archetype_node->getNextChild()) { if (child->hasName("param")) @@ -379,13 +489,13 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) if (!child->getFastAttributeString(id_string, id_s) || !LLStringUtil::convertToU32(id_s, id) || !child->getFastAttributeString(value_string, value_s) || !LLStringUtil::convertToF32(value_s, value)) { - llwarns << "Possible syntax error or corruption for node in " << filename << llendl; - continue; + llwarns << "Possible syntax error or corruption for node in " << filename << llendl; + continue; } LLVisualParam* visual_param = edit_wearable->getVisualParam(id); if (visual_param) { - found = true; + found_param = true; visual_param->setWeight(value, FALSE); } } @@ -398,27 +508,44 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) if (!child->getFastAttributeString(te_string, te_s) || !LLStringUtil::convertToS32(te_s, te) || te < 0 || te >= TEX_NUM_INDICES || !child->getFastAttributeString(uuid_string, uuid_s) || !uuid.set(uuid_s, TRUE)) { - llwarns << "Possible syntax error or corruption for node in " << filename << llendl; - continue; + llwarns << "Possible syntax error or corruption for node in " << filename << llendl; + continue; } ETextureIndex te_index = (ETextureIndex)te; LLWearableType::EType te_wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(te_index); if (te_wearable_type == edit_wearable->getType()) { - found = true; - panel_edit_wearable->setNewImageID(te_index, uuid); + found_texture = true; + if (!different_grid || mixed_grids) + { + panel_edit_wearable->setNewImageID(te_index, uuid); + } } } } - if (found) + if (found_param || found_texture) { edit_wearable->writeToAvatar(gAgentAvatarp); gAgentAvatarp->updateVisualParams(); panel_edit_wearable->updateScrollingPanelUI(); + if (found_texture && different_grid) + { + args["EXPORTGRID"] = gridnick; + args["CURRENTGRID"] = gHippoGridManager->getConnectedGrid()->getGridNick(); + if (mixed_grids) + { + LLNotificationsUtil::add("AIXMLImportMixedGrid", args); + } + else + { + LLNotificationsUtil::add("AIXMLImportDifferentGrid", args); + } + } } else { args["TYPE"] = panel_edit_wearable->LLPanel::getLabel(); + args["ARCHETYPENAME"] = label; LLNotificationsUtil::add("AIXMLImportWearableTypeMismatch", args); } } diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index 5445fc06f..6eb27cb20 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -165,7 +165,7 @@ Import Failure: the file "[FILE]" is not a linden_genepool XML file. icon="alertmodal.tga" name="AIXMLImportRootVersionError" type="alertmodal"> -Import Failure: the file "[FILE]" contains linden_genepool XML data of the wrong version. Version 1.0 is required. +Import Failure: the file "[FILE]" contains linden_genepool XML data with the wrong [TAG]. Version "[VERSIONMAJOR].0" or less is required. + +Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have NOT been applied! + + + +Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have been applied but might not exist here! + + Import Warning: the file "[FILE]" does not contain a wearable of type [TYPE]. -Please select the correct type before importing. +It contains an archetype of type [ARCHETYPENAME]. Please select the correct type before importing.