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