Prelimilary parsing support of references, payload, inherits and specializes

This commit is contained in:
Syoyo Fujita
2022-09-23 23:00:27 +09:00
parent 7db7ab520c
commit 2d9f0536cc
20 changed files with 627 additions and 153 deletions

View File

@@ -121,10 +121,10 @@ static void RegisterStageMetas(
std::map<std::string, AsciiParser::VariableDef> &metas) {
metas.clear();
metas["doc"] = AsciiParser::VariableDef(value::kString, "doc");
metas["documentation"] = AsciiParser::VariableDef(value::kString, "doc"); // alias to 'doc'
metas["documentation"] =
AsciiParser::VariableDef(value::kString, "doc"); // alias to 'doc'
metas["comment"] =
AsciiParser::VariableDef(value::kString, "comment");
metas["comment"] = AsciiParser::VariableDef(value::kString, "comment");
// TODO: both support float and double?
metas["metersPerUnit"] =
@@ -146,7 +146,8 @@ static void RegisterStageMetas(
// Composition arc.
// Type can be array. i.e. asset, asset[]
metas["subLayers"] = AsciiParser::VariableDef(value::kAssetPath, "subLayers", /* allow array type */true);
metas["subLayers"] = AsciiParser::VariableDef(value::kAssetPath, "subLayers",
/* allow array type */ true);
}
static void RegisterPrimMetas(
@@ -156,29 +157,30 @@ static void RegisterPrimMetas(
metas["kind"] = AsciiParser::VariableDef(value::kToken, "kind");
metas["doc"] = AsciiParser::VariableDef(value::kString, "doc");
// Composition arcs
//
// Composition arcs -----------------------
//
// Type can be array. i.e. path, path[]
metas["references"] =
AsciiParser::VariableDef(value::kAssetPath, "references", /* allow array type */true);
metas["references"] = AsciiParser::VariableDef("Reference", "references",
/* allow array type */ true);
metas["inherits"] = AsciiParser::VariableDef(value::kPath, "inherits", true);
metas["payload"] = AsciiParser::VariableDef(value::kAssetPath, "payload", true);
metas["payload"] = AsciiParser::VariableDef("Reference", "payload", true);
metas["specializes"] =
AsciiParser::VariableDef(value::kRelationship, "specializes");
AsciiParser::VariableDef(value::kPath, "specializes", true);
metas["variantSets"] = AsciiParser::VariableDef(value::kToken, "variantSets",
/* allow array type */ true);
// token or token[]
metas["variantSets"] =
AsciiParser::VariableDef(value::kToken, "variantSets", /* allow array type */true);
// Parse as dict. TODO: Use ParseVariants()
metas["variants"] = AsciiParser::VariableDef(value::kDictionary, "variants");
// ------------------------------------------
metas["assetInfo"] =
AsciiParser::VariableDef(value::kDictionary, "assetInfo");
metas["customData"] =
AsciiParser::VariableDef(value::kDictionary, "customData");
// TODO: Use ParseVariants
metas["variants"] = AsciiParser::VariableDef(value::kDictionary, "variants");
metas["active"] = AsciiParser::VariableDef(value::kBool, "active");
// usdSkel
@@ -755,10 +757,30 @@ bool AsciiParser::ReadBasicType(
template <typename T, size_t N>
bool AsciiParser::ParseTupleArray(
std::vector<nonstd::optional<std::array<T, N>>> *result) {
if (!Expect('[')) {
return false;
}
if (!SkipCommentAndWhitespaceAndNewline()) {
return false;
}
// Empty array?
{
char c;
if (!Char1(&c)) {
return false;
}
if (c == ']') {
result->clear();
return true;
}
Rewind(1);
}
if (!SepBy1TupleType<T, N>(',', result)) {
return false;
}
@@ -815,7 +837,6 @@ bool AsciiParser::ReadBasicType(nonstd::optional<Identifier> *value) {
template <>
bool AsciiParser::ReadBasicType(value::token *value) {
// Try triple-quotated string first.
{
StringData sdata;
@@ -1834,6 +1855,25 @@ bool AsciiParser::ParseBasicTypeArray(
return false;
}
if (!SkipCommentAndWhitespaceAndNewline()) {
return false;
}
// Empty array?
{
char c;
if (!Char1(&c)) {
return false;
}
if (c == ']') {
result->clear();
return true;
}
Rewind(1);
}
if (!SepBy1BasicType<T>(',', result)) {
return false;
}
@@ -2058,6 +2098,26 @@ bool AsciiParser::ParseBasicTypeArray(std::vector<Reference> *result) {
result->push_back(ref);
} else {
if (!SkipCommentAndWhitespaceAndNewline()) {
return false;
}
// Empty array?
{
char ce;
if (!Char1(&ce)) {
return false;
}
if (ce == ']') {
result->clear();
return true;
}
Rewind(1);
}
if (!SepBy1BasicType(',', result)) {
return false;
}
@@ -2083,6 +2143,25 @@ bool AsciiParser::ParseBasicTypeArray(std::vector<Path> *result) {
return false;
}
if (!SkipCommentAndWhitespaceAndNewline()) {
return false;
}
// Empty array?
{
char c;
if (!Char1(&c)) {
return false;
}
if (c == ']') {
result->clear();
return true;
}
Rewind(1);
}
if (!SepBy1BasicType(',', result)) {
return false;
}
@@ -2831,7 +2910,6 @@ bool AsciiParser::ReadBasicType(nonstd::optional<value::quatd> *value) {
template <>
bool AsciiParser::ReadBasicType(value::AssetPath *value) {
bool triple_deliminated;
if (ParseAssetIdentifier(value, &triple_deliminated)) {
return true;
@@ -2855,6 +2933,33 @@ bool AsciiParser::ReadBasicType(nonstd::optional<value::AssetPath> *value) {
return false;
}
template <>
bool AsciiParser::ReadBasicType(Reference *value) {
bool triple_deliminated;
if (ParseReference(value, &triple_deliminated)) {
return true;
}
(void)triple_deliminated;
return false;
}
template <>
bool AsciiParser::ReadBasicType(nonstd::optional<Reference> *value) {
if (MaybeNone()) {
(*value) = nonstd::nullopt;
return true;
}
Reference v;
if (ReadBasicType(&v)) {
(*value) = v;
return true;
}
return false;
}
// 1D array
template <typename T>
bool AsciiParser::ReadBasicType(std::vector<T> *value) {
@@ -3136,8 +3241,7 @@ bool AsciiParser::ParseDict(std::map<std::string, MetaVariable> *out_dict) {
}
bool AsciiParser::ParseVariantsElement(std::string *out_key,
std::string *out_var) {
std::string *out_var) {
// variants_element: string name '=' value
// ;
@@ -3149,7 +3253,8 @@ bool AsciiParser::ParseVariantsElement(std::string *out_key,
// must be `string`
if (type_name != value::kString) {
PUSH_ERROR_AND_RETURN("TinyUSDZ only accepts type `string` for `variants` element.");
PUSH_ERROR_AND_RETURN(
"TinyUSDZ only accepts type `string` for `variants` element.");
}
if (!SkipWhitespace()) {
@@ -3361,8 +3466,9 @@ bool AsciiParser::ReadStringLiteral(std::string *literal) {
}
if (!end_with_quotation) {
PUSH_ERROR_AND_RETURN(fmt::format("String literal expected but it does not end with {}.",
single_quote ? "'" : "\""));
PUSH_ERROR_AND_RETURN(
fmt::format("String literal expected but it does not end with {}.",
single_quote ? "'" : "\""));
}
(*literal) = ss.str();
@@ -3457,7 +3563,7 @@ bool AsciiParser::MaybeTripleQuotedString(StringData *str) {
triple_quote[2] == '"') {
// ok
} else if (triple_quote[0] == '\'' && triple_quote[1] == '\'' &&
triple_quote[2] == '\'') {
triple_quote[2] == '\'') {
// ok
single_quote = true;
} else {
@@ -3470,8 +3576,8 @@ bool AsciiParser::MaybeTripleQuotedString(StringData *str) {
auto locinfo = _curr_cursor;
int single_quote_count = 0; // '
int double_quote_count = 0; // "
int single_quote_count = 0; // '
int double_quote_count = 0; // "
bool got_triple_quote{false};
@@ -3551,7 +3657,7 @@ bool AsciiParser::MaybeTripleQuotedString(StringData *str) {
// remove last '"""' or '''
str->single_quote = single_quote;
std::string s = str_buf.str();
if (s.size() > 3) { // just in case
if (s.size() > 3) { // just in case
s.erase(s.size() - 3);
}
str->value = s;
@@ -4601,12 +4707,12 @@ AsciiParser::TryParseTimeSamplesOfArray() {
data.push_back({timeVal, tsValue});
}
DCOUT("Parse TimeSamples of array type success. # of items = " << data.size());
DCOUT(
"Parse TimeSamples of array type success. # of items = " << data.size());
return std::move(data);
}
template <typename T>
value::TimeSamples AsciiParser::ConvertToTimeSamples(
const TimeSampleData<T> &ts) {
@@ -4922,8 +5028,8 @@ bool AsciiParser::ParseCustomMetaValue() {
PUSH_ERROR_AND_RETURN("TODO");
}
bool AsciiParser::ParseAssetIdentifier(value::AssetPath *out, bool *triple_deliminated)
{
bool AsciiParser::ParseAssetIdentifier(value::AssetPath *out,
bool *triple_deliminated) {
// @...@
// or @@@...@@@ (Triple '@'-deliminated asset identifier.)
// @@@ = Path containing '@'. '@@@' in Path is encoded as '\@@@'
@@ -5058,7 +5164,6 @@ bool AsciiParser::ParseAssetIdentifier(value::AssetPath *out, bool *triple_delim
// TODO: Return Path
bool AsciiParser::ParseReference(Reference *out, bool *triple_deliminated) {
/*
Asset reference = AsssetIdentifier + optially followd by prim path
@@ -5135,7 +5240,8 @@ bool AsciiParser::ParseMetaValue(const VariableDef &def, MetaVariable *outvar) {
if (is_array_type) {
std::vector<value::token> value;
if (!ParseBasicTypeArray(&value)) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, fmt::format("token[] expected for `{}`.", varname));
PUSH_ERROR_AND_RETURN_TAG(
kAscii, fmt::format("token[] expected for `{}`.", varname));
}
DCOUT("token[] = " << value);
@@ -5152,7 +5258,6 @@ bool AsciiParser::ParseMetaValue(const VariableDef &def, MetaVariable *outvar) {
var.Set(value);
}
} else if (vartype == "token[]") {
std::vector<value::token> value;
if (!ParseBasicTypeArray(&value)) {
std::string msg = "Token array expected for `" + varname + "`.\n";
@@ -5318,33 +5423,63 @@ bool AsciiParser::ParseMetaValue(const VariableDef &def, MetaVariable *outvar) {
if (is_array_type) {
std::vector<Path> paths;
if (!ParseBasicTypeArray(&paths)) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, fmt::format("Failed to parse `{}` in Prim metadatum.", def.name));
PUSH_ERROR_AND_RETURN_TAG(
kAscii,
fmt::format("Failed to parse `{}` in Prim metadatum.", def.name));
}
var.Set(paths);
var.type = vartype + "[]";
} else {
Path path;
if (!ReadBasicType(&path)) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, fmt::format("Failed to parse `{}` in Prim metadatum.", def.name));
PUSH_ERROR_AND_RETURN_TAG(
kAscii,
fmt::format("Failed to parse `{}` in Prim metadatum.", def.name));
}
}
var.Set(path);
}
} else if (vartype == value::kAssetPath) {
if (is_array_type) {
std::vector<value::AssetPath> paths;
if (!ParseBasicTypeArray(&paths)) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, fmt::format("Failed to parse `{}` in Prim metadataum.", def.name));
PUSH_ERROR_AND_RETURN_TAG(
kAscii,
fmt::format("Failed to parse `{}` in Prim metadataum.", def.name));
}
var.Set(paths);
} else {
value::AssetPath asset_path;
if (!ReadBasicType(&asset_path)) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, fmt::format("Failed to parse `{}` in Prim metadataum.", def.name));
PUSH_ERROR_AND_RETURN_TAG(
kAscii,
fmt::format("Failed to parse `{}` in Prim metadataum.", def.name));
}
var.Set(asset_path);
}
} else if (vartype == "Reference") {
if (is_array_type) {
std::vector<Reference> refs;
if (!ParseBasicTypeArray(&refs)) {
PUSH_ERROR_AND_RETURN_TAG(
kAscii,
fmt::format("Failed to parse `{}` in Prim metadataum.", def.name));
}
var.Set(refs);
} else {
nonstd::optional<Reference> ref;
if (!ReadBasicType(&ref)) {
PUSH_ERROR_AND_RETURN_TAG(
kAscii,
fmt::format("Failed to parse `{}` in Prim metadataum.", def.name));
}
if (ref) {
var.Set(ref.value());
} else {
// None
var.Set(value::ValueBlock());
}
}
} else if (vartype == value::kDictionary) {
DCOUT("Parse dict in meta.");
CustomDataType dict;
@@ -6230,7 +6365,8 @@ bool AsciiParser::ParsePrimProps(std::map<std::string, Property> *props) {
//
if (listop_qual != ListEditQual::ResetToExplicit) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, "List editing qualifier is not allowed for Attribute.");
PUSH_ERROR_AND_RETURN_TAG(
kAscii, "List editing qualifier is not allowed for Attribute.");
}
if (type_name == "uniform") {
@@ -6363,7 +6499,7 @@ bool AsciiParser::ParsePrimProps(std::map<std::string, Property> *props) {
Relation rel;
rel.Set(path);
Property p(rel, /* value typename */type_name, custom_qual);
Property p(rel, /* value typename */ type_name, custom_qual);
(*props)[primattr_name] = p;
@@ -6382,23 +6518,22 @@ bool AsciiParser::ParsePrimProps(std::map<std::string, Property> *props) {
}
// 1D and scalar
#define PARSE_TYPE(__type) \
if ((type_name == value::TypeTrait<__type>::type_name()) && array_qual) { \
if (auto pv = TryParseTimeSamplesOfArray<__type>()) { \
ts = ConvertToTimeSamples<std::vector<__type>>(pv.value()); \
} else { \
PUSH_ERROR_AND_RETURN("Failed to parse timeSample data with type `" \
<< value::TypeTrait<__type>::type_name() \
<< "[]`"); \
} \
} else if (type_name == value::TypeTrait<__type>::type_name()) { \
if (auto pv = TryParseTimeSamples<__type>()) { \
ts = ConvertToTimeSamples<__type>(pv.value()); \
} else { \
PUSH_ERROR_AND_RETURN("Failed to parse timeSample data with type `" \
<< value::TypeTrait<__type>::type_name() \
<< "`"); \
} \
#define PARSE_TYPE(__type) \
if ((type_name == value::TypeTrait<__type>::type_name()) && array_qual) { \
if (auto pv = TryParseTimeSamplesOfArray<__type>()) { \
ts = ConvertToTimeSamples<std::vector<__type>>(pv.value()); \
} else { \
PUSH_ERROR_AND_RETURN("Failed to parse timeSample data with type `" \
<< value::TypeTrait<__type>::type_name() \
<< "[]`"); \
} \
} else if (type_name == value::TypeTrait<__type>::type_name()) { \
if (auto pv = TryParseTimeSamples<__type>()) { \
ts = ConvertToTimeSamples<__type>(pv.value()); \
} else { \
PUSH_ERROR_AND_RETURN("Failed to parse timeSample data with type `" \
<< value::TypeTrait<__type>::type_name() << "`"); \
} \
} else
value::TimeSamples ts;
@@ -6463,7 +6598,8 @@ bool AsciiParser::ParsePrimProps(std::map<std::string, Property> *props) {
} else {
PrimAttrib attr;
// TODO: Refactor. ParseAttrMeta is currently called inside ParseBasicPrimAttr()
// TODO: Refactor. ParseAttrMeta is currently called inside
// ParseBasicPrimAttr()
if (type_name == value::kBool) {
if (!ParseBasicPrimAttr<bool>(array_qual, primattr_name, &attr)) {
return false;
@@ -6722,7 +6858,7 @@ bool AsciiParser::IsStageMeta(const std::string &name) {
return _supported_stage_metas.count(name) ? true : false;
}
#if 0 // TODO: Remove
#if 0 // TODO: Remove
///
/// Parse `class` block.
///
@@ -6917,8 +7053,8 @@ bool AsciiParser::ParseOverBlock(const int64_t primIdx,
#endif
bool AsciiParser::ParseVariantSet(const int64_t primIdx,
const int64_t parentPrimIdx,
const uint32_t depth) {
const int64_t parentPrimIdx,
const uint32_t depth) {
// {
// "variantName0" { ... }
// "variantName1" { ... }
@@ -6932,7 +7068,6 @@ bool AsciiParser::ParseVariantSet(const int64_t primIdx,
return false;
}
while (!Eof()) {
{
char c;
@@ -6951,7 +7086,8 @@ bool AsciiParser::ParseVariantSet(const int64_t primIdx,
// string
std::string variantName;
if (!ReadBasicType(&variantName)) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, "Failed to parse variant name for `variantSet` statement.");
PUSH_ERROR_AND_RETURN_TAG(
kAscii, "Failed to parse variant name for `variantSet` statement.");
}
if (!SkipWhitespace()) {
@@ -6969,7 +7105,6 @@ bool AsciiParser::ParseVariantSet(const int64_t primIdx,
}
while (!Eof()) {
{
char c;
if (!Char1(&c)) {
@@ -6999,8 +7134,7 @@ bool AsciiParser::ParseVariantSet(const int64_t primIdx,
}
if (tok == "variantSet") {
PUSH_ERROR_AND_RETURN(
"Nested `variantSet` is not supported yet.");
PUSH_ERROR_AND_RETURN("Nested `variantSet` is not supported yet.");
}
Specifier child_spec{Specifier::Invalid};
@@ -7015,11 +7149,13 @@ bool AsciiParser::ParseVariantSet(const int64_t primIdx,
if (child_spec != Specifier::Invalid) {
// FIXME: Prim index stacking.
int64_t idx = _prim_idx_assign_fun(parentPrimIdx);
DCOUT("enter parseDef. spec = " << to_string(child_spec) << ", idx = " << idx << ", rootIdx = " << primIdx);
DCOUT("enter parseDef. spec = " << to_string(child_spec) << ", idx = "
<< idx << ", rootIdx = " << primIdx);
// recusive call
if (!ParseBlock(child_spec, idx, primIdx, depth + 1)) {
PUSH_ERROR_AND_RETURN(fmt::format("`{}` block parse failed.", to_string(child_spec)));
PUSH_ERROR_AND_RETURN(
fmt::format("`{}` block parse failed.", to_string(child_spec)));
}
DCOUT(fmt::format("Done parse `{}` block.", to_string(child_spec)));
} else {
@@ -7041,8 +7177,7 @@ bool AsciiParser::ParseVariantSet(const int64_t primIdx,
}
DCOUT("variantSet item parsed.");
}
}
return true;
}
@@ -7059,8 +7194,8 @@ bool AsciiParser::ParseVariantSet(const int64_t primIdx,
/// another USD file or referenced USD)
///
bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
const int64_t parentPrimIdx,
const uint32_t depth) {
const int64_t parentPrimIdx,
const uint32_t depth) {
DCOUT("ParseBlock");
if (!SkipCommentAndWhitespaceAndNewline()) {
@@ -7084,17 +7219,20 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
// Ensure spec and def is same.
if (def == "def") {
if (spec != Specifier::Def) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, "Internal error. Invalid Specifier token combination.");
PUSH_ERROR_AND_RETURN_TAG(
kAscii, "Internal error. Invalid Specifier token combination.");
}
}
if (def == "over") {
if (spec != Specifier::Over) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, "Internal error. Invalid Specifier token combination.");
PUSH_ERROR_AND_RETURN_TAG(
kAscii, "Internal error. Invalid Specifier token combination.");
}
}
if (def == "class") {
if (spec != Specifier::Class) {
PUSH_ERROR_AND_RETURN_TAG(kAscii, "Internal error. Invalid Specifier token combination.");
PUSH_ERROR_AND_RETURN_TAG(
kAscii, "Internal error. Invalid Specifier token combination.");
}
}
@@ -7192,15 +7330,25 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
return false;
}
std::vector<std::pair<ListEditQual, Reference>> references;
#if 0
std::pair<ListEditQual, std::vector<Reference>> references;
std::pair<ListEditQual, std::vector<Reference>> payload;
DCOUT("`references.count` = " + std::to_string(in_metas.count("references")));
// TODO
if (in_metas.count("references")) {
// TODO
// references = GetReferences(args["references"]);
// DCOUT("`references.size` = " + std::to_string(references.size()));
}
// TODO
if (in_metas.count("payload")) {
// TODO
// payload = GetReferences(args["payload"]);
// DCOUT("`payload.size` = " + std::to_string(payload.size()));
}
#endif
std::map<std::string, Property> props;
@@ -7258,8 +7406,7 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
std::string variantName;
if (!ReadBasicType(&variantName)) {
PUSH_ERROR_AND_RETURN(
"Failed to parse `variantSet` statement.");
PUSH_ERROR_AND_RETURN("Failed to parse `variantSet` statement.");
}
DCOUT("variantName = " << variantName);
@@ -7277,8 +7424,7 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
}
if (!ParseVariantSet(primIdx, parentPrimIdx, depth)) {
PUSH_ERROR_AND_RETURN(
"Failed to parse `variantSet` statement.");
PUSH_ERROR_AND_RETURN("Failed to parse `variantSet` statement.");
}
continue;
@@ -7288,7 +7434,6 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
return false;
}
Specifier child_spec{Specifier::Invalid};
if (tok == "def") {
child_spec = Specifier::Def;
@@ -7300,11 +7445,13 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
if (child_spec != Specifier::Invalid) {
int64_t idx = _prim_idx_assign_fun(parentPrimIdx);
DCOUT("enter parseDef. spec = " << to_string(child_spec) << ", idx = " << idx << ", rootIdx = " << primIdx);
DCOUT("enter parseDef. spec = " << to_string(child_spec) << ", idx = "
<< idx << ", rootIdx = " << primIdx);
// recusive call
if (!ParseBlock(child_spec, idx, primIdx, depth + 1)) {
PUSH_ERROR_AND_RETURN(fmt::format("`{}` block parse failed.", to_string(child_spec)));
PUSH_ERROR_AND_RETURN(
fmt::format("`{}` block parse failed.", to_string(child_spec)));
}
DCOUT(fmt::format("Done parse `{}` block.", to_string(child_spec)));
} else {
@@ -7325,10 +7472,8 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
if (prim_type.empty()) {
// No Prim type specified. Treat it as Model
// TODO: support `references` and infer prim type from referenced asset.
pTy = "Model";
}
if (_prim_construct_fun_map.count(pTy)) {
@@ -7337,7 +7482,7 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
Path fullpath(GetCurrentPath(), "");
Path pname(prim_name, "");
nonstd::expected<bool, std::string> ret = construct_fun(
fullpath, spec, pname, primIdx, parentPrimIdx, props, references, in_metas);
fullpath, spec, pname, primIdx, parentPrimIdx, props, in_metas);
if (!ret) {
// construction failed.
@@ -7345,7 +7490,9 @@ bool AsciiParser::ParseBlock(const Specifier spec, const int64_t primIdx,
"` failed: " + ret.error());
}
} else {
PUSH_WARN(fmt::format("TODO: Unsupported/Unimplemented Prim type: `{}`. Skipping parsing.", pTy));
PUSH_WARN(fmt::format(
"TODO: Unsupported/Unimplemented Prim type: `{}`. Skipping parsing.",
pTy));
}
PopPath();

View File

@@ -246,7 +246,7 @@ class AsciiParser {
std::function<nonstd::expected<bool, std::string>(
const Path &full_path, const Specifier spec, const Path &prim_name, const int64_t primIdx, const int64_t parentPrimIdx,
const std::map<std::string, Property> &properties,
std::vector<std::pair<ListEditQual, Reference>> &references, const PrimMetaInput &in_meta)>;
const PrimMetaInput &in_meta)>;
///
/// Register Prim construction callback function.

View File

@@ -4,6 +4,7 @@
//
#include "pprinter.hh"
#include "prim-types.hh"
#include "prim-pprint.hh"
#include "usdShade.hh"
#include "value-pprint.hh"
#include "str-util.hh"
@@ -39,6 +40,26 @@ std::ostream &operator<<(std::ostream &ofs, const tinyusdz::Path &v) {
return ofs;
}
std::ostream &operator<<(std::ostream &ofs, const tinyusdz::Reference &v) {
ofs << v.asset_path;
if (v.prim_path.IsValid()) {
ofs << v.prim_path;
}
return ofs;
}
std::ostream &operator<<(std::ostream &ofs, const tinyusdz::Payload &v) {
ofs << v.asset_path;
if (v._prim_path.IsValid()) {
ofs << v._prim_path;
}
return ofs;
}
std::ostream &operator<<(std::ostream &ofs, const tinyusdz::StringData &v) {
std::string delim = v.single_quote ? "'" : "\"";
@@ -93,14 +114,6 @@ void SetIndentString(const std::string &s) {
namespace {
#if 0
// TODO: Triple @
std::string aquote(const value::AssetPath &p) {
return wquote(p.GetAssetPath(), "@", "@");
}
#endif
std::string to_string(const double &v) {
std::stringstream ss;
ss << v;
@@ -232,6 +245,53 @@ std::string print_variantsMap(const VariantsMap &m, const uint32_t indent) {
return ss.str();
}
std::string print_references(const prim::ReferenceList &references, const uint32_t indent) {
std::stringstream ss;
auto listEditQual = std::get<0>(references);
auto vars = std::get<1>(references);
ss << pprint::Indent(indent);
if (listEditQual != ListEditQual::ResetToExplicit) {
ss << to_string(listEditQual) << " ";
}
ss << "references = ";
if (vars.empty()) {
ss << "None";
} else {
ss << vars;
}
ss << "\n";
return ss.str();
}
std::string print_payload(const prim::PayloadList &payload, const uint32_t indent) {
std::stringstream ss;
auto listEditQual = std::get<0>(payload);
auto vars = std::get<1>(payload);
ss << pprint::Indent(indent);
if (listEditQual != ListEditQual::ResetToExplicit) {
ss << to_string(listEditQual) << " ";
}
ss << "payload = ";
if (vars.empty()) {
ss << "None";
} else {
ss << vars;
}
ss << "\n";
return ss.str();
}
std::string print_prim_metas(const PrimMeta &meta, const uint32_t indent) {
std::stringstream ss;
@@ -248,6 +308,40 @@ std::string print_prim_metas(const PrimMeta &meta, const uint32_t indent) {
ss << print_customData(meta.assetInfo.value(), "assetInfo", indent);
}
if (meta.inherits) {
ss << pprint::Indent(indent);
auto listEditQual = std::get<0>(meta.inherits.value());
auto var = std::get<1>(meta.inherits.value());
if (listEditQual != ListEditQual::ResetToExplicit) {
ss << to_string(listEditQual) << " ";
}
ss << "inherits = " << var;
ss << "\n";
}
if (meta.specializes) {
ss << pprint::Indent(indent);
auto listEditQual = std::get<0>(meta.specializes.value());
auto var = std::get<1>(meta.specializes.value());
if (listEditQual != ListEditQual::ResetToExplicit) {
ss << to_string(listEditQual) << " ";
}
ss << "specializes = " << var;
ss << "\n";
}
if (meta.references) {
ss << print_references(meta.references.value(), indent);
}
if (meta.payload) {
ss << print_payload(meta.payload.value(), indent);
}
if (meta.variants) {
ss << print_variantsMap(meta.variants.value(), indent);
}
@@ -271,7 +365,7 @@ std::string print_prim_metas(const PrimMeta &meta, const uint32_t indent) {
ss << "[InternalError]";
}
ss << "\n";
ss << "\n";
}
if (meta.apiSchemas) {

View File

@@ -151,6 +151,7 @@ std::string print_customData(const CustomDataType &customData, const std::string
std::string print_variantsMap(const VariantsMap &map, const uint32_t indent);
} // namespace tinyusdz
namespace std {

21
src/prim-pprint.hh Normal file
View File

@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
// Copyright 2022 - Present, Syoyo Fujita.
#pragma once
#include <string>
#include <cstdint>
#include "prim-types.hh"
namespace tinyusdz {
namespace prim {
//
// Impelemnted in pprinter.cc
//
std::string print_references(const ReferenceList &references, const uint32_t indent);
std::string print_payload(const PayloadList &payload, const uint32_t indent);
} // namespace prim
} // namespace tinyusdz

View File

@@ -1915,15 +1915,19 @@ bool ReconstructPrim(
std::string *warn,
std::string *err) {
(void)references;
(void)warn;
#if 0 // TODO
//
// Resolve prepend references
//
for (const auto &ref : references) {
if (std::get<0>(ref) == tinyusdz::ListEditQual::Prepend) {
if (std::get<0>(references) == ListEditQual::Prepend) {
for (const auto &ref : std::get<1>(references)) {
(void)ref;
}
}
#endif
std::set<std::string> table;
if (!prim::ReconstructXformOpsFromProperties(table, properties, &xform->xformOps, err)) {
@@ -1935,14 +1939,17 @@ bool ReconstructPrim(
PARSE_PROPERTY_END_MAKE_WARN(table, prop)
}
#if 0 // TODO
//
// Resolve append references
// (Overwrite variables with the referenced one).
//
for (const auto &ref : references) {
if (std::get<0>(ref) == tinyusdz::ListEditQual::Append) {
if (std::get<0>(references) == ListEditQual::Append) {
for (const auto &ref : std::get<1>(references)) {
(void)ref;
}
}
#endif
return true;
}
@@ -2951,6 +2958,7 @@ bool ReconstructPrim<GeomMesh>(
PARSE_PROPERTY_END_MAKE_WARN(table, prop)
}
#if 0
//
// Resolve append references
// (Overwrite variables with the referenced one).
@@ -2960,6 +2968,7 @@ bool ReconstructPrim<GeomMesh>(
// TODO
}
}
#endif
return true;
}

View File

@@ -13,9 +13,6 @@
namespace tinyusdz {
namespace prim {
using PropertyMap = std::map<std::string, Property>;
using ReferenceList = std::vector<std::pair<ListEditQual, Reference>>;
///
/// Reconstruct property with `xformOp:***` namespace in `properties` to `XformOp` class.

View File

@@ -45,7 +45,7 @@ namespace tinyusdz {
// SpecType enum must be same order with pxrUSD's SdfSpecType(since enum value is stored in Crate directly)
enum class SpecType {
Unknown = 0, // must be 0
Attribute,
Attribute,
Connection,
Expression,
Mapper,
@@ -354,6 +354,7 @@ class TokenizedPath {
bool operator==(const Path &lhs, const Path &rhs);
// variants in Prim Meta.
//
// e.g.
@@ -361,7 +362,7 @@ bool operator==(const Path &lhs, const Path &rhs);
// string variant0 = "bora"
// string variant1 = "dora"
// }
// pxrUSD uses dict type for the content, but TinyUSDZ only accepts list of strings for now
// pxrUSD uses dict type for the content, but TinyUSDZ only accepts list of strings for now
//
using VariantsMap = std::map<std::string, std::string>;
@@ -373,7 +374,7 @@ using CustomDataType = std::map<std::string, MetaVariable>;
// TODO: Use unify with PrimVar?
class MetaVariable {
public:
std::string type; // Explicit name of type
std::string type; // Explicit (declared) name of type
std::string name;
bool custom{false};
@@ -432,6 +433,10 @@ class MetaVariable {
return type_id(*this);
}
bool IsBlocked() const {
return (TypeId() == value::TYPE_ID_VALUEBLOCK);
}
private:
static std::string type_name(const MetaVariable &v) {
@@ -545,6 +550,25 @@ struct APISchemas
std::vector<std::pair<APIName, std::string>> names;
};
struct LayerOffset {
double _offset;
double _scale;
};
struct Payload {
value::AssetPath asset_path;
Path _prim_path;
LayerOffset _layer_offset;
};
struct Reference {
value::AssetPath asset_path;
Path prim_path;
LayerOffset layerOffset;
//value::dict custom_data;
CustomDataType customData;
};
// Metadata for Prim
struct PrimMeta {
nonstd::optional<bool> active; // 'active'
@@ -554,12 +578,21 @@ struct PrimMeta {
nonstd::optional<StringData> doc; // 'documentation'
nonstd::optional<StringData> comment; // 'comment'
nonstd::optional<APISchemas> apiSchemas; // 'apiSchemas'
//
// Compositions
//
nonstd::optional<std::pair<ListEditQual, std::vector<Reference>>> references;
nonstd::optional<std::pair<ListEditQual, std::vector<Payload>>> payload;
// Currently TinyUSDZ allow single Path
nonstd::optional<std::pair<ListEditQual, Path>> inherits; // 'inherits'
nonstd::optional<std::pair<ListEditQual, MetaVariable>> variantSets; // 'variantSets'. type `token` or `token[]`
nonstd::optional<VariantsMap> variants; // `variants`
// Currently TinyUSDZ allow single Path
nonstd::optional<std::pair<ListEditQual, Path>> inherits; // 'inherits'
nonstd::optional<std::pair<ListEditQual, Path>> specializes; // 'specializes'
// USDZ extensions
nonstd::optional<std::string> sceneName; // 'sceneName'
@@ -863,7 +896,7 @@ class TypedAttribute {
return nonstd::nullopt;
}
void SetValueEmpty() {
_empty = true;
}
@@ -1193,26 +1226,6 @@ struct ListOpHeader {
};
struct LayerOffset {
double _offset;
double _scale;
};
struct Payload {
std::string _asset_path;
Path _prim_path;
LayerOffset _layer_offset;
};
struct Reference {
value::AssetPath asset_path;
Path prim_path;
LayerOffset layerOffset;
//value::dict custom_data;
CustomDataType customData;
};
//
// Colum-major order(e.g. employed in OpenGL).
// For example, 12th([3][0]), 13th([3][1]), 14th([3][2]) element corresponds to
@@ -1610,7 +1623,7 @@ class Property {
void SetListEditQual(ListEditQual qual) {
_listOpQual = qual;
}
const PrimAttrib &GetAttrib() const {
return _attrib;
}
@@ -1635,13 +1648,13 @@ class Property {
ListEditQual GetListEditQual() const {
return _listOpQual;
}
private:
PrimAttrib _attrib;
// List Edit qualifier(Attribute can never be list editable)
// TODO: Store listEdit qualifier to `Relation`
ListEditQual _listOpQual{ListEditQual::ResetToExplicit};
ListEditQual _listOpQual{ListEditQual::ResetToExplicit};
Type _type{Type::EmptyAttrib};
Relation _rel; // Relation(`rel`) or Connection(`.connect`)
@@ -1829,7 +1842,8 @@ struct Model {
PrimMeta meta;
std::vector<std::pair<ListEditQual, Reference>> references;
std::pair<ListEditQual, std::vector<Reference>> references;
std::pair<ListEditQual, std::vector<Payload>> payload;
std::map<std::string, Property> props;
};
@@ -2104,6 +2118,15 @@ DEFINE_TYPE_TRAIT(Extent, "float3[]", TYPE_ID_EXTENT, 2); // float3[2]
} // namespace value
namespace prim {
using PropertyMap = std::map<std::string, Property>;
using ReferenceList = std::pair<ListEditQual, std::vector<Reference>>;
using PayloadList = std::pair<ListEditQual, std::vector<Payload>>;
} // namespace prim
// TODO(syoyo): Range, Interval, Rect2i, Frustum, MultiInterval
// and Quaternion?

View File

@@ -204,8 +204,6 @@ class VariableDef {
namespace {
using ReferenceList = std::vector<std::pair<ListEditQual, Reference>>;
#if 0
// Extract array of References from Variable.
ReferenceList GetReferences(
@@ -461,7 +459,7 @@ class USDAReader::Impl {
template <typename T>
bool ReconstructPrim(
const prim::PropertyMap &properties,
const ReferenceList &references,
const prim::ReferenceList &references,
T *out);
#if 0
@@ -484,7 +482,6 @@ class USDAReader::Impl {
[&](const Path &full_path, const Specifier spec, const Path &prim_name, const int64_t primIdx,
const int64_t parentPrimIdx,
const prim::PropertyMap &properties,
const ReferenceList &references,
const ascii::AsciiParser::PrimMetaInput &in_meta)
-> nonstd::expected<bool, std::string> {
if (!prim_name.IsValid()) {
@@ -526,6 +523,11 @@ class USDAReader::Impl {
DCOUT("full_path = " << full_path.full_path_name());
DCOUT("primName = " << prim_name.full_path_name());
prim::ReferenceList references;
if (prim.meta.references) {
references = prim.meta.references.value();
}
bool ret = ReconstructPrim<T>(properties, references, &prim);
if (!ret) {
@@ -663,12 +665,12 @@ class USDAReader::Impl {
for (const auto &item : dict) {
// TODO: duplicated key check?
if (auto pv = item.second.Get<std::string>()) {
m[item.first] = pv.value();
m[item.first] = pv.value();
} else if (auto pvs = item.second.Get<StringData>()) {
// TODO: store triple-quote info
m[item.first] = pvs.value().value;
m[item.first] = pvs.value().value;
} else {
return nonstd::make_unexpected(fmt::format("TinyUSDZ only accepts `string` value for `variants` element, but got type `{}`(type_id {}).", item.second.TypeName(), item.second.TypeId()));
return nonstd::make_unexpected(fmt::format("TinyUSDZ only accepts `string` value for `variants` element, but got type `{}`(type_id {}).", item.second.TypeName(), item.second.TypeId()));
}
}
@@ -800,8 +802,27 @@ class USDAReader::Impl {
"got type `"
<< var.type << "`");
}
} else if (meta.first == "specializes") {
if (auto pv = var.Get<std::vector<Path>>()) {
if (pv.value().size() == 0) {
// empty
} else {
// Currently no multiple inherits? are supported.
if (pv.value().size() > 1) {
PUSH_WARN("Multiple paths are not supported for `specializes`. Use the first one.");
}
out->specializes = std::make_pair(listEditQual, pv.value()[0]);
}
} else if (auto pvp = var.Get<Path>()) {
out->specializes = std::make_pair(listEditQual, pvp.value());
} else {
PUSH_ERROR_AND_RETURN(
"(Internal error?) `specializes` metadataum should be either `path` or `path[]`. "
"got type `"
<< var.type << "`");
}
} else if (meta.first == "variantSets") {
if (auto pv = var.Get<value::token>()) {
out->variantSets = meta.second;
@@ -813,7 +834,7 @@ class USDAReader::Impl {
"`token` or `token[]`. got type `"
<< var.type << "`");
}
} else if (meta.first == "apiSchemas") {
DCOUT("apiSchemas. type = " << var.type);
if (var.type == "token[]") {
@@ -846,6 +867,54 @@ class USDAReader::Impl {
"`token[]`. got type `"
<< var.type << "`");
}
} else if (meta.first == "references") {
if (var.IsBlocked()) {
// create references with empty array.
out->references = std::make_pair(listEditQual, std::vector<Reference>());
} else if (auto pv = var.Get<Reference>()) {
// To Reference
std::vector<Reference> refs;
refs.emplace_back(pv.value());
out->references = std::make_pair(listEditQual, refs);
} else if (auto pva = var.Get<std::vector<Reference>>()) {
out->references = std::make_pair(listEditQual, pva.value());
} else {
PUSH_ERROR_AND_RETURN(
"(Internal error?) `references` metadataum is not type "
"`path` or `path[]`. got type `"
<< var.type << "`");
}
} else if (meta.first == "payload") {
if (var.IsBlocked()) {
// create payload with empty array.
out->payload = std::make_pair(listEditQual, std::vector<Payload>());
} else if (auto pv = var.Get<Reference>()) {
// To Payload
std::vector<Payload> refs;
Payload ref;
ref.asset_path = pv.value().asset_path;
ref._prim_path = pv.value().prim_path;
// TODO: Other member variables
refs.emplace_back(ref);
out->payload = std::make_pair(listEditQual, refs);
} else if (auto pva = var.Get<std::vector<Reference>>()) {
std::vector<Payload> refs;
for (const auto &item : pva.value()) {
Payload ref;
ref.asset_path = item.asset_path;
ref._prim_path = item.prim_path;
// TODO: Other member variables
refs.emplace_back(ref);
}
out->payload = std::make_pair(listEditQual, refs);
} else {
PUSH_ERROR_AND_RETURN(
"(Internal error?) `references` metadataum is not type "
"`path` or `path[]`. got type `"
<< var.type << "`");
}
} else {
// string-only data?
if (auto pv = var.Get<StringData>()) {
@@ -1032,7 +1101,7 @@ bool USDAReader::Impl::ReconstructStage() {
template <>
bool USDAReader::Impl::ReconstructPrim(
const prim::PropertyMap &properties,
const ReferenceList &references,
const prim::ReferenceList &references,
Xform *xform) {
std::string err;
@@ -1095,7 +1164,7 @@ bool USDAReader::Impl::RegisterReconstructCallback<GeomSubset>() {
[&](const Path &full_path, const Specifier spec, const Path &prim_name, const int64_t primIdx,
const int64_t parentPrimIdx,
const prim::PropertyMap &properties,
const ReferenceList &references,
//const prim::ReferenceList &references,
const ascii::AsciiParser::PrimMetaInput &in_meta)
-> nonstd::expected<bool, std::string> {
const Path &parent = full_path.GetParentPrim();
@@ -1334,7 +1403,7 @@ bool USDAReader::Impl::RegisterReconstructCallback<GeomSubset>() {
template <>
bool USDAReader::Impl::ReconstructPrim(
const prim::PropertyMap &properties,
const ReferenceList &references,
const prim::ReferenceList &references,
GPrim *gprim) {
(void)gprim;
@@ -1349,7 +1418,7 @@ bool USDAReader::Impl::ReconstructPrim(
template <>
bool USDAReader::Impl::ReconstructPrim<NodeGraph>(
const prim::PropertyMap &properties,
const ReferenceList &references,
const prim::ReferenceList &references,
NodeGraph *graph) {
(void)properties;
(void)references;
@@ -1380,7 +1449,7 @@ bool USDAReader::Impl::ReconstructPrim<Material>(
template <typename T>
bool USDAReader::Impl::ReconstructPrim(
const prim::PropertyMap &properties,
const ReferenceList &references,
const prim::ReferenceList &references,
T *prim) {
std::string err;

View File

@@ -14,6 +14,8 @@ namespace tinyusdz {
// in prim-types.hh
class Path;
struct StringData;
struct Reference;
struct Payload;
} // namespace tinyusdz
@@ -85,6 +87,9 @@ std::ostream &operator<<(std::ostream &os, const tinyusdz::value::AssetPath &v);
std::ostream &operator<<(std::ostream &os, const tinyusdz::Path &v);
std::ostream &operator<<(std::ostream &os, const tinyusdz::StringData &v);
std::ostream &operator<<(std::ostream &os, const tinyusdz::Reference &v);
std::ostream &operator<<(std::ostream &os, const tinyusdz::Payload &v);
// 1D array
template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {

View File

@@ -0,0 +1,16 @@
#usda 1.0
(
defaultPrim = "hello"
)
def Xform "hello" (
variants = {
string shadingVariant = "green"
string bora = "red"
}
prepend variantSets = "shadingVariant"
variantSet = { "bora" { active = true } }
)
{
}

View File

@@ -0,0 +1,8 @@
#usda 1.0
def "sphere1" (
payload = @sphere.usda@
)
{
}

View File

@@ -0,0 +1,8 @@
#usda 1.0
def "sphere1" (
payload = [@sphere.usda@, @suzanne.usda@]
)
{
}

View File

@@ -0,0 +1,8 @@
#usda 1.0
def "sphere1" (
payload = None
)
{
}

View File

@@ -0,0 +1,8 @@
#usda 1.0
def "sphere1" (
references = @sphere.usda@</sphere>
)
{
}

View File

@@ -0,0 +1,8 @@
#usda 1.0
def "sphere1" (
references = [@sphere.usda@</sphere>, @suzanne.usda@</Suzanne>]
)
{
}

View File

@@ -0,0 +1,8 @@
#usda 1.0
def "sphere1" (
references = []
)
{
}

View File

@@ -0,0 +1,8 @@
#usda 1.0
def "sphere1" (
references = None
)
{
}

View File

@@ -0,0 +1,36 @@
#usda 1.0
def Xform "Implicits" (
append variantSets = "shapeVariant"
)
{
# Prim meta in variant Stmt.
variantSet "shapeVariant" = {
"Capsule" ( active = true ) {
def Capsule "Pill"
{
}
}
"Cone" {
def Cone "PartyHat"
{
}
}
"Cube" {
def Cube "Box"
{
}
}
"Cylinder" {
def Cylinder "Tube"
{
}
}
"Sphere" {
def Sphere "Ball"
{
}
}
}
}