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/materialAPI.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<UsdRiMaterialAPI,
38         TfType::Bases< UsdAPISchemaBase > >();
39 
40 }
41 
42 TF_DEFINE_PRIVATE_TOKENS(
43     _schemaTokens,
44     (RiMaterialAPI)
45 );
46 
47 /* virtual */
~UsdRiMaterialAPI()48 UsdRiMaterialAPI::~UsdRiMaterialAPI()
49 {
50 }
51 
52 /* static */
53 UsdRiMaterialAPI
Get(const UsdStagePtr & stage,const SdfPath & path)54 UsdRiMaterialAPI::Get(const UsdStagePtr &stage, const SdfPath &path)
55 {
56     if (!stage) {
57         TF_CODING_ERROR("Invalid stage");
58         return UsdRiMaterialAPI();
59     }
60     return UsdRiMaterialAPI(stage->GetPrimAtPath(path));
61 }
62 
63 
64 /* virtual */
_GetSchemaKind() const65 UsdSchemaKind UsdRiMaterialAPI::_GetSchemaKind() const
66 {
67     return UsdRiMaterialAPI::schemaKind;
68 }
69 
70 /* static */
71 bool
CanApply(const UsdPrim & prim,std::string * whyNot)72 UsdRiMaterialAPI::CanApply(
73     const UsdPrim &prim, std::string *whyNot)
74 {
75     return prim.CanApplyAPI<UsdRiMaterialAPI>(whyNot);
76 }
77 
78 /* static */
79 UsdRiMaterialAPI
Apply(const UsdPrim & prim)80 UsdRiMaterialAPI::Apply(const UsdPrim &prim)
81 {
82     if (prim.ApplyAPI<UsdRiMaterialAPI>()) {
83         return UsdRiMaterialAPI(prim);
84     }
85     return UsdRiMaterialAPI();
86 }
87 
88 /* static */
89 const TfType &
_GetStaticTfType()90 UsdRiMaterialAPI::_GetStaticTfType()
91 {
92     static TfType tfType = TfType::Find<UsdRiMaterialAPI>();
93     return tfType;
94 }
95 
96 /* static */
97 bool
_IsTypedSchema()98 UsdRiMaterialAPI::_IsTypedSchema()
99 {
100     static bool isTyped = _GetStaticTfType().IsA<UsdTyped>();
101     return isTyped;
102 }
103 
104 /* virtual */
105 const TfType &
_GetTfType() const106 UsdRiMaterialAPI::_GetTfType() const
107 {
108     return _GetStaticTfType();
109 }
110 
111 UsdAttribute
GetSurfaceAttr() const112 UsdRiMaterialAPI::GetSurfaceAttr() const
113 {
114     return GetPrim().GetAttribute(UsdRiTokens->outputsRiSurface);
115 }
116 
117 UsdAttribute
CreateSurfaceAttr(VtValue const & defaultValue,bool writeSparsely) const118 UsdRiMaterialAPI::CreateSurfaceAttr(VtValue const &defaultValue, bool writeSparsely) const
119 {
120     return UsdSchemaBase::_CreateAttr(UsdRiTokens->outputsRiSurface,
121                        SdfValueTypeNames->Token,
122                        /* custom = */ false,
123                        SdfVariabilityVarying,
124                        defaultValue,
125                        writeSparsely);
126 }
127 
128 UsdAttribute
GetDisplacementAttr() const129 UsdRiMaterialAPI::GetDisplacementAttr() const
130 {
131     return GetPrim().GetAttribute(UsdRiTokens->outputsRiDisplacement);
132 }
133 
134 UsdAttribute
CreateDisplacementAttr(VtValue const & defaultValue,bool writeSparsely) const135 UsdRiMaterialAPI::CreateDisplacementAttr(VtValue const &defaultValue, bool writeSparsely) const
136 {
137     return UsdSchemaBase::_CreateAttr(UsdRiTokens->outputsRiDisplacement,
138                        SdfValueTypeNames->Token,
139                        /* custom = */ false,
140                        SdfVariabilityVarying,
141                        defaultValue,
142                        writeSparsely);
143 }
144 
145 UsdAttribute
GetVolumeAttr() const146 UsdRiMaterialAPI::GetVolumeAttr() const
147 {
148     return GetPrim().GetAttribute(UsdRiTokens->outputsRiVolume);
149 }
150 
151 UsdAttribute
CreateVolumeAttr(VtValue const & defaultValue,bool writeSparsely) const152 UsdRiMaterialAPI::CreateVolumeAttr(VtValue const &defaultValue, bool writeSparsely) const
153 {
154     return UsdSchemaBase::_CreateAttr(UsdRiTokens->outputsRiVolume,
155                        SdfValueTypeNames->Token,
156                        /* custom = */ false,
157                        SdfVariabilityVarying,
158                        defaultValue,
159                        writeSparsely);
160 }
161 
162 namespace {
163 static inline TfTokenVector
_ConcatenateAttributeNames(const TfTokenVector & left,const TfTokenVector & right)164 _ConcatenateAttributeNames(const TfTokenVector& left,const TfTokenVector& right)
165 {
166     TfTokenVector result;
167     result.reserve(left.size() + right.size());
168     result.insert(result.end(), left.begin(), left.end());
169     result.insert(result.end(), right.begin(), right.end());
170     return result;
171 }
172 }
173 
174 /*static*/
175 const TfTokenVector&
GetSchemaAttributeNames(bool includeInherited)176 UsdRiMaterialAPI::GetSchemaAttributeNames(bool includeInherited)
177 {
178     static TfTokenVector localNames = {
179         UsdRiTokens->outputsRiSurface,
180         UsdRiTokens->outputsRiDisplacement,
181         UsdRiTokens->outputsRiVolume,
182     };
183     static TfTokenVector allNames =
184         _ConcatenateAttributeNames(
185             UsdAPISchemaBase::GetSchemaAttributeNames(true),
186             localNames);
187 
188     if (includeInherited)
189         return allNames;
190     else
191         return localNames;
192 }
193 
194 PXR_NAMESPACE_CLOSE_SCOPE
195 
196 // ===================================================================== //
197 // Feel free to add custom code below this line. It will be preserved by
198 // the code generator.
199 //
200 // Just remember to wrap code in the appropriate delimiters:
201 // 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'.
202 // ===================================================================== //
203 // --(BEGIN CUSTOM CODE)--
204 
205 #include "pxr/base/tf/envSetting.h"
206 #include "pxr/usd/usdShade/connectableAPI.h"
207 #include "pxr/usd/usdShade/material.h"
208 
209 PXR_NAMESPACE_OPEN_SCOPE
210 
211 TF_DEFINE_PRIVATE_TOKENS(
212     _tokens,
213     ((defaultOutputName, "outputs:out"))
214     (ri)
215 
216     // deprecated tokens for handling backwards compatibility.
217     ((bxdfOutputName, "ri:bxdf"))
218     ((bxdfOutputAttrName, "outputs:ri:bxdf"))
219     ((riLookBxdf, "riLook:bxdf"))
220 );
221 
222 UsdShadeShader
_GetSourceShaderObject(const UsdShadeOutput & output,bool ignoreBaseMaterial) const223 UsdRiMaterialAPI::_GetSourceShaderObject(const UsdShadeOutput &output,
224                                          bool ignoreBaseMaterial) const
225 {
226     // If output doesn't have a valid attribute, return an invalid shader.
227     if (!output.GetAttr()) {
228         return UsdShadeShader();
229     }
230 
231     if (ignoreBaseMaterial &&
232         UsdShadeConnectableAPI::IsSourceConnectionFromBaseMaterial(output)) {
233         return UsdShadeShader();
234     }
235 
236     UsdShadeConnectableAPI source;
237     TfToken sourceName;
238     UsdShadeAttributeType sourceType;
239 
240     if (UsdShadeConnectableAPI::GetConnectedSource(output,
241             &source, &sourceName, &sourceType)) {
242         return source;
243     }
244 
245     return UsdShadeShader();
246 }
247 
248 UsdShadeOutput
_GetBxdfOutput(const UsdPrim & materialPrim) const249 UsdRiMaterialAPI::_GetBxdfOutput(const UsdPrim &materialPrim) const
250 {
251     // Check if the deprecated bxdf output is present.
252     if (const UsdAttribute bxdfAttr = materialPrim.GetAttribute(
253             _tokens->bxdfOutputAttrName)) {
254         return UsdShadeOutput(bxdfAttr);
255     }
256     return UsdShadeOutput();
257 }
258 
259 UsdShadeShader
GetSurface(bool ignoreBaseMaterial) const260 UsdRiMaterialAPI::GetSurface(bool ignoreBaseMaterial) const
261 {
262     if (UsdShadeShader surface =
263             _GetSourceShaderObject(GetSurfaceOutput(), ignoreBaseMaterial)) {
264         return surface;
265     }
266 
267     if (UsdShadeOutput bxdfOutput = _GetBxdfOutput(GetPrim())) {
268         return _GetSourceShaderObject(bxdfOutput, ignoreBaseMaterial);
269     }
270 
271     return UsdShadeShader();
272 }
273 
274 UsdShadeShader
GetDisplacement(bool ignoreBaseMaterial) const275 UsdRiMaterialAPI::GetDisplacement(bool ignoreBaseMaterial) const
276 {
277     return _GetSourceShaderObject(GetDisplacementOutput(), ignoreBaseMaterial);
278 }
279 
280 UsdShadeShader
GetVolume(bool ignoreBaseMaterial) const281 UsdRiMaterialAPI::GetVolume(bool ignoreBaseMaterial) const
282 {
283     return _GetSourceShaderObject(GetVolumeOutput(), ignoreBaseMaterial);
284 }
285 
286 UsdShadeOutput
GetSurfaceOutput() const287 UsdRiMaterialAPI::GetSurfaceOutput() const
288 {
289     return  UsdShadeMaterial(GetPrim()).GetSurfaceOutput(_tokens->ri);
290 }
291 
292 UsdShadeOutput
GetDisplacementOutput() const293 UsdRiMaterialAPI::GetDisplacementOutput() const
294 {
295     return UsdShadeMaterial(GetPrim()).GetDisplacementOutput(_tokens->ri);
296 }
297 
298 UsdShadeOutput
GetVolumeOutput() const299 UsdRiMaterialAPI::GetVolumeOutput() const
300 {
301     return UsdShadeMaterial(GetPrim()).GetVolumeOutput(_tokens->ri);
302 }
303 
304 bool
SetSurfaceSource(const SdfPath & surfacePath) const305 UsdRiMaterialAPI::SetSurfaceSource(const SdfPath &surfacePath) const
306 {
307     UsdShadeOutput surfaceOutput = UsdShadeMaterial(GetPrim())
308             .CreateSurfaceOutput(/*purpose*/ _tokens->ri);
309     return UsdShadeConnectableAPI::ConnectToSource(
310         surfaceOutput, surfacePath.IsPropertyPath() ? surfacePath :
311             surfacePath.AppendProperty(_tokens->defaultOutputName));
312 }
313 
314 bool
SetDisplacementSource(const SdfPath & displacementPath) const315 UsdRiMaterialAPI::SetDisplacementSource(const SdfPath &displacementPath) const
316 {
317     UsdShadeOutput displacementOutput = UsdShadeMaterial(GetPrim())
318             .CreateDisplacementOutput(/*purpose*/ _tokens->ri);
319     return UsdShadeConnectableAPI::ConnectToSource(
320         displacementOutput, displacementPath.IsPropertyPath() ?
321             displacementPath :
322             displacementPath.AppendProperty(_tokens->defaultOutputName));
323 }
324 
325 bool
SetVolumeSource(const SdfPath & volumePath) const326 UsdRiMaterialAPI::SetVolumeSource(const SdfPath &volumePath) const
327 {
328     UsdShadeOutput volumeOutput = UsdShadeMaterial(GetPrim())
329             .CreateVolumeOutput(/*purpose*/ _tokens->ri);
330     return UsdShadeConnectableAPI::ConnectToSource(
331         volumeOutput, volumePath.IsPropertyPath() ?
332             volumePath :
333             volumePath.AppendProperty(_tokens->defaultOutputName));
334 }
335 
336 UsdShadeNodeGraph::InterfaceInputConsumersMap
ComputeInterfaceInputConsumersMap(bool computeTransitiveConsumers) const337 UsdRiMaterialAPI::ComputeInterfaceInputConsumersMap(
338         bool computeTransitiveConsumers) const
339 {
340     return UsdShadeNodeGraph(GetPrim()).ComputeInterfaceInputConsumersMap(
341         computeTransitiveConsumers);
342 }
343 
344 PXR_NAMESPACE_CLOSE_SCOPE
345