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 /// \file wrapPrimSpec.cpp
25 
26 #include "pxr/pxr.h"
27 #include "pxr/usd/sdf/primSpec.h"
28 #include "pxr/usd/sdf/attributeSpec.h"
29 #include "pxr/usd/sdf/layer.h"
30 #include "pxr/usd/sdf/pyChildrenProxy.h"
31 #include "pxr/usd/sdf/pySpec.h"
32 #include "pxr/usd/sdf/relationshipSpec.h"
33 #include "pxr/usd/sdf/variantSetSpec.h"
34 
35 #include "pxr/base/tf/pyContainerConversions.h"
36 #include "pxr/base/tf/pyEnum.h"
37 #include "pxr/base/tf/pyPtrHelpers.h"
38 #include "pxr/base/tf/pyResultConversions.h"
39 #include "pxr/base/tf/iterator.h"
40 #include "pxr/base/tf/stringUtils.h"
41 #include "pxr/base/tf/token.h"
42 
43 #include <boost/python.hpp>
44 #include <boost/function.hpp>
45 
46 using namespace boost::python;
47 
48 PXR_NAMESPACE_USING_DIRECTIVE
49 
50 namespace {
51 
52 ////////////////////////////////////////////////////////////////////////
53 // Wrappers for constructors and proxy constructors
54 
55 static
56 SdfPrimSpecHandle
_NewFromLayer(const SdfLayerHandle & parent,const std::string & name,SdfSpecifier spec,const std::string & typeName)57 _NewFromLayer(const SdfLayerHandle& parent,
58           const std::string& name, SdfSpecifier spec,
59           const std::string& typeName)
60 {
61     return SdfPrimSpec::New(parent, name, spec, typeName);
62 }
63 
64 static
65 SdfPrimSpecHandle
_NewTypelessFromLayer(const SdfLayerHandle & parent,const std::string & name,SdfSpecifier spec)66 _NewTypelessFromLayer(const SdfLayerHandle& parent,
67           const std::string& name, SdfSpecifier spec)
68 {
69     return SdfPrimSpec::New(parent, name, spec);
70 }
71 
72 static
73 SdfPrimSpecHandle
_NewPrim(const SdfPrimSpecHandle & parent,const std::string & name,SdfSpecifier spec,const std::string & typeName)74 _NewPrim(const SdfPrimSpecHandle& parent,
75          const std::string& name, SdfSpecifier spec,
76          const std::string& typeName)
77 {
78     return SdfPrimSpec::New(parent, name, spec, typeName);
79 }
80 
81 static
82 SdfPrimSpecHandle
_NewTypelessPrim(const SdfPrimSpecHandle & parent,const std::string & name,SdfSpecifier spec)83 _NewTypelessPrim(const SdfPrimSpecHandle& parent,
84                  const std::string& name, SdfSpecifier spec)
85 {
86     return SdfPrimSpec::New(parent, name, spec);
87 }
88 
89 typedef SdfPyChildrenProxy<SdfPrimSpec::NameChildrenView> NameChildrenProxy;
90 
91 static
92 NameChildrenProxy
_WrapGetNameChildrenProxy(const SdfPrimSpec & prim)93 _WrapGetNameChildrenProxy(const SdfPrimSpec& prim)
94 {
95     return NameChildrenProxy(prim.GetNameChildren(), "prim");
96 }
97 
98 typedef SdfPyChildrenProxy<SdfPrimSpec::PropertySpecView> PropertiesProxy;
99 
100 static
101 PropertiesProxy
_WrapGetPropertiesProxy(const SdfPrimSpec & prim)102 _WrapGetPropertiesProxy(const SdfPrimSpec& prim)
103 {
104     return PropertiesProxy(prim.GetProperties(), "property");
105 }
106 
107 typedef SdfPyChildrenProxy<SdfVariantSetView> VariantSetProxy;
108 
109 static
110 VariantSetProxy
_WrapGetVariantSetsProxy(const SdfPrimSpec & prim)111 _WrapGetVariantSetsProxy(const SdfPrimSpec& prim)
112 {
113     return VariantSetProxy(prim.GetVariantSets());
114 }
115 
116 static void
_SetSymmetryArguments(const SdfPrimSpec & self,VtDictionary const & dictionary)117 _SetSymmetryArguments(const SdfPrimSpec& self,
118                       VtDictionary const &dictionary)
119 {
120     self.GetSymmetryArguments() = dictionary;
121 }
122 
123 static void
_SetCustomData(const SdfPrimSpec & self,VtDictionary const & dictionary)124 _SetCustomData(const SdfPrimSpec& self,
125                VtDictionary const &dictionary)
126 {
127     self.GetCustomData() = dictionary;
128 }
129 
130 static void
_SetAssetInfo(const SdfPrimSpec & self,VtDictionary const & dictionary)131 _SetAssetInfo(const SdfPrimSpec& self,
132               VtDictionary const &dictionary)
133 {
134     self.GetAssetInfo() = dictionary;
135 }
136 
137 static void
_SetRelocates(SdfPrimSpec & self,const dict & d)138 _SetRelocates(SdfPrimSpec& self, const dict &d)
139 {
140     SdfRelocatesMap reloMap;
141 
142     list keys = d.keys();
143     int numKeys = len(d);
144 
145     for (int i = 0; i < numKeys; i++) {
146         SdfPath key = extract<SdfPath>(keys[i]);
147         SdfPath val = extract<SdfPath>(d[keys[i]]);
148 
149         reloMap[key] = val;
150     }
151 
152     self.SetRelocates(reloMap);
153 }
154 
155 ////////////////////////////////////////////////////////////////////////
156 
157 static
158 void
_WrapSetName(SdfPrimSpec & self,const std::string & newName)159 _WrapSetName(SdfPrimSpec& self, const std::string& newName)
160 {
161     // Always validate the new name from python.
162     self.SetName(newName, true);
163 }
164 
165 static
166 bool
_WrapCanSetName(SdfPrimSpec & self,const std::string & newName)167 _WrapCanSetName(SdfPrimSpec& self, const std::string& newName)
168 {
169     std::string errStr;
170     return self.CanSetName(newName, &errStr);
171 }
172 
173 static
174 std::vector<TfToken>
_ApplyNameChildrenOrder(const SdfPrimSpec & self,const std::vector<TfToken> & names)175 _ApplyNameChildrenOrder(
176     const SdfPrimSpec& self,
177     const std::vector<TfToken>& names)
178 {
179     std::vector<TfToken> result = names;
180     self.ApplyNameChildrenOrder(&result);
181     return result;
182 }
183 
184 static
185 std::vector<TfToken>
_ApplyPropertyOrder(const SdfPrimSpec & self,const std::vector<TfToken> & names)186 _ApplyPropertyOrder(
187     const SdfPrimSpec& self,
188     const std::vector<TfToken>& names)
189 {
190     std::vector<TfToken> result = names;
191     self.ApplyPropertyOrder(&result);
192     return result;
193 }
194 
195 } // anonymous namespace
196 
wrapPrimSpec()197 void wrapPrimSpec()
198 {
199     def("CreatePrimInLayer", SdfCreatePrimInLayer);
200     def("JustCreatePrimInLayer", SdfJustCreatePrimInLayer);
201 
202     typedef SdfPrimSpec This;
203 
204     // Register python conversions for vector<SdfPrimSpecHandle>
205     to_python_converter< SdfPrimSpecHandleVector,
206                          TfPySequenceToPython<SdfPrimSpecHandleVector> >();
207     TfPyContainerConversions::from_python_sequence<
208         SdfPrimSpecHandleVector,
209         TfPyContainerConversions::variable_capacity_policy >();
210 
211     // Register python conversions for vector<SdfPrimSpecConstHandle>
212     to_python_converter< SdfPrimSpecConstHandleVector,
213                          TfPySequenceToPython<SdfPrimSpecConstHandleVector> >();
214     TfPyContainerConversions::from_python_sequence<
215         SdfPrimSpecConstHandleVector,
216         TfPyContainerConversions::variable_capacity_policy >();
217 
218     // Register python coversions for SdfVariantSets
219     typedef SdfVariantSetSpecHandleMap::value_type VSSHVT;
220     to_python_converter<VSSHVT,
221                         TfPyContainerConversions::to_tuple<VSSHVT> >();
222     to_python_converter<SdfVariantSetSpecHandleMap,
223                         TfPySequenceToPython<SdfVariantSetSpecHandleMap> >();
224 
225     class_<This, SdfHandle<This>, bases<SdfSpec>, boost::noncopyable>
226         ("PrimSpec", no_init)
227         .def(SdfPySpec())
228 
229         .def(SdfMakePySpecConstructor(&_NewFromLayer))
230         .def(SdfMakePySpecConstructor(&_NewTypelessFromLayer))
231         .def(SdfMakePySpecConstructor(&_NewPrim))
232         .def(SdfMakePySpecConstructor(&_NewTypelessPrim))
233 
234         .add_property("name",
235             make_function(&This::GetName,
236                           return_value_policy<return_by_value>()),
237             &_WrapSetName,
238             "The prim's name.")
239 
240         .add_property("comment",
241             &This::GetComment,
242             &This::SetComment,
243             "The prim's comment string.")
244 
245         .add_property("documentation",
246             &This::GetDocumentation,
247             &This::SetDocumentation,
248             "The prim's documentation string.")
249 
250         .add_property("active",
251             &This::GetActive,
252             &This::SetActive,
253             "Whether this prim spec is active.\n"
254             "The default value is true.")
255 
256         .def("HasActive", &This::HasActive)
257         .def("ClearActive", &This::ClearActive)
258 
259         .add_property("hidden",
260             &This::GetHidden,
261             &This::SetHidden,
262             "Whether this prim spec will be hidden in browsers.\n"
263             "The default value is false.")
264 
265         .add_property("kind",
266             &This::GetKind,
267             &This::SetKind,
268             "What kind of model this prim spec represents, if any.\n"
269             "The default is an empty string")
270 
271         .def("HasKind", &This::HasKind)
272         .def("ClearKind", &This::ClearKind)
273 
274         .add_property("instanceable",
275             &This::GetInstanceable,
276             &This::SetInstanceable,
277             "Whether this prim spec is flagged as instanceable.\n"
278             "The default value is false.")
279 
280         .def("HasInstanceable", &This::HasInstanceable)
281         .def("ClearInstanceable", &This::ClearInstanceable)
282 
283         .add_property("permission",
284             &This::GetPermission,
285             &This::SetPermission,
286             "The prim's permission restriction.\n"
287             "The default value is SdfPermissionPublic.")
288 
289         .add_property("symmetryFunction",
290             &This::GetSymmetryFunction,
291             &This::SetSymmetryFunction,
292             "The prim's symmetry function.")
293 
294         .add_property("symmetryArguments",
295             &This::GetSymmetryArguments,
296             &_SetSymmetryArguments,
297             "Dictionary with prim symmetry arguments.\n\n"
298             "Although this property is marked read-only, you can "
299             "modify the contents to add, change, and clear symmetry "
300             "arguments.")
301 
302         .add_property("symmetricPeer",
303             &This::GetSymmetricPeer,
304             &This::SetSymmetricPeer,
305             "The prims's symmetric peer.")
306 
307         .add_property("customData",
308             &This::GetCustomData,
309             &_SetCustomData,
310             "The custom data for this prim.\n\n"
311             "The default value for custom data is an empty dictionary.\n\n"
312             "Custom data is for use by plugins or other non-tools supplied \n"
313             "extensions that need to be able to store data attached to arbitrary\n"
314             "scene objects.  Note that if the only objects you want to store data\n"
315             "on are prims, using custom attributes is probably a better choice.\n"
316             "But if you need to possibly store this data on attributes or \n"
317             "relationships or as annotations on reference arcs, then custom data\n"
318             "is an appropriate choice.")
319 
320         .add_property("assetInfo",
321             &This::GetAssetInfo,
322             &_SetAssetInfo,
323             "Returns the asset info dictionary for this prim.\n\n"
324             "The default value is an empty dictionary.\n\n"
325             "The asset info dictionary is used to annotate prims representing "
326             "the root-prims of assets (generally organized as models) with "
327             "various data related to asset management. For example, asset "
328             "name, root layer identifier, asset version etc.")
329 
330         .add_property("specifier",
331             &This::GetSpecifier,
332             &This::SetSpecifier,
333             "The prim's specifier (SpecifierDef or SpecifierOver).\n"
334             "The default value is SpecifierOver.")
335 
336         .add_property("nameRoot",
337             &This::GetNameRoot,
338             "The name pseudo-root of this prim.")
339 
340         .add_property("nameParent",
341             &This::GetNameParent,
342             "The name parent of this prim.")
343 
344         .add_property("realNameParent",
345             &This::GetRealNameParent,
346             "The name parent of this prim.")
347 
348         .def("GetObjectAtPath",
349             &This::GetObjectAtPath,
350             "GetObjectAtPath(path) -> object\n\n"
351             "path: Path\n\n"
352             "Returns a prim or property given its namespace path.\n\n"
353             "If path is relative then it will be interpreted as relative "
354             "to this prim.  If it is absolute then it will be "
355             "interpreted as absolute in this prim's layer. The "
356             "return type can be either PrimSpecPtr or "
357             "PropertySpecPtr.")
358         .def("GetPrimAtPath", &This::GetPrimAtPath)
359         .def("GetPropertyAtPath", &This::GetPropertyAtPath)
360         .def("RemoveProperty", &This::RemoveProperty)
361         .def("GetAttributeAtPath", &This::GetAttributeAtPath)
362         .def("GetRelationshipAtPath", &This::GetRelationshipAtPath)
363         .def("GetVariantNames", &This::GetVariantNames)
364         .def("BlockVariantSelection", &This::BlockVariantSelection)
365 
366         .add_property("variantSelections",
367             &This::GetVariantSelections,
368             "Dictionary whose keys are variant set names and whose values are "
369             "the variants chosen for each set.\n\n"
370             "Although this property is marked read-only, you can "
371             "modify the contents to add, change, and clear variants.")
372 
373         .add_property("prefix",
374             &This::GetPrefix,
375             &This::SetPrefix,
376             "The prim's prefix.")
377 
378         .add_property("prefixSubstitutions",
379             &This::GetPrefixSubstitutions,
380             &This::SetPrefixSubstitutions,
381             "Dictionary of prefix substitutions.")
382 
383         .add_property("suffix",
384             &This::GetSuffix,
385             &This::SetSuffix,
386             "The prim's suffix.")
387 
388         .add_property("suffixSubstitutions",
389             &This::GetSuffixSubstitutions,
390             &This::SetSuffixSubstitutions,
391             "Dictionary of prefix substitutions.")
392 
393         .add_property("variantSetNameList",
394             &This::GetVariantSetNameList,
395             "A StringListEditor for the names of the variant \n"
396             "sets for this prim.\n\n"
397             "The list of the names of the variants sets of this prim may be\n"
398             "modified with this StringListEditor.\n\n"
399             "A StringListEditor may express a list either as an explicit "
400             "value or as a set of list editing operations.  See StringListEditor "
401             "for more information.\n\n"
402             "Although this property is marked as read-only, the returned object "
403             "is modifiable.")
404 
405         .add_property("variantSets",
406             &_WrapGetVariantSetsProxy,
407             "The VariantSetSpecs for this prim indexed by name.\n\n"
408             "Although this property is marked as read-only, you can \n"
409             "modify the contents to remove variant sets.  New variant sets \n"
410             "are created by creating them with the prim as the owner.\n\n"
411             "Although this property is marked as read-only, the returned object\n"
412             "is modifiable.")
413 
414         .add_property("typeName",
415             &This::GetTypeName,
416             &This::SetTypeName,
417             "The type of this prim.")
418 
419         .add_property("nameChildren",
420             &_WrapGetNameChildrenProxy,
421             "The prim name children of this prim, as an ordered "
422             "dictionary.\n\n"
423             "Note that although this property is described as being "
424             "read-only, you can modify the contents to add, "
425             "remove, or reorder children.")
426 
427         .add_property("nameChildrenOrder",
428             &This::GetNameChildrenOrder,
429             &This::SetNameChildrenOrder,
430             "Get/set the list of child names for this prim's 'reorder "
431             "nameChildren' statement.")
432 
433         .add_property("properties",
434             &_WrapGetPropertiesProxy,
435             "The properties of this prim, as an ordered dictionary.\n\n"
436             "Note that although this property is described as being "
437             "read-only, you can modify the contents to add, "
438             "remove, or reorder properties.")
439 
440         .add_property("attributes",
441             &This::GetAttributes,
442             "The attributes of this prim, as an ordered dictionary.")
443 
444         .add_property("relationships",
445             &This::GetRelationships,
446             "The relationships of this prim, as an ordered dictionary.")
447 
448         .add_property("propertyOrder",
449             &This::GetPropertyOrder,
450             &This::SetPropertyOrder,
451             "Get/set the list of property names for this prim's 'reorder "
452             "properties' statement.")
453 
454         .add_property("inheritPathList",
455             &This::GetInheritPathList,
456             "A PathListEditor for the prim's inherit paths.\n\n"
457             "The list of the inherit paths for this prim may be "
458             "modified with this PathListEditor.\n\n"
459             "A PathListEditor may express a list either as an explicit "
460             "value or as a set of list editing operations.  See PathListEditor "
461             "for more information.")
462 
463         .add_property("specializesList",
464             &This::GetSpecializesList,
465             "A PathListEditor for the prim's specializes.\n\n"
466             "The list of the specializes for this prim may be "
467             "modified with this PathListEditor.\n\n"
468             "A PathListEditor may express a list either as an explicit "
469             "value or as a set of list editing operations.  See PathListEditor "
470             "for more information.")
471 
472         .add_property("referenceList",
473             &This::GetReferenceList,
474             "A ReferenceListEditor for the prim's references.\n\n"
475             "The list of the references for this prim may be "
476             "modified with this ReferenceListEditor.\n\n"
477             "A ReferenceListEditor may express a list either as an explicit "
478             "value or as a set of list editing operations.  See "
479             "ReferenceListEditor for more information.")
480 
481         .add_property("payloadList",
482             &This::GetPayloadList,
483             "A PayloadListEditor for the prim's payloads.\n\n"
484             "The list of the payloads for this prim may be "
485             "modified with this PayloadListEditor.\n\n"
486             "A PayloadListEditor may express a list either as an explicit "
487             "value or as a set of list editing operations.  See "
488             "PayloadListEditor for more information.")
489 
490         .add_property("hasReferences",
491             &This::HasReferences,
492             "Returns true if this prim has references set.")
493 
494         .add_property("hasPayloads",
495             &This::HasPayloads,
496             "Returns true if this prim has payloads set.")
497 
498         .add_property("relocates",
499             &This::GetRelocates,
500             &_SetRelocates,
501             "An editing proxy for the prim's map of relocation paths.\n\n"
502             "The map of source-to-target paths specifying namespace "
503             "relocation may be set or cleared whole, or individual map "
504             "entries may be added, removed, or edited.")
505 
506         .def("ClearReferenceList",
507             &This::ClearReferenceList,
508             "Clears the references for this prim.")
509 
510         .def("ClearPayloadList",
511             &This::ClearPayloadList,
512             "Clears the payloads for this prim.")
513 
514         .def("CanSetName", &_WrapCanSetName)
515 
516         .def("ApplyNameChildrenOrder", &_ApplyNameChildrenOrder,
517              return_value_policy<TfPySequenceToList>())
518         .def("ApplyPropertyOrder", &_ApplyPropertyOrder,
519              return_value_policy<TfPySequenceToList>())
520 
521         .setattr("ActiveKey", SdfFieldKeys->Active)
522         .setattr("AnyTypeToken", SdfTokens->AnyTypeToken)
523         .setattr("CommentKey", SdfFieldKeys->Comment)
524         .setattr("CustomDataKey", SdfFieldKeys->CustomData)
525         .setattr("DocumentationKey", SdfFieldKeys->Documentation)
526         .setattr("HiddenKey", SdfFieldKeys->Hidden)
527         .setattr("InheritPathsKey", SdfFieldKeys->InheritPaths)
528         .setattr("KindKey", SdfFieldKeys->Kind)
529         .setattr("PrimOrderKey", SdfFieldKeys->PrimOrder)
530         .setattr("PayloadKey", SdfFieldKeys->Payload)
531         .setattr("PermissionKey", SdfFieldKeys->Permission)
532         .setattr("PrefixKey", SdfFieldKeys->Prefix)
533         .setattr("PrefixSubstitutionsKey", SdfFieldKeys->PrefixSubstitutions)
534         .setattr("PropertyOrderKey", SdfFieldKeys->PropertyOrder)
535         .setattr("ReferencesKey", SdfFieldKeys->References)
536         .setattr("RelocatesKey", SdfFieldKeys->Relocates)
537         .setattr("SpecializesKey", SdfFieldKeys->Specializes)
538         .setattr("SpecifierKey", SdfFieldKeys->Specifier)
539         .setattr("SymmetricPeerKey", SdfFieldKeys->SymmetricPeer)
540         .setattr("SymmetryArgumentsKey", SdfFieldKeys->SymmetryArguments)
541         .setattr("SymmetryFunctionKey", SdfFieldKeys->SymmetryFunction)
542         .setattr("TypeNameKey", SdfFieldKeys->TypeName)
543         .setattr("VariantSelectionKey", SdfFieldKeys->VariantSelection)
544         .setattr("VariantSetNamesKey", SdfFieldKeys->VariantSetNames)
545         ;
546 }
547