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_SDF_CHANGE_LIST_H
25 #define PXR_USD_SDF_CHANGE_LIST_H
26 
27 /// \file sdf/changeList.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/api.h"
31 #include "pxr/usd/sdf/path.h"
32 #include "pxr/usd/sdf/types.h"
33 #include "pxr/base/tf/smallVector.h"
34 
35 #include <set>
36 #include <map>
37 #include <unordered_map>
38 #include <iosfwd>
39 
40 PXR_NAMESPACE_OPEN_SCOPE
41 
42 class SdfChangeList;
43 typedef std::vector<
44     std::pair<SdfLayerHandle, SdfChangeList>
45     > SdfLayerChangeListVec;
46 
47 /// \class SdfChangeList
48 ///
49 /// A list of scene description modifications, organized by the namespace
50 /// paths where the changes occur.
51 ///
52 class SdfChangeList
53 {
54 public:
55 
56     SdfChangeList() = default;
57     SDF_API SdfChangeList(SdfChangeList const &);
58     SdfChangeList(SdfChangeList &&) = default;
59     SDF_API SdfChangeList &operator=(SdfChangeList const &);
60     SdfChangeList &operator=(SdfChangeList &&) = default;
61 
62     enum SubLayerChangeType {
63         SubLayerAdded,
64         SubLayerRemoved,
65         SubLayerOffset
66     };
67 
68     void DidReplaceLayerContent();
69     void DidReloadLayerContent();
70     void DidChangeLayerResolvedPath();
71     void DidChangeLayerIdentifier(const std::string &oldIdentifier);
72     void DidChangeSublayerPaths(const std::string &subLayerPath,
73                                 SubLayerChangeType changeType);
74 
75     void DidAddPrim(const SdfPath &primPath, bool inert);
76     void DidRemovePrim(const SdfPath &primPath, bool inert);
77     void DidReorderPrims(const SdfPath &parentPath);
78     void DidChangePrimName(const SdfPath &oldPath, const SdfPath &newPath);
79     void DidChangePrimVariantSets(const SdfPath &primPath);
80     void DidChangePrimInheritPaths(const SdfPath &primPath);
81     void DidChangePrimReferences(const SdfPath &primPath);
82     void DidChangePrimSpecializes(const SdfPath &primPath);
83 
84     void DidAddProperty(const SdfPath &propPath, bool hasOnlyRequiredFields);
85     void DidRemoveProperty(const SdfPath &propPath, bool hasOnlyRequiredFields);
86     void DidReorderProperties(const SdfPath &propPath);
87     void DidChangePropertyName(const SdfPath &oldPath, const SdfPath &newPath);
88 
89     void DidChangeAttributeTimeSamples(const SdfPath &attrPath);
90     void DidChangeAttributeConnection(const SdfPath &attrPath);
91     void DidChangeRelationshipTargets(const SdfPath &relPath);
92     void DidAddTarget(const SdfPath &targetPath);
93     void DidRemoveTarget(const SdfPath &targetPath);
94 
95     void DidChangeInfo(const SdfPath &path, const TfToken &key,
96                        const VtValue &oldValue, const VtValue &newValue);
97 
98     /// \struct Entry
99     ///
100     /// Entry of changes at a single path in namespace.
101     ///
102     /// If the path is SdfPath::AbsoluteRootPath(), that indicates a change
103     /// to the root of namespace (that is, a layer or stage).
104     ///
105     /// Note: Our language for invalidation used to be more precise
106     /// about items added, removed, or reordered.  It might seem that
107     /// this would afford more opportunities for efficient updates,
108     /// but in practice it does not.  Because our derived data typically
109     /// must recompose or reinstantiate based on the underlying data,
110     /// the particular delta might be ignored, overridden, or invalid.
111     /// It is simpler to treat all changes identically, and focus on
112     /// making the common base case fast, rather than have complicated
113     /// differential update logic.  It also vastly simplifies the
114     /// language of invalidation.
115     ///
116     struct Entry {
117         // Map of info keys that have changed to (old, new) value pairs.
118         typedef std::pair<VtValue, VtValue> InfoChange;
119         // We usually change just a few fields on a spec in one go, so we store
120         // up to three locally (e.g. typeName, variability, default).
121         typedef TfSmallVector<std::pair<TfToken, InfoChange>, 3> InfoChangeVec;
122         InfoChangeVec infoChanged;
123 
124         /// Return the iterator in infoChanged whose first element is \p key, or
125         /// infoChanged.end() if there is no such element.
126         InfoChangeVec::const_iterator
FindInfoChangeEntry127         FindInfoChange(TfToken const &key) const {
128             InfoChangeVec::const_iterator iter = infoChanged.begin();
129             for (InfoChangeVec::const_iterator end = infoChanged.end();
130                  iter != end; ++iter) {
131                 if (iter->first == key) {
132                     break;
133                 }
134             }
135             return iter;
136         }
137 
138         /// Return true if this entry has an info change for \p key, false
139         /// otherwise.
HasInfoChangeEntry140         bool HasInfoChange(TfToken const &key) const {
141             return FindInfoChange(key) != infoChanged.end();
142         }
143 
144         typedef std::pair<std::string, SubLayerChangeType> SubLayerChange;
145         std::vector<SubLayerChange> subLayerChanges;
146 
147         // Empty if didRename is not set
148         SdfPath oldPath;
149 
150         // Empty if didChangeIdentifier is not set
151         std::string oldIdentifier;
152 
153         // Most changes are stored as simple bits.
154         struct _Flags {
_FlagsEntry::_Flags155             _Flags() {
156                 memset(this, 0, sizeof(*this));
157             }
158 
159             // SdfLayer
160             bool didChangeIdentifier:1;
161             bool didChangeResolvedPath:1;
162             bool didReplaceContent:1;
163             bool didReloadContent:1;
164 
165             // SdfLayer, SdfPrimSpec, SdfRelationshipTarget.
166             bool didReorderChildren:1;
167             bool didReorderProperties:1;
168 
169             // SdfPrimSpec, SdfPropertySpec
170             bool didRename:1;
171 
172             // SdfPrimSpec
173             bool didChangePrimVariantSets:1;
174             bool didChangePrimInheritPaths:1;
175             bool didChangePrimSpecializes:1;
176             bool didChangePrimReferences:1;
177 
178             // SdfPropertySpec
179             bool didChangeAttributeTimeSamples:1;
180             bool didChangeAttributeConnection:1;
181             bool didChangeRelationshipTargets:1;
182             bool didAddTarget:1;
183             bool didRemoveTarget:1;
184 
185             // SdfPrimSpec add/remove
186             bool didAddInertPrim:1;
187             bool didAddNonInertPrim:1;
188             bool didRemoveInertPrim:1;
189             bool didRemoveNonInertPrim:1;
190 
191             // Property add/remove
192             bool didAddPropertyWithOnlyRequiredFields:1;
193             bool didAddProperty:1;
194             bool didRemovePropertyWithOnlyRequiredFields:1;
195             bool didRemoveProperty:1;
196         };
197 
198         _Flags flags;
199     };
200 
201     /// Map of change entries at various paths in a layer.  We store one entry
202     /// in local space, since it's very common to edit just a single spec in a
203     /// single round of changes.
204     using EntryList = TfSmallVector<std::pair<SdfPath, Entry>, 1>;
205 
206 public:
GetEntryList()207     const EntryList & GetEntryList() const { return _entries; }
208 
209     // Change accessors/mutators
210     SDF_API
211     Entry const &GetEntry( const SdfPath & ) const;
212 
213     using const_iterator = EntryList::const_iterator;
214 
215     SDF_API
216     const_iterator FindEntry(SdfPath const &) const;
217 
begin()218     const_iterator begin() const {
219         return _entries.begin();
220     }
221 
cbegin()222     const_iterator cbegin() const {
223         return _entries.cbegin();
224     }
225 
end()226     const_iterator end() const {
227         return _entries.end();
228     }
229 
cend()230     const_iterator cend() const {
231         return _entries.cend();
232     }
233 
234 private:
swap(SdfChangeList & a,SdfChangeList & b)235     friend void swap(SdfChangeList &a, SdfChangeList &b) {
236         a._entries.swap(b._entries);
237         a._entriesAccel.swap(b._entriesAccel);
238     }
239 
240     Entry &_GetEntry(SdfPath const &);
241 
242     // If no entry with `newPath` exists, create one.  If an entry with
243     // `oldPath` exists, move its contents over `newPath`'s and erase it.
244     // Return a reference to `newPath`'s entry.
245     Entry &_MoveEntry(SdfPath const &oldPath, SdfPath const &newPath);
246 
247     EntryList::iterator _MakeNonConstIterator(EntryList::const_iterator i);
248 
249     Entry &_AddNewEntry(SdfPath const &path);
250 
251     void _EraseEntry(SdfPath const &);
252 
253     void _RebuildAccel();
254 
255     EntryList _entries;
256     using _AccelTable = std::unordered_map<SdfPath, size_t, SdfPath::Hash>;
257     std::unique_ptr<_AccelTable> _entriesAccel;
258     static constexpr size_t _AccelThreshold = 64;
259 };
260 
261 // Stream-output operator
262 SDF_API std::ostream& operator<<(std::ostream&, const SdfChangeList &);
263 
264 PXR_NAMESPACE_CLOSE_SCOPE
265 
266 #endif // PXR_USD_SDF_CHANGE_LIST_H
267