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 #ifndef USDSHADE_GENERATED_MATERIALBINDINGAPI_H
25 #define USDSHADE_GENERATED_MATERIALBINDINGAPI_H
26 
27 /// \file usdShade/materialBindingAPI.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/usdShade/api.h"
31 #include "pxr/usd/usd/apiSchemaBase.h"
32 #include "pxr/usd/usd/prim.h"
33 #include "pxr/usd/usd/stage.h"
34 #include "pxr/usd/usdShade/tokens.h"
35 
36 #include "pxr/usd/usd/collectionAPI.h"
37 #include "pxr/usd/usdGeom/subset.h"
38 #include "pxr/usd/usdShade/material.h"
39 #include <tbb/concurrent_unordered_map.h>
40 
41 #include "pxr/base/vt/value.h"
42 
43 #include "pxr/base/gf/vec3d.h"
44 #include "pxr/base/gf/vec3f.h"
45 #include "pxr/base/gf/matrix4d.h"
46 
47 #include "pxr/base/tf/token.h"
48 #include "pxr/base/tf/type.h"
49 
50 PXR_NAMESPACE_OPEN_SCOPE
51 
52 class SdfAssetPath;
53 
54 // -------------------------------------------------------------------------- //
55 // MATERIALBINDINGAPI                                                         //
56 // -------------------------------------------------------------------------- //
57 
58 /// \class UsdShadeMaterialBindingAPI
59 ///
60 /// UsdShadeMaterialBindingAPI is an API schema that provides an
61 /// interface for binding materials to prims or collections of prims
62 /// (represented by UsdCollectionAPI objects).
63 ///
64 /// In the USD shading model, each renderable gprim computes a single
65 /// <b>resolved Material</b> that will be used to shade the gprim (exceptions,
66 /// of course, for gprims that possess UsdGeomSubsets, as each subset can be
67 /// shaded by a different Material).  A gprim <b>and each of its ancestor
68 /// prims</b> can possess, through the MaterialBindingAPI, both a
69 /// <b>direct</b> binding to a Material, and any number of
70 /// <b>collection-based</b> bindings to Materials; each binding can be generic
71 /// or declared for a particular <b>purpose</b>, and given a specific <b>binding
72 /// strength</b>. It is the process of "material resolution" (see
73 /// \ref UsdShadeMaterialBindingAPI_MaterialResolution) that examines all of
74 /// these bindings, and selects the one Material that best matches the
75 /// client's needs.
76 ///
77 /// The intent of <b>purpose</b> is that each gprim should be able to resolve a
78 /// Material for any given purpose, which implies it can have differently bound
79 /// materials for different purposes. There are two <i>special</i> values of
80 /// <b>purpose</b> defined in UsdShade, although the API fully supports
81 /// specifying arbitrary values for it, for the sake of extensibility:
82 /// <ul><li><b>UsdShadeTokens->full</b>: to be used when the purpose of the
83 /// render is entirely to visualize the truest representation of a scene,
84 /// considering all lighting and material information, at highest fidelity.</li>
85 /// <li><b>UsdShadeTokens->preview</b>: to be used when the render is in
86 /// service of a goal other than a high fidelity "full" render (such as scene
87 /// manipulation, modeling, or realtime playback). Latency and speed are
88 /// generally of greater concern for preview renders, therefore preview
89 /// materials are generally designed to be "lighterweight" compared to full
90 /// materials.</li></ul>
91 /// A binding can also have no specific purpose at all, in which
92 /// case, it is considered to be the fallback or all-purpose binding (denoted
93 /// by the empty-valued token <b>UsdShadeTokens->allPurpose</b>).
94 ///
95 /// The <b>purpose</b> of a material binding is encoded in the name of the
96 /// binding relationship.
97 /// <ul><li>
98 /// In the case of a direct binding, the <i>allPurpose</i> binding is
99 /// represented by the relationship named <b>"material:binding"</b>.
100 /// Special-purpose direct bindings are represented by relationships named
101 /// <b>"material:binding:<i>purpose</i></b>. A direct binding relationship
102 /// must have a single target path that points to a <b>UsdShadeMaterial</b>.</li>
103 /// <li>
104 /// In the case of a collection-based binding, the <i>allPurpose</i> binding is
105 /// represented by a relationship named
106 /// "material:binding:collection:<i>bindingName</i>", where
107 /// <b>bindingName</b> establishes an identity for the binding that is unique
108 /// on the prim. Attempting to establish two collection bindings of the same
109 /// name on the same prim will result in the first binding simply being
110 /// overridden. A special-purpose collection-based binding is represented by a
111 /// relationship named "material:binding:collection:<i>purpose:bindingName</i>".
112 /// A collection-based binding relationship must have exacly two targets, one of
113 /// which should be a collection-path (see
114 /// ef UsdCollectionAPI::GetCollectionPath()) and the other should point to a
115 /// <b>UsdShadeMaterial</b>. In the future, we may allow a single collection
116 /// binding to target multiple collections, if we can establish a reasonable
117 /// round-tripping pattern for applications that only allow a single collection
118 /// to be associated with each Material.
119 /// </li>
120 /// </ul>
121 ///
122 /// <b>Note:</b> Both <b>bindingName</b> and <b>purpose</b> must be
123 /// non-namespaced tokens. This allows us to know the role of a binding
124 /// relationship simply from the number of tokens in it.
125 /// <ul><li><b>Two tokens</b>: the fallback, "all purpose", direct binding,
126 /// <i>material:binding</i></li>
127 /// <li><b>Three tokens</b>: a purpose-restricted, direct, fallback binding,
128 /// e.g. material:binding:preview</li>
129 /// <li><b>Four tokens</b>: an all-purpose, collection-based binding, e.g.
130 /// material:binding:collection:metalBits</li>
131 /// <li><b>Five tokens</b>: a purpose-restricted, collection-based binding,
132 /// e.g. material:binding:collection:full:metalBits</li>
133 /// </ul>
134 ///
135 /// A <b>binding-strength</b> value is used to specify whether a binding
136 /// authored on a prim should be weaker or stronger than bindings that appear
137 /// lower in namespace. We encode the binding strength with as token-valued
138 /// metadata <b>'bindMaterialAs'</b> for future flexibility, even though for
139 /// now, there are only two possible values:
140 /// <i>UsdShadeTokens->weakerThanDescendants</i> and
141 /// <i>UsdShadeTokens->strongerThanDescendants</i>. When binding-strength is
142 /// not authored (i.e. empty) on a binding-relationship, the default behavior
143 /// matches UsdShadeTokens->weakerThanDescendants.
144 ///
145 /// \note If a material binding relationship is a built-in property defined as
146 /// part of a typed prim's schema, a fallback value should not be provided for
147 /// it. This is because the "material resolution" algorithm only conisders
148 /// <i>authored</i> properties.
149 ///
150 ///
151 class UsdShadeMaterialBindingAPI : public UsdAPISchemaBase
152 {
153 public:
154     /// Compile time constant representing what kind of schema this class is.
155     ///
156     /// \sa UsdSchemaKind
157     static const UsdSchemaKind schemaKind = UsdSchemaKind::SingleApplyAPI;
158 
159     /// Construct a UsdShadeMaterialBindingAPI on UsdPrim \p prim .
160     /// Equivalent to UsdShadeMaterialBindingAPI::Get(prim.GetStage(), prim.GetPath())
161     /// for a \em valid \p prim, but will not immediately throw an error for
162     /// an invalid \p prim
163     explicit UsdShadeMaterialBindingAPI(const UsdPrim& prim=UsdPrim())
UsdAPISchemaBase(prim)164         : UsdAPISchemaBase(prim)
165     {
166     }
167 
168     /// Construct a UsdShadeMaterialBindingAPI on the prim held by \p schemaObj .
169     /// Should be preferred over UsdShadeMaterialBindingAPI(schemaObj.GetPrim()),
170     /// as it preserves SchemaBase state.
UsdShadeMaterialBindingAPI(const UsdSchemaBase & schemaObj)171     explicit UsdShadeMaterialBindingAPI(const UsdSchemaBase& schemaObj)
172         : UsdAPISchemaBase(schemaObj)
173     {
174     }
175 
176     /// Destructor.
177     USDSHADE_API
178     virtual ~UsdShadeMaterialBindingAPI();
179 
180     /// Return a vector of names of all pre-declared attributes for this schema
181     /// class and all its ancestor classes.  Does not include attributes that
182     /// may be authored by custom/extended methods of the schemas involved.
183     USDSHADE_API
184     static const TfTokenVector &
185     GetSchemaAttributeNames(bool includeInherited=true);
186 
187     /// Return a UsdShadeMaterialBindingAPI holding the prim adhering to this
188     /// schema at \p path on \p stage.  If no prim exists at \p path on
189     /// \p stage, or if the prim at that path does not adhere to this schema,
190     /// return an invalid schema object.  This is shorthand for the following:
191     ///
192     /// \code
193     /// UsdShadeMaterialBindingAPI(stage->GetPrimAtPath(path));
194     /// \endcode
195     ///
196     USDSHADE_API
197     static UsdShadeMaterialBindingAPI
198     Get(const UsdStagePtr &stage, const SdfPath &path);
199 
200 
201     /// Returns true if this <b>single-apply</b> API schema can be applied to
202     /// the given \p prim. If this schema can not be a applied to the prim,
203     /// this returns false and, if provided, populates \p whyNot with the
204     /// reason it can not be applied.
205     ///
206     /// Note that if CanApply returns false, that does not necessarily imply
207     /// that calling Apply will fail. Callers are expected to call CanApply
208     /// before calling Apply if they want to ensure that it is valid to
209     /// apply a schema.
210     ///
211     /// \sa UsdPrim::GetAppliedSchemas()
212     /// \sa UsdPrim::HasAPI()
213     /// \sa UsdPrim::CanApplyAPI()
214     /// \sa UsdPrim::ApplyAPI()
215     /// \sa UsdPrim::RemoveAPI()
216     ///
217     USDSHADE_API
218     static bool
219     CanApply(const UsdPrim &prim, std::string *whyNot=nullptr);
220 
221     /// Applies this <b>single-apply</b> API schema to the given \p prim.
222     /// This information is stored by adding "MaterialBindingAPI" to the
223     /// token-valued, listOp metadata \em apiSchemas on the prim.
224     ///
225     /// \return A valid UsdShadeMaterialBindingAPI object is returned upon success.
226     /// An invalid (or empty) UsdShadeMaterialBindingAPI object is returned upon
227     /// failure. See \ref UsdPrim::ApplyAPI() for conditions
228     /// resulting in failure.
229     ///
230     /// \sa UsdPrim::GetAppliedSchemas()
231     /// \sa UsdPrim::HasAPI()
232     /// \sa UsdPrim::CanApplyAPI()
233     /// \sa UsdPrim::ApplyAPI()
234     /// \sa UsdPrim::RemoveAPI()
235     ///
236     USDSHADE_API
237     static UsdShadeMaterialBindingAPI
238     Apply(const UsdPrim &prim);
239 
240 protected:
241     /// Returns the kind of schema this class belongs to.
242     ///
243     /// \sa UsdSchemaKind
244     USDSHADE_API
245     UsdSchemaKind _GetSchemaKind() const override;
246 
247 private:
248     // needs to invoke _GetStaticTfType.
249     friend class UsdSchemaRegistry;
250     USDSHADE_API
251     static const TfType &_GetStaticTfType();
252 
253     static bool _IsTypedSchema();
254 
255     // override SchemaBase virtuals.
256     USDSHADE_API
257     const TfType &_GetTfType() const override;
258 
259 public:
260     // ===================================================================== //
261     // Feel free to add custom code below this line, it will be preserved by
262     // the code generator.
263     //
264     // Just remember to:
265     //  - Close the class declaration with };
266     //  - Close the namespace with PXR_NAMESPACE_CLOSE_SCOPE
267     //  - Close the include guard with #endif
268     // ===================================================================== //
269     // --(BEGIN CUSTOM CODE)--
270 
271     /// \anchor UsdShadeMaterialBindingAPI_SchemaProperties
272     /// \name Schema property and associated data retrieval API
273     ///
274     /// This section contains API for fetching the two kinds of binding
275     /// relationships and for computing the corresponding bindings.
276     ///
277     /// @{
278 
279     /// Returns the direct material-binding relationship on this prim for the
280     /// given material purpose.
281     ///
282     /// The material purpose of the relationship that's returned will match
283     /// the specified \p materialPurpose.
284     USDSHADE_API
285     UsdRelationship GetDirectBindingRel(
286         const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const;
287 
288     /// Returns the collection-based material-binding relationship with the
289     /// given \p bindingName and \p materialPurpose on this prim.
290     ///
291     /// For info on \p bindingName, see UsdShadeMaterialBindingAPI::Bind().
292     /// The material purpose of the relationship that's returned will match
293     /// the specified \p materialPurpose.
294     USDSHADE_API
295     UsdRelationship GetCollectionBindingRel(
296         const TfToken &bindingName,
297         const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const;
298 
299     /// Returns the list of collection-based material binding relationships
300     /// on this prim for the given material purpose, \p materialPurpose.
301     ///
302     /// The returned list of binding relationships will be in native property
303     /// order. See UsdPrim::GetPropertyOrder(), UsdPrim::SetPropertyOrder().
304     /// Bindings that appear earlier in the property order are considered to be
305     /// stronger than the ones that come later. See rule #6 in
306     /// \ref UsdShadeMaterialBindingAPI_MaterialResolution.
307     USDSHADE_API
308     std::vector<UsdRelationship> GetCollectionBindingRels(
309         const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const;
310 
311     /// \class DirectBinding
312     /// This class represents a direct material binding.
313     class DirectBinding {
314     public:
315         /// Default constructor initializes a DirectBinding object with
316         /// invalid material and bindingRel data members.
DirectBinding()317         DirectBinding()
318         {}
319 
320         USDSHADE_API
321         explicit DirectBinding(const UsdRelationship &bindingRel);
322 
323         /// Gets the material object that this direct binding binds to.
324         USDSHADE_API
325         UsdShadeMaterial GetMaterial() const;
326 
327         /// Returns the path to the material that is bound to by this
328         /// direct binding.
GetMaterialPath()329         const SdfPath &GetMaterialPath() const {
330             return _materialPath;
331         }
332 
333         /// Returns the binding-relationship that represents this direct
334         /// binding.
GetBindingRel()335         const UsdRelationship &GetBindingRel() const {
336             return _bindingRel;
337         }
338 
339         /// Returns the purpose of the direct binding.
GetMaterialPurpose()340         const TfToken &GetMaterialPurpose() const {
341             return _materialPurpose;
342         }
343 
344     private:
345         // The path to the material that is bound to.
346         SdfPath _materialPath;
347 
348         // The binding relationship.
349         UsdRelationship _bindingRel;
350 
351         // The purpose of the material binding.
352         TfToken _materialPurpose;
353     };
354 
355     /// \class CollectionBinding
356     /// This struct is used to represent a collection-based material binding,
357     /// which contains two objects - a collection and a bound material.
358     class CollectionBinding {
359     public:
360         /// Default constructor initializes a CollectionBinding object with
361         /// invalid collection, material and bindingRel data members.
CollectionBinding()362         CollectionBinding()
363         {}
364 
365         /// Constructs a CollectionBinding object from the given collection-
366         /// binding relationship. This inspects the targets of the relationship
367         /// and determines the bound collection and the target material that
368         /// the collection is bound to.
369         USDSHADE_API
370         explicit CollectionBinding(const UsdRelationship &collBindingRel);
371 
372         /// Constructs and returns the material object that this
373         /// collection-based binding binds to.
374         USDSHADE_API
375         UsdShadeMaterial GetMaterial() const;
376 
377         /// Constructs and returns the CollectionAPI object for the collection
378         /// that is bound by this collection-binding.
379         USDSHADE_API
380         UsdCollectionAPI GetCollection() const;
381 
382         /// Returns true if the CollectionBinding points to a valid material
383         /// and collection.
IsValid()384         bool IsValid() const {
385             return GetCollection() && GetMaterial();
386         }
387         /// Returns the path to the collection that is bound by this binding.
GetCollectionPath()388         const SdfPath &GetCollectionPath() const {
389             return _collectionPath;
390         }
391 
392         /// Returns the path to the material that is bound to by this binding.
GetMaterialPath()393         const SdfPath &GetMaterialPath() const {
394             return _materialPath;
395         }
396 
397         /// Returns the binding-relationship that represents this collection-
398         /// based binding.
GetBindingRel()399         const UsdRelationship &GetBindingRel() const {
400             return _bindingRel;
401         }
402 
403     private:
404         // The collection being bound.
405         SdfPath _collectionPath;
406 
407         // The material that is bound to.
408         SdfPath _materialPath;
409 
410         // The relationship that binds the collection to the material.
411         UsdRelationship _bindingRel;
412     };
413 
414     using CollectionBindingVector = std::vector<CollectionBinding>;
415 
416     /// Computes and returns the direct binding for the given material purpose
417     /// on this prim.
418     ///
419     /// The returned binding always has the specified \p materialPurpose
420     /// (i.e. the all-purpose binding is not returned if a special purpose
421     /// binding is requested).
422     ///
423     /// If the direct binding is to a prim that is not a Material, this does not
424     /// generate an error, but the returned Material will be invalid (i.e.
425     /// evaluate to false).
426     USDSHADE_API
427     DirectBinding GetDirectBinding(
428         const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const;
429 
430     /// Returns all the collection-based bindings on this prim for the given
431     /// material purpose.
432     ///
433     /// The returned CollectionBinding objects always have the specified
434     /// \p materialPurpose (i.e. the all-purpose binding is not returned if a
435     /// special purpose binding is requested).
436     ///
437     /// If one or more collection based bindings are to prims that are not
438     /// Materials, this does not generate an error, but the corresponding
439     /// Material(s) will be invalid (i.e. evaluate to false).
440     ///
441     /// The python version of this API returns a tuple containing the
442     /// vector of CollectionBinding objects and the corresponding vector
443     /// of binding relationships.
444     ///
445     /// The returned list of collection-bindings will be in native property
446     /// order of the associated binding relationships. See
447     /// UsdPrim::GetPropertyOrder(), UsdPrim::SetPropertyOrder().
448     /// Binding relationships that come earlier in the list are considered to
449     /// be stronger than the ones that come later. See rule #6 in
450     /// \ref UsdShadeMaterialBindingAPI_MaterialResolution.
451     USDSHADE_API
452     CollectionBindingVector GetCollectionBindings(
453         const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const;
454 
455     /// Resolves the 'bindMaterialAs' token-valued metadata on the given binding
456     /// relationship and returns it.
457     /// If the resolved value is empty, this returns the fallback value
458     /// UsdShadeTokens->weakerThanDescendants.
459     ///
460     /// \sa UsdShadeMaterialBindingAPI::SetMaterialBindingStrength()
461     USDSHADE_API
462     static TfToken GetMaterialBindingStrength(
463         const UsdRelationship &bindingRel);
464 
465     /// Sets the 'bindMaterialAs' token-valued metadata on the given binding
466     /// relationship.
467     ///
468     /// If \p bindingStrength is <i>UsdShadeTokens->fallbackStrength</i>, the
469     /// value UsdShadeTokens->weakerThanDescendants is authored sparsely, i.e.
470     /// only when there is a different existing bindingStrength value.
471     /// To stamp out the bindingStrength value explicitly, clients can pass in
472     /// UsdShadeTokens->weakerThanDescendants or
473     /// UsdShadeTokens->strongerThanDescendants directly.
474 
475     /// Returns true on success, false otherwise.
476     ///
477     /// \sa UsdShadeMaterialBindingAPI::GetMaterialBindingStrength()
478     USDSHADE_API
479     static bool SetMaterialBindingStrength(
480         const UsdRelationship &bindingRel,
481         const TfToken &bindingStrength);
482 
483     /// @}
484 
485     /// \anchor UsdShadeMaterialBindingAPI_Binding
486     /// \name Binding authoring and clearing API
487     ///
488     /// This section provides API for authoring and clearing both direct and
489     /// collection-based material bindings on a prim.
490     ///
491     /// @{
492 
493     /// Authors a direct binding to the given \p material on this prim.
494     ///
495     /// If \p bindingStrength is UsdShadeTokens->fallbackStrength, the value
496     /// UsdShadeTokens->weakerThanDescendants is authored sparsely.
497     /// To stamp out the bindingStrength value explicitly, clients can pass in
498     /// UsdShadeTokens->weakerThanDescendants or
499     /// UsdShadeTokens->strongerThanDescendants directly.
500     ///
501     /// If \p materialPurpose is specified and isn't equal to
502     /// UsdShadeTokens->allPurpose, the binding only applies to the specified
503     /// material purpose.
504     ///
505     /// Note that UsdShadeMaterialBindingAPI is a SingleAppliedAPI schema which
506     /// when applied updates the prim definition accordingly. This information
507     /// on the prim definition is helpful in multiple queries and more
508     /// performant. Hence its recommended to call
509     /// UsdShadeMaterialBindingAPI::Apply() when Binding a material.
510     ///
511     /// Returns true on success, false otherwise.
512     USDSHADE_API
513     bool Bind(
514         const UsdShadeMaterial &material,
515         const TfToken &bindingStrength=UsdShadeTokens->fallbackStrength,
516         const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const;
517 
518     /// Authors a collection-based binding, which binds the given \p material
519     /// to the given \p collection on this prim.
520     ///
521     /// \p bindingName establishes an identity for the binding that is unique
522     /// on the prim. Attempting to establish two collection bindings of the same
523     /// name on the same prim will result in the first binding simply being
524     /// overridden. If \p bindingName is empty, it is set to the base-name of
525     /// the collection being bound (which is the collection-name with any
526     /// namespaces stripped out). If there are multiple collections with the
527     /// same base-name being bound at the same prim, clients should pass in a
528     /// unique binding name per binding, in order to preserve all bindings.
529     /// The binding name used in constructing the collection-binding
530     /// relationship name shoud not contain namespaces. Hence, a coding error
531     /// is issued and no binding is authored if the provided value of
532     /// \p bindingName is non-empty and contains namespaces.
533     ///
534     /// If \p bindingStrength is <i>UsdShadeTokens->fallbackStrength</i>, the
535     /// value UsdShadeTokens->weakerThanDescendants is authored sparsely, i.e.
536     /// only when there is an existing binding with a different bindingStrength.
537     /// To stamp out the bindingStrength value explicitly, clients can pass in
538     /// UsdShadeTokens->weakerThanDescendants or
539     /// UsdShadeTokens->strongerThanDescendants directly.
540     ///
541     /// If \p materialPurpose is specified and isn't equal to
542     /// UsdShadeTokens->allPurpose, the binding only applies to the specified
543     /// material purpose.
544     ///
545     /// Note that UsdShadeMaterialBindingAPI is a SingleAppliedAPI schema which
546     /// when applied updates the prim definition accordingly. This information
547     /// on the prim definition is helpful in multiple queries and more
548     /// performant. Hence its recommended to call
549     /// UsdShadeMaterialBindingAPI::Apply() when Binding a material.
550     ///
551     /// Returns true on success, false otherwise.
552     USDSHADE_API
553     bool Bind(
554         const UsdCollectionAPI &collection,
555         const UsdShadeMaterial &material,
556         const TfToken &bindingName=TfToken(),
557         const TfToken &bindingStrength=UsdShadeTokens->fallbackStrength,
558         const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const;
559 
560     /// Unbinds the direct binding for the given material purpose
561     /// (\p materialPurpose) on this prim. It accomplishes this by blocking
562     /// the targets of the binding relationship in the current edit target.
563     USDSHADE_API
564     bool UnbindDirectBinding(
565         const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const;
566 
567     /// Unbinds the collection-based binding with the given \p bindingName, for
568     /// the given \p materialPurpose on this prim. It accomplishes this by
569     /// blocking the targets of the associated binding relationship in the
570     /// current edit target.
571     USDSHADE_API
572     bool UnbindCollectionBinding(
573         const TfToken &bindingName,
574         const TfToken &materialPurpose=UsdShadeTokens->allPurpose) const;
575 
576     /// Unbinds all direct and collection-based bindings on this prim.
577     USDSHADE_API
578     bool UnbindAllBindings() const;
579 
580     /// Removes the specified \p prim from the collection targeted by the
581     /// binding relationship corresponding to given \p bindingName and
582     /// \p materialPurpose.
583     ///
584     /// If the collection-binding relationship doesn't exist or if the
585     /// targeted collection does not include the \p prim, then this does
586     /// nothing and returns true.
587     ///
588     /// If the targeted collection includes \p prim, then this modifies the
589     /// collection by removing the prim from it (by invoking
590     /// UsdCollectionAPI::RemovePrim()). This method can be used in conjunction
591     /// with the Unbind*() methods (if desired) to guarantee that a prim
592     /// has no resolved material binding.
593     USDSHADE_API
594     bool RemovePrimFromBindingCollection(
595         const UsdPrim &prim,
596         const TfToken &bindingName,
597         const TfToken &materialPurpose) const;
598 
599     /// Adds the specified \p prim to the collection targeted by the
600     /// binding relationship corresponding to given \p bindingName and
601     /// \p materialPurpose.
602     ///
603     /// If the collection-binding relationship doesn't exist or if the
604     /// targeted collection already includes the \p prim, then this does
605     /// nothing and returns true.
606     ///
607     /// If the targeted collection does not include \p prim (or excludes it
608     /// explicitly), then this modifies the collection by adding the prim to it
609     /// (by invoking UsdCollectionAPI::AddPrim()).
610     USDSHADE_API
611     bool AddPrimToBindingCollection(
612         const UsdPrim &prim,
613         const TfToken &bindingName,
614         const TfToken &materialPurpose) const;
615 
616     /// @}
617 
618     /// \anchor UsdShadeMaterialBindingAPI_MaterialResolution
619     /// \name Bound Material Resolution
620     ///
621     /// Material resolution is the process of determining the final bound
622     /// material for a given gprim (or UsdGeomSubset), for a given value of
623     /// material purpose. It involves examining all the bindings on the prim
624     /// and its ancestors, until a matching binding is found. The following
625     /// set of rules are applied in the process:
626     /// <ul>
627     /// <li>[1] Material bindings are inherited down the namespace chain.
628     /// Bindings lower in namespace (closer to leaf gprims) are stronger than
629     /// bindings on ancestors, unless they have their binding-strength set to
630     /// <i>UsdShadeTokens->strongerThanDescendants</i>.</li>
631     /// <li>[2] A collection binding only applies to members of the collection
632     /// that are at or beneath the prim owning the binding relationship.</li>
633     /// <li>[3] The purpose of the resolved material binding must either match
634     /// the requested special (i.e. restricted) purpose or be an all-purpose
635     /// binding. The restricted purpose binding, if available is preferred over
636     /// an all-purpose binding.
637     /// <li>[4] At any given prim, the collection-based bindings are considered
638     /// to be stronger than the direct bindings. This reflects our belief that
639     /// the combination would appear primarily to define a "fallback" material
640     /// to be used by any child prims that are not targeted by a more specific
641     /// assignment</li>
642     /// <li>[5] Collection-based binding relationships are applied in native
643     /// property order, with the earlier ordered binding relationships being
644     /// stronger.</li>
645     /// <li>[6] The "namespace specificity" with which a prim is included in a
646     /// collection is irrelevant to the binding strength of the collection. For
647     /// example, if a prim contains the ordered collection bindings
648     /// material:binding:collection:metalBits and
649     /// material:binding:collection:plasticBits, each of which targets a
650     /// collection of the same name, then if metalBits includes </Chair/Back>,
651     /// while plasticBits includes </Chair/Back/Brace/Rivet>, the binding for
652     /// </Chair/Back/Brace/Rivet> will be metalBits, because the metalBits
653     /// collection is bound more strongly than the plasticBits, and includes
654     /// an ancestor of </Chair/Back/Brace/Rivet>.
655     /// </li>
656     /// </ul>
657     ///
658     /// \note If a material binding relationship is a built-in property defined
659     /// as part of a typed prim schema, a fallback value should not be provided
660     /// for it. This is because the "material resolution" algorithm only
661     /// conisders <i>authored</i> properties.
662     ///
663     /// @{
664 
665     /// An unordered list of collection paths mapped to the associated
666     /// collection's MembershipQuery object. This is used to cache the
667     /// MembershipQuery objects for collections that are encountered during
668     /// binding resolution for a tree of prims.
669     using CollectionQueryCache =
670         tbb::concurrent_unordered_map<SdfPath,
671             std::unique_ptr<UsdCollectionAPI::MembershipQuery>, SdfPath::Hash>;
672 
673     /// Alias for a unique_ptr to a DirectBinding object.
674     using DirectBindingPtr = std::unique_ptr<DirectBinding>;
675 
676     struct BindingsAtPrim {
677         /// Inspects all the material:binding* properties on the \p prim and
678         /// computes direct and collection-based bindings for the given
679         /// value of \p materialPurpose.
680         USDSHADE_API
681         BindingsAtPrim(const UsdPrim &prim, const TfToken &materialPurpose);
682 
683         /// If the prim has a restricted purpose direct binding, then it is
684         /// stored here. If there is no restricted purpose binding on the prim,
685         /// then the all-purpose direct binding is stored.
686         DirectBindingPtr directBinding;
687 
688         /// The ordered list of restricted-purpose collection bindings on the
689         /// prim.
690         CollectionBindingVector restrictedPurposeCollBindings;
691 
692         /// The ordered list of all-purpose collection bindings on the prim.
693         CollectionBindingVector allPurposeCollBindings;
694     };
695 
696     /// BindingsAtPrim needs to invoke private _GetCollectionBindings().
697     friend struct BindingsAtPrim;
698 
699     /// An unordered list of prim-paths mapped to the corresponding set of
700     /// bindings at the associated prim. This is used when computing resolved
701     /// bindings to avoid redundant computations for the shared ancestor
702     /// prims and to re-use the computed results for leaf prims.
703     using BindingsCache = tbb::concurrent_unordered_map<SdfPath,
704             std::unique_ptr<BindingsAtPrim>, SdfPath::Hash>;
705 
706     /// \overload
707     /// Computes the resolved bound material for this prim, for the given
708     /// material purpose.
709     ///
710     /// This overload of ComputeBoundMaterial makes use of the BindingsCache
711     /// (\p bindingsCache) and CollectionQueryCache (\p collectionQueryCache)
712     /// that are passed in, to avoid redundant binding computations and
713     /// computations of MembershipQuery objects for collections.
714     /// It would be beneficial to make use of these when resolving bindings for
715     /// a tree of prims. These caches are populated lazily as more and more
716     /// bindings are resolved.
717     ///
718     /// When the goal is to compute the bound material for a range (or list) of
719     /// prims, it is recommended to use this version of ComputeBoundMaterial().
720     /// Here's how you could compute the bindings of a range of prims
721     /// efficiently in C++:
722     ///
723     /// \code
724     /// std::vector<std::pair<UsdPrim, UsdShadeMaterial> primBindings;
725     /// UsdShadeMaterialBindingAPI::BindingsCache bindingsCache;
726     /// UsdShadeMaterialBindingAPI::CollectionQueryCache collQueryCache;
727     ///
728     /// for (auto prim : UsdPrimRange(rootPrim)) {
729     ///     UsdShadeMaterial boundMaterial =
730     ///           UsdShadeMaterialBindingAPI(prim).ComputeBoundMaterial(
731     ///           &bindingsCache, &collQueryCache);
732     ///     if (boundMaterial) {
733     ///         primBindings.emplace_back({prim, boundMaterial});
734     ///     }
735     /// }
736     /// \endcode
737     ///
738     /// If \p bindingRel is not null, then it is set to the "winning" binding
739     /// relationship.
740     ///
741     /// See \ref UsdShadeMaterialBindingAPI_MaterialResolution "Bound Material Resolution"
742     /// for details on the material resolution process.
743     ///
744     /// The python version of this method returns a tuple containing the
745     /// bound material and the "winning" binding relationship.
746     USDSHADE_API
747     UsdShadeMaterial ComputeBoundMaterial(
748         BindingsCache *bindingsCache,
749         CollectionQueryCache *collectionQueryCache,
750         const TfToken &materialPurpose=UsdShadeTokens->allPurpose,
751         UsdRelationship *bindingRel=nullptr) const;
752 
753     /// \overload
754     /// Computes the resolved bound material for this prim, for the given
755     /// material purpose.
756     ///
757     /// This overload does not utilize cached MembershipQuery object. However,
758     /// it only computes the MembershipQuery of every collection that bound
759     /// in the ancestor chain at most once.
760     ///
761     /// If \p bindingRel is not null, then it is set to the winning binding
762     /// relationship.
763     ///
764     /// See \ref UsdShadeMaterialBindingAPI_MaterialResolution "Bound Material Resolution"
765     /// for details on the material resolution process.
766     ///
767     /// The python version of this method returns a tuple containing the
768     /// bound material and the "winning" binding relationship.
769     USDSHADE_API
770     UsdShadeMaterial ComputeBoundMaterial(
771         const TfToken &materialPurpose=UsdShadeTokens->allPurpose,
772         UsdRelationship *bindingRel=nullptr) const;
773 
774     /// Static API for efficiently and concurrently computing the resolved
775     /// material bindings for a vector of UsdPrims, \p prims for the
776     /// given \p materialPurpose.
777     ///
778     /// The size of the returned vector always matches the size of the input
779     /// vector, \p prims. If a prim is not bound to any material, an invalid
780     /// or empty UsdShadeMaterial is returned at the index corresponding to it.
781     ///
782     /// If the pointer \p bindingRels points to a valid vector, then it is
783     /// populated with the set of all "winning" binding relationships.
784     ///
785     /// The python version of this method returns a tuple containing two lists -
786     /// the bound materials and the corresponding "winning" binding
787     /// relationships.
788     USDSHADE_API
789     static std::vector<UsdShadeMaterial> ComputeBoundMaterials(
790         const std::vector<UsdPrim> &prims,
791         const TfToken &materialPurpose=UsdShadeTokens->allPurpose,
792         std::vector<UsdRelationship> *bindingRels=nullptr);
793 
794     /// @}
795 
796     // --------------------------------------------------------------------- //
797     /// \anchor UsdShadeMaterialBindingAPI_Subsets
798     /// \name Binding materials to subsets
799     ///
800     /// API to create, access and query the presence of GeomSubsets that are
801     /// created for the purpose of binding materials.
802     ///
803     /// \note GeomSubsets can only be created on valid UsdGeomImageable prims.
804     /// Hence, this API only works when the prim held by the MaterialBindingAPI
805     /// schema object is an imageable prim.
806     ///
807     /// \note Material bindings authored on GeomSubsets are honored by renderers
808     /// only if their familyName is <b>UsdShadeTokens->materialBind</b>. This
809     /// allows robust interchange of subset bindings between multiple DCC apps.
810     ///
811     /// \note The family type of the <i>materialBind</i> family of subsets
812     /// defaults to UsdGeomTokens->nonOverlapping. It can be set to
813     /// UsdGeomTokens->partition, using the API
814     /// SetMaterialBindFaceSubsetsFamilyType(). It should never be set to
815     /// UsdGeomTokens->unrestricted, since it is invalid for a piece of
816     /// geometry to be bound to multiple materials.
817     ///
818     /// Here's some sample code that shows how to create "face" subsets and
819     /// and bind materials to them.
820     /// \code
821     /// // Get the imageable prim under which subsets must be created and
822     /// // bound.
823     /// UsdGeomImageable mesh = UsdGeomImageable::Get(stage,
824     ///         SdfPath("/path/to/meshPrim");
825     ///
826     /// // Get the materials to bind to.
827     /// UsdShadeMaterial plastic = UsdShadeMaterial::Get(stage,
828     ///         SdfPath("/path/to/PlasticMaterial");
829     /// UsdShadeMaterial metal = UsdShadeMaterial::Get(stage,
830     ///         SdfPath("/path/to/MetalMaterial");
831     ///
832     /// VtIntArray plasticFaces, metalFaces;
833     /// //.. populate faceIndices here.
834     /// //..
835     ///
836     /// UsdGeomMaterialBindingAPI meshBindingAPI(mesh.GetPrim());
837     /// UsdGeomSubset plasticSubset = meshBindingAPI.CreateMaterialBindSubset(
838     ///                 "plasticSubset", plasticFaces);
839     /// UsdGeomSubset metalSubset = meshBindingAPI.CreateMaterialBindSubset(
840     ///                 "metalSubset", metalFaces);
841     ///
842     /// // Bind materials to the created geom-subsets.
843     /// UsdShadeMaterialBindingAPI(pasticSubset.GetPrim()).Bind(plastic)
844     /// UsdShadeMaterialBindingAPI(metalSubset.GetPrim()).Bind(metal)
845     ///
846     /// \endcode
847     /// @{
848 
849     /// Creates a GeomSubset named \p subsetName with element type,
850     /// \p elementType and familyName <b>materialBind<b> below this prim.
851     ///
852     /// If a GeomSubset named \p subsetName already exists, then its
853     /// "familyName" is updated to be UsdShadeTokens->materialBind and its
854     /// indices (at <i>default</i> timeCode) are updated with the provided
855     /// \p indices value before returning.
856     ///
857     /// This method forces the familyType of the "materialBind" family of
858     /// subsets to UsdGeomTokens->nonOverlapping if it's unset or explicitly set
859     /// to UsdGeomTokens->unrestricted.
860     ///
861     /// The default value \p elementType is UsdGeomTokens->face, as we expect
862     /// materials to be bound most often to subsets of faces on meshes.
863     USDSHADE_API
864     UsdGeomSubset CreateMaterialBindSubset(
865         const TfToken &subsetName,
866         const VtIntArray &indices,
867         const TfToken &elementType=UsdGeomTokens->face);
868 
869     /// Returns all the existing GeomSubsets with
870     /// familyName=UsdShadeTokens->materialBind below this prim.
871     USDSHADE_API
872     std::vector<UsdGeomSubset> GetMaterialBindSubsets();
873 
874     /// Author the <i>familyType</i> of the "materialBind" family of GeomSubsets
875     /// on this prim.
876     ///
877     /// The default \p familyType is  <i>UsdGeomTokens->nonOverlapping<i>. It
878     /// can be set to <i>UsdGeomTokens->partition</i> to indicate that the
879     /// entire imageable prim is included in the union of all the "materialBind"
880     /// subsets. The family type should never be set to
881     /// UsdGeomTokens->unrestricted, since it is invalid for a single piece
882     /// of geometry (in this case, a subset) to be bound to more than one
883     /// material. Hence, a coding error is issued if \p familyType is
884     /// UsdGeomTokens->unrestricted.
885     ///
886     /// \sa UsdGeomSubset::SetFamilyType
887     USDSHADE_API
888     bool SetMaterialBindSubsetsFamilyType(const TfToken &familyType);
889 
890     /// Returns the familyType of the family of "materialBind" GeomSubsets on
891     /// this prim.
892     ///
893     /// By default, materialBind subsets have familyType="nonOverlapping", but
894     /// they can also be tagged as a "partition", using
895     /// SetMaterialBindFaceSubsetsFamilyType().
896     ///
897     /// \sa UsdGeomSubset::GetFamilyNameAttr
898     USDSHADE_API
899     TfToken GetMaterialBindSubsetsFamilyType();
900 
901     /// Test whether a given \p name contains the "material:binding:" prefix
902     ///
903     USDSHADE_API
904     static bool CanContainPropertyName(const TfToken &name);
905 
906     /// @}
907 
908 private:
909 
910     UsdRelationship _CreateDirectBindingRel(
911         const TfToken &materialPurpose) const;
912 
913     UsdRelationship _CreateCollectionBindingRel(
914         const TfToken &bindingName,
915         const TfToken &materialPurpose) const;
916 
917     // Helper method for getting collection bindings when the set of all
918     // collection binding relationship names for the required purpose is
919     // known.
920     CollectionBindingVector _GetCollectionBindings(
921         const TfTokenVector &collBindingPropertyNames) const;
922 };
923 
924 PXR_NAMESPACE_CLOSE_SCOPE
925 
926 #endif
927