1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/usd/usdRi/statementsAPI.h"
25 #include "pxr/usd/usd/schemaRegistry.h"
26 #include "pxr/usd/usd/typed.h"
27 #include "pxr/usd/usd/tokens.h"
28
29 #include "pxr/usd/sdf/types.h"
30 #include "pxr/usd/sdf/assetPath.h"
31
32 PXR_NAMESPACE_OPEN_SCOPE
33
34 // Register the schema with the TfType system.
TF_REGISTRY_FUNCTION(TfType)35 TF_REGISTRY_FUNCTION(TfType)
36 {
37 TfType::Define<UsdRiStatementsAPI,
38 TfType::Bases< UsdAPISchemaBase > >();
39
40 }
41
42 TF_DEFINE_PRIVATE_TOKENS(
43 _schemaTokens,
44 (StatementsAPI)
45 );
46
47 /* virtual */
~UsdRiStatementsAPI()48 UsdRiStatementsAPI::~UsdRiStatementsAPI()
49 {
50 }
51
52 /* static */
53 UsdRiStatementsAPI
Get(const UsdStagePtr & stage,const SdfPath & path)54 UsdRiStatementsAPI::Get(const UsdStagePtr &stage, const SdfPath &path)
55 {
56 if (!stage) {
57 TF_CODING_ERROR("Invalid stage");
58 return UsdRiStatementsAPI();
59 }
60 return UsdRiStatementsAPI(stage->GetPrimAtPath(path));
61 }
62
63
64 /* virtual */
_GetSchemaKind() const65 UsdSchemaKind UsdRiStatementsAPI::_GetSchemaKind() const
66 {
67 return UsdRiStatementsAPI::schemaKind;
68 }
69
70 /* static */
71 bool
CanApply(const UsdPrim & prim,std::string * whyNot)72 UsdRiStatementsAPI::CanApply(
73 const UsdPrim &prim, std::string *whyNot)
74 {
75 return prim.CanApplyAPI<UsdRiStatementsAPI>(whyNot);
76 }
77
78 /* static */
79 UsdRiStatementsAPI
Apply(const UsdPrim & prim)80 UsdRiStatementsAPI::Apply(const UsdPrim &prim)
81 {
82 if (prim.ApplyAPI<UsdRiStatementsAPI>()) {
83 return UsdRiStatementsAPI(prim);
84 }
85 return UsdRiStatementsAPI();
86 }
87
88 /* static */
89 const TfType &
_GetStaticTfType()90 UsdRiStatementsAPI::_GetStaticTfType()
91 {
92 static TfType tfType = TfType::Find<UsdRiStatementsAPI>();
93 return tfType;
94 }
95
96 /* static */
97 bool
_IsTypedSchema()98 UsdRiStatementsAPI::_IsTypedSchema()
99 {
100 static bool isTyped = _GetStaticTfType().IsA<UsdTyped>();
101 return isTyped;
102 }
103
104 /* virtual */
105 const TfType &
_GetTfType() const106 UsdRiStatementsAPI::_GetTfType() const
107 {
108 return _GetStaticTfType();
109 }
110
111 /*static*/
112 const TfTokenVector&
GetSchemaAttributeNames(bool includeInherited)113 UsdRiStatementsAPI::GetSchemaAttributeNames(bool includeInherited)
114 {
115 static TfTokenVector localNames;
116 static TfTokenVector allNames =
117 UsdAPISchemaBase::GetSchemaAttributeNames(true);
118
119 if (includeInherited)
120 return allNames;
121 else
122 return localNames;
123 }
124
125 PXR_NAMESPACE_CLOSE_SCOPE
126
127 // ===================================================================== //
128 // Feel free to add custom code below this line. It will be preserved by
129 // the code generator.
130 //
131 // Just remember to wrap code in the appropriate delimiters:
132 // 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'.
133 // ===================================================================== //
134 // --(BEGIN CUSTOM CODE)--
135
136 #include "typeUtils.h"
137 #include "pxr/usd/sdf/types.h"
138 #include "pxr/base/tf/envSetting.h"
139 #include <string>
140
141 using std::string;
142
143 PXR_NAMESPACE_OPEN_SCOPE
144
145 TF_DEFINE_ENV_SETTING(
146 USDRI_STATEMENTS_READ_OLD_ATTR_ENCODING, true,
147 "If on, UsdRiStatementsAPI will read old-style attributes. "
148 "Otherwise, primvars in the ri: namespace will be read instead.");
149
150 TF_DEFINE_PRIVATE_TOKENS(
151 _tokens,
152 ((fullAttributeNamespace, "ri:attributes:"))
153 ((primvarAttrNamespace, "primvars:ri:attributes:"))
154 ((rootNamespace, "ri"))
155 ((attributeNamespace, "attributes"))
156 ((coordsys, "ri:coordinateSystem"))
157 ((scopedCoordsys, "ri:scopedCoordinateSystem"))
158 ((modelCoordsys, "ri:modelCoordinateSystems"))
159 ((modelScopedCoordsys, "ri:modelScopedCoordinateSystems"))
160 );
161
162 static TfToken
_MakeRiAttrNamespace(const string & nameSpace,const string & attrName)163 _MakeRiAttrNamespace(const string &nameSpace, const string &attrName)
164 {
165 return TfToken(_tokens->fullAttributeNamespace.GetString() +
166 nameSpace + ":" + attrName);
167 }
168
169 UsdAttribute
CreateRiAttribute(const TfToken & name,const string & riType,const string & nameSpace)170 UsdRiStatementsAPI::CreateRiAttribute(
171 const TfToken& name,
172 const string &riType,
173 const string &nameSpace)
174 {
175 TfToken fullName = _MakeRiAttrNamespace(nameSpace, name.GetString());
176 SdfValueTypeName usdType = UsdRi_GetUsdType(riType);
177 return UsdGeomPrimvarsAPI(GetPrim())
178 .CreatePrimvar(fullName, usdType).GetAttr();
179 }
180
181 UsdAttribute
CreateRiAttribute(const TfToken & name,const TfType & tfType,const string & nameSpace)182 UsdRiStatementsAPI::CreateRiAttribute(
183 const TfToken &name,
184 const TfType &tfType,
185 const string &nameSpace)
186 {
187 TfToken fullName = _MakeRiAttrNamespace(nameSpace, name.GetString());
188 SdfValueTypeName usdType = SdfSchema::GetInstance().FindType(tfType);
189 return UsdGeomPrimvarsAPI(GetPrim())
190 .CreatePrimvar(fullName, usdType).GetAttr();
191 }
192
193 UsdAttribute
GetRiAttribute(const TfToken & name,const std::string & nameSpace)194 UsdRiStatementsAPI::GetRiAttribute(
195 const TfToken &name,
196 const std::string &nameSpace)
197 {
198 TfToken fullName = _MakeRiAttrNamespace(nameSpace, name.GetString());
199 if (UsdGeomPrimvar p = UsdGeomPrimvarsAPI(GetPrim()).GetPrimvar(fullName)) {
200 return p;
201 }
202 if (TfGetEnvSetting(USDRI_STATEMENTS_READ_OLD_ATTR_ENCODING)) {
203 return GetPrim().GetAttribute(fullName);
204 }
205 return UsdAttribute();
206 }
207
208 std::vector<UsdProperty>
GetRiAttributes(const string & nameSpace) const209 UsdRiStatementsAPI::GetRiAttributes(
210 const string &nameSpace) const
211 {
212 std::vector<UsdProperty> validProps;
213
214 // Read as primvars.
215 std::string const& ns = _tokens->fullAttributeNamespace.GetString();
216 for (UsdGeomPrimvar const& pv:
217 UsdGeomPrimvarsAPI(GetPrim()).GetPrimvars()) {
218 if (TfStringStartsWith(pv.GetPrimvarName().GetString(), ns)) {
219 validProps.push_back(pv.GetAttr());
220 }
221 }
222
223 // If enabled, read the old-style encoding.
224 if (TfGetEnvSetting(USDRI_STATEMENTS_READ_OLD_ATTR_ENCODING)) {
225 const size_t numNewStylePrimvars = validProps.size();
226 std::vector<UsdProperty> props =
227 GetPrim().GetPropertiesInNamespace(_tokens->fullAttributeNamespace);
228 std::vector<string> names;
229 bool requestedNameSpace = (nameSpace != "");
230 for (UsdProperty const& prop: props) {
231 names = prop.SplitName();
232 if (requestedNameSpace && names[2] != nameSpace) {
233 // wrong namespace
234 continue;
235 }
236 // If we encounter the same Ri attribute name encoded as both
237 // a new and old style attribute, return only the new-style one.
238 bool foundAsPrimvar = false;
239 for (size_t i=0; i < numNewStylePrimvars; ++i) {
240 const std::string &primvarName =
241 validProps[i].GetName().GetString();
242 std::size_t nsOffset = primvarName.find(":");
243 if (nsOffset != std::string::npos &&
244 primvarName.compare(nsOffset+1, std::string::npos,
245 prop.GetName().GetText()) == 0) {
246 foundAsPrimvar = true;
247 break;
248 }
249 }
250 if (!foundAsPrimvar) {
251 validProps.push_back(prop);
252 }
253 }
254 }
255
256 return validProps;
257 }
258
GetRiAttributeNameSpace(const UsdProperty & prop)259 TfToken UsdRiStatementsAPI::GetRiAttributeNameSpace(const UsdProperty &prop)
260 {
261 const std::vector<string> names = prop.SplitName();
262 // Parse primvar encoding.
263 if (TfStringStartsWith(prop.GetName(), _tokens->primvarAttrNamespace)) {
264 if (names.size() >= 5) {
265 // Primvar with N custom namespaces:
266 // "primvars:ri:attributes:$(NS_1):...:$(NS_N):$(NAME)"
267 return TfToken(TfStringJoin(names.begin() + 3, names.end()-1, ":"));
268 }
269 return TfToken();
270 }
271 // Optionally parse old-style attribute encoding.
272 if (TfStringStartsWith(prop.GetName(), _tokens->fullAttributeNamespace) &&
273 TfGetEnvSetting(USDRI_STATEMENTS_READ_OLD_ATTR_ENCODING)) {
274 if (names.size() >= 4) {
275 // Old-style attribute with N custom namespaces:
276 // "ri:attributes:$(NS_1):...:$(NS_N):$(NAME)"
277 return TfToken(TfStringJoin(names.begin() + 2, names.end()-1, ":"));
278 }
279 }
280 return TfToken();
281 }
282
283 bool
IsRiAttribute(const UsdProperty & attr)284 UsdRiStatementsAPI::IsRiAttribute(const UsdProperty &attr)
285 {
286 // Accept primvar encoding.
287 if (TfStringStartsWith(attr.GetName(), _tokens->primvarAttrNamespace)) {
288 return true;
289 }
290 // Optionally accept old-style attribute encoding.
291 if (TfStringStartsWith(attr.GetName(), _tokens->fullAttributeNamespace) &&
292 TfGetEnvSetting(USDRI_STATEMENTS_READ_OLD_ATTR_ENCODING)) {
293 return true;
294 }
295 return false;
296 }
297
298 std::string
MakeRiAttributePropertyName(const std::string & attrName)299 UsdRiStatementsAPI::MakeRiAttributePropertyName(const std::string &attrName)
300 {
301 std::vector<string> names = TfStringTokenize(attrName, ":");
302
303 // If this is an already-encoded name, return it unchanged.
304 if (names.size() == 5 &&
305 TfStringStartsWith(attrName, _tokens->primvarAttrNamespace)) {
306 return attrName;
307 }
308 if (names.size() == 4 &&
309 TfStringStartsWith(attrName, _tokens->fullAttributeNamespace)) {
310 return attrName;
311 }
312
313 // Attempt to parse namespaces in different forms.
314 if (names.size() == 1) {
315 names = TfStringTokenize(attrName, ".");
316 }
317 if (names.size() == 1) {
318 names = TfStringTokenize(attrName, "_");
319 }
320
321 // Fallback to user namespace if no other exists.
322 if (names.size() == 1) {
323 names.insert(names.begin(), "user");
324 }
325
326 string fullName =
327 _tokens->primvarAttrNamespace.GetString() +
328 names[0] + ":" + ( names.size() > 2 ?
329 TfStringJoin(names.begin() + 1, names.end(), "_")
330 : names[1]);
331
332 return SdfPath::IsValidNamespacedIdentifier(fullName) ? fullName : string();
333 }
334
335 void
SetCoordinateSystem(const std::string & coordSysName)336 UsdRiStatementsAPI::SetCoordinateSystem(const std::string &coordSysName)
337 {
338 UsdAttribute attr = GetPrim().CreateAttribute(_tokens->coordsys,
339 SdfValueTypeNames->String,
340 /* custom = */ false);
341 if (TF_VERIFY(attr)) {
342 attr.Set(coordSysName);
343
344 UsdPrim currPrim = GetPrim();
345 while (currPrim && currPrim.GetPath() != SdfPath::AbsoluteRootPath()) {
346 if (currPrim.IsModel() && !currPrim.IsGroup() &&
347 currPrim.GetPath() != SdfPath::AbsoluteRootPath()) {
348 UsdRelationship rel =
349 currPrim.CreateRelationship(_tokens->modelCoordsys,
350 /* custom = */ false);
351 if (TF_VERIFY(rel)) {
352 // Order should not matter, since these are a set,
353 // but historically we have appended these.
354 rel.AddTarget(GetPrim().GetPath());
355 }
356 break;
357 }
358
359 currPrim = currPrim.GetParent();
360 }
361 }
362 }
363
364 std::string
GetCoordinateSystem() const365 UsdRiStatementsAPI::GetCoordinateSystem() const
366 {
367 std::string result;
368 UsdAttribute attr = GetPrim().GetAttribute(_tokens->coordsys);
369 if (attr) {
370 attr.Get(&result);
371 }
372 return result;
373 }
374
375 bool
HasCoordinateSystem() const376 UsdRiStatementsAPI::HasCoordinateSystem() const
377 {
378 std::string result;
379 UsdAttribute attr = GetPrim().GetAttribute(_tokens->coordsys);
380 if (attr) {
381 return attr.Get(&result);
382 }
383 return false;
384 }
385
386 void
SetScopedCoordinateSystem(const std::string & coordSysName)387 UsdRiStatementsAPI::SetScopedCoordinateSystem(const std::string &coordSysName)
388 {
389 UsdAttribute attr = GetPrim().CreateAttribute(_tokens->scopedCoordsys,
390 SdfValueTypeNames->String,
391 /* custom = */ false);
392 if (TF_VERIFY(attr)) {
393 attr.Set(coordSysName);
394
395 UsdPrim currPrim = GetPrim();
396 while (currPrim) {
397 if (currPrim.IsModel() && !currPrim.IsGroup() &&
398 currPrim.GetPath() != SdfPath::AbsoluteRootPath()) {
399 UsdRelationship rel =
400 currPrim.CreateRelationship(_tokens->modelScopedCoordsys,
401 /* custom = */ false);
402 if (TF_VERIFY(rel)) {
403 rel.AddTarget(GetPrim().GetPath());
404 }
405 break;
406 }
407
408 currPrim = currPrim.GetParent();
409 }
410 }
411 }
412
413 std::string
GetScopedCoordinateSystem() const414 UsdRiStatementsAPI::GetScopedCoordinateSystem() const
415 {
416 std::string result;
417 UsdAttribute attr = GetPrim().GetAttribute(_tokens->scopedCoordsys);
418 if (attr) {
419 attr.Get(&result);
420 }
421 return result;
422 }
423
424 bool
HasScopedCoordinateSystem() const425 UsdRiStatementsAPI::HasScopedCoordinateSystem() const
426 {
427 std::string result;
428 UsdAttribute attr = GetPrim().GetAttribute(_tokens->scopedCoordsys);
429 if (attr) {
430 return attr.Get(&result);
431 }
432 return false;
433 }
434
435 bool
GetModelCoordinateSystems(SdfPathVector * targets) const436 UsdRiStatementsAPI::GetModelCoordinateSystems(SdfPathVector *targets) const
437 {
438 if (GetPrim().IsModel()) {
439 UsdRelationship rel =
440 GetPrim().GetRelationship(_tokens->modelCoordsys);
441 return rel && rel.GetForwardedTargets(targets);
442 }
443
444 return true;
445 }
446
447 bool
GetModelScopedCoordinateSystems(SdfPathVector * targets) const448 UsdRiStatementsAPI::GetModelScopedCoordinateSystems(SdfPathVector *targets) const
449 {
450 if (GetPrim().IsModel()) {
451 UsdRelationship rel =
452 GetPrim().GetRelationship(_tokens->modelScopedCoordsys);
453 return rel && rel.GetForwardedTargets(targets);
454 }
455
456 return true;
457 }
458
459 PXR_NAMESPACE_CLOSE_SCOPE
460