├── treemodel ├── __init__.py └── qt │ ├── __init__.py │ └── base.py ├── requirements.txt ├── .gitignore ├── pxr ├── UsdQtEditors.py ├── usdQt │ ├── testenv │ │ ├── testUsdQtLayerModel │ │ │ ├── simpleLayerStack_two.usda │ │ │ ├── simpleLayerStack_child_one.usda │ │ │ ├── simpleLayerStack_three.usda │ │ │ ├── simpleLayerStack_one.usdc │ │ │ └── simpleLayerStack.usda │ │ ├── testUsdQtPrimFilterCache │ │ │ └── simpleFilter.usda │ │ ├── testUsdQtOpinionModel │ │ │ └── simple.usda │ │ ├── testUsdQtHierarchyModel │ │ │ └── simpleHierarchy.usda │ │ ├── testUsdQtOpinionProxy │ │ │ └── simple.usda │ │ ├── testUsdQtPrimFilterCache.py │ │ ├── testUsdQtLayerModel.py │ │ ├── testUsdQtOpinionModel.py │ │ └── testUsdQtUndoRouter.py │ ├── __init__.py │ ├── utils.cpp │ ├── proxyBase.cpp │ ├── module.cpp │ ├── _bindings.py │ ├── debugCodes.h │ ├── displayGroupProxy.cpp │ ├── _Qt.py │ ├── proxyBase.h │ ├── utils.h │ ├── moduleDeps.cpp │ ├── debugCodes.cpp │ ├── wrapPrimFilterCache.cpp │ ├── CMakeLists.txt │ ├── displayGroupProxy.h │ ├── undoBlock.h │ ├── wrapHierarchyCache.cpp │ ├── undoRouter.cpp │ ├── undoBlock.cpp │ ├── undoInverse.cpp │ ├── wrapUndoRouter.cpp │ ├── undoInverse.h │ ├── relationshipProxy.h │ ├── roles.py │ ├── icons │ │ ├── noarcs_2.xpm │ │ ├── arcs_2.xpm │ │ ├── arcs.xpm │ │ └── noarcs.xpm │ ├── hooks.py │ ├── primProxy.h │ ├── undoRouter.h │ ├── relationshipProxy.cpp │ ├── stageCacheModel.py │ ├── compatability.py │ ├── usdUtils.py │ ├── attributeProxy.h │ ├── primProxy.cpp │ ├── primFilterCache.h │ ├── variantSetsProxy.h │ ├── objectProxy.h │ ├── hierarchyCache.h │ ├── attributeProxy.cpp │ ├── layerModel.py │ ├── metadataProxy.h │ ├── objectProxy.cpp │ ├── variantSetsProxy.cpp │ ├── undoStateDelegate.h │ └── metadataProxy.cpp ├── CMakeLists.txt ├── __init__.py ├── UsdQt.py └── usdQtEditors │ ├── CMakeLists.txt │ ├── __init__.py │ ├── _Qt.py │ └── treeView.py ├── CMakeLists.txt ├── setup.py ├── cmake └── macros │ └── compilePython.py └── README.md /treemodel/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | PySide2 2 | -------------------------------------------------------------------------------- /treemodel/qt/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build.sh 2 | *.pyc 3 | -------------------------------------------------------------------------------- /pxr/UsdQtEditors.py: -------------------------------------------------------------------------------- 1 | import pxr.usdQtEditors 2 | globals().update(pxr.usdQtEditors.__dict__) 3 | -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtLayerModel/simpleLayerStack_two.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | 3 | ( 4 | subLayers = [] 5 | ) -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtLayerModel/simpleLayerStack_child_one.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | 3 | ( 4 | subLayers = [] 5 | ) -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtLayerModel/simpleLayerStack_three.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | 3 | ( 4 | subLayers = [] 5 | ) -------------------------------------------------------------------------------- /pxr/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | install( 3 | FILES __init__.py 4 | DESTINATION lib/python/pxr/ 5 | ) 6 | 7 | add_subdirectory(usdQt) 8 | add_subdirectory(usdQtEditors) 9 | -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtLayerModel/simpleLayerStack_one.usdc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LumaPictures/usd-qt/HEAD/pxr/usdQt/testenv/testUsdQtLayerModel/simpleLayerStack_one.usdc -------------------------------------------------------------------------------- /pxr/__init__.py: -------------------------------------------------------------------------------- 1 | try: 2 | __import__('pkg_resources').declare_namespace(__name__) 3 | except: 4 | from pkgutil import extend_path 5 | __path__ = extend_path(__path__, __name__) 6 | -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtLayerModel/simpleLayerStack.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | 3 | ( 4 | subLayers = [@./simpleLayerStack_one.usdc@, 5 | @./simpleLayerStack_two.usda@, 6 | @./simpleLayerStack_three.usda@] 7 | ) -------------------------------------------------------------------------------- /pxr/UsdQt.py: -------------------------------------------------------------------------------- 1 | from pkgutil import extend_path 2 | import imp 3 | import sys 4 | _usdQt = imp.load_module('pxr.UsdQt._usdQt', 5 | *imp.find_module('_usdQt', 6 | extend_path([], 'pxr.UsdQt'))) 7 | sys.modules['pxr'].UsdQt = sys.modules['pxr.UsdQt'] 8 | import pxr.usdQt 9 | # make this module proxy the usdQt package 10 | globals().update(pxr.usdQt.__dict__) 11 | 12 | del sys, imp, extend_path 13 | -------------------------------------------------------------------------------- /pxr/usdQtEditors/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(PXR_PREFIX pxr/usdQtEditors) 2 | set(PXR_PACKAGE usdQtEditors) 3 | 4 | if (INSTALL_PURE_PYTHON) 5 | set(PYTHON_FILES 6 | _Qt.py 7 | __init__.py 8 | hierarchyEditor.py 9 | layerTextEditor.py 10 | opinionEditor.py 11 | outliner.py 12 | treeView.py 13 | ) 14 | else () 15 | set(PYTHON_FILES 16 | __init__.py) 17 | endif() 18 | 19 | 20 | _pxr_python_module(usdQtEditors 21 | PYTHON_LIBRARY 22 | PYTHON_FILES 23 | ${PYTHON_FILES} 24 | ) 25 | -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtPrimFilterCache/simpleFilter.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | 3 | def "World"(){ 4 | def "Reject" (){ 5 | } 6 | 7 | def "Accept" (){ 8 | } 9 | 10 | def "AcceptParent" (){ 11 | def "RejectChild" (){ 12 | } 13 | 14 | def "AcceptChild" (){ 15 | } 16 | } 17 | 18 | def "IntermediateParent" (){ 19 | def "RejectChild" (){ 20 | } 21 | 22 | def "IntermediateChild" (){ 23 | def "AcceptGrandchild" (){ 24 | } 25 | def "RejectGrandchild" (){ 26 | } 27 | 28 | } 29 | 30 | def "AcceptChild" (){ 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtOpinionModel/simple.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | 3 | def Xform "MyPrim1" ( 4 | kind = "prop" 5 | add variantSets = ["variant1", "variant2"]){ 6 | def "Child1"{ 7 | int x = 1 8 | int y = 2 9 | rel rel1 = 10 | rel rel2 11 | } 12 | def "Child2"{ 13 | string x = "one" 14 | int y = 2 15 | rel rel1 = 16 | rel rel2 = 17 | } 18 | def "Child3"{ 19 | int x = 2 20 | int y = 2 21 | rel rel1 = 22 | } 23 | def "Child4" { 24 | int x = 1 25 | int y = 2 26 | color3f z = (.5, .6, .7) 27 | rel rel1 = 28 | } 29 | } 30 | 31 | def Xform "MyPrim2" (add variantSets = ["variant2"] 32 | kind = "prop"){ 33 | } 34 | -------------------------------------------------------------------------------- /pxr/usdQt/__init__.py: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /pxr/usdQtEditors/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 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 | -------------------------------------------------------------------------------- /pxr/usdQt/utils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | 26 | #include "utils.h" 27 | -------------------------------------------------------------------------------- /pxr/usdQt/proxyBase.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "proxyBase.h" 26 | 27 | PXR_NAMESPACE_OPEN_SCOPE 28 | 29 | bool UsdQt_ProxyBase::IsValid() const { return true; } 30 | 31 | PXR_NAMESPACE_CLOSE_SCOPE -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtHierarchyModel/simpleHierarchy.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | 3 | def Xform "World" { 4 | 5 | def Xform "PrimToDeactivate"(active=True){ 6 | def Xform "Child1" { 7 | def Xform "Grandchild1"{ 8 | } 9 | def Xform "Grandchild2"{ 10 | } 11 | } 12 | def Xform "Child2"{ 13 | } 14 | } 15 | 16 | def Xform "PrimToActivate" (active=False){ 17 | def Xform "Child1" { 18 | def Xform "Grandchild1"{ 19 | } 20 | def Xform "Grandchild2"{ 21 | } 22 | } 23 | def Xform "Child2"{ 24 | } 25 | } 26 | 27 | 28 | def Xform "PrimWithVariants" (add variantSets = "testVariant"){ 29 | variantSet "testVariant" = { 30 | "Variant1"{ 31 | def "VariantChild0"{} 32 | def "VariantChild1"{ 33 | def "VariantGrandchild1"{ 34 | } 35 | } 36 | def "VariantChild2"{ 37 | } 38 | } 39 | "Variant2"{ 40 | def "VariantChild1"{ 41 | def "DifferentVariantGrandchild1"{ 42 | } 43 | } 44 | def "VariantChild3"{ 45 | } 46 | } 47 | } 48 | 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /pxr/usdQt/module.cpp: -------------------------------------------------------------------------------- 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 | 25 | #include "pxr/base/tf/pyModule.h" 26 | 27 | using namespace BOOST_NS::python; 28 | 29 | TF_WRAP_MODULE { 30 | TF_WRAP(HierarchyCache); 31 | TF_WRAP(OpinionProxy); 32 | TF_WRAP(PrimFilterCache); 33 | TF_WRAP(UndoRouter); 34 | } 35 | -------------------------------------------------------------------------------- /pxr/usdQtEditors/_Qt.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 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 | 25 | # Use this for site customization of Qt binding versions. This code targets 26 | # PySide2, but may be compatible with a variety of other shims/APIs. Override 27 | # this file to specify any site specific preferences. 28 | 29 | from __future__ import absolute_import 30 | import pxr.UsdQt._Qt 31 | 32 | globals().update(pxr.UsdQt._Qt.__dict__) 33 | 34 | del pxr 35 | -------------------------------------------------------------------------------- /pxr/usdQt/_bindings.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 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 | 25 | import pxr.UsdQt._usdQt as _usdQt 26 | from pxr import Tf 27 | Tf.PrepareModule(_usdQt, locals()) 28 | del _usdQt, Tf 29 | 30 | try: 31 | import __DOC 32 | __DOC.Execute(locals()) 33 | del __DOC 34 | except Exception: 35 | try: 36 | import __tmpDoc 37 | __tmpDoc.Execute(locals()) 38 | del __tmpDoc 39 | except: 40 | pass 41 | -------------------------------------------------------------------------------- /pxr/usdQt/debugCodes.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_DEBUG_H 26 | #define USDQT_DEBUG_H 27 | 28 | #include "pxr/pxr.h" 29 | #include "pxr/base/tf/debug.h" 30 | 31 | PXR_NAMESPACE_OPEN_SCOPE 32 | 33 | TF_DEBUG_CODES(USDQT_DEBUG_HIERARCHYCACHE, USDQT_DEBUG_PRIMFILTERCACHE, 34 | USDQT_DEBUG_UNDOSTATEDELEGATE, USDQT_DEBUG_UNDOSTACK); 35 | 36 | PXR_NAMESPACE_CLOSE_SCOPE 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /pxr/usdQt/displayGroupProxy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "displayGroupProxy.h" 26 | 27 | PXR_NAMESPACE_OPEN_SCOPE 28 | 29 | UsdQt_DisplayGroupProxy::UsdQt_DisplayGroupProxy(const TfToken &name) 30 | : _name(name) {} 31 | 32 | UsdQt_DisplayGroupProxyRefPtr 33 | UsdQt_DisplayGroupProxy::New(const TfToken &name) { 34 | return TfCreateRefPtr(new UsdQt_DisplayGroupProxy(name)); 35 | } 36 | 37 | TfToken UsdQt_DisplayGroupProxy::GetName() const { return _name; } 38 | 39 | PXR_NAMESPACE_CLOSE_SCOPE -------------------------------------------------------------------------------- /pxr/usdQt/_Qt.py: -------------------------------------------------------------------------------- 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 | 25 | # Use this for site customization of Qt binding versions. This code targets 26 | # PySide2, but may be compatible with a variety of other shims/APIs. Override 27 | # this file to specify any site specific preferences. 28 | 29 | from __future__ import absolute_import 30 | 31 | def _get_proxied_module(): 32 | import os 33 | import importlib 34 | mod = os.environ.get('PXR_QT_PYTHON_BINDING', 'PySide2') 35 | return importlib.import_module(mod) 36 | 37 | globals().update(_get_proxied_module().__dict__) 38 | 39 | del _get_proxied_module 40 | -------------------------------------------------------------------------------- /pxr/usdQt/proxyBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_PROXYBASE_H 26 | #define USDQT_PROXYBASE_H 27 | 28 | #include "pxr/pxr.h" 29 | #include "pxr/base/tf/declarePtrs.h" 30 | #include "pxr/base/tf/weakPtr.h" 31 | 32 | PXR_NAMESPACE_OPEN_SCOPE 33 | 34 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_ProxyBase); 35 | 36 | /// \brief Common super class of an proxy for use with the QAbstractItemModels 37 | class UsdQt_ProxyBase : public TfRefBase, public TfWeakBase { 38 | public: 39 | virtual bool IsValid() const; 40 | }; 41 | 42 | PXR_NAMESPACE_CLOSE_SCOPE 43 | 44 | #endif -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # >=3.1 is required for CMAKE_CXX_STANDARD 3 | cmake_minimum_required(VERSION 3.1) 4 | project(usdqt) 5 | 6 | if (UNIX AND NOT APPLE) 7 | set(LINUX TRUE) 8 | endif () 9 | 10 | set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules;${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros") 11 | 12 | if (NOT MSVC) 13 | add_compile_options(-Wall -Wno-unused-local-typedefs -Wno-deprecated ) 14 | else() 15 | add_compile_options("/DNOMINMAX") 16 | endif() 17 | 18 | add_compile_options(-DBUILD_OPTLEVEL_OPT -DBUILD_COMPONENT_SRC_PREFIX="") 19 | 20 | option(INSTALL_PURE_PYTHON "Install pure python files. Disable to only install compiled extension" ON) 21 | 22 | set(BOOST_SYMBOL_NAMESPACE "boost" 23 | CACHE STRING 24 | "The symbol namespace used in the Boost build. Defaults to \"boost\"") 25 | 26 | include(Private) 27 | 28 | if (NOT DEFINED CMAKE_CXX_STANDARD) 29 | set(CMAKE_CXX_STANDARD 14) 30 | endif() 31 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 32 | 33 | find_package(USD REQUIRED) 34 | find_package(TBB REQUIRED) 35 | 36 | find_package(PythonInterp 2.7 REQUIRED) 37 | find_package(PythonLibs 2.7 REQUIRED) 38 | 39 | set(Boost_USE_STATIC_LIBS OFF) 40 | find_package(Boost COMPONENTS python27) 41 | if (NOT Boost_FOUND) 42 | find_package(Boost COMPONENTS python REQUIRED) 43 | endif() 44 | 45 | include_directories(${Boost_INCLUDE_DIRS}) 46 | 47 | include_directories(${USD_INCLUDE_DIR}) 48 | link_directories(${USD_LIBRARY_DIR}) 49 | 50 | include_directories(SYSTEM ${PYTHON_INCLUDE_DIRS}) 51 | include_directories(SYSTEM ${TBB_INCLUDE_DIRS}) 52 | 53 | add_subdirectory(pxr) 54 | 55 | # TODO: Compile installed .py files as well 56 | install(DIRECTORY treemodel 57 | DESTINATION lib/python 58 | PATTERN "*.py") 59 | -------------------------------------------------------------------------------- /pxr/usdQt/utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_OBJECTUTILS_H 26 | #define USDQT_OBJECTUTILS_H 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #include "pxr/pxr.h" 34 | #include "pxr/base/vt/array.h" 35 | 36 | PXR_NAMESPACE_OPEN_SCOPE 37 | 38 | template 39 | bool UsdQt_ItemNotInVector(const std::vector& v, const Type& item) { 40 | return std::find(v.begin(), v.end(), item) == v.end(); 41 | } 42 | 43 | template 44 | bool UsdQt_ItemNotInArray(const VtArray& v, const Type& item) { 45 | return std::find(v.begin(), v.end(), item) == v.end(); 46 | } 47 | 48 | PXR_NAMESPACE_CLOSE_SCOPE 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /pxr/usdQt/moduleDeps.cpp: -------------------------------------------------------------------------------- 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 | //////////////////////////////////////////////////////////////////////// 25 | 26 | #include "pxr/pxr.h" 27 | #include "pxr/base/tf/registryManager.h" 28 | #include "pxr/base/tf/scriptModuleLoader.h" 29 | #include "pxr/base/tf/token.h" 30 | 31 | #include 32 | 33 | PXR_NAMESPACE_OPEN_SCOPE 34 | 35 | TF_REGISTRY_FUNCTION(TfScriptModuleLoader) { 36 | // List of direct dependencies for this library. 37 | const std::vector reqs = { 38 | TfToken("sdf"), 39 | TfToken("tf"), 40 | TfToken("usd") 41 | }; 42 | TfScriptModuleLoader::GetInstance(). 43 | RegisterLibrary(TfToken("usdQt"), TfToken("pxr.UsdQt"), reqs); 44 | } 45 | 46 | PXR_NAMESPACE_CLOSE_SCOPE 47 | 48 | 49 | -------------------------------------------------------------------------------- /pxr/usdQt/debugCodes.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "debugCodes.h" 26 | 27 | PXR_NAMESPACE_OPEN_SCOPE 28 | 29 | TF_REGISTRY_FUNCTION(TfDebug) { 30 | TF_DEBUG_ENVIRONMENT_SYMBOL( 31 | USDQT_DEBUG_HIERARCHYCACHE, 32 | "Enabling debug information for the hierarchy cache."); 33 | TF_DEBUG_ENVIRONMENT_SYMBOL( 34 | USDQT_DEBUG_PRIMFILTERCACHE, 35 | "Enabling debug information for the prim filter cache."); 36 | TF_DEBUG_ENVIRONMENT_SYMBOL( 37 | USDQT_DEBUG_UNDOSTATEDELEGATE, 38 | "Enabling debug information for the layer state delegate."); 39 | TF_DEBUG_ENVIRONMENT_SYMBOL(USDQT_DEBUG_UNDOSTACK, 40 | "Enabling Undo Stack debugging."); 41 | } 42 | 43 | PXR_NAMESPACE_CLOSE_SCOPE 44 | -------------------------------------------------------------------------------- /pxr/usdQt/wrapPrimFilterCache.cpp: -------------------------------------------------------------------------------- 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 | 25 | #include 26 | #include 27 | 28 | #include "pxr/pxr.h" 29 | #include "pxr/base/tf/pyEnum.h" 30 | 31 | #include "primFilterCache.h" 32 | 33 | using namespace BOOST_NS::python; 34 | 35 | PXR_NAMESPACE_USING_DIRECTIVE 36 | 37 | void wrapPrimFilterCache() { 38 | { 39 | typedef UsdQtPrimFilterCache This; 40 | scope obj = 41 | class_("PrimFilterCache", init<>()) 42 | .def("ApplyPathContainsFilter", &This::ApplyPathContainsFilter) 43 | .def("GetState", &This::GetState) 44 | .def("PrintDebugString", &This::PrintDebugString); 45 | TfPyWrapEnum(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pxr/usdQt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(PXR_PREFIX pxr/usdQt) 2 | set(PXR_PACKAGE usdQt) 3 | 4 | add_compile_definitions(BOOST_NS=${BOOST_SYMBOL_NAMESPACE}) 5 | 6 | # Adding these targets tricks the `_pxr_python_module` function into working 7 | # outside of a normal USD build context. 8 | add_custom_target(shared_libs) 9 | add_custom_target(python ALL) 10 | 11 | if (INSTALL_PURE_PYTHON) 12 | set(PYTHON_FILES 13 | _Qt.py 14 | __init__.py 15 | _bindings.py 16 | compatability.py 17 | hierarchyModel.py 18 | hooks.py 19 | layerModel.py 20 | opinionModel.py 21 | opinionStackModel.py 22 | qtUtils.py 23 | roles.py 24 | stageCacheModel.py 25 | usdUtils.py 26 | valueDelegate.py 27 | valueWidgets.py 28 | ) 29 | else () 30 | set(PYTHON_FILES 31 | __init__.py) 32 | endif() 33 | 34 | 35 | _pxr_python_module(usdQt 36 | PYTHON_LIBRARY 37 | LIBRARIES 38 | tf 39 | sdf 40 | vt 41 | pcp 42 | arch 43 | usd 44 | ${Boost_PYTHON_LIBRARY} 45 | ${PYTHON_LIBRARIES} 46 | 47 | INCLUDE_DIRS 48 | ${Boost_INCLUDE_DIRS} 49 | ${PYTHON_INCLUDE_DIRS} 50 | 51 | CPPFILES 52 | attributeProxy.cpp 53 | debugCodes.cpp 54 | displayGroupProxy.cpp 55 | hierarchyCache.cpp 56 | metadataProxy.cpp 57 | objectProxy.cpp 58 | primFilterCache.cpp 59 | primProxy.cpp 60 | proxyBase.cpp 61 | relationshipProxy.cpp 62 | variantSetsProxy.cpp 63 | utils.cpp 64 | undoBlock.cpp 65 | undoInverse.cpp 66 | undoRouter.cpp 67 | undoStateDelegate.cpp 68 | wrapHierarchyCache.cpp 69 | wrapOpinionProxy.cpp 70 | wrapPrimFilterCache.cpp 71 | wrapUndoRouter.cpp 72 | module.cpp 73 | moduleDeps.cpp 74 | 75 | PYTHON_FILES 76 | ${PYTHON_FILES} 77 | ) 78 | -------------------------------------------------------------------------------- /pxr/usdQt/displayGroupProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_DISPLAYGROUPPROXY_H 26 | #define USDQT_DISPLAYGROUPPROXY_H 27 | 28 | #include "pxr/pxr.h" 29 | #include "pxr/base/tf/token.h" 30 | 31 | #include "proxyBase.h" 32 | 33 | PXR_NAMESPACE_OPEN_SCOPE 34 | 35 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_DisplayGroupProxy); 36 | 37 | /// \class UsdQt_DisplayGroupProxy 38 | /// \brief Proxy interface for an display group 39 | class UsdQt_DisplayGroupProxy : public UsdQt_ProxyBase { 40 | private: 41 | TfToken _name; 42 | explicit UsdQt_DisplayGroupProxy(const TfToken& displayName); 43 | 44 | public: 45 | static UsdQt_DisplayGroupProxyRefPtr New(const TfToken& displayName); 46 | 47 | /// \brief Return the name of the displayGroup 48 | TfToken GetName() const; 49 | }; 50 | 51 | PXR_NAMESPACE_CLOSE_SCOPE 52 | 53 | #endif -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import fnmatch 2 | import os 3 | from setuptools import setup, find_packages 4 | from distutils.extension import Extension 5 | from codecs import open # For consistent encoding 6 | 7 | here = os.path.abspath(os.path.dirname(__file__)) 8 | 9 | with open(os.path.join(here, 'README.md'), encoding='utf-8') as f: 10 | long_description = f.read() 11 | 12 | with open(os.path.join(here, 'requirements.txt'), encoding='utf-8') as f: 13 | requirements = f.read().splitlines() 14 | 15 | usdQtFiles = os.listdir(os.path.join(here, 'usdQt')) 16 | extensionSources = [] 17 | extensionSources.extend(fnmatch.filter(usdQtFiles, '*.cpp')) 18 | extensionSources.extend(fnmatch.filter(usdQtFiles, '*.h')) 19 | extensionSources = ['usdQt/%s' % name for name in extensionSources] 20 | 21 | cppModule = Extension( 22 | 'usdQt._usdQt', 23 | define_macros = [('BUILD_OPTLEVEL_OPT', None), 24 | ('BUILD_COMPONENT_SRC_PREFIX', ""), 25 | ('MFB_PACKAGE_NAME', 'usdQt'), 26 | ('MFB_ALT_PACKAGE_NAME', 'usdQt'), 27 | ('MFB_PACKAGE_MODULE', 'UsdQt'), 28 | ('BOOST_PYTHON_NO_PY_SIGNATURES', None), 29 | ('PXR_PYTHON_SUPPORT_ENABLED', None)], 30 | libraries = ['boost_python-mt', 'tbb', 'usd', 'sdf', 'tf'], 31 | sources = extensionSources, 32 | extra_compile_args=['-std=c++11', '-Wno-unused-local-typedefs', '-Wno-deprecated']) 33 | 34 | packages = find_packages(exclude=['tests']) 35 | 36 | setup( 37 | name='UsdQt', 38 | version='0.5.0', 39 | description='USD Qt Components', 40 | long_description=long_description, 41 | url='https://github.com/LumaPictures/usd-qt', 42 | license='Modified Apache 2.0 License', 43 | packages=packages, 44 | package_dir={'UsdQt':'usdQt'}, 45 | install_requires=requirements, 46 | ext_modules=[cppModule] 47 | # entry_points={ 48 | # 'console_scripts': [ 49 | # 'usdoutliner=sample:main', 50 | # ], 51 | # }, 52 | ) 53 | -------------------------------------------------------------------------------- /pxr/usdQt/undoBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_UNDOBLOCK_H 26 | #define USDQT_UNDOBLOCK_H 27 | 28 | #include "pxr/pxr.h" 29 | #include "pxr/usd/sdf/layer.h" 30 | #include "pxr/base/tf/weakPtr.h" 31 | #include "pxr/base/tf/refPtr.h" 32 | #include "pxr/base/tf/declarePtrs.h" 33 | 34 | PXR_NAMESPACE_OPEN_SCOPE 35 | 36 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQtUndoRouter); 37 | 38 | /// \class UsdQtUndoBlock 39 | /// 40 | /// Similar to an SdfChangeBlock, this will collect multiple edits into a single 41 | /// undo operation. 42 | /// 43 | /// Because edit tracking is done at the Sdf level, it's important to 44 | /// aggressively use UndoBlocks even around single Usd calls. One Usd call 45 | /// may map to multiple Sdf calls, each spawning their own unique inverse. 46 | /// 47 | /// Future refactoring may try to address and smooth over this quirk. 48 | /// 49 | /// Sample Python Usage: 50 | /// 51 | /// with UsdQt.UndoBlock(): 52 | /// attribute1.Set(5) 53 | /// attribute2.Set(6) 54 | /// 55 | class UsdQtUndoBlock { 56 | private: 57 | void _Initialize(); 58 | 59 | public: 60 | explicit UsdQtUndoBlock(); 61 | ~UsdQtUndoBlock(); 62 | }; 63 | 64 | PXR_NAMESPACE_CLOSE_SCOPE 65 | 66 | #endif -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtOpinionProxy/simple.usda: -------------------------------------------------------------------------------- 1 | #usda 1.0 2 | 3 | ( 4 | ) 5 | 6 | def "World" { 7 | def "VariantPrim1" (add variantSets = ["variant1", "variant2", "variant3"] 8 | variants = {string variant1 = "one" 9 | string variant2 = "three" 10 | string variant3 = "five" 11 | } 12 | ) { 13 | variantSet "variant1" = { 14 | "one"{} 15 | "two"{} 16 | } 17 | variantSet "variant2" = { 18 | "three"{} 19 | "four"{} 20 | } 21 | variantSet "variant3" = { 22 | "five"{} 23 | "six"{} 24 | } 25 | } 26 | def "VariantPrim2" (add variantSets = ["variant4", "variant2", "variant3"] 27 | variants = {string variant4 = "eight" 28 | string variant2 = "four" 29 | string variant3 = "five" 30 | } 31 | ) { 32 | variantSet "variant4" = { 33 | "seven"{} 34 | "eight"{} 35 | } 36 | variantSet "variant2" = { 37 | "three"{} 38 | "four"{} 39 | } 40 | variantSet "variant3" = { 41 | "five"{} 42 | "nine"{} 43 | "ten"{} 44 | } 45 | } 46 | 47 | def "MetadataPrim1" (doc = "sharedDoc"){} 48 | def "MetadataPrim2" (doc = "sharedDoc"){} 49 | def "MetadataPrim3" (doc = "ShaAredDOc"){} 50 | 51 | def "AttrPrim1" { 52 | int x = 5 53 | } 54 | def "AttrPrim2" { 55 | int x = 5 56 | } 57 | def "AttrPrim3" { 58 | int x = 7 59 | } 60 | def "AttrPrim4" { 61 | string x = "five" 62 | } 63 | 64 | def "Prim1" { 65 | int x 66 | int y 67 | int q 68 | rel rel1 69 | rel rel2 70 | rel relZ 71 | } 72 | def "Prim2" { 73 | int x 74 | int y 75 | int w 76 | rel rel1 77 | rel rel2 78 | rel relY 79 | } 80 | def "Prim3" { 81 | int x 82 | int y 83 | int z 84 | rel rel1 85 | rel rel2 86 | rel relX 87 | } 88 | 89 | def "TokenPrim" { 90 | token a (allowedTokens = ["five", "one", "two", "four"]) 91 | token b (allowedTokens = ["one", "two", "three"]) 92 | token c (allowedTokens = ["six", "one", "two", "three"]) 93 | } 94 | } -------------------------------------------------------------------------------- /pxr/usdQt/wrapHierarchyCache.cpp: -------------------------------------------------------------------------------- 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 | 25 | #include 26 | #include 27 | 28 | #include "pxr/pxr.h" 29 | #include "pxr/base/tf/pyPtrHelpers.h" 30 | 31 | #include "hierarchyCache.h" 32 | 33 | using namespace BOOST_NS::python; 34 | 35 | PXR_NAMESPACE_USING_DIRECTIVE 36 | 37 | TF_REFPTR_CONST_VOLATILE_GET(UsdQt_HierarchyCache::Proxy) 38 | 39 | void wrapHierarchyCache() { 40 | { 41 | typedef UsdQt_HierarchyCache This; 42 | scope obj = 43 | class_( 44 | "_HierarchyCache", init()) 45 | .def("GetChildCount", &This::GetChildCount) 46 | .def("GetChild", &This::GetChild) 47 | .def("GetRoot", &This::GetRoot) 48 | .def("IsRoot", &This::IsRoot) 49 | .def("GetParent", &This::GetParent) 50 | .def("GetRow", &This::GetRow) 51 | .def("ResyncSubtrees", &This::ResyncSubtrees) 52 | .def("ContainsPath", &This::ContainsPath) 53 | .def("GetProxy", &This::GetProxy) 54 | .def("GetPredicate", &This::GetPredicate) 55 | .def("DebugFullIndex", &This::DebugFullIndex); 56 | class_, BOOST_NS::noncopyable>("Proxy", 57 | no_init) 58 | .def(TfPyRefAndWeakPtr()) 59 | .def("GetPrim", &This::Proxy::GetPrim); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /pxr/usdQt/undoRouter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "undoRouter.h" 26 | 27 | #include "pxr/base/tf/instantiateSingleton.h" 28 | #include "pxr/base/tf/refPtr.h" 29 | 30 | #include 31 | 32 | #include "debugCodes.h" 33 | #include "undoBlock.h" 34 | #include "undoStateDelegate.h" 35 | 36 | using BOOST_NS::adaptors::slice; 37 | 38 | PXR_NAMESPACE_OPEN_SCOPE 39 | 40 | TF_REGISTRY_FUNCTION(TfType) { 41 | TfType::Define >(); 42 | } 43 | 44 | TF_INSTANTIATE_SINGLETON(UsdQtUndoRouter); 45 | 46 | namespace UsdQt { 47 | UndoStackNotice::UndoStackNotice() {} 48 | } 49 | 50 | UsdQtUndoRouter::UsdQtUndoRouter() { 51 | // TfDebug::Enable(USDQT_DEBUG_UNDOSTACK); 52 | } 53 | 54 | bool UsdQtUndoRouter::TrackLayer(const SdfLayerHandle& layer) { 55 | layer->SetStateDelegate(UsdQt_UndoStateDelegate::New()); 56 | return true; 57 | } 58 | 59 | void UsdQtUndoRouter::_AddInverse(std::function inverse) { 60 | UsdQtUndoBlock undoBlock; 61 | _inversion._Append(inverse); 62 | } 63 | 64 | UsdQtUndoRouter& UsdQtUndoRouter::Get() { 65 | return TfSingleton::GetInstance(); 66 | } 67 | 68 | bool UsdQtUndoRouter::TransferEdits(UsdQtUndoInverse* inverse){ 69 | inverse->_Adopt(Get()._inversion); 70 | Get()._inversion._Clear(); 71 | return true; 72 | } 73 | 74 | void UsdQtUndoRouter::_Mute(){ 75 | Get()._muteDepth++; 76 | } 77 | 78 | void UsdQtUndoRouter::_Unmute(){ 79 | Get()._muteDepth--; 80 | if (Get()._muteDepth < 0){ 81 | TF_CODING_ERROR("Mute depth error."); 82 | } 83 | } 84 | 85 | bool UsdQtUndoRouter::IsMuted(){ 86 | return Get()._muteDepth > 0; 87 | } 88 | 89 | PXR_NAMESPACE_CLOSE_SCOPE 90 | -------------------------------------------------------------------------------- /pxr/usdQt/undoBlock.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "undoBlock.h" 26 | 27 | #include "undoRouter.h" 28 | #include "debugCodes.h" 29 | 30 | PXR_NAMESPACE_OPEN_SCOPE 31 | 32 | void UsdQtUndoBlock::_Initialize(){ 33 | UsdQtUndoRouter& router = UsdQtUndoRouter::Get(); 34 | TF_VERIFY(router._depth >= 0); 35 | TF_DEBUG(USDQT_DEBUG_UNDOSTACK).Msg( 36 | "--Opening undo block inverse at depth '%i'.\n", router._depth); 37 | if (router._depth == 0) { 38 | if (router._inversion._GetSize() != 0) { 39 | TF_CODING_ERROR( 40 | "Opening fragmented undo block. This may be because of an undo " 41 | "command running inside of an edit block."); 42 | } 43 | } 44 | router._depth++; 45 | } 46 | 47 | UsdQtUndoBlock::UsdQtUndoBlock() { 48 | _Initialize(); 49 | } 50 | 51 | UsdQtUndoBlock::~UsdQtUndoBlock() { 52 | UsdQtUndoRouter& router = UsdQtUndoRouter::Get(); 53 | router._depth--; 54 | TF_VERIFY(router._depth >= 0); 55 | if (router._depth == 0) { 56 | if (router._inversion._GetSize() < 1) { 57 | TF_DEBUG(USDQT_DEBUG_UNDOSTACK) 58 | .Msg("Skipping sending notice for empty undo block.\n"); 59 | } else { 60 | UsdQt::UndoStackNotice().Send(); 61 | TF_DEBUG(USDQT_DEBUG_UNDOSTACK).Msg("Undo Notice Sent.\n"); 62 | if (router._inversion._GetSize() > 0){ 63 | TF_CODING_ERROR("All edits have not been adopted. Undo stack may be incomplete."); 64 | router._inversion._Clear(); 65 | } 66 | } 67 | } 68 | TF_DEBUG(USDQT_DEBUG_UNDOSTACK).Msg( 69 | "--Closed undo block inverse at depth '%i'.\n", router._depth); 70 | } 71 | 72 | PXR_NAMESPACE_CLOSE_SCOPE -------------------------------------------------------------------------------- /cmake/macros/compilePython.py: -------------------------------------------------------------------------------- 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 | # 25 | # Usage: compilePython source.py dest.pyc 26 | # 27 | # This program compiles python code, providing a reasonable 28 | # gcc-esque error message if errors occur. 29 | # 30 | # parameters: 31 | # src.py - the source file to report errors for 32 | # file.py - the installed location of the file 33 | # file.pyc - the precompiled python file 34 | 35 | import sys 36 | import py_compile 37 | 38 | if len(sys.argv) < 4: 39 | print "Usage: %s src.py file.py file.pyc" % sys.argv[0] 40 | sys.exit(1) 41 | 42 | try: 43 | py_compile.compile(sys.argv[2], sys.argv[3], sys.argv[1], doraise=True) 44 | except py_compile.PyCompileError as compileError: 45 | exc_value = compileError.exc_value 46 | if compileError.exc_type_name == SyntaxError.__name__: 47 | # py_compile.compile stashes the type name and args of the exception 48 | # in the raised PyCompileError rather than the exception itself. This 49 | # is especially annoying because the args member of some SyntaxError 50 | # instances are lacking the source information tuple, but do have a 51 | # usable lineno. 52 | error = exc_value[0] 53 | try: 54 | linenumber = exc_value[1][1] 55 | line = exc_value[1][3] 56 | print '%s:%s: %s: "%s"' % (sys.argv[1], linenumber, error, line) 57 | except IndexError: 58 | print '%s: Syntax error: "%s"' % (sys.argv[1], error) 59 | else: 60 | print "%s: Unhandled compile error: (%s) %s" % ( 61 | sys.argv[1], compileError.exc_type_name, exc_value) 62 | sys.exit(1) 63 | except: 64 | exc_type, exc_value, exc_traceback = sys.exc_info() 65 | print "%s: Unhandled exception: %s" % (sys.argv[1], exc_value) 66 | sys.exit(1) 67 | -------------------------------------------------------------------------------- /pxr/usdQt/undoInverse.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | #include "undoInverse.h" 25 | 26 | #include 27 | 28 | #include "undoBlock.h" 29 | #include "undoRouter.h" 30 | 31 | PXR_NAMESPACE_OPEN_SCOPE 32 | 33 | void UsdQtUndoInverse::_Append(std::function inverse) { 34 | _inversion.push_back(inverse); 35 | } 36 | 37 | void UsdQtUndoInverse::_Invert() { 38 | SdfChangeBlock changeBlock; 39 | for (const auto& inverse : BOOST_NS::adaptors::reverse(_inversion)) { 40 | inverse(); 41 | } 42 | } 43 | 44 | void UsdQtUndoInverse::Invert() { 45 | UsdQtUndoRouter& router = UsdQtUndoRouter::Get(); 46 | if (router._depth != 0) { 47 | TF_CODING_ERROR( 48 | "Inversion during open edit block may result in corrupted undo " 49 | "stack."); 50 | } 51 | 52 | // open up an edit change block to capture the inverse of the inversion 53 | UsdQtUndoBlock editBlock; 54 | _Invert(); 55 | _Clear(); 56 | // adopt the edits and clear the listeners inversion tracker. 57 | // when the change block is popped, no notices will be sent 58 | // TODO: Do we want a more explicit version of this that 59 | // explicitly marks that we are inverting an undo/redo as 60 | // opposed to a new edit? 61 | _Adopt(router._inversion); 62 | router._inversion._Clear(); 63 | } 64 | 65 | void UsdQtUndoInverse::_Clear() { _inversion.clear(); } 66 | 67 | void UsdQtUndoInverse::_Adopt(const UsdQtUndoInverse& inversion) { 68 | for (const auto& inverse : inversion._inversion) { 69 | _inversion.push_back(inverse); 70 | } 71 | } 72 | 73 | UsdQtUndoInverse::UsdQtUndoInverse(UsdQtUndoRouter& router) { 74 | _Adopt(router._inversion); 75 | router._inversion._Clear(); 76 | } 77 | 78 | PXR_NAMESPACE_CLOSE_SCOPE 79 | -------------------------------------------------------------------------------- /pxr/usdQt/wrapUndoRouter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include 26 | #include 27 | 28 | #include "pxr/pxr.h" 29 | #include "pxr/base/tf/makePyConstructor.h" 30 | #include "pxr/base/tf/pyPtrHelpers.h" 31 | #include "pxr/base/tf/pyNoticeWrapper.h" 32 | 33 | #include "undoBlock.h" 34 | #include "undoInverse.h" 35 | #include "undoRouter.h" 36 | 37 | using namespace BOOST_NS::python; 38 | 39 | PXR_NAMESPACE_USING_DIRECTIVE 40 | 41 | TF_INSTANTIATE_NOTICE_WRAPPER(UsdQt::UndoStackNotice, TfNotice); 42 | 43 | class UsdQt_PythonUndoBlock { 44 | public: 45 | explicit UsdQt_PythonUndoBlock() : _block(0) {} 46 | 47 | void Open() { 48 | if (!TF_VERIFY(_block == 0)) { 49 | return; 50 | } 51 | _block = new UsdQtUndoBlock(); 52 | } 53 | 54 | void Close(object, object, object) { 55 | if (!TF_VERIFY(_block != 0)) { 56 | return; 57 | } 58 | delete _block; 59 | _block = 0; 60 | } 61 | 62 | ~UsdQt_PythonUndoBlock() { delete _block; } 63 | 64 | private: 65 | UsdQtUndoBlock* _block; 66 | }; 67 | 68 | void wrapUndoRouter() { 69 | { 70 | typedef UsdQt_PythonUndoBlock This; 71 | class_("UndoBlock", init<>()) 72 | .def("__enter__", &This::Open) 73 | .def("__exit__", &This::Close); 74 | } 75 | { 76 | typedef UsdQtUndoRouter This; 77 | class_("UndoRouter", no_init) 78 | .def("TrackLayer", &This::TrackLayer) 79 | .def("TransferEdits", &This::TransferEdits) 80 | .staticmethod("TrackLayer") 81 | .staticmethod("TransferEdits"); 82 | } 83 | { 84 | typedef UsdQt::UndoStackNotice This; 85 | TfPyNoticeWrapper::Wrap(); 86 | } 87 | { 88 | typedef UsdQtUndoInverse This; 89 | class_("UndoInverse", init<>()) 90 | .def("Invert", &This::Invert); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtPrimFilterCache.py: -------------------------------------------------------------------------------- 1 | #!/pxrpythonsubst 2 | # 3 | # Copyright 2016 Pixar 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "Apache License") 6 | # with the following modification; you may not use this file except in 7 | # compliance with the Apache License and the following modification to it: 8 | # Section 6. Trademarks. is deleted and replaced with: 9 | # 10 | # 6. Trademarks. This License does not grant permission to use the trade 11 | # names, trademarks, service marks, or product names of the Licensor 12 | # and its affiliates, except as required to comply with Section 4(c) of 13 | # the License and to reproduce the content of the NOTICE file. 14 | # 15 | # You may obtain a copy of the Apache License at 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the Apache License with the above modification is 21 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 22 | # KIND, either express or implied. See the Apache License for the specific 23 | # language governing permissions and limitations under the Apache License. 24 | # 25 | 26 | from __future__ import print_function 27 | 28 | import unittest 29 | import os.path 30 | 31 | from pxr import Sdf, Usd 32 | from pxr.UsdQt._bindings import PrimFilterCache 33 | 34 | from collections import OrderedDict 35 | 36 | 37 | class TestSimplePrimFilterCache(unittest.TestCase): 38 | 39 | def setUp(self): 40 | stagePath = 'simpleFilter.usda' 41 | stagePath = stagePath if os.path.isfile(stagePath) else \ 42 | os.path.join(os.path.splitext(__file__)[0], stagePath) 43 | 44 | self.stage = Usd.Stage.Open(stagePath) 45 | self.cache = PrimFilterCache() 46 | 47 | def testSimple(self): 48 | self.cache.ApplyPathContainsFilter(self.stage.GetPrimAtPath("/World"), 49 | "Accept", Usd.PrimDefaultPredicate) 50 | 51 | pathToState = OrderedDict([ 52 | ("/World", PrimFilterCache.Accept), 53 | ("/World/Reject", PrimFilterCache.Reject), 54 | ("/World/Accept", PrimFilterCache.Accept), 55 | ("/World/AcceptParent", PrimFilterCache.Accept), 56 | ("/World/AcceptParent/RejectChild", PrimFilterCache.Reject), 57 | ("/World/AcceptParent/AcceptChild", PrimFilterCache.Accept), 58 | ("/World/IntermediateParent/RejectChild", PrimFilterCache.Reject), 59 | ("/World/IntermediateParent/AcceptChild", PrimFilterCache.Accept), 60 | ("/World/IntermediateParent/IntermediateChild", 61 | PrimFilterCache.Accept), 62 | ("/World/IntermediateParent/IntermediateChild/AcceptGrandchild", 63 | PrimFilterCache.Accept), 64 | ("/World/IntermediateParent/IntermediateChild/RejectGrandchild", 65 | PrimFilterCache.Reject) 66 | ] 67 | ) 68 | 69 | for path in pathToState: 70 | self.assertEqual(self.cache.GetState( 71 | Sdf.Path(path)), pathToState[path]) 72 | 73 | 74 | if __name__ == '__main__': 75 | unittest.main(verbosity=2) 76 | -------------------------------------------------------------------------------- /pxr/usdQt/undoInverse.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_UNDOINVERSE_H 26 | #define USDQT_UNDOINVERSE_H 27 | 28 | #include 29 | #include 30 | 31 | #include "pxr/pxr.h" 32 | #include "pxr/usd/sdf/layer.h" 33 | #include "pxr/base/tf/weakPtr.h" 34 | #include "pxr/base/tf/refPtr.h" 35 | #include "pxr/base/tf/declarePtrs.h" 36 | 37 | PXR_NAMESPACE_OPEN_SCOPE 38 | 39 | class UsdQtUndoRouter; 40 | 41 | /// \class UsdQtUndoInverse 42 | /// 43 | /// An UsdUndoInverse is a list of invertible edits to one or more SdfLayers 44 | /// which MAY span multiple stages. 45 | /// 46 | /// It may contain more than one edit. When an edit is inverted, say by an undo 47 | /// operation, it automatically converts itself into a redo operation by 48 | /// tracking edits in the UndoRouter which spawned it. 49 | /// 50 | /// This is the object you should store in your application's native undo stack. 51 | /// The implementation of undo and redo should be the same, simply calling 52 | /// inverse.Invert(). 53 | /// 54 | 55 | class UsdQtUndoInverse { 56 | private: 57 | std::string _name; 58 | std::vector> _inversion; 59 | void _Invert(); 60 | 61 | void _Append(std::function); 62 | void _Clear(); 63 | size_t _GetSize() { return _inversion.size(); } 64 | void _Adopt(const UsdQtUndoInverse& inversion); 65 | explicit UsdQtUndoInverse(UsdQtUndoRouter& router); 66 | 67 | public: 68 | UsdQtUndoInverse(){} 69 | /// \brief Apply the inverse functions. 70 | /// 71 | /// When Invert() has been called, this object now stores the Inverse of 72 | /// the Inverse. Calling Invert() twice in a row should result in the same 73 | /// state. 74 | /// 75 | /// WARNING: This is not reentrant. When Invert is called, no other threads 76 | /// may engage in edits that affect the router. If this warning is ignored, 77 | /// inverses may get incorrectly routed. 78 | void Invert(); 79 | friend class UsdQtUndoRouter; 80 | friend class UsdQtUndoBlock; 81 | }; 82 | 83 | PXR_NAMESPACE_CLOSE_SCOPE 84 | 85 | #endif -------------------------------------------------------------------------------- /pxr/usdQt/relationshipProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_RELATIONSHIPPROXY_H 26 | #define USDQT_RELATIONSHIPPROXY_H 27 | 28 | #include 29 | #include 30 | 31 | #include "pxr/pxr.h" 32 | #include "pxr/base/tf/token.h" 33 | #include "pxr/usd/usd/relationship.h" 34 | 35 | #include "metadataProxy.h" 36 | #include "objectProxy.h" 37 | 38 | PXR_NAMESPACE_OPEN_SCOPE 39 | 40 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_RelationshipProxy); 41 | 42 | /// \class UsdQt_RelationshipProxy 43 | /// \brief Proxy interface for a relationship 44 | class UsdQt_RelationshipProxy 45 | : public UsdQt_PropertyProxyBase { 46 | private: 47 | std::vector _relationships; 48 | explicit UsdQt_RelationshipProxy(const std::vector& rels); 49 | 50 | protected: 51 | virtual const std::vector& _GetObjects() const override; 52 | virtual std::vector& _GetObjects() override; 53 | 54 | public: 55 | static UsdQt_RelationshipProxyRefPtr New( 56 | const std::vector& rels); 57 | 58 | /// \brief Return the list of all relationships for this proxy. 59 | const std::vector& GetRelationships(); 60 | 61 | /// \brief Get the intersection of targets for the contained relationships 62 | /// 63 | /// Return true if all GetTargets requests are successful on the 64 | /// UsdRelationship contents. 65 | bool GetTargets(SdfPathVector* result) const; 66 | 67 | /// \brief Get the intersection of forwarded targets for the contained 68 | /// relationships 69 | /// 70 | /// Return true if all GetForwardedTargets requests are successful on the 71 | /// UsdRelationship contents. 72 | bool GetForwardedTargets(SdfPathVector* result) const; 73 | 74 | /// \brief Clear targets for all relationships on this proxy. 75 | /// 76 | /// Returns true if all UsdRelationship ClearTargets requests were 77 | /// successful. 78 | bool ClearTargets(bool removeSpec); 79 | }; 80 | 81 | PXR_NAMESPACE_CLOSE_SCOPE 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /pxr/usdQt/roles.py: -------------------------------------------------------------------------------- 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 | 25 | """ 26 | Contains UsdQt-specific Qt user roles, as well as some hint types for custom 27 | editor widgets. 28 | """ 29 | from __future__ import absolute_import 30 | 31 | from ._Qt import QtCore 32 | 33 | # The editor hint role is used to provide additional information for UI 34 | # instantiation that the value of the edit role alone may not be sufficient to 35 | # provide. For example, we may need to differentiate between a GfVec3f that 36 | # represents a 3-tuple and a GfVec3f that represents a color. 37 | # All UsdQt EditorHints are defined below and are prefixed with EditorHint. 38 | EditorHintRole = QtCore.Qt.UserRole + 2 39 | 40 | # Used to retrieve the prim object in hierarchy models. 41 | HierarchyPrimRole = QtCore.Qt.UserRole + 3 42 | 43 | # Specializations that leverage UsdQt at its core can use UsdQtUserRole as the 44 | # first safe index for additional user roles 45 | UsdQtUserRole = QtCore.Qt.UserRole + 16 46 | 47 | 48 | class EditorHintBasicValue(object): 49 | """Used for values whose editor can be inferred soley from the TfType""" 50 | __slots__ = ('__type',) 51 | 52 | def __init__(self, tfType): 53 | self.__type = tfType 54 | 55 | @property 56 | def type(self): 57 | return self.__type 58 | 59 | 60 | class EditorHintColorValue(object): 61 | """Hint for when a color editor needs to be instantiated""" 62 | __slots__ = ('__type',) 63 | 64 | def __init__(self, tfType): 65 | self.__type = tfType 66 | 67 | @property 68 | def type(self): 69 | return self.__type 70 | 71 | 72 | class EditorHintTextCombo(object): 73 | """Used for a string/token editor restricted by a list of allowed values""" 74 | __slots__ = ('__allowedValues',) 75 | 76 | def __init__(self, allowedValues): 77 | self.__allowedValues = allowedValues 78 | 79 | @property 80 | def allowedValues(self): 81 | return self.__allowedValues 82 | 83 | 84 | class EditorHintTab(object): 85 | """Used when an item should be drawn as a tab""" 86 | __slots__ = () 87 | 88 | def __init__(self): 89 | pass 90 | -------------------------------------------------------------------------------- /pxr/usdQt/icons/noarcs_2.xpm: -------------------------------------------------------------------------------- 1 | /* XPM */ 2 | static char * noarcs_2_xpm[] = { 3 | "20 20 103 2", 4 | " c None", 5 | ". c #BDBFBE", 6 | "+ c #B4B6B6", 7 | "@ c #BEBFBD", 8 | "# c #C5C5BF", 9 | "$ c #CACAC2", 10 | "% c #CDCCC5", 11 | "& c #CBCCC8", 12 | "* c #A6ABB2", 13 | "= c #6E7482", 14 | "- c #818895", 15 | "; c #868D9A", 16 | "> c #8D939F", 17 | ", c #949AA4", 18 | "' c #9CA1A8", 19 | ") c #A5A8AD", 20 | "! c #B1B4B5", 21 | "~ c #BBBDBC", 22 | "{ c #C2C3BF", 23 | "] c #CBCBC1", 24 | "^ c #CCCBC8", 25 | "/ c #A8ACB2", 26 | "( c #6D737F", 27 | "_ c #757B87", 28 | ": c #747A86", 29 | "< c #717783", 30 | "[ c #6F7581", 31 | "} c #707784", 32 | "| c #737A87", 33 | "1 c #777E8B", 34 | "2 c #7D8391", 35 | "3 c #848B98", 36 | "4 c #888E9A", 37 | "5 c #A0A5B2", 38 | "6 c #C5C4BD", 39 | "7 c #7A808C", 40 | "8 c #7B818D", 41 | "9 c #787E8A", 42 | "0 c #707682", 43 | "a c #6C727E", 44 | "b c #9EA4B2", 45 | "c c #C1C1B5", 46 | "d c #6F7683", 47 | "e c #9AA0AC", 48 | "f c #C9CABC", 49 | "g c #6E7480", 50 | "h c #9FA7B3", 51 | "i c #CFC9C5", 52 | "j c #6C7380", 53 | "k c #9BA1AF", 54 | "l c #BFC0B6", 55 | "m c #777D89", 56 | "n c #6F757F", 57 | "o c #707680", 58 | "p c #B8BBC0", 59 | "q c #777E89", 60 | "r c #C1C4C7", 61 | "s c #90959E", 62 | "t c #B5B8BD", 63 | "u c #A0A4AC", 64 | "v c #CFCFCF", 65 | "w c #8D929B", 66 | "x c #B9BCC1", 67 | "y c #737985", 68 | "z c #A8ACB0", 69 | "A c #C3C5C9", 70 | "B c #B1B5BB", 71 | "C c #7B8293", 72 | "D c #AEB2B1", 73 | "E c #707782", 74 | "F c #7C828E", 75 | "G c #7F8697", 76 | "H c #ABADAB", 77 | "I c #7D8495", 78 | "J c #ADB1AE", 79 | "K c #A7ABAF", 80 | "L c #AEB0AF", 81 | "M c #ACAFB4", 82 | "N c #717887", 83 | "O c #C0C1BB", 84 | "P c #B6B9BA", 85 | "Q c #AEB1B4", 86 | "R c #A2A6AC", 87 | "S c #989CA4", 88 | "T c #9096A0", 89 | "U c #898F9B", 90 | "V c #7A8190", 91 | "W c #7E8596", 92 | "X c #ACAEAC", 93 | "Y c #CECEC6", 94 | "Z c #C8C8C2", 95 | "` c #C0C1BD", 96 | " . c #B9BBBA", 97 | ".. c #B0B3B6", 98 | "+. c #A3A7AD", 99 | "@. c #999DA5", 100 | "#. c #9399A3", 101 | "$. c #838A97", 102 | "%. c #767F92", 103 | "&. c #ABADAC", 104 | "*. c #BABCBA", 105 | "=. c #B0B4BC", 106 | "-. c #B6B7B5", 107 | " . + @ # $ % & ", 108 | " * = - ; > , ' ) ! ~ { ] ^ ", 109 | " / ( _ : < [ } | 1 2 3 4 5 6 ", 110 | " / [ 7 7 8 7 7 7 7 9 _ 0 a b c ", 111 | " / [ 7 7 7 7 8 7 8 7 8 8 9 d e f ", 112 | " / [ 7 7 8 8 8 8 7 8 7 8 8 9 g h i ", 113 | " / 0 7 8 7 8 8 7 7 8 8 7 8 8 7 j k l ", 114 | " / [ 7 7 8 8 m n o 0 8 8 7 8 8 9 0 p ", 115 | " / [ 7 7 7 m q / r s 0 8 8 7 8 7 : t ", 116 | " / [ 7 7 7 n u v v v w 0 7 8 7 7 : x ", 117 | " / 0 7 8 7 n / v v v / n 7 7 8 9 y x ", 118 | " z 0 7 7 7 0 w v v v u n 7 8 7 7 y x ", 119 | " z 0 7 8 7 8 o s A B 9 _ 8 8 7 7 C D ", 120 | " z } 7 7 8 8 8 0 E E _ F 8 7 8 7 G H ", 121 | " / } 7 8 7 8 7 8 7 7 8 8 7 8 7 7 I J ", 122 | " K [ 7 7 8 7 8 7 7 7 8 7 8 7 8 7 C L ", 123 | " M N } [ [ 0 : _ 7 7 7 8 7 7 7 7 I J ", 124 | " O P Q R S T U - V | [ [ 0 y m m W X ", 125 | " v Y % Z ` ...+.@.#.U $.V %.&. ", 126 | " v Y $ Z # *.=.-. "}; 127 | -------------------------------------------------------------------------------- /pxr/usdQt/icons/arcs_2.xpm: -------------------------------------------------------------------------------- 1 | /* XPM */ 2 | static char * arcs_2_xpm[] = { 3 | "20 20 131 2", 4 | " c None", 5 | ". c #D0DAD4", 6 | "+ c #C2D6D5", 7 | "@ c #D5DDCB", 8 | "# c #EAECC6", 9 | "$ c #FAF9C2", 10 | "% c #E8ECD6", 11 | "& c #99B1ED", 12 | "* c #2C61E8", 13 | "= c #4E7AEA", 14 | "- c #5D85EB", 15 | "; c #6A8EEA", 16 | "> c #7B9AE9", 17 | ", c #8CA7E4", 18 | "' c #A3BADD", 19 | ") c #BDCCD7", 20 | "! c #F9FBBD", 21 | "~ c #EAE8D6", 22 | "{ c #A3B8E3", 23 | "] c #3063D6", 24 | "^ c #406ED6", 25 | "/ c #3E6CD6", 26 | "( c #3667D6", 27 | "_ c #3465D6", 28 | ": c #3468DE", 29 | "< c #2D60E1", 30 | "[ c #4475E6", 31 | "} c #5982EB", 32 | "| c #83A6FF", 33 | "1 c #F5ECB9", 34 | "2 c #4B77D9", 35 | "3 c #4E78D8", 36 | "4 c #3E6DD8", 37 | "5 c #6388DB", 38 | "6 c #3162D3", 39 | "7 c #295FDB", 40 | "8 c #81A5FF", 41 | "9 c #F8FBA9", 42 | "0 c #4471D8", 43 | "a c #AFC3EB", 44 | "b c #E6E6E6", 45 | "c c #BECFEC", 46 | "d c #4974D5", 47 | "e c #F9FFB5", 48 | "f c #3565D3", 49 | "g c #7E9CE2", 50 | "h c #A6BBEA", 51 | "i c #3767D3", 52 | "j c #4873D4", 53 | "k c #2C61DA", 54 | "l c #83B5FF", 55 | "m c #FDDDC5", 56 | "n c #7B9AE1", 57 | "o c #C0CFF0", 58 | "p c #4777D7", 59 | "q c #4874D8", 60 | "r c #7D9CFF", 61 | "s c #E9EFB3", 62 | "t c #A1B7E9", 63 | "u c #4374D7", 64 | "v c #B9C9EF", 65 | "w c #A0B7E6", 66 | "x c #92ACE6", 67 | "y c #C3D1ED", 68 | "z c #6E93DE", 69 | "A c #4270DA", 70 | "B c #BAC8E8", 71 | "C c #2C5DCE", 72 | "D c #A8BDE8", 73 | "E c #8DA8E5", 74 | "F c #2050BC", 75 | "G c #527BDA", 76 | "H c #9AB1E6", 77 | "I c #3A6BDA", 78 | "J c #7B99DF", 79 | "K c #99B2E5", 80 | "L c #86A4E2", 81 | "M c #2B5BC9", 82 | "N c #BBCCF1", 83 | "O c #B9CAED", 84 | "P c #2D60D3", 85 | "Q c #A6BADE", 86 | "R c #275ACD", 87 | "S c #7596E1", 88 | "T c #B9CAEB", 89 | "U c #3E6DF2", 90 | "V c #BED0CC", 91 | "W c #275BD1", 92 | "X c #C9D6EF", 93 | "Y c #7F9EE3", 94 | "Z c #3C68F8", 95 | "` c #B6CCB8", 96 | " . c #3467DA", 97 | ".. c #BECEEE", 98 | "+. c #3869F4", 99 | "@. c #BCCCC1", 100 | "#. c #89A7E3", 101 | "$. c #3A6DEE", 102 | "%. c #A9BDE5", 103 | "&. c #3065EC", 104 | "*. c #396CDF", 105 | "=. c #3064DA", 106 | "-. c #2658C8", 107 | ";. c #3E69F6", 108 | ">. c #BBCFC0", 109 | ",. c #E2E6C2", 110 | "'. c #C5D3D9", 111 | "). c #B2C5DE", 112 | "!. c #9BB3DF", 113 | "~. c #7092EA", 114 | "{. c #5F87EB", 115 | "]. c #507CEC", 116 | "^. c #4573E9", 117 | "/. c #3A6DE0", 118 | "(. c #295ED7", 119 | "_. c #2A5AC6", 120 | ":. c #B7CDB9", 121 | "<. c #F8F8CA", 122 | "[. c #F4F7C3", 123 | "}. c #F1F0C7", 124 | "|. c #CDD7D1", 125 | "1. c #B7C6DD", 126 | "2. c #9FB6DF", 127 | "3. c #7398EB", 128 | "4. c #547FEC", 129 | "5. c #2B62FF", 130 | "6. c #B8CAC4", 131 | "7. c #E2E6CA", 132 | "8. c #CBD9CB", 133 | "9. c #A8BCF6", 134 | "0. c #D0D9BF", 135 | " . + @ # $ $ % ", 136 | " & * = - ; > , ' ) . @ ! ~ ", 137 | " { ] ^ / ( _ ( : < [ } - | 1 ", 138 | " { ( 2 3 3 3 4 ^ 5 / 6 / 7 8 9 ", 139 | " { ( 2 3 3 0 0 a b c 2 ^ d < 8 e ", 140 | " { ( 2 3 2 f g b b b h i 2 j k l m ", 141 | " { ( 2 2 3 f n b b b o p q 3 p k r s ", 142 | " { ( 2 3 2 q / a b b t / d 2 3 u : v ", 143 | " { ( 2 2 3 u 2 w x y z 6 3 3 2 q A B ", 144 | " { ( 2 j ( C D E F G H u 2 2 3 q ^ c ", 145 | " { I ^ j 5 J K ^ 2 6 H L M q 3 j ^ N ", 146 | " { ] 2 O b b z P 3 u G K 5 / ^ 2 ^ c ", 147 | " Q R S b b b a ^ q q / a b T 2 / U V ", 148 | " Q W z b b b X 2 u f Y b b b t _ Z ` ", 149 | " Q ./ t b b t / q f g b b b ..u +.@. ", 150 | " Q .^ / g #.q u 2 u p O b b h ( $.V ", 151 | " %.&.*.=.-.-._ u p 3 / 2 t t 3 ^ ;.>. ", 152 | " ,.'.).!.L ~.{.].^./.I (.-._._ 0 Z :. ", 153 | " b <.[.}.@ |.1.2.#.3.{.4.^.5.6. ", 154 | " b <.! ! 7.8.9.0. "}; 155 | -------------------------------------------------------------------------------- /pxr/usdQt/hooks.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Luma Pictures 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 | 25 | from __future__ import absolute_import 26 | 27 | from pxr import Sdf 28 | 29 | from ._Qt import QtWidgets 30 | 31 | if False: 32 | from typing import * 33 | from pxr import Usd 34 | 35 | 36 | class FallbackException(Exception): 37 | """Raised if a customized function fails and wants to fallback to the 38 | default implementation.""" 39 | pass 40 | 41 | 42 | class UsdQtHooks(object): 43 | """Simple aggregator for overrideable hooks within a UsdQt app. 44 | 45 | This allows for easy site-specific overrides to common operations like 46 | browsing for a reference path, etc. 47 | """ 48 | _registered = {} 49 | 50 | @classmethod 51 | def Register(cls, name, func): 52 | # type: (str, Callable) -> None 53 | """ 54 | Parameters 55 | ---------- 56 | name : str 57 | func : Callable 58 | """ 59 | cls._registered.setdefault(name, []).insert(0, func) 60 | 61 | @classmethod 62 | def Call(cls, name, *args, **kwargs): 63 | # type: (str, *Any, **Dict[str, Any]) -> Any 64 | """ 65 | Parameters 66 | ---------- 67 | name : str 68 | args : *Any 69 | kwargs : **Dict[str, Any] 70 | 71 | Returns 72 | ------- 73 | Any 74 | """ 75 | for func in cls._registered[name]: 76 | try: 77 | return func(*args, **kwargs) 78 | except FallbackException: 79 | continue 80 | 81 | 82 | def GetReferencePath(parent, stage=None): 83 | # type: (QtWidgets.QWidget, Optional[Usd.Stage]) -> str 84 | """Prompts the user for a reference path. 85 | 86 | Parameters 87 | ---------- 88 | parent : QtWidgets.QWidget 89 | stage : Optional[Usd.Stage] 90 | 91 | Returns 92 | ------- 93 | str 94 | """ 95 | name, _ = QtWidgets.QInputDialog.getText(parent, 'Add Reference', 96 | 'Enter Usd Layer Identifier:') 97 | return name 98 | 99 | 100 | def GetId(layer): 101 | # type: (Sdf.Layer) -> str 102 | """Returns the unique key used to store the original contents of a layer. 103 | This is currently used for change tracking in the outliner app. 104 | 105 | Parameters 106 | ---------- 107 | layer : Sdf.Layer 108 | 109 | Returns 110 | ------- 111 | str 112 | """ 113 | if isinstance(layer, Sdf.Layer): 114 | return layer.identifier 115 | return str(layer) 116 | 117 | 118 | UsdQtHooks.Register('GetReferencePath', GetReferencePath) 119 | UsdQtHooks.Register('GetId', GetId) 120 | -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtLayerModel.py: -------------------------------------------------------------------------------- 1 | #!/pxrpythonsubst 2 | # 3 | # Copyright 2016 Pixar 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "Apache License") 6 | # with the following modification; you may not use this file except in 7 | # compliance with the Apache License and the following modification to it: 8 | # Section 6. Trademarks. is deleted and replaced with: 9 | # 10 | # 6. Trademarks. This License does not grant permission to use the trade 11 | # names, trademarks, service marks, or product names of the Licensor 12 | # and its affiliates, except as required to comply with Section 4(c) of 13 | # the License and to reproduce the content of the NOTICE file. 14 | # 15 | # You may obtain a copy of the Apache License at 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the Apache License with the above modification is 21 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 22 | # KIND, either express or implied. See the Apache License for the specific 23 | # language governing permissions and limitations under the Apache License. 24 | # 25 | 26 | from __future__ import print_function 27 | 28 | import unittest2 as unittest 29 | import os.path 30 | 31 | import pxr.UsdQt.layerModel as layerModel 32 | from pxr import Sdf, Usd 33 | from pxr.UsdQt._Qt import QtCore 34 | 35 | stageFilePath = "simpleLayerStack.usda" 36 | stageFilePath = stageFilePath if os.path.isfile(stageFilePath) else \ 37 | os.path.join(os.path.splitext(__file__)[0], stageFilePath) 38 | 39 | 40 | class TestSimpleLayerModelBase(unittest.TestCase): 41 | 42 | def setUp(self): 43 | 44 | self.stage = Usd.Stage.Open(stageFilePath) 45 | assert(self.stage) 46 | 47 | self.model = layerModel.LayerBaseModel(self.stage) 48 | 49 | def test_basicUsage(self): 50 | layerStack = self.stage.GetLayerStack(includeSessionLayers=True) 51 | self.assertEqual(self.model.rowCount(), len(layerStack)) 52 | 53 | self.assertEqual(self.model.data(self.model.createIndex(0, 0)), 54 | 'session') 55 | for i, layer in enumerate(layerStack[1:]): 56 | self.assertEqual( 57 | os.path.splitext(os.path.split(layer.identifier)[1])[0], 58 | self.model.data(self.model.createIndex(i + 1, 0))) 59 | 60 | def test_invalidModel(self): 61 | invalidModel = layerModel.LayerBaseModel() 62 | self.assertEqual(invalidModel.rowCount(), 0) 63 | with self.assertRaises(Exception): 64 | invalidModel.data(invalidModel.createIndex(0, 0)) 65 | 66 | with self.assertRaises(Exception): 67 | invalidModel.GetLayerFromIndex(self.createIndex(0, 0)) 68 | 69 | 70 | class TestSimpleLayerStandardModel(unittest.TestCase): 71 | """ 72 | TODO: Also test uneditable and unsaveable flag masks as well. 73 | """ 74 | 75 | def setUp(self): 76 | 77 | self.stage = Usd.Stage.Open(stageFilePath) 78 | assert(self.stage) 79 | 80 | self.model = layerModel.LayerStandardModel(self.stage) 81 | 82 | def test_fileFormatFlagMask(self): 83 | layerStack = self.stage.GetLayerStack(includeSessionLayers=True) 84 | self.assertEqual(self.model.rowCount(), len(layerStack)) 85 | 86 | self.model.SetFileFormatFlagMask(Sdf.FileFormat.FindById('usdc'), 87 | ~QtCore.Qt.ItemIsEnabled) 88 | 89 | for i, layer in enumerate(layerStack): 90 | flags = self.model.flags(self.model.createIndex(i, 0)) 91 | if layer.GetFileFormat() == Sdf.FileFormat.FindById('usdc'): 92 | assert(flags & ~QtCore.Qt.ItemIsEnabled) 93 | else: 94 | assert(flags & QtCore.Qt.ItemIsEnabled) 95 | 96 | 97 | if __name__ == '__main__': 98 | unittest.main(verbosity=2) 99 | -------------------------------------------------------------------------------- /pxr/usdQt/primProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_PRIMSPROXY_H 26 | #define USDQT_PRIMSPROXY_H 27 | 28 | #include "pxr/pxr.h" 29 | #include "pxr/usd/usd/prim.h" 30 | 31 | #include "attributeProxy.h" 32 | #include "metadataProxy.h" 33 | #include "objectProxy.h" 34 | #include "relationshipProxy.h" 35 | #include "variantSetsProxy.h" 36 | 37 | PXR_NAMESPACE_OPEN_SCOPE 38 | 39 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_PrimProxy); 40 | 41 | /// \class UsdQt_PrimProxy 42 | /// \brief Proxy interface for an ordered list of prims 43 | /// 44 | /// A prim proxy can be used to as a single interface to query and edit 45 | /// data on multiple prims. 46 | /// 47 | /// When a vector of properties is returned, the order is determined 48 | /// by the first prim in the list. 49 | /// 50 | /// NOTE: Nothing about this interface enforces that the prims must be 51 | /// on the same stage. While we aren't taking advantage of this yet, 52 | /// this could be used to enable multi-stage/shot editing workflows and 53 | /// tools. 54 | class UsdQt_PrimProxy : public UsdQt_ObjectProxyBase { 55 | private: 56 | std::vector _prims; 57 | explicit UsdQt_PrimProxy(const std::vector& prims); 58 | 59 | protected: 60 | virtual const std::vector& _GetObjects() const override; 61 | virtual std::vector& _GetObjects() override; 62 | 63 | public: 64 | static UsdQt_PrimProxyRefPtr New(const std::vector& prims); 65 | 66 | /// \brief Return the name of all prims (not their paths) 67 | std::vector GetNames(); 68 | 69 | /// \brief Return the prims this proxy refers to 70 | const std::vector& GetPrims(); 71 | 72 | /// \brief Get the names of attributes that ALL prims for this proxy share 73 | std::vector GetAttributeNames(); 74 | 75 | /// \brief Create a proxy if ALL prims for this proxy have a 'name' 76 | /// attribute 77 | UsdQt_AttributeProxyRefPtr CreateAttributeProxy(const TfToken& name); 78 | 79 | /// \brief Get the names of relationships that ALL prims for this proxy 80 | /// share 81 | std::vector GetRelationshipNames(); 82 | 83 | /// \brief Create a proxy if ALL prims for this proxy have a 'name' 84 | /// relationship 85 | UsdQt_RelationshipProxyRefPtr CreateRelationshipProxy(const TfToken& name); 86 | 87 | /// \brief Check if one or more of the prims for this proxy have variant 88 | /// sets. 89 | bool HasVariantSets(); 90 | 91 | /// \brief Create a proxy if one or more prims for this proxy have variant 92 | /// sets. 93 | UsdQt_VariantSetsProxyRefPtr CreateVariantSetsProxy(); 94 | 95 | /// \brief Strip any expired prims 96 | void ClearExpired(); 97 | }; 98 | 99 | PXR_NAMESPACE_CLOSE_SCOPE 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /pxr/usdQt/icons/arcs.xpm: -------------------------------------------------------------------------------- 1 | /* XPM */ 2 | static char *[] = { 3 | /* columns rows colors chars-per-pixel */ 4 | "20 20 143 2", 5 | " c #26A2CF", 6 | ". c #32A8D4", 7 | "X c #32AAD6", 8 | "o c #38AAD3", 9 | "O c #39ADD7", 10 | "+ c #3CACD4", 11 | "@ c #3BAED9", 12 | "# c #40ADD5", 13 | "$ c #46B0D6", 14 | "% c #41B1DA", 15 | "& c #43B4DE", 16 | "* c #46B4DD", 17 | "= c #4AB2D7", 18 | "- c #4DB3D7", 19 | "; c #4EB3D7", 20 | ": c #48B3DA", 21 | "> c #4AB3D9", 22 | ", c #4AB5DD", 23 | "< c #4FB4D8", 24 | "1 c #4EB5DA", 25 | "2 c #4FB7DD", 26 | "3 c #50B4D7", 27 | "4 c #50B6DA", 28 | "5 c #51B6DB", 29 | "6 c #57B7DA", 30 | "7 c #54B8DD", 31 | "8 c #58B7DA", 32 | "9 c #5BB9DA", 33 | "0 c #5AB9DC", 34 | "q c #5FBBDB", 35 | "w c #5DBBDE", 36 | "e c #48B7E3", 37 | "r c #49B7E3", 38 | "t c #4FB8E1", 39 | "y c #49BAE9", 40 | "u c #4EBEED", 41 | "i c #56BBE2", 42 | "p c #57BCE3", 43 | "a c #62BAD9", 44 | "s c #60BBDC", 45 | "d c #63BCDB", 46 | "f c #63BCDC", 47 | "g c #64BBDA", 48 | "h c #66BEDD", 49 | "j c #68BEDD", 50 | "k c #4FC4FD", 51 | "l c #5BC2EF", 52 | "z c #59C4F4", 53 | "x c #5FC4F3", 54 | "c c #5EC5F8", 55 | "v c #6EC1DF", 56 | "b c #62C3E9", 57 | "n c #64C3EB", 58 | "m c #64C4EC", 59 | "M c #6FC8ED", 60 | "N c #60C4F6", 61 | "B c #72C9EE", 62 | "V c #75CAEE", 63 | "C c #7ACCEE", 64 | "Z c #7DCDEE", 65 | "A c #81C8E1", 66 | "S c #83CAE3", 67 | "D c #81CEEE", 68 | "F c #8DCEE4", 69 | "G c #8CD2EE", 70 | "H c #95D1E7", 71 | "J c #92D4EE", 72 | "K c #96D6EF", 73 | "L c #99D2E6", 74 | "P c #9BD4E8", 75 | "I c #9ED5E9", 76 | "U c #9DD7EE", 77 | "Y c #A0D6E9", 78 | "T c #A7D8E9", 79 | "R c #A9DAEA", 80 | "E c #AEDBEB", 81 | "W c #AFDCEC", 82 | "Q c #B4DEED", 83 | "! c #BBDFE9", 84 | "~ c #A7E0FF", 85 | "^ c #AAE6FF", 86 | "/ c #ADE6FF", 87 | "( c #AEF0FF", 88 | ") c #BAE0ED", 89 | "_ c #BFE0E9", 90 | "` c #BCE1EE", 91 | "' c #BEE3F3", 92 | "] c #D4DDCF", 93 | "[ c #D1DDD4", 94 | "{ c #D6DFD1", 95 | "} c #D6DFD5", 96 | "| c #D6E1D4", 97 | " . c #D7E2DB", 98 | ".. c #C2E1E8", 99 | "X. c #C3E4EF", 100 | "o. c #C6E2EA", 101 | "O. c #C4E3ED", 102 | "+. c #CAE6EF", 103 | "@. c #C4E5F1", 104 | "#. c #C5E6F0", 105 | "$. c #C9E7F2", 106 | "%. c #CBE8F1", 107 | "&. c #D1E7EB", 108 | "*. c #D5E7EB", 109 | "=. c #D8E7E7", 110 | "-. c #DDE8E3", 111 | ";. c #D4ECF4", 112 | ":. c #D2EDFA", 113 | ">. c #DCEDF3", 114 | ",. c #DDEFF5", 115 | "<. c #DFF1F7", 116 | "1. c #DFF1F8", 117 | "2. c #EAE9DB", 118 | "3. c #F7EDD8", 119 | "4. c #FDEDD4", 120 | "5. c #E6EBE6", 121 | "6. c #E1EBEA", 122 | "7. c #E8ECE5", 123 | "8. c #EBEFEB", 124 | "9. c #E3F3F7", 125 | "0. c #E2F3F9", 126 | "q. c #E4F3F8", 127 | "w. c #E6F4F9", 128 | "e. c #E8F4F8", 129 | "r. c #EDF7FA", 130 | "t. c #F4EFE4", 131 | "y. c #FBEDE3", 132 | "u. c #F0F0E8", 133 | "i. c #F5F2EA", 134 | "p. c #FFF6E4", 135 | "a. c #F8F3EA", 136 | "s. c #FBF5EE", 137 | "d. c #FCF6EF", 138 | "f. c #FEF7EC", 139 | "g. c #FDF8EF", 140 | "h. c #FFF5F5", 141 | "j. c #FBF9F7", 142 | "k. c #FDF9F2", 143 | "l. c #FEF8F0", 144 | "z. c #FEFAF5", 145 | "x. c #FCFBF8", 146 | "c. c gray100", 147 | "v. c None", 148 | /* pixels */ 149 | "v.8.-.u.a.l.l.x.v.v.v.v.v.v.v.v.v.v.v.v.", 150 | "v.' y M Z G U E ..=.8.u.f.j.v.v.v.v.v.v.", 151 | "v.O.> 9 8 4 1 4 t r b C Z / y.v.v.v.v.v.", 152 | "v.O.4 h j j j 0 9 A 6 = 6 & ^ 4.v.v.v.v.", 153 | "v.O.4 h j j s s ;.c.9.h 9 g r ^ p.v.v.v.", 154 | "v.O.4 h j h ; I c.c.c.$.3 h a * ( h.v.v.", 155 | "v.O.4 h h j ; P c.c.c.w.d f j d * ~ 3.v.", 156 | "v.O.4 h j h f 6 ;.c.c.@.6 g h j q t 1.v.", 157 | "v.O.4 h h j q h X.Q e.F = j j h f w >.v.", 158 | "v.O.4 h a 4 # %.W v ` q h h j f 9 9.v.", 159 | "v.O.7 9 a A L ) 9 h = ` T + f j a 9 0.v.", 160 | "v.O.> h <.c.c.F $ j q v ) A 6 9 h 9 9.v.", 161 | "v.o.O H c.c.c.;.9 f f 8 ;.c.,.h 6 x .v.", 162 | "v.o.@ F c.c.c.r.h q ; Y c.c.c.@.1 c ] v.", 163 | "v.o.2 6 @.c.c.@.6 f ; I c.c.c.q.q z } v.", 164 | "v.o.2 9 8 I R f q h q d <.c.c.$.4 l .v.", 165 | "v.+.u i , X X 1 q d j 6 h @.@.j 9 N | v.", 166 | "v.t.6.&.! T J D B n p 7 % X o 1 s c { v.", 167 | "v.v.v.v.c.z.g.s.u.5.*._ R K D V n k [ v.", 168 | "v.v.v.v.v.v.v.v.v.v.v.c.z.f.f.i.7.:.2.v." 169 | }; 170 | -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtOpinionModel.py: -------------------------------------------------------------------------------- 1 | #!/pxrpythonsubst 2 | # 3 | # Copyright 2016 Pixar 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "Apache License") 6 | # with the following modification; you may not use this file except in 7 | # compliance with the Apache License and the following modification to it: 8 | # Section 6. Trademarks. is deleted and replaced with: 9 | # 10 | # 6. Trademarks. This License does not grant permission to use the trade 11 | # names, trademarks, service marks, or product names of the Licensor 12 | # and its affiliates, except as required to comply with Section 4(c) of 13 | # the License and to reproduce the content of the NOTICE file. 14 | # 15 | # You may obtain a copy of the Apache License at 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the Apache License with the above modification is 21 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 22 | # KIND, either express or implied. See the Apache License for the specific 23 | # language governing permissions and limitations under the Apache License. 24 | # 25 | 26 | from __future__ import print_function 27 | 28 | import unittest2 as unittest 29 | import os 30 | import os.path 31 | 32 | import pxr.UsdQt.opinionModel as opinionModel 33 | from pxr import Usd 34 | from pxr.UsdQt._Qt import QtCore 35 | 36 | 37 | class TestOpinionModel(unittest.TestCase): 38 | 39 | def setUp(self): 40 | stageFilePath = "simple.usda" 41 | stageFilePath = stageFilePath if os.path.isfile(stageFilePath) else \ 42 | os.path.join(os.path.splitext(__file__)[0], stageFilePath) 43 | self.stage = Usd.Stage.Open(stageFilePath) 44 | 45 | def testProperties(self): 46 | prims = [self.stage.GetPrimAtPath(path) for path in 47 | ['/MyPrim1/Child1', '/MyPrim1/Child2', '/MyPrim1/Child3', '/MyPrim1/Child4']] 48 | 49 | model = opinionModel.OpinionStandardModel(prims) 50 | primIndex = model.index(0, 0, QtCore.QModelIndex()) 51 | proxy = model.GetProxyForIndex(primIndex) 52 | self.assertEqual(proxy.GetNames(), 53 | ['Child1', 'Child2', 'Child3', 'Child4']) 54 | self.assertEqual(model.data(primIndex), 55 | 'Child1, Child2, Child3, Child4') 56 | 57 | metadataGroupIndex = model.index(0, 0, primIndex) 58 | attributeGroupIndex = model.index(1, 0, primIndex) 59 | relationshipGroupIndex = model.index(2, 0, primIndex) 60 | 61 | self.assertGreater(model.rowCount(metadataGroupIndex), 0) 62 | self.assertEqual(model.rowCount(attributeGroupIndex), 2) 63 | self.assertEqual(model.rowCount(relationshipGroupIndex), 1) 64 | 65 | self.assertEqual(model.index(0, 0, attributeGroupIndex).data(), "x") 66 | self.assertEqual(model.index(0, 1, attributeGroupIndex).data(), "") 67 | self.assertEqual(model.index(0, 2, attributeGroupIndex).data( 68 | QtCore.Qt.DisplayRole), "") 69 | self.assertEqual(model.index(0, 2, attributeGroupIndex).data( 70 | QtCore.Qt.EditRole), None) 71 | 72 | self.assertEqual(model.index(1, 0, attributeGroupIndex).data(), "y") 73 | self.assertEqual(model.index(1, 1, attributeGroupIndex).data(), "int") 74 | self.assertEqual(model.index(1, 2, attributeGroupIndex).data( 75 | QtCore.Qt.DisplayRole), "2") 76 | self.assertEqual(model.index( 77 | 1, 2, attributeGroupIndex).data(QtCore.Qt.EditRole), 2) 78 | 79 | self.assertEqual(model.index( 80 | 0, 0, relationshipGroupIndex).data(), "rel1") 81 | 82 | def testMetadata(self): 83 | prims = [self.stage.GetPrimAtPath(path) for path in 84 | ['/MyPrim1', '/MyPrim2']] 85 | 86 | def testInvalidSetData(self): 87 | """Ensure that indices are property cleaned when a bad setData occurs. 88 | This can end up triggering a very hard to track down deferred crash 89 | where persistent indices are created and not cleaned up.""" 90 | pass 91 | 92 | 93 | if __name__ == '__main__': 94 | unittest.main(verbosity=2) 95 | -------------------------------------------------------------------------------- /pxr/usdQt/undoRouter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_UNDOADAPTERBASE_H 26 | #define USDQT_UNDOADAPTERBASE_H 27 | 28 | #include 29 | 30 | #include "pxr/pxr.h" 31 | #include "pxr/base/tf/declarePtrs.h" 32 | #include "pxr/base/tf/refPtr.h" 33 | #include "pxr/base/tf/singleton.h" 34 | #include "pxr/base/tf/weakPtr.h" 35 | #include "pxr/usd/sdf/layer.h" 36 | #include "pxr/usd/usd/stage.h" 37 | 38 | #include "undoInverse.h" 39 | 40 | PXR_NAMESPACE_OPEN_SCOPE 41 | 42 | /// \class UsdQtUndoRouter 43 | /// 44 | /// Class used to track edits to one or more SdfLayers. This is the primary 45 | /// class in UsdQt's undo adapter. The UndoRouter attaches itself to track 46 | /// edits 47 | /// to a layer by spawning a UsdQt_UndoLayerStateDelegate. It may batch 48 | /// multiple edits by attaching a UsdQtUndoBlock to it. Once the last block has 49 | /// been closed, a UsdQt::UndoStackNotice is emitted. The application's native 50 | /// undo queue system now knows it's safe to adopt the edits tracked by the 51 | /// router into a local UsdQtUndoInverse object. When undo is called, this 52 | /// object can invert all the edits it represents and transforms itself into 53 | /// a redo. 54 | /// 55 | /// The UndoRouter is the linchpin and it's important to maintain its lifetime 56 | /// as long as there is an UndoBlock, UndoInverse, or UndoLayerStateDelegate 57 | /// that is expecting to forward or receive information from it. 58 | /// 59 | /// Here is a quick breakdown of the chain of triggers. 60 | /// Usd Edit => Sdf Edit => Delegate => Router => Notice => Native Undo Listener 61 | /// 62 | /// Usage: 63 | /// # setup 64 | /// UsdQt.UndoRouter.TrackLayer(stage.GetRootLayer()) 65 | /// # usage 66 | /// prim = stage.GetPrimAtPath('/World') 67 | /// with UsdQt.UndoBlock(): 68 | /// prim.GetAttribute('hello').Set(True) 69 | /// 70 | class UsdQtUndoRouter : BOOST_NS::noncopyable { 71 | private: 72 | int _depth = 0; 73 | UsdQtUndoInverse _inversion; 74 | 75 | void _AddInverse(std::function inverse); 76 | 77 | UsdQtUndoRouter(); 78 | 79 | int _muteDepth = 0; 80 | 81 | static UsdQtUndoRouter& Get(); 82 | 83 | static void _Mute(); 84 | static void _Unmute(); 85 | public: 86 | 87 | static bool TrackLayer(const SdfLayerHandle& layer); 88 | static bool TransferEdits(UsdQtUndoInverse* inverse); 89 | static bool IsMuted(); 90 | 91 | friend class UsdQtUndoBlock; 92 | friend class UsdQtUndoInverse; 93 | friend class UsdQt_UndoStateDelegate; 94 | friend class TfSingleton; 95 | }; 96 | 97 | namespace UsdQt { 98 | 99 | /// \class UndoStackNotice 100 | /// 101 | /// When an undoable change has been made, and all open UndoBlocks have been 102 | /// freed, this notice is emitted. The listener of this notice should adopt the 103 | /// edits tracked by the router and place the edits into the application's 104 | /// native undo queue. 105 | class UndoStackNotice : public TfNotice { 106 | public: 107 | explicit UndoStackNotice(); 108 | }; 109 | } 110 | 111 | PXR_NAMESPACE_CLOSE_SCOPE 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /pxr/usdQt/relationshipProxy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "relationshipProxy.h" 26 | #include "utils.h" 27 | 28 | PXR_NAMESPACE_OPEN_SCOPE 29 | 30 | using BOOST_NS::adaptors::slice; 31 | 32 | UsdQt_RelationshipProxy::UsdQt_RelationshipProxy( 33 | const std::vector& rels) 34 | : _relationships(rels) {} 35 | 36 | UsdQt_RelationshipProxyRefPtr UsdQt_RelationshipProxy::New( 37 | const std::vector& rels) { 38 | return TfCreateRefPtr(new UsdQt_RelationshipProxy(rels)); 39 | } 40 | 41 | bool UsdQt_RelationshipProxy::GetTargets(SdfPathVector* result) const { 42 | if (!result) return false; 43 | if (_relationships.size() < 1) { 44 | result->clear(); 45 | return true; 46 | } 47 | SdfPathVector sharedTargets; 48 | if (!_relationships[0].GetTargets(&sharedTargets)) { 49 | result->clear(); 50 | return false; 51 | } 52 | 53 | auto sharedTargetsEnd = sharedTargets.end(); 54 | for (const auto& relationship : 55 | slice(_relationships, 1, _relationships.size())) { 56 | SdfPathVector targets; 57 | if (!relationship.GetTargets(&targets)) { 58 | result->clear(); 59 | return false; 60 | } 61 | sharedTargetsEnd = remove_if(sharedTargets.begin(), sharedTargetsEnd, 62 | [&](const SdfPath& target) { 63 | return UsdQt_ItemNotInVector(targets, target); 64 | }); 65 | } 66 | 67 | sharedTargets.erase(sharedTargetsEnd, sharedTargets.end()); 68 | result->assign(sharedTargets.begin(), sharedTargets.end()); 69 | return true; 70 | } 71 | 72 | bool UsdQt_RelationshipProxy::GetForwardedTargets(SdfPathVector* result) const { 73 | if (!result) return false; 74 | if (_relationships.size() < 1) { 75 | result->clear(); 76 | return true; 77 | } 78 | SdfPathVector sharedTargets; 79 | if (!_relationships[0].GetForwardedTargets(&sharedTargets)) { 80 | result->clear(); 81 | return false; 82 | } 83 | 84 | auto sharedTargetsEnd = sharedTargets.end(); 85 | for (const auto& relationship : 86 | slice(_relationships, 1, _relationships.size())) { 87 | SdfPathVector targets; 88 | if (!relationship.GetForwardedTargets(&targets)) { 89 | (*result) = SdfPathVector(); 90 | return false; 91 | } 92 | sharedTargetsEnd = remove_if(sharedTargets.begin(), sharedTargetsEnd, 93 | [&](const SdfPath& target) { 94 | return UsdQt_ItemNotInVector(targets, target); 95 | }); 96 | } 97 | 98 | sharedTargets.erase(sharedTargetsEnd, sharedTargets.end()); 99 | result->assign(sharedTargets.begin(), sharedTargets.end()); 100 | return true; 101 | } 102 | 103 | bool UsdQt_RelationshipProxy::ClearTargets(bool removeSpec) { 104 | bool success = true; 105 | for (const auto& relationship : _relationships) { 106 | success &= relationship.ClearTargets(removeSpec); 107 | } 108 | return success; 109 | } 110 | 111 | std::vector& UsdQt_RelationshipProxy::_GetObjects() { 112 | return _relationships; 113 | } 114 | const std::vector& UsdQt_RelationshipProxy::_GetObjects() 115 | const { 116 | return _relationships; 117 | } 118 | 119 | PXR_NAMESPACE_CLOSE_SCOPE 120 | -------------------------------------------------------------------------------- /pxr/usdQtEditors/treeView.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 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 | 25 | from __future__ import absolute_import 26 | from __future__ import division 27 | from __future__ import print_function 28 | 29 | import sys 30 | 31 | from pxr import Sdf 32 | 33 | from ._Qt import QtCore, QtWidgets 34 | 35 | if False: 36 | from typing import * 37 | 38 | 39 | class TreeView(QtWidgets.QTreeView): 40 | """Specialization of QTreeView to add selection edit based functionality. 41 | 42 | Selection edits allow editing of all selected attriutes simultaneously. 43 | 44 | This class should be as sparse as possible. In general, all models and 45 | functionality should work with QTreeView natively. 46 | 47 | This exists because commitData seems like the best place for selection 48 | based overrides. Neither the delegate nor the model have access to the 49 | selection model. To avoid breaking encapsulation, we use this wrapper 50 | class instead. 51 | """ 52 | SelectedEditOff = 0 53 | SelectedEditColumnsOnly = 1 54 | 55 | def __init__(self, parent=None): 56 | """ 57 | Parameters 58 | ---------- 59 | parent : Optional[QtWidgets.QWidget] 60 | """ 61 | super(TreeView, self).__init__(parent) 62 | self._selectionEditMode = TreeView.SelectedEditColumnsOnly 63 | 64 | def SetSelectedEditMode(self, mode): 65 | self._selectionEditMode = mode 66 | 67 | def commitData(self, editor): 68 | """overriden to support multiple selected index edits""" 69 | 70 | # TODO: Add an UndoBlock 71 | if self.indexWidget(self.currentIndex()) == editor: 72 | editorIndex = self.currentIndex() 73 | else: 74 | editorIndex = None 75 | 76 | if not editorIndex: 77 | super(TreeView, self).commitData(editor) 78 | return 79 | 80 | if self._selectionEditMode == TreeView.SelectedEditColumnsOnly: 81 | selection = [i for i in self.selectionModel().selectedIndexes() 82 | if i.column() == editorIndex.column() 83 | and i != editorIndex] 84 | else: 85 | selection = None 86 | 87 | # It's important to put all edits inside of an Sdf Change Block so 88 | # they happen in a single pass and no signals are emitted that may 89 | # change state 90 | with Sdf.ChangeBlock(): 91 | super(TreeView, self).commitData(editor) 92 | if selection: 93 | value = editor.value 94 | for index in selection: 95 | # This try / except is covering for a very ugly and hard 96 | # to isolate bug. It appears that when commitData 97 | # raises an exception, Qt holds onto some indices that 98 | # should safely expire, trigging a deferred but hard 99 | # crash. I haven't found a reliable repro case, but 100 | # this seems to make it go away. A better solution 101 | # likely involves better detection on the model side. 102 | try: 103 | self.model().setData(index, value, QtCore.Qt.EditRole) 104 | except Exception, e: 105 | # TODO: We should do something better than printing to 106 | # stderr 107 | print("Exception during multi-edit:", e, 108 | file=sys.stderr) 109 | -------------------------------------------------------------------------------- /pxr/usdQt/stageCacheModel.py: -------------------------------------------------------------------------------- 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 | 25 | from __future__ import absolute_import 26 | from __future__ import division 27 | from __future__ import print_function 28 | 29 | from ._Qt import QtCore 30 | 31 | if False: 32 | from typing import * 33 | from pxr import Usd 34 | 35 | 36 | class StageCacheModel(QtCore.QAbstractTableModel): 37 | """A stage cache model exposes the stages a cache is holding to Qt. 38 | 39 | The stage cache model by default exposes the root layer in column 0 and 40 | the session layer in column 1. Even though this is an abstract table model, 41 | this code often will be paired with a QListItemView to selection a stage 42 | from a stage cache to edit. 43 | 44 | Currently, this isn't very efficient as it makes repeated queries to 45 | GetAllStages. There are rarely all that many stages open so this shouldn't 46 | be problmatic, but we should reevaluate the implementation. 47 | 48 | Storing the cache membership directly doesn't work, as this can 49 | change over time. However, if stage cache membership changes were backed 50 | by an UsdNotice, we could know when to flush and update our own internal 51 | cache membership list. 52 | """ 53 | def __init__(self, stageCache, parent=None): 54 | # type: (Usd.StageCache, Optional[QtCore.QObject]) -> None 55 | """ 56 | Parameters 57 | ---------- 58 | stageCache : Usd.StageCache 59 | parent : Optional[QtCore.QObject] 60 | """ 61 | super(StageCacheModel, self).__init__(parent=parent) 62 | self._stageCache = stageCache 63 | 64 | def rowCount(self, parent=QtCore.QModelIndex()): 65 | return len(self._stageCache.GetAllStages()) 66 | 67 | def columnCount(self, parent=QtCore.QModelIndex()): 68 | return 2 69 | 70 | def data(self, index, role=QtCore.Qt.DisplayRole): 71 | if not index.isValid(): 72 | return None 73 | 74 | if role == QtCore.Qt.DisplayRole: 75 | if index.column() == 0: 76 | return self._stageCache.GetAllStages()[index.row()].GetRootLayer().identifier 77 | elif index.column() == 1: 78 | return self._stageCache.GetAllStages()[index.row()].GetSessionLayer().identifier 79 | # return super(StageCacheModel, self).data(index, role) 80 | 81 | def GetStageForIndex(self, index): 82 | # type: (QtCore.QModelIndex) -> Usd.Stage 83 | """Retrieve the UsdStage associated with the row of index 84 | 85 | Parameters 86 | ---------- 87 | index : QtCore.QModelIndex 88 | 89 | Returns 90 | ------- 91 | Usd.Stage 92 | """ 93 | return self._stageCache.GetAllStages()[index.row()] 94 | 95 | 96 | if __name__ == '__main__': 97 | """ 98 | Sample usage 99 | """ 100 | import os 101 | from pxr import Usd, UsdUtils 102 | from ._Qt import QtWidgets 103 | import sys 104 | app = QtWidgets.QApplication([]) 105 | 106 | stageCache = UsdUtils.StageCache.Get() 107 | dir = os.path.split(__file__)[0] 108 | path = os.path.join( 109 | dir, 'testenv', 'testUsdQtOpinionModel', 'simple.usda') 110 | with Usd.StageCacheContext(stageCache): 111 | stage1 = Usd.Stage.CreateInMemory() 112 | stage2 = Usd.Stage.Open(path) 113 | stage3 = Usd.Stage.CreateInMemory() 114 | 115 | comboBox = QtWidgets.QComboBox() 116 | model = StageCacheModel(stageCache) 117 | comboBox.setModel(model) 118 | comboBox.show() 119 | 120 | sys.exit(app.exec_()) 121 | -------------------------------------------------------------------------------- /pxr/usdQt/compatability.py: -------------------------------------------------------------------------------- 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 | 25 | """ 26 | UsdQt is currently architected to work with PySide2's API. This module is used 27 | to provide compatability with other Qt APIs. 28 | 29 | If you need to add a function here, try to document the reason it is being 30 | added, and if there is any known path to deprecating it. 31 | """ 32 | from __future__ import absolute_import 33 | 34 | from ._Qt import QtCore 35 | 36 | if False: 37 | from typing import * 38 | from ._Qt import QtGui, QtWidgets 39 | 40 | 41 | QT_VERSION_STR = QtCore.qVersion() 42 | QT_VERSION_PARTS = map(int, QT_VERSION_STR.split('.')) 43 | QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_RELEASE = QT_VERSION_PARTS 44 | 45 | 46 | def StyledItemDelegateSetEditorData(cls, delegate, editor, index): 47 | # type: (Type[QtWidgets.QStyledItemDelegate], QtWidgets.QStyledItemDelegate, QtWidgets.QWidget, QtCore.QModelIndex) -> Any 48 | """PySide appears to force types that can behave as lists 49 | (ie. GfMatrix*, GfVec*) to be converted to lists when accessed via 50 | index.data(). Interestingly, model.data() in Pyside doesn't do this 51 | so there's a simple work around. 52 | 53 | Parameters 54 | ---------- 55 | cls : Type[QtWidgets.QStyledItemDelegate] 56 | Unused 57 | delegate : QtWidgets.QStyledItemDelegate 58 | Unused 59 | editor : QtWidgets.QWidget 60 | index : QtCore.QModelIndex 61 | """ 62 | data = index.data(QtCore.Qt.EditRole) 63 | setattr(editor, editor.metaObject().userProperty().name(), data) 64 | 65 | 66 | def StyledItemDelegateSetModelData(cls, delegate, editor, model, index): 67 | # type: (Type[QtWidgets.QStyledItemDelegate], QtWidgets.QStyledItemDelegate, QtWidgets.QWidget, QtCore.QAbstractItemModel, QtCore.QModelIndex) -> Any 68 | """PySide appears to force types that can behave as lists 69 | (ie. GfMatrix*, GfVec*) to be converted to lists when accessed via 70 | index.data(). Interestingly, model.data() in Pyside doesn't do this, 71 | so there's a simple work around. 72 | 73 | Parameters 74 | ---------- 75 | cls : Type[QtWidgets.QStyledItemDelegate] 76 | Unused 77 | delegate : QtWidgets.QStyledItemDelegate 78 | Unused 79 | editor : QtWidgets.QWidget 80 | model : QtCore.QAbstractItemModel 81 | index : QtCore.QModelIndex 82 | """ 83 | value = getattr(editor, str(editor.metaObject().userProperty().name())) 84 | model.setData(index, value, role=QtCore.Qt.EditRole) 85 | 86 | 87 | def HeaderViewSetResizeMode(header, mode): 88 | # type: (QtGui.QHeaderView, QtGui.QHeaderView.ResizeMode) -> Any 89 | """This method appears to have been renamed in Qt 5. For backwards, 90 | compatability with Qt4. 91 | 92 | Parameters 93 | ---------- 94 | header : QtGui.QHeaderView 95 | mode : QtGui.QHeaderView.ResizeMode 96 | """ 97 | if QT_VERSION_MAJOR == 4: 98 | header.setResizeMode(mode) 99 | elif QT_VERSION_MAJOR == 5: 100 | header.setSectionResizeMode(mode) 101 | 102 | 103 | def EmitDataChanged(model, topLeft, bottomRight): 104 | # type: (QtCore.QAbstractItemModel, QtCore.QModelIndex, QtCore.QModelIndex) -> Any 105 | """The data changed API has changed between Qt4 and Qt5. 106 | 107 | Parameters 108 | ---------- 109 | model : QtCore.QAbstractItemModel 110 | topLeft : QtCore.QModelIndex 111 | bottomRight : QtCore.QModelIndex 112 | """ 113 | if QT_VERSION_MAJOR == 4: 114 | model.dataChanged.emit(topLeft, bottomRight) 115 | elif QT_VERSION_MAJOR == 5: 116 | model.dataChanged.emit(topLeft, bottomRight, []) 117 | -------------------------------------------------------------------------------- /pxr/usdQt/icons/noarcs.xpm: -------------------------------------------------------------------------------- 1 | /* XPM */ 2 | static char *[] = { 3 | /* columns rows colors chars-per-pixel */ 4 | "20 20 178 2", 5 | " c #43B4DE", 6 | ". c #46B4DE", 7 | "X c #47B4DF", 8 | "o c #4EB3D7", 9 | "O c #4AB3D9", 10 | "+ c #4FB5DA", 11 | "@ c #4FB5DB", 12 | "# c #4FB6DA", 13 | "$ c #4FB6DB", 14 | "% c #4DB5DC", 15 | "& c #4CB6DD", 16 | "* c #4DB6DD", 17 | "= c #4DB7DE", 18 | "- c #4EB5DC", 19 | "; c #4FB7DD", 20 | ": c #4DB8DF", 21 | "> c #50B4D7", 22 | ", c #53B5D6", 23 | "< c #50B4D8", 24 | "1 c #51B5D9", 25 | "2 c #50B5DB", 26 | "3 c #51B5DB", 27 | "4 c #52B5D8", 28 | "5 c #52B5D9", 29 | "6 c #52B5DA", 30 | "7 c #53B6D9", 31 | "8 c #50B6DC", 32 | "9 c #50B7DC", 33 | "0 c #50B7DD", 34 | "q c #54B6D8", 35 | "w c #54B6DA", 36 | "e c #56B7D8", 37 | "r c #56B7DB", 38 | "t c #57B8DB", 39 | "y c #58B7D9", 40 | "u c #58B8DB", 41 | "i c #59B9DA", 42 | "p c #5AB8DB", 43 | "a c #5ABADC", 44 | "s c #5CBADB", 45 | "d c #5DBADB", 46 | "f c #5EBADB", 47 | "g c #5EBBDC", 48 | "h c #5FBADC", 49 | "j c #5FBBDC", 50 | "k c #44B7E5", 51 | "l c #48B7E3", 52 | "z c #48BBEA", 53 | "x c #51B9E0", 54 | "c c #52B9E1", 55 | "v c #54BBE1", 56 | "b c #5ABEE5", 57 | "n c #62BBDB", 58 | "m c #60BBDC", 59 | "M c #62BCDA", 60 | "N c #61BCDC", 61 | "B c #63BDDD", 62 | "V c #64BCDA", 63 | "C c #65BCDB", 64 | "Z c #66BDDB", 65 | "A c #64BDDD", 66 | "S c #65BDDC", 67 | "D c #65BDDD", 68 | "F c #66BEDD", 69 | "G c #67BEDD", 70 | "H c #67BEDE", 71 | "J c #68BEDD", 72 | "K c #68BFDD", 73 | "L c #68BEDE", 74 | "P c #68BFDE", 75 | "I c #6BBFDE", 76 | "U c #4AC2FB", 77 | "Y c #5CC2EE", 78 | "T c #5CC2F2", 79 | "R c #5DC3F5", 80 | "E c #5EC5F4", 81 | "W c #5CC4F8", 82 | "Q c #5FC6F9", 83 | "! c #6BC0DE", 84 | "~ c #60C1E8", 85 | "^ c #60C2EB", 86 | "/ c #65C3E8", 87 | "( c #6CC6EB", 88 | ") c #6EC7EB", 89 | "_ c #70C8EB", 90 | "` c #73C9EB", 91 | "' c #78CBEC", 92 | "] c #7ACCEC", 93 | "[ c #7CCCEB", 94 | "{ c #80CDEA", 95 | "} c #87CFEC", 96 | "| c #88CCE1", 97 | " . c #8BCDE2", 98 | ".. c #8ECEE4", 99 | "X. c #8DD1EB", 100 | "o. c #92CFE3", 101 | "O. c #91D3EC", 102 | "+. c #97D4EB", 103 | "@. c #9ED6E8", 104 | "#. c #9ADCF7", 105 | "$. c #9DDBFB", 106 | "%. c #9EE0FF", 107 | "&. c #A2D7E8", 108 | "*. c #A8D8E7", 109 | "=. c #B5DCE7", 110 | "-. c #B0DCEA", 111 | ";. c #B0DDEB", 112 | ":. c #BADDE6", 113 | ">. c #BDDDE5", 114 | ",. c #A3E0FE", 115 | "<. c #A2EAFF", 116 | "1. c #BDE2EE", 117 | "2. c #BFE2ED", 118 | "3. c #B8E2F0", 119 | "4. c #CDDBD1", 120 | "5. c #D0DBCC", 121 | "6. c #D2DDCE", 122 | "7. c #D2DDD2", 123 | "8. c #D2DFD1", 124 | "9. c #C0DFE6", 125 | "0. c #D4E1D6", 126 | "q. c #D2E0D8", 127 | "w. c #C1E0E7", 128 | "e. c #C1E0E8", 129 | "r. c #C1E1E9", 130 | "t. c #C1E1EA", 131 | "y. c #C0E2EB", 132 | "u. c #C1E2EA", 133 | "i. c #C1E2EB", 134 | "p. c #C3E0E8", 135 | "a. c #C0E2EC", 136 | "s. c #C0E3ED", 137 | "d. c #C5E3EC", 138 | "f. c #CCE4E9", 139 | "g. c #CFEAF2", 140 | "h. c #CCEAF6", 141 | "j. c #D4E5E4", 142 | "k. c #D2E6E8", 143 | "l. c #D8E5E0", 144 | "z. c #DCE9E7", 145 | "x. c #D9ECF1", 146 | "c. c #DAEFF6", 147 | "v. c #DEF0F5", 148 | "b. c #DFF0F4", 149 | "n. c #E7E7DB", 150 | "m. c #F6ECD7", 151 | "M. c #FBECD3", 152 | "N. c #E2E9E4", 153 | "B. c #E5EAE3", 154 | "V. c #E5EBE6", 155 | "C. c #EEEEE7", 156 | "Z. c #E8EEEA", 157 | "A. c #E0F3F8", 158 | "S. c #EBF6F8", 159 | "D. c #F2EEE3", 160 | "F. c #F0EFE7", 161 | "G. c #F9ECE2", 162 | "H. c #F2F0E9", 163 | "J. c #F3F1E9", 164 | "K. c #F6F2E9", 165 | "L. c #FFF6E3", 166 | "P. c #F9F4ED", 167 | "I. c #FBF5EE", 168 | "U. c #FDF6EB", 169 | "Y. c #FCF7EE", 170 | "T. c #FDF7EF", 171 | "R. c #F0F8FA", 172 | "E. c #FFF5F5", 173 | "W. c #FBF9F7", 174 | "Q. c #FDF8F0", 175 | "!. c #FDF8F2", 176 | "~. c #FEFAF5", 177 | "^. c #FEFBF7", 178 | "/. c #FCFBF8", 179 | "(. c #FFFEFE", 180 | "). c #FFFFFE", 181 | "_. c gray100", 182 | "`. c None", 183 | /* pixels */ 184 | "`.Z.l.C.K.Y.!./.`.`.`.`.`.`.`.`.`.`.`.`.", 185 | "`.3.k ( ' } +.*.>.j.V.H.U.W.`.`.`.`.`.`.", 186 | "`.2.O d p w + 0 c b / ` ] ,.G.`.`.`.`.`.", 187 | "`.a.+ F F J F F F F N d 2 %.M.`.`.`.`.", 188 | "`.y.+ F F F F J F J F J J C l #.L.`.`.`.", 189 | "`.a.+ F F J J J J F J F J J C X <.E.`.`.", 190 | "`.y.2 F J F J J F F J J F J J F . $.m.`.", 191 | "`.y.+ F F J J m o , 2 J J F J J n : c.`.", 192 | "`.y.+ F F F j M a.S.o.2 J J F J F a x.`.", 193 | "`.y.+ F F F o -._._._. .2 F J F F p v.`.", 194 | "`.y.2 F J F o 2._._._.2.o F F J N y v.`.", 195 | "`.w.2 F F F 2 ._._._.-.o F J F F t v.`.", 196 | "`.w.2 F J F J , o.R.g.C d J J F F T q.`.", 197 | "`.w.0 F F J J J 2 q q d ! J F J F Q 5.`.", 198 | "`.y.0 F J F J F J F F J J F J F F E 8.`.", 199 | "`.9.& F F J F J F F F J F J F J F T 7.`.", 200 | "`.d.z 0 & & 2 p d F F F J F F F F R 8.`.", 201 | "`.D.z.f.=.@.X.[ ( ~ v & + 2 r j j W 6.`.", 202 | "`.`.`.`._.~.!.P.F.N.k.:.&.O.{ _ Y U 4.`.", 203 | "`.`.`.`.`.`.`.`.`.`.`._.~.Y.P.K.B.h.n.`." 204 | }; 205 | -------------------------------------------------------------------------------- /pxr/usdQt/usdUtils.py: -------------------------------------------------------------------------------- 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 | 25 | from __future__ import absolute_import 26 | 27 | from pxr import Pcp, Sdf 28 | 29 | if False: 30 | from typing import * 31 | from pxr import Usd 32 | 33 | 34 | def SpecifierToString(specifier): 35 | # type: (Sdf.Specifier) -> str 36 | """ 37 | Parameters 38 | ---------- 39 | specifier : Sdf.Specifier 40 | 41 | Returns 42 | ------- 43 | str 44 | """ 45 | if specifier is Sdf.SpecifierDef: 46 | return "def" 47 | elif specifier is Sdf.SpecifierOver: 48 | return "over" 49 | elif specifier is Sdf.SpecifierClass: 50 | return "class" 51 | else: 52 | raise Exception("Unknown specifier.") 53 | 54 | 55 | class EditTargetContext(object): 56 | """A context manager that changes a stage's edit target on entry, and then 57 | returns it to its previous value on exit. 58 | """ 59 | __slots__ = ('stage', 'target', 'originalEditTarget') 60 | 61 | def __init__(self, stage, target): 62 | # type: (Usd.Stage, Sdf.Layer) -> None 63 | """ 64 | Parameters 65 | ---------- 66 | stage : Usd.Stage 67 | target : Sdf.Layer 68 | """ 69 | self.stage = stage 70 | self.target = target 71 | self.originalEditTarget = None 72 | 73 | def __enter__(self): 74 | self.originalEditTarget = self.stage.GetEditTarget() 75 | self.stage.SetEditTarget(self.target) 76 | 77 | def __exit__(self, exc_type, exc_val, exc_tb): 78 | self.stage.SetEditTarget(self.originalEditTarget) 79 | 80 | 81 | def GetPrimVariants(prim): 82 | # type: (Usd.Prim) -> List[Tuple[str, str]] 83 | """Returns a list of tuples representing a prim's variant set names and 84 | active values. 85 | 86 | The results are ordered "depth-first" by variant opinion strength in the 87 | prim's index. 88 | 89 | Parameters 90 | ---------- 91 | prim : Usd.Prim 92 | 93 | Returns 94 | ------- 95 | List[Tuple[str, str]] 96 | (variantSetName, variantName) pairs 97 | """ 98 | # FIXME: We might need a strategy for duplicate variant sets that are nested 99 | # under different variant hierarchies. These aren't very practical though, 100 | # since the selection on the composed stage is the same. 101 | 102 | def walkVariantNodes(node): 103 | if node.arcType == Pcp.ArcTypeVariant and not node.IsDueToAncestor(): 104 | yield node.path.GetVariantSelection() 105 | 106 | for childNode in node.children: 107 | for childSelection in walkVariantNodes(childNode): 108 | yield childSelection 109 | 110 | results = [] 111 | primIndex = prim.GetPrimIndex() 112 | setNames = set(prim.GetVariantSets().GetNames()) 113 | for variantSetName, variantSetValue in walkVariantNodes(primIndex.rootNode): 114 | try: 115 | setNames.remove(variantSetName) 116 | except KeyError: 117 | pass 118 | else: 119 | results.append((variantSetName, variantSetValue)) 120 | 121 | # If a variant is not selected, it won't be included in the prim index, so 122 | # we need a way to get those variants. `Prim.ComputeExpandedPrimIndex()` 123 | # seems unstable and slow so far. We can easily get variant names using the 124 | # main API methods. The problem is they are not ordered hierarchically... 125 | # Variants with no selection hide subsequent variants so missing ones are 126 | # usually top level variants. 127 | for setName in setNames: 128 | setValue = prim.GetVariantSet(setName).GetVariantSelection() 129 | results.append((setName, setValue)) 130 | 131 | return results 132 | -------------------------------------------------------------------------------- /pxr/usdQt/attributeProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_ATTRIBUTEPROXY_H 26 | #define USDQT_ATTRIBUTEPROXY_H 27 | 28 | #include 29 | #include 30 | 31 | #include "pxr/pxr.h" 32 | #include "pxr/base/tf/token.h" 33 | #include "pxr/usd/usd/attribute.h" 34 | 35 | #include "metadataProxy.h" 36 | #include "objectProxy.h" 37 | 38 | PXR_NAMESPACE_OPEN_SCOPE 39 | 40 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_AttributeProxy); 41 | 42 | /// \class UsdQt_AttributeProxy 43 | /// \brief Proxy interface for an ordered list of attributes 44 | /// 45 | /// An attribute proxy can be used to as a single interface to query and edit 46 | /// data on multiple attributes across disparate prims. 47 | /// 48 | /// As much as possible, we try to make the API method names, parameters, 49 | /// and return types match UsdAttribute for duck typing in python. Code 50 | /// that one wrote to operate on an Attribute should whenever possible also 51 | /// work on an attribute proxy. 52 | class UsdQt_AttributeProxy 53 | : public UsdQt_PropertyProxyBase { 54 | private: 55 | std::vector _attributes; 56 | explicit UsdQt_AttributeProxy(const std::vector& attributes); 57 | 58 | protected: 59 | virtual const std::vector& _GetObjects() const override; 60 | virtual std::vector& _GetObjects() override; 61 | 62 | public: 63 | static UsdQt_AttributeProxyRefPtr New( 64 | const std::vector& attributes); 65 | 66 | /// \brief Get the variability that all attributes for this proxy share 67 | /// 68 | /// If variability for all attributes is not equal, then 69 | /// SdfVariabilityUniform is returned as a fallback. 70 | SdfVariability GetVariability() const; 71 | 72 | /// \brief Get the value type name that all attributes for this proxy share 73 | /// 74 | /// If the typeName for all attributes is not equal, an empty 75 | /// SdfValueTypeName is returned. 76 | SdfValueTypeName GetTypeName() const; 77 | 78 | /// \brief Return the list of all attributes for this proxy. 79 | const std::vector& GetAttributes() { return _attributes; } 80 | 81 | /// \brief Get the shared value that all attributes for this proxy share 82 | /// 83 | /// If the value for all attributes is not equal, an empty VtValue is 84 | /// stored in 'result'. 85 | /// 86 | /// Returns true all UsdAttribute Get requests were successful. 87 | bool Get(VtValue* result, UsdTimeCode timeCode) const; 88 | 89 | /// \brief Set a value on all attributes for this proxy. 90 | /// 91 | /// Returns true if all UsdAttribute Set requests were successful. 92 | bool Set(const VtValue& value, UsdTimeCode timeCode); 93 | 94 | /// \brief Clear time samples and defaults on all attributes for this proxy. 95 | /// 96 | /// Returns true if all UsdAttribute Clear requests were successful. 97 | bool Clear(); 98 | 99 | /// \brief Clear value at time code on all attributes for this proxy. 100 | /// 101 | /// Returns true if all UsdAttribute ClearAtTime requests were successful. 102 | bool ClearAtTime(UsdTimeCode time); 103 | 104 | /// \brief Authors a block on all attriutes for this proxy. 105 | /// 106 | /// NOTE: BlockValue doesn't return a bool only because UsdAttribute Block 107 | /// doesn't return a bool. If this changes, this should be updated in kind. 108 | void Block(); 109 | 110 | /// \brief Get the intersection of allowedTokens for all attributes of this 111 | /// proxy. 112 | /// 113 | /// This is only valid for attributes with valueType 'token' 114 | VtTokenArray GetAllowedTokens() const; 115 | }; 116 | 117 | PXR_NAMESPACE_CLOSE_SCOPE 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /pxr/usdQt/primProxy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "primProxy.h" 26 | 27 | #include 28 | 29 | using BOOST_NS::adaptors::slice; 30 | 31 | PXR_NAMESPACE_OPEN_SCOPE 32 | 33 | UsdQt_PrimProxy::UsdQt_PrimProxy(const std::vector& prims) 34 | : _prims(prims) {} 35 | 36 | UsdQt_PrimProxyRefPtr UsdQt_PrimProxy::New(const std::vector& prims) { 37 | return TfCreateRefPtr(new UsdQt_PrimProxy(prims)); 38 | } 39 | 40 | std::vector UsdQt_PrimProxy::GetNames() { 41 | std::vector names; 42 | for (const auto& prim : _prims) { 43 | names.push_back(prim.GetName()); 44 | } 45 | return names; 46 | } 47 | 48 | const std::vector& UsdQt_PrimProxy::GetPrims() { return _prims; } 49 | 50 | TfTokenVector UsdQt_PrimProxy::GetAttributeNames() { 51 | if (_prims.size() < 1) return TfTokenVector(); 52 | 53 | std::vector firstAttributes = _prims[0].GetAttributes(); 54 | std::vector sharedNames; 55 | for (const auto& attribute : firstAttributes) { 56 | sharedNames.push_back(attribute.GetName()); 57 | } 58 | 59 | auto sharedNamesEnd = sharedNames.end(); 60 | for (const auto& prim : slice(_prims, 1, _prims.size())) { 61 | sharedNamesEnd = remove_if( 62 | sharedNames.begin(), sharedNamesEnd, 63 | [&](const TfToken& name) { return !prim.HasAttribute(name); }); 64 | } 65 | sharedNames.erase(sharedNamesEnd, sharedNames.end()); 66 | return sharedNames; 67 | } 68 | 69 | TfTokenVector UsdQt_PrimProxy::GetRelationshipNames() { 70 | if (_prims.size() < 1) return TfTokenVector(); 71 | 72 | std::vector firstRelationships = 73 | _prims[0].GetRelationships(); 74 | TfTokenVector sharedNames; 75 | for (const auto& relationship : firstRelationships) { 76 | sharedNames.push_back(relationship.GetName()); 77 | } 78 | 79 | auto sharedNamesEnd = sharedNames.end(); 80 | for (const auto& prim : slice(_prims, 1, _prims.size())) { 81 | sharedNamesEnd = remove_if( 82 | sharedNames.begin(), sharedNamesEnd, 83 | [&](const TfToken& name) { return !prim.HasRelationship(name); }); 84 | } 85 | sharedNames.erase(sharedNamesEnd, sharedNames.end()); 86 | return sharedNames; 87 | } 88 | 89 | UsdQt_RelationshipProxyRefPtr UsdQt_PrimProxy::CreateRelationshipProxy( 90 | const TfToken& name) { 91 | std::vector sharedRelationships; 92 | 93 | for (const auto& prim : _prims) { 94 | if (!prim.HasRelationship(name)) 95 | return UsdQt_RelationshipProxy::New(std::vector()); 96 | sharedRelationships.push_back(prim.GetRelationship(name)); 97 | } 98 | return UsdQt_RelationshipProxy::New(sharedRelationships); 99 | } 100 | 101 | UsdQt_VariantSetsProxyRefPtr UsdQt_PrimProxy::CreateVariantSetsProxy() { 102 | return UsdQt_VariantSetsProxy::New(_prims); 103 | } 104 | 105 | UsdQt_AttributeProxyRefPtr UsdQt_PrimProxy::CreateAttributeProxy( 106 | const TfToken& name) { 107 | std::vector sharedAttributes; 108 | 109 | for (const auto& prim : _prims) { 110 | if (!prim.HasAttribute(name)) return NULL; 111 | sharedAttributes.push_back(prim.GetAttribute(name)); 112 | } 113 | return UsdQt_AttributeProxy::New(sharedAttributes); 114 | } 115 | 116 | void UsdQt_PrimProxy::ClearExpired() { 117 | auto primsEnd = remove_if(_prims.begin(), _prims.end(), 118 | [&](const UsdPrim& prim) { return !prim; }); 119 | _prims.erase(primsEnd, _prims.end()); 120 | } 121 | 122 | std::vector& UsdQt_PrimProxy::_GetObjects() { return _prims; } 123 | const std::vector& UsdQt_PrimProxy::_GetObjects() const { 124 | return _prims; 125 | } 126 | PXR_NAMESPACE_CLOSE_SCOPE 127 | -------------------------------------------------------------------------------- /pxr/usdQt/primFilterCache.h: -------------------------------------------------------------------------------- 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 | 25 | #ifndef USDQT_PRIMFILTERCACHE_H 26 | #define USDQT_PRIMFILTERCACHE_H 27 | 28 | #include 29 | #include 30 | 31 | #include "pxr/pxr.h" 32 | #include "pxr/usd/usd/primFlags.h" 33 | #include "pxr/usd/usd/prim.h" 34 | #include "pxr/usd/usd/stage.h" 35 | #include "pxr/usd/sdf/path.h" 36 | 37 | #include "tbb/concurrent_unordered_map.h" 38 | 39 | #include "debugCodes.h" 40 | 41 | PXR_NAMESPACE_OPEN_SCOPE 42 | 43 | /// \class UsdQtPrimFilterCache 44 | /// 45 | /// By default, Qt rejects parents before traversing the children. The prim 46 | /// filter cache is used to fully traverse the stage in parallel and 47 | /// cache Accept and Reject states for the prim hierarchy based on a filter. 48 | /// 49 | /// This filtering allows for a "Intermediate" State which will accept the 50 | /// current location if and only if one ofthe children have been accepted. 51 | /// 52 | /// For example, take this hierarchy... 53 | /// /World 54 | /// /sets 55 | /// /crowds 56 | /// /fx 57 | /// If I were try and match prims whose path contains "crowds", Qt by default 58 | /// would not know whether or not to accept or reject '/World'. The filter 59 | /// cache allows a user to specify "Intermediate" as the state for '/World' to 60 | /// defer Acceptance or Rejection until after its children have been processed. 61 | class UsdQtPrimFilterCache { 62 | 63 | public: 64 | enum State { 65 | Accept, // Accept the current location 66 | Intermediate, // Accept the current location if and only if one of the 67 | // children have been accepted 68 | Reject, // Reject the current location 69 | Untraversed // Default value 70 | }; 71 | 72 | private: 73 | tbb::concurrent_unordered_map _stateMap; 74 | 75 | public: 76 | UsdQtPrimFilterCache(); 77 | 78 | /// \brief Apply a string match against the name of root and its descendents 79 | /// 80 | /// The prim will match the substring if the prim's name contains the 81 | /// substring. 82 | void ApplyPathContainsFilter(const UsdPrim& root, 83 | const std::string& substring, 84 | Usd_PrimFlagsPredicate predicate = 85 | UsdPrimDefaultPredicate); 86 | 87 | /// \brief Apply a custom filter to root and its descendents 88 | void ApplyFilter(const UsdPrim& root, 89 | const std::function& filter, 90 | Usd_PrimFlagsPredicate predicate = 91 | UsdPrimDefaultPredicate); 92 | 93 | /// \brief Retrieve the stored Acceptance/Rejection state for a path 94 | /// 95 | /// If a path has not been found, returns Untraversed. This implies a 96 | /// coding error that's allowed the cache to become out of sync. 97 | /// 98 | /// This should never return Intermediate to a client unless it's accessing 99 | /// the cache in a thread-unsafe matter. 100 | State GetState(const SdfPath& path); 101 | 102 | void PrintDebugString() const; 103 | 104 | private: 105 | State _RunFilter(UsdPrim prim, 106 | const std::function& filter, 107 | Usd_PrimFlagsPredicate predicate); 108 | }; 109 | 110 | /// \class UsdQtPrimFilterPathContains 111 | /// Function object which checks to see if the prim's name contains the 112 | /// substring. 113 | /// 114 | class UsdQtPrimFilterPathContains { 115 | private: 116 | std::string _substring; 117 | 118 | public: 119 | explicit UsdQtPrimFilterPathContains(const std::string& substring) 120 | : _substring(substring) {} 121 | 122 | UsdQtPrimFilterCache::State operator()(const UsdPrim& prim); 123 | }; 124 | 125 | PXR_NAMESPACE_CLOSE_SCOPE 126 | 127 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UsdQt 2 | 3 | ### Qt components for building custom USD tools 4 | 5 | #### Current Branch Compatibility 6 | 7 | - master : USD 19.07 8 | - Should be compatible with the post-19.07 USD dev branch up to and including [b6ccb4e5](https://github.com/PixarAnimationStudios/USD/commit/b6ccb4e543dea2ab4cd41b0fc162c5501ac9b103) 9 | - dev : USD 19.11+ 10 | 11 | ## Project Goals 12 | 13 | The UI components that make up `usdview` are good reference for functionality, 14 | but they’re purpose-built for the application, and are implemented in ways that 15 | make them difficult to decouple from it. 16 | 17 | This project is meant to provide application components that can provide similar 18 | (as well as new) functionality, to allow for ad-hoc use in custom tools. 19 | 20 | Longer-term, we hope this project will grow to the point that it can be used to 21 | build a fully-functional `usdview` application. 22 | 23 | ## Contents 24 | 25 | This project contains a mixture of pure Python and wrapped C++ code. All Qt code 26 | is written in pure Python to avoid the need to link against Qt and get `moc` 27 | involved in the build process. This may change in the future if deemed 28 | beneficial/necessary. 29 | 30 | The compiled extension module provides a set of helper classes that interface 31 | with the USD C++ API to accelerate certain USD queries, operations, etc. 32 | 33 | #### Installed Python Packages 34 | 35 | - `pxr.UsdQt`: Contains various Qt item data models, helper classes for building 36 | UIs, and some other USD and Qt utility code. The `_bindings` module currently 37 | contains all of the wrapped classes from the compiled extension module. 38 | - `pxr.UsdQtEditors`: Contains various Qt UI elements. These range from 39 | purpose-built display/editor widgets to an extensible outliner UI that also 40 | serves as a good usage example for many of the utilities in `pxr.UsdQt`. 41 | - `treemodel`: Contains a generic item tree and a Qt item model mixin that uses 42 | it, which are used by some of the classes in `pxr.UsdQt`. 43 | 44 | ## Building/Installation 45 | 46 | The recommended (and currently only tested) way to build the project is using 47 | CMake. A `setup.py` file is provided as well, but it has not been tested with 48 | the most recent updates. 49 | 50 | #### Build Requirements 51 | 52 | - Boost Python 53 | - USD 54 | - TBB 55 | 56 | #### CMake Options 57 | 58 | - `INSTALL_PURE_PYTHON (BOOL)`: Whether to install the pure Python code in 59 | addition to the compiled extension module. This defaults to `ON`. 60 | 61 | #### A note about `UsdQt.py` and `UsdQtEditors.py` 62 | 63 | You may notice that the source contains `UsdQt.py` and `UsdQtEditors.py` files 64 | alongside the package source directories. These are "shim" modules that we've 65 | found to be very useful during the development of this project, as they enable 66 | us to do more rapid editing and testing on the pure Python code without needing 67 | to run a CMake build and install between each minor edit. They are not installed 68 | with the project. 69 | 70 | ## Using `UsdQt` with the USD Python bindings 71 | 72 | `UsdQt` uses `pkg_resources` (or `pkgutil` if the former is not available) to 73 | declare `pxr` as a "namespace package" at runtime. This allows it to overlay its 74 | sub-packages onto the same `pxr` package used by the USD Python bindings, so 75 | that the two projects can be installed in separate locations and still work 76 | together. 77 | 78 | However, the USD Python bindings do not currently declare `pxr` as a namespace 79 | package in a symmetrical way, which unfortunately means that if the USD Python 80 | bindings are listed before `UsdQt` on the module search path, you will not be 81 | able to import `pxr.UsdQt`. Thus, unless/until the USD Python bindings are 82 | updated to declare `pxr` as a namespace package, you will need to make sure 83 | `UsdQt` is listed before the USD Python bindings on the module search path. 84 | 85 | More information on namespace packages in Python can be found in the docs for 86 | `pkg_resources` and `pkgutil`: 87 | 88 | https://setuptools.readthedocs.io/en/latest/pkg_resources.html#namespace-package-support 89 | 90 | https://docs.python.org/2/library/pkgutil.html 91 | 92 | ## Using an alternate Qt API 93 | 94 | `UsdQt` expects its underlying Qt API to adhere to the Qt5 module layout, and 95 | uses the PySide2 API. 96 | 97 | By default, it will attempt to import and use `PySide2`. This can be overridden 98 | by setting the `PXR_QT_PYTHON_BINDING` environment variable to the name of the 99 | API package/module you wish to use instead. 100 | 101 | This works with the popular [Qt.py](https://github.com/mottosso/Qt.py) project. 102 | 103 | ## Planned Future Additions 104 | 105 | Here are some of the ideas we've had for future additions to the project. We're 106 | happy to consider new suggestions as well. 107 | 108 | - UI components for authoring and working with USD variant sets. 109 | - An adaptor class to translate USD notices to Qt signals. 110 | - A `QSyntaxHighlighter` class for `.usda` syntax. 111 | - A Hydra viewport widget. 112 | -------------------------------------------------------------------------------- /treemodel/qt/base.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Luma Pictures 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 | 25 | from __future__ import absolute_import 26 | 27 | from treemodel.itemtree import ItemTree, TreeItem 28 | 29 | from pxr.UsdQt._Qt import QtCore, QtGui 30 | 31 | if False: 32 | from typing import * 33 | 34 | 35 | NULL_INDEX = QtCore.QModelIndex() 36 | 37 | 38 | class AbstractTreeModelMixin(object): 39 | """Mixin class that implements the necessary methods for Qt model to reflect 40 | the structure of an ``ItemTree`` instance. 41 | """ 42 | def __init__(self, itemTree=None, parent=None): 43 | """ 44 | Parameters 45 | ---------- 46 | itemTree : Optional[ItemTree] 47 | parent 48 | """ 49 | super(AbstractTreeModelMixin, self).__init__(parent=parent) 50 | 51 | self.itemTree = None # type: ItemTree 52 | self.SetItemTree(itemTree or ItemTree()) 53 | 54 | # Qt methods --------------------------------------------------------------- 55 | def hasChildren(self, parentIndex): 56 | """ 57 | Parameters 58 | ---------- 59 | parentIndex : QtCore.QModelIndex 60 | 61 | Returns 62 | ------- 63 | bool 64 | """ 65 | return bool(self.rowCount(parentIndex)) 66 | 67 | def index(self, row, column, parentIndex): 68 | """ 69 | Parameters 70 | ---------- 71 | row : int 72 | column : int 73 | parentIndex : QtCore.QModelIndex 74 | 75 | Returns 76 | ------- 77 | QtCore.QModelIndex 78 | """ 79 | if parentIndex.isValid(): 80 | parentItem = parentIndex.internalPointer() 81 | else: 82 | parentItem = self.itemTree.root 83 | return self.ItemIndex(row, column, parentItem) 84 | 85 | def parent(self, modelIndex): 86 | """ 87 | Parameters 88 | ---------- 89 | modelIndex : QtCore.QModelIndex 90 | 91 | Returns 92 | ------- 93 | QtCore.QModelIndex 94 | """ 95 | if modelIndex.isValid(): 96 | parent = self.itemTree.Parent(modelIndex.internalPointer()) 97 | if parent is not self.itemTree.root: 98 | return self.createIndex(self.itemTree.RowIndex(parent), 0, parent) 99 | return NULL_INDEX 100 | 101 | def rowCount(self, parentIndex): 102 | """ 103 | Parameters 104 | ---------- 105 | parentIndex : QtCore.QModelIndex 106 | 107 | Returns 108 | ------- 109 | int 110 | """ 111 | if parentIndex.column() > 0: 112 | return 0 113 | if parentIndex.isValid(): 114 | parent = parentIndex.internalPointer() 115 | else: 116 | parent = self.itemTree.root 117 | return self.itemTree.ChildCount(parent=parent) 118 | 119 | # Custom methods ----------------------------------------------------------- 120 | def SetItemTree(self, itemTree): 121 | """ 122 | Parameters 123 | ---------- 124 | itemTree : ItemTree 125 | """ 126 | assert isinstance(itemTree, ItemTree) 127 | self.beginResetModel() 128 | self.itemTree = itemTree 129 | self.endResetModel() 130 | 131 | def ItemIndex(self, row, column, parentItem): 132 | """ 133 | Parameters 134 | ---------- 135 | row : int 136 | column : int 137 | parentItem: TreeItem 138 | 139 | Returns 140 | ------- 141 | QtCore.QModelIndex 142 | """ 143 | try: 144 | childItem = self.itemTree.ChildAtRow(parentItem, row) 145 | except (KeyError, IndexError): 146 | return NULL_INDEX 147 | else: 148 | return self.createIndex(row, column, childItem) 149 | 150 | def GetItemIndex(self, item, column=0): 151 | """ 152 | Parameters 153 | ---------- 154 | item : TreeItem 155 | column : int 156 | 157 | Returns 158 | ------- 159 | QtCore.QModelIndex 160 | """ 161 | return self.ItemIndex(self.itemTree.RowIndex(item), column, 162 | self.itemTree.Parent(item)) 163 | -------------------------------------------------------------------------------- /pxr/usdQt/testenv/testUsdQtUndoRouter.py: -------------------------------------------------------------------------------- 1 | #!/pxrpythonsubst 2 | # 3 | # Copyright 2016 Pixar 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "Apache License") 6 | # with the following modification; you may not use this file except in 7 | # compliance with the Apache License and the following modification to it: 8 | # Section 6. Trademarks. is deleted and replaced with: 9 | # 10 | # 6. Trademarks. This License does not grant permission to use the trade 11 | # names, trademarks, service marks, or product names of the Licensor 12 | # and its affiliates, except as required to comply with Section 4(c) of 13 | # the License and to reproduce the content of the NOTICE file. 14 | # 15 | # You may obtain a copy of the Apache License at 16 | # 17 | # http://www.apache.org/licenses/LICENSE-2.0 18 | # 19 | # Unless required by applicable law or agreed to in writing, software 20 | # distributed under the Apache License with the above modification is 21 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 22 | # KIND, either express or implied. See the Apache License for the specific 23 | # language governing permissions and limitations under the Apache License. 24 | # 25 | 26 | import unittest2 as unittest 27 | 28 | from pxr import Tf, Usd 29 | from pxr.UsdQt._bindings import (UndoBlock, UndoInverse, UndoRouter, 30 | UndoStackNotice) 31 | 32 | 33 | class TestUndoRouter(unittest.TestCase): 34 | 35 | def setUp(self): 36 | self.stage = Usd.Stage.CreateInMemory() 37 | UndoRouter.TrackLayer(self.stage.GetRootLayer()) 38 | self.localUndoStack = [] 39 | self.listener = Tf.Notice.RegisterGlobally(UndoStackNotice, self.Notice) 40 | 41 | def Notice(self, notice, sender): 42 | inverse = UndoInverse() 43 | UndoRouter.TransferEdits(inverse) 44 | self.localUndoStack.append(inverse) 45 | 46 | def testExpiredStage(self): 47 | with UndoBlock(): 48 | self.stage.DefinePrim('/World') 49 | 50 | self.stage = None 51 | with self.assertRaises(Tf.ErrorException): 52 | self.localUndoStack[-1].Invert() 53 | 54 | def testMidEditBlockInversion(self): 55 | self.stage.DefinePrim('/World') 56 | with UndoBlock(): 57 | with self.assertRaisesRegexp(Tf.ErrorException, 'Inversion during \ 58 | open edit block may result in corrupted undo stack.'): 59 | self.localUndoStack[-1].Invert() 60 | 61 | def testNoEditBlock(self): 62 | prim = self.stage.DefinePrim('/World') 63 | self.assertTrue(bool(prim)) 64 | self.assertEqual(len(self.localUndoStack), 3) 65 | # undo 66 | self.localUndoStack[-1].Invert() 67 | self.localUndoStack[-2].Invert() 68 | self.localUndoStack[-3].Invert() 69 | self.assertFalse(bool(prim)) 70 | # redo 71 | self.localUndoStack[-3].Invert() 72 | self.localUndoStack[-2].Invert() 73 | self.localUndoStack[-1].Invert() 74 | prim = self.stage.GetPrimAtPath('/World') 75 | self.assertTrue(bool(prim)) 76 | 77 | def testRevokedListener(self): 78 | self.listener.Revoke() 79 | with UndoBlock(): 80 | self.stage.DefinePrim('/World') 81 | with UndoBlock(): 82 | self.stage.DefinePrim('/World/Child') 83 | self.assertEqual(self.localUndoStack, []) 84 | 85 | def testNestedUndoBlock(self): 86 | with UndoBlock(): 87 | prim = self.stage.DefinePrim('/World') 88 | 89 | self.assertTrue(bool(prim)) 90 | with UndoBlock(): 91 | prim.SetActive(False) 92 | with UndoBlock(): 93 | prim.SetActive(True) 94 | with UndoBlock(): 95 | prim.SetActive(False) 96 | 97 | self.assertFalse(prim.IsActive()) 98 | self.assertEqual(len(self.localUndoStack), 2) 99 | 100 | with UndoBlock(): 101 | prim.SetActive(False) 102 | with UndoBlock(): 103 | prim.SetActive(True) 104 | 105 | self.assertTrue(prim.IsActive()) 106 | self.assertEqual(len(self.localUndoStack), 3) 107 | 108 | self.localUndoStack[-1].Invert() # undo 109 | self.assertFalse(prim.IsActive()) 110 | self.localUndoStack[-1].Invert() # redo 111 | self.assertTrue(prim.IsActive()) 112 | self.localUndoStack[-1].Invert() # undo 113 | self.assertFalse(prim.IsActive()) 114 | self.localUndoStack[-2].Invert() # undo 115 | self.assertTrue(prim.IsActive()) 116 | self.localUndoStack[-3].Invert() # undo 117 | self.assertFalse(bool(prim)) 118 | self.localUndoStack[-3].Invert() # redo 119 | prim = self.stage.GetPrimAtPath('/World') 120 | self.assertTrue(bool(prim)) 121 | self.assertTrue(prim.IsActive()) 122 | 123 | self.assertEqual(len(self.localUndoStack), 3) 124 | 125 | def testEmptyUndoBlock(self): 126 | with UndoBlock(): 127 | pass 128 | self.assertEqual(self.localUndoStack, []) 129 | 130 | with UndoBlock(): 131 | with UndoBlock(): 132 | with UndoBlock(): 133 | pass 134 | self.assertEqual(self.localUndoStack, []) 135 | 136 | 137 | if __name__ == '__main__': 138 | unittest.main() 139 | -------------------------------------------------------------------------------- /pxr/usdQt/variantSetsProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_VARIANTSETSPROXY_H 26 | #define USDQT_VARIANTSETSPROXY_H 27 | 28 | #include 29 | #include 30 | 31 | #include "pxr/pxr.h" 32 | #include "pxr/base/tf/token.h" 33 | #include "pxr/usd/usd/variantSets.h" 34 | 35 | #include "proxyBase.h" 36 | 37 | PXR_NAMESPACE_OPEN_SCOPE 38 | 39 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_VariantSetsProxy); 40 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_VariantSetProxy); 41 | 42 | /// \class UsdQt_VariantSetsProxy 43 | /// \brief Proxy interface for an ordered list of 'UsdVariantSets' 44 | /// 45 | /// A VariantSets proxy can be used to as a single interface to query and edit 46 | /// data on multiple UsdVariantSets across disparate prims. 47 | /// 48 | /// This should not be confused with a UsdQt_VariantSetProxy which is an 49 | /// interface on top of one specific VariantSet, not all VariantSets for a 50 | /// list of prims. 51 | class UsdQt_VariantSetsProxy : public UsdQt_ProxyBase { 52 | private: 53 | std::vector _prims; 54 | explicit UsdQt_VariantSetsProxy( 55 | const std::vector& prims); 56 | 57 | public: 58 | static UsdQt_VariantSetsProxyRefPtr New( 59 | const std::vector& prims); 60 | 61 | /// \brief Return the number of VariantSets this proxy refers to. 62 | size_t GetSize() const { return _prims.size(); } 63 | 64 | /// \brief Return the number of VariantSets this proxy refers to. 65 | std::vector GetNames() const; 66 | 67 | /// \brief Get the intersection of variant set names for all members of this 68 | /// proxy. 69 | /// 70 | /// Returns true all UsdVarianSets queries were successful. 71 | bool GetNames(std::vector* names) const; 72 | 73 | /// \brief Append a new variant set for all members of this proxy 74 | void AddVariantSet(const std::string& name); 75 | 76 | /// \brief Create a new proxy for the 'name' variant set for all VariantSets 77 | /// 78 | /// If all prims don't have a variant set 'name', no proxy is created and 79 | /// NULL is returend. 80 | UsdQt_VariantSetProxyRefPtr CreateVariantSetProxy(const std::string& name); 81 | }; 82 | 83 | 84 | /// \class UsdQt_VariantSetProxy 85 | /// \brief Proxy interface for an ordered list of 'UsdVariantSet' objects 86 | /// 87 | /// A VariantSet proxy can be used to as a single interface to query and edit 88 | /// data on multiple UsdVariantSet objects across disparate prims. 89 | /// 90 | /// This should not be confused with a UsdQt_VariantSetsProxy which is an 91 | /// interface on top of all of the VariantSets of a list of prims, not one 92 | /// specific VariantSet. 93 | class UsdQt_VariantSetProxy : public UsdQt_ProxyBase { 94 | private: 95 | std::vector _variantSets; 96 | explicit UsdQt_VariantSetProxy( 97 | const std::vector& variantSet); 98 | 99 | public: 100 | static UsdQt_VariantSetProxyRefPtr New( 101 | const std::vector& variantSets); 102 | 103 | /// \brief Return the number of VariantSet objects this proxy refers to. 104 | size_t GetSize() const { return _variantSets.size(); } 105 | 106 | /// \brief Get the name that all VariantSet objects for this proxy share 107 | /// 108 | /// If the name for all VariantSet objects is not equal, an empty string is 109 | /// returned. 110 | std::string GetName() const; 111 | 112 | /// \brief Get the intersection of all variant names for all sets for this 113 | /// proxy 114 | std::vector GetVariantNames() const; 115 | 116 | /// \brief Get a shared variant selection string for all sets for this proxy 117 | /// 118 | /// If all variant selections are not the same, the empty string is 119 | /// returned. 120 | std::string GetVariantSelection() const; 121 | 122 | /// \brief Set the variant selection string for all sets for this proxy 123 | /// 124 | /// Returns true if all Variant selections were successful. 125 | bool SetVariantSelection(const std::string& variant); 126 | 127 | /// \brief Clear the variant selection string for all sets for this proxy 128 | /// 129 | /// Returns true if all clears were successful. 130 | bool ClearVariantSelection(); 131 | 132 | /// \brief Add a new variant to all set objects for this proxy 133 | bool AddVariant (const std::string &variantName); 134 | }; 135 | 136 | PXR_NAMESPACE_CLOSE_SCOPE 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /pxr/usdQt/objectProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_OBJECTPROXY_H 26 | #define USDQT_OBJECTPROXY_H 27 | 28 | #include "pxr/pxr.h" 29 | #include "pxr/usd/sdf/path.h" 30 | 31 | #include "metadataProxy.h" 32 | #include "proxyBase.h" 33 | 34 | PXR_NAMESPACE_OPEN_SCOPE 35 | 36 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_ObjectProxy); 37 | 38 | /// \brief Common super class of any proxy representing a list of UsdObjects 39 | /// 40 | /// User customized types in general shouldn't subclass this, becaus the only 41 | /// valid UsdObject types are Prim, Attribute, and Relationship. 42 | class UsdQt_ObjectProxy : public UsdQt_ProxyBase { 43 | public: 44 | /// \brief Check if any object explicilty refers to any path in the vector 45 | /// 46 | /// For example, let's say a proxy refers to 47 | /// [Usd.Prim(/World/prim1), Usd.Prim(/World/prim2), 48 | /// Usd.Prim(/World/prim3)] 49 | /// 50 | /// The SdfPathVector [/World/prim3, /World/SomeOthePrim] would return true 51 | /// because just one of the paths "/World/prim3" matches. 52 | /// 53 | /// The SdfPathVector [/World, /AnotherWorld] return false because no path 54 | /// matches exactly. 55 | /// 56 | /// The primary role of this function is to detect objects that may need 57 | /// to be updated because of ChangeInfo UsdNotices. 58 | virtual bool ContainsPath(const SdfPathVector&) const = 0; 59 | 60 | /// \brief Check if any object is a descendent or is any path in the vector 61 | /// 62 | /// For example, let's say a proxy refers to 63 | /// [Usd.Prim(/World/prim1), Usd.Prim(/World/prim2), 64 | /// Usd.Prim(/World/prim3)] 65 | /// 66 | /// The SdfPathVector [/World/prim3, /World/SomeOthePrim] would return true 67 | /// because the paths "/World/prim3" matches. 68 | /// 69 | /// The SdfPathVector [/World, /AnotherWorld] would also return true because 70 | /// the path "/World" is an ancestor of prim 71 | /// 72 | /// The SdfPathVector [/World/] 73 | /// 74 | /// The primary role of this function is to detect objects that may need 75 | /// to be updated because of Resync UsdNotices. 76 | virtual bool ContainsPathOrDescendent(const SdfPathVector&) const = 0; 77 | }; 78 | 79 | template 80 | class UsdQt_ObjectProxyBase : public UsdQt_ObjectProxy { 81 | protected: 82 | virtual std::vector& _GetObjects() = 0; 83 | virtual const std::vector& _GetObjects() const = 0; 84 | 85 | public: 86 | /// \brief Create a new proxy for the 'field' metadata for all attributes 87 | /// 88 | /// If all attributes don't have metadata 'field', no proxy is created and 89 | /// NULL is returend. 90 | UsdQt_MetadataProxyRefPtr CreateMetadataProxy(const TfToken& field); 91 | virtual bool ContainsPathOrDescendent(const SdfPathVector&) const override; 92 | virtual bool ContainsPath(const SdfPathVector&) const override; 93 | 94 | /// \brief Return metadata fields that ALL attributes share. 95 | TfTokenVector GetMetadataFields() const; 96 | 97 | /// \brief Get the name that all attributes for this proxy share 98 | /// 99 | /// If the name for all attributes is not equal, an empty TfToken is 100 | /// returned. 101 | TfToken GetName() const; 102 | 103 | /// \brief Get the documentation from the FIRST attribute for this proxy. 104 | /// Unlike most methods, we don't diff attempt to mediate disparate 105 | /// opinions for the documentation metadata, as large strings could be 106 | /// expensive to diff and unlikely to differ. 107 | std::string GetDocumentation() const; 108 | 109 | /// \brief Return true if ALL attributes for this proxy are valid. 110 | bool IsValid() const; 111 | 112 | /// \brief Return the number of attributes this proxy refers to. 113 | size_t GetSize() const; 114 | }; 115 | 116 | /// \brief A Property specific specialization of UsdQt_ObjectProxyBase 117 | /// 118 | template 119 | class UsdQt_PropertyProxyBase : public UsdQt_ObjectProxyBase { 120 | public: 121 | /// \brief Check if ANY property for this proxy is defined. 122 | bool IsDefined() const; 123 | 124 | /// \brief Check if ANY property for this proxy is authored. 125 | bool IsAuthored() const; 126 | 127 | /// \brief Check if ANY property for this proxy is authored at the editTarget. 128 | bool IsAuthoredAt(const UsdEditTarget&) const; 129 | }; 130 | 131 | PXR_NAMESPACE_CLOSE_SCOPE 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /pxr/usdQt/hierarchyCache.h: -------------------------------------------------------------------------------- 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 | 25 | #ifndef USDQT_HIERARCHYCACHE_H 26 | #define USDQT_HIERARCHYCACHE_H 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "pxr/pxr.h" 33 | #include "pxr/base/tf/refPtr.h" 34 | #include "pxr/base/tf/weakPtr.h" 35 | #include "pxr/usd/sdf/path.h" 36 | #include "pxr/usd/sdf/pathTable.h" 37 | #include "pxr/usd/usd/prim.h" 38 | #include "pxr/usd/usd/primFlags.h" 39 | #include "pxr/usd/usd/stage.h" 40 | 41 | PXR_NAMESPACE_OPEN_SCOPE 42 | 43 | /// \class UsdQt_HierarchyCache 44 | /// 45 | /// The HierarchyCache is an internal class to UsdQt and provides a mapping 46 | /// from SdfPaths to ref counted pointers that can be used with 47 | /// QModelIndexs. We provide this class so that the hierarchy can be quickly 48 | /// indexed and traversed in C++ without mandating that clients link against 49 | /// the Qt library. This class should also be compatable with a variety of 50 | /// flavors of Qt bindings and versions. 51 | 52 | class UsdQt_HierarchyCache { 53 | public: 54 | class Proxy : public TfRefBase, public TfWeakBase { 55 | private: 56 | UsdPrim _prim; 57 | SdfPathVector _children; 58 | explicit Proxy(const UsdPrim& prim); 59 | static TfRefPtr New(const UsdPrim& prim); 60 | 61 | void _RefreshChildren(Usd_PrimFlagsPredicate predicate); 62 | const SdfPathVector& _GetChildren(); 63 | 64 | public: 65 | UsdPrim GetPrim(); 66 | friend class UsdQt_HierarchyCache; 67 | }; 68 | 69 | private: 70 | Usd_PrimFlagsPredicate _predicate; 71 | TfRefPtr _root; 72 | TfRefPtr _invalidPrim; 73 | 74 | SdfPathTable> _pathToProxy; 75 | 76 | void _RegisterPrim(const UsdPrim& prim); 77 | void _InvalidateSubtree(const SdfPath& path); 78 | void _DeleteSubtree(const SdfPath& prim); 79 | 80 | public: 81 | /// Given a pointer to a stage, a root prim, and a predicate, construct 82 | /// the table. 83 | /// 84 | /// The predicate and root prim should be as accepting as possible, and 85 | /// a QSortFilterProxyModel used to dynamically filter the view. 86 | /// The root should almost always be the stage's pseudo root. 87 | /// The predicate should almost always be a tautology. The predicate and 88 | /// root allow you to optimize traversal if, for example, you know that you 89 | /// will only need to ever browse a specific scope (say Materials or Looks) 90 | /// or know that you never want to browse abstract or absent prims. 91 | explicit UsdQt_HierarchyCache(const UsdPrim& root, 92 | const Usd_PrimFlagsPredicate& predicate = 93 | UsdPrimDefaultPredicate); 94 | 95 | bool IsRoot(TfWeakPtr root) const; 96 | TfRefPtr GetRoot() const { return _root; } 97 | 98 | /// \brief 99 | bool ContainsPath(const SdfPath& path) { 100 | return _pathToProxy.find(path) != _pathToProxy.end(); 101 | } 102 | 103 | /// \brief Return the predicate used to filter 104 | /// 105 | /// The predicate cannot be changed after instantiation of the index. 106 | Usd_PrimFlagsPredicate GetPredicate() const { return _predicate; } 107 | 108 | /// \brief Return the id of the parent of the prim mapped to 'childId' 109 | TfRefPtr GetParent(TfWeakPtr child) const; 110 | 111 | /// \brief Return the index of the prim in the list of its parent's children 112 | size_t GetRow(TfWeakPtr child) const; 113 | 114 | /// \brief Return the number of children the prim for the proxy 115 | size_t GetChildCount(TfWeakPtr prim) const; 116 | 117 | /// \brief Return the proxy of the 'index'th child of the prim for the proxy 118 | /// This may create the child under the hood. 119 | TfRefPtr GetChild(TfWeakPtr, size_t index); 120 | 121 | TfRefPtr GetProxy(const SdfPath& path) { return _pathToProxy[path]; } 122 | 123 | /// \brief Refresh all the ids for the input paths and their descendants 124 | /// 125 | /// Resyncing is terminology from the UsdObjectChanged notice. Resyncing 126 | /// may imply a variety of things, addition, removal, variant change, etc. 127 | /// which is why we have to potentially touch every descendent of the 128 | /// input paths 129 | void ResyncSubtrees(const std::vector& paths); 130 | 131 | // void PrintSubtreeIndex(const SdfPath& path); 132 | void DebugFullIndex(); 133 | }; 134 | 135 | PXR_NAMESPACE_CLOSE_SCOPE 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /pxr/usdQt/attributeProxy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "attributeProxy.h" 26 | #include "utils.h" 27 | 28 | #include 29 | 30 | PXR_NAMESPACE_OPEN_SCOPE 31 | 32 | using BOOST_NS::adaptors::slice; 33 | using std::remove_if; 34 | 35 | VtTokenArray UsdQt_AttributeProxy::GetAllowedTokens() const { 36 | if (_attributes.size() < 1) return VtTokenArray(); 37 | if (GetTypeName() != SdfValueTypeNames->Token) return VtTokenArray(); 38 | 39 | TfToken allowedTokensStr("allowedTokens"); 40 | 41 | VtTokenArray sharedAllowedTokens; 42 | if (!_attributes[0].GetMetadata(allowedTokensStr, &sharedAllowedTokens)) { 43 | return VtTokenArray(); 44 | } 45 | 46 | auto sharedAllowedTokensEnd = sharedAllowedTokens.end(); 47 | for (const auto &attribute : slice(_attributes, 1, _attributes.size())) { 48 | VtTokenArray allowedTokens; 49 | if (!attribute.GetMetadata(allowedTokensStr, &allowedTokens)) { 50 | return VtTokenArray(); 51 | } 52 | sharedAllowedTokensEnd = 53 | remove_if(sharedAllowedTokens.begin(), sharedAllowedTokensEnd, 54 | [&](const TfToken &token) { 55 | return UsdQt_ItemNotInArray(allowedTokens, token); 56 | }); 57 | } 58 | 59 | sharedAllowedTokens.resize(sharedAllowedTokensEnd - 60 | sharedAllowedTokens.begin()); 61 | 62 | // waiting on bug http://bugzilla.pixar.com/show_bug.cgi?id=125316 63 | // sharedAllowedTokens.erase(sharedAllowedTokensEnd, 64 | // sharedAllowedTokens.end()); 65 | return sharedAllowedTokens; 66 | }; 67 | 68 | UsdQt_AttributeProxy::UsdQt_AttributeProxy( 69 | const std::vector &attributes) 70 | : _attributes(attributes) {} 71 | 72 | UsdQt_AttributeProxyRefPtr UsdQt_AttributeProxy::New( 73 | const std::vector &attributes) { 74 | return TfCreateRefPtr(new UsdQt_AttributeProxy(attributes)); 75 | } 76 | 77 | SdfVariability UsdQt_AttributeProxy::GetVariability() const { 78 | if (_attributes.size() < 1) { 79 | return SdfVariabilityUniform; 80 | } 81 | for (const auto &attribute : _attributes) { 82 | if (!attribute.GetVariability() == SdfVariabilityVarying) { 83 | return SdfVariabilityUniform; 84 | } 85 | } 86 | return SdfVariabilityVarying; 87 | } 88 | 89 | SdfValueTypeName UsdQt_AttributeProxy::GetTypeName() const { 90 | if (_attributes.size() < 1) { 91 | return SdfValueTypeName(); 92 | } 93 | SdfValueTypeName sharedTypeName = _attributes[0].GetTypeName(); 94 | for (const auto &attribute : slice(_attributes, 1, _attributes.size())) { 95 | if (attribute.GetTypeName() != sharedTypeName) { 96 | return SdfValueTypeName(); 97 | } 98 | } 99 | return sharedTypeName; 100 | } 101 | 102 | bool UsdQt_AttributeProxy::Get(VtValue *result, UsdTimeCode time) const { 103 | if (_attributes.size() < 1) { 104 | (*result) = VtValue(); 105 | return true; 106 | } 107 | VtValue sharedValue; 108 | _attributes[0].Get(&sharedValue, time); 109 | for (const auto &attribute : slice(_attributes, 1, _attributes.size())) { 110 | VtValue value; 111 | if (!attribute.Get(&value, time) || value != sharedValue) { 112 | (*result) = VtValue(); 113 | return false; 114 | } 115 | } 116 | (*result) = sharedValue; 117 | return true; 118 | } 119 | 120 | bool UsdQt_AttributeProxy::Set(const VtValue &result, UsdTimeCode time) { 121 | bool success = true; 122 | for (auto &attribute : _attributes) { 123 | success &= attribute.Set(result, time); 124 | } 125 | return success; 126 | } 127 | 128 | bool UsdQt_AttributeProxy::Clear() { 129 | bool success = true; 130 | for (auto &attribute : _attributes) { 131 | success &= attribute.Clear(); 132 | } 133 | return success; 134 | } 135 | 136 | bool UsdQt_AttributeProxy::ClearAtTime(UsdTimeCode time) { 137 | bool success = true; 138 | for (auto &attribute : _attributes) { 139 | success &= attribute.ClearAtTime(time); 140 | } 141 | return success; 142 | } 143 | 144 | void UsdQt_AttributeProxy::Block() { 145 | for (auto &attribute : _attributes) { 146 | attribute.Block(); 147 | } 148 | } 149 | 150 | std::vector &UsdQt_AttributeProxy::_GetObjects() { 151 | return _attributes; 152 | } 153 | const std::vector &UsdQt_AttributeProxy::_GetObjects() const { 154 | return _attributes; 155 | } 156 | 157 | PXR_NAMESPACE_CLOSE_SCOPE 158 | -------------------------------------------------------------------------------- /pxr/usdQt/layerModel.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Luma Pictures 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 | 25 | from __future__ import absolute_import 26 | 27 | from ._Qt import QtCore 28 | from pxr import Sdf, Usd 29 | 30 | from treemodel.itemtree import ItemTree, TreeItem 31 | from treemodel.qt.base import AbstractTreeModelMixin 32 | 33 | if False: 34 | from typing import * 35 | 36 | 37 | class LayerItem(TreeItem): 38 | __slots__ = ('layer',) 39 | 40 | def __init__(self, layer): 41 | # type: (Sdf.Layer) -> None 42 | """ 43 | Parameters 44 | ---------- 45 | layer : Sdf.Layer 46 | """ 47 | super(LayerItem, self).__init__(key=layer.identifier) 48 | self.layer = layer 49 | 50 | 51 | class LayerStackBaseModel(AbstractTreeModelMixin, QtCore.QAbstractItemModel): 52 | """Basic tree model that exposes a Stage's layer stack.""" 53 | headerLabels = ('Name', 'Path') 54 | 55 | def __init__(self, stage, includeSessionLayers=True, parent=None): 56 | # type: (Usd.Stage, bool, Optional[QtCore.QObject]) -> None 57 | """ 58 | Parameters 59 | ---------- 60 | stage : Usd.Stage 61 | includeSessionLayers : bool 62 | parent : Optional[QtCore.QObject] 63 | """ 64 | super(LayerStackBaseModel, self).__init__(parent=parent) 65 | self._stage = None 66 | self._includeSessionLayers = includeSessionLayers 67 | self.ResetStage(stage) 68 | 69 | # Qt methods --------------------------------------------------------------- 70 | def columnCount(self, parentIndex): 71 | return 2 72 | 73 | def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole): 74 | if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: 75 | return self.headerLabels[section] 76 | 77 | def data(self, modelIndex, role=QtCore.Qt.DisplayRole): 78 | if not modelIndex.isValid(): 79 | return 80 | if role == QtCore.Qt.DisplayRole: 81 | column = modelIndex.column() 82 | item = modelIndex.internalPointer() 83 | if column == 0: 84 | if item.layer.anonymous: 85 | return '' 86 | return item.layer.identifier.rsplit('/', 1)[-1] 87 | elif column == 1: 88 | return item.layer.identifier 89 | 90 | # Custom methods ----------------------------------------------------------- 91 | def LayerCount(self): 92 | """Return the number of layers in the current stage's layer stack.""" 93 | return self.itemTree.ItemCount() 94 | 95 | def ResetStage(self, stage): 96 | # type: (Usd.Stage) -> None 97 | """Reset the model from a new stage. 98 | 99 | Parameters 100 | ---------- 101 | stage : Usd.Stage 102 | """ 103 | if stage == self._stage: 104 | return 105 | 106 | self.beginResetModel() 107 | itemTree = self.itemTree = ItemTree() 108 | 109 | def addLayer(layer, parent=None): 110 | layerItem = LayerItem(layer) 111 | itemTree.AddItems(layerItem, parent=parent) 112 | return layerItem 113 | 114 | def addLayerTree(layerTree, parent=None): 115 | item = addLayer(layerTree.layer, parent=parent) 116 | for childTree in layerTree.childTrees: 117 | addLayerTree(childTree, parent=item) 118 | 119 | self._stage = None 120 | if stage: 121 | root = stage.GetPseudoRoot() 122 | if root: 123 | self._stage = stage 124 | if self._includeSessionLayers: 125 | sessionLayer = stage.GetSessionLayer() 126 | if sessionLayer: 127 | sessionLayerItem = addLayer(sessionLayer) 128 | for path in sessionLayer.subLayerPaths: 129 | addLayer(Sdf.Layer.FindOrOpen(path), 130 | parent=sessionLayerItem) 131 | layerTree = root.GetPrimIndex().rootNode.layerStack.layerTree 132 | addLayerTree(layerTree) 133 | 134 | self.endResetModel() 135 | 136 | 137 | if __name__ == '__main__': 138 | """ Sample usage """ 139 | from pxr import Usd 140 | from ._Qt import QtWidgets 141 | import sys 142 | import os 143 | 144 | app = QtWidgets.QApplication([]) 145 | path = os.path.join(os.path.dirname(__file__), 'testenv', 146 | 'testUsdQtLayerModel', 'simpleLayerStack.usda') 147 | stage = Usd.Stage.Open(path) 148 | 149 | model = LayerStackBaseModel(stage) 150 | view = QtWidgets.QTreeView() 151 | view.setModel(model) 152 | 153 | def OnDoubleClicked(modelIndex): 154 | print modelIndex.data() 155 | 156 | view.doubleClicked.connect(OnDoubleClicked) 157 | view.show() 158 | 159 | sys.exit(app.exec_()) 160 | -------------------------------------------------------------------------------- /pxr/usdQt/metadataProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #ifndef USDQT_METADATAPROXY_H 26 | #define USDQT_METADATAPROXY_H 27 | 28 | #include 29 | #include 30 | 31 | #include "pxr/pxr.h" 32 | #include "pxr/base/tf/token.h" 33 | #include "pxr/base/vt/value.h" 34 | #include "pxr/usd/usd/object.h" 35 | #include "pxr/usd/usd/stage.h" 36 | 37 | #include "proxyBase.h" 38 | 39 | PXR_NAMESPACE_OPEN_SCOPE 40 | 41 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_MetadataProxy); 42 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_MetadataDictKeyProxy); 43 | 44 | /// \class UsdQt_MetadataProxy 45 | /// \brief Proxy interface for metadata on a list of UsdObjects 46 | /// 47 | /// A metadata proxy can be used to as a single interface to query and edit 48 | /// metadata on multiple UsdObjects 49 | class UsdQt_MetadataProxy : public UsdQt_ProxyBase { 50 | private: 51 | std::vector _objects; 52 | TfToken _field; 53 | explicit UsdQt_MetadataProxy(const std::vector& objects, 54 | TfToken field); 55 | 56 | public: 57 | static UsdQt_MetadataProxyRefPtr New(const std::vector& objects, 58 | TfToken field); 59 | 60 | /// \brief Return the list of all objects for this proxy. 61 | const std::vector& GetObjects() const {return _objects;} 62 | 63 | /// \brief Get the name of the metdata field for this proxy. 64 | TfToken GetName() const; 65 | 66 | /// \brief Get the type of the metdata field for this proxy. 67 | TfType GetType() const; 68 | 69 | /// \brief Get the shared value of metdata for all objects in this proxy. 70 | /// 71 | /// If all values are not the same, result will be an empty VtValue. 72 | /// This method returns true if all metadata Get requests were successful. 73 | bool GetValue(VtValue* result) const; 74 | 75 | /// \brief Set the value of metdata for all objects in this proxy. 76 | /// 77 | /// This method returns true if all metadata Set requests were successful. 78 | bool SetValue(const VtValue& value); 79 | 80 | /// \brief Clear the value of metdata for all objects in this proxy. 81 | /// 82 | /// This method returns true if all metadata Clearrequests were successful. 83 | bool ClearValue(); 84 | 85 | /// \brief Get the intersection of all dictionary keys for this metadata. 86 | /// 87 | /// Just as we provide a specailized interface for VariantSet metadata 88 | /// It may make sense to provide a specialized interface for VtDictionary 89 | /// Metadata to avoid polluting the MetadataProxy API. 90 | std::vector GetDictKeys() const; 91 | 92 | /// \brief Create a proxy for this entry in a metadata dictionary 93 | UsdQt_MetadataDictKeyProxyRefPtr CreateMetadataDictKeyProxy( 94 | const TfToken& dictKey); 95 | 96 | /// \brief Return the number of UsdObjects this proxy refers to. 97 | size_t GetSize() const { return _objects.size(); } 98 | }; 99 | 100 | /// \class UsdQt_MetadataDictKeyProxy 101 | /// \brief Proxy interface for an entry in a metadata dictionary 102 | /// 103 | /// A metadata dict key proxy can be used to as a single interface to query and 104 | /// edit a single entry of a metadata dictionary on multiple UsdObjects 105 | class UsdQt_MetadataDictKeyProxy : public UsdQt_ProxyBase { 106 | private: 107 | std::vector _objects; 108 | TfToken _field; 109 | TfToken _dictKey; 110 | explicit UsdQt_MetadataDictKeyProxy(const std::vector& objects, 111 | TfToken field, TfToken dictKey); 112 | 113 | public: 114 | static UsdQt_MetadataDictKeyProxyRefPtr New( 115 | const std::vector& objects, TfToken field, TfToken dictKey); 116 | 117 | /// \brief Get the name of the metadata field that refers to this dictionary 118 | TfToken GetDictName() const; 119 | 120 | /// \brief Get the name of the key of the entry in this dictionary 121 | TfToken GetEntryName() const; 122 | 123 | /// \brief Get the shared value of this entry in the dictionary 124 | /// 125 | /// Return true if all GetMetadataByDictKey requests are succesful. 126 | /// If the values of the entry are not eqaul, 'result' is set to an empty 127 | /// VtValue 128 | bool GetValue(VtValue* result) const; 129 | 130 | /// \brief Set the value of this entry in the dictionary for all objects 131 | /// 132 | /// Return true if all SetMetadataByDictKey requests are succesful. 133 | bool SetValue(const VtValue& value); 134 | 135 | /// \brief Clear the value of this entry in the dictionary for all objects 136 | /// 137 | /// Return true if all ClearMetadataByDictKey requests are succesful. 138 | bool ClearValue(); 139 | 140 | /// \brief Get the type of the metdata field for this proxy. 141 | TfType GetType() const; 142 | 143 | /// \brief Return the number of UsdObjects this proxy refers to. 144 | size_t GetSize() const { return _objects.size(); } 145 | }; 146 | 147 | PXR_NAMESPACE_CLOSE_SCOPE 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /pxr/usdQt/objectProxy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | // 25 | 26 | #include 27 | 28 | #include "pxr/usd/usd/attribute.h" 29 | #include "pxr/usd/usd/object.h" 30 | #include "pxr/usd/usd/prim.h" 31 | #include "pxr/usd/usd/relationship.h" 32 | 33 | #include "objectProxy.h" 34 | 35 | using BOOST_NS::adaptors::slice; 36 | using std::remove_if; 37 | 38 | PXR_NAMESPACE_OPEN_SCOPE; 39 | 40 | template 41 | UsdQt_MetadataProxyRefPtr 42 | UsdQt_ObjectProxyBase::CreateMetadataProxy(const TfToken& field) { 43 | std::vector parentObjects; 44 | for (const T& objectIt : _GetObjects()) { 45 | UsdObject object = objectIt.template As(); 46 | parentObjects.push_back(object); 47 | } 48 | return UsdQt_MetadataProxy::New(parentObjects, field); 49 | } 50 | 51 | template 52 | bool UsdQt_ObjectProxyBase::ContainsPathOrDescendent( 53 | const SdfPathVector& potentialPaths) const { 54 | for (auto path : potentialPaths) { 55 | for (auto object : _GetObjects()) { 56 | // return true if the paths are equal or of if the shared 57 | // // common parent is the path we are testing against. 58 | if (!path.IsEmpty() && 59 | object.GetPath().GetCommonPrefix(path) == path) { 60 | return true; 61 | } 62 | } 63 | } 64 | return false; 65 | } 66 | 67 | template 68 | bool UsdQt_ObjectProxyBase::ContainsPath( 69 | const SdfPathVector& potentialPaths) const { 70 | for (auto path : potentialPaths) { 71 | for (auto object : _GetObjects()) { 72 | if (!path.IsEmpty() && object.GetPath() == path) return true; 73 | } 74 | } 75 | return false; 76 | } 77 | 78 | template 79 | TfTokenVector UsdQt_ObjectProxyBase::GetMetadataFields() const { 80 | if (_GetObjects().size() < 1) { 81 | return TfTokenVector(); 82 | } 83 | 84 | TfTokenVector fields = SdfSchema::GetInstance().GetMetadataFields(SpecType); 85 | auto newFieldsEnd = 86 | std::remove_if(fields.begin(), fields.end(), [&](const TfToken& field) { 87 | return SdfSchema::GetInstance().GetMetadataFieldDisplayGroup( 88 | SdfSpecTypeAttribute, field) == TfToken("deprecated"); 89 | }); 90 | fields.erase(newFieldsEnd, fields.end()); 91 | std::sort(fields.begin(), fields.end()); 92 | return fields; 93 | } 94 | 95 | template 96 | TfToken UsdQt_ObjectProxyBase::GetName() const { 97 | if (_GetObjects().size() < 1) { 98 | return TfToken(); 99 | } 100 | TfToken sharedName = _GetObjects()[0].GetName(); 101 | for (const auto& object : slice(_GetObjects(), 1, _GetObjects().size())) { 102 | if (object.GetName() != sharedName) { 103 | return TfToken(); 104 | } 105 | } 106 | return sharedName; 107 | } 108 | 109 | template 110 | std::string UsdQt_ObjectProxyBase::GetDocumentation() const { 111 | if (_GetObjects().size() < 1) return std::string(); 112 | return _GetObjects()[0].GetDocumentation(); 113 | } 114 | 115 | template 116 | bool UsdQt_ObjectProxyBase::IsValid() const { 117 | return std::all_of( 118 | this->_GetObjects().begin(), this->_GetObjects().end(), 119 | [](const UsdObject& object) { return object.IsValid(); }); 120 | } 121 | 122 | template 123 | size_t UsdQt_ObjectProxyBase::GetSize() const { 124 | return _GetObjects().size(); 125 | } 126 | 127 | template 128 | bool UsdQt_PropertyProxyBase::IsAuthored() const { 129 | return std::any_of( 130 | this->_GetObjects().begin(), this->_GetObjects().end(), 131 | [](const UsdProperty& property) { return property.IsAuthored(); }); 132 | } 133 | 134 | template 135 | bool UsdQt_PropertyProxyBase::IsAuthoredAt( 136 | const UsdEditTarget& editTarget) const { 137 | return std::any_of(this->_GetObjects().begin(), this->_GetObjects().end(), 138 | [&editTarget](const T& property) { 139 | return property.IsAuthoredAt(editTarget); 140 | }); 141 | } 142 | 143 | template 144 | bool UsdQt_PropertyProxyBase::IsDefined() const { 145 | return std::any_of(this->_GetObjects().begin(), this->_GetObjects().end(), 146 | [](const T& property) { return property.IsDefined(); }); 147 | } 148 | 149 | template class UsdQt_ObjectProxyBase; 150 | template class UsdQt_ObjectProxyBase; 151 | template class UsdQt_ObjectProxyBase; 152 | 153 | template class UsdQt_PropertyProxyBase; 154 | template class UsdQt_PropertyProxyBase; 155 | 156 | 157 | PXR_NAMESPACE_CLOSE_SCOPE 158 | -------------------------------------------------------------------------------- /pxr/usdQt/variantSetsProxy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "variantSetsProxy.h" 26 | 27 | #include 28 | 29 | #include "utils.h" 30 | 31 | PXR_NAMESPACE_OPEN_SCOPE 32 | 33 | using BOOST_NS::adaptors::slice; 34 | 35 | UsdQt_VariantSetsProxy::UsdQt_VariantSetsProxy( 36 | const std::vector& prims) 37 | : _prims(prims) {} 38 | 39 | UsdQt_VariantSetsProxyRefPtr UsdQt_VariantSetsProxy::New( 40 | const std::vector& prims) { 41 | return TfCreateRefPtr(new UsdQt_VariantSetsProxy(prims)); 42 | } 43 | 44 | std::vector UsdQt_VariantSetsProxy::GetNames() const { 45 | std::vector names; 46 | if (!GetNames(&names)) { 47 | return std::vector(); 48 | } 49 | return names; 50 | } 51 | 52 | bool UsdQt_VariantSetsProxy::GetNames(std::vector* names) const { 53 | if (!names) return false; 54 | if (_prims.size() < 1) { 55 | return true; 56 | } 57 | if (!_prims[0]) { 58 | names->clear(); 59 | return false; 60 | } 61 | std::vector sharedNames = 62 | _prims[0].GetVariantSets().GetNames(); 63 | auto sharedNamesEnd = sharedNames.end(); 64 | 65 | for (const auto& prim : slice(_prims, 1, _prims.size())) { 66 | if (!prim) { 67 | names->clear(); 68 | return false; 69 | } 70 | sharedNamesEnd = remove_if( 71 | sharedNames.begin(), sharedNamesEnd, [&](const std::string& name) { 72 | return !prim.GetVariantSets().HasVariantSet(name); 73 | }); 74 | } 75 | sharedNames.erase(sharedNamesEnd, sharedNames.end()); 76 | names->assign(sharedNames.begin(), sharedNames.end()); 77 | return true; 78 | } 79 | 80 | void UsdQt_VariantSetsProxy::AddVariantSet(const std::string& name) { 81 | for (auto& prim : _prims) { 82 | #ifdef PXR_USDQT_APPEND_NOT_ADD 83 | prim.GetVariantSets().AppendVariantSet(name); 84 | #else 85 | prim.GetVariantSets().AddVariantSet(name); 86 | #endif 87 | } 88 | } 89 | 90 | UsdQt_VariantSetProxyRefPtr UsdQt_VariantSetsProxy::CreateVariantSetProxy( 91 | const std::string& name) { 92 | std::vector sharedSets; 93 | 94 | for (const auto& prim : _prims) { 95 | if (!prim.GetVariantSets().HasVariantSet(name)) return NULL; 96 | sharedSets.push_back(prim.GetVariantSets().GetVariantSet(name)); 97 | } 98 | return UsdQt_VariantSetProxy::New(sharedSets); 99 | } 100 | 101 | UsdQt_VariantSetProxy::UsdQt_VariantSetProxy( 102 | const std::vector& variantSets) 103 | : _variantSets(variantSets) {} 104 | 105 | UsdQt_VariantSetProxyRefPtr UsdQt_VariantSetProxy::New( 106 | const std::vector& variantSets) { 107 | return TfCreateRefPtr(new UsdQt_VariantSetProxy(variantSets)); 108 | } 109 | 110 | std::string UsdQt_VariantSetProxy::GetVariantSelection() const { 111 | if (_variantSets.size() < 1) { 112 | return std::string(); 113 | } 114 | std::string sharedName = _variantSets[0].GetVariantSelection(); 115 | 116 | for (const auto& variantSet : slice(_variantSets, 1, _variantSets.size())) { 117 | if (variantSet.GetVariantSelection() != sharedName) { 118 | return std::string(); 119 | } 120 | } 121 | 122 | return sharedName; 123 | } 124 | 125 | bool UsdQt_VariantSetProxy::ClearVariantSelection() { 126 | bool success = true; 127 | for (auto& variantSet : _variantSets) { 128 | success &= variantSet.ClearVariantSelection(); 129 | } 130 | return success; 131 | } 132 | 133 | std::vector UsdQt_VariantSetProxy::GetVariantNames() const { 134 | if (_variantSets.size() < 1) { 135 | return std::vector(); 136 | } 137 | std::vector sharedNames = _variantSets[0].GetVariantNames(); 138 | auto sharedNamesEnd = sharedNames.end(); 139 | for (const auto& variantSet : slice(_variantSets, 1, _variantSets.size())) { 140 | std::vector names = variantSet.GetVariantNames(); 141 | sharedNamesEnd = remove_if( 142 | sharedNames.begin(), sharedNamesEnd, [&](const std::string& name) { 143 | return UsdQt_ItemNotInVector(names, name); 144 | }); 145 | } 146 | sharedNames.erase(sharedNamesEnd, sharedNames.end()); 147 | return sharedNames; 148 | } 149 | 150 | std::string UsdQt_VariantSetProxy::GetName() const { 151 | if (_variantSets.size() < 1) { 152 | return std::string(); 153 | } 154 | std::string sharedName = _variantSets[0].GetName(); 155 | 156 | for (const auto& variantSet : slice(_variantSets, 1, _variantSets.size())) { 157 | if (variantSet.GetName() != sharedName) { 158 | return std::string(); 159 | } 160 | } 161 | return sharedName; 162 | } 163 | 164 | bool UsdQt_VariantSetProxy::SetVariantSelection(const std::string& variant) { 165 | bool success = true; 166 | for (auto& variantSet : _variantSets) { 167 | success &= variantSet.SetVariantSelection(variant); 168 | } 169 | return success; 170 | } 171 | 172 | bool UsdQt_VariantSetProxy::AddVariant(const std::string& variant) { 173 | bool success = true; 174 | for (auto& variantSet : _variantSets) { 175 | success &= variantSet.AddVariant(variant); 176 | } 177 | return success; 178 | } 179 | 180 | PXR_NAMESPACE_CLOSE_SCOPE 181 | -------------------------------------------------------------------------------- /pxr/usdQt/undoStateDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 USDQT_UNDOSTATEDELEGATE_H 25 | #define USDQT_UNDOSTATEDELEGATE_H 26 | 27 | #include 28 | 29 | #include "pxr/pxr.h" 30 | #include "pxr/base/tf/declarePtrs.h" 31 | 32 | #include "pxr/usd/sdf/layerStateDelegate.h" 33 | #include "pxr/usd/sdf/path.h" 34 | 35 | #include "pxr/usd/usd/attribute.h" 36 | #include "pxr/usd/usd/prim.h" 37 | #include "pxr/usd/usd/property.h" 38 | 39 | PXR_NAMESPACE_OPEN_SCOPE 40 | 41 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQt_UndoStateDelegate); 42 | TF_DECLARE_WEAK_AND_REF_PTRS(UsdQtUndoRouter); // forward declaration 43 | 44 | /// \class UsdQt_UndoStateDelegate 45 | /// 46 | /// The layer state delegate is a class that forwards the inverse of a given 47 | /// edit to a UsdQtUndoRouter. To instantiate this class, create a 48 | /// UsdQtUndoRouterPtr, and call yourRouter->TrackLayer(yourLayer). 49 | class UsdQt_UndoStateDelegate : public SdfLayerStateDelegateBase { 50 | private: 51 | SdfLayerHandle _layer; 52 | bool _dirty; 53 | 54 | static UsdQt_UndoStateDelegateRefPtr New(); 55 | 56 | UsdQt_UndoStateDelegate(); 57 | 58 | void _RouteInverse(std::function inverse); 59 | 60 | virtual bool _IsDirty() override; 61 | virtual void _MarkCurrentStateAsClean() override; 62 | virtual void _MarkCurrentStateAsDirty() override; 63 | 64 | bool _InvertSetField(const SdfPath& path, const TfToken& fieldName, 65 | const VtValue& inverse); 66 | 67 | bool _InvertSetFieldDictValueByKey(const SdfPath& path, 68 | const TfToken& fieldName, 69 | const TfToken& keyPath, 70 | const VtValue& inverse); 71 | bool _InvertSetTimeSample(const SdfPath& path, double time, 72 | const VtValue& inverse); 73 | bool _InvertCreateSpec(const SdfPath& path, bool inert); 74 | bool _InvertDeleteSpec(const SdfPath& path, bool inert, 75 | SdfSpecType deletedSpecType, 76 | const SdfDataRefPtr& deletedData); 77 | bool _InvertPushTokenChild(const SdfPath& parentPath, 78 | const TfToken& fieldName, const TfToken& value); 79 | bool _InvertPopTokenChild(const SdfPath& parentPath, 80 | const TfToken& fieldName, const TfToken& value); 81 | bool _InvertPushPathChild(const SdfPath& parentPath, 82 | const TfToken& fieldName, const SdfPath& value); 83 | bool _InvertPopPathChild(const SdfPath& parentPath, 84 | const TfToken& fieldName, const SdfPath& value); 85 | 86 | bool _InvertMoveSpec(const SdfPath& oldPath, const SdfPath& newPath); 87 | 88 | void _OnSetLayer(const SdfLayerHandle& layer) override; 89 | 90 | void _OnSetField(const SdfPath& path, const TfToken& fieldName, 91 | const VtValue& value) override; 92 | virtual void _OnSetField(const SdfPath& path, 93 | const TfToken& fieldName, 94 | const SdfAbstractDataConstValue& value) override; 95 | void _OnSetFieldImpl(const SdfPath& path, 96 | const TfToken& fieldName); 97 | 98 | virtual void _OnSetFieldDictValueByKey(const SdfPath& path, 99 | const TfToken& fieldName, 100 | const TfToken& keyPath, 101 | const VtValue& value) override; 102 | virtual void _OnSetFieldDictValueByKey( 103 | const SdfPath& path, const TfToken& fieldName, 104 | const TfToken& keyPath, 105 | const SdfAbstractDataConstValue& value) override; 106 | void _OnSetFieldDictValueByKeyImpl(const SdfPath& path, 107 | const TfToken& fieldName, 108 | const TfToken& keyPath); 109 | 110 | virtual void _OnSetTimeSample(const SdfPath& path, double time, 111 | const VtValue& value) override; 112 | 113 | virtual void _OnSetTimeSample( 114 | const SdfPath& path, double time, 115 | const SdfAbstractDataConstValue& value) override; 116 | void _OnSetTimeSampleImpl(const SdfPath& path, double time); 117 | 118 | virtual void _OnCreateSpec(const SdfPath& path, SdfSpecType specType, 119 | bool inert) override; 120 | 121 | virtual void _OnDeleteSpec(const SdfPath& path, bool inert) override; 122 | 123 | virtual void _OnMoveSpec(const SdfPath& oldPath, 124 | const SdfPath& newPath) override; 125 | virtual void _OnPushChild(const SdfPath& parentPath, 126 | const TfToken& fieldName, 127 | const TfToken& value) override; 128 | virtual void _OnPushChild(const SdfPath& parentPath, 129 | const TfToken& fieldName, 130 | const SdfPath& value) override; 131 | 132 | virtual void _OnPopChild(const SdfPath& parentPath, 133 | const TfToken& fieldName, 134 | const TfToken& oldValue) override; 135 | 136 | virtual void _OnPopChild(const SdfPath& parentPath, 137 | const TfToken& fieldName, 138 | const SdfPath& oldValue) override; 139 | friend class UsdQtUndoRouter; 140 | }; 141 | 142 | PXR_NAMESPACE_CLOSE_SCOPE 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /pxr/usdQt/metadataProxy.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 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 | 25 | #include "metadataProxy.h" 26 | 27 | #include 28 | 29 | 30 | PXR_NAMESPACE_OPEN_SCOPE 31 | 32 | using BOOST_NS::adaptors::slice; 33 | 34 | UsdQt_MetadataProxy::UsdQt_MetadataProxy(const std::vector& objects, 35 | TfToken field) 36 | : _objects(objects), _field(field) {} 37 | 38 | UsdQt_MetadataProxyRefPtr UsdQt_MetadataProxy::New( 39 | const std::vector& objects, TfToken field) { 40 | return TfCreateRefPtr(new UsdQt_MetadataProxy(objects, field)); 41 | } 42 | 43 | TfType UsdQt_MetadataProxy::GetType() const { 44 | return SdfSchema::GetInstance().GetFallback(_field).GetType(); 45 | } 46 | 47 | TfToken UsdQt_MetadataProxy::GetName() const { return _field; } 48 | 49 | bool UsdQt_MetadataProxy::GetValue(VtValue* result) const { 50 | if (_objects.size() < 1) { 51 | (*result) = VtValue(); 52 | return true; 53 | } 54 | VtValue sharedValue; 55 | _objects[0].GetMetadata(_field, &sharedValue); 56 | for (const auto& object : slice(_objects, 1, _objects.size())) { 57 | VtValue value; 58 | if (!object.GetMetadata(_field, &value) || value != sharedValue) { 59 | (*result) = VtValue(); 60 | return false; 61 | } 62 | } 63 | (*result) = sharedValue; 64 | return true; 65 | } 66 | 67 | bool UsdQt_MetadataProxy::SetValue(const VtValue& value) { 68 | bool success = true; 69 | for (auto& object : _objects) { 70 | success &= object.SetMetadata(_field, value); 71 | } 72 | return success; 73 | } 74 | 75 | bool UsdQt_MetadataProxy::ClearValue() { 76 | bool success = true; 77 | for (auto& object : _objects) { 78 | success &= object.ClearMetadata(_field); 79 | } 80 | return success; 81 | }; 82 | 83 | std::vector UsdQt_MetadataProxy::GetDictKeys() const { 84 | if (GetType() != TfType::FindByName("VtDictionary")) { 85 | TF_CODING_ERROR("Metadata isn't a VtDictionary."); 86 | return std::vector(); 87 | } 88 | if (_objects.size() == 0) return std::vector(); 89 | VtDictionary dict; 90 | if (!_objects[0].GetMetadata(_field, &dict)) 91 | return std::vector(); 92 | 93 | std::vector sharedKeys; 94 | for (const auto& key : dict) { 95 | sharedKeys.push_back(key.first); 96 | } 97 | 98 | auto sharedKeysEnd = sharedKeys.end(); 99 | 100 | for (const auto& object : slice(_objects, 1, _objects.size())) { 101 | sharedKeysEnd = remove_if(sharedKeys.begin(), sharedKeysEnd, 102 | [&](const std::string& key) { 103 | return !object.HasMetadataDictKey(_field, TfToken(key)); 104 | }); 105 | } 106 | sharedKeys.erase(sharedKeysEnd, sharedKeys.end()); 107 | return sharedKeys; 108 | } 109 | 110 | UsdQt_MetadataDictKeyProxyRefPtr 111 | UsdQt_MetadataProxy::CreateMetadataDictKeyProxy(const TfToken& dictKey) { 112 | if (GetType() != TfType::FindByName("VtDictionary")) { 113 | return NULL; 114 | } 115 | std::vector parentObjects; 116 | for (const auto& object : _objects) { 117 | if (!object.HasMetadataDictKey(_field, dictKey)) return NULL; 118 | parentObjects.push_back(object.As()); 119 | } 120 | return UsdQt_MetadataDictKeyProxy::New(parentObjects, _field, dictKey); 121 | } 122 | 123 | UsdQt_MetadataDictKeyProxy::UsdQt_MetadataDictKeyProxy( 124 | const std::vector& objects, TfToken field, TfToken dictKey) 125 | : _objects(objects), _field(field), _dictKey(dictKey) {} 126 | 127 | UsdQt_MetadataDictKeyProxyRefPtr UsdQt_MetadataDictKeyProxy::New( 128 | const std::vector& objects, TfToken field, TfToken dictKey) { 129 | return TfCreateRefPtr( 130 | new UsdQt_MetadataDictKeyProxy(objects, field, dictKey)); 131 | } 132 | 133 | TfToken UsdQt_MetadataDictKeyProxy::GetEntryName() const { return _dictKey; } 134 | 135 | TfToken UsdQt_MetadataDictKeyProxy::GetDictName() const { return _field; } 136 | 137 | bool UsdQt_MetadataDictKeyProxy::GetValue(VtValue* result) const { 138 | if (_objects.size() < 1) { 139 | (*result) = VtValue(); 140 | return true; 141 | } 142 | VtValue sharedValue; 143 | _objects[0].GetMetadataByDictKey(_field, _dictKey, &sharedValue); 144 | for (const auto& object : slice(_objects, 1, _objects.size())) { 145 | VtValue value; 146 | if (!object.GetMetadataByDictKey(_field, _dictKey, &value) || 147 | value != sharedValue) { 148 | (*result) = VtValue(); 149 | return false; 150 | } 151 | } 152 | (*result) = sharedValue; 153 | return true; 154 | } 155 | 156 | bool UsdQt_MetadataDictKeyProxy::SetValue(const VtValue& value) { 157 | bool success = true; 158 | for (auto& object : _objects) { 159 | success &= object.SetMetadataByDictKey(_field, _dictKey, value); 160 | } 161 | return success; 162 | } 163 | 164 | bool UsdQt_MetadataDictKeyProxy::ClearValue() { 165 | bool success = true; 166 | for (auto& object : _objects) { 167 | success &= object.ClearMetadataByDictKey(_field, _dictKey); 168 | } 169 | return success; 170 | } 171 | 172 | /// \brief Get the type of the metdata field for this proxy. 173 | TfType UsdQt_MetadataDictKeyProxy::GetType() const { 174 | VtValue temp; 175 | if (GetValue(&temp)) return temp.GetType(); 176 | return TfType(); 177 | } 178 | 179 | PXR_NAMESPACE_CLOSE_SCOPE 180 | --------------------------------------------------------------------------------