HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
layerRelocatesEditBuilder.h
Go to the documentation of this file.
1 //
2 // Copyright 2024 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_USD_PCP_LAYER_RELOCATES_EDIT_BUILDER_H
8 #define PXR_USD_PCP_LAYER_RELOCATES_EDIT_BUILDER_H
9 
10 /// \file pcp/layerRelocatesEditBuilder.h
11 
12 #include "pxr/pxr.h"
13 #include "pxr/usd/pcp/api.h"
14 #include "pxr/usd/pcp/errors.h"
16 #include "pxr/usd/sdf/path.h"
17 #include "pxr/usd/sdf/types.h"
19 
20 #include <vector>
21 
23 
26 
27 /// \class PcpLayerRelocatesEditBuilder
28 ///
29 /// Utility class for building up a map of valid relocates and producing
30 /// the layer metadata edits that can be performed to set these relocates on a
31 /// layer stack.
32 ///
33 /// This class must be constructed from an existing PcpLayerStack which will
34 /// initialize the edit builder with the layer stack's current relocates. Then
35 /// Relocate can be called any number of times to build a validly formatted map
36 /// of edited relocates. This can then be asked for a list of layer metadata
37 /// edits that need to be performed to update the layer stack to have the edited
38 /// relocates.
39 ///
40 /// This class is not stateful in regards to the layer stack or its layers. In
41 /// other words, the provided layer stack is only used to initialize the
42 /// existing relocates and to get which layers should be the layers to edit.
43 /// This does not listen to any change notifications for the layers or the layer
44 /// stack or the PcpCache that built it. This is class is meant to be
45 /// transiently used to build up a set of edits to perform on layers and then
46 /// discarded.
48 public:
49 
50  /// Constructor that initializes the relocates map from the given
51  /// \p layerStack.
52  ///
53  /// If \p addNewRelocatesLayer is provided, it must be a layer in the given
54  /// layer stack and any new relocates map entries created by calls to
55  /// Relocate will be added as part of the edit for that layer. If
56  /// \p addNewRelocatesLayer is not provided, then the layer stack's root
57  /// layer will be used as the target edit location for new relocates.
58  ///
59  PCP_API
61  const PcpLayerStackPtr &layerStack,
62  const SdfLayerHandle &addNewRelocatesLayer = nullptr);
63 
64  /// Updates the relocates map and layer edits so that \p sourcePath is moved
65  /// to \p targetPath in the edited relocates.
66  ///
67  /// Returns true if the relocate can be performed given the source and
68  /// target and current relocates map. Returns false and populates \p whyNot,
69  /// (if it's not nullptr) with the reason why if the relocate cannot be
70  /// performed.
71  ///
72  /// The edited relocates map will always conform to the relocates format
73  /// that is considered valid by the layer stack population and will
74  /// therefore not produce relocation errors when set as the layer stack's
75  /// authored relocates. Maintaining this format means that calling Relocate
76  /// can a cause a combination of different effects on the relocates map
77  /// depending the existing relocates at the time. These effects can include
78  /// adding a new relocate entry, updating paths in existing entries, and
79  /// deleting existing entries. The following examples demonstrate many of
80  /// these behaviors.
81  ///
82  /// Example 1:
83  /// Existing relocates:
84  /// - </Root/A> -> </Root/B>
85  /// Relocate(</Root/C>, </Root/D>)
86  /// - Just adds a new relocate
87  /// Result relocates:
88  /// - </Root/A> -> </Root/B>
89  /// - </Root/C> -> </Root/D>
90  ///
91  /// Example 2:
92  /// Existing relocates:
93  /// - </Root/A> -> </Root/B>
94  /// Relocate(</Root/B>, </Root/C>)
95  /// - Updates existing relocate to point to </Root/C>
96  /// Result relocates:
97  /// - </Root/A> -> </Root/C>
98  ///
99  /// Example 3:
100  /// Existing relocates:
101  /// - </Root/A/Y> -> </Root/B/Y>
102  /// - </Root/A/X> -> </Root/B/X>
103  /// Relocate(</Root/A>, </Root/B>)
104  /// - Adds a new relocate but removes the existing relocates which become
105  /// redundant with their parents relocated.
106  /// Result relocates:
107  /// - </Root/A> -> </Root/B>
108  ///
109  /// Example 4:
110  /// Existing relocates:
111  /// - </Root/A/B> -> </Root/A/C>
112  /// - </Root/A/D> -> </Root/D>
113  /// - </Root/E> -> </Root/A/E>
114  /// Relocate(</Root/A>, </Root/Z>)
115  /// - Adds a new relocate and updates any existing relocates so that
116  /// their source and target paths are ancestrally relocated by the new
117  /// relocate.
118  /// Result relocates:
119  /// - </Root/A> -> </Root/Z>
120  /// - </Root/Z/B> -> </Root/Z/C>
121  /// - </Root/Z/D> -> </Root/D>
122  /// - </Root/E> -> </Root/Z/E>
123  ///
124  /// Example 5:
125  /// Existing relocates:
126  /// - </Root/A> -> </Root/B>
127  /// Relocate(</Root/B>, </Root/A>)
128  /// - Deletes the relocate that has been moved back to its original
129  /// source. This is equivalent to calling RemoveRelocate(</Root/A>)
130  /// Result relocates:
131  /// - none
132  ///
133  PCP_API
134  bool Relocate(
135  const SdfPath &sourcePath,
136  const SdfPath &targetPath,
137  std::string *whyNot = nullptr);
138 
139  /// Updates the relocates map and layer edits so that the relocate with
140  /// \p sourcePath is removed from the edited relocates.
141  ///
142  /// Returns true if a relocate with the given source path exists in the
143  /// current relocates map and can be removed. Returns false and populates
144  /// \p whyNot, (if it's not nullptr) with the reason why if not.
145  ///
146  /// Like the Relocate method, calling this function will maintain the
147  /// validity of relocates map and may update or delete other existing
148  /// relocates entries, in addition to the entry with the input source path,
149  /// to do so.
150  ///
151  PCP_API
152  bool RemoveRelocate(
153  const SdfPath &sourcePath,
154  std::string *whyNot = nullptr);
155 
156  /// An edit is a layer and an SdfRelocates value to set in the layer's
157  /// 'layerRelocates' metatdata.
158  using LayerRelocatesEdit = std::pair<SdfLayerHandle, SdfRelocates>;
159 
160  /// List of relocates edits to perform on all layers.
161  using LayerRelocatesEdits = std::vector<LayerRelocatesEdit>;
162 
163  /// Returns a list of edits to perform on the layers of the layer stack this
164  /// builder was initialized with that will update the layer stack to have
165  /// the relocates returned by GetEditedRelocatesMap.
166  ///
167  /// The format of each edit is a pair consisting of a layer and an
168  /// SdfRelocates value. To perform each edit, set the 'layerRelocates'
169  /// field in the layer's metadata to be the new relocates value.
170  /// For example:
171  /// \code
172  /// for (const auto &[layer, relocates] : relocatesEditBuilder.GetEdits()) {
173  /// layer->SetRelocates(relocates);
174  /// }
175  /// \endcode
176  PCP_API
178 
179  /// Returns a map of relocates composed from the edited layer relocates.
180  PCP_API
181  const SdfRelocatesMap &GetEditedRelocatesMap() const;
182 
183 private:
184  void _UpdateExistingRelocates(
185  const SdfPath &source, const SdfPath &target);
186 
187  void _RemoveRelocatesWithErrors(const PcpErrorVector &errors);
188 
189  mutable std::optional<SdfRelocatesMap> _relocatesMap;
190 
191  LayerRelocatesEdits _layerRelocatesEdits;
192  SdfLayerHandleSet _layersWithRelocatesChanges;
193  size_t _editForNewRelocatesIndex = ~0;
194 };
195 
196 // Modifies the given relocates in place by moving paths at or under
197 // oldPath to be at or under newPath.
198 //
199 // The old path may not be empty but the new path can be. Any relocates
200 // that become invalid or no-ops are removed from the resulting modified
201 // relocates. Returns true if any modifications were made to the relocates,
202 // false otherwise.
203 bool
205  SdfRelocates *relocates, const SdfPath &oldPath, const SdfPath &newPath);
206 
208 
209 #endif // PXR_USD_PCP_LAYER_RELOCATES_EDIT_BUILDER_H
Definition: layer.h:81
bool Pcp_ModifyRelocates(SdfRelocates *relocates, const SdfPath &oldPath, const SdfPath &newPath)
std::map< SdfPath, SdfPath > SdfRelocatesMap
A map of source SdfPaths to target SdfPaths for relocation.
Definition: types.h:267
PCP_API PcpLayerRelocatesEditBuilder(const PcpLayerStackPtr &layerStack, const SdfLayerHandle &addNewRelocatesLayer=nullptr)
std::set< SdfHandleTo< SdfLayer >::Handle > SdfLayerHandleSet
PXR_NAMESPACE_OPEN_SCOPE SDF_DECLARE_HANDLES(SdfLayer)
PCP_API const SdfRelocatesMap & GetEditedRelocatesMap() const
Returns a map of relocates composed from the edited layer relocates.
PCP_API LayerRelocatesEdits GetEdits() const
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
GLenum target
Definition: glcorearb.h:1667
PCP_API bool RemoveRelocate(const SdfPath &sourcePath, std::string *whyNot=nullptr)
Definition: path.h:273
std::pair< SdfLayerHandle, SdfRelocates > LayerRelocatesEdit
std::vector< PcpErrorBasePtr > PcpErrorVector
Definition: errors.h:65
PCP_API bool Relocate(const SdfPath &sourcePath, const SdfPath &targetPath, std::string *whyNot=nullptr)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
TF_DECLARE_WEAK_PTRS(PcpLayerStack)
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
std::vector< SdfRelocate > SdfRelocates
A vector of relocation source path to target path pairs.
Definition: types.h:274
std::vector< LayerRelocatesEdit > LayerRelocatesEdits
List of relocates edits to perform on all layers.
#define PCP_API
Definition: api.h:23