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/usdShade/nodeDefAPI.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<UsdShadeNodeDefAPI,
38         TfType::Bases< UsdAPISchemaBase > >();
39 
40 }
41 
42 TF_DEFINE_PRIVATE_TOKENS(
43     _schemaTokens,
44     (NodeDefAPI)
45 );
46 
47 /* virtual */
~UsdShadeNodeDefAPI()48 UsdShadeNodeDefAPI::~UsdShadeNodeDefAPI()
49 {
50 }
51 
52 /* static */
53 UsdShadeNodeDefAPI
Get(const UsdStagePtr & stage,const SdfPath & path)54 UsdShadeNodeDefAPI::Get(const UsdStagePtr &stage, const SdfPath &path)
55 {
56     if (!stage) {
57         TF_CODING_ERROR("Invalid stage");
58         return UsdShadeNodeDefAPI();
59     }
60     return UsdShadeNodeDefAPI(stage->GetPrimAtPath(path));
61 }
62 
63 
64 /* virtual */
_GetSchemaKind() const65 UsdSchemaKind UsdShadeNodeDefAPI::_GetSchemaKind() const
66 {
67     return UsdShadeNodeDefAPI::schemaKind;
68 }
69 
70 /* static */
71 bool
CanApply(const UsdPrim & prim,std::string * whyNot)72 UsdShadeNodeDefAPI::CanApply(
73     const UsdPrim &prim, std::string *whyNot)
74 {
75     return prim.CanApplyAPI<UsdShadeNodeDefAPI>(whyNot);
76 }
77 
78 /* static */
79 UsdShadeNodeDefAPI
Apply(const UsdPrim & prim)80 UsdShadeNodeDefAPI::Apply(const UsdPrim &prim)
81 {
82     if (prim.ApplyAPI<UsdShadeNodeDefAPI>()) {
83         return UsdShadeNodeDefAPI(prim);
84     }
85     return UsdShadeNodeDefAPI();
86 }
87 
88 /* static */
89 const TfType &
_GetStaticTfType()90 UsdShadeNodeDefAPI::_GetStaticTfType()
91 {
92     static TfType tfType = TfType::Find<UsdShadeNodeDefAPI>();
93     return tfType;
94 }
95 
96 /* static */
97 bool
_IsTypedSchema()98 UsdShadeNodeDefAPI::_IsTypedSchema()
99 {
100     static bool isTyped = _GetStaticTfType().IsA<UsdTyped>();
101     return isTyped;
102 }
103 
104 /* virtual */
105 const TfType &
_GetTfType() const106 UsdShadeNodeDefAPI::_GetTfType() const
107 {
108     return _GetStaticTfType();
109 }
110 
111 UsdAttribute
GetImplementationSourceAttr() const112 UsdShadeNodeDefAPI::GetImplementationSourceAttr() const
113 {
114     return GetPrim().GetAttribute(UsdShadeTokens->infoImplementationSource);
115 }
116 
117 UsdAttribute
CreateImplementationSourceAttr(VtValue const & defaultValue,bool writeSparsely) const118 UsdShadeNodeDefAPI::CreateImplementationSourceAttr(VtValue const &defaultValue, bool writeSparsely) const
119 {
120     return UsdSchemaBase::_CreateAttr(UsdShadeTokens->infoImplementationSource,
121                        SdfValueTypeNames->Token,
122                        /* custom = */ false,
123                        SdfVariabilityUniform,
124                        defaultValue,
125                        writeSparsely);
126 }
127 
128 UsdAttribute
GetIdAttr() const129 UsdShadeNodeDefAPI::GetIdAttr() const
130 {
131     return GetPrim().GetAttribute(UsdShadeTokens->infoId);
132 }
133 
134 UsdAttribute
CreateIdAttr(VtValue const & defaultValue,bool writeSparsely) const135 UsdShadeNodeDefAPI::CreateIdAttr(VtValue const &defaultValue, bool writeSparsely) const
136 {
137     return UsdSchemaBase::_CreateAttr(UsdShadeTokens->infoId,
138                        SdfValueTypeNames->Token,
139                        /* custom = */ false,
140                        SdfVariabilityUniform,
141                        defaultValue,
142                        writeSparsely);
143 }
144 
145 namespace {
146 static inline TfTokenVector
_ConcatenateAttributeNames(const TfTokenVector & left,const TfTokenVector & right)147 _ConcatenateAttributeNames(const TfTokenVector& left,const TfTokenVector& right)
148 {
149     TfTokenVector result;
150     result.reserve(left.size() + right.size());
151     result.insert(result.end(), left.begin(), left.end());
152     result.insert(result.end(), right.begin(), right.end());
153     return result;
154 }
155 }
156 
157 /*static*/
158 const TfTokenVector&
GetSchemaAttributeNames(bool includeInherited)159 UsdShadeNodeDefAPI::GetSchemaAttributeNames(bool includeInherited)
160 {
161     static TfTokenVector localNames = {
162         UsdShadeTokens->infoImplementationSource,
163         UsdShadeTokens->infoId,
164     };
165     static TfTokenVector allNames =
166         _ConcatenateAttributeNames(
167             UsdAPISchemaBase::GetSchemaAttributeNames(true),
168             localNames);
169 
170     if (includeInherited)
171         return allNames;
172     else
173         return localNames;
174 }
175 
176 PXR_NAMESPACE_CLOSE_SCOPE
177 
178 // ===================================================================== //
179 // Feel free to add custom code below this line. It will be preserved by
180 // the code generator.
181 //
182 // Just remember to wrap code in the appropriate delimiters:
183 // 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'.
184 // ===================================================================== //
185 // --(BEGIN CUSTOM CODE)--
186 
187 #include "pxr/usd/sdr/registry.h"
188 
189 PXR_NAMESPACE_OPEN_SCOPE
190 
191 TF_DEFINE_PRIVATE_TOKENS(
192     _tokens,
193     (info)
194     ((infoSourceAsset, "info:sourceAsset"))
195     ((infoSubIdentifier, "info:sourceAsset:subIdentifier"))
196     ((infoSourceCode, "info:sourceCode"))
197 );
198 
199 TfToken
GetImplementationSource() const200 UsdShadeNodeDefAPI::GetImplementationSource() const
201 {
202     TfToken implSource;
203     GetImplementationSourceAttr().Get(&implSource);
204 
205     if (implSource == UsdShadeTokens->id ||
206         implSource == UsdShadeTokens->sourceAsset ||
207         implSource == UsdShadeTokens->sourceCode) {
208         return implSource;
209     } else {
210         TF_WARN("Found invalid info:implementationSource value '%s' on shader "
211                 "at path <%s>. Falling back to 'id'.", implSource.GetText(),
212                 GetPath().GetText());
213         return UsdShadeTokens->id;
214     }
215 }
216 
217 bool
SetShaderId(const TfToken & id) const218 UsdShadeNodeDefAPI::SetShaderId(const TfToken &id) const
219 {
220     return CreateImplementationSourceAttr(VtValue(UsdShadeTokens->id),
221                                           /*writeSparsely*/ true) &&
222            GetIdAttr().Set(id);
223 }
224 
225 bool
GetShaderId(TfToken * id) const226 UsdShadeNodeDefAPI::GetShaderId(TfToken *id) const
227 {
228     TfToken implSource = GetImplementationSource();
229     if (implSource == UsdShadeTokens->id) {
230         return GetIdAttr().Get(id);
231     }
232     return false;
233 }
234 
235 static
236 TfToken
_GetSourceAssetAttrName(const TfToken & sourceType)237 _GetSourceAssetAttrName(const TfToken &sourceType)
238 {
239     if (sourceType == UsdShadeTokens->universalSourceType) {
240         return _tokens->infoSourceAsset;
241     }
242     return TfToken(SdfPath::JoinIdentifier(TfTokenVector{
243                                     _tokens->info,
244                                     sourceType,
245                                     UsdShadeTokens->sourceAsset}));
246 }
247 
248 bool
SetSourceAsset(const SdfAssetPath & sourceAsset,const TfToken & sourceType) const249 UsdShadeNodeDefAPI::SetSourceAsset(
250     const SdfAssetPath &sourceAsset,
251     const TfToken &sourceType) const
252 {
253     TfToken sourceAssetAttrName = _GetSourceAssetAttrName(sourceType);
254     return CreateImplementationSourceAttr(VtValue(UsdShadeTokens->sourceAsset))
255         && UsdSchemaBase::_CreateAttr(sourceAssetAttrName,
256                                       SdfValueTypeNames->Asset,
257                                       /* custom = */ false,
258                                       SdfVariabilityUniform,
259                                       VtValue(sourceAsset),
260                                       /* writeSparsely */ false);
261 }
262 
263 bool
GetSourceAsset(SdfAssetPath * sourceAsset,const TfToken & sourceType) const264 UsdShadeNodeDefAPI::GetSourceAsset(
265     SdfAssetPath *sourceAsset,
266     const TfToken &sourceType) const
267 {
268     TfToken implSource = GetImplementationSource();
269     if (implSource != UsdShadeTokens->sourceAsset) {
270         return false;
271     }
272 
273     TfToken sourceAssetAttrName = _GetSourceAssetAttrName(sourceType);
274     UsdAttribute sourceAssetAttr = GetPrim().GetAttribute(sourceAssetAttrName);
275     if (sourceAssetAttr) {
276         return sourceAssetAttr.Get(sourceAsset);
277     }
278 
279     if (sourceType != UsdShadeTokens->universalSourceType) {
280         UsdAttribute univSourceAssetAttr = GetPrim().GetAttribute(
281                 _GetSourceAssetAttrName(UsdShadeTokens->universalSourceType));
282         if (univSourceAssetAttr) {
283             return univSourceAssetAttr.Get(sourceAsset);
284         }
285     }
286 
287     return false;
288 }
289 
290 static
291 TfToken
_GetSourceAssetSubIdentifierAttrName(const TfToken & sourceType)292 _GetSourceAssetSubIdentifierAttrName(const TfToken &sourceType)
293 {
294     if (sourceType == UsdShadeTokens->universalSourceType) {
295         return _tokens->infoSubIdentifier;
296     }
297     return TfToken(SdfPath::JoinIdentifier(TfTokenVector{
298                                     _tokens->info,
299                                     sourceType,
300                                     UsdShadeTokens->sourceAsset,
301                                     UsdShadeTokens->subIdentifier}));
302 }
303 
304 bool
SetSourceAssetSubIdentifier(const TfToken & subIdentifier,const TfToken & sourceType) const305 UsdShadeNodeDefAPI::SetSourceAssetSubIdentifier(
306     const TfToken &subIdentifier,
307     const TfToken &sourceType) const
308 {
309     TfToken subIdentifierAttrName =
310         _GetSourceAssetSubIdentifierAttrName(sourceType);
311     return CreateImplementationSourceAttr(VtValue(UsdShadeTokens->sourceAsset))
312         && UsdSchemaBase::_CreateAttr(subIdentifierAttrName,
313                                       SdfValueTypeNames->Token,
314                                       /* custom = */ false,
315                                       SdfVariabilityUniform,
316                                       VtValue(subIdentifier),
317                                       /* writeSparsely */ false);
318 }
319 
320 bool
GetSourceAssetSubIdentifier(TfToken * subIdentifier,const TfToken & sourceType) const321 UsdShadeNodeDefAPI::GetSourceAssetSubIdentifier(
322     TfToken *subIdentifier,
323     const TfToken &sourceType) const
324 {
325     TfToken implSource = GetImplementationSource();
326     if (implSource != UsdShadeTokens->sourceAsset) {
327         return false;
328     }
329 
330     TfToken subIdentifierAttrName =
331         _GetSourceAssetSubIdentifierAttrName(sourceType);
332     UsdAttribute subIdentifierAttr = GetPrim().GetAttribute(
333         subIdentifierAttrName);
334     if (subIdentifierAttr) {
335         return subIdentifierAttr.Get(subIdentifier);
336     }
337 
338     if (sourceType != UsdShadeTokens->universalSourceType) {
339         UsdAttribute univSubIdentifierAttr = GetPrim().GetAttribute(
340             _GetSourceAssetSubIdentifierAttrName(
341                 UsdShadeTokens->universalSourceType));
342         if (univSubIdentifierAttr) {
343             return univSubIdentifierAttr.Get(subIdentifier);
344         }
345     }
346 
347     return false;
348 }
349 
350 static
351 TfToken
_GetSourceCodeAttrName(const TfToken & sourceType)352 _GetSourceCodeAttrName(const TfToken &sourceType)
353 {
354     if (sourceType == UsdShadeTokens->universalSourceType) {
355         return _tokens->infoSourceCode;
356     }
357     return TfToken(SdfPath::JoinIdentifier(TfTokenVector{
358                                     _tokens->info,
359                                     sourceType,
360                                     UsdShadeTokens->sourceCode}));
361 }
362 
363 bool
SetSourceCode(const std::string & sourceCode,const TfToken & sourceType) const364 UsdShadeNodeDefAPI::SetSourceCode(
365     const std::string &sourceCode,
366     const TfToken &sourceType) const
367 {
368     TfToken sourceCodeAttrName = _GetSourceCodeAttrName(sourceType);
369     return CreateImplementationSourceAttr(VtValue(UsdShadeTokens->sourceCode))
370         && UsdSchemaBase::_CreateAttr(sourceCodeAttrName,
371                                       SdfValueTypeNames->String,
372                                       /* custom = */ false,
373                                       SdfVariabilityUniform,
374                                       VtValue(sourceCode),
375                                       /* writeSparsely */ false);
376 }
377 
378 bool
GetSourceCode(std::string * sourceCode,const TfToken & sourceType) const379 UsdShadeNodeDefAPI::GetSourceCode(
380     std::string *sourceCode,
381     const TfToken &sourceType) const
382 {
383     TfToken implSource = GetImplementationSource();
384     if (implSource != UsdShadeTokens->sourceCode) {
385         return false;
386     }
387 
388     TfToken sourceCodeAttrName = _GetSourceCodeAttrName(sourceType);
389     UsdAttribute sourceCodeAttr = GetPrim().GetAttribute(sourceCodeAttrName);
390     if (sourceCodeAttr) {
391         return sourceCodeAttr.Get(sourceCode);
392     }
393 
394     if (sourceType != UsdShadeTokens->universalSourceType) {
395         UsdAttribute univSourceCodeAttr = GetPrim().GetAttribute(
396                 _GetSourceCodeAttrName(UsdShadeTokens->universalSourceType));
397         if (univSourceCodeAttr) {
398             return univSourceCodeAttr.Get(sourceCode);
399         }
400     }
401 
402     return false;
403 }
404 
405 static NdrTokenMap
_GetSdrMetadata(UsdPrim const & prim)406 _GetSdrMetadata(UsdPrim const& prim)
407 {
408     NdrTokenMap result;
409 
410     VtDictionary sdrMetadata;
411     if (prim.GetMetadata(UsdShadeTokens->sdrMetadata, &sdrMetadata)){
412         for (const auto &it : sdrMetadata) {
413             result[TfToken(it.first)] = TfStringify(it.second);
414         }
415     }
416 
417     return result;
418 }
419 
420 SdrShaderNodeConstPtr
GetShaderNodeForSourceType(const TfToken & sourceType) const421 UsdShadeNodeDefAPI::GetShaderNodeForSourceType(const TfToken &sourceType) const
422 {
423     TfToken implSource = GetImplementationSource();
424     if (implSource == UsdShadeTokens->id) {
425         TfToken shaderId;
426         if (GetShaderId(&shaderId)) {
427             return SdrRegistry::GetInstance().GetShaderNodeByIdentifierAndType(
428                     shaderId, sourceType);
429         }
430     } else if (implSource == UsdShadeTokens->sourceAsset) {
431         SdfAssetPath sourceAsset;
432         if (GetSourceAsset(&sourceAsset, sourceType)) {
433             TfToken subIdentifier;
434             GetSourceAssetSubIdentifier(&subIdentifier, sourceType);
435             return SdrRegistry::GetInstance().GetShaderNodeFromAsset(
436                 sourceAsset, _GetSdrMetadata(GetPrim()), subIdentifier, sourceType);
437         }
438     } else if (implSource == UsdShadeTokens->sourceCode) {
439         std::string sourceCode;
440         if (GetSourceCode(&sourceCode, sourceType)) {
441             return SdrRegistry::GetInstance().GetShaderNodeFromSourceCode(
442                 sourceCode, sourceType, _GetSdrMetadata(GetPrim()));
443         }
444     }
445 
446     return nullptr;
447 }
448 
449 PXR_NAMESPACE_CLOSE_SCOPE
450