HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
listEditorProxy.h
Go to the documentation of this file.
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_LIST_EDITOR_PROXY_H
25 #define PXR_USD_SDF_LIST_EDITOR_PROXY_H
26 
27 /// \file sdf/listEditorProxy.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/listEditor.h"
31 #include "pxr/usd/sdf/listProxy.h"
33 
34 #include "pxr/base/vt/value.h" // for Vt_DefaultValueFactory
35 
36 #include <functional>
37 #include <memory>
38 #include <optional>
39 
41 
42 /// \class SdfListEditorProxy
43 ///
44 /// Represents a set of list editing operations.
45 ///
46 /// An SdfListEditorProxy allows consumers to specify a transformation to be
47 /// applied to a list via a set of list editing operations. Given a starting
48 /// ordered list, it can either replace the result with another ordered list
49 /// or apply a sequence of three operations: deleting keys, then adding keys
50 /// to the end (if they aren't already in the starting list), then reordering
51 /// keys.
52 ///
53 /// The type policy defines the value type that a particular proxy can operate
54 /// on.
55 template <class _TypePolicy>
57 public:
58  typedef _TypePolicy TypePolicy;
62  typedef std::vector<value_type> value_vector_type;
63 
64  // ApplyEdits types.
65  typedef std::function<std::optional<value_type>
67 
68  // ModifyEdits types.
69  typedef std::function<std::optional<value_type>
71 
72  /// Creates a default proxy object. The object evaluates to \c false in a
73  /// boolean context and all operations on this object have no effect.
75  {
76  }
77 
78  /// Creates a new proxy object backed by the supplied list editor.
80  const std::shared_ptr<Sdf_ListEditor<TypePolicy> >& listEditor)
81  : _listEditor(listEditor)
82  {
83  }
84 
85  /// Returns true if the list editor is expired.
86  bool IsExpired() const
87  {
88  if (!_listEditor) {
89  return false;
90  }
91 
92  return _listEditor->IsExpired();
93  }
94 
95  /// Returns \c true if the editor has an explicit list, \c false if
96  /// it has list operations.
97  bool IsExplicit() const
98  {
99  return _Validate() ? _listEditor->IsExplicit() : true;
100  }
101 
102  /// Returns \c true if the editor is not explicit and allows ordering
103  /// only.
104  bool IsOrderedOnly() const
105  {
106  return _Validate() ? _listEditor->IsOrderedOnly() : false;
107  }
108 
109  /// Returns \c true if the editor has an explicit list (even if it's
110  /// empty) or it has any added, prepended, appended, deleted,
111  /// or ordered keys.
112  bool HasKeys() const
113  {
114  return _Validate() ? _listEditor->HasKeys() : true;
115  }
116 
117  /// Apply the edits to \p vec.
119  {
120  if (_Validate()) {
121  _listEditor->ApplyEditsToList(vec, ApplyCallback());
122  }
123  }
124 
125  /// Apply the edits to \p vec. If \p callback is valid then it's called
126  /// for every key in the editor before applying it to \p vec. If the
127  /// returned key is invalid then the key will not be applied. Otherwise
128  /// the returned key is applied, allowing callbacks to perform key
129  /// translation.
130  template <class CB>
131  void ApplyEditsToList(value_vector_type* vec, CB callback) const
132  {
133  if (_Validate()) {
134  _listEditor->ApplyEditsToList(vec, ApplyCallback(callback));
135  }
136  }
137 
138  /// Copies the keys from \p other. This differs from assignment
139  /// because assignment just makes two list editors refer to the
140  /// same lists.
141  ///
142  /// Not all list editors support changing their mode. If the mode
143  /// can't be changed to the mode of \p other then this does nothing
144  /// and returns \c false, otherwise it returns \c true.
145  bool CopyItems(const This& other)
146  {
147  return _Validate() && other._Validate() ?
148  _listEditor->CopyEdits(*other._listEditor) : false;
149  }
150 
151  /// Removes all keys and changes the editor to have list operations.
152  ///
153  /// Not all list editors support changing their mode. If the mode
154  /// can't be changed to the mode of \p other then this does nothing
155  /// and returns \c false, otherwise it returns \c true.
156  bool ClearEdits()
157  {
158  return _Validate() ? _listEditor->ClearEdits() : false;
159  }
160 
161  /// Removes all keys and changes the editor to be explicit.
162  ///
163  /// Not all list editors support changing their mode. If the mode
164  /// can't be changed to the mode of \p other then this does nothing
165  /// and returns \c false, otherwise it returns \c true.
167  {
168  return _Validate() ? _listEditor->ClearEditsAndMakeExplicit() : false;
169  }
170 
171  /// \p callback is called for every key. If the returned key is
172  /// invalid then the key is removed, otherwise it's replaced with the
173  /// returned key.
174  template <class CB>
175  void ModifyItemEdits(CB callback)
176  {
177  if (_Validate()) {
178  _listEditor->ModifyItemEdits(ModifyCallback(callback));
179  }
180  }
181 
182  /// Check if the given item is explicit, added, prepended, appended,
183  /// deleted, or ordered by this editor. If \p onlyAddOrExplicit is
184  /// \c true we only check the added or explicit items.
185  bool ContainsItemEdit(const value_type& item,
186  bool onlyAddOrExplicit = false) const
187  {
188  if (_Validate()) {
189  size_t i;
190 
191  i = GetExplicitItems().Find(item);
192  if (i != size_t(-1)) {
193  return true;
194  }
195 
196  i = GetAddedItems().Find(item);
197  if (i != size_t(-1)) {
198  return true;
199  }
200 
201  i = GetPrependedItems().Find(item);
202  if (i != size_t(-1)) {
203  return true;
204  }
205 
206  i = GetAppendedItems().Find(item);
207  if (i != size_t(-1)) {
208  return true;
209  }
210 
211  if (!onlyAddOrExplicit) {
212  i = GetDeletedItems().Find(item);
213  if (i != size_t(-1)) {
214  return true;
215  }
216 
217  i = GetOrderedItems().Find(item);
218  if (i != size_t(-1)) {
219  return true;
220  }
221  }
222  }
223 
224  return false;
225  }
226 
227  /// Remove all occurrences of the given item, regardless of whether
228  /// the item is explicit, added, prepended, appended, deleted, or ordered.
229  void RemoveItemEdits(const value_type& item)
230  {
231  if (_Validate()) {
232  SdfChangeBlock block;
233 
234  GetExplicitItems().Remove(item);
235  GetAddedItems().Remove(item);
236  GetPrependedItems().Remove(item);
237  GetAppendedItems().Remove(item);
238  GetDeletedItems().Remove(item);
239  GetOrderedItems().Remove(item);
240  }
241  }
242 
243  /// Replace all occurrences of the given item, regardless of
244  /// whether the item is explicit, added, prepended, appended,
245  /// deleted or ordered.
246  void ReplaceItemEdits(const value_type& oldItem, const value_type& newItem)
247  {
248  if (_Validate()) {
249  SdfChangeBlock block;
250 
251  GetExplicitItems().Replace(oldItem, newItem);
252  GetAddedItems().Replace(oldItem, newItem);
253  GetPrependedItems().Replace(oldItem, newItem);
254  GetAppendedItems().Replace(oldItem, newItem);
255  GetDeletedItems().Replace(oldItem, newItem);
256  GetOrderedItems().Replace(oldItem, newItem);
257  }
258  }
259 
260  /// Returns the explicitly set items.
262  {
263  return ListProxy(_listEditor, SdfListOpTypeExplicit);
264  }
265 
266  /// Returns the items added by this list editor
268  {
269  return ListProxy(_listEditor, SdfListOpTypeAdded);
270  }
271 
272  /// Returns the items prepended by this list editor
274  {
275  return ListProxy(_listEditor, SdfListOpTypePrepended);
276  }
277 
278  /// Returns the items appended by this list editor
280  {
281  return ListProxy(_listEditor, SdfListOpTypeAppended);
282  }
283 
284  /// Returns the items deleted by this list editor
286  {
287  return ListProxy(_listEditor, SdfListOpTypeDeleted);
288  }
289 
290  /// Returns the items reordered by this list editor
292  {
293  return ListProxy(_listEditor, SdfListOpTypeOrdered);
294  }
295 
296  /// Deprecated. Please use \ref GetAppliedItems
298  {
299  return GetAppliedItems();
300  }
301 
302  /// Returns the effective list of items represented by the operations in
303  /// this list op. This function should be used to determine the final list
304  /// of items added instead of looking at the individual explicit, prepended,
305  /// and appended item lists.
306  ///
307  /// This is equivalent to calling ApplyOperations on an empty item vector.
308 
310  {
312  if (_Validate()) {
313  _listEditor->ApplyEditsToList(&result);
314  }
315  return result;
316  }
317 
318  void Add(const value_type& value)
319  {
320  if (_Validate()) {
321  if (!_listEditor->IsOrderedOnly()) {
322  if (_listEditor->IsExplicit()) {
323  _AddOrReplace(SdfListOpTypeExplicit, value);
324  }
325  else {
326  GetDeletedItems().Remove(value);
327  _AddOrReplace(SdfListOpTypeAdded, value);
328  }
329  }
330  }
331  }
332 
333  void Prepend(const value_type& value)
334  {
335  if (_Validate()) {
336  if (!_listEditor->IsOrderedOnly()) {
337  if (_listEditor->IsExplicit()) {
338  _Prepend(SdfListOpTypeExplicit, value);
339  }
340  else {
341  GetDeletedItems().Remove(value);
342  _Prepend(SdfListOpTypePrepended, value);
343  }
344  }
345  }
346  }
347 
348  void Append(const value_type& value)
349  {
350  if (_Validate()) {
351  if (!_listEditor->IsOrderedOnly()) {
352  if (_listEditor->IsExplicit()) {
353  _Append(SdfListOpTypeExplicit, value);
354  }
355  else {
356  GetDeletedItems().Remove(value);
357  _Append(SdfListOpTypeAppended, value);
358  }
359  }
360  }
361  }
362 
363  void Remove(const value_type& value)
364  {
365  if (_Validate()) {
366  if (_listEditor->IsExplicit()) {
367  GetExplicitItems().Remove(value);
368  }
369  else if (!_listEditor->IsOrderedOnly()) {
370  GetAddedItems().Remove(value);
371  GetPrependedItems().Remove(value);
372  GetAppendedItems().Remove(value);
373  _AddIfMissing(SdfListOpTypeDeleted, value);
374  }
375  }
376  }
377 
378  void Erase(const value_type& value)
379  {
380  if (_Validate()) {
381  if (!_listEditor->IsOrderedOnly()) {
382  if (_listEditor->IsExplicit()) {
383  GetExplicitItems().Remove(value);
384  }
385  else {
386  GetAddedItems().Remove(value);
387  GetPrependedItems().Remove(value);
388  GetAppendedItems().Remove(value);
389  }
390  }
391  }
392  }
393 
394  /// Explicit bool conversion operator. A ListEditorProxy object
395  /// converts to \c true iff the list editor is valid, converts to \c false
396  /// otherwise.
397  explicit operator bool() const
398  {
399  return _listEditor && _listEditor->IsValid();
400  }
401 
402 private:
403  bool _Validate()
404  {
405  if (!_listEditor) {
406  return false;
407  }
408 
409  if (IsExpired()) {
410  TF_CODING_ERROR("Accessing expired list editor");
411  return false;
412  }
413  return true;
414  }
415 
416  bool _Validate() const
417  {
418  if (!_listEditor) {
419  return false;
420  }
421 
422  if (IsExpired()) {
423  TF_CODING_ERROR("Accessing expired list editor");
424  return false;
425  }
426  return true;
427  }
428 
429  void _AddIfMissing(SdfListOpType op, const value_type& value)
430  {
431  ListProxy proxy(_listEditor, op);
432  size_t index = proxy.Find(value);
433  if (index == size_t(-1)) {
434  proxy.push_back(value);
435  }
436  }
437 
438  void _AddOrReplace(SdfListOpType op, const value_type& value)
439  {
440  ListProxy proxy(_listEditor, op);
441  size_t index = proxy.Find(value);
442  if (index == size_t(-1)) {
443  proxy.push_back(value);
444  }
445  else if (value != static_cast<value_type>(proxy[index])) {
446  proxy[index] = value;
447  }
448  }
449 
450  void _Prepend(SdfListOpType op, const value_type& value)
451  {
452  ListProxy proxy(_listEditor, op);
453  size_t index = proxy.Find(value);
454  if (index != 0) {
455  if (index != size_t(-1)) {
456  proxy.Erase(index);
457  }
458  proxy.insert(proxy.begin(), value);
459  }
460  }
461 
462  void _Append(SdfListOpType op, const value_type& value)
463  {
464  ListProxy proxy(_listEditor, op);
465  size_t index = proxy.Find(value);
466  if (proxy.empty() || (index != proxy.size()-1)) {
467  if (index != size_t(-1)) {
468  proxy.Erase(index);
469  }
470  proxy.push_back(value);
471  }
472  }
473 
474 private:
475  std::shared_ptr<Sdf_ListEditor<TypePolicy> > _listEditor;
476 
478  template <class T> friend class SdfPyWrapListEditorProxy;
479 };
480 
481 // Cannot get from a VtValue except as the correct type.
482 template <class TP>
484  static Vt_DefaultValueHolder Invoke() = delete;
485 };
486 
488 
489 #endif // PXR_USD_SDF_LIST_EDITOR_PROXY_H
bool IsOrderedOnly() const
std::vector< value_type > value_vector_type
ListProxy GetPrependedItems() const
Returns the items prepended by this list editor.
ListProxy GetAppendedItems() const
Returns the items appended by this list editor.
GLsizei const GLfloat * value
Definition: glcorearb.h:824
std::function< std::optional< value_type >const value_type &)> ModifyCallback
ListProxy GetExplicitItems() const
Returns the explicitly set items.
#define TF_CODING_ERROR
void ApplyEditsToList(value_vector_type *vec, CB callback) const
void ModifyItemEdits(CB callback)
bool ContainsItemEdit(const value_type &item, bool onlyAddOrExplicit=false) const
void Prepend(const value_type &value)
void Add(const value_type &value)
**But if you need a result
Definition: thread.h:613
uint64 value_type
Definition: GA_PrimCompat.h:29
bool ClearEditsAndMakeExplicit()
void Erase(const value_type &value)
bool IsExplicit() const
ListProxy GetOrderedItems() const
Returns the items reordered by this list editor.
SdfListEditorProxy(const std::shared_ptr< Sdf_ListEditor< TypePolicy > > &listEditor)
Creates a new proxy object backed by the supplied list editor.
void RemoveItemEdits(const value_type &item)
SdfListOpType
Definition: listOp.h:46
friend class Sdf_ListEditorProxyAccess
ListProxy GetDeletedItems() const
Returns the items deleted by this list editor.
void ApplyEditsToList(value_vector_type *vec) const
Apply the edits to vec.
void Replace(const value_type &oldValue, const value_type &newValue)
Definition: listProxy.h:629
value_vector_type GetAppliedItems() const
SdfListProxy< TypePolicy > ListProxy
_TypePolicy TypePolicy
std::function< std::optional< value_type >SdfListOpType, const value_type &)> ApplyCallback
bool IsExpired() const
Returns true if the list editor is expired.
TypePolicy::value_type value_type
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
void Append(const value_type &value)
ListProxy GetAddedItems() const
Returns the items added by this list editor.
GLuint index
Definition: glcorearb.h:786
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
bool HasKeys() const
void Remove(const value_type &value)
Definition: core.h:1131
value_vector_type GetAddedOrExplicitItems() const
Deprecated. Please use GetAppliedItems.
bool CopyItems(const This &other)
static Vt_DefaultValueHolder Invoke()
Definition: value.h:1529
void ReplaceItemEdits(const value_type &oldItem, const value_type &newItem)
SdfListEditorProxy< TypePolicy > This
void Remove(const value_type &value)
Definition: listProxy.h:616
size_t Find(const value_type &value) const
Definition: listProxy.h:603