GCC Code Coverage Report


ernie/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
78 / 88
88.6%
Branches:
193 / 416
46.4%
Functions:
10 / 10
100.0%

scene/usd_plugin.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 /// @file usd_plugin.cpp
3 /// @brief Ernie's own schemas as a codeless USD schema plugin: `generatedSchema.usda`, its
4 /// classes flattened as `usdGenSchema` writes them, and `plugInfo.json`.
5 ///
6 /// References:
7 /// - Pixar, "Generating New Schema Classes" (codeless schemas),
8 /// https://openusd.org/release/tut_generating_new_schema.html
9 #include "ernie/scene/json_value.h"
10 #include "ernie/scene/reference.h"
11 #include "ernie/util/text.h"
12
13 #include <array>
14 #include <string>
15
16 namespace ernie {
17 namespace {
18
19 /// @return JSON as USD's text format writes a value: arrays as tuples, or with `list` as lists.
20 158 std::string UsdText(const Json& json, bool list = false) {
21
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 152 times.
158 if (json.is_boolean()) {
22
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 time.
11 return json.get<bool>() ? "1" : "0";
23 }
24
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 30 times.
152 if (!json.is_array()) {
25 122 return json.dump();
26 }
27
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
56 const std::string items = Join(json, ", ", [](const Json& item) { return UsdText(item); });
28
8/14
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 11 times.
✓ Branch 3 taken 19 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 19 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 19 times.
✓ Branch 17 taken 11 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
60 return list ? "[" + items + "]" : "(" + items + ")";
29 30 }
30
31 /// @return A fallback in USD's text format, or empty when it has none there (relationships, empty
32 /// assets).
33 147 std::string UsdFallback(const AttributeDef& def, const Value& fallback) {
34
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 13 times.
147 const bool none = fallback.Empty() || fallback.Is<Path>() || fallback.Is<std::vector<Path>>();
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 134 times.
134 if (none || def.type == ColumnType::Tensor) {
36 13 return {};
37 }
38 134 const Json json = ToJson(fallback);
39
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 132 times.
134 if (def.meta.asset) {
40
5/18
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
2 return json.get<std::string>().empty() ? "" : "@" + json.get<std::string>() + "@";
41 }
42
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
132 if (def.type == ColumnType::Matrix) {
43 // USD's rows are its row vectors: the columns of Ernie's matrices.
44
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Json columns = Json::array();
45
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (std::size_t column = 0; column < 4; ++column) {
46
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ columns.push_back(Json::array());
47
0/6
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ for (const Json& row : json) {
48
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ columns.back().push_back(row[column]);
49 }
50 }
51
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ return UsdText(columns);
52 ✗ }
53
1/2
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
132 return UsdText(json, def.type == ColumnType::FloatArray || def.type == ColumnType::TokenArray);
54 134 }
55
56 161 std::string Quoted(std::string_view text) {
57
1/2
✓ Branch 2 taken 161 times.
✗ Branch 3 not taken.
322 return "\"\"\"" + std::string(text) + "\"\"\"";
58 }
59
60 26 std::string Strings(const auto& texts) {
61
2/4
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 8 taken 73 times.
✗ Branch 9 not taken.
125 return "[" + Join(texts, ", ", [](std::string_view text) { return Json(text).dump(); }) + "]";
62 }
63
64 147 std::string Property(const SchemaDef& schema, const AttributeDef& def) {
65
3/6
✓ Branch 2 taken 147 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 147 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 147 times.
✗ Branch 9 not taken.
441 std::string out = " " + UsdTypeName(def) + " " + std::string(def.name);
66
4/6
✓ Branch 1 taken 147 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 147 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 132 times.
✓ Branch 7 taken 15 times.
294 if (const std::string fallback = UsdFallback(def, schema.Fallback(def)); !fallback.empty()) {
67 132 out += " = " + fallback;
68 ✗ }
69
1/2
✓ Branch 1 taken 147 times.
✗ Branch 2 not taken.
147 out += " (\n";
70
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 123 times.
147 if (!def.meta.options.empty()) {
71
3/6
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 24 times.
✗ Branch 8 not taken.
72 out += " allowedTokens = " + Strings(def.meta.options) + "\n";
72 }
73
3/6
✓ Branch 1 taken 147 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 147 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 147 times.
✗ Branch 8 not taken.
294 return out + " doc = " + Quoted(def.meta.doc) + "\n )\n";
74
1/2
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
279 }
75
76 /// @return The plugin type name of a schema, as `UsdLuxBoundableLightBase` or `ErnieLaserLight`.
77 21 std::string TypeName(const SchemaDef& schema) {
78 21 const std::string name(schema.name);
79
3/4
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 7 times.
21 if (IsErnieSchema(name)) {
80
4/6
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 11 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
14 return name.starts_with("Ernie") ? name : "Ernie" + name;
81 }
82
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 const SchemaFamily* family = FindFamily(name);
83
3/6
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
14 return std::string(family != nullptr ? family->usdModule : "Usd") + name;
84 21 }
85
86 14 std::string Class(const SchemaDef& schema) {
87 14 const std::string name(schema.name);
88 14 std::string out = schema.kind == SchemaKind::Concrete
89
9/16
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 7 times.
✓ Branch 12 taken 7 times.
✓ Branch 13 taken 7 times.
✓ Branch 14 taken 7 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
49 ? "class " + name + " \"" + name + "\" (\n"
90
7/14
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 7 times.
✓ Branch 12 taken 7 times.
✓ Branch 13 taken 7 times.
✓ Branch 14 taken 7 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
21 : "class \"" + name + "\" (\n";
91
3/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 12 times.
14 if (const std::vector<std::string_view> builtins = schema.AllBuiltinApis(); !builtins.empty()) {
92
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
6 out += " prepend apiSchemas = " + Strings(builtins) + "\n";
93 14 }
94
3/6
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
42 out += " doc = " + Quoted(schema.doc) + "\n)\n{\n";
95
3/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 147 times.
✓ Branch 4 taken 14 times.
161 for (const AttributeDef* def : schema.AllAttributes()) {
96
1/2
✓ Branch 1 taken 147 times.
✗ Branch 2 not taken.
294 out += Property(schema, *def);
97 ✗ }
98
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 return out + "}\n\n";
99 14 }
100
101 14 Json PlugInfoType(const SchemaDef& schema) {
102 14 static constexpr std::array<std::string_view, 4> kKinds{"abstractTyped", "concreteTyped",
103 "singleApplyAPI", "multipleApplyAPI"};
104 14 const bool typed = schema.kind == SchemaKind::Abstract || schema.kind == SchemaKind::Concrete;
105
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 const std::string base = !typed ? "UsdAPISchemaBase"
106
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 : schema.base != nullptr ? TypeName(*schema.base)
107 14 : "UsdTyped";
108 28 Json type{{"alias", {{"UsdSchemaBase", schema.name}}},
109 {"autoGenerated", true},
110
2/4
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 14 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
42 {"bases", Json::array({base})},
111 14 {"schemaIdentifier", schema.name},
112
2/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 14 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
266 {"schemaKind", kKinds[static_cast<std::size_t>(schema.kind)]}};
113 14 if (!schema.appliesTo.empty()) {
114
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ type["apiSchemaCanOnlyApplyTo"] = schema.appliesTo;
115 }
116 14 return type;
117
34/80
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 14 times.
✗ Branch 20 not taken.
✓ Branch 23 taken 14 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 14 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 14 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 14 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 14 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 14 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 14 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 14 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 14 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 14 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 14 times.
✗ Branch 54 not taken.
✗ Branch 56 not taken.
✓ Branch 57 taken 14 times.
✓ Branch 58 taken 28 times.
✓ Branch 59 taken 14 times.
✓ Branch 60 taken 28 times.
✓ Branch 61 taken 14 times.
✓ Branch 62 taken 28 times.
✓ Branch 63 taken 14 times.
✓ Branch 64 taken 28 times.
✓ Branch 65 taken 14 times.
✓ Branch 66 taken 28 times.
✓ Branch 67 taken 14 times.
✓ Branch 68 taken 14 times.
✓ Branch 69 taken 14 times.
✓ Branch 70 taken 28 times.
✓ Branch 71 taken 14 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 14 times.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
252 }
118
119 } // namespace
120
121 1 UsdSchemaPlugin ErnieUsdSchemaPlugin() {
122
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 UsdSchemaPlugin plugin;
123 1 plugin.generatedSchema = "#usda 1.0\n(\n \"WARNING: THIS FILE IS GENERATED BY ernie schema. "
124
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 "DO NOT EDIT.\"\n)\n\n";
125
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 Json types = Json::object();
126
3/4
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 65 times.
✓ Branch 4 taken 1 time.
66 for (const SchemaDef* schema : Schemas()) {
127
3/4
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 51 times.
65 if (IsErnieSchema(schema->name)) {
128
2/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
28 plugin.generatedSchema += Class(*schema);
129
3/6
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
14 types[TypeName(*schema)] = PlugInfoType(*schema);
130 }
131 }
132
2/4
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
24 const Json info{{"Plugins", Json::array({{{"Info", {{"Types", std::move(types)}}},
133 {"LibraryPath", ""},
134 {"Name", "ernie"},
135 {"ResourcePath", "."},
136 {"Root", "."},
137
2/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 {"Type", "resource"}}})}};
138 1 plugin.plugInfo = PrintJson(info);
139 1 return plugin;
140
46/108
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 11 taken 1 time.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 time.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 time.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 time.
✗ Branch 21 not taken.
✓ Branch 23 taken 1 time.
✗ Branch 24 not taken.
✓ Branch 26 taken 1 time.
✗ Branch 27 not taken.
✓ Branch 29 taken 1 time.
✗ Branch 30 not taken.
✓ Branch 32 taken 1 time.
✗ Branch 33 not taken.
✓ Branch 35 taken 1 time.
✗ Branch 36 not taken.
✓ Branch 38 taken 1 time.
✗ Branch 39 not taken.
✓ Branch 41 taken 1 time.
✗ Branch 42 not taken.
✓ Branch 44 taken 1 time.
✗ Branch 45 not taken.
✓ Branch 47 taken 1 time.
✗ Branch 48 not taken.
✓ Branch 50 taken 1 time.
✗ Branch 51 not taken.
✓ Branch 53 taken 1 time.
✗ Branch 54 not taken.
✓ Branch 56 taken 1 time.
✗ Branch 57 not taken.
✓ Branch 59 taken 1 time.
✗ Branch 60 not taken.
✓ Branch 62 taken 1 time.
✗ Branch 63 not taken.
✓ Branch 65 taken 1 time.
✗ Branch 66 not taken.
✓ Branch 68 taken 1 time.
✗ Branch 69 not taken.
✓ Branch 71 taken 1 time.
✗ Branch 72 not taken.
✓ Branch 74 taken 1 time.
✗ Branch 75 not taken.
✓ Branch 76 taken 2 times.
✓ Branch 77 taken 1 time.
✓ Branch 78 taken 1 time.
✓ Branch 79 taken 6 times.
✓ Branch 80 taken 2 times.
✓ Branch 81 taken 1 time.
✓ Branch 82 taken 2 times.
✓ Branch 83 taken 1 time.
✓ Branch 84 taken 2 times.
✓ Branch 85 taken 1 time.
✓ Branch 86 taken 2 times.
✓ Branch 87 taken 1 time.
✓ Branch 88 taken 2 times.
✓ Branch 89 taken 1 time.
✓ Branch 90 taken 1 time.
✓ Branch 91 taken 2 times.
✓ Branch 92 taken 1 time.
✓ Branch 93 taken 1 time.
✓ Branch 94 taken 2 times.
✓ Branch 95 taken 1 time.
✓ Branch 97 taken 1 time.
✗ Branch 98 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
31 }
141
142 } // namespace ernie
143