Updated language gen tool to match vn scene gen style and rollup

This commit is contained in:
2023-02-18 09:57:13 -08:00
parent 73535765ab
commit ff706410c0
17 changed files with 454 additions and 194 deletions

View File

@ -79,10 +79,12 @@ endfunction()
# Language Tool
function(tool_language target in)
add_custom_target(${target}
COMMAND languagegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_ASSETS_BUILD_DIR}"
COMMAND languagegen --input="${DAWN_ASSETS_SOURCE_DIR}/${in}" --output="${DAWN_TOOL_GENERATED_LANG_DIR}/${target}.language"
COMMENT "Generating language set ${target} from ${in}"
DEPENDS languagegen
)
tool_generatedlanguages("${DAWN_TOOL_GENERATED_LANG_DIR}/${target}.language")
add_dependencies(${DAWN_TARGET_NAME} ${target})
endfunction()
# Audio Tool

View File

@ -26,6 +26,7 @@ int32_t GeneratedLanguages::start() {
// Now process each language file
std::map<std::string, std::map<std::string, std::string>> strings;
std::vector<std::string> knownKeys;
auto itFiles = files.begin();
while(itFiles != files.end()) {
@ -84,6 +85,7 @@ int32_t GeneratedLanguages::start() {
File langOut(flags["output"] + FILE_PATH_SEP + "language_" + itLang->first + ".language");
bufferOut.clear();
auto itKeys = knownKeys.begin();
while(itKeys != knownKeys.end()) {
auto key = *itKeys;
@ -97,6 +99,7 @@ int32_t GeneratedLanguages::start() {
}
// Write out.
langOut.mkdirp();
if(!langOut.writeString(bufferOut)) {
std::cout << "Failed to create output file \"" + langOut.filename + "\"" << std::endl;
return 1;

View File

@ -6,31 +6,32 @@
# Texture Build Tool
project(languagegen VERSION 2.0)
add_executable(languagegen)
# Sources
target_sources(languagegen
PRIVATE
${DAWN_SHARED_SOURCES}
${DAWN_TOOL_SOURCES}
LanguageGen.cpp
../../util/DawnTool.cpp
../../util/File.cpp
../../util/file.cpp
../../util/csv.cpp
../../util/xml.cpp
)
# Includes
target_include_directories(languagegen
PUBLIC
${DAWN_SHARED_INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/../../
${DAWN_TOOL_INCLUDES}
${CMAKE_CURRENT_LIST_DIR}
)
# Definitions
target_compile_definitions(languagegen
PUBLIC
DAWN_TOOL_INSTANCE=LanguageGen
DAWN_TOOL_HEADER="LanguageGen.hpp"
)
# Libraries
target_link_libraries(languagegen
PUBLIC
${DAWN_BUILD_HOST_LIBS}

View File

@ -9,162 +9,144 @@
using namespace Dawn;
int32_t LanguageGen::start() {
if(this->args.size() != 3) {
std::cout << "Invalid number of arguments provided to language gen!" << std::endl;
return 1;
std::vector<std::string> LanguageParser::getRequiredAttributes() {
return std::vector<std::string>{ "key" };
}
std::map<std::string, std::string> LanguageParser::getOptionalAttributes() {
return std::map<std::string, std::string>();
}
int32_t LanguageParser::onParse(
Xml *node,
std::map<std::string, std::string> values,
struct LanguageString *out,
std::string *error
) {
out->key = values["key"];
out->text = node->value;
return 0;
}
std::vector<std::string> LanguageGroupParser::getRequiredAttributes() {
return std::vector<std::string>{ "key" };
}
std::map<std::string, std::string> LanguageGroupParser::getOptionalAttributes() {
return std::map<std::string, std::string>();
}
int32_t LanguageGroupParser::onParse(
Xml *node,
std::map<std::string, std::string> values,
struct LanguageGroup *out,
std::string *error
) {
std::string key = values["key"];
out->key += key;
auto it = node->children.begin();
int32_t ret;
while(it != node->children.end()) {
auto c = *it;
if(c->node == "string") {
struct LanguageString string;
ret = (LanguageParser()).parse(c, &string, error);
if(ret != 0) return ret;
string.lang = out->lang;
string.key = out->key + "." + string.key;
out->strings.push_back(string);
} else if(c->node == "group") {
struct LanguageGroup group;
group.key += key + ".";
group.lang = out->lang;
ret = (LanguageGroupParser()).parse(c, &group, error);
if(ret != 0) return ret;
vectorAppend(&out->strings, group.strings);
}
++it;
}
return 0;
}
std::vector<std::string> LanguageRootParser::getRequiredAttributes() {
return std::vector<std::string>{ "lang" };
}
std::map<std::string, std::string> LanguageRootParser::getOptionalAttributes() {
return std::map<std::string, std::string>();
}
int32_t LanguageRootParser::onParse(
Xml *node,
std::map<std::string, std::string> values,
struct LanguageRoot *out,
std::string *error
) {
int32_t ret;
out->lang = values["lang"];
auto it = node->children.begin();
while(it != node->children.end()) {
auto c = *it;
if(c->node == "string") {
struct LanguageString string;
ret = (LanguageParser()).parse(c, &string, error);
if(ret != 0) return ret;
string.lang = out->lang;
out->strings.push_back(string);
} else if(c->node == "group") {
struct LanguageGroup group;
group.lang = out->lang;
ret = (LanguageGroupParser()).parse(c, &group, error);
if(ret != 0) return ret;
vectorAppend(&out->strings, group.strings);
}
++it;
}
auto fileIn = File(this->args[1]);
return 0;
}
std::vector<std::string> LanguageGen::getRequiredFlags() {
return std::vector<std::string>{ "input", "output" };
}
int32_t LanguageGen::start() {
auto fileIn = File(flags["input"]);
std::string buffer;
if(!fileIn.readString(&buffer)) {
std::cout << "Failed to open/read input file " << fileIn.filename << std::endl;
return 1;
}
auto xml = Xml::load(buffer);
std::string error;
struct LanguageRoot root;
// Begin parsing. Start by looking for the <language> tags
std::vector<std::string> languages;
auto itChildren = xml.children.begin();
while(itChildren != xml.children.end()) {
auto child = *itChildren;
if(child->node == "language") {
auto attrName = child->attributes.find("name");
if(attrName == child->attributes.end()) {
std::cout << "Missing name param on language node" << std::endl;
return 1;
}
languages.push_back(attrName->second);
}
++itChildren;
auto ret = (LanguageRootParser()).parse(&xml, &root, &error);
if(ret != 0) {
std::cout << error << std::endl;
return ret;
}
// Now begin actually parsing
std::map<std::string, std::vector<struct LanguageString>> strings;
itChildren = xml.children.begin();
while(itChildren != xml.children.end()) {
auto child = *itChildren;
if(child->node == "group") {
auto ret = this->parseGroup(child, "", &strings);
if(ret != 0) return ret;
} else if(child->node == "string") {
std::cout << "String cannot be a root node" << std::endl;
return 1;
}
++itChildren;
}
// Now we validate each lang has each key.
std::vector<std::string> keys;
auto it = strings.begin();
while(it != strings.end()) {
auto it2 = it->second.begin();
while(it2 != it->second.end()) {
auto key = it2->key;
auto exist = std::find(keys.begin(), keys.end(), key);
if(exist == keys.end()) {
keys.push_back(key);
}
it2++;
}
++it;
}
// Now we actually parse each string, validating as we go.
it = strings.begin();
while(it != strings.end()) {
std::vector<std::string> itKeys;
std::string bufferOut;
auto it2 = it->second.begin();
while(it2 != it->second.end()) {
auto l = *it2;
itKeys.push_back(l.key);
bufferOut += l.key + "|" + l.value + "|";
it2++;
}
File fileOut(this->args[2] + "/language_" + it->first + ".language");
if(!fileOut.mkdirp()) {
std::cout << "Failed to create output folder" << std::endl;
}
if(!fileOut.writeString(bufferOut)) {
std::cout << "Failed to write to output file " << fileOut.filename << std::endl;
return 1;
}
auto it3 = keys.begin();
while(it3 != keys.end()) {
auto key = *it3;
auto inIt = std::find(itKeys.begin(), itKeys.end(), key);
if(inIt == itKeys.end()) {
std::cout << "Locale " << it->first << " missing key " << key << std::endl;
}
it3++;
}
if(itKeys.size() != keys.size()) {
std::cout << "Locale is missing some keys, see above" << std::endl;
return 1;
}
++it;
}
return 0;
}
int32_t LanguageGen::parseString(
Xml *stringNode,
std::string key,
std::map<std::string,std::vector<struct LanguageString>> *strings
) {
auto attrLang = stringNode->attributes.find("lang");
if(attrLang == stringNode->attributes.end()) {
std::cout << "String is missing lang parameter." << std::endl;
return -1;
}
struct LanguageString str;
str.key = key;
str.value = stringNode->value;
auto existing = (*strings).find(attrLang->second);
if(existing == (*strings).end()) {
(*strings).insert(std::make_pair(attrLang->second, std::vector<struct LanguageString>()));
}
(*strings)[attrLang->second].push_back(str);
return 0;
}
int32_t LanguageGen::parseGroup(
Xml *groupNode,
std::string key,
std::map<std::string, std::vector<struct LanguageString>> *strings
) {
int32_t ret;
auto attrKey = groupNode->attributes.find("key");
if(attrKey == groupNode->attributes.end()) {
std::cout << "Group node is missing key" << std::endl;
return 1;
}
if(key.size() > 0) key += ".";
key += attrKey->second;
auto itChildren = groupNode->children.begin();
while(itChildren != groupNode->children.end()) {
auto child = *itChildren;
if(child->node == "string") {
ret = this->parseString(child, key, strings);
if(ret != 0) return ret;
} else if(child->node == "group") {
ret = this->parseGroup(child, key, strings);
if(ret != 0) return ret;
}
++itChildren;
}
// Now dump out the language strings to be picked up later.
ret = languageSaveStrings(flags["output"], root.strings);
if(ret != 0) return ret;
return 0;
}

View File

@ -5,17 +5,62 @@
#pragma once
#include "util/DawnTool.hpp"
#include "util/Xml.hpp"
#include "util/File.hpp"
#include "util/XmlParser.hpp"
#include "util/Language.cpp"
namespace Dawn {
struct LanguageString {
struct LanguageGroup {
std::vector<struct LanguageString> strings;
std::string key;
std::string value;
std::string lang;
};
struct LanguageRoot {
std::string lang;
std::vector<struct LanguageString> strings;
};
class LanguageParser : public XmlParser<struct LanguageString> {
protected:
std::vector<std::string> getRequiredAttributes();
std::map<std::string, std::string> getOptionalAttributes();
int32_t onParse(
Xml *node,
std::map<std::string, std::string> values,
struct LanguageString *out,
std::string *error
);
};
class LanguageGroupParser : public XmlParser<struct LanguageGroup> {
protected:
std::vector<std::string> getRequiredAttributes();
std::map<std::string, std::string> getOptionalAttributes();
int32_t onParse(
Xml *node,
std::map<std::string, std::string> values,
struct LanguageGroup *out,
std::string *error
);
};
class LanguageRootParser : public XmlParser<struct LanguageRoot> {
protected:
std::vector<std::string> getRequiredAttributes();
std::map<std::string, std::string> getOptionalAttributes();
int32_t onParse(
Xml *node,
std::map<std::string, std::string> values,
struct LanguageRoot *out,
std::string *error
) override;
};
class LanguageGen : public DawnTool {
protected:
std::vector<std::string> getRequiredFlags() override;
int32_t parseGroup(
Xml *node,
std::string key,