feat: support alternative vcm models syntax
This commit is contained in:
@@ -352,21 +352,35 @@ assetload::postfunc assetload::model(
|
||||
throw;
|
||||
}
|
||||
}
|
||||
path = paths.find(file + ".xml");
|
||||
if (io::exists(path)) {
|
||||
auto text = io::read_string(path);
|
||||
try {
|
||||
auto model = vcm::parse(path.string(), text).release();
|
||||
return [=](Assets* assets) {
|
||||
request_textures(loader, *model);
|
||||
assets->store(std::unique_ptr<model::Model>(model), name);
|
||||
};
|
||||
} catch (const parsing_error& err) {
|
||||
std::cerr << err.errorLog() << std::endl;
|
||||
throw;
|
||||
|
||||
std::array<std::string, 2> extensions {
|
||||
".xml",
|
||||
".vcm"
|
||||
};
|
||||
|
||||
path = "";
|
||||
for (const auto& ext : extensions) {
|
||||
auto newPath = paths.find(file + ext);
|
||||
if (io::exists(newPath)) {
|
||||
path = std::move(newPath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("could not to find model " + util::quote(file));
|
||||
if (path.empty()) {
|
||||
throw std::runtime_error("could not to find model " + util::quote(file));
|
||||
}
|
||||
|
||||
auto text = io::read_string(path);
|
||||
try {
|
||||
auto model = vcm::parse(path.string(), text).release();
|
||||
return [=](Assets* assets) {
|
||||
request_textures(loader, *model);
|
||||
assets->store(std::unique_ptr<model::Model>(model), name);
|
||||
};
|
||||
} catch (const parsing_error& err) {
|
||||
std::cerr << err.errorLog() << std::endl;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static void read_anim_file(
|
||||
|
||||
+14
-7
@@ -5,6 +5,7 @@
|
||||
#include "xml.hpp"
|
||||
#include "util/stringutil.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "io/io.hpp"
|
||||
|
||||
using namespace vcm;
|
||||
using namespace xml;
|
||||
@@ -143,12 +144,18 @@ static std::unique_ptr<model::Model> load_model(const xmlelement& root) {
|
||||
std::unique_ptr<model::Model> vcm::parse(
|
||||
std::string_view file, std::string_view src
|
||||
) {
|
||||
auto doc = xml::parse(file, src);
|
||||
const auto& root = *doc->getRoot();
|
||||
if (root.getTag() != "model") {
|
||||
throw std::runtime_error(
|
||||
"'model' tag expected as root, got '" + root.getTag() + "'"
|
||||
);
|
||||
try {
|
||||
auto doc = io::path(std::string(file)).extension() == ".xml"
|
||||
? xml::parse(file, src) : xml::parse_vcm(file, src, "model");
|
||||
const auto& root = *doc->getRoot();
|
||||
if (root.getTag() != "model") {
|
||||
throw std::runtime_error(
|
||||
"'model' tag expected as root, got '" + root.getTag() + "'"
|
||||
);
|
||||
}
|
||||
std::cout << xml::stringify(*doc) << std::endl;
|
||||
return load_model(root);
|
||||
} catch (const parsing_error& err) {
|
||||
throw std::runtime_error(err.errorLog());
|
||||
}
|
||||
return load_model(root);
|
||||
}
|
||||
|
||||
@@ -355,6 +355,83 @@ std::unique_ptr<Document> xml::parse(
|
||||
return parser.parse();
|
||||
}
|
||||
|
||||
namespace {
|
||||
class VcmParser : public BasicParser<char> {
|
||||
public:
|
||||
VcmParser(std::string_view filename, std::string_view source)
|
||||
: BasicParser(filename, source) {
|
||||
document = std::make_unique<Document>("1.0", "UTF-8");
|
||||
hashComment = true;
|
||||
}
|
||||
|
||||
std::string parseValue() {
|
||||
char c = peek();
|
||||
if (c == '"' || c == '\'') {
|
||||
nextChar();
|
||||
return parseString(c);
|
||||
}
|
||||
if (c == '(') {
|
||||
nextChar();
|
||||
// TODO: replace with array parsing after moving to dv::value's
|
||||
std::string value = std::string(readUntil(')'));
|
||||
expect(')');
|
||||
return value;
|
||||
}
|
||||
return std::string(readUntilWhitespace());
|
||||
}
|
||||
|
||||
void parseSubElements(Node& node) {
|
||||
skipWhitespace();
|
||||
while (hasNext()) {
|
||||
if (peek() != '@') {
|
||||
throw error("unexpected character in element");
|
||||
}
|
||||
nextChar();
|
||||
auto subnodePtr = std::make_unique<Node>(parseName());
|
||||
auto subnode = subnodePtr.get();
|
||||
node.add(std::move(subnodePtr));
|
||||
|
||||
skipWhitespace();
|
||||
while (hasNext() && peek() != '@' && peek() != '{' && peek() != '}') {
|
||||
std::string attrname = parseName();
|
||||
skipWhitespace();
|
||||
std::string value = parseValue();
|
||||
subnode->set(attrname, value);
|
||||
skipWhitespace();
|
||||
}
|
||||
if (!hasNext()) {
|
||||
break;
|
||||
}
|
||||
char c = peek();
|
||||
if (c == '{') {
|
||||
nextChar();
|
||||
parseSubElements(*subnode);
|
||||
expect('}');
|
||||
skipWhitespace();
|
||||
} else if (c == '}') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Document> parse(const std::string& rootTag) {
|
||||
auto root = std::make_unique<Node>(rootTag);
|
||||
parseSubElements(*root);
|
||||
document->setRoot(std::move(root));
|
||||
return std::move(document);
|
||||
}
|
||||
private:
|
||||
std::unique_ptr<Document> document;
|
||||
};
|
||||
}
|
||||
|
||||
std::unique_ptr<Document> xml::parse_vcm(
|
||||
std::string_view filename, std::string_view source, std::string_view tag
|
||||
) {
|
||||
VcmParser parser(filename, source);
|
||||
return parser.parse(std::string(tag));
|
||||
}
|
||||
|
||||
inline void newline(
|
||||
std::stringstream& ss, bool nice, const std::string& indentStr, int indent
|
||||
) {
|
||||
|
||||
@@ -126,5 +126,9 @@ namespace xml {
|
||||
std::string_view filename, std::string_view source
|
||||
);
|
||||
|
||||
std::unique_ptr<Document> parse_vcm(
|
||||
std::string_view filename, std::string_view source, std::string_view tag
|
||||
);
|
||||
|
||||
using xmlelement = Node;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ static int l_parse_model(lua::State* L) {
|
||||
auto string = lua::require_lstring(L, 2);
|
||||
auto name = lua::require_string(L, 3);
|
||||
|
||||
if (format == "xml") {
|
||||
if (format == "xml" || format == "vcm") {
|
||||
engine->getAssets()->store(vcm::parse(name, string), name);
|
||||
} else {
|
||||
throw std::runtime_error("unknown format " + util::quote(std::string(format)));
|
||||
|
||||
Reference in New Issue
Block a user