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