diff --git a/Source/Ember/XmlToEmber.h b/Source/Ember/XmlToEmber.h index 7593c72..da69128 100644 --- a/Source/Ember/XmlToEmber.h +++ b/Source/Ember/XmlToEmber.h @@ -295,14 +295,14 @@ public: } } -/// -/// Parse the specified buffer and place the results in the vector of embers passed in. -/// -/// The buffer to parse -/// Full path and filename, optionally empty -/// The newly constructed embers based on what was parsed -/// True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. Default: true. -/// True if there were no errors, else false. + /// + /// Parse the specified buffer and place the results in the vector of embers passed in. + /// + /// The buffer to parse + /// Full path and filename, optionally empty + /// The newly constructed embers based on what was parsed + /// True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. Default: true. + /// True if there were no errors, else false. bool Parse(byte* buf, const char* filename, vector>& embers, bool useDefaults = true) { char* bn; @@ -378,14 +378,14 @@ public: return true; } -/// -/// Parse the specified file and place the results in the vector of embers passed in. -/// This will strip out ampersands because the Xml parser can't handle them. -/// -/// Full path and filename -/// The newly constructed embers based on what was parsed -/// True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. Default: true. -/// True if there were no errors, else false. + /// + /// Parse the specified file and place the results in the vector of embers passed in. + /// This will strip out ampersands because the Xml parser can't handle them. + /// + /// Full path and filename + /// The newly constructed embers based on what was parsed + /// True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. Default: true. + /// True if there were no errors, else false. bool Parse(const char* filename, vector>& embers, bool useDefaults = true) { const char* loc = __FUNCTION__; @@ -407,13 +407,13 @@ public: return false; } -/// -/// Thin wrapper around converting the string to a numeric value and return a bool indicating success. -/// See error report for errors. -/// -/// The string to convert -/// The converted value -/// True if success, else false. + /// + /// Thin wrapper around converting the string to a numeric value and return a bool indicating success. + /// See error report for errors. + /// + /// The string to convert + /// The converted value + /// True if success, else false. template bool Aton(const char* str, valT& val) { @@ -431,14 +431,13 @@ public: return b; } - -/// -/// Convert an integer to a string. -/// Just a wrapper around _itoa_s() which wraps the result in a std::string. -/// -/// The integer to convert -/// The radix of the integer. Default: 10. -/// The converted string + /// + /// Convert an integer to a string. + /// Just a wrapper around _itoa_s() which wraps the result in a std::string. + /// + /// The integer to convert + /// The radix of the integer. Default: 10. + /// The converted string static string Itos(int i, int radix = 10) { char ch[16]; @@ -450,13 +449,13 @@ public: return string(ch); } -/// -/// Convert an unsigned 64-bit integer to a string. -/// Just a wrapper around _ui64toa_s() which wraps the result in a std::string. -/// -/// The unsigned 64-bit integer to convert -/// The radix of the integer. Default: 10. -/// The converted string + /// + /// Convert an unsigned 64-bit integer to a string. + /// Just a wrapper around _ui64toa_s() which wraps the result in a std::string. + /// + /// The unsigned 64-bit integer to convert + /// The radix of the integer. Default: 10. + /// The converted string static string Itos64(size_t i, int radix = 10) { char ch[64]; @@ -471,13 +470,13 @@ public: static vector m_FlattenNames; private: -/// -/// Scan the file for ember nodes, and parse them out into the vector of embers. -/// -/// The current node to parse -/// The full path and filename -/// The newly constructed embers based on what was parsed -/// True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. + /// + /// Scan the file for ember nodes, and parse them out into the vector of embers. + /// + /// The current node to parse + /// The full path and filename + /// The newly constructed embers based on what was parsed + /// True to use defaults if they are not present in the file, else false to use invalid values as placeholders to indicate the values were not present. void ScanForEmberNodes(xmlNode* curNode, char* parentFile, vector>& embers, bool useDefaults) { bool parseEmberSuccess; @@ -530,12 +529,12 @@ private: } } -/// -/// Parse an ember element. -/// -/// The current node to parse -/// The newly constructed ember based on what was parsed -/// True if there were no errors, else false. + /// + /// Parse an ember element. + /// + /// The current node to parse + /// The newly constructed ember based on what was parsed + /// True if there were no errors, else false. bool ParseEmberElement(xmlNode* emberNode, Ember& currentEmber) { bool ret = true; @@ -640,10 +639,9 @@ private: if (sscanf_s(attStr, "%lu %lu", ¤tEmber.m_FinalRasW, ¤tEmber.m_FinalRasH) != 2) { AddToReport(string(loc) + " : Invalid size attribute " + string(attStr)); - xmlFree(attStr); - //These return statements are bad. One because they are inconsistent with others that just assign defaults. - //Two, because assigning easily guessable defaults is easy and less drastic. - return false; + //Assign reasonable defaults. + currentEmber.m_FinalRasW = 1000; + currentEmber.m_FinalRasH = 1000; } currentEmber.m_OrigFinalRasW = currentEmber.m_FinalRasW; @@ -654,8 +652,8 @@ private: if (sscanf_s(attStr, "%lf %lf", &vals[0], &vals[1]) != 2) { AddToReport(string(loc) + " : Invalid center attribute " + string(attStr)); - xmlFree(attStr); - return false; + vals[0] = 0; + vals[1] = 0; } currentEmber.m_CenterX = T(vals[0]); @@ -686,8 +684,9 @@ private: if (sscanf_s(attStr, "%lf %lf %lf", &vals[0], &vals[1], &vals[2]) != 3) { AddToReport(string(loc) + " : Invalid background attribute " + string(attStr)); - xmlFree(attStr); - return false; + vals[0] = 0; + vals[1] = 0; + vals[2] = 0; } currentEmber.m_Background[0] = T(vals[0]);//[0..1] @@ -1003,8 +1002,8 @@ private: motion.m_MotionFunc = eMotion::MOTION_SAW; else { - AddToReport(string(loc) + " : invalid flame motion function " + func); - return false; + AddToReport(string(loc) + " : invalid flame motion function " + func + ", setting to sin"); + motion.m_MotionFunc = eMotion::MOTION_SIN; } } else if (!Compare(curAtt->name, "zoom")) @@ -1038,8 +1037,7 @@ private: if (sscanf_s(attStr, "%lf %lf %lf", &r, &g, &b) != 3) { AddToReport(string(loc) + " : Invalid flame motion background attribute " + string(attStr)); - xmlFree(attStr); - return false; + r = g = b = 0; } if (r != 0) @@ -1058,8 +1056,7 @@ private: if (sscanf_s(attStr, "%lf %lf", &cx, &cy) != 2) { AddToReport(string(loc) + " : Invalid flame motion center attribute " + string(attStr)); - xmlFree(attStr); - return false; + cx = cy = 0; } if (cx != 0) @@ -1071,8 +1068,6 @@ private: else { AddToReport(string(loc) + " : Unknown flame motion attribute " + string(CCX(curAtt->name))); - xmlFree(attStr); - return false; } xmlFree(attStr); @@ -1089,17 +1084,17 @@ private: if (soloXform >= 0 && i != soloXform) currentEmber.GetXform(i)->m_Opacity = 0;//Will calc the cached adjusted viz value later. - return ErrorReport().empty(); + return true; } -/// -/// Parse a floating point value from an xml attribute and add the value to a EmberMotion object -/// -/// The current attribute -/// The attribute value to parse -/// The flame motion parameter type -/// The flame motion element to add the parameter to -/// True if there were no errors, else false. + /// + /// Parse a floating point value from an xml attribute and add the value to a EmberMotion object + /// + /// The current attribute + /// The attribute value to parse + /// The flame motion parameter type + /// The flame motion element to add the parameter to + /// True if there were no errors, else false. bool AttToEmberMotionFloat(xmlAttrPtr att, const char* attStr, eEmberMotionParam param, EmberMotion& motion) { const char* loc = __FUNCTION__; @@ -1119,13 +1114,13 @@ private: return r; } -/// -/// Parse an xform element. -/// -/// The current node to parse -/// The newly constructed xform based on what was parsed -/// True if this xform is a motion within a parent xform, else false -/// True if there were no errors, else false. + /// + /// Parse an xform element. + /// + /// The current node to parse + /// The newly constructed xform based on what was parsed + /// True if this xform is a motion within a parent xform, else false + /// True if there were no errors, else false. bool ParseXform(xmlNode* childNode, Xform& xform, bool motion, bool fromEmber) { bool success = true; @@ -1368,13 +1363,13 @@ private: return true; } -/// -/// Some Apophysis plugins use an inconsistent naming scheme for the parametric variation variables. -/// This function identifies and converts them to Ember's consistent naming convention. -/// -/// The map of corrected names to search -/// The current Xml node to check -/// The corrected name if one was found, else the passed in name. + /// + /// Some Apophysis plugins use an inconsistent naming scheme for the parametric variation variables. + /// This function identifies and converts them to Ember's consistent naming convention. + /// + /// The map of corrected names to search + /// The current Xml node to check + /// The corrected name if one was found, else the passed in name. static string GetCorrectedParamName(const unordered_map& names, const char* name) { const auto& newName = names.find(ToLower(name)); @@ -1385,15 +1380,15 @@ private: return name; } -/// -/// Some Apophysis plugins use an inconsistent naming scheme for variation names. -/// This function identifies and converts them to Ember's consistent naming convention. -/// It uses some additional intelligence to ensure the variation is the expected one, -/// by examining the rest of the xform for the existence of parameter names. -/// -/// The vector of corrected names to search -/// The current Xml node to check -/// The corrected name if one was found, else the passed in name. + /// + /// Some Apophysis plugins use an inconsistent naming scheme for variation names. + /// This function identifies and converts them to Ember's consistent naming convention. + /// It uses some additional intelligence to ensure the variation is the expected one, + /// by examining the rest of the xform for the existence of parameter names. + /// + /// The vector of corrected names to search + /// The current Xml node to check + /// The corrected name if one was found, else the passed in name. static string GetCorrectedVariationName(vector, vector>>& vec, xmlAttrPtr att) { for (auto& v : vec) @@ -1418,12 +1413,12 @@ private: return string(CCX(att->name)); } -/// -/// Determine if an Xml node contains a given tag. -/// -/// The Xml node to search -/// The node name to search for -/// True if name was found, else false. + /// + /// Determine if an Xml node contains a given tag. + /// + /// The Xml node to search + /// The node name to search for + /// True if name was found, else false. static bool XmlContainsTag(xmlAttrPtr att, const char* name) { xmlAttrPtr temp = att; @@ -1438,15 +1433,15 @@ private: return false; } -/// -/// Parse hexadecimal colors. -/// This can read RGB and RGBA, however only RGB will be stored. -/// -/// The string of hex colors to parse -/// The ember whose palette will be assigned the colors -/// The number of colors present -/// The number of channels in each color -/// True if there were no errors, else false. + /// + /// Parse hexadecimal colors. + /// This can read RGB and RGBA, however only RGB will be stored. + /// + /// The string of hex colors to parse + /// The ember whose palette will be assigned the colors + /// The number of colors present + /// The number of channels in each color + /// True if there were no errors, else false. bool ParseHexColors(char* colstr, Ember& ember, size_t numColors, intmax_t chan) { size_t colorIndex = 0; @@ -1509,15 +1504,15 @@ private: return ok; } -/// -/// Wrapper to parse a numeric Xml string value and convert it. -/// -/// The xml tag to parse -/// The name of the Xml attribute -/// The name of the Xml tag -/// The parsed value -/// Bitwise ANDed with true if name matched str and the conversion succeeded, else false. Used for keeping a running value between successive calls. -/// True if the tag was matched and the conversion succeeded, else false + /// + /// Wrapper to parse a numeric Xml string value and convert it. + /// + /// The xml tag to parse + /// The name of the Xml attribute + /// The name of the Xml tag + /// The parsed value + /// Bitwise ANDed with true if name matched str and the conversion succeeded, else false. Used for keeping a running value between successive calls. + /// True if the tag was matched and the conversion succeeded, else false template bool ParseAndAssign(const xmlChar* name, const char* attStr, const char* str, valT& val, bool& b) { diff --git a/Source/Fractorium/FractoriumMenus.cpp b/Source/Fractorium/FractoriumMenus.cpp index 55193d5..e6d9dfd 100644 --- a/Source/Fractorium/FractoriumMenus.cpp +++ b/Source/Fractorium/FractoriumMenus.cpp @@ -172,6 +172,7 @@ void FractoriumEmberController::OpenAndPrepFiles(const QStringList& filenames EmberFile emberFile; XmlToEmber parser; vector> embers; + vector errors; uint previousSize = append ? uint(m_EmberFile.Size()) : 0u; StopPreviewRender(); emberFile.m_Filename = filenames[0]; @@ -196,13 +197,16 @@ void FractoriumEmberController::OpenAndPrepFiles(const QStringList& filenames m_LastSaveAll = ""; emberFile.m_Embers.insert(emberFile.m_Embers.end(), embers.begin(), embers.end()); + errors = parser.ErrorReport(); } else { - auto errors = parser.ErrorReport(); - m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit); + errors = parser.ErrorReport(); m_Fractorium->ShowCritical("Open Failed", "Could not open file, see info tab for details."); } + + if (!errors.empty()) + m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit); } if (append)