├── .gitattributes
├── .gitignore
├── DOCS.md
├── LICENSE.md
├── README.md
├── config
└── readme.md
├── install.gif
├── install.mel
├── install.py
├── install.txt
└── src
├── mutils
├── README.md
├── __init__.py
├── animation.py
├── attribute.py
├── cmds.py
├── decorators.py
├── gui
│ ├── __init__.py
│ ├── framerangemenu.py
│ ├── modelpanelwidget.py
│ ├── thumbnailcapturedialog.py
│ └── thumbnailcapturemenu.py
├── matchnames.py
├── mirrortable.py
├── namespace.py
├── node.py
├── playblast.py
├── pose.py
├── scriptjob.py
├── selectionset.py
├── tests
│ ├── __init__.py
│ ├── data
│ │ ├── anim.ma
│ │ ├── animation.anim
│ │ ├── pose.json
│ │ ├── sphere.ma
│ │ ├── test.ma
│ │ ├── test_anim.ma
│ │ ├── test_bake_connected.anim
│ │ │ ├── animation.ma
│ │ │ ├── animation.mb
│ │ │ └── pose.json
│ │ ├── test_bake_connected.ma
│ │ ├── test_load_insert.anim
│ │ │ ├── animation.ma
│ │ │ ├── animation.mb
│ │ │ └── pose.json
│ │ ├── test_load_replace.anim
│ │ │ ├── animation.ma
│ │ │ ├── animation.mb
│ │ │ └── pose.json
│ │ ├── test_load_replace_completely.anim
│ │ │ ├── animation.ma
│ │ │ ├── animation.mb
│ │ │ └── pose.json
│ │ ├── test_mirror_tables.ma
│ │ ├── test_non_unique_names.ma
│ │ ├── test_non_unique_names.pose
│ │ ├── test_older_version.anim
│ │ │ ├── .studioLibrary
│ │ │ │ └── record.dict
│ │ │ ├── animation.ma
│ │ │ └── pose.dict
│ │ ├── test_older_version.dict
│ │ ├── test_pose.ma
│ │ ├── test_pose.pose
│ │ └── test_poseplugin.pose
│ │ │ └── .studiolibrary
│ │ │ └── record.dict
│ ├── run.py
│ ├── test_anim.py
│ ├── test_attribute.py
│ ├── test_base.py
│ ├── test_match.py
│ ├── test_mirrortable.py
│ ├── test_pose.py
│ └── test_utils.py
└── transferobject.py
├── studiolibrary
├── __init__.py
├── config.py
├── config
│ └── default.json
├── folderitem.py
├── library.py
├── libraryitem.py
├── librarywindow.py
├── main.py
├── resource.py
├── resource
│ ├── css
│ │ └── default.css
│ ├── fonts
│ │ ├── LICENSE.txt
│ │ ├── OpenSans-Bold.ttf
│ │ ├── OpenSans-BoldItalic.ttf
│ │ ├── OpenSans-ExtraBold.ttf
│ │ ├── OpenSans-ExtraBoldItalic.ttf
│ │ ├── OpenSans-Italic.ttf
│ │ ├── OpenSans-Light.ttf
│ │ ├── OpenSans-LightItalic.ttf
│ │ ├── OpenSans-Regular.ttf
│ │ ├── OpenSans-SemiBold.ttf
│ │ └── OpenSans-SemiBoldItalic.ttf
│ └── icons
│ │ ├── add.png
│ │ ├── add_28.png
│ │ ├── archive.svg
│ │ ├── arrows-rotate.svg
│ │ ├── asset.svg
│ │ ├── assets.svg
│ │ ├── bars.svg
│ │ ├── blank.png
│ │ ├── book.svg
│ │ ├── branch_closed_black.png
│ │ ├── branch_closed_white.png
│ │ ├── branch_open_black.png
│ │ ├── branch_open_white.png
│ │ ├── camera-alt.svg
│ │ ├── camera.svg
│ │ ├── cancel.png
│ │ ├── caret-down.svg
│ │ ├── caret-right.svg
│ │ ├── character.svg
│ │ ├── check_box_checked_black.png
│ │ ├── check_box_checked_white.png
│ │ ├── check_box_unchecked_black.png
│ │ ├── check_box_unchecked_white.png
│ │ ├── circle.png
│ │ ├── circle.svg
│ │ ├── cloud.svg
│ │ ├── cog.png
│ │ ├── columns-3.svg
│ │ ├── critical.png
│ │ ├── cross.png
│ │ ├── database.svg
│ │ ├── delete.png
│ │ ├── drop_arrow_black.png
│ │ ├── drop_arrow_white.png
│ │ ├── environment.svg
│ │ ├── error.png
│ │ ├── expand.svg
│ │ ├── eye-slash.svg
│ │ ├── eye.svg
│ │ ├── face.svg
│ │ ├── favorite.svg
│ │ ├── file-alt.svg
│ │ ├── file.svg
│ │ ├── filter.svg
│ │ ├── folder.svg
│ │ ├── folder_collapsed.png
│ │ ├── folder_expanded.png
│ │ ├── folder_item.png
│ │ ├── folder_open.png
│ │ ├── folder_open.svg
│ │ ├── globe.svg
│ │ ├── groupby.png
│ │ ├── hand.svg
│ │ ├── header.png
│ │ ├── icon.png
│ │ ├── image.png
│ │ ├── inbox.svg
│ │ ├── info.png
│ │ ├── layers.svg
│ │ ├── lock.svg
│ │ ├── logo.png
│ │ ├── logo_high.png
│ │ ├── logo_white.png
│ │ ├── magnifying-glass.svg
│ │ ├── plus-large.svg
│ │ ├── plus.svg
│ │ ├── preview_placeholder.png
│ │ ├── question.png
│ │ ├── radio_button_checked_black.png
│ │ ├── radio_button_checked_white.png
│ │ ├── radio_button_unchecked_black.png
│ │ ├── radio_button_unchecked_white.png
│ │ ├── search.png
│ │ ├── search.svg
│ │ ├── settings.png
│ │ ├── share.svg
│ │ ├── shot.svg
│ │ ├── sliders.svg
│ │ ├── sortby.png
│ │ ├── sync.png
│ │ ├── tag.png
│ │ ├── thumbnail.png
│ │ ├── thumbnail_solid.png
│ │ ├── times.svg
│ │ ├── trash.svg
│ │ ├── tree.svg
│ │ ├── user.svg
│ │ ├── users.svg
│ │ ├── vehicle.svg
│ │ ├── video.svg
│ │ ├── view_all.png
│ │ ├── view_compact.png
│ │ ├── view_settings.png
│ │ ├── warning.png
│ │ └── xmark.svg
├── utils.py
└── widgets
│ ├── PlaceholderWidget.ui
│ ├── PreviewWidget.ui
│ ├── __init__.py
│ ├── colorpicker.py
│ ├── fieldwidgets.py
│ ├── filterbymenu.py
│ ├── formwidget.py
│ ├── groupboxwidget.py
│ ├── groupbymenu.py
│ ├── iconpicker.py
│ ├── itemswidget
│ ├── __init__.py
│ ├── groupitem.py
│ ├── item.py
│ ├── itemdelegate.py
│ ├── itemswidget.py
│ ├── itemviewmixin.py
│ ├── listview.py
│ └── treewidget.py
│ ├── librariesmenu.py
│ ├── lightbox.py
│ ├── lineedit.py
│ ├── menubarwidget.py
│ ├── messagebox.py
│ ├── placeholderwidget.py
│ ├── previewwidget.py
│ ├── searchwidget.py
│ ├── separatoraction.py
│ ├── sequencewidget.py
│ ├── settings.py
│ ├── sidebarwidget
│ ├── __init__.py
│ ├── sidebarwidget.py
│ └── sidebarwidgetitem.py
│ ├── slideraction.py
│ ├── sortbymenu.py
│ ├── statuswidget.py
│ ├── themesmenu.py
│ └── toastwidget.py
├── studiolibrarymaya
├── BaseLoadWidget.ui
├── BaseSaveWidget.ui
├── README.md
├── __init__.py
├── animitem.py
├── baseitem.py
├── baseloadwidget.py
├── basesavewidget.py
├── exampleitem.py
├── icons
│ ├── animation.png
│ ├── arrow.png
│ ├── file.png
│ ├── insert.png
│ ├── insertConnect.png
│ ├── merge.png
│ ├── mergeConnect.png
│ ├── mirrortable.png
│ ├── pose.png
│ ├── replace.png
│ ├── replaceCompletely.png
│ ├── replaceConnect.png
│ ├── selectionSet.png
│ └── selectionSet2.png
├── mayafileitem.py
├── mayalibrarywindow.py
├── mirroritem.py
├── poseitem.py
├── setsitem.py
└── setsmenu.py
├── studioqt
├── __init__.py
├── color.py
├── decorators.py
├── icon.py
├── imagesequence.py
├── menu.py
├── pixmap.py
├── stylesheet.py
└── utils.py
└── studiovendor
├── Qt.py
├── __init__.py
└── six.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | packages/mutils/tests/data/* linguist-vendored
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 | config/config.json
6 |
7 | # C extensions
8 | *.so
9 |
10 | # Distribution / packaging
11 | .Python
12 | env/
13 | build/
14 | develop-eggs/
15 | dist/
16 | downloads/
17 | eggs/
18 | .eggs/
19 | .idea/
20 | lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .coverage
43 | .coverage.*
44 | .cache
45 | nosetests.xml
46 | coverage.xml
47 | *,cover
48 | .hypothesis/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 |
58 | # Flask instance folder
59 | instance/
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # IPython Notebook
71 | .ipynb_checkpoints
72 |
73 | # pyenv
74 | .python-version
75 |
76 | # celery beat schedule file
77 | celerybeat-schedule
78 |
79 | # dotenv
80 | .env
81 |
82 | # virtualenv
83 | venv/
84 | ENV/
85 |
86 | # Spyder project settings
87 | .spyderproject
88 |
89 | # Rope project settings
90 | .ropeproject
91 |
92 | # =========================
93 | # Operating System Files
94 | # =========================
95 |
96 | # OSX
97 | # =========================
98 |
99 | .DS_Store
100 | .AppleDouble
101 | .LSOverride
102 |
103 | # Thumbnails
104 | ._*
105 |
106 | # Files that might appear in the root of a volume
107 | .DocumentRevisions-V100
108 | .fseventsd
109 | .Spotlight-V100
110 | .TemporaryItems
111 | .Trashes
112 | .VolumeIcon.icns
113 |
114 | # Directories potentially created on remote AFP share
115 | .AppleDB
116 | .AppleDesktop
117 | Network Trash Folder
118 | Temporary Items
119 | .apdisk
120 |
121 | # Windows
122 | # =========================
123 |
124 | # Windows image file caches
125 | Thumbs.db
126 | ehthumbs.db
127 |
128 | # Folder config file
129 | Desktop.ini
130 |
131 | # Recycle Bin used on file shares
132 | $RECYCLE.BIN/
133 |
134 | # Windows Installer files
135 | *.cab
136 | *.msi
137 | *.msm
138 | *.msp
139 |
140 | # Windows shortcuts
141 | *.lnk
142 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Studio Library is a python-based Qt tool for managing poses and animation in Maya.
6 |
7 | ## Features
8 |
9 | * Save poses and animation
10 | * Mirror poses and animation
11 | * Create easy to use selection sets
12 | * MMB drag for fast pose blending
13 | * LMB drag and drop to organize items
14 | * Insert, merge and replace animation
15 | * Supports Windows, Linux and OSX
16 | * Supports Maya 2018+
17 |
18 | ## Tutorials
19 |
20 | * [How to use poses](https://www.youtube.com/watch?v=lpaWrT7VXfM)
21 | * [How to use selection sets](https://www.youtube.com/watch?v=xejWubal_j8)
22 | * [How to use mirror tables](https://www.youtube.com/watch?v=kCv0XleJfjU&t=3s)
23 |
24 | ## Installation
25 |
26 | 1. Download and unzip the *studiolibrary.zip* file from [github releases](https://github.com/krathjen/studiolibrary/releases) or [website](http://www.studiolibrary.com/download).
27 |
28 | 2. Drag and drop the "studiolibrary/install.mel" file onto the Maya viewport.
29 |
30 | 3. Click the Studio Library icon on the shelf to run.
31 |
32 | Tip: If you would like to share the Studio Library with other users then
33 | place the unzipped "studiolibrary" folder on a network drive.
34 |
35 |
36 |
37 |
38 |
39 | ## Documentation
40 |
41 | Find the latest documentation [here](DOCS.md).
42 |
43 |
44 | ## Contributing
45 |
46 | Contributions to Studio Library are always welcome! Whether it's reporting bugs, feature requests, discussing ideas or committing code.
47 |
48 | We follow the below guides for...
49 |
50 | * [Commit messages style](https://github.com/erlang/otp/wiki/Writing-good-commit-messages)
51 | * [GitHub Forking Workflow](https://gist.github.com/Chaser324/ce0505fbed06b947d962)
52 | * [Python Qt Style Guidelines](http://bitesofcode.blogspot.co.uk/2011/10/pyqt-coding-style-guidelines.html)
53 |
54 | ## License
55 |
56 | The Studio Library is free to use in production under the GNU Lesser General Public License v3.0.
57 | For more information please click [here](LICENSE.md).
58 |
59 |
60 | ## Support
61 |
62 | Comments, suggestions and bug reports are welcome.
63 |
64 | Feel free to submit any issues with the error message and a detailed step by step process of how you got the error in [github issues](https://github.com/krathjen/studiolibrary/issues/new) or contact [support@studiolibrary.com](support@studiolibrary.com).
--------------------------------------------------------------------------------
/config/readme.md:
--------------------------------------------------------------------------------
1 |
2 | ## Config
3 |
4 | There are two ways to create a custom config.
5 |
6 | 1. You can create a config.json file in this directory.
7 | The config.json file will override any keys in the [default.json](../src/studiolibrary/config/default.json) file
8 | and will be ignored by git.
9 |
10 | 2. The other way is to create an environment variable with the name
11 | STUDIO_LIBRARY_CONFIG_PATH. The value of this variable should be the
12 | full path to your config.json file.
13 |
14 | The config uses the json file type with basic support for comments using "//".
15 |
16 | ##### Example:
17 |
18 | ```javascript
19 | // config.json
20 | {
21 | // The maximum walking depth from the root directory
22 | "recursiveSearchDepth": 4
23 | }
24 | ```
25 |
26 |
--------------------------------------------------------------------------------
/install.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/install.gif
--------------------------------------------------------------------------------
/install.mel:
--------------------------------------------------------------------------------
1 | /*
2 | Drag and drop for Maya 2016+
3 | */
4 |
5 | global proc studioLibraryInstall() {
6 | string $whatIs = `whatIs studioLibraryInstall`;
7 | string $path = `substring $whatIs 25 999`;
8 | string $filename = `substitute "install.mel" $path "install.py"`;;
9 | python("import imp;imp.load_source('_studioLibraryInstall', '"+$filename+"')");
10 | }
11 |
12 | studioLibraryInstall();
--------------------------------------------------------------------------------
/install.py:
--------------------------------------------------------------------------------
1 | # Copyright 2017 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or
4 | # modify it under the terms of the GNU Lesser General Public
5 | # License as published by the Free Software Foundation, either
6 | # version 3 of the License, or (at your option) any later version.
7 | # This library is distributed in the hope that it will be useful,
8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 | # Lesser General Public License for more details.
11 | # You should have received a copy of the GNU Lesser General Public
12 | # License along with this library. If not, see .
13 | """
14 | Drag and drop for Maya 2018+
15 | """
16 | import os
17 | import sys
18 |
19 |
20 | try:
21 | import maya.mel
22 | import maya.cmds
23 | isMaya = True
24 | except ImportError:
25 | isMaya = False
26 |
27 |
28 | def onMayaDroppedPythonFile(*args, **kwargs):
29 | """This function is only supported since Maya 2017 Update 3"""
30 | pass
31 |
32 |
33 | def _onMayaDropped():
34 | """Dragging and dropping this file into the scene executes the file."""
35 |
36 | srcPath = os.path.join(os.path.dirname(__file__), 'src')
37 | iconPath = os.path.join(srcPath, 'studiolibrary', 'resource', 'icons', 'icon.png')
38 |
39 | srcPath = os.path.normpath(srcPath)
40 | iconPath = os.path.normpath(iconPath)
41 |
42 | if not os.path.exists(iconPath):
43 | raise IOError('Cannot find ' + iconPath)
44 |
45 | for path in sys.path:
46 | if os.path.exists(path + '/studiolibrary/__init__.py'):
47 | maya.cmds.warning('Studio Library is already installed at ' + path)
48 |
49 | command = '''
50 | # -----------------------------------
51 | # Studio Library
52 | # www.studiolibrary.com
53 | # -----------------------------------
54 |
55 | import os
56 | import sys
57 |
58 | if not os.path.exists(r'{path}'):
59 | raise IOError(r'The source path "{path}" does not exist!')
60 |
61 | if r'{path}' not in sys.path:
62 | sys.path.insert(0, r'{path}')
63 |
64 | import studiolibrary
65 | studiolibrary.main()
66 | '''.format(path=srcPath)
67 |
68 | shelf = maya.mel.eval('$gShelfTopLevel=$gShelfTopLevel')
69 | parent = maya.cmds.tabLayout(shelf, query=True, selectTab=True)
70 | maya.cmds.shelfButton(
71 | command=command,
72 | annotation='Studio Library',
73 | sourceType='Python',
74 | image=iconPath,
75 | image1=iconPath,
76 | parent=parent
77 | )
78 |
79 | # print("\n// Studio Library has been added to current shelf.")
80 |
81 |
82 | if isMaya:
83 | _onMayaDropped()
84 |
--------------------------------------------------------------------------------
/install.txt:
--------------------------------------------------------------------------------
1 | How to install the Studio Library.
2 |
3 | 1. Drag and drop the "install.mel" file onto the Maya viewport.
4 |
5 | 2. Click the Studio Library icon on the shelf to run.
6 |
7 | Tip: If you would like to share the Studio Library with other users then
8 | place the downloaded "studiolibrary" folder on a network drive.
9 |
10 | Support:
11 |
12 | www.studiolibrary.com
--------------------------------------------------------------------------------
/src/mutils/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to mutils!
2 |
3 | `mutils` is a python package containing many Maya utility functions for managing poses and animations in Maya.
4 |
5 | * www.studiolibrary.com
6 |
--------------------------------------------------------------------------------
/src/mutils/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from .cmds import *
14 | from .decorators import *
15 |
16 | from . import playblast
17 | from . import namespace
18 |
19 | from .scriptjob import ScriptJob
20 | from .matchnames import matchNames, groupObjects
21 |
22 | from .node import Node
23 | from .attribute import Attribute
24 |
25 | from .transferobject import TransferObject
26 |
27 | from .selectionset import SelectionSet, saveSelectionSet
28 | from .pose import Pose, savePose, loadPose
29 | from .animation import Animation, PasteOption, saveAnim, loadAnims
30 | from .mirrortable import MirrorTable, MirrorOption, saveMirrorTable
31 |
--------------------------------------------------------------------------------
/src/mutils/decorators.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import time
14 | import logging
15 |
16 | try:
17 | import maya.cmds
18 | except ImportError:
19 | import traceback
20 | traceback.print_exc()
21 |
22 |
23 | logger = logging.getLogger(__name__)
24 |
25 |
26 | __all__ = [
27 | "timing",
28 | "unifyUndo",
29 | "disableUndo",
30 | "disableViews",
31 | "disableAutoKey",
32 | "showWaitCursor",
33 | "restoreSelection",
34 | "restoreCurrentTime",
35 | ]
36 |
37 |
38 | def timing(fn):
39 |
40 | def wrapped(*args, **kwargs):
41 | time1 = time.time()
42 | ret = fn(*args, **kwargs)
43 | time2 = time.time()
44 | logger.debug('%s function took %0.5f sec' % (fn.__name__, (time2 - time1)))
45 | return ret
46 |
47 | return wrapped
48 |
49 |
50 | def unifyUndo(fn):
51 |
52 | def wrapped(*args, **kwargs):
53 | maya.cmds.undoInfo(openChunk=True)
54 | try:
55 | return fn(*args, **kwargs)
56 | finally:
57 | maya.cmds.undoInfo(closeChunk=True)
58 |
59 | wrapped.__name__ = fn.__name__
60 | wrapped.__doc__ = fn.__doc__
61 |
62 | return wrapped
63 |
64 |
65 | def disableUndo(fn):
66 |
67 | def wrapped(*args, **kwargs):
68 | initialUndoState = maya.cmds.undoInfo(q=True, state=True)
69 | maya.cmds.undoInfo(stateWithoutFlush=False)
70 | try:
71 | return fn(*args, **kwargs)
72 | finally:
73 | maya.cmds.undoInfo(stateWithoutFlush=initialUndoState)
74 |
75 | wrapped.__name__ = fn.__name__
76 | wrapped.__doc__ = fn.__doc__
77 |
78 | return wrapped
79 |
80 |
81 | def disableAutoKey(fn):
82 |
83 | def wrapped(*args, **kwargs):
84 | initialState = maya.cmds.autoKeyframe(query=True, state=True)
85 | maya.cmds.autoKeyframe(edit=True, state=False)
86 | try:
87 | return fn(*args, **kwargs)
88 | finally:
89 | maya.cmds.autoKeyframe(edit=True, state=initialState)
90 |
91 | wrapped.__name__ = fn.__name__
92 | wrapped.__doc__ = fn.__doc__
93 |
94 | return wrapped
95 |
96 |
97 | def restoreSelection(fn):
98 |
99 | def wrapped(*args, **kwargs):
100 | selection = maya.cmds.ls(selection=True) or []
101 | try:
102 | return fn(*args, **kwargs)
103 | finally:
104 | if selection:
105 | maya.cmds.select(selection)
106 |
107 | wrapped.__name__ = fn.__name__
108 | wrapped.__doc__ = fn.__doc__
109 |
110 | return wrapped
111 |
112 |
113 | def restoreCurrentTime(fn):
114 |
115 | def wrapped(*args, **kwargs):
116 | initialTime = maya.cmds.currentTime(query=True)
117 | try:
118 | return fn(*args, **kwargs)
119 | finally:
120 | maya.cmds.currentTime(initialTime, edit=True)
121 |
122 | wrapped.__name__ = fn.__name__
123 | wrapped.__doc__ = fn.__doc__
124 |
125 | return wrapped
126 |
127 |
128 | def showWaitCursor(fn):
129 |
130 | def wrapped(*args, **kwargs):
131 | maya.cmds.waitCursor(state=True)
132 | try:
133 | return fn(*args, **kwargs)
134 | finally:
135 | maya.cmds.waitCursor(state=False)
136 |
137 | wrapped.__name__ = fn.__name__
138 | wrapped.__doc__ = fn.__doc__
139 |
140 | return wrapped
141 |
142 |
143 | def disableViews(fn):
144 |
145 | def wrapped(*args, **kwargs):
146 | modelPanels = maya.cmds.getPanel(vis=True)
147 | emptySelConn = maya.cmds.selectionConnection()
148 |
149 | for panel in modelPanels:
150 | if maya.cmds.getPanel(to=panel) == 'modelPanel':
151 | maya.cmds.isolateSelect(panel, state=True)
152 | maya.cmds.modelEditor(panel, e=True, mlc=emptySelConn)
153 |
154 | try:
155 | return fn(*args, **kwargs)
156 | finally:
157 | for panel in modelPanels:
158 | if maya.cmds.getPanel(to=panel) == 'modelPanel':
159 | maya.cmds.isolateSelect(panel, state=False)
160 |
161 | maya.cmds.deleteUI(emptySelConn)
162 |
163 | wrapped.__name__ = fn.__name__
164 | wrapped.__doc__ = fn.__doc__
165 |
166 | return wrapped
167 |
--------------------------------------------------------------------------------
/src/mutils/gui/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor.Qt import QtCore
14 | from studiovendor.Qt import QtCompat
15 | from studiovendor.Qt import QtWidgets
16 |
17 | try:
18 | import maya.OpenMayaUI as omui
19 | except ImportError as error:
20 | print(error)
21 |
22 | from .framerangemenu import FrameRangeMenu
23 | from .framerangemenu import showFrameRangeMenu
24 | from .modelpanelwidget import ModelPanelWidget
25 | from .thumbnailcapturedialog import *
26 | from .thumbnailcapturemenu import ThumbnailCaptureMenu
27 |
28 |
29 | def mayaWindow():
30 | """
31 | Return the Maya main window as a QMainWindow object.
32 |
33 | :rtype: QMainWindow
34 | """
35 | mainWindowPtr = omui.MQtUtil.mainWindow()
36 | return QtCompat.wrapInstance(mainWindowPtr, QtWidgets.QMainWindow)
37 |
38 |
39 | def makeMayaStandaloneWindow(w):
40 | """
41 | Make a standalone window, though parented under Maya's mainWindow.
42 |
43 | The parenting under Maya's mainWindow is done so that the QWidget will
44 | not auto-destroy itself when the instance variable goes out of scope.
45 | """
46 | # Parent under the main Maya window
47 | w.setParent(mayaWindow())
48 |
49 | # Make this widget appear as a standalone window
50 | w.setWindowFlags(QtCore.Qt.Window)
51 | w.raise_()
52 | w.show()
53 |
--------------------------------------------------------------------------------
/src/mutils/gui/framerangemenu.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor.Qt import QtGui
14 | from studiovendor.Qt import QtWidgets
15 |
16 | import mutils
17 |
18 |
19 | __all__ = ["FrameRangeMenu", "showFrameRangeMenu"]
20 |
21 |
22 | class FrameRangeAction(QtWidgets.QAction):
23 | def __init__(self, *args):
24 | super(FrameRangeAction, self).__init__(*args)
25 |
26 | self._frameRange = (0, 100)
27 |
28 | def frameRange(self):
29 | return self._frameRange
30 |
31 | def setFrameRange(self, frameRange):
32 | self._frameRange = frameRange
33 |
34 |
35 | class FrameRangeMenu(QtWidgets.QMenu):
36 |
37 | def __init__(self, parent=None):
38 | super(FrameRangeMenu, self).__init__(parent)
39 |
40 | action = FrameRangeAction("From Timeline", self)
41 | action.setFrameRange(mutils.playbackFrameRange())
42 | self.addAction(action)
43 |
44 | action = FrameRangeAction("From Selected Timeline", self)
45 | action.setFrameRange(mutils.selectedFrameRange())
46 | self.addAction(action)
47 |
48 | action = FrameRangeAction("From Selected Objects", self)
49 | action.setFrameRange(mutils.selectedObjectsFrameRange())
50 | self.addAction(action)
51 |
52 |
53 | def showFrameRangeMenu():
54 | """
55 | Show the frame range menu at the current cursor position.
56 |
57 | :rtype: QtWidgets.QAction
58 | """
59 | menu = FrameRangeMenu()
60 | position = QtGui.QCursor().pos()
61 | action = menu.exec_(position)
62 | return action
63 |
64 |
65 | if __name__ == "__main__":
66 | action = showFrameRangeMenu()
67 | print(action.frameRange())
68 |
--------------------------------------------------------------------------------
/src/mutils/gui/modelpanelwidget.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import mutils
14 | import mutils.gui
15 |
16 | from studiovendor.Qt import QtCore
17 | from studiovendor.Qt import QtWidgets
18 |
19 | try:
20 | import maya.cmds
21 | import maya.OpenMayaUI as mui
22 | isMaya = True
23 | except ImportError:
24 | isMaya = False
25 |
26 |
27 | __all__ = ["ModelPanelWidget"]
28 |
29 |
30 | class ModelPanelWidget(QtWidgets.QWidget):
31 |
32 | def __init__(self, parent, name="capturedModelPanel", **kwargs):
33 | super(ModelPanelWidget, self).__init__(parent, **kwargs)
34 |
35 | uniqueName = name + str(id(self))
36 | self.setObjectName(uniqueName + 'Widget')
37 |
38 | layout = QtWidgets.QVBoxLayout()
39 | layout.setContentsMargins(0, 0, 0, 0)
40 | layout.setObjectName(uniqueName + "Layout")
41 | self.setLayout(layout)
42 |
43 | maya.cmds.setParent(layout.objectName())
44 | self._modelPanel = maya.cmds.modelPanel(uniqueName, label="ModelPanel")
45 | self.setModelPanelOptions()
46 |
47 | def setModelPanelOptions(self):
48 |
49 | modelPanel = self.name()
50 |
51 | maya.cmds.modelEditor(modelPanel, edit=True, allObjects=False)
52 | maya.cmds.modelEditor(modelPanel, edit=True, grid=False)
53 | maya.cmds.modelEditor(modelPanel, edit=True, dynamics=False)
54 | maya.cmds.modelEditor(modelPanel, edit=True, activeOnly=False)
55 | maya.cmds.modelEditor(modelPanel, edit=True, manipulators=False)
56 | maya.cmds.modelEditor(modelPanel, edit=True, headsUpDisplay=False)
57 | maya.cmds.modelEditor(modelPanel, edit=True, selectionHiliteDisplay=False)
58 |
59 | maya.cmds.modelEditor(modelPanel, edit=True, polymeshes=True)
60 | maya.cmds.modelEditor(modelPanel, edit=True, nurbsSurfaces=True)
61 | maya.cmds.modelEditor(modelPanel, edit=True, subdivSurfaces=True)
62 | maya.cmds.modelEditor(modelPanel, edit=True, displayTextures=True)
63 | maya.cmds.modelEditor(modelPanel, edit=True, displayAppearance="smoothShaded")
64 |
65 | currentModelPanel = mutils.currentModelPanel()
66 |
67 | if currentModelPanel:
68 | camera = maya.cmds.modelEditor(currentModelPanel, query=True, camera=True)
69 | displayLights = maya.cmds.modelEditor(currentModelPanel, query=True, displayLights=True)
70 | displayTextures = maya.cmds.modelEditor(currentModelPanel, query=True, displayTextures=True)
71 |
72 | maya.cmds.modelEditor(modelPanel, edit=True, camera=camera)
73 | maya.cmds.modelEditor(modelPanel, edit=True, displayLights=displayLights)
74 | maya.cmds.modelEditor(modelPanel, edit=True, displayTextures=displayTextures)
75 |
76 | def name(self):
77 | return self._modelPanel
78 |
79 | def modelPanel(self):
80 | ptr = mui.MQtUtil.findControl(self._modelPanel)
81 | return mutils.gui.wrapInstance(ptr, QtWidgets.QWidget)
82 |
83 | def barLayout(self):
84 | name = maya.cmds.modelPanel(self._modelPanel, query=True, barLayout=True)
85 | ptr = mui.MQtUtil.findControl(name)
86 | return mutils.gui.wrapInstance(ptr, QtCore.QObject)
87 |
88 | def hideBarLayout(self):
89 | self.barLayout().hide()
90 |
91 | def hideMenuBar(self):
92 | maya.cmds.modelPanel(self._modelPanel, edit=True, menuBarVisible=False)
93 |
94 | def setCamera(self, name):
95 | maya.cmds.modelPanel(self._modelPanel, edit=True, cam=name)
96 |
97 |
98 | if __name__ == "__main__":
99 | widget = ModelPanelWidget(None, "modelPanel")
100 | widget.show()
101 |
--------------------------------------------------------------------------------
/src/mutils/namespace.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 | import logging
13 | import traceback
14 | from collections import OrderedDict
15 |
16 | try:
17 | import maya.cmds
18 | except ImportError:
19 | traceback.print_exc()
20 |
21 |
22 | logger = logging.getLogger(__name__)
23 |
24 |
25 | __all__ = [
26 | "getAll",
27 | "getFromDagPath",
28 | "getFromDagPaths",
29 | "getFromSelection",
30 | ]
31 |
32 |
33 | def getFromDagPaths(dagPaths):
34 | """
35 | :type dagPaths: list[str]
36 | :rtype: list[str]
37 | """
38 | namespaces = []
39 |
40 | for dagPath in dagPaths:
41 | namespace = getFromDagPath(dagPath)
42 | namespaces.append(namespace)
43 |
44 | # Remove any duplicates while retaining the order
45 | return list(OrderedDict.fromkeys(namespaces))
46 |
47 |
48 | def getFromDagPath(dagPath):
49 | """
50 | :type dagPath: str
51 | :rtype: str
52 | """
53 | shortName = dagPath.split("|")[-1]
54 | namespace = ":".join(shortName.split(":")[:-1])
55 | return namespace
56 |
57 |
58 | def getFromSelection():
59 | """
60 | Get the current namespaces from the selected objects in Maya.
61 |
62 | :rtype: list[str]
63 | """
64 | namespaces = [""]
65 |
66 | try:
67 | names = maya.cmds.ls(selection=True)
68 | namespaces = getFromDagPaths(names) or namespaces
69 | except NameError as error:
70 | # Catch any errors when running this command outside of Maya
71 | logger.exception(error)
72 |
73 | return namespaces
74 |
75 |
76 | def getAll():
77 | """
78 | Get all the available namespaces in the scene
79 |
80 | :rtype: list[str]
81 | """
82 | IGNORE_NAMESPACES = ['UI', 'shared']
83 |
84 | namespaces = maya.cmds.namespaceInfo(listOnlyNamespaces=True, recurse=True)
85 | namespaces = list(set(namespaces) - set(IGNORE_NAMESPACES))
86 | namespaces = sorted(namespaces)
87 |
88 | return namespaces
89 |
--------------------------------------------------------------------------------
/src/mutils/playblast.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import os
14 | import logging
15 |
16 | import mutils
17 |
18 | try:
19 | import maya.cmds
20 | except Exception:
21 | import traceback
22 | traceback.print_exc()
23 |
24 |
25 | __all__ = [
26 | "playblast",
27 | ]
28 |
29 | logger = logging.getLogger(__name__)
30 |
31 |
32 | # Valid Renderers:
33 | # [u'vp2Renderer', u'base_OpenGL_Renderer',
34 | # u'hwRender_OpenGL_Renderer', u'stub_Renderer']
35 | DEFAULT_PLAYBLAST_RENDERER = None
36 |
37 |
38 | class PlayblastError(Exception):
39 | """Base class for exceptions in this module."""
40 | pass
41 |
42 |
43 | def playblast(filename, modelPanel, startFrame, endFrame, width, height, step=1):
44 | """
45 | Wrapper for Maya's Playblast command.
46 |
47 | :type filename: str
48 | :type modelPanel: str
49 | :type startFrame: int
50 | :type endFrame: int
51 | :type width: int
52 | :type height: int
53 | :type step: list[int]
54 | :rtype: str
55 | """
56 | logger.info(u"Playblasting '{filename}'".format(filename=filename))
57 |
58 | if startFrame == endFrame and os.path.exists(filename):
59 | os.remove(filename)
60 |
61 | frame = [i for i in range(startFrame, endFrame + 1, step)]
62 |
63 | modelPanel = modelPanel or mutils.currentModelPanel()
64 | if maya.cmds.modelPanel(modelPanel, query=True, exists=True):
65 | maya.cmds.setFocus(modelPanel)
66 | if DEFAULT_PLAYBLAST_RENDERER:
67 | maya.cmds.modelEditor(
68 | modelPanel,
69 | edit=True,
70 | rendererName=DEFAULT_PLAYBLAST_RENDERER
71 | )
72 |
73 | name, compression = os.path.splitext(filename)
74 | filename = filename.replace(compression, "")
75 | compression = compression.replace(".", "")
76 | offScreen = mutils.isLinux()
77 |
78 | path = maya.cmds.playblast(
79 | format="image",
80 | viewer=False,
81 | percent=100,
82 | quality=100,
83 | frame=frame,
84 | width=width,
85 | height=height,
86 | filename=filename,
87 | endTime=endFrame,
88 | startTime=startFrame,
89 | offScreen=offScreen,
90 | forceOverwrite=True,
91 | showOrnaments=False,
92 | compression=compression,
93 | )
94 |
95 | if not path:
96 | raise PlayblastError("Playblast was canceled")
97 |
98 | src = path.replace("####", str(int(0)).rjust(4, "0"))
99 |
100 | if startFrame == endFrame:
101 | dst = src.replace(".0000.", ".")
102 | logger.info("Renaming '%s' => '%s" % (src, dst))
103 | os.rename(src, dst)
104 | src = dst
105 |
106 | logger.info(u"Playblasted '%s'" % src)
107 | return src
108 |
--------------------------------------------------------------------------------
/src/mutils/scriptjob.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import traceback
14 |
15 | try:
16 | import maya.cmds
17 | except ImportError:
18 | traceback.print_exc()
19 |
20 |
21 | class ScriptJob(object):
22 | """
23 | self._scriptJob = mutils.ScriptJob(e=['SelectionChanged', self.selectionChanged])
24 | """
25 | def __init__(self, *args, **kwargs):
26 | self.id = maya.cmds.scriptJob(*args, **kwargs)
27 |
28 | def kill(self):
29 | if self.id:
30 | maya.cmds.scriptJob(kill=self.id, force=True)
31 | self.id = None
32 |
33 | def __enter__(self):
34 | return self
35 |
36 | def __exit__(self, t, v, tb):
37 | if t is not None:
38 | self.kill()
39 |
--------------------------------------------------------------------------------
/src/mutils/selectionset.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import logging
14 |
15 | import mutils
16 |
17 | try:
18 | import maya.cmds
19 | except Exception:
20 | import traceback
21 | traceback.print_exc()
22 |
23 |
24 | logger = logging.getLogger(__name__)
25 |
26 |
27 | def saveSelectionSet(path, objects, metadata=None):
28 | """
29 | Convenience function for saving a selection set to the given disc location.
30 |
31 | :type path: str
32 | :type objects: list[str]
33 | :type metadata: dict or None
34 | :type args: list
35 | :type kwargs: dict
36 | :rtype: SelectionSet
37 | """
38 | selectionSet = SelectionSet.fromObjects(objects)
39 |
40 | if metadata:
41 | selectionSet.updateMetadata(metadata)
42 |
43 | selectionSet.save(path)
44 |
45 | return selectionSet
46 |
47 |
48 | class SelectionSet(mutils.TransferObject):
49 |
50 | def load(self, objects=None, namespaces=None, **kwargs):
51 | """
52 | Load/Select the transfer objects to the given objects or namespaces.
53 |
54 | :type objects: list[str] or None
55 | :type namespaces: list[str] or None
56 | :type kwargs:
57 | """
58 | validNodes = []
59 | dstObjects = objects
60 | srcObjects = self.objects()
61 |
62 | self.validate(namespaces=namespaces)
63 |
64 | matches = mutils.matchNames(
65 | srcObjects,
66 | dstObjects=dstObjects,
67 | dstNamespaces=namespaces
68 | )
69 |
70 | for srcNode, dstNode in matches:
71 | # Support for wild cards eg: ['*_control'].
72 | if "*" in dstNode.name():
73 | validNodes.append(dstNode.name())
74 | else:
75 | # Remove the first pipe in-case the object has a parent.
76 | dstNode.stripFirstPipe()
77 |
78 | # Try to get the short name. Much faster than the long
79 | # name when selecting objects.
80 | try:
81 | dstNode = dstNode.toShortName()
82 |
83 | except mutils.NoObjectFoundError as error:
84 | logger.debug(error)
85 | continue
86 |
87 | except mutils.MoreThanOneObjectFoundError as error:
88 | logger.debug(error)
89 |
90 | validNodes.append(dstNode.name())
91 |
92 | if validNodes:
93 | maya.cmds.select(validNodes, **kwargs)
94 |
95 | # Return the focus to the Maya window
96 | maya.cmds.setFocus("MayaWindow")
97 | else:
98 | text = "No objects match when loading data. " \
99 | "Turn on debug mode to see more details."
100 |
101 | raise mutils.NoMatchFoundError(text)
102 |
103 | def select(self, objects=None, namespaces=None, **kwargs):
104 | """
105 | Convenience method for any classes inheriting SelectionSet.
106 |
107 | :type objects: str
108 | :type namespaces: list[str]
109 | :rtype: None
110 | """
111 | SelectionSet.load(self, objects=objects, namespaces=namespaces, **kwargs)
112 |
--------------------------------------------------------------------------------
/src/mutils/tests/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from mutils.tests.run import run
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/mutils/tests/data/anim.ma:
--------------------------------------------------------------------------------
1 | //Maya ASCII 2013 scene
2 | //Name: anim.ma
3 | //Last modified: Wed, Aug 20, 2014 07:33:27 PM
4 | //Codeset: UTF-8
5 | requires maya "2013";
6 | requires "stereoCamera" "10.0";
7 | currentUnit -l centimeter -a degree -t film;
8 | fileInfo "application" "maya";
9 | fileInfo "product" "Maya batch mode";
10 | fileInfo "version" "2013 Service Pack 2P12 x64";
11 | fileInfo "cutIdentifier" "201304120319-868747";
12 | fileInfo "osv" "Linux 3.5.4-2.10-desktop #1 SMP PREEMPT Fri Oct 5 14:56:49 CEST 2012 x86_64";
13 | createNode animCurveTA -n "CURVE1";
14 | setAttr ".tan" 18;
15 | setAttr ".wgt" no;
16 | setAttr -s 2 ".ktv[0:1]" 1 45 10 30.81018202226841;
17 | createNode animCurveTU -n "CURVE2";
18 | setAttr ".tan" 9;
19 | setAttr ".wgt" no;
20 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
21 | setAttr -s 2 ".kot[0:1]" 5 5;
22 | createNode animCurveTL -n "CURVE3";
23 | setAttr ".tan" 18;
24 | setAttr ".wgt" no;
25 | setAttr -s 2 ".ktv[0:1]" 1 0 10 0;
26 | createNode animCurveTL -n "CURVE4";
27 | setAttr ".tan" 18;
28 | setAttr ".wgt" no;
29 | setAttr -s 2 ".ktv[0:1]" 1 8 10 8;
30 | createNode animCurveTL -n "CURVE5";
31 | setAttr ".tan" 18;
32 | setAttr ".wgt" no;
33 | setAttr -s 2 ".ktv[0:1]" 1 -12 10 11.214436147065292;
34 | createNode animCurveTU -n "CURVE6";
35 | setAttr ".tan" 18;
36 | setAttr ".wgt" no;
37 | setAttr -s 2 ".ktv[0:1]" 1 0.666 10 0.666;
38 | createNode animCurveTU -n "CURVE7";
39 | setAttr ".tan" 18;
40 | setAttr ".wgt" no;
41 | setAttr -s 2 ".ktv[0:1]" 1 0 10 10;
42 | createNode animCurveTU -n "CURVE8";
43 | setAttr ".tan" 18;
44 | setAttr ".wgt" no;
45 | setAttr -s 2 ".ktv[0:1]" 1 0.25 10 0.42958527814637792;
46 | createNode animCurveTU -n "CURVE9";
47 | setAttr ".tan" 9;
48 | setAttr ".wgt" no;
49 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
50 | setAttr -s 2 ".kot[0:1]" 5 5;
51 | createNode animCurveTU -n "CURVE10";
52 | setAttr ".tan" 18;
53 | setAttr ".wgt" no;
54 | setAttr -s 2 ".ktv[0:1]" 1 0.2 10 0.2;
55 | createNode animCurveTU -n "CURVE11";
56 | setAttr ".tan" 18;
57 | setAttr ".wgt" no;
58 | setAttr -s 2 ".ktv[0:1]" 1 1.4 10 1.4;
59 | createNode animCurveTA -n "CURVE12";
60 | setAttr ".tan" 18;
61 | setAttr ".wgt" no;
62 | setAttr -s 2 ".ktv[0:1]" 1 90 10 149.70880463068096;
63 | createNode animCurveTU -n "CURVE13";
64 | setAttr ".tan" 18;
65 | setAttr ".wgt" no;
66 | setAttr -s 2 ".ktv[0:1]" 1 2.6 10 2.6;
67 | createNode animCurveTU -n "CURVE14";
68 | setAttr ".tan" 18;
69 | setAttr ".wgt" no;
70 | setAttr -s 2 ".ktv[0:1]" 1 0.5 10 0.85917055629275585;
71 | createNode animCurveTU -n "CURVE15";
72 | setAttr ".tan" 18;
73 | setAttr ".wgt" no;
74 | setAttr -s 2 ".ktv[0:1]" 1 5 10 5;
75 | createNode animCurveTU -n "CURVE16";
76 | setAttr ".tan" 9;
77 | setAttr ".wgt" no;
78 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
79 | setAttr -s 2 ".kot[0:1]" 5 5;
80 | createNode animCurveTL -n "CURVE18";
81 | setAttr ".tan" 18;
82 | setAttr ".wgt" no;
83 | setAttr -s 2 ".ktv[0:1]" 1 0 10 15;
84 | // End
--------------------------------------------------------------------------------
/src/mutils/tests/data/animation.anim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/mutils/tests/data/animation.anim
--------------------------------------------------------------------------------
/src/mutils/tests/data/pose.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "angularUnit": "deg",
4 | "description": "test shot",
5 | "user": "testuser",
6 | "startTime": 1,
7 | "mayaSceneFile": "/norman/work/krathjen/git/sandbox/site-packages/mutils/tests/data/test_anim.ma",
8 | "timeUnit": "film",
9 | "cTime": 646464451,
10 | "mayaVersion": "2013 Service Pack 2P12 x64",
11 | "linearUnit": "cm",
12 | "version": "1.0.0",
13 | "endTime": 48
14 | }
15 | ,
16 | "objects": {
17 | "srcSphere:offset": {
18 | "attrs": {}
19 | },
20 | "srcSphere:sphere": {
21 | "attrs": {
22 | "rotateX": {
23 | "curve": "CURVE1",
24 | "type": "doubleAngle",
25 | "value": 45.0
26 | },
27 | "testEnum": {
28 | "curve": "CURVE2",
29 | "type": "enum",
30 | "value": 1
31 | },
32 | "translateX": {
33 | "curve": "CURVE3",
34 | "type": "doubleLinear",
35 | "value": 0.0
36 | },
37 | "translateY": {
38 | "curve": "CURVE4",
39 | "type": "doubleLinear",
40 | "value": 8.0
41 | },
42 | "translateZ": {
43 | "curve": "CURVE5",
44 | "type": "doubleLinear",
45 | "value": -12.0
46 | },
47 | "rotateY": {
48 | "type": "doubleAngle",
49 | "value": 50.0
50 | },
51 | "testFloat": {
52 | "curve": "CURVE6",
53 | "type": "double",
54 | "value": 0.66600000000000004
55 | },
56 | "testAnimated": {
57 | "curve": "CURVE7",
58 | "type": "double",
59 | "value": 0.0
60 | },
61 | "scaleX": {
62 | "curve": "CURVE8",
63 | "type": "double",
64 | "value": 0.25
65 | },
66 | "scaleY": {
67 | "type": "double",
68 | "value": 4.6600000000000001
69 | },
70 | "visibility": {
71 | "curve": "CURVE9",
72 | "type": "bool",
73 | "value": true
74 | },
75 | "testString": {
76 | "type": "string",
77 | "value": "Hello world"
78 | },
79 | "testVectorX": {
80 | "curve": "CURVE10",
81 | "type": "double",
82 | "value": 0.20000000000000001
83 | },
84 | "testVectorY": {
85 | "curve": "CURVE11",
86 | "type": "double",
87 | "value": 1.3999999999999999
88 | },
89 | "rotateZ": {
90 | "curve": "CURVE12",
91 | "type": "doubleAngle",
92 | "value": 90.0
93 | },
94 | "testVectorZ": {
95 | "curve": "CURVE13",
96 | "type": "double",
97 | "value": 2.6000000000000001
98 | },
99 | "scaleZ": {
100 | "curve": "CURVE14",
101 | "type": "double",
102 | "value": 0.5
103 | },
104 | "testInteger": {
105 | "curve": "CURVE15",
106 | "type": "long",
107 | "value": 5
108 | },
109 | "testBoolean": {
110 | "curve": "CURVE16",
111 | "type": "bool",
112 | "value": true
113 | },
114 | "testConnect": {
115 | "type": "double",
116 | "value": 8.0
117 | }
118 | }
119 | },
120 | "srcSphere:lockedNode": {
121 | "attrs": {
122 | "translateX": {
123 | "type": "doubleLinear",
124 | "value": 0.0
125 | },
126 | "translateY": {
127 | "type": "doubleLinear",
128 | "value": 5.0
129 | },
130 | "translateZ": {
131 | "curve": "CURVE18",
132 | "type": "doubleLinear",
133 | "value": 0.0
134 | },
135 | "scaleX": {
136 | "type": "double",
137 | "value": 1.0
138 | },
139 | "scaleY": {
140 | "type": "double",
141 | "value": 1.0
142 | },
143 | "visibility": {
144 | "type": "bool",
145 | "value": true
146 | },
147 | "rotateX": {
148 | "type": "doubleAngle",
149 | "value": 0.0
150 | },
151 | "rotateY": {
152 | "type": "doubleAngle",
153 | "value": 0.0
154 | },
155 | "rotateZ": {
156 | "type": "doubleAngle",
157 | "value": 0.0
158 | },
159 | "scaleZ": {
160 | "type": "double",
161 | "value": 1.0
162 | }
163 | }
164 | }
165 | }
166 | }
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_bake_connected.anim/animation.ma:
--------------------------------------------------------------------------------
1 | //Maya ASCII 2016 scene
2 | //Name: animation.ma
3 | //Last modified: Tue, Aug 09, 2016 08:47:07 AM
4 | //Codeset: 1252
5 | requires maya "2016";
6 | currentUnit -l centimeter -a degree -t film;
7 | fileInfo "application" "maya";
8 | fileInfo "product" "Maya 2016";
9 | fileInfo "version" "2016";
10 | fileInfo "cutIdentifier" "201502261600-953408";
11 | fileInfo "osv" "Microsoft Windows 8 Business Edition, 64-bit (Build 9200)\n";
12 | createNode animCurveTU -n "CURVE1";
13 | rename -uid "B3A2D98C-465C-F630-EA7F-7A960B6B0B4D";
14 | setAttr ".tan" 18;
15 | setAttr ".wgt" no;
16 | setAttr -s 2 ".ktv[0:1]" 1 0 10 10;
17 | createNode animCurveTU -n "CURVE2";
18 | rename -uid "3A3C753F-43CD-18A5-3E19-E9B3F445D832";
19 | setAttr ".tan" 18;
20 | setAttr ".wgt" no;
21 | setAttr -s 10 ".ktv[0:9]" 1 8 2 8 3 8 4 8 5 8 6 8 7 8 8 8 9 8 10 8;
22 | setAttr -s 10 ".kit[9]" 1;
23 | setAttr -s 10 ".kot[0:9]" 1 18 18 18 18 18 18 18
24 | 18 18;
25 | setAttr -s 10 ".kix[9]" 1;
26 | setAttr -s 10 ".kiy[9]" 0;
27 | setAttr -s 10 ".kox[0:9]" 1 1 1 1 1 1 1 1 1 1;
28 | setAttr -s 10 ".koy[0:9]" 0 0 0 0 0 0 0 0 0 0;
29 | // End
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_bake_connected.anim/animation.mb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/mutils/tests/data/test_bake_connected.anim/animation.mb
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_load_insert.anim/animation.ma:
--------------------------------------------------------------------------------
1 | //Maya ASCII 2016 scene
2 | //Name: animation.ma
3 | //Last modified: Tue, Aug 09, 2016 08:47:07 AM
4 | //Codeset: 1252
5 | requires maya "2016";
6 | currentUnit -l centimeter -a degree -t film;
7 | fileInfo "application" "maya";
8 | fileInfo "product" "Maya 2016";
9 | fileInfo "version" "2016";
10 | fileInfo "cutIdentifier" "201502261600-953408";
11 | fileInfo "osv" "Microsoft Windows 8 Business Edition, 64-bit (Build 9200)\n";
12 | createNode animCurveTU -n "CURVE1";
13 | rename -uid "B4FA69EE-4158-445F-5AB5-769D92B60EE3";
14 | setAttr ".tan" 18;
15 | setAttr ".wgt" no;
16 | setAttr -s 2 ".ktv[0:1]" 1 5 10 5;
17 | createNode animCurveTU -n "CURVE2";
18 | rename -uid "CA0863B5-4680-36D0-E9A3-83A0A33EC51B";
19 | setAttr ".tan" 9;
20 | setAttr ".wgt" no;
21 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
22 | setAttr -s 2 ".kot[0:1]" 5 5;
23 | createNode animCurveTU -n "CURVE3";
24 | rename -uid "436929BD-4536-FD91-F836-FA9961D739F5";
25 | setAttr ".tan" 18;
26 | setAttr ".wgt" no;
27 | setAttr -s 2 ".ktv[0:1]" 1 0.25 10 0.42958527814637792;
28 | createNode animCurveTU -n "CURVE4";
29 | rename -uid "9E217B7B-4585-8318-49F7-249A1ACBA95B";
30 | setAttr ".tan" 18;
31 | setAttr ".wgt" no;
32 | setAttr -s 2 ".ktv[0:1]" 1 0.5 10 0.85917055629275585;
33 | createNode animCurveTA -n "CURVE5";
34 | rename -uid "5649AD20-440E-7866-8CAB-B08834F07905";
35 | setAttr ".tan" 18;
36 | setAttr ".wgt" no;
37 | setAttr -s 2 ".ktv[0:1]" 1 45 10 30.81018202226841;
38 | createNode animCurveTA -n "CURVE6";
39 | rename -uid "19E0B15E-449C-F085-5151-10BFD6772FE1";
40 | setAttr ".tan" 18;
41 | setAttr ".wgt" no;
42 | setAttr -s 2 ".ktv[0:1]" 1 90 10 149.70880463068096;
43 | createNode animCurveTL -n "CURVE7";
44 | rename -uid "1FE3DC07-4819-A244-0BC3-B8A3B3EF1275";
45 | setAttr ".tan" 18;
46 | setAttr ".wgt" no;
47 | setAttr -s 2 ".ktv[0:1]" 1 0 10 0;
48 | createNode animCurveTL -n "CURVE8";
49 | rename -uid "00984994-4BA2-5907-9C38-D1BE8279B667";
50 | setAttr ".tan" 18;
51 | setAttr ".wgt" no;
52 | setAttr -s 2 ".ktv[0:1]" 1 8 10 8;
53 | createNode animCurveTL -n "CURVE9";
54 | rename -uid "40524ED9-44E0-043B-4F9E-00ABB81FF2FA";
55 | setAttr ".tan" 18;
56 | setAttr ".wgt" no;
57 | setAttr -s 2 ".ktv[0:1]" 1 -12 10 11.214436147065292;
58 | createNode animCurveTU -n "CURVE10";
59 | rename -uid "240A5025-4AA3-D27B-CBD9-3D98E97E7B2A";
60 | setAttr ".tan" 9;
61 | setAttr ".wgt" no;
62 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
63 | setAttr -s 2 ".kot[0:1]" 5 5;
64 | createNode animCurveTU -n "CURVE11";
65 | rename -uid "4541CB45-4FD7-656E-2626-0394702423B3";
66 | setAttr ".tan" 18;
67 | setAttr ".wgt" no;
68 | setAttr -s 2 ".ktv[0:1]" 1 0.666 10 0.666;
69 | createNode animCurveTU -n "CURVE12";
70 | rename -uid "55FC02E9-4D2D-FF69-A838-978CC1CA83B4";
71 | setAttr ".tan" 18;
72 | setAttr ".wgt" no;
73 | setAttr -s 2 ".ktv[0:1]" 1 0 10 10;
74 | createNode animCurveTU -n "CURVE13";
75 | rename -uid "CBF4DD9D-4839-361A-70F2-6990E98D9C30";
76 | setAttr ".tan" 18;
77 | setAttr ".wgt" no;
78 | setAttr -s 2 ".ktv[0:1]" 1 0.2 10 0.2;
79 | createNode animCurveTU -n "CURVE14";
80 | rename -uid "1A7FD955-44FC-DA80-17C8-F8B2936C2A64";
81 | setAttr ".tan" 18;
82 | setAttr ".wgt" no;
83 | setAttr -s 2 ".ktv[0:1]" 1 1.4 10 1.4;
84 | createNode animCurveTU -n "CURVE15";
85 | rename -uid "3F957170-4D7E-FD98-8F3E-6086609AB97F";
86 | setAttr ".tan" 18;
87 | setAttr ".wgt" no;
88 | setAttr -s 2 ".ktv[0:1]" 1 2.6 10 2.6;
89 | createNode animCurveTU -n "CURVE16";
90 | rename -uid "2EC19608-4057-B2F8-7796-27BB84CC1532";
91 | setAttr ".tan" 9;
92 | setAttr ".wgt" no;
93 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
94 | setAttr -s 2 ".kot[0:1]" 5 5;
95 | createNode animCurveTL -n "CURVE18";
96 | rename -uid "75AC48FC-4740-40A9-B0B6-AFB0FB0FAD85";
97 | setAttr ".tan" 18;
98 | setAttr ".wgt" no;
99 | setAttr -s 2 ".ktv[0:1]" 1 0 10 15;
100 | // End
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_load_insert.anim/animation.mb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/mutils/tests/data/test_load_insert.anim/animation.mb
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_load_insert.anim/pose.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "mayaSceneFile": "C:/Users/hovel/Dropbox/git/site-packages/studiolibrary/packages/mutils/tests/data/test_anim.ma",
4 | "angularUnit": "deg",
5 | "ctime": "1518341545",
6 | "endFrame": 10,
7 | "linearUnit": "cm",
8 | "version": "1.0.0",
9 | "user": "Hovel",
10 | "startFrame": 1,
11 | "timeUnit": "film",
12 | "mayaVersion": "2017"
13 | }
14 | ,
15 | "objects": {
16 | "srcSphere:offset": {
17 | "attrs": {}
18 | },
19 | "srcSphere:sphere": {
20 | "attrs": {
21 | "testInteger": {
22 | "curve": "CURVE1",
23 | "type": "long",
24 | "value": 5
25 | },
26 | "testProxy": {
27 | "type": "double",
28 | "value": 1.0
29 | },
30 | "scaleY": {
31 | "type": "double",
32 | "value": 4.66
33 | },
34 | "testLimit": {
35 | "type": "double",
36 | "value": 10.0
37 | },
38 | "testConnect": {
39 | "type": "double",
40 | "value": 8.0
41 | },
42 | "testEnum": {
43 | "curve": "CURVE2",
44 | "type": "enum",
45 | "value": 1
46 | },
47 | "scaleX": {
48 | "curve": "CURVE3",
49 | "type": "double",
50 | "value": 0.25
51 | },
52 | "testString": {
53 | "type": "string",
54 | "value": "Hello world"
55 | },
56 | "scaleZ": {
57 | "curve": "CURVE4",
58 | "type": "double",
59 | "value": 0.5
60 | },
61 | "rotateX": {
62 | "curve": "CURVE5",
63 | "type": "doubleAngle",
64 | "value": 45.0
65 | },
66 | "rotateY": {
67 | "type": "doubleAngle",
68 | "value": 50.0
69 | },
70 | "rotateZ": {
71 | "curve": "CURVE6",
72 | "type": "doubleAngle",
73 | "value": 90.0
74 | },
75 | "testStatic": {
76 | "type": "double",
77 | "value": 0.0
78 | },
79 | "translateX": {
80 | "curve": "CURVE7",
81 | "type": "doubleLinear",
82 | "value": 0.0
83 | },
84 | "translateY": {
85 | "curve": "CURVE8",
86 | "type": "doubleLinear",
87 | "value": 8.0
88 | },
89 | "translateZ": {
90 | "curve": "CURVE9",
91 | "type": "doubleLinear",
92 | "value": -12.0
93 | },
94 | "visibility": {
95 | "curve": "CURVE10",
96 | "type": "bool",
97 | "value": true
98 | },
99 | "testFloat": {
100 | "curve": "CURVE11",
101 | "type": "double",
102 | "value": 0.666
103 | },
104 | "testAnimated": {
105 | "curve": "CURVE12",
106 | "type": "double",
107 | "value": 0.0
108 | },
109 | "testVectorX": {
110 | "curve": "CURVE13",
111 | "type": "double",
112 | "value": 0.2
113 | },
114 | "testVectorY": {
115 | "curve": "CURVE14",
116 | "type": "double",
117 | "value": 1.4
118 | },
119 | "testVectorZ": {
120 | "curve": "CURVE15",
121 | "type": "double",
122 | "value": 2.6
123 | },
124 | "testBoolean": {
125 | "curve": "CURVE16",
126 | "type": "bool",
127 | "value": true
128 | }
129 | }
130 | },
131 | "srcSphere:lockedNode": {
132 | "attrs": {
133 | "translateX": {
134 | "type": "doubleLinear",
135 | "value": 0.0
136 | },
137 | "translateY": {
138 | "type": "doubleLinear",
139 | "value": 5.0
140 | },
141 | "translateZ": {
142 | "curve": "CURVE18",
143 | "type": "doubleLinear",
144 | "value": 0.0
145 | },
146 | "scaleX": {
147 | "type": "double",
148 | "value": 1.0
149 | },
150 | "scaleY": {
151 | "type": "double",
152 | "value": 1.0
153 | },
154 | "visibility": {
155 | "type": "bool",
156 | "value": true
157 | },
158 | "rotateX": {
159 | "type": "doubleAngle",
160 | "value": 0.0
161 | },
162 | "rotateY": {
163 | "type": "doubleAngle",
164 | "value": 0.0
165 | },
166 | "rotateZ": {
167 | "type": "doubleAngle",
168 | "value": 0.0
169 | },
170 | "scaleZ": {
171 | "type": "double",
172 | "value": 1.0
173 | }
174 | }
175 | }
176 | }
177 | }
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_load_replace.anim/animation.ma:
--------------------------------------------------------------------------------
1 | //Maya ASCII 2016 scene
2 | //Name: animation.ma
3 | //Last modified: Tue, Aug 09, 2016 08:47:07 AM
4 | //Codeset: 1252
5 | requires maya "2016";
6 | currentUnit -l centimeter -a degree -t film;
7 | fileInfo "application" "maya";
8 | fileInfo "product" "Maya 2016";
9 | fileInfo "version" "2016";
10 | fileInfo "cutIdentifier" "201502261600-953408";
11 | fileInfo "osv" "Microsoft Windows 8 Business Edition, 64-bit (Build 9200)\n";
12 | createNode animCurveTU -n "CURVE1";
13 | rename -uid "44F21FB5-4121-8FAA-4E5A-2795D8DB1C98";
14 | setAttr ".tan" 18;
15 | setAttr ".wgt" no;
16 | setAttr -s 2 ".ktv[0:1]" 1 5 10 5;
17 | createNode animCurveTU -n "CURVE2";
18 | rename -uid "89D65122-4A81-C08C-8F60-A8A69D8BDDFF";
19 | setAttr ".tan" 9;
20 | setAttr ".wgt" no;
21 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
22 | setAttr -s 2 ".kot[0:1]" 5 5;
23 | createNode animCurveTU -n "CURVE3";
24 | rename -uid "394F9F8B-44A0-7AEE-3FF8-43BE62C0DDC8";
25 | setAttr ".tan" 18;
26 | setAttr ".wgt" no;
27 | setAttr -s 2 ".ktv[0:1]" 1 0.25 10 0.42958527814637792;
28 | createNode animCurveTU -n "CURVE4";
29 | rename -uid "CF90746B-43BD-0210-E0FC-05A5368FC36F";
30 | setAttr ".tan" 18;
31 | setAttr ".wgt" no;
32 | setAttr -s 2 ".ktv[0:1]" 1 0.5 10 0.85917055629275585;
33 | createNode animCurveTA -n "CURVE5";
34 | rename -uid "C88B0183-4A49-7472-1F9B-75861AB915A8";
35 | setAttr ".tan" 18;
36 | setAttr ".wgt" no;
37 | setAttr -s 2 ".ktv[0:1]" 1 45 10 30.81018202226841;
38 | createNode animCurveTA -n "CURVE6";
39 | rename -uid "70CBACAA-40C4-7C42-B9F5-0BB67E97595D";
40 | setAttr ".tan" 18;
41 | setAttr ".wgt" no;
42 | setAttr -s 2 ".ktv[0:1]" 1 90 10 149.70880463068096;
43 | createNode animCurveTL -n "CURVE7";
44 | rename -uid "9A9A4A91-42EF-2651-3696-91ACC6F098B6";
45 | setAttr ".tan" 18;
46 | setAttr ".wgt" no;
47 | setAttr -s 2 ".ktv[0:1]" 1 0 10 0;
48 | createNode animCurveTL -n "CURVE8";
49 | rename -uid "CBDCAEFF-4D9E-5162-0CAC-7C8CE46E91F2";
50 | setAttr ".tan" 18;
51 | setAttr ".wgt" no;
52 | setAttr -s 2 ".ktv[0:1]" 1 8 10 8;
53 | createNode animCurveTL -n "CURVE9";
54 | rename -uid "B745DFCE-4739-96FC-C827-1494F35ED50D";
55 | setAttr ".tan" 18;
56 | setAttr ".wgt" no;
57 | setAttr -s 2 ".ktv[0:1]" 1 -12 10 11.214436147065292;
58 | createNode animCurveTU -n "CURVE10";
59 | rename -uid "0A53795D-45F0-B3C3-E5F2-AAB7665A9E8E";
60 | setAttr ".tan" 9;
61 | setAttr ".wgt" no;
62 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
63 | setAttr -s 2 ".kot[0:1]" 5 5;
64 | createNode animCurveTU -n "CURVE11";
65 | rename -uid "7DC24CA9-48A1-3B3A-8278-5A81D70CA4E9";
66 | setAttr ".tan" 18;
67 | setAttr ".wgt" no;
68 | setAttr -s 2 ".ktv[0:1]" 1 0.666 10 0.666;
69 | createNode animCurveTU -n "CURVE12";
70 | rename -uid "400DED74-4D52-543D-91D4-0881D938C5C9";
71 | setAttr ".tan" 18;
72 | setAttr ".wgt" no;
73 | setAttr -s 2 ".ktv[0:1]" 1 0 10 10;
74 | createNode animCurveTU -n "CURVE13";
75 | rename -uid "5527A666-49BE-9277-3936-12B07312A901";
76 | setAttr ".tan" 18;
77 | setAttr ".wgt" no;
78 | setAttr -s 2 ".ktv[0:1]" 1 0.2 10 0.2;
79 | createNode animCurveTU -n "CURVE14";
80 | rename -uid "DF0B2F0E-49A4-61C0-521D-0A8497BF2753";
81 | setAttr ".tan" 18;
82 | setAttr ".wgt" no;
83 | setAttr -s 2 ".ktv[0:1]" 1 1.4 10 1.4;
84 | createNode animCurveTU -n "CURVE15";
85 | rename -uid "20CAFE14-4EBD-6A5D-458C-5B82383EC0F2";
86 | setAttr ".tan" 18;
87 | setAttr ".wgt" no;
88 | setAttr -s 2 ".ktv[0:1]" 1 2.6 10 2.6;
89 | createNode animCurveTU -n "CURVE16";
90 | rename -uid "7996F54C-49E2-85E5-D444-CBB553D75344";
91 | setAttr ".tan" 9;
92 | setAttr ".wgt" no;
93 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
94 | setAttr -s 2 ".kot[0:1]" 5 5;
95 | createNode animCurveTL -n "CURVE18";
96 | rename -uid "C516D5DD-4FA0-4AEC-8E33-0ABF26EF9D60";
97 | setAttr ".tan" 18;
98 | setAttr ".wgt" no;
99 | setAttr -s 2 ".ktv[0:1]" 1 0 10 15;
100 | // End
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_load_replace.anim/animation.mb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/mutils/tests/data/test_load_replace.anim/animation.mb
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_load_replace.anim/pose.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "mayaSceneFile": "C:/Users/hovel/Dropbox/git/site-packages/studiolibrary/packages/mutils/tests/data/test_anim.ma",
4 | "angularUnit": "deg",
5 | "ctime": "1518341546",
6 | "endFrame": 10,
7 | "linearUnit": "cm",
8 | "version": "1.0.0",
9 | "user": "Hovel",
10 | "startFrame": 1,
11 | "timeUnit": "film",
12 | "mayaVersion": "2017"
13 | }
14 | ,
15 | "objects": {
16 | "srcSphere:offset": {
17 | "attrs": {}
18 | },
19 | "srcSphere:sphere": {
20 | "attrs": {
21 | "testInteger": {
22 | "curve": "CURVE1",
23 | "type": "long",
24 | "value": 5
25 | },
26 | "testProxy": {
27 | "type": "double",
28 | "value": 1.0
29 | },
30 | "scaleY": {
31 | "type": "double",
32 | "value": 4.66
33 | },
34 | "testLimit": {
35 | "type": "double",
36 | "value": 10.0
37 | },
38 | "testConnect": {
39 | "type": "double",
40 | "value": 8.0
41 | },
42 | "testEnum": {
43 | "curve": "CURVE2",
44 | "type": "enum",
45 | "value": 1
46 | },
47 | "scaleX": {
48 | "curve": "CURVE3",
49 | "type": "double",
50 | "value": 0.25
51 | },
52 | "testString": {
53 | "type": "string",
54 | "value": "Hello world"
55 | },
56 | "scaleZ": {
57 | "curve": "CURVE4",
58 | "type": "double",
59 | "value": 0.5
60 | },
61 | "rotateX": {
62 | "curve": "CURVE5",
63 | "type": "doubleAngle",
64 | "value": 45.0
65 | },
66 | "rotateY": {
67 | "type": "doubleAngle",
68 | "value": 50.0
69 | },
70 | "rotateZ": {
71 | "curve": "CURVE6",
72 | "type": "doubleAngle",
73 | "value": 90.0
74 | },
75 | "testStatic": {
76 | "type": "double",
77 | "value": 0.0
78 | },
79 | "translateX": {
80 | "curve": "CURVE7",
81 | "type": "doubleLinear",
82 | "value": 0.0
83 | },
84 | "translateY": {
85 | "curve": "CURVE8",
86 | "type": "doubleLinear",
87 | "value": 8.0
88 | },
89 | "translateZ": {
90 | "curve": "CURVE9",
91 | "type": "doubleLinear",
92 | "value": -12.0
93 | },
94 | "visibility": {
95 | "curve": "CURVE10",
96 | "type": "bool",
97 | "value": true
98 | },
99 | "testFloat": {
100 | "curve": "CURVE11",
101 | "type": "double",
102 | "value": 0.666
103 | },
104 | "testAnimated": {
105 | "curve": "CURVE12",
106 | "type": "double",
107 | "value": 0.0
108 | },
109 | "testVectorX": {
110 | "curve": "CURVE13",
111 | "type": "double",
112 | "value": 0.2
113 | },
114 | "testVectorY": {
115 | "curve": "CURVE14",
116 | "type": "double",
117 | "value": 1.4
118 | },
119 | "testVectorZ": {
120 | "curve": "CURVE15",
121 | "type": "double",
122 | "value": 2.6
123 | },
124 | "testBoolean": {
125 | "curve": "CURVE16",
126 | "type": "bool",
127 | "value": true
128 | }
129 | }
130 | },
131 | "srcSphere:lockedNode": {
132 | "attrs": {
133 | "translateX": {
134 | "type": "doubleLinear",
135 | "value": 0.0
136 | },
137 | "translateY": {
138 | "type": "doubleLinear",
139 | "value": 5.0
140 | },
141 | "translateZ": {
142 | "curve": "CURVE18",
143 | "type": "doubleLinear",
144 | "value": 0.0
145 | },
146 | "scaleX": {
147 | "type": "double",
148 | "value": 1.0
149 | },
150 | "scaleY": {
151 | "type": "double",
152 | "value": 1.0
153 | },
154 | "visibility": {
155 | "type": "bool",
156 | "value": true
157 | },
158 | "rotateX": {
159 | "type": "doubleAngle",
160 | "value": 0.0
161 | },
162 | "rotateY": {
163 | "type": "doubleAngle",
164 | "value": 0.0
165 | },
166 | "rotateZ": {
167 | "type": "doubleAngle",
168 | "value": 0.0
169 | },
170 | "scaleZ": {
171 | "type": "double",
172 | "value": 1.0
173 | }
174 | }
175 | }
176 | }
177 | }
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_load_replace_completely.anim/animation.ma:
--------------------------------------------------------------------------------
1 | //Maya ASCII 2016 scene
2 | //Name: animation.ma
3 | //Last modified: Tue, Aug 09, 2016 08:47:08 AM
4 | //Codeset: 1252
5 | requires maya "2016";
6 | currentUnit -l centimeter -a degree -t film;
7 | fileInfo "application" "maya";
8 | fileInfo "product" "Maya 2016";
9 | fileInfo "version" "2016";
10 | fileInfo "cutIdentifier" "201502261600-953408";
11 | fileInfo "osv" "Microsoft Windows 8 Business Edition, 64-bit (Build 9200)\n";
12 | createNode animCurveTU -n "CURVE1";
13 | rename -uid "07400D46-41EF-56B5-ABE2-FCB3FDC705F2";
14 | setAttr ".tan" 18;
15 | setAttr ".wgt" no;
16 | setAttr -s 2 ".ktv[0:1]" 1 5 10 5;
17 | createNode animCurveTU -n "CURVE2";
18 | rename -uid "E2B997BA-4A97-2EF7-C65E-E7BD483688D6";
19 | setAttr ".tan" 9;
20 | setAttr ".wgt" no;
21 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
22 | setAttr -s 2 ".kot[0:1]" 5 5;
23 | createNode animCurveTU -n "CURVE3";
24 | rename -uid "2AF61E8F-4817-A910-3417-6B9823CED36D";
25 | setAttr ".tan" 18;
26 | setAttr ".wgt" no;
27 | setAttr -s 2 ".ktv[0:1]" 1 0.25 10 0.42958527814637792;
28 | createNode animCurveTU -n "CURVE4";
29 | rename -uid "61ED901E-4BFA-A417-6F1A-A89854BAE1F9";
30 | setAttr ".tan" 18;
31 | setAttr ".wgt" no;
32 | setAttr -s 2 ".ktv[0:1]" 1 0.5 10 0.85917055629275585;
33 | createNode animCurveTA -n "CURVE5";
34 | rename -uid "25E543E0-4233-B654-6DC2-C980CC9ED600";
35 | setAttr ".tan" 18;
36 | setAttr ".wgt" no;
37 | setAttr -s 2 ".ktv[0:1]" 1 45 10 30.81018202226841;
38 | createNode animCurveTA -n "CURVE6";
39 | rename -uid "3921DD56-44E6-E6D7-DB1B-C28209F3157E";
40 | setAttr ".tan" 18;
41 | setAttr ".wgt" no;
42 | setAttr -s 2 ".ktv[0:1]" 1 90 10 149.70880463068096;
43 | createNode animCurveTL -n "CURVE7";
44 | rename -uid "5EE5D458-498D-AD10-196B-0F99DE4A9F97";
45 | setAttr ".tan" 18;
46 | setAttr ".wgt" no;
47 | setAttr -s 2 ".ktv[0:1]" 1 0 10 0;
48 | createNode animCurveTL -n "CURVE8";
49 | rename -uid "81FBC4EF-479F-58C1-D24D-859C16E01BA1";
50 | setAttr ".tan" 18;
51 | setAttr ".wgt" no;
52 | setAttr -s 2 ".ktv[0:1]" 1 8 10 8;
53 | createNode animCurveTL -n "CURVE9";
54 | rename -uid "898B5C26-448D-366F-0E63-5082268110FB";
55 | setAttr ".tan" 18;
56 | setAttr ".wgt" no;
57 | setAttr -s 2 ".ktv[0:1]" 1 -12 10 11.214436147065292;
58 | createNode animCurveTU -n "CURVE10";
59 | rename -uid "139725A4-4C9A-C99F-2E9F-AF91BC3F67E9";
60 | setAttr ".tan" 9;
61 | setAttr ".wgt" no;
62 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
63 | setAttr -s 2 ".kot[0:1]" 5 5;
64 | createNode animCurveTU -n "CURVE11";
65 | rename -uid "1A5281F1-4252-087B-1631-9998C170D33B";
66 | setAttr ".tan" 18;
67 | setAttr ".wgt" no;
68 | setAttr -s 2 ".ktv[0:1]" 1 0.666 10 0.666;
69 | createNode animCurveTU -n "CURVE12";
70 | rename -uid "3B543491-429F-763A-0075-4EB85B2E50AB";
71 | setAttr ".tan" 18;
72 | setAttr ".wgt" no;
73 | setAttr -s 2 ".ktv[0:1]" 1 0 10 10;
74 | createNode animCurveTU -n "CURVE13";
75 | rename -uid "8532CE01-49F8-571C-2D65-A98F3427EBF0";
76 | setAttr ".tan" 18;
77 | setAttr ".wgt" no;
78 | setAttr -s 2 ".ktv[0:1]" 1 0.2 10 0.2;
79 | createNode animCurveTU -n "CURVE14";
80 | rename -uid "D9767D2E-4DFC-F089-183D-789D8B697CF1";
81 | setAttr ".tan" 18;
82 | setAttr ".wgt" no;
83 | setAttr -s 2 ".ktv[0:1]" 1 1.4 10 1.4;
84 | createNode animCurveTU -n "CURVE15";
85 | rename -uid "73706920-4309-DAEE-AE70-CAAF4C1D68FB";
86 | setAttr ".tan" 18;
87 | setAttr ".wgt" no;
88 | setAttr -s 2 ".ktv[0:1]" 1 2.6 10 2.6;
89 | createNode animCurveTU -n "CURVE16";
90 | rename -uid "70D851D4-43F8-72F5-0327-E28AEB0F174C";
91 | setAttr ".tan" 9;
92 | setAttr ".wgt" no;
93 | setAttr -s 2 ".ktv[0:1]" 1 1 10 1;
94 | setAttr -s 2 ".kot[0:1]" 5 5;
95 | createNode animCurveTL -n "CURVE18";
96 | rename -uid "716232B6-4903-7906-472A-569BBA3146DA";
97 | setAttr ".tan" 18;
98 | setAttr ".wgt" no;
99 | setAttr -s 2 ".ktv[0:1]" 1 0 10 15;
100 | // End
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_load_replace_completely.anim/animation.mb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/mutils/tests/data/test_load_replace_completely.anim/animation.mb
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_load_replace_completely.anim/pose.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "mayaSceneFile": "C:/Users/hovel/Dropbox/git/site-packages/studiolibrary/packages/mutils/tests/data/test_anim.ma",
4 | "angularUnit": "deg",
5 | "ctime": "1518341546",
6 | "endFrame": 10,
7 | "linearUnit": "cm",
8 | "version": "1.0.0",
9 | "user": "Hovel",
10 | "startFrame": 1,
11 | "timeUnit": "film",
12 | "mayaVersion": "2017"
13 | }
14 | ,
15 | "objects": {
16 | "srcSphere:offset": {
17 | "attrs": {}
18 | },
19 | "srcSphere:sphere": {
20 | "attrs": {
21 | "testInteger": {
22 | "curve": "CURVE1",
23 | "type": "long",
24 | "value": 5
25 | },
26 | "testProxy": {
27 | "type": "double",
28 | "value": 1.0
29 | },
30 | "scaleY": {
31 | "type": "double",
32 | "value": 4.66
33 | },
34 | "testLimit": {
35 | "type": "double",
36 | "value": 10.0
37 | },
38 | "testConnect": {
39 | "type": "double",
40 | "value": 8.0
41 | },
42 | "testEnum": {
43 | "curve": "CURVE2",
44 | "type": "enum",
45 | "value": 1
46 | },
47 | "scaleX": {
48 | "curve": "CURVE3",
49 | "type": "double",
50 | "value": 0.25
51 | },
52 | "testString": {
53 | "type": "string",
54 | "value": "Hello world"
55 | },
56 | "scaleZ": {
57 | "curve": "CURVE4",
58 | "type": "double",
59 | "value": 0.5
60 | },
61 | "rotateX": {
62 | "curve": "CURVE5",
63 | "type": "doubleAngle",
64 | "value": 45.0
65 | },
66 | "rotateY": {
67 | "type": "doubleAngle",
68 | "value": 50.0
69 | },
70 | "rotateZ": {
71 | "curve": "CURVE6",
72 | "type": "doubleAngle",
73 | "value": 90.0
74 | },
75 | "testStatic": {
76 | "type": "double",
77 | "value": 0.0
78 | },
79 | "translateX": {
80 | "curve": "CURVE7",
81 | "type": "doubleLinear",
82 | "value": 0.0
83 | },
84 | "translateY": {
85 | "curve": "CURVE8",
86 | "type": "doubleLinear",
87 | "value": 8.0
88 | },
89 | "translateZ": {
90 | "curve": "CURVE9",
91 | "type": "doubleLinear",
92 | "value": -12.0
93 | },
94 | "visibility": {
95 | "curve": "CURVE10",
96 | "type": "bool",
97 | "value": true
98 | },
99 | "testFloat": {
100 | "curve": "CURVE11",
101 | "type": "double",
102 | "value": 0.666
103 | },
104 | "testAnimated": {
105 | "curve": "CURVE12",
106 | "type": "double",
107 | "value": 0.0
108 | },
109 | "testVectorX": {
110 | "curve": "CURVE13",
111 | "type": "double",
112 | "value": 0.2
113 | },
114 | "testVectorY": {
115 | "curve": "CURVE14",
116 | "type": "double",
117 | "value": 1.4
118 | },
119 | "testVectorZ": {
120 | "curve": "CURVE15",
121 | "type": "double",
122 | "value": 2.6
123 | },
124 | "testBoolean": {
125 | "curve": "CURVE16",
126 | "type": "bool",
127 | "value": true
128 | }
129 | }
130 | },
131 | "srcSphere:lockedNode": {
132 | "attrs": {
133 | "translateX": {
134 | "type": "doubleLinear",
135 | "value": 0.0
136 | },
137 | "translateY": {
138 | "type": "doubleLinear",
139 | "value": 5.0
140 | },
141 | "translateZ": {
142 | "curve": "CURVE18",
143 | "type": "doubleLinear",
144 | "value": 0.0
145 | },
146 | "scaleX": {
147 | "type": "double",
148 | "value": 1.0
149 | },
150 | "scaleY": {
151 | "type": "double",
152 | "value": 1.0
153 | },
154 | "visibility": {
155 | "type": "bool",
156 | "value": true
157 | },
158 | "rotateX": {
159 | "type": "doubleAngle",
160 | "value": 0.0
161 | },
162 | "rotateY": {
163 | "type": "doubleAngle",
164 | "value": 0.0
165 | },
166 | "rotateZ": {
167 | "type": "doubleAngle",
168 | "value": 0.0
169 | },
170 | "scaleZ": {
171 | "type": "double",
172 | "value": 1.0
173 | }
174 | }
175 | }
176 | }
177 | }
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_non_unique_names.pose:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "mayaSceneFile": "C:/Users/hovel/Dropbox/git/site-packages/studiolibrary/packages/mutils/tests/data/test_non_unique_names.ma",
4 | "version": "1.0.0",
5 | "user": "Hovel",
6 | "mayaVersion": "2017",
7 | "ctime": "1518341544"
8 | }
9 | ,
10 | "objects": {
11 | "srcSphere:offset": {
12 | "attrs": {}
13 | },
14 | "srcSphere:sphere": {
15 | "attrs": {
16 | "testInteger": {
17 | "type": "long",
18 | "value": 5
19 | },
20 | "testProxy": {
21 | "type": "double",
22 | "value": 1.0
23 | },
24 | "scaleY": {
25 | "type": "double",
26 | "value": 4.66
27 | },
28 | "testLimit": {
29 | "type": "double",
30 | "value": 10.0
31 | },
32 | "testConnect": {
33 | "type": "double",
34 | "value": 8.0
35 | },
36 | "testEnum": {
37 | "type": "enum",
38 | "value": 1
39 | },
40 | "scaleX": {
41 | "type": "double",
42 | "value": 0.25
43 | },
44 | "testString": {
45 | "type": "string",
46 | "value": "Hello world"
47 | },
48 | "scaleZ": {
49 | "type": "double",
50 | "value": 0.5
51 | },
52 | "rotateX": {
53 | "type": "doubleAngle",
54 | "value": 45.0
55 | },
56 | "rotateY": {
57 | "type": "doubleAngle",
58 | "value": 50.0
59 | },
60 | "rotateZ": {
61 | "type": "doubleAngle",
62 | "value": 90.0
63 | },
64 | "translateX": {
65 | "type": "doubleLinear",
66 | "value": 0.0
67 | },
68 | "translateY": {
69 | "type": "doubleLinear",
70 | "value": 8.0
71 | },
72 | "translateZ": {
73 | "type": "doubleLinear",
74 | "value": -12.0
75 | },
76 | "visibility": {
77 | "type": "bool",
78 | "value": true
79 | },
80 | "testFloat": {
81 | "type": "double",
82 | "value": 0.666
83 | },
84 | "testAnimated": {
85 | "type": "double",
86 | "value": 0.0
87 | },
88 | "testVectorX": {
89 | "type": "double",
90 | "value": 0.2
91 | },
92 | "testVectorY": {
93 | "type": "double",
94 | "value": 1.4
95 | },
96 | "testVectorZ": {
97 | "type": "double",
98 | "value": 2.6
99 | },
100 | "testBoolean": {
101 | "type": "bool",
102 | "value": true
103 | }
104 | }
105 | },
106 | "srcSphere:lockedNode": {
107 | "attrs": {
108 | "translateX": {
109 | "type": "doubleLinear",
110 | "value": 0.0
111 | },
112 | "translateY": {
113 | "type": "doubleLinear",
114 | "value": 5.0
115 | },
116 | "translateZ": {
117 | "type": "doubleLinear",
118 | "value": 0.0
119 | },
120 | "scaleX": {
121 | "type": "double",
122 | "value": 1.0
123 | },
124 | "scaleY": {
125 | "type": "double",
126 | "value": 1.0
127 | },
128 | "visibility": {
129 | "type": "bool",
130 | "value": true
131 | },
132 | "rotateX": {
133 | "type": "doubleAngle",
134 | "value": 0.0
135 | },
136 | "rotateY": {
137 | "type": "doubleAngle",
138 | "value": 0.0
139 | },
140 | "rotateZ": {
141 | "type": "doubleAngle",
142 | "value": 0.0
143 | },
144 | "scaleZ": {
145 | "type": "double",
146 | "value": 1.0
147 | }
148 | }
149 | }
150 | }
151 | }
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_older_version.anim/.studioLibrary/record.dict:
--------------------------------------------------------------------------------
1 | {'end': 24, 'description': 'eded', 'scene': '', 'start': 1, 'mtime': '1391012417', 'owner': 'tlhomme', 'ctime': '1391012417'}
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_older_version.dict:
--------------------------------------------------------------------------------
1 | {'srcSphere:sphere': {
2 | 'rotateX': ('doubleAngle', 45.0),
3 | 'testEnum': ('enum', 1),
4 | 'translateX': ('doubleLinear', 0.0),
5 | 'translateY': ('doubleLinear', 8.0),
6 | 'translateZ': ('doubleLinear', -12.0),
7 | 'rotateY': ('doubleAngle', 50.0),
8 | 'testFloat': ('double', 0.66600000000000004),
9 | 'testAnimated': ('double', 0.0),
10 | 'scaleX': ('double', 0.25),
11 | 'scaleY': ('double', 4.6600000000000001),
12 | 'visibility': ('bool', True),
13 | 'testString': ('string', u'Hello world'),
14 | 'testVectorX': ('double', 0.20000000000000001),
15 | 'testVectorY': ('double', 1.3999999999999999),
16 | 'rotateZ': ('doubleAngle', 90.0),
17 | 'testVectorZ': ('double', 2.6000000000000001),
18 | 'scaleZ': ('double', 0.5),
19 | 'testInteger': ('long', 5),
20 | 'testBoolean': ('bool', True),
21 | 'testConnect': ('double', 8.0)
22 | },
23 | 'srcSphere:lockedNode': {
24 | 'translateX': ('doubleLinear', 0.0),
25 | 'translateY': ('doubleLinear', 5.0),
26 | 'translateZ': ('doubleLinear', 0.0),
27 | 'scaleX': ('double', 1.0),
28 | 'scaleY': ('double', 1.0),
29 | 'visibility': ('bool', True),
30 | 'rotateX': ('doubleAngle', 0.0),
31 | 'rotateY': ('doubleAngle', 0.0),
32 | 'rotateZ': ('doubleAngle', 0.0),
33 | 'scaleZ': ('double', 1.0)
34 | }}
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_pose.pose:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "mayaSceneFile": "C:/Users/hovel/Dropbox/git/site-packages/studiolibrary/packages/mutils/tests/data/test_pose.ma",
4 | "version": "1.0.0",
5 | "user": "Hovel",
6 | "mayaVersion": "2017",
7 | "ctime": "1518341544"
8 | }
9 | ,
10 | "objects": {
11 | "srcSphere:offset": {
12 | "attrs": {}
13 | },
14 | "srcSphere:sphere": {
15 | "attrs": {
16 | "testInteger": {
17 | "type": "long",
18 | "value": 5
19 | },
20 | "testProxy": {
21 | "type": "double",
22 | "value": 1.0
23 | },
24 | "scaleY": {
25 | "type": "double",
26 | "value": 1.5
27 | },
28 | "testLimit": {
29 | "type": "double",
30 | "value": 10.0
31 | },
32 | "testConnect": {
33 | "type": "double",
34 | "value": 8.0
35 | },
36 | "testEnum": {
37 | "type": "enum",
38 | "value": 1
39 | },
40 | "scaleX": {
41 | "type": "double",
42 | "value": 0.25
43 | },
44 | "testString": {
45 | "type": "string",
46 | "value": "Hello world"
47 | },
48 | "scaleZ": {
49 | "type": "double",
50 | "value": 0.5
51 | },
52 | "rotateX": {
53 | "type": "doubleAngle",
54 | "value": 45.0
55 | },
56 | "rotateY": {
57 | "type": "doubleAngle",
58 | "value": 25.0
59 | },
60 | "rotateZ": {
61 | "type": "doubleAngle",
62 | "value": 90.0
63 | },
64 | "translateX": {
65 | "type": "doubleLinear",
66 | "value": 0.0
67 | },
68 | "translateY": {
69 | "type": "doubleLinear",
70 | "value": 8.0
71 | },
72 | "translateZ": {
73 | "type": "doubleLinear",
74 | "value": -12.0
75 | },
76 | "visibility": {
77 | "type": "bool",
78 | "value": true
79 | },
80 | "testFloat": {
81 | "type": "double",
82 | "value": 0.666
83 | },
84 | "testAnimated": {
85 | "type": "double",
86 | "value": 0.0
87 | },
88 | "testVectorX": {
89 | "type": "double",
90 | "value": 0.2
91 | },
92 | "testVectorY": {
93 | "type": "double",
94 | "value": 1.4
95 | },
96 | "testVectorZ": {
97 | "type": "double",
98 | "value": 2.6
99 | },
100 | "testBoolean": {
101 | "type": "bool",
102 | "value": true
103 | }
104 | }
105 | },
106 | "srcSphere:lockedNode": {
107 | "attrs": {
108 | "translateX": {
109 | "type": "doubleLinear",
110 | "value": 0.0
111 | },
112 | "translateY": {
113 | "type": "doubleLinear",
114 | "value": 0.0
115 | },
116 | "translateZ": {
117 | "type": "doubleLinear",
118 | "value": 0.0
119 | },
120 | "scaleX": {
121 | "type": "double",
122 | "value": 1.0
123 | },
124 | "scaleY": {
125 | "type": "double",
126 | "value": 1.0
127 | },
128 | "visibility": {
129 | "type": "bool",
130 | "value": true
131 | },
132 | "rotateX": {
133 | "type": "doubleAngle",
134 | "value": 0.0
135 | },
136 | "rotateY": {
137 | "type": "doubleAngle",
138 | "value": 0.0
139 | },
140 | "rotateZ": {
141 | "type": "doubleAngle",
142 | "value": 0.0
143 | },
144 | "scaleZ": {
145 | "type": "double",
146 | "value": 1.0
147 | }
148 | }
149 | }
150 | }
151 | }
--------------------------------------------------------------------------------
/src/mutils/tests/data/test_poseplugin.pose/.studiolibrary/record.dict:
--------------------------------------------------------------------------------
1 | {'owner': 'hovel', 'ctime': '1437148163', 'mtime': '1437148163'}
--------------------------------------------------------------------------------
/src/mutils/tests/run.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 | """
13 | # Example:
14 | # RUN TEST SUITE
15 | import mutils.tests
16 | reload(mutils.tests)
17 | mutils.tests.run()
18 | """
19 | import unittest
20 |
21 | import logging
22 |
23 |
24 | logging.basicConfig(
25 | filemode='w',
26 | level=logging.DEBUG,
27 | format='%(levelname)s: %(funcName)s: %(message)s',
28 | )
29 |
30 |
31 | def testSuite():
32 | """
33 | Return a test suite containing all the tests.
34 |
35 | :rtype: unittest.TestSuite
36 | """
37 | import test_pose
38 | import test_anim
39 | import test_match
40 | import test_utils
41 | import test_attribute
42 | import test_mirrortable
43 |
44 | suite = unittest.TestSuite()
45 |
46 | s = unittest.makeSuite(test_pose.TestPose, 'test')
47 | suite.addTest(s)
48 |
49 | s = unittest.makeSuite(test_anim.TestAnim, 'test')
50 | suite.addTest(s)
51 |
52 | s = unittest.makeSuite(test_utils.TestUtils, 'test')
53 | suite.addTest(s)
54 |
55 | s = unittest.makeSuite(test_match.TestMatch, 'test')
56 | suite.addTest(s)
57 |
58 | s = unittest.makeSuite(test_attribute.TestAttribute, 'test')
59 | suite.addTest(s)
60 |
61 | s = unittest.makeSuite(test_mirrortable.TestMirrorTable, 'test')
62 | suite.addTest(s)
63 |
64 | return suite
65 |
66 |
67 | def run():
68 | """
69 | Call from within Maya to run all valid tests.
70 | """
71 | import mutils.animation
72 | mutils.animation.FIX_SAVE_ANIM_REFERENCE_LOCKED_ERROR = True
73 |
74 | tests = unittest.TextTestRunner()
75 | tests.run(testSuite())
76 |
--------------------------------------------------------------------------------
/src/mutils/tests/test_anim.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import unittest
14 |
15 | import mutils
16 |
17 | import test_base
18 |
19 |
20 | class TestAnim(test_base.TestBase):
21 |
22 | def setUp(self):
23 | """
24 | """
25 |
26 | def save(self, bakeConnected=False):
27 | """
28 | Test saving the animation to disc.
29 | """
30 | self.open()
31 | anim = mutils.Animation.fromObjects(self.srcObjects)
32 | anim.save(self.dstPath, bakeConnected=bakeConnected)
33 |
34 | # def test_older_version(self):
35 | # """
36 | # Test animation parser for an older animation format
37 | # """
38 | # srcPath = self.dataPath("test_older_version.anim")
39 | # a = mutils.Animation.fromPath(srcPath)
40 |
41 | def test_load_replace_completely(self):
42 | """
43 | Test loading the animation with replace completely option.
44 | """
45 | self.srcPath = self.dataPath("test_anim.ma")
46 | self.dstPath = self.dataPath("test_load_replace_completely.anim")
47 | self.save()
48 |
49 | anim = mutils.Animation.fromPath(self.dstPath)
50 | anim.load(self.dstObjects)
51 |
52 | self.assertEqualAnimation()
53 |
54 | def test_bake_connected(self):
55 | """
56 | Test saving animation with the option bake connected.
57 | """
58 | srcPath = self.dataPath("test_bake_connected.ma")
59 | dstPath = self.dataPath("test_bake_connected.anim")
60 |
61 | srcObjects = [
62 | "srcSphere:group",
63 | "srcSphere:lockedNode",
64 | "srcSphere:offset",
65 | "srcSphere:sphere"
66 | ]
67 |
68 | dstObjects = [
69 | "dstSphere:group",
70 | "dstSphere:lockedNode",
71 | "dstSphere:offset",
72 | "dstSphere:sphere"
73 | ]
74 |
75 | self.open(path=srcPath)
76 |
77 | anim = mutils.Animation.fromObjects(srcObjects)
78 | anim.save(dstPath, bakeConnected=True)
79 |
80 | anim = mutils.Animation.fromPath(dstPath)
81 | anim.load(dstObjects)
82 |
83 | self.assertEqualAnimation()
84 |
85 | def test_load_replace(self):
86 | """
87 | Test loading the animation with the option Replace.
88 | """
89 | self.srcPath = self.dataPath("test_anim.ma")
90 | self.dstPath = self.dataPath("test_load_replace.anim")
91 | self.save()
92 |
93 | anim = mutils.Animation.fromPath(self.dstPath)
94 | anim.load(self.dstObjects, option=mutils.PasteOption.Replace, startFrame=5)
95 |
96 | def test_load_insert(self):
97 | """
98 | Test loading the animation with the option Insert.
99 | """
100 | self.srcPath = self.dataPath("test_anim.ma")
101 | self.dstPath = self.dataPath("test_load_insert.anim")
102 | self.save()
103 |
104 | anim = mutils.Animation.fromPath(self.dstPath)
105 | anim.load(self.dstObjects, option=mutils.PasteOption.Insert, startFrame=5)
106 |
107 |
108 | def testSuite():
109 | """
110 | Return the test suite for the test case.
111 |
112 | :rtype: unittest.TestSuite
113 | """
114 | suite = unittest.TestSuite()
115 | s = unittest.makeSuite(TestAnim, 'test')
116 | suite.addTest(s)
117 | return suite
118 |
119 |
120 | def run():
121 | """
122 | Call from within Maya to run all valid tests.
123 | """
124 | tests = unittest.TextTestRunner()
125 | tests.run(testSuite())
126 |
--------------------------------------------------------------------------------
/src/mutils/tests/test_base.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import os
14 | import unittest
15 |
16 | import maya.cmds
17 |
18 | import mutils
19 |
20 |
21 | TEST_DATA_DIR = os.path.join(os.path.dirname(mutils.__file__), "tests", "data")
22 |
23 |
24 | class TestBase(unittest.TestCase):
25 |
26 | def __init__(self, *args):
27 | """
28 | :type args: list
29 | """
30 | unittest.TestCase.__init__(self, *args)
31 |
32 | self.srcPath = os.path.join(TEST_DATA_DIR, "test_pose.ma")
33 | self.dstPath = os.path.join(TEST_DATA_DIR, "test_pose.pose")
34 |
35 | self.srcObjects = [
36 | "srcSphere:lockedNode",
37 | "srcSphere:offset",
38 | "srcSphere:sphere",
39 | ]
40 |
41 | self.dstObjects = [
42 | "dstSphere:lockedNode",
43 | "dstSphere:offset",
44 | "dstSphere:sphere",
45 | ]
46 |
47 | self.srcNamespaces = ["srcSphere"]
48 | self.dstNamespaces = ["dstSphere"]
49 |
50 | def dataDir(self):
51 | """
52 | Return the location on disc to the test data.
53 |
54 | :rtype: str
55 | """
56 | return os.path.join(os.path.dirname(mutils.__file__), "tests", "data")
57 |
58 | def dataPath(self, fileName):
59 | """
60 | Return data location with the given fileName.
61 |
62 | :rtype: str
63 | """
64 | return os.path.join(self.dataDir(), fileName)
65 |
66 | def open(self, path=None):
67 | """
68 | Open the specified file in Maya.
69 |
70 | :type path: str | None
71 | """
72 | if path is None:
73 | path = self.srcPath
74 |
75 | maya.cmds.file(
76 | path,
77 | open=True,
78 | force=True,
79 | ignoreVersion=True,
80 | executeScriptNodes=False,
81 | )
82 |
83 | def listAttr(self, srcObjects=None, dstObjects=None):
84 | """
85 | Return the source & destination attributes for the given objects.
86 |
87 | :rtype: list[(mutils.Attribute, mutils.Attribute)]
88 | """
89 | attrs = []
90 | srcObjects = srcObjects or self.srcObjects
91 | dstObjects = dstObjects or self.dstObjects
92 |
93 | for i, srcObj in enumerate(srcObjects):
94 | srcObj = srcObjects[i]
95 | dstObj = dstObjects[i]
96 |
97 | srcAttrs = maya.cmds.listAttr(srcObj, keyable=True, unlocked=True, scalar=True) or []
98 |
99 | for srcAttr in srcAttrs:
100 | srcAttribute = mutils.Attribute(srcObj, srcAttr)
101 | dstAttribute = mutils.Attribute(dstObj, srcAttr)
102 | attrs.append((srcAttribute, dstAttribute))
103 |
104 | return attrs
105 |
106 | def assertEqualAnimation(
107 | self,
108 | srcObjects=None,
109 | dstObjects=None,
110 | ):
111 | """
112 | Test that the animation for the given objects is equal.
113 |
114 | If the animation curves do not compare equal, the test will fail.
115 |
116 | :type srcObjects: list[str] | None
117 | :type dstObjects: list[str] | None
118 | """
119 | for frame in [1, 10, 24]:
120 | maya.cmds.currentTime(frame)
121 | self.assertEqualAttributeValues(srcObjects, dstObjects)
122 |
123 | def assertEqualAttributeValues(
124 | self,
125 | srcObjects=None,
126 | dstObjects=None,
127 | ):
128 | """
129 | Test that the attribute values for the given objects are equal.
130 |
131 | If the values do not compare equal, the test will fail.
132 |
133 | :type srcObjects: list[str] | None
134 | :type dstObjects: list[str] | None
135 | """
136 | for srcAttribute, dstAttribute in self.listAttr(srcObjects, dstObjects):
137 |
138 | if not dstAttribute.exists():
139 | continue
140 |
141 | msg = "Attribute value is not equal! {0} != {1}"
142 | msg = msg.format(srcAttribute.fullname(), dstAttribute.fullname())
143 | self.assertEqual(srcAttribute.value(), dstAttribute.value(), msg)
144 |
--------------------------------------------------------------------------------
/src/mutils/tests/test_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import unittest
14 |
15 | import mutils.animation
16 |
17 |
18 | class TestUtils(unittest.TestCase):
19 |
20 | def test_clamp_range(self):
21 | """
22 | Test the clamp range command
23 | """
24 | msg = "Incorrect clamp range"
25 |
26 | # Test clamp range on both min and max
27 | clampRange = mutils.animation.clampRange((15, 35), (20, 30))
28 | assert (20, 30) == clampRange, msg
29 |
30 | # Test clamp range on min time
31 | clampRange = mutils.animation.clampRange((10, 25), (20, 30))
32 | assert (20, 25) == clampRange, msg
33 |
34 | # Test clamp range on man time
35 | clampRange = mutils.animation.clampRange((25, 40), (20, 30))
36 | assert (25, 30) == clampRange, msg
37 |
38 | # Test min out of bounds error
39 | def test_exception():
40 | clampRange = mutils.animation.clampRange((5, 15), (20, 30))
41 | self.assertRaises(mutils.animation.OutOfBoundsError, test_exception)
42 |
43 | # Test max out of bounds error
44 | def test_exception():
45 | clampRange = mutils.animation.clampRange((65, 95), (20, 30))
46 | self.assertRaises(mutils.animation.OutOfBoundsError, test_exception)
47 |
48 |
49 | def testSuite():
50 | """
51 | Return the test suite for this module.
52 |
53 | :rtype: unittest.TestSuite
54 | """
55 | suite = unittest.TestSuite()
56 | s = unittest.makeSuite(TestUtils, 'test')
57 | suite.addTest(s)
58 | return suite
59 |
60 |
61 | def run():
62 | """
63 | Call from within Maya to run all valid tests.
64 |
65 | Example:
66 |
67 | import mutils.tests.test_attribute
68 | reload(mutils.tests.test_attribute)
69 | mutils.tests.test_attribute.run()
70 | """
71 | tests = unittest.TextTestRunner()
72 | tests.run(testSuite())
73 |
--------------------------------------------------------------------------------
/src/studiolibrary/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | __version__ = "2.20.2"
14 |
15 |
16 | def version():
17 | """
18 | Return the current version of the Studio Library
19 |
20 | :rtype: str
21 | """
22 | return __version__
23 |
24 |
25 | from studiolibrary import config
26 | from studiolibrary import resource
27 | from studiolibrary.utils import *
28 | from studiolibrary.library import Library
29 | from studiolibrary.libraryitem import LibraryItem
30 | from studiolibrary.main import main
31 |
--------------------------------------------------------------------------------
/src/studiolibrary/config.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import os
14 | import json
15 |
16 |
17 | _config = None
18 |
19 |
20 | def get(*args):
21 | """
22 | Get values from the config.
23 |
24 | :rtype: str
25 | """
26 | global _config
27 |
28 | if not _config:
29 | _config = read(paths())
30 |
31 | return _config.get(*args)
32 |
33 |
34 | def set(key, value):
35 |
36 | global _config
37 |
38 | if not _config:
39 | _config = read(paths())
40 |
41 | _config[key] = value
42 |
43 |
44 | def paths():
45 | """
46 | Return all possible config paths.
47 |
48 | :rtype: list[str]
49 | """
50 | cwd = os.path.dirname(__file__)
51 | paths_ = [os.path.join(cwd, "config", "default.json")]
52 |
53 | path = os.environ.get("STUDIO_LIBRARY_CONFIG_PATH")
54 | path = path or os.path.join(cwd, "config", "config.json")
55 |
56 | if not os.path.exists(path):
57 | cwd = os.path.dirname(os.path.dirname(cwd))
58 | path = os.path.join(cwd, "config", "config.json")
59 |
60 | if os.path.exists(path):
61 | paths_.append(path)
62 |
63 | return paths_
64 |
65 |
66 | def read(paths):
67 | """
68 | Read all paths and overwrite the keys with each successive file.
69 |
70 | A custom config parser for passing JSON files.
71 |
72 | We use this instead of the standard ConfigParser as the JSON format
73 | can support list and dict types.
74 |
75 | This parser can also support comments using the following style "//"
76 |
77 | :type paths: list[str]
78 | :rtype: dict
79 | """
80 | conf = {}
81 |
82 | for path in paths:
83 | lines = []
84 |
85 | with open(path) as f:
86 | for line in f.readlines():
87 | if not line.strip().startswith('//'):
88 | lines.append(line)
89 |
90 | data = '\n'.join(lines)
91 | if data:
92 | conf.update(json.loads(data))
93 |
94 | return conf
95 |
--------------------------------------------------------------------------------
/src/studiolibrary/config/default.json:
--------------------------------------------------------------------------------
1 | // This is the default config file and should NOT be changed.
2 | //
3 | // There are two ways to create a custom config.
4 | //
5 | // 1. You can create a "config.json" at repo/config/config.json.
6 | // This file will override any keys in this default.json file
7 | // and will be ignored by git.
8 | //
9 | // 2. The other way is to create an environment variable with the name
10 | // STUDIO_LIBRARY_CONFIG_PATH. The value of this variable should be the
11 | // full path to your config.json file.
12 | //
13 | // 3. Or you could use code to modify the config before loading the window.
14 | // import studiolibrary
15 | // studiolibrary.config.set("recursiveSearchDepth", 6)
16 | // studiolibrary.main()
17 |
18 | {
19 | // The database path is used for caching the library items.
20 | // You can use environment variables within the path. eg: {HOME}
21 | "databasePath": "{root}/.studiolibrary/database.json",
22 |
23 | // The temp location used for saving out items and thumbnails
24 | "tempPath": "{temp}/StudioLibrary/{user}",
25 |
26 | // The metadata path used for each item. Used for tags, item color etc
27 | // eg: /library/data/animation/nemo/.metadata
28 | "metadataPath": "{path}/.studiolibrary/metadata.json",
29 |
30 | // Used for saving persistent user data
31 | "settingsPath": "{local}/StudioLibrary/LibraryWidget.json",
32 |
33 | // The maximum walking depth from the root directory
34 | "recursiveSearchDepth": 5,
35 |
36 | // A list of paths to ignore when walking the root directory
37 | "ignorePaths": ["/."],
38 |
39 | // The command used to show a path in the file explorer
40 | //"showInFolderCmd": "konqueror \"{path}\"&",
41 |
42 | // Enables the scale factor option in the setting dialog
43 | // This might be useful when using high-DPI devices like a 4k monitor
44 | "scaleFactorEnabled": true,
45 |
46 | // Check if there are any new versions available on start up
47 | "checkForUpdatesEnabled": true,
48 |
49 | // A list of the default item plugins
50 | "itemRegistry": [
51 | // This is an example item for development
52 | // "studiolibrarymaya.exampleitem.ExampleItem",
53 | // The maya file item is in development
54 | // "studiolibrarymaya.mayafileitem.MayaFileItem",
55 | "studiolibrarymaya.poseitem.PoseItem",
56 | "studiolibrarymaya.animitem.AnimItem",
57 | "studiolibrarymaya.mirroritem.MirrorItem",
58 | "studiolibrarymaya.setsitem.SetsItem",
59 | "studiolibrary.folderitem.FolderItem"
60 | ]
61 | }
--------------------------------------------------------------------------------
/src/studiolibrary/main.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import studioqt
14 | import studiolibrary
15 |
16 |
17 | def main(*args, **kwargs):
18 | """
19 | Convenience method for creating/showing a library widget instance.
20 |
21 | return studiolibrary.LibraryWindow.instance(
22 | name="",
23 | path="",
24 | show=True,
25 | lock=False,
26 | superusers=None,
27 | lockRegExp=None,
28 | unlockRegExp=None
29 | )
30 |
31 | :rtype: studiolibrary.LibraryWindow
32 | """
33 | # Reload all Studio Library modules when Shift is pressed.
34 | # This is for developers to test their changes in a DCC application.
35 | if studioqt.isShiftModifier():
36 | import studiolibrary
37 | studiolibrary.reload()
38 |
39 | # Register all the items from the config file.
40 | import studiolibrary
41 | studiolibrary.registerItems()
42 |
43 | if studiolibrary.isMaya():
44 | from studiolibrarymaya import mayalibrarywindow
45 | libraryWindow = mayalibrarywindow.MayaLibraryWindow.instance(*args, **kwargs)
46 | else:
47 | from studiolibrary import librarywindow
48 | libraryWindow = librarywindow.LibraryWindow.instance(*args, **kwargs)
49 |
50 | return libraryWindow
51 |
52 |
53 | if __name__ == "__main__":
54 |
55 | # Run the Studio Library in a QApplication instance
56 | import studioqt
57 | with studioqt.app():
58 | studiolibrary.main()
59 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import os
14 |
15 | from studioqt import Icon
16 | from studioqt import Pixmap
17 |
18 | from . import utils
19 |
20 |
21 | PATH = os.path.abspath(__file__)
22 | DIRNAME = os.path.dirname(PATH)
23 | RESOURCE_DIRNAME = os.path.join(DIRNAME, "resource")
24 |
25 |
26 | def get(*args):
27 | """
28 | This is a convenience function for returning the resource path.
29 |
30 | :rtype: str
31 | """
32 | path = os.path.join(RESOURCE_DIRNAME, *args)
33 | return utils.normPath(path)
34 |
35 |
36 | def icon(*args, **kwargs):
37 | """
38 | Return an Icon object from the given resource name.
39 |
40 | :rtype: str
41 | """
42 | path = get("icons", *args)
43 | return Icon(pixmap(path, **kwargs))
44 |
45 |
46 | def pixmap(name, scope="icons", extension="png", color=None):
47 | """
48 | Return a Pixmap object from the given resource name.
49 |
50 | :type name: str
51 | :type scope: str
52 | :type extension: str
53 | :type color: str
54 | :rtype: QtWidgets.QPixmap
55 | """
56 | if name.endswith(".svg"):
57 | extension = ""
58 |
59 | path = ""
60 |
61 | if os.path.exists(name):
62 | path = name
63 |
64 | elif extension:
65 | path = get(scope, name + "." + extension)
66 | if not os.path.exists(path):
67 | path = get(scope, name + ".svg")
68 |
69 | p = Pixmap(path)
70 |
71 | if color:
72 | p.setColor(color)
73 |
74 | return p
75 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-Bold.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-BoldItalic.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-ExtraBold.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-ExtraBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-ExtraBoldItalic.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-Italic.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-Light.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-LightItalic.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-Regular.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-SemiBold.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/fonts/OpenSans-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/fonts/OpenSans-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/add.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/add_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/add_28.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/archive.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/arrows-rotate.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/asset.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/assets.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/bars.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/blank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/blank.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/book.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/branch_closed_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/branch_closed_black.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/branch_closed_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/branch_closed_white.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/branch_open_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/branch_open_black.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/branch_open_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/branch_open_white.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/camera-alt.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/camera.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/cancel.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/caret-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/caret-right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/character.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/check_box_checked_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/check_box_checked_black.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/check_box_checked_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/check_box_checked_white.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/check_box_unchecked_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/check_box_unchecked_black.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/check_box_unchecked_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/check_box_unchecked_white.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/circle.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/cloud.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/cog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/cog.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/columns-3.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/critical.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/critical.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/cross.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/database.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/delete.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/drop_arrow_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/drop_arrow_black.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/drop_arrow_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/drop_arrow_white.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/environment.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/error.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/expand.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/eye-slash.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/eye.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/face.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/favorite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/file-alt.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/file.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/filter.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/folder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/folder_collapsed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/folder_collapsed.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/folder_expanded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/folder_expanded.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/folder_item.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/folder_item.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/folder_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/folder_open.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/folder_open.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/globe.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/groupby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/groupby.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/hand.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/header.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/icon.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/image.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/inbox.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/info.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/layers.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/lock.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/logo.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/logo_high.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/logo_high.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/logo_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/logo_white.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/magnifying-glass.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/plus-large.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/plus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/preview_placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/preview_placeholder.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/question.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/radio_button_checked_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/radio_button_checked_black.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/radio_button_checked_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/radio_button_checked_white.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/radio_button_unchecked_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/radio_button_unchecked_black.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/radio_button_unchecked_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/radio_button_unchecked_white.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/search.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/settings.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/share.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/shot.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/sliders.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/sortby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/sortby.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/sync.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/sync.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/tag.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/thumbnail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/thumbnail.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/thumbnail_solid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/thumbnail_solid.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/times.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/trash.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/tree.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/users.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/vehicle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/video.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/view_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/view_all.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/view_compact.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/view_compact.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/view_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/view_settings.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrary/resource/icons/warning.png
--------------------------------------------------------------------------------
/src/studiolibrary/resource/icons/xmark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/PlaceholderWidget.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Frame
4 |
5 |
6 |
7 | 0
8 | 0
9 | 229
10 | 639
11 |
12 |
13 |
14 | Frame
15 |
16 |
17 | QFrame::NoFrame
18 |
19 |
20 | QFrame::Plain
21 |
22 |
23 | 0
24 |
25 |
26 | -
27 |
28 |
29 |
30 | 0
31 | 10
32 |
33 |
34 |
35 | QFrame::NoFrame
36 |
37 |
38 | QFrame::Plain
39 |
40 |
41 | 0
42 |
43 |
44 |
-
45 |
46 |
47 |
48 | 96
49 | 96
50 |
51 |
52 |
53 |
54 | 96
55 | 96
56 |
57 |
58 |
59 |
60 |
61 |
62 | ../resource/icons/preview_placeholder.png
63 |
64 |
65 | true
66 |
67 |
68 |
69 |
70 |
71 |
72 | -
73 |
74 |
75 |
76 | 0
77 | 2
78 |
79 |
80 |
81 | QFrame::NoFrame
82 |
83 |
84 | QFrame::Plain
85 |
86 |
87 | 0
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from .lightbox import Lightbox
14 | from .lineedit import LineEdit
15 | from .sortbymenu import SortByMenu
16 | from .groupbymenu import GroupByMenu
17 | from .filterbymenu import FilterByMenu
18 | from .messagebox import MessageBox, createMessageBox
19 | from .toastwidget import ToastWidget
20 | from .searchwidget import SearchWidget
21 | from .statuswidget import StatusWidget
22 | from .previewwidget import PreviewWidget
23 | from .menubarwidget import MenuBarWidget
24 | from .sidebarwidget import SidebarWidget
25 | from .groupboxwidget import GroupBoxWidget
26 | from .placeholderwidget import PlaceholderWidget
27 | from .itemswidget.item import Item
28 | from .itemswidget.groupitem import GroupItem
29 | from .itemswidget.itemswidget import ItemsWidget
30 | from .themesmenu import Theme, ThemesMenu
31 | from .librariesmenu import LibrariesMenu
32 | from .slideraction import SliderAction
33 | from .separatoraction import SeparatorAction
34 | from .iconpicker import IconPickerAction, IconPickerWidget
35 | from .colorpicker import ColorPickerAction, ColorPickerWidget
36 | from .sequencewidget import ImageSequenceWidget
37 | from .formwidget import FormWidget, FormDialog
38 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/groupboxwidget.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import logging
14 |
15 | from studiovendor.Qt import QtCore
16 | from studiovendor.Qt import QtWidgets
17 |
18 | from . import settings
19 |
20 | import studioqt
21 | import studiolibrary
22 |
23 |
24 | logger = logging.getLogger(__name__)
25 |
26 |
27 | class GroupBoxWidget(QtWidgets.QFrame):
28 |
29 | toggled = QtCore.Signal(bool)
30 |
31 | def __init__(self, title, widget, persistent=False, *args, **kwargs):
32 | super(GroupBoxWidget, self).__init__(*args, **kwargs)
33 |
34 | self._widget = None
35 | self._persistent = None
36 |
37 | layout = QtWidgets.QVBoxLayout()
38 | layout.setContentsMargins(0, 0, 0, 0)
39 | layout.setSpacing(0)
40 |
41 | self.setLayout(layout)
42 |
43 | self._titleWidget = QtWidgets.QPushButton(self)
44 | self._titleWidget.setCheckable(True)
45 | self._titleWidget.setText(title)
46 | self._titleWidget.setObjectName("title")
47 | self._titleWidget.toggled.connect(self._toggled)
48 |
49 | on_path = studiolibrary.resource.get("icons", "caret-down.svg")
50 | off_path = studiolibrary.resource.get("icons", "caret-right.svg")
51 | icon = studioqt.Icon.fa(on_path, color="rgba(255,255,255,200)", off=off_path)
52 | self._titleWidget.setIcon(icon)
53 |
54 | self.layout().addWidget(self._titleWidget)
55 |
56 | self._widgetFrame = QtWidgets.QFrame(self)
57 | self._widgetFrame.setObjectName("frame")
58 |
59 | layout = QtWidgets.QVBoxLayout()
60 | layout.setContentsMargins(0, 0, 0, 0)
61 | layout.setSpacing(0)
62 |
63 | self._widgetFrame.setLayout(layout)
64 |
65 | self.layout().addWidget(self._widgetFrame)
66 |
67 | if widget:
68 | self.setWidget(widget)
69 |
70 | self.setPersistent(persistent)
71 |
72 | def setPersistent(self, persistent):
73 | """
74 | Save and load the state of the widget to disk.
75 |
76 | :type persistent: bool
77 | """
78 | self._persistent = persistent
79 | self.loadSettings()
80 |
81 | def title(self):
82 | """
83 | Get the title for the group box.
84 |
85 | :rtype: str
86 | """
87 | return self._titleWidget.text()
88 |
89 | def setWidget(self, widget):
90 | """
91 | Set the widget to hide when the user clicks the title.
92 |
93 | :type widget: QWidgets.QWidget
94 | """
95 | self._widget = widget
96 | # self._widget.setParent(self._widgetFrame)
97 | # self._widgetFrame.layout().addWidget(self._widget)
98 |
99 | def _toggled(self, visible):
100 | """
101 | Triggered when the user clicks the title.
102 |
103 | :type visible: bool
104 | """
105 | self.saveSettings()
106 | self.setChecked(visible)
107 | self.toggled.emit(visible)
108 |
109 | def isChecked(self):
110 | """
111 | Check the checked state for the group box.
112 |
113 | :rtype: bool
114 | """
115 | return self._titleWidget.isChecked()
116 |
117 | def setChecked(self, checked):
118 | """
119 | Overriding this method to hide the widget when the state changes.
120 |
121 | :type checked: bool
122 | """
123 | self._titleWidget.setChecked(checked)
124 | if self._widget:
125 | self._widget.setVisible(checked)
126 |
127 | def saveSettings(self):
128 | """Save the state to disc."""
129 | if self._persistent:
130 |
131 | if not self.objectName():
132 | raise NameError("No object name set for persistent widget.")
133 |
134 | data = {self.objectName(): {"checked": self.isChecked()}}
135 | settings.save(data)
136 |
137 | def loadSettings(self):
138 | """Load the state to disc."""
139 | if self._persistent:
140 |
141 | if not self.objectName():
142 | raise NameError("No object name set for persistent widget.")
143 |
144 | data = settings.read()
145 | data = data.get(self.objectName(), {})
146 |
147 | if isinstance(data, dict):
148 | checked = data.get("checked", True)
149 | self.setChecked(checked)
150 |
151 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/groupbymenu.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from functools import partial
14 |
15 | from studiovendor.Qt import QtGui
16 | from studiovendor.Qt import QtWidgets
17 |
18 | from .separatoraction import SeparatorAction
19 |
20 |
21 | class GroupByMenu(QtWidgets.QMenu):
22 |
23 | def __init__(self, name, parent, dataset):
24 | super(GroupByMenu, self).__init__(name, parent)
25 |
26 | self._dataset = dataset
27 | self.aboutToShow.connect(self.populateMenu)
28 |
29 | def setDataset(self, dataset):
30 | """
31 | Set the dataset model for the menu:
32 |
33 | :type dataset: studiolibrary.Dataset
34 | """
35 | self._dataset = dataset
36 |
37 | def dataset(self):
38 | """
39 | Get the dataset model for the menu.
40 |
41 | :rtype: studiolibrary.Dataset
42 | """
43 | return self._dataset
44 |
45 | def setGroupBy(self, groupName, groupOrder):
46 | """
47 | Set the group by value for the dataset.
48 |
49 | :type groupName: str
50 | :type groupOrder: str
51 | """
52 | if groupName:
53 | value = [groupName + ":" + groupOrder]
54 | else:
55 | value = None
56 |
57 | self.dataset().setGroupBy(value)
58 | self.dataset().search()
59 |
60 | def populateMenu(self):
61 | """
62 | Show the menu options.
63 | """
64 | self.clear()
65 |
66 | groupBy = self.dataset().groupBy()
67 | if groupBy:
68 | currentField = groupBy[0].split(":")[0]
69 | currentOrder = "dsc" if "dsc" in groupBy[0] else "asc"
70 | else:
71 | currentField = ""
72 | currentOrder = ""
73 |
74 | action = SeparatorAction("Group By", self)
75 | self.addAction(action)
76 |
77 | action = self.addAction("None")
78 | action.setCheckable(True)
79 |
80 | if not currentField:
81 | action.setChecked(True)
82 |
83 | callback = partial(self.setGroupBy, None, None)
84 | action.triggered.connect(callback)
85 |
86 | fields = self.dataset().fields()
87 |
88 | for field in fields:
89 |
90 | if not field.get("groupable"):
91 | continue
92 |
93 | name = field.get("name")
94 |
95 | action = self.addAction(name.title())
96 | action.setCheckable(True)
97 |
98 | if currentField == name:
99 | action.setChecked(True)
100 | else:
101 | action.setChecked(False)
102 |
103 | callback = partial(self.setGroupBy, name, currentOrder)
104 | action.triggered.connect(callback)
105 |
106 | action = SeparatorAction("Group Order", self)
107 | self.addAction(action)
108 |
109 | action = self.addAction("Ascending")
110 | action.setCheckable(True)
111 | action.setChecked(currentOrder == "asc")
112 |
113 | callback = partial(self.setGroupBy, currentField, "asc")
114 | action.triggered.connect(callback)
115 |
116 | action = self.addAction("Descending")
117 | action.setCheckable(True)
118 | action.setChecked(currentOrder == "dsc")
119 |
120 | callback = partial(self.setGroupBy, currentField, "dsc")
121 | action.triggered.connect(callback)
122 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/itemswidget/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/itemswidget/itemdelegate.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor.Qt import QtWidgets
14 |
15 | from .groupitem import GroupItem
16 |
17 |
18 | class ItemDelegate(QtWidgets.QStyledItemDelegate):
19 |
20 | def __init__(self):
21 | """
22 | This class is used to display data for the items in a ItemsWidget.
23 | """
24 | QtWidgets.QStyledItemDelegate.__init__(self)
25 |
26 | self._itemsWidget = None
27 |
28 | def itemsWidget(self):
29 | """
30 | Return the ItemsWidget that contains the item delegate.
31 |
32 | :rtype: studioqt.ItemsWidget
33 | """
34 | return self._itemsWidget
35 |
36 | def setItemsWidget(self, itemsWidget):
37 | """
38 | Set the ItemsWidget for the delegate.
39 |
40 | :type itemsWidget: studioqt.ItemsWidget
41 | :rtype: None
42 | """
43 | self._itemsWidget = itemsWidget
44 |
45 | def sizeHint(self, option, index):
46 | """
47 | Return the size for the given index.
48 |
49 | :type option: QtWidgets.QStyleOptionViewItem
50 | :type index: QtCore.QModelIndex
51 | :rtype: QtCore.QSize
52 | """
53 | #This will be called for each row.
54 | item = self.itemsWidget().itemFromIndex(index)
55 |
56 | if isinstance(item, GroupItem):
57 | return item.sizeHint()
58 |
59 | return self.itemsWidget().itemSizeHint(index)
60 |
61 | def paint(self, painter, option, index):
62 | """
63 | Paint performs low-level painting for the given model index.
64 |
65 | :type painter: QtWidgets.QPainter
66 | :type option: QtWidgets.QStyleOptionViewItem
67 | :type index: QtCore.QModelIndex
68 | :rtype: None
69 | """
70 | item = self.itemsWidget().itemFromIndex(index)
71 | item.paint(painter, option, index)
72 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/librariesmenu.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 | """
13 | Example:
14 |
15 | from PySide2 import QtGui
16 | import studiolibrary.widgets
17 | menu = studiolibrary.widgets.LibrariesMenu()
18 | point = QtGui.QCursor.pos()
19 | menu.exec_(point)
20 | """
21 | from functools import partial
22 |
23 | from studiovendor.Qt import QtWidgets
24 |
25 | import studiolibrary
26 |
27 |
28 | class LibrariesMenu(QtWidgets.QMenu):
29 |
30 | def __init__(self, libraryWindow=None):
31 | super(LibrariesMenu, self).__init__(libraryWindow)
32 |
33 | self.setTitle('Libraries')
34 |
35 | libraries = studiolibrary.readSettings()
36 | default = studiolibrary.defaultLibrary()
37 |
38 | for name in libraries:
39 |
40 | library = libraries[name]
41 |
42 | path = library.get('path', '')
43 | kwargs = library.get('kwargs', {})
44 |
45 | enabled = True
46 | if libraryWindow:
47 | enabled = name != libraryWindow.name()
48 |
49 | text = name
50 | if name == default and name.lower() != "default":
51 | text = name + " (default)"
52 |
53 | action = QtWidgets.QAction(text, self)
54 | action.setEnabled(enabled)
55 | callback = partial(self.showLibrary, name, path, **kwargs)
56 | action.triggered.connect(callback)
57 | self.addAction(action)
58 |
59 | def showLibrary(self, name, path, **kwargs):
60 | """
61 | Show the library window which has given name and path.
62 |
63 | :type name: str
64 | :type path: str
65 | :type kwargs: dict
66 | """
67 | studiolibrary.main(name, path, **kwargs)
68 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/placeholderwidget.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor.Qt import QtWidgets
14 |
15 | import studioqt
16 |
17 |
18 | class PlaceholderWidget(QtWidgets.QWidget):
19 |
20 | def __init__(self, *args):
21 | QtWidgets.QWidget.__init__(self, *args)
22 | studioqt.loadUi(self)
23 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/separatoraction.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor.Qt import QtWidgets
14 |
15 |
16 | __all__ = ["SeparatorAction"]
17 |
18 |
19 | class Line(QtWidgets.QFrame):
20 | pass
21 |
22 |
23 | class SeparatorWidgetAction(QtWidgets.QFrame):
24 | pass
25 |
26 |
27 | class SeparatorAction(QtWidgets.QWidgetAction):
28 |
29 | def __init__(self, label="", parent=None):
30 | """
31 | :type parent: QtWidgets.QMenu
32 | """
33 | QtWidgets.QWidgetAction.__init__(self, parent)
34 |
35 | self._widget = SeparatorWidgetAction(parent)
36 |
37 | self._label = QtWidgets.QLabel(self._widget)
38 | self._label.setText(label)
39 |
40 | self._line = Line(self._widget)
41 | self._line.setSizePolicy(
42 | QtWidgets.QSizePolicy.Expanding,
43 | QtWidgets.QSizePolicy.Expanding
44 | )
45 |
46 | def setText(self, text):
47 | """
48 | Set the text of the separator.
49 |
50 | :type text: str
51 | :rtype: None
52 | """
53 | self.label().setText(text)
54 |
55 | def widget(self):
56 | """
57 | Return the QFrame object.
58 |
59 | :rtype: Frame
60 | """
61 | return self._widget
62 |
63 | def label(self):
64 | """
65 | Return the QLabel object.
66 |
67 | :rtype: QtWidgets.QLabel
68 | """
69 | return self._label
70 |
71 | def line(self):
72 | """
73 | Return the line widget.
74 |
75 | :rtype: Line
76 | """
77 | return self._line
78 |
79 | def createWidget(self, menu):
80 | """
81 | This method is called by the QWidgetAction base class.
82 |
83 | :type menu: QtWidgets.QMenu
84 | """
85 | actionWidget = self.widget()
86 |
87 | actionLayout = QtWidgets.QHBoxLayout()
88 | actionLayout.setContentsMargins(0, 0, 0, 0)
89 | actionLayout.addWidget(self.label())
90 | actionLayout.addWidget(self.line())
91 | actionWidget.setLayout(actionLayout)
92 |
93 | return actionWidget
94 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/settings.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import studiolibrary
14 |
15 | _settings = None
16 |
17 |
18 | def path():
19 | """
20 | Get the settings path.
21 |
22 | :rtype: str
23 | """
24 | return studiolibrary.localPath("widgets2.json")
25 |
26 |
27 | def get(key, default=None):
28 | """
29 | Convenience function for getting the a value from disc.
30 |
31 | :type key: str
32 | :type default: object
33 | :rtype: object
34 | """
35 | return read().get(key, default)
36 |
37 |
38 | def set(key, value):
39 | """
40 | Convenience function for setting key values to disc.
41 |
42 | :type key: str
43 | :type value: object
44 | """
45 | save({key: value})
46 |
47 |
48 | def read():
49 | """
50 | Return the local settings from the location of the SETTING_PATH.
51 |
52 | :rtype: dict
53 | """
54 | global _settings
55 |
56 | if not _settings:
57 | _settings = studiolibrary.readJson(path())
58 |
59 | return _settings
60 |
61 |
62 | def save(data):
63 | """
64 | Save the given dict to the local location of the SETTING_PATH.
65 |
66 | :type data: dict
67 | :rtype: None
68 | """
69 | global _settings
70 | _settings = None
71 | studiolibrary.updateJson(path(), data)
72 |
73 |
74 | def reset():
75 | """Remove and reset the item settings."""
76 | global _settings
77 | _settings = None
78 | studiolibrary.removePath(path())
79 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/sidebarwidget/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 | from .sidebarwidget import SidebarWidget
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/slideraction.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor.Qt import QtCore
14 | from studiovendor.Qt import QtWidgets
15 |
16 |
17 | __all__ = ["SliderAction"]
18 |
19 |
20 | class SliderWidgetAction(QtWidgets.QFrame):
21 | pass
22 |
23 |
24 | class SliderAction(QtWidgets.QWidgetAction):
25 |
26 | def __init__(self, label="", parent=None):
27 | """
28 | :type parent: QtWidgets.QMenu
29 | """
30 | QtWidgets.QWidgetAction.__init__(self, parent)
31 |
32 | self._widget = SliderWidgetAction(parent)
33 | self._label = QtWidgets.QLabel(label, self._widget)
34 |
35 | self._slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self._widget)
36 | self._slider.setSizePolicy(
37 | QtWidgets.QSizePolicy.Expanding,
38 | QtWidgets.QSizePolicy.Expanding
39 | )
40 |
41 | self.valueChanged = self._slider.valueChanged
42 |
43 | def widget(self):
44 | """
45 | Return the widget for this action.
46 |
47 | :rtype: QtWidgets.QWidget
48 | """
49 | return self._widget
50 |
51 | def label(self):
52 | """
53 | Return the QLabel object.
54 |
55 | :rtype: QtWidgets.QLabel
56 | """
57 | return self._label
58 |
59 | def slider(self):
60 | """
61 | Return the QLabel object.
62 |
63 | :rtype: QtWidgets.QSlider
64 | """
65 | return self._slider
66 |
67 | def createWidget(self, menu):
68 | """
69 | This method is called by the QWidgetAction base class.
70 |
71 | :type menu: QtWidgets.QMenu
72 | """
73 | actionWidget = self.widget()
74 |
75 | actionLayout = QtWidgets.QHBoxLayout()
76 | actionLayout.setContentsMargins(0, 0, 0, 0)
77 | actionLayout.addWidget(self.label())
78 | actionLayout.addWidget(self.slider())
79 | actionWidget.setLayout(actionLayout)
80 |
81 | return actionWidget
82 |
--------------------------------------------------------------------------------
/src/studiolibrary/widgets/sortbymenu.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from functools import partial
14 |
15 | from studiovendor.Qt import QtGui
16 | from studiovendor.Qt import QtWidgets
17 |
18 | from .separatoraction import SeparatorAction
19 |
20 |
21 | class SortByMenu(QtWidgets.QMenu):
22 |
23 | def __init__(self, name, parent, dataset):
24 | super(SortByMenu, self).__init__(name, parent)
25 |
26 | self._dataset = dataset
27 | self.aboutToShow.connect(self.populateMenu)
28 |
29 | def setDataset(self, dataset):
30 | """
31 | Set the dataset model for the menu:
32 |
33 | :type dataset: studiolibrary.Dataset
34 | """
35 | self._dataset = dataset
36 |
37 | def dataset(self):
38 | """
39 | Get the dataset model for the menu.
40 |
41 | :rtype: studiolibrary.Dataset
42 | """
43 | return self._dataset
44 |
45 | def setSortBy(self, sortName, sortOrder):
46 | """
47 | Set the sort by value for the dataset.
48 |
49 | :type sortName: str
50 | :type sortOrder: str
51 | """
52 | if sortName == "Custom Order":
53 | sortOrder = "asc"
54 |
55 | value = sortName + ":" + sortOrder
56 | self.dataset().setSortBy([value])
57 | self.dataset().search()
58 |
59 | def populateMenu(self):
60 | """
61 | Show the menu options.
62 | """
63 | self.clear()
64 |
65 | sortby = self.dataset().sortBy()
66 | if sortby:
67 | currentField = self.dataset().sortBy()[0].split(":")[0]
68 | currentOrder = "dsc" if "dsc" in self.dataset().sortBy()[0] else "asc"
69 | else:
70 | currentField = ""
71 | currentOrder = ""
72 |
73 | action = SeparatorAction("Sort By", self)
74 | self.addAction(action)
75 |
76 | fields = self.dataset().fields()
77 |
78 | for field in fields:
79 |
80 | if not field.get("sortable"):
81 | continue
82 |
83 | name = field.get("name")
84 |
85 | action = self.addAction(name.title())
86 | action.setCheckable(True)
87 |
88 | if currentField == name:
89 | action.setChecked(True)
90 | else:
91 | action.setChecked(False)
92 |
93 | callback = partial(self.setSortBy, name, currentOrder)
94 | action.triggered.connect(callback)
95 |
96 | action = SeparatorAction("Sort Order", self)
97 | self.addAction(action)
98 |
99 | action = self.addAction("Ascending")
100 | action.setCheckable(True)
101 | action.setChecked(currentOrder == "asc")
102 |
103 | callback = partial(self.setSortBy, currentField, "asc")
104 | action.triggered.connect(callback)
105 |
106 | action = self.addAction("Descending")
107 | action.setCheckable(True)
108 | action.setChecked(currentOrder == "dsc")
109 |
110 | callback = partial(self.setSortBy, currentField, "dsc")
111 | action.triggered.connect(callback)
112 |
--------------------------------------------------------------------------------
/src/studiolibrarymaya/README.md:
--------------------------------------------------------------------------------
1 | # Studio Library Items
2 |
3 | Items are used for loading and saving data.
4 |
5 |
6 | ### Pose Item
7 |
8 | Saving and loading a pose items
9 |
10 | ```python
11 | from studiolibrarymaya import poseitem
12 |
13 | path = "/AnimLibrary/Characters/Malcolm/malcolm.pose"
14 | objects = maya.cmds.ls(selection=True) or []
15 | namespaces = []
16 |
17 | # Saving a pose item
18 | poseitem.save(path, objects=objects)
19 |
20 | # Loading a pose item
21 | poseitem.load(path, objects=objects, namespaces=namespaces, key=True, mirror=False)
22 | ```
23 |
24 | ### Animation Item
25 |
26 | Saving and loading animation items
27 |
28 | ```python
29 | from studiolibrarymaya import animitem
30 |
31 | path = "/AnimLibrary/Characters/Malcolm/malcolm.anim"
32 | objects = maya.cmds.ls(selection=True) or []
33 |
34 | # Saving an animation item
35 | animitem.save(path, objects=objects, frameRange=(0, 200), bakeConnected=False)
36 |
37 | # Loading an animation item
38 | animitem.load(path, objects=objects, option="replace all", connect=False, currentTime=False)
39 | ```
40 |
41 | Loading an animation to multiple namespaces
42 |
43 | ```python
44 | from studiolibrarymaya import animitem
45 | animitem.load(path, namespaces=["character1", "character2"], option="replace all")
46 | ```
47 |
48 | ### Mirror Table Item
49 |
50 | Saving and loading mirror tables
51 |
52 | ```python
53 | from studiolibrarymaya import mirroritem
54 |
55 | path = "/AnimLibrary/Characters/Malcolm/malcolm.mirror"
56 | objects = maya.cmds.ls(selection=True) or []
57 |
58 | # Saving a mirror table item
59 | mirroritem.save(path, objects=objects, leftSide="Lf", rightSide="Rf")
60 |
61 | # Loading a mirror table item
62 | mirroritem.load(path, objects=objects, namespaces=[], option="swap", animation=True, time=None)
63 | ```
64 |
65 | ### Selection Set Item
66 |
67 | Saving and loading selection sets
68 |
69 | ```python
70 | from studiolibrarymaya import setsitem
71 |
72 | path = "/AnimLibrary/Characters/Malcolm/malcolm.set"
73 | objects = maya.cmds.ls(selection=True) or []
74 |
75 | # Saving a selection sets item
76 | setsitem.save(path, objects=objects)
77 |
78 | # Loading a selection sets item
79 | setsitem.load(path, objects=objects, namespaces=[])
80 | ```
81 |
82 |
83 | ### Maya File Item (Development)
84 |
85 | Saving and loading a Maya file item
86 |
87 | This item can be used to load and save any Maya nodes. For example:
88 | locators and geometry.
89 |
90 | ```python
91 | from studiolibrarymaya import mayafileitem
92 |
93 | path = "/AnimLibrary/Characters/Malcolm/malcolm.mayafile"
94 | objects = maya.cmds.ls(selection=True) or []
95 |
96 | # Saving the item to disc
97 | mayafileitem.save(path, objects=objects)
98 |
99 | # Loading the item from disc
100 | mayafileitem.load(path)
101 | ```
102 |
103 | ### Example Item
104 |
105 | If you would like to create a custom item for saving and loading different data types, then please have a look at the [exampleitem.py](exampleitem.py)
106 |
107 | When developing a new item you can "Shift + Click" on the shelf icon which will reload all Studio Library modules including your changes to the item.
108 |
109 | Make sure you register any new items using either the "itemRegistry" key in the [config file](../studiolibrary/config/default.json) or by calling `studiolibrary.registerItem(cls)`.
110 |
--------------------------------------------------------------------------------
/src/studiolibrarymaya/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
--------------------------------------------------------------------------------
/src/studiolibrarymaya/exampleitem.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 | """
13 | NOTE: Make sure you register this item in the config.
14 | """
15 |
16 | import os
17 | import logging
18 |
19 | from studiolibrarymaya import baseitem
20 |
21 |
22 | logger = logging.getLogger(__name__)
23 |
24 |
25 | class ExampleItem(baseitem.BaseItem):
26 |
27 | NAME = "Example"
28 | EXTENSION = ".example"
29 | ICON_PATH = os.path.join(os.path.dirname(__file__), "icons", "pose.png")
30 |
31 | def loadSchema(self, **kwargs):
32 | """
33 | Get the schema used for loading the example item.
34 |
35 | :rtype: list[dict]
36 | """
37 | return [
38 | {
39 | "name": "option",
40 | "type": "bool",
41 | "default": False,
42 | "persistent": True,
43 | },
44 | ]
45 |
46 | def load(self, **kwargs):
47 | """
48 | The load method is called with the user values from the load schema.
49 |
50 | :type kwargs: dict
51 | """
52 | logger.info("Loading %s %s", self.path(), kwargs)
53 | raise NotImplementedError("The load method is not implemented!")
54 |
55 | def saveSchema(self, **kwargs):
56 | """
57 | Get the schema used for saving the example item.
58 |
59 | :rtype: list[dict]
60 | """
61 | return [
62 | # The 'name' field and the 'folder' field are both required by
63 | # the BaseItem. How this is handled may change in the future.
64 | {
65 | "name": "folder",
66 | "type": "path",
67 | "layout": "vertical",
68 | "visible": False,
69 | },
70 | {
71 | "name": "name",
72 | "type": "string",
73 | "layout": "vertical"
74 | },
75 | {
76 | "name": "fileType",
77 | "type": "enum",
78 | "layout": "vertical",
79 | "default": "mayaAscii",
80 | "items": ["mayaAscii", "mayaBinary"],
81 | "persistent": True
82 | },
83 | ]
84 |
85 | def save(self, **kwargs):
86 | """
87 | The save method is called with the user values from the save schema.
88 |
89 | :type kwargs: dict
90 | """
91 | logger.info("Saving %s %s", self.path(), kwargs)
92 | raise NotImplementedError("The save method is not implemented!")
93 |
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/animation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/animation.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/arrow.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/file.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/insert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/insert.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/insertConnect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/insertConnect.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/merge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/merge.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/mergeConnect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/mergeConnect.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/mirrortable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/mirrortable.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/pose.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/pose.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/replace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/replace.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/replaceCompletely.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/replaceCompletely.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/replaceConnect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/replaceConnect.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/selectionSet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/selectionSet.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/icons/selectionSet2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiolibrarymaya/icons/selectionSet2.png
--------------------------------------------------------------------------------
/src/studiolibrarymaya/mayafileitem.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 | """
13 | NOTE: Make sure you register this item in the config.
14 | """
15 |
16 | import os
17 | import logging
18 |
19 | import maya.cmds
20 |
21 | from studiolibrarymaya import baseitem
22 |
23 |
24 | logger = logging.getLogger(__name__)
25 |
26 |
27 | class MayaFileItem(baseitem.BaseItem):
28 |
29 | NAME = "Maya File"
30 | TYPE = NAME
31 | EXTENSION = ".mayafile"
32 | ICON_PATH = os.path.join(os.path.dirname(__file__), "icons", "file.png")
33 |
34 | def transferPath(self):
35 | return self.path() + "/mayafile.ma"
36 |
37 | def loadSchema(self, **kwargs):
38 | """
39 | Get the schema used for loading the example item.
40 |
41 | :rtype: list[dict]
42 | """
43 | return []
44 |
45 | def load(self, **kwargs):
46 | """
47 | The load method is called with the user values from the load schema.
48 |
49 | :type kwargs: dict
50 | """
51 | logger.info("Loading %s %s", self.path(), kwargs)
52 |
53 | maya.cmds.file(
54 | self.transferPath(),
55 | i=True,
56 | type="mayaAscii",
57 | options="v=0;",
58 | preserveReferences=True,
59 | mergeNamespacesOnClash=False,
60 | )
61 |
62 | def saveSchema(self, **kwargs):
63 | """
64 | Get the schema used for saving the example item.
65 |
66 | :rtype: list[dict]
67 | """
68 | return [
69 | # The 'name' field and the 'folder' field are both required by
70 | # the BaseItem. How this is handled may change in the future.
71 | {
72 | "name": "folder",
73 | "type": "path",
74 | "layout": "vertical",
75 | "visible": False,
76 | },
77 | {
78 | "name": "name",
79 | "type": "string",
80 | "layout": "vertical"
81 | },
82 | {
83 | "name": "objects",
84 | "type": "objects",
85 | "layout": "vertical"
86 | },
87 | ]
88 |
89 | def save(self, **kwargs):
90 | """
91 | The save method is called with the user values from the save schema.
92 |
93 | :type kwargs: dict
94 | """
95 | logger.info("Saving %s %s", self.path(), kwargs)
96 |
97 | super(MayaFileItem, self).save(**kwargs)
98 |
99 | maya.cmds.file(
100 | self.transferPath(),
101 | type="mayaAscii",
102 | options="v=0;",
103 | preserveReferences=True,
104 | exportSelected=True
105 | )
106 |
--------------------------------------------------------------------------------
/src/studiolibrarymaya/setsitem.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import os
14 |
15 | try:
16 | import mutils
17 | except ImportError as error:
18 | print(error)
19 |
20 | from studiolibrarymaya import baseitem
21 |
22 |
23 | def save(path, *args, **kwargs):
24 | """Convenience function for saving a SetsItem."""
25 | SetsItem(path).safeSave(*args, **kwargs)
26 |
27 |
28 | def load(path, *args, **kwargs):
29 | """Convenience function for loading a SetsItem."""
30 | SetsItem(path).load(*args, **kwargs)
31 |
32 |
33 | class SetsItem(baseitem.BaseItem):
34 |
35 | NAME = "Selection Set"
36 | EXTENSION = ".set"
37 | ICON_PATH = os.path.join(os.path.dirname(__file__), "icons", "selectionSet.png")
38 | TRANSFER_CLASS = mutils.SelectionSet
39 | TRANSFER_BASENAME = "set.json"
40 |
41 | def loadFromCurrentValues(self):
42 | """Load the selection set using the settings for this item."""
43 | self.load(namespaces=self.namespaces())
44 |
45 | def load(self, namespaces=None):
46 | """
47 | :type namespaces: list[str] | None
48 | """
49 | self.selectContent(namespaces=namespaces)
50 |
51 | def save(self, objects, **kwargs):
52 | """
53 | Save all the given object data to the item path on disc.
54 |
55 | :type objects: list[str]
56 | :type kwargs: dict
57 | """
58 | super(SetsItem, self).save(**kwargs)
59 |
60 | # Save the selection set to the given path
61 | mutils.saveSelectionSet(
62 | self.path() + "/set.json",
63 | objects,
64 | metadata={"description": kwargs.get("comment", "")}
65 | )
66 |
--------------------------------------------------------------------------------
/src/studioqt/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studioqt.utils import *
14 | from studioqt.icon import Icon
15 | from studioqt.menu import Menu
16 | from studioqt.color import Color
17 | from studioqt.pixmap import Pixmap
18 | from studioqt.stylesheet import StyleSheet
19 | from studioqt.decorators import showWaitCursor
20 | from studioqt.decorators import showArrowCursor
21 | from studioqt.imagesequence import ImageSequence
22 |
--------------------------------------------------------------------------------
/src/studioqt/color.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor.Qt import QtGui
14 |
15 |
16 | COLORS = [
17 | {"name": "red", "color": "rgb(255, 115, 100)"},
18 | {"name": "orange", "color": "rgb(255, 150, 100)"},
19 | {"name": "yellow", "color": "rgb(255, 210, 103)"},
20 | {"name": "green", "color": "rgb(140, 220, 140)"},
21 | {"name": "blue", "color": "rgb(110, 175, 255)"},
22 | {"name": "purple", "color": "rgb(160, 120, 255)"},
23 | {"name": "pink", "color": "rgb(230, 130, 180)"},
24 | {"name": "grey", "color": "rgb(125, 125, 140)"},
25 | ]
26 |
27 | COLORS_INDEXED = {c["name"]: c for c in COLORS}
28 |
29 |
30 | class Color(QtGui.QColor):
31 |
32 | @classmethod
33 | def fromColor(cls, color):
34 | """
35 | :type color: QtGui.QColor
36 | """
37 | color = ('rgba(%d, %d, %d, %d)' % color.getRgb())
38 | return cls.fromString(color)
39 |
40 | @classmethod
41 | def fromString(cls, c):
42 | """
43 | :type c: str
44 | """
45 | a = 255
46 |
47 | c = c.replace(";", "")
48 | if not c.startswith("rgb"):
49 | c = COLORS_INDEXED.get(c)
50 | if c:
51 | c = c.get("color")
52 | else:
53 | return cls(0, 0, 0, 255)
54 |
55 | try:
56 | r, g, b, a = c.replace("rgb(", "").replace("rgba(", "").replace(")", "").split(",")
57 | except ValueError:
58 | r, g, b = c.replace("rgb(", "").replace(")", "").split(",")
59 |
60 | return cls(int(r), int(g), int(b), int(a))
61 |
62 | def __eq__(self, other):
63 | if isinstance(other, Color):
64 | return self.toString() == other.toString()
65 | else:
66 | return QtGui.QColor.__eq__(self, other)
67 |
68 | def toString(self):
69 | """
70 | :type: str
71 | """
72 | return 'rgba(%d, %d, %d, %d)' % self.getRgb()
73 |
74 | def isDark(self):
75 | """
76 | :type: bool
77 | """
78 | return self.red() < 125 and self.green() < 125 and self.blue() < 125
79 |
--------------------------------------------------------------------------------
/src/studioqt/decorators.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor.Qt import QtGui
14 | from studiovendor.Qt import QtCore
15 | from studiovendor.Qt import QtWidgets
16 |
17 |
18 | def showWaitCursor(fn):
19 |
20 | def wrapped(*args, **kwargs):
21 | cursor = QtGui.QCursor(QtCore.Qt.WaitCursor)
22 | QtWidgets.QApplication.setOverrideCursor(cursor)
23 | try:
24 | return fn(*args, **kwargs)
25 | finally:
26 | QtWidgets.QApplication.restoreOverrideCursor()
27 |
28 | wrapped.__name__ = fn.__name__
29 | wrapped.__doc__ = fn.__doc__
30 |
31 | return wrapped
32 |
33 |
34 | def showArrowCursor(fn):
35 |
36 | def wrapped(*args, **kwargs):
37 | cursor = QtGui.QCursor(QtCore.Qt.ArrowCursor)
38 | QtWidgets.QApplication.setOverrideCursor(cursor)
39 | try:
40 | return fn(*args, **kwargs)
41 | finally:
42 | QtWidgets.QApplication.restoreOverrideCursor()
43 |
44 | wrapped.__name__ = fn.__name__
45 | wrapped.__doc__ = fn.__doc__
46 |
47 | return wrapped
48 |
--------------------------------------------------------------------------------
/src/studioqt/menu.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor import six
14 | from studiovendor.Qt import QtWidgets
15 |
16 |
17 | class Menu(QtWidgets.QMenu):
18 |
19 | def __init__(self, *args):
20 | QtWidgets.QMenu.__init__(self, *args)
21 |
22 | def findAction(self, text):
23 | """
24 | Return the action that contains the given text.
25 |
26 | :type text: str
27 |
28 | :rtype: QtWidgets.QAction
29 | """
30 | for child in self.children():
31 |
32 | action = None
33 |
34 | if isinstance(child, QtWidgets.QMenu):
35 | action = child.menuAction()
36 | elif isinstance(child, QtWidgets.QAction):
37 | action = child
38 |
39 | if action and action.text().lower() == text.lower():
40 | return action
41 |
42 | def insertAction(self, before, *args):
43 | """
44 | Add support for finding the before action by the given string.
45 |
46 | :type before: str or QtWidget.QAction
47 | :type args: list
48 |
49 | :rtype: QtWidgets.QAction
50 | """
51 | if isinstance(before, six.string_types):
52 | before = self.findAction(before)
53 |
54 | return QtWidgets.QMenu.insertAction(self, before, *args)
55 |
56 | def insertMenu(self, before, menu):
57 | """
58 | Add support for finding the before action by the given string.
59 |
60 | :type before: str or QtWidget.QAction
61 | :type menu: QtWidgets.QMenu
62 |
63 | :rtype: QtWidgets.QAction
64 | """
65 | if isinstance(before, six.string_types):
66 | before = self.findAction(before)
67 |
68 | QtWidgets.QMenu.insertMenu(self, before, menu)
69 |
70 | def insertSeparator(self, before):
71 | """
72 | Add support for finding the before action by the given string.
73 |
74 | :type before: str or QtWidget.QAction
75 |
76 | :rtype: QtWidgets.QAction
77 | """
78 | if isinstance(before, six.string_types):
79 | before = self.findAction(before)
80 |
81 | return QtWidgets.QMenu.insertSeparator(self, before)
82 |
--------------------------------------------------------------------------------
/src/studioqt/pixmap.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | from studiovendor import six
14 | from studiovendor.Qt import QtGui
15 |
16 | import studioqt
17 |
18 |
19 | class Pixmap(QtGui.QPixmap):
20 |
21 | def __init__(self, *args):
22 | QtGui.QPixmap.__init__(self, *args)
23 |
24 | self._color = None
25 |
26 | def setColor(self, color):
27 | """
28 | :type color: QtGui.QColor
29 | :rtype: None
30 | """
31 | if isinstance(color, six.string_types):
32 | color = studioqt.Color.fromString(color)
33 |
34 | if not self.isNull():
35 | painter = QtGui.QPainter(self)
36 | painter.setCompositionMode(QtGui.QPainter.CompositionMode_SourceIn)
37 | painter.setBrush(color)
38 | painter.setPen(color)
39 | painter.drawRect(self.rect())
40 | painter.end()
41 |
--------------------------------------------------------------------------------
/src/studioqt/stylesheet.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 by Kurt Rathjen. All Rights Reserved.
2 | #
3 | # This library is free software: you can redistribute it and/or modify it
4 | # under the terms of the GNU Lesser General Public License as published by
5 | # the Free Software Foundation, either version 3 of the License, or
6 | # (at your option) any later version. This library is distributed in the
7 | # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 | # See the GNU Lesser General Public License for more details.
10 | # You should have received a copy of the GNU Lesser General Public
11 | # License along with this library. If not, see .
12 |
13 | import os
14 | import re
15 |
16 | import studioqt
17 |
18 |
19 | class StyleSheet(object):
20 |
21 | @classmethod
22 | def fromPath(cls, path, **kwargs):
23 | """
24 | :type path: str
25 | :rtype: str
26 | """
27 | styleSheet = cls()
28 | data = styleSheet.read(path)
29 | data = StyleSheet.format(data, **kwargs)
30 | styleSheet.setData(data)
31 | return styleSheet
32 |
33 | @classmethod
34 | def fromText(cls, text, options=None):
35 | """
36 | :type text: str
37 | :rtype: str
38 | """
39 | styleSheet = cls()
40 | data = StyleSheet.format(text, options=options)
41 | styleSheet.setData(data)
42 | return styleSheet
43 |
44 | def __init__(self):
45 | self._data = ""
46 |
47 | def setData(self, data):
48 | """
49 | :type data: str
50 | """
51 | self._data = data
52 |
53 | def data(self):
54 | """
55 | :rtype: str
56 | """
57 | return self._data
58 |
59 | @staticmethod
60 | def read(path):
61 | """
62 | :type path: str
63 | :rtype: str
64 | """
65 | data = ""
66 |
67 | if os.path.isfile(path):
68 | with open(path, "r") as f:
69 | data = f.read()
70 |
71 | return data
72 |
73 | @staticmethod
74 | def format(data=None, options=None, dpi=1):
75 | """
76 | :type data:
77 | :type options: dict
78 | :rtype: str
79 | """
80 | if options is not None:
81 | keys = list(options.keys())
82 | keys.sort(key=len, reverse=True)
83 | for key in keys:
84 | data = data.replace(key, options[key])
85 |
86 | reDpi = re.compile("[0-9]+px")
87 | newData = []
88 |
89 | for line in data.split("\n"):
90 | dpi_ = reDpi.search(line)
91 |
92 | if dpi_:
93 | new = dpi_.group().replace("px", "")
94 | val = int(new)
95 | if val > 0:
96 | val = int(val * dpi)
97 | line = line.replace(dpi_.group(), str(val) + "px")
98 |
99 | newData.append(line)
100 |
101 | data = "\n".join(newData)
102 | return data
103 |
--------------------------------------------------------------------------------
/src/studiovendor/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/krathjen/studiolibrary/0a2df600ab7b5353a995af79636751bdc6d2914c/src/studiovendor/__init__.py
--------------------------------------------------------------------------------