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 PXR_USD_USD_REFERENCES_H
25 #define PXR_USD_USD_REFERENCES_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/usd/api.h"
29 #include "pxr/usd/usd/common.h"
30 #include "pxr/usd/usd/prim.h"
31 
32 #include "pxr/usd/sdf/declareHandles.h"
33 #include "pxr/usd/sdf/path.h"
34 #include "pxr/usd/sdf/reference.h"
35 
36 PXR_NAMESPACE_OPEN_SCOPE
37 
38 /// \class UsdReferences
39 ///
40 /// UsdReferences provides an interface to authoring and introspecting
41 /// references in Usd.
42 ///
43 /// References are the primary operator for "encapsulated aggregation" of
44 /// scene description. \em aggregation means that references let us
45 /// build up rich scenes by composing scene description recorded in a (most
46 /// often) different layer.  A scene can reference the same layer many times at
47 /// different locations in a scene's namespace.  Referenced scene description
48 /// can be overridden in the referencing (or stronger) layers, allowing each
49 /// instance of the reference to be directly customized/overridden.
50 /// \em Encapsulated means that regardless of how much scene description is in
51 /// the referenced layer, only the scene description under and composed from
52 /// (via other composition arcs in the referenced layer) the targeted prim
53 /// will be composed into the aggregate scene.  Multiple references to the
54 /// same layer will result in the layer being opened and retained in memory
55 /// only once, although each referencing prim will compose unique
56 /// \ref PcpPrimIndex "prim indices" for the tree rooted at the referenced prim.
57 ///
58 /// \section Usd_References Important Qualities and Effective Use of References
59 ///
60 /// \li Any prim can host zero, one or multiple references
61 ///
62 /// \li References are \ref SdfListOp "list editable"; that is, they compose
63 /// differently than ordinary properties and metadata.  In any given
64 /// LayerStack, each authored reference operation at the same SdfPath
65 /// location in each layer (i.e. on the same prim) will compose into an
66 /// aggregate result by adding to, removing from, or replacing "weaker"
67 /// references.
68 ///
69 /// \li References can target the same LayerStack in which they are authored,
70 /// as long as doing so does not introduce a cycle in the composition graph.
71 /// See \ref Usd_Internal_References
72 ///
73 /// \li The \c identifier component of a reference in the provided API
74 /// can be a resolvable asset-path to some external layer, empty, in which case
75 /// the reference targets the root layer of the LayerStack containing the
76 /// referencing layer, or the identifier of an existing anonymous, in-memory-only
77 /// SdfLayer.  Care should be exercised in the latter case: calling Export() on
78 /// an anonymous layer to serialize it to a file will not attempt to replace
79 /// any references to anonymous layers with references to file-backed layers.
80 ///
81 /// \li Opinions brought in by reference on an ancestor prim are weaker than
82 /// opinions brought in by references on a descendant prim.
83 ///
84 /// \subsection Usd_DefaultPrim_References Expressing references without prim paths
85 ///
86 /// References may omit the target prim path if the referenced layer has the
87 /// 'defaultPrim' metadata set.  In this case, the reference targets the
88 /// 'defaultPrim' in the referenced layer. A layer's defaultPrim can be
89 /// authored and accessed on a UsdStage whose root layer is the layer in
90 /// question: see UsdStage::GetDefaultPrim() and UsdStage::SetDefaultPrim().
91 /// One can also author defaultPrim directly on an SdfLayer - see
92 /// SdfLayer::GetDefaultPrim(), SdfLayer::SetDefaultPrim().
93 ///
94 /// \subsection Usd_Internal_References Expressing "internal" references to the containing LayerStack
95 ///
96 /// References may omit the identifier specifying the referenced layer.  This
97 /// creates an "internal" reference. During composition, the referenced layer
98 /// will be resolved to the root layer of the LayerStack containing the
99 /// layer where the reference was authored.  See AddInternalReference().
100 ///
101 /// \subsection Usd_Subroot_References Referencing sub-root prims
102 ///
103 /// References may target any prim in a layer. In the simplest and most
104 /// common case, a root prim in a layer will be referenced. However,
105 /// referencing sub-root prims can be useful in a variety of other cases;
106 /// for example, a user might organize prims into a meaningful hierarchy
107 /// in a layer for display purposes, then use sub-root references to
108 /// reference a selection from that hierarchy into a scene.
109 ///
110 /// Sub-root references have subtle behaviors with respect to opinions
111 /// and composition arcs authored on ancestors of the referenced prim.
112 /// Users should carefully consider this when deciding whether to use
113 /// sub-root references. These issues can be avoided by not authoring
114 /// any properties or metadata on ancestors of prims that are meant to
115 /// be referenced.
116 ///
117 /// Consider the following example:
118 ///
119 /// \code
120 /// * shot.usda                                 | * asset.usda
121 ///                                             |
122 /// #usda 1.0                                   | #usda 1.0
123 ///                                             |
124 /// over "Class"                                | class "Class"
125 /// {                                           | {
126 ///     over "B"                                | }
127 ///     {                                       |
128 ///         over "Model"                        | def "A" (
129 ///         {                                   |    inherits = </Class>
130 ///             int a = 3                       | )
131 ///         }                                   | {
132 ///     }                                       |     token purpose = "render"
133 /// }                                           |
134 ///                                             |     def "B" (
135 /// over "A"                                    |        variantSets = "type"
136 /// {                                           |        variants = {
137 ///     over "B" (                              |             string type = "a"
138 ///         # variant selection won't be used   |        }
139 ///         variants = {                        |     )
140 ///             string type = "b"               |     {
141 ///         }                                   |         variantSet "type" = {
142 ///     )                                       |             "a" {
143 ///     {                                       |                 def "Model"
144 ///     }                                       |                 {
145 /// }                                           |                     int a = 1
146 ///                                             |                 }
147 /// def "ReferencedModel" (                     |             }
148 ///     references = @./asset.usda@</A/B/Model> |             "b" {
149 /// )                                           |                 def "Model"
150 /// {                                           |                 {
151 /// }                                           |                     int a = 2
152 ///                                             |                 }
153 ///                                             |             }
154 ///                                             |         }
155 ///                                             |     }
156 ///                                             | }
157 /// \endcode
158 ///
159 /// * Property and metadata opinions on the ancestors of the referenced prim
160 ///   *are not* present in the composed stage and will never contribute to any
161 ///   computations. In this example, the opinion for the attribute /A.purpose
162 ///   in asset.usda will never be visible in the UsdStage for shot.usda.
163 ///
164 /// * Property and metadata opinions due to ancestral composition arcs
165 ///   *are* present in the composed stage. In this example, the attribute
166 ///   /Class/B/Model.a in shot.usda will be present in the UsdStage for
167 ///   shot.usda, even though the inherit arc is authored on an ancestor
168 ///   of the referenced prim.
169 ///
170 /// * A consequence of these rules is that users might not be able to
171 ///   override ancestral variant selections that affect the referenced prim.
172 ///   In this example, the Model prim being referenced comes from the
173 ///   variant selection {type=a} on prim /A/B in asset.usda. The {type=b}
174 ///   variant cannot be selected in shot.usda, even if prims with the
175 ///   same hierarchy happen to exist there. There are various workarounds
176 ///   for this; in this example, the {type=b} variant selection could be
177 ///   authored on /Class/B/Model in shot.usda instead because of the
178 ///   inherit arc that was established on prim /A.
179 ///
180 /// \subsection Usd_Failing_References Reasons why adding a reference may fail, why adding a reference may succeed but still generate errors, and what it all means
181 ///
182 /// AddReference() and SetReferences() can each fail for a number of
183 /// reasons.  If one of the specified prim targets for one of the references
184 /// is not a prim, we will generate an error, fail to author any scene
185 /// description, and return \c false.  If anything goes wrong in attempting
186 /// to write the reference, we also return false, and the reference will also
187 /// remain unauthored.  Otherwise, if the reference was successfully
188 /// authored, we will return \c true.  <b>A successful reference authoring
189 /// operation may still generate composition errors!</b> Just because the
190 /// reference you specified was syntactically correct and therefore
191 /// successfully authored, does not imply it was meaningful. If you wish to
192 /// ensure that the reference you are about to author will be meaningfully
193 /// consumable by your stage, you are strongly encouraged to <b>ensure it
194 /// will resolve to an actual file by using
195 /// UsdStage::ResolveIdentifierToEditTarget() before authoring the
196 /// reference.</b>
197 ///
198 /// When adding an internal reference, the given prim path is expected to
199 /// be in the namespace of the owning prim's stage. Sub-root prim paths
200 /// will be translated from this namespace to the namespace of the
201 /// current edit target, if necessary. If a path cannot be translated,
202 /// a coding error will be issued and no changes will be made. Non-sub-root
203 /// paths will not be translated.
204 ///
205 /// Immediately upon successful authoring of the reference (before returning
206 /// from AddReference(), RemoveReference(), ClearReferences(), or
207 /// SetReferences()), the UsdStage on which the reference was authored will
208 /// recompose the subtree rooted at the prim hosting the reference.  If the
209 /// provided identifier does not resolve to a layer that is already opened or
210 /// that can be opened in the usd format, \em or if the provided primPath is
211 /// not an actual prim in that layer, the stage's recomposition will
212 /// fail, and pass on composition errors to the client.
213 ///
214 class UsdReferences {
215     friend class UsdPrim;
216 
UsdReferences(const UsdPrim & prim)217     explicit UsdReferences(const UsdPrim& prim) : _prim(prim) {}
218 
219 public:
220     /// Adds a reference to the reference listOp at the current EditTarget,
221     /// in the position specified by \p position.
222     /// \sa \ref Usd_Failing_References "Why adding references may fail" for
223     /// explanation of expectations on \p ref and what return values and errors
224     /// to expect, and \ref Usd_OM_ListOps for details on list editing and
225     /// composition of listOps.
226     USD_API
227     bool AddReference(const SdfReference& ref,
228                   UsdListPosition position=UsdListPositionBackOfPrependList);
229 
230     /// \overload
231     USD_API
232     bool AddReference(const std::string &identifier,
233                   const SdfPath &primPath,
234                   const SdfLayerOffset &layerOffset = SdfLayerOffset(),
235                   UsdListPosition position=UsdListPositionBackOfPrependList);
236 
237     /// \overload
238     /// \sa \ref Usd_DefaultPrim_References "References Without Prim Paths"
239     USD_API
240     bool AddReference(const std::string &identifier,
241                   const SdfLayerOffset &layerOffset = SdfLayerOffset(),
242                   UsdListPosition position=UsdListPositionBackOfPrependList);
243 
244     /// Add an internal reference to the specified prim.
245     /// \sa \ref Usd_Internal_References "Internal References"
246     USD_API
247     bool AddInternalReference(const SdfPath &primPath,
248                   const SdfLayerOffset &layerOffset = SdfLayerOffset(),
249                   UsdListPosition position=UsdListPositionBackOfPrependList);
250 
251     /// Removes the specified reference from the references listOp at the
252     /// current EditTarget.  This does not necessarily eliminate the
253     /// reference completely, as it may be added or set in another layer in
254     /// the same LayerStack as the current EditTarget.
255     /// \sa \ref Usd_OM_ListOps
256     USD_API
257     bool RemoveReference(const SdfReference& ref);
258 
259     /// Removes the authored reference listOp edits at the current EditTarget.
260     /// The same caveats for Remove() apply to Clear().  In fact, Clear() may
261     /// actually increase the number of composed references, if the listOp
262     /// being cleared contained the "remove" operator.
263     /// \sa \ref Usd_OM_ListOps
264     USD_API
265     bool ClearReferences();
266 
267     /// Explicitly set the references, potentially blocking weaker opinions
268     /// that add or remove items.
269     /// \sa \ref Usd_Failing_References "Why adding references may fail" for
270     /// explanation of expectations on \p ref and what return values and errors
271     /// to expect, and \ref Usd_OM_ListOps for details on list editing and
272     /// composition of listOps.
273     USD_API
274     bool SetReferences(const SdfReferenceVector& items);
275 
276     /// Return the prim this object is bound to.
GetPrim()277     const UsdPrim &GetPrim() const { return _prim; }
278 
279     /// \overload
GetPrim()280     UsdPrim GetPrim() { return _prim; }
281 
282     explicit operator bool() { return bool(_prim); }
283 
284 private:
285     UsdPrim _prim;
286 };
287 
288 PXR_NAMESPACE_CLOSE_SCOPE
289 
290 #endif // PXR_USD_USD_REFERENCES_H
291