├── .gitignore
├── DeformationLearningSolver
├── bin
│ ├── SSDSolverCmd
│ │ ├── 2014
│ │ │ └── plug-ins
│ │ │ │ ├── SSDSolverCmd.bundle
│ │ │ │ ├── SSDSolverCmd.mll
│ │ │ │ └── SSDSolverCmd.so
│ │ ├── 2015
│ │ │ └── plug-ins
│ │ │ │ ├── SSDSolverCmd.bundle
│ │ │ │ ├── SSDSolverCmd.mll
│ │ │ │ └── SSDSolverCmd.so
│ │ ├── 2016
│ │ │ └── plug-ins
│ │ │ │ ├── SSDSolverCmd.bundle
│ │ │ │ ├── SSDSolverCmd.mll
│ │ │ │ └── SSDSolverCmd.so
│ │ └── 2017
│ │ │ └── plug-ins
│ │ │ ├── SSDSolverCmd.bundle
│ │ │ ├── SSDSolverCmd.mll
│ │ │ └── SSDSolverCmd.so
│ └── wbDeltaMushDeformer
│ │ ├── 2014
│ │ ├── plug-ins
│ │ │ ├── wbDeltaMushDeformer.bundle
│ │ │ ├── wbDeltaMushDeformer.mll
│ │ │ └── wbDeltaMushDeformer.so
│ │ └── scripts
│ │ │ └── AEwbDeltaMushTemplate.mel
│ │ ├── 2015
│ │ ├── plug-ins
│ │ │ ├── wbDeltaMushDeformer.bundle
│ │ │ ├── wbDeltaMushDeformer.mll
│ │ │ └── wbDeltaMushDeformer.so
│ │ └── scripts
│ │ │ └── AEwbDeltaMushTemplate.mel
│ │ ├── 2016
│ │ ├── plug-ins
│ │ │ ├── wbDeltaMushDeformer.bundle
│ │ │ ├── wbDeltaMushDeformer.mll
│ │ │ └── wbDeltaMushDeformer.so
│ │ └── scripts
│ │ │ └── AEwbDeltaMushTemplate.mel
│ │ └── 2017
│ │ ├── plug-ins
│ │ ├── wbDeltaMushDeformer.bundle
│ │ ├── wbDeltaMushDeformer.mll
│ │ └── wbDeltaMushDeformer.so
│ │ └── scripts
│ │ └── AEwbDeltaMushTemplate.mel
├── icons
│ └── wbDeltaMush.png
├── install.mel
├── modules
│ └── DeformationLearningSolver.mod
└── scripts
│ └── DLS
│ ├── __init__.py
│ ├── core
│ ├── __init__.py
│ ├── fnData.py
│ ├── learningFunc.py
│ ├── miscFunc.py
│ ├── samplingFunc.py
│ └── utils.py
│ ├── startup
│ ├── __init__.py
│ └── setup.py
│ └── widget
│ ├── __init__.py
│ ├── aboutDialog.py
│ ├── axisOptionWindow.py
│ ├── baseOptionWindow.py
│ ├── baseTab.py
│ ├── config.ini
│ ├── customAttributeEditor.py
│ ├── learningTab.py
│ ├── mainWindow.py
│ ├── miscTab.py
│ ├── optionWindow.py
│ ├── samplingTab.py
│ ├── ui
│ ├── aboutDialog.ui
│ ├── axisWindow.ui
│ ├── customAttributeEditor.ui
│ ├── learningTab.ui
│ ├── miscTab.ui
│ ├── optionWindow.ui
│ └── samplingTab.ui
│ └── utils.py
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | # C extensions
6 |
7 | # Distribution / packaging
8 | .Python
9 | env/
10 | build/
11 | develop-eggs/
12 | dist/
13 | downloads/
14 | eggs/
15 | .eggs/
16 | lib/
17 | lib64/
18 | parts/
19 | sdist/
20 | var/
21 | *.egg-info/
22 | .installed.cfg
23 | *.egg
24 |
25 | # PyInstaller
26 | # Usually these files are written by a python script from a template
27 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
28 | *.manifest
29 | *.spec
30 |
31 | # Installer logs
32 | pip-log.txt
33 | pip-delete-this-directory.txt
34 |
35 | # Unit test / coverage reports
36 | htmlcov/
37 | .tox/
38 | .coverage
39 | .coverage.*
40 | .cache
41 | nosetests.xml
42 | coverage.xml
43 | *,cover
44 |
45 | # Translations
46 | *.mo
47 | *.pot
48 |
49 | # Django stuff:
50 | *.log
51 |
52 | # Sphinx documentation
53 | docs/_build/
54 |
55 | # PyBuilder
56 | target/
57 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2014/plug-ins/SSDSolverCmd.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2014/plug-ins/SSDSolverCmd.bundle
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2014/plug-ins/SSDSolverCmd.mll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2014/plug-ins/SSDSolverCmd.mll
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2014/plug-ins/SSDSolverCmd.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2014/plug-ins/SSDSolverCmd.so
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2015/plug-ins/SSDSolverCmd.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2015/plug-ins/SSDSolverCmd.bundle
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2015/plug-ins/SSDSolverCmd.mll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2015/plug-ins/SSDSolverCmd.mll
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2015/plug-ins/SSDSolverCmd.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2015/plug-ins/SSDSolverCmd.so
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2016/plug-ins/SSDSolverCmd.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2016/plug-ins/SSDSolverCmd.bundle
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2016/plug-ins/SSDSolverCmd.mll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2016/plug-ins/SSDSolverCmd.mll
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2016/plug-ins/SSDSolverCmd.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2016/plug-ins/SSDSolverCmd.so
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2017/plug-ins/SSDSolverCmd.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2017/plug-ins/SSDSolverCmd.bundle
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2017/plug-ins/SSDSolverCmd.mll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2017/plug-ins/SSDSolverCmd.mll
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/SSDSolverCmd/2017/plug-ins/SSDSolverCmd.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/SSDSolverCmd/2017/plug-ins/SSDSolverCmd.so
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2014/plug-ins/wbDeltaMushDeformer.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2014/plug-ins/wbDeltaMushDeformer.bundle
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2014/plug-ins/wbDeltaMushDeformer.mll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2014/plug-ins/wbDeltaMushDeformer.mll
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2014/plug-ins/wbDeltaMushDeformer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2014/plug-ins/wbDeltaMushDeformer.so
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2014/scripts/AEwbDeltaMushTemplate.mel:
--------------------------------------------------------------------------------
1 | global proc AEwbDeltaMushTemplate( string $nodeName )
2 | {
3 | editorTemplate -beginScrollLayout;
4 |
5 | // Add Delta Mush Attributes section
6 | editorTemplate -beginLayout "Delta Mush Attributes" -collapse 0;
7 | editorTemplate -addControl "smoothingIterations";
8 | editorTemplate -addControl "smoothingAlgorithm";
9 | editorTemplate -addControl "smoothingStep";
10 | editorTemplate -addControl "pinBorderVertices";
11 | editorTemplate -addControl "displacement";
12 | editorTemplate -addControl "scale";
13 | editorTemplate -addControl "tangentMode";
14 | editorTemplate -endLayout;
15 |
16 | AEweightGeometryFilterTemplate $nodeName;
17 |
18 | editorTemplate -addExtraControls;
19 | editorTemplate -suppress "cache";
20 | editorTemplate -endScrollLayout;
21 | }
22 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2015/plug-ins/wbDeltaMushDeformer.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2015/plug-ins/wbDeltaMushDeformer.bundle
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2015/plug-ins/wbDeltaMushDeformer.mll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2015/plug-ins/wbDeltaMushDeformer.mll
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2015/plug-ins/wbDeltaMushDeformer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2015/plug-ins/wbDeltaMushDeformer.so
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2015/scripts/AEwbDeltaMushTemplate.mel:
--------------------------------------------------------------------------------
1 | global proc AEwbDeltaMushTemplate( string $nodeName )
2 | {
3 | editorTemplate -beginScrollLayout;
4 |
5 | // Add Delta Mush Attributes section
6 | editorTemplate -beginLayout "Delta Mush Attributes" -collapse 0;
7 | editorTemplate -addControl "smoothingIterations";
8 | editorTemplate -addControl "smoothingAlgorithm";
9 | editorTemplate -addControl "smoothingStep";
10 | editorTemplate -addControl "pinBorderVertices";
11 | editorTemplate -addControl "displacement";
12 | editorTemplate -addControl "scale";
13 | editorTemplate -addControl "tangentMode";
14 | editorTemplate -endLayout;
15 |
16 | AEweightGeometryFilterTemplate $nodeName;
17 |
18 | editorTemplate -addExtraControls;
19 | editorTemplate -suppress "cache";
20 | editorTemplate -endScrollLayout;
21 | }
22 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2016/plug-ins/wbDeltaMushDeformer.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2016/plug-ins/wbDeltaMushDeformer.bundle
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2016/plug-ins/wbDeltaMushDeformer.mll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2016/plug-ins/wbDeltaMushDeformer.mll
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2016/plug-ins/wbDeltaMushDeformer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2016/plug-ins/wbDeltaMushDeformer.so
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2016/scripts/AEwbDeltaMushTemplate.mel:
--------------------------------------------------------------------------------
1 | global proc AEwbDeltaMushTemplate( string $nodeName )
2 | {
3 | editorTemplate -beginScrollLayout;
4 |
5 | // Add Delta Mush Attributes section
6 | editorTemplate -beginLayout "Delta Mush Attributes" -collapse 0;
7 | editorTemplate -addControl "smoothingIterations";
8 | editorTemplate -addControl "smoothingAlgorithm";
9 | editorTemplate -addControl "smoothingStep";
10 | editorTemplate -addControl "pinBorderVertices";
11 | editorTemplate -addControl "displacement";
12 | editorTemplate -addControl "scale";
13 | editorTemplate -addControl "tangentMode";
14 | editorTemplate -endLayout;
15 |
16 | AEweightGeometryFilterTemplate $nodeName;
17 |
18 | editorTemplate -addExtraControls;
19 | editorTemplate -suppress "cache";
20 | editorTemplate -endScrollLayout;
21 | }
22 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2017/plug-ins/wbDeltaMushDeformer.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2017/plug-ins/wbDeltaMushDeformer.bundle
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2017/plug-ins/wbDeltaMushDeformer.mll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2017/plug-ins/wbDeltaMushDeformer.mll
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2017/plug-ins/wbDeltaMushDeformer.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/bin/wbDeltaMushDeformer/2017/plug-ins/wbDeltaMushDeformer.so
--------------------------------------------------------------------------------
/DeformationLearningSolver/bin/wbDeltaMushDeformer/2017/scripts/AEwbDeltaMushTemplate.mel:
--------------------------------------------------------------------------------
1 | global proc AEwbDeltaMushTemplate( string $nodeName )
2 | {
3 | editorTemplate -beginScrollLayout;
4 |
5 | // Add Delta Mush Attributes section
6 | editorTemplate -beginLayout "Delta Mush Attributes" -collapse 0;
7 | editorTemplate -addControl "smoothingIterations";
8 | editorTemplate -addControl "smoothingAlgorithm";
9 | editorTemplate -addControl "smoothingStep";
10 | editorTemplate -addControl "pinBorderVertices";
11 | editorTemplate -addControl "displacement";
12 | editorTemplate -addControl "scale";
13 | editorTemplate -addControl "tangentMode";
14 | editorTemplate -endLayout;
15 |
16 | AEweightGeometryFilterTemplate $nodeName;
17 |
18 | editorTemplate -addExtraControls;
19 | editorTemplate -suppress "cache";
20 | editorTemplate -endScrollLayout;
21 | }
22 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/icons/wbDeltaMush.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebberHuang/DeformationLearningSolver/c58f2c7eb8e4f172948de9acd2b3e6cb39bb8bc2/DeformationLearningSolver/icons/wbDeltaMush.png
--------------------------------------------------------------------------------
/DeformationLearningSolver/install.mel:
--------------------------------------------------------------------------------
1 | /*
2 | #----------------------------------------------------------------------
3 | # Author: Webber Huang
4 | # Contact: xracz.fx@gmail.com
5 | # Homepage: http://riggingtd.com
6 | #----------------------------------------------------------------------
7 | */
8 |
9 |
10 | global string $gShelfTopLevel;
11 | string $currentShelf = `tabLayout -query -selectTab $gShelfTopLevel`;
12 | setParent $currentShelf;
13 |
14 | string $scriptLocation=`scriptLocation`;
15 | string $scriptName="Deformation Learning Solver";
16 | string $command="import DLS\nDLS.launch()";
17 |
18 | // Setup module
19 | python("import os");
20 | python("home = os.path.expanduser(\"~\")");
21 | string $mayaModDir = python("home+\"/maya/modules/\"");
22 | if (`about -os` == "mac") $mayaModDir = python("home+\"/Library/Preferences/Autodesk/maya/modules/\"");
23 | python("try:\n\tmodDir=os.path.relpath(\""+$scriptLocation+"\",\""+$mayaModDir+"\").replace('\\\\', '/')\nexcept:\n\tmodDir=\"\"");
24 | string $modDir = python("modDir");
25 | if ($modDir == "") $modDir = `substring $scriptLocation 1 (size($scriptLocation)-1)`;
26 |
27 | string $modName = "DeformationLearningSolver";
28 | string $modFileName = $modName+".mod";
29 | string $modFile = $scriptLocation + "modules/" + $modFileName;
30 | string $newModFile = $mayaModDir + $modFileName ;
31 | string $toBeReplacedStr = "REPLACE_TO_YOUR_PATH";
32 |
33 | int $copySuccess = `sysFile -cp $newModFile $modFile`;
34 | if (!$copySuccess) sysFile -md $mayaModDir;
35 |
36 | $inFileId=`fopen $modFile "r"`;
37 | $outFileId=`fopen $newModFile "w"`;
38 | string $nextLine = `fgetline $inFileId`;
39 | while ( size( $nextLine ) > 0 ) {
40 | $nextLine = `substitute $toBeReplacedStr $nextLine $modDir`;
41 | fprint($outFileId, $nextLine);
42 | $nextLine = `fgetline $inFileId`;
43 | }
44 | fclose $inFileId;
45 | fclose $outFileId;
46 |
47 | // load script path for current session
48 | loadModule -a;
49 | string $modScriptDir = ($scriptLocation+"scripts");
50 | print ($modScriptDir +"\n");
51 | python ("import sys") ;
52 | string $pyPaths[] = python ("sys.path") ;
53 | if ( stringArrayCount ($modScriptDir, $pyPaths) == 0 )
54 | python ("sys.path.insert(0, '" + $modScriptDir + "')") ;
55 |
56 | //string $icon=$scriptLocation+"icons/deformationLearningIcon.png";
57 |
58 | // Install button to current shelf
59 | shelfButton
60 | -command $command
61 | -annotation $scriptName
62 | -label $scriptName
63 | //-image $icon
64 | -imageOverlayLabel $scriptName
65 | -image "pythonFamily.png"
66 | -style "iconOnly"
67 | -sourceType "python"
68 | ;
69 |
70 | print ("// "+$scriptName+" has been added to current shelf.\n");
71 |
72 | // Helper functions for locating script's location
73 | global proc scriptLocator (){}
74 |
75 | global proc string scriptLocation ()
76 | {
77 | string $whatIs=`whatIs scriptLocator`;
78 | string $fullPath=`substring $whatIs 25 999`;
79 | string $buffer[];
80 | int $numTok=`tokenize $fullPath "/" $buffer`;
81 | int $numLetters=size($fullPath);
82 | int $numLettersLastFolder=size($buffer[$numTok-1]);
83 | string $scriptLocation=`substring $fullPath 1 ($numLetters-$numLettersLastFolder)`;
84 | return $scriptLocation;
85 | }
--------------------------------------------------------------------------------
/DeformationLearningSolver/modules/DeformationLearningSolver.mod:
--------------------------------------------------------------------------------
1 | + DeformationLearningSolver any REPLACE_TO_YOUR_PATH
2 |
3 | + MAYAVERSION:2014 SSDSolverCmd any REPLACE_TO_YOUR_PATH/bin/SSDSolverCmd/2014
4 | + MAYAVERSION:2015 SSDSolverCmd any REPLACE_TO_YOUR_PATH/bin/SSDSolverCmd/2015
5 | + MAYAVERSION:2016 SSDSolverCmd any REPLACE_TO_YOUR_PATH/bin/SSDSolverCmd/2016
6 | + MAYAVERSION:2017 SSDSolverCmd any REPLACE_TO_YOUR_PATH/bin/SSDSolverCmd/2017
7 |
8 | + MAYAVERSION:2014 wbDeltaMushDeformer any REPLACE_TO_YOUR_PATH/bin/wbDeltaMushDeformer/2014
9 | + MAYAVERSION:2015 wbDeltaMushDeformer any REPLACE_TO_YOUR_PATH/bin/wbDeltaMushDeformer/2015
10 | + MAYAVERSION:2016 wbDeltaMushDeformer any REPLACE_TO_YOUR_PATH/bin/wbDeltaMushDeformer/2016
11 | + MAYAVERSION:2017 wbDeltaMushDeformer any REPLACE_TO_YOUR_PATH/bin/wbDeltaMushDeformer/2017
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 |
6 | #----------------------------------------------------------------------
7 | def launch():
8 | """"""
9 | from DLS.startup import setup
10 | reload(setup)
11 | setup.launch()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/core/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/core/fnData.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 |
6 | import maya.cmds as cmds
7 | import maya.OpenMaya as om
8 | import maya.OpenMayaAnim as oma
9 | from DLS.core import utils
10 |
11 |
12 | class FnSkinCluster(object):
13 |
14 | def __init__(self, skinCluster=None):
15 | """
16 | Args:
17 | skinCluster (str, Optional): Defaults to None
18 | """
19 | self.skinCluster = skinCluster
20 | if skinCluster:
21 | self.fn = oma.MFnSkinCluster(utils.getDependNode(skinCluster))
22 |
23 | def setSkinCluster(self, skinCluster):
24 | """
25 | Args:
26 | skinCluster (str, Optional): Defaults to None
27 |
28 | Returns:
29 | SkinClusterFn
30 | """
31 | self.skinCluster = skinCluster
32 | self.fn = oma.MFnSkinCluster(utils.getDependNode(skinCluster))
33 | return self
34 |
35 | def getLogicalInfluenceIndex(self,influence):
36 | """
37 | Args:
38 | influence (str)
39 |
40 | Returns:
41 | int
42 | """
43 | try:
44 | dagPath = utils.getDagPath(influence)
45 | except:
46 | raise utils.UserInputError("Could not find influence '%s' in %s" %
47 | (influence, self.skinCluster))
48 |
49 | return self.fn.indexForInfluenceObject(dagPath)
50 |
51 | #----------------------------------------------------------------------
52 | def getPhysicalInfluenceIndex(self, influence):
53 | """
54 | Args:
55 | influence (str)
56 |
57 | Returns:
58 | int
59 | """
60 | matrices = cmds.listConnections("%s.matrix" % self.skinCluster, s=1, d=0)
61 | return matrices.index(influence)
62 |
63 | #----------------------------------------------------------------------
64 | def getInfluenceData(self, influence):
65 | """
66 | Args:
67 | influence (str)
68 |
69 | Returns:
70 | WeightData
71 | """
72 | try:
73 | dagPath = utils.getDagPath(influence)
74 | except:
75 | raise utils.UserInputError("Could not find influence '%s' in %s" %
76 | (influence, self.skinCluster))
77 | selList = om.MSelectionList()
78 | weights = om.MDoubleArray()
79 |
80 | self.fn.getPointsAffectedByInfluence(dagPath, selList, weights)
81 |
82 | componentStr = []
83 | selList.getSelectionStrings(componentStr)
84 | componentStr = cmds.ls(componentStr, ap=1, fl=1)
85 | weights = [w for w in weights]
86 |
87 | return WeightData(componentStr, weights)
88 |
89 | #----------------------------------------------------------------------
90 | def listInfluences(self, asDagPath=True):
91 | """
92 | Returns:
93 | list
94 | """
95 | dagPaths = om.MDagPathArray()
96 | self.fn.influenceObjects(dagPaths)
97 | if asDagPath: return dagPaths
98 | else: return [dagPaths[i].partialPathName() for i in xrange(dagPaths.length())]
99 |
100 | #----------------------------------------------------------------------
101 | def getWeightData(self, elements):
102 | """
103 | Args:
104 | elements (list)
105 |
106 | Returns:
107 | SkinWeightData
108 | """
109 | dagPath, components = utils.getDagPathComponents(elements)
110 |
111 | # Get all influences
112 | infs = self.listInfluences(asDagPath=False)
113 | influenceIndices = om.MIntArray()
114 | [influenceIndices.append(self.getPhysicalInfluenceIndex(inf)) for inf in infs]
115 |
116 | # Get all weights
117 | weights = om.MDoubleArray()
118 | self.fn.getWeights(dagPath, components, influenceIndices, weights)
119 | weights = [w for w in weights]
120 |
121 | return SkinWeightData(elements, infs, weights)
122 |
123 | #----------------------------------------------------------------------
124 | def setWeightData(self, data, normalize=True):
125 | """
126 | Args:
127 | data (SkinWeightData)
128 | normalize (bool, Optional): Defaults to True
129 | """
130 | # Construct dagPath and components
131 | compList = data.getComponents()
132 | dagPath, components = utils.getDagPathComponents(compList)
133 |
134 | # Construct influence indices
135 | influenceIndices = om.MIntArray()
136 | [influenceIndices.append(self.getPhysicalInfluenceIndex(inf)) for inf in data.getInfluences()]
137 |
138 | # Construct weights
139 | weights = om.MDoubleArray()
140 | [weights.append(w) for w in data.getWeights()]
141 | oldValues = om.MDoubleArray()
142 | self.fn.getWeights(dagPath, components, influenceIndices, oldValues)
143 |
144 | self.fn.setWeights(dagPath, components, influenceIndices, weights, normalize, oldValues)
145 |
146 | #----------------------------------------------------------------------
147 | def flushWeights(self, influence):
148 | """
149 | Args:
150 | influence (str)
151 | """
152 | weightData = self.getInfluenceData(influence)
153 | skinData = SkinWeightData(weightData.getElements(), [influence], weightData.getWeights())
154 | [skinData.addInfluence(comp, influence, 0.0) for comp in skinData.getComponents()]
155 | self.setWeightData(skinData)
156 |
157 | #----------------------------------------------------------------------
158 | def getInfluenceTransforms(self, space=om.MSpace.kObject):
159 | infs = self.listInfluences()
160 |
161 | if space == om.MSpace.kWorld:
162 | return [infs[i].inclusiveMatrix() for i in xrange(infs.length())]
163 |
164 | return [om.MFnTransform(infs[i]).transformation().asMatrix()
165 | for i in xrange(infs.length())]
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/core/learningFunc.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 |
6 | import maya.cmds as cmds
7 | import maya.OpenMaya as om
8 |
9 | from DLS.core import utils
10 | from DLS.core import fnData
11 | reload(utils)
12 |
13 |
14 | #----------------------------------------------------------------------
15 | def solve(numBones, maxInfs, targetMesh, isAlternativeUpdate, start, end, maxIters=10, isKeepOriginal=True,
16 | pruneBelow=0.0, epsilon=1.0, isDeleteDeltaMush=False):
17 | """
18 | Args:
19 | numBones (int)
20 | maxInfs (int)
21 | start (int)
22 | end (int)
23 | maxIters (int)
24 | epsilon (float)
25 | """
26 | try:
27 | mesh = cmds.ls(sl=1)[0];
28 | except:
29 | om.MGlobal.displayError("Select mesh first.")
30 | return
31 |
32 | mode = 0
33 |
34 | skinCluster = utils.findRelatedSkinCluster(mesh)
35 | if skinCluster:
36 | fnSkin = fnData.FnSkinCluster(skinCluster)
37 | bones = fnSkin.listInfluences(False)
38 |
39 | if targetMesh: # Solve transformations from existing weights
40 | if not isAlternativeUpdate: # Alternative update transformations and weights with new mesh sequences
41 | mode = 2
42 | else: # Solve weights from existing transformations
43 | targetMesh = mesh
44 | mode = 1
45 | cmds.ssdSolver(mesh,
46 | tm=targetMesh,
47 | m=mode,
48 | mit=maxIters,
49 | mi=maxInfs,
50 | ib=bones,
51 | isc=skinCluster,
52 | st=start,
53 | et=end,
54 | pb=pruneBelow,
55 | e=epsilon)
56 | else:
57 | if isKeepOriginal:
58 | # Duplicate a new mesh, then transfer deformation with blendshape
59 | cmds.currentTime(start)
60 | new_mesh = cmds.duplicate(mesh, name="%s_solved" % mesh, rc=1, rr=1)[0]
61 | blendshape = cmds.blendShape(mesh, new_mesh, o="world")[0]
62 | attrs = cmds.listAttr('%s.weight' % blendshape, m=1)
63 | cmds.setAttr("%s.%s" % (blendshape, attrs[0]), 1)
64 | mesh = new_mesh
65 |
66 | targetMesh = mesh
67 | cmds.ssdSolver(mesh,
68 | tm=targetMesh,
69 | m=mode,
70 | mi=maxInfs,
71 | nb=numBones,
72 | st=start,
73 | et=end,
74 | mit=maxIters,
75 | pb=pruneBelow,
76 | e=epsilon)
77 |
78 | if isKeepOriginal:
79 | cmds.delete(blendshape)
80 |
81 | # postprocessing
82 | if isDeleteDeltaMush:
83 | deltaMushNode = utils.findRelatedDeltaMush(mesh)
84 | if deltaMushNode:
85 | cmds.delete(deltaMushNode)
86 |
87 | #----------------------------------------------------------------------
88 | def measure(start, end):
89 | """"""
90 | src, tgt = '', ''
91 | try:
92 | src, tgt = cmds.ls(sl=1, ap=1)
93 | except:
94 | om.MGlobal.displayError("Please select two meshes.")
95 | return
96 |
97 | cmds.ssdSolver(src, st=start, et=end, cw=tgt)
98 |
99 | #----------------------------------------------------------------------
100 | def getMeshFromSelection():
101 | """"""
102 | try:
103 | node = cmds.ls(sl=1, ap=1)[0]
104 | dagPath = utils.getDagPath(node)
105 | if dagPath.hasFn(om.MFn.kMesh):
106 | return node
107 | else:
108 | om.MGlobal.displayError("\"%s\" isn't mesh type." % node)
109 | except:
110 | return ""
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/core/miscFunc.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 |
6 | import maya.cmds as cmds
7 | import maya.OpenMaya as om
8 |
9 | from DLS.core import utils
10 |
11 |
12 | #----------------------------------------------------------------------
13 | def applyRigidSkin():
14 | """"""
15 | sel = cmds.ls(sl=1, ap=1)
16 | if len(sel) < 2:
17 | om.MGlobal.displayError("Please select joints first, then mesh.")
18 | return
19 | mesh = sel.pop()
20 | cmds.skinCluster(sel, mesh, tsb=1, mi=0, nw=1, bm=1)
21 |
22 | #----------------------------------------------------------------------
23 | def applyDeltaMush(smooth=1.0, iterations=20, useBuildIn=False):
24 | """
25 | Args:
26 | smooth (float)
27 | iterations (int)
28 | """
29 | sel = cmds.ls(sl=1, ap=1)
30 |
31 | if not sel:
32 | om.MGlobal.displayError("Please select a few meshes.")
33 | return
34 |
35 | if useBuildIn:
36 | cmds.deltaMush(sel, si=iterations, ss=smooth, pbv=0)
37 | else:
38 | cmds.wbDeltaMush(sel, si=iterations, ss=smooth, pbv=0)
39 |
40 | #----------------------------------------------------------------------
41 | def selectAllBelow(skipTips=False):
42 | try:
43 | sel = cmds.ls(sl=1, ap=1)
44 | allDescs = sel + cmds.listRelatives(sel, f=1, ad=1, s=0, ni=1)
45 | if skipTips:
46 | allDescs = [s for s in allDescs if cmds.listRelatives(s, c=1)]
47 | cmds.select(allDescs)
48 | except:
49 | om.MGlobal.displayError("Please select something.")
50 | return
51 |
52 | #----------------------------------------------------------------------
53 | def selectInfluenceJoints():
54 | try:
55 | sel = cmds.ls(sl=1, ap=1)[0]
56 | try:
57 | skinNode = utils.findRelatedSkinCluster(sel)
58 | infs = cmds.skinCluster(skinNode, q=1, inf=1)
59 | except:
60 | om.MGlobal.displayError("No skinCluster found in history of %s." % sel)
61 | return
62 | cmds.select(infs)
63 | except:
64 | om.MGlobal.displayError("Please select something.")
65 | return
66 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/core/samplingFunc.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 |
6 | import maya.cmds as cmds
7 | import maya.OpenMaya as om
8 |
9 | from DLS.core import utils
10 |
11 |
12 | #----------------------------------------------------------------------
13 | def attrSampling(node, attr, minVal, maxVal, interval=1):
14 | """
15 | Args:
16 | node (str)
17 | attrs (list)
18 | minVal (float)
19 | maxVal (float)
20 | interval (int)
21 |
22 | Returns:
23 | int
24 | """
25 | currTime = cmds.currentTime(q=1)
26 | currVal = cmds.getAttr('%s.%s' % (node, attr))
27 | vals = [currVal, currVal+minVal, currVal+maxVal, currVal]
28 |
29 | for i, v in enumerate(vals):
30 | if i not in [0, len(vals)-1] and (currVal - v) == 0:
31 | continue
32 |
33 | cmds.setKeyframe(node, at=attr, v=v, t=currTime)
34 | currTime += interval
35 | return currTime
36 |
37 | #----------------------------------------------------------------------
38 | def attrsSampling(attrData, interval=1):
39 | """
40 | Args:
41 | attrData (dict): {node1: [[attr1, min, max], [attr2, min, max], ...],
42 | node2: [[attr1, min, max], [attr2, min, max], ...],
43 | ...}
44 | interval (int)
45 |
46 | Returns:
47 | int
48 | """
49 | currTime = cmds.currentTime(q=1)
50 | for node, attrVals in attrData.iteritems():
51 | for vals in attrVals:
52 | attr, minVal, maxVal = vals
53 | if not cmds.objExists('.'.join([node, attr])):
54 | continue
55 | currTime = attrSampling(node, attr, minVal, maxVal, interval)
56 | currTime -= 2 * interval
57 | cmds.currentTime(currTime)
58 | return currTime+1 * interval
59 |
60 | #----------------------------------------------------------------------
61 | def customAttrsSampling(attrData, interval=1):
62 | """
63 | Args:
64 | attrData (dict): {node1: [[attr1, min, max], [attr2, min, max], ...],
65 | node2: [[attr1, min, max], [attr2, min, max], ...],
66 | ...}
67 | interval (int)
68 |
69 | Returns:
70 | int
71 | """
72 | start = cmds.currentTime(q=1)
73 | currTime = attrsSampling(attrData, interval)
74 | end = currTime-1
75 | utils.trimTimeRange(start, end)
76 | cmds.currentTime(start)
77 |
78 | #----------------------------------------------------------------------
79 | def blendShapeSampling(node, interval=1):
80 | """
81 | Args:
82 | node (str)
83 | interval (int)
84 |
85 | Returns:
86 | int
87 | """
88 | assert cmds.nodeType(node) == 'blendShape', \
89 | "node must be a blendShape type"
90 | start = cmds.currentTime(q=1)
91 |
92 | attrs = cmds.listAttr('%s.weight' % node, m=1)
93 | attrData = {node: [[attr, 0.0, 1.0] for attr in attrs]}
94 |
95 | currTime = attrsSampling(attrData, interval)
96 |
97 | end = currTime-1
98 | utils.trimTimeRange(start, end)
99 | cmds.currentTime(start)
100 |
101 | #----------------------------------------------------------------------
102 | def transformSampling(translateMin, translateMax,
103 | rotateMin, rotateMax,
104 | scaleMin, scaleMax,
105 | isTranslate, isRotate, isScale,
106 | translateAttrs = ('tx', 'ty', 'tz'),
107 | rotateAttrs = ('rx', 'ry', 'rz'),
108 | scaleAttrs = ('sx', 'sy', 'sz'),
109 | interval=1):
110 | """
111 | Args:
112 | translateMin (float)
113 | translateMax (float)
114 | rotateMin (float)
115 | rotateMax (float)
116 | scaleMin (float)
117 | scaleMax (float)
118 | isTranslate (bool)
119 | isRotate (bool)
120 | isScale (bool)
121 | interval (int)
122 | """
123 | start = cmds.currentTime(q=1)
124 | sel = cmds.ls(sl=1, ap=1)
125 | if not sel:
126 | om.MGlobal.displayError("Please select some tranform nodes.")
127 | return
128 |
129 | attrData = {}
130 | for node in sel:
131 | if not attrData.has_key(node):
132 | attrData[node] = []
133 |
134 | if isRotate:
135 | [attrData[node].append([attr, rotateMin, rotateMax]) for attr in rotateAttrs]
136 |
137 | if isTranslate:
138 | [attrData[node].append([attr, translateMin, translateMax]) for attr in translateAttrs]
139 |
140 | if isScale:
141 | [attrData[node].append([attr, scaleMin, scaleMax]) for attr in scaleAttrs]
142 |
143 | currTime = attrsSampling(attrData, interval)
144 |
145 | end = currTime-1
146 | utils.trimTimeRange(start, end)
147 | cmds.currentTime(start)
148 |
149 | #----------------------------------------------------------------------
150 | def getBlendshapeFromSelection():
151 | """
152 | Returns:
153 | str
154 | """
155 | try:
156 | return cmds.ls(sl=1, type='blendShape')[0]
157 | except:
158 | om.MGlobal.displayError("No blendshape found in your selection.")
159 | return
160 |
161 | #----------------------------------------------------------------------
162 | def deleteAnimations():
163 | """"""
164 | animCurveTypes = ['animCurveTU', 'animCurveTA', 'animCurveTL', 'animCurveTT']
165 |
166 | sel = cmds.ls(sl=1, ap=1)
167 | if not sel:
168 | om.MGlobal.displayError("Please select something first.")
169 | return
170 |
171 | for node in sel:
172 | connects = cmds.listConnections(node, s=1, d=0, scn=1)
173 | animCurves = cmds.ls(connects, type=animCurveTypes)
174 | cmds.delete(animCurves)
175 |
176 |
177 | if __name__ == '__main__':
178 | node = 'locator1'
179 | bsNode = 'headGEO_IMBS'
180 | attr = 'tx'
181 | maxVal = 1
182 | minVal = -1
183 | interval = 1
184 | sel = cmds.ls(sl=1, ap=1)
185 | for s in sel:
186 | rotateSampling(s, -90, 90, interval)
187 | currTime = translateSampling(s, minVal, maxVal, interval)
188 | cmds.currentTime(currTime+1)
189 | # currTime = blendShapeSampling(bsNode, interval)
190 | # cmds.currentTime(currTime)
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/core/utils.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | import maya.cmds as cmds
6 | import maya.mel as mel
7 | import maya.OpenMaya as om
8 | import maya.OpenMayaAnim as oma
9 |
10 |
11 |
12 | # Create exception class
13 | class UserInputError(Exception): pass
14 |
15 | #----------------------------------------------------------------------
16 | def mayaVersion():
17 | """
18 | need to manage this better and use the API version,
19 | eg: 2013.5 returns 2013
20 | """
21 | return mel.eval('getApplicationVersionAsFloat')
22 |
23 | #----------------------------------------------------------------------
24 | def getDependNode(name):
25 | """
26 | Args:
27 | name (str)
28 |
29 | Returns:
30 | MOBject
31 | """
32 | selList = om.MSelectionList()
33 | selList.add (name)
34 | node = om.MObject()
35 | selList.getDependNode(0, node)
36 | return node
37 |
38 | #----------------------------------------------------------------------
39 | def getDagPath(name):
40 | """
41 | Args:
42 | name (str)
43 |
44 | Returns:
45 | MDagPath
46 | """
47 | selList = om.MSelectionList()
48 | selList.add (name)
49 | dagPath = om.MDagPath()
50 | selList.getDagPath(0, dagPath)
51 | return dagPath
52 |
53 | #----------------------------------------------------------------------
54 | def getComponent(name):
55 | """
56 | Args:
57 | name (str)
58 |
59 | Returns:
60 | MOBject
61 | """
62 | selList = om.MSelectionList()
63 | selList.add (name)
64 | dagPath = om.MDagPath()
65 | component = om.MObject()
66 | selList.getDagPath(0, dagPath, component)
67 | return component
68 |
69 | #----------------------------------------------------------------------
70 | def getDagPathComponents(compList):
71 | """
72 | Args:
73 | compList (list)
74 |
75 | Returns:
76 | MObject
77 | """
78 |
79 | currSel = cmds.ls(sl=1, l=1)
80 | cmds.select(compList, r=1)
81 | selList = om.MSelectionList()
82 | om.MGlobal.getActiveSelectionList(selList)
83 | dagPath = om.MDagPath()
84 | components = om.MObject()
85 | selList.getDagPath(0, dagPath, components)
86 | cmds.select(cl=1)
87 | try:
88 | cmds.select(currSel, r=1)
89 | except:
90 | pass
91 | return dagPath, components
92 |
93 | #----------------------------------------------------------------------
94 | def findRelatedSkinCluster(geometry):
95 | '''
96 | Return the skinCluster attached to the specified geometry
97 |
98 | Args:
99 | geometry (str): Geometry object/transform to query
100 |
101 | Returns:
102 | str
103 | '''
104 | # Check geometry
105 | if not cmds.objExists(geometry):
106 | om.MGlobal.displayError('Object '+geometry+' does not exist!')
107 | return
108 |
109 | # Check transform
110 | if cmds.objectType(geometry) == 'transform':
111 | try: geometry = cmds.listRelatives(geometry,s=True,ni=True,pa=True)[0]
112 | except:
113 | om.MGlobal.displayError('Object %s has no deformable geometry!' % geometry)
114 | return
115 |
116 | # Determine skinCluster
117 | skin = mel.eval('findRelatedSkinCluster \"%s\"' % geometry)
118 | if not skin:
119 | skin = cmds.ls(cmds.listHistory(geometry, pdo=1, gl=1), type='skinCluster')
120 | if skin: skin = skin[0]
121 | if not skin: skin = None
122 |
123 | # Return result
124 | return skin
125 |
126 | #----------------------------------------------------------------------
127 | def findRelatedDeltaMush(geometry):
128 | """
129 | Return the delta mush deformer attached to the specified geometry
130 |
131 | Args:
132 | geometry (str): Geometry object/transform to query
133 |
134 | Returns:
135 | str
136 | """
137 | # Check geometry
138 | if not cmds.objExists(geometry):
139 | raise Exception('Object '+geometry+' does not exist!')
140 |
141 | hist = cmds.listHistory(geometry, pdo=1, gl=1)
142 | try:
143 | if mayaVersion() >= 2016:
144 | return cmds.ls(hist, type=["deltaMush", "wbDeltaMush"])[0]
145 | else:
146 | return cmds.ls(hist, type="wbDeltaMush")[0]
147 | except:
148 | return None
149 |
150 | #----------------------------------------------------------------------
151 | def trimTimeRange(start, end):
152 | """
153 | Args:
154 | start (float)
155 | end (float)
156 | """
157 | animCtrl = oma.MAnimControl()
158 | startTime = om.MTime(start)
159 | endTime = om.MTime(end)
160 | animCtrl.setAnimationStartEndTime (startTime, endTime)
161 | animCtrl.setMinMaxTime(startTime, endTime)
162 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/startup/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/startup/setup.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 | __buildVersionID__ = '1.5.5'
5 | __ENVIRONMENT_NAME__ = "DEFORMATION_LEARNING_SOLVER"
6 |
7 |
8 | import sys
9 | import os
10 | import maya.cmds as cmds
11 | import maya.mel as mel
12 | import maya.OpenMayaUI as omui
13 |
14 | PYSIDE_VERSION = '-1'
15 | try:
16 | import PySide
17 | PYSIDE_VERSION = PySide.__version__
18 | from PySide import QtGui, QtCore
19 | from PySide.QtGui import *
20 | from PySide.QtCore import *
21 | from shiboken import wrapInstance
22 | except ImportError:
23 | import PySide2
24 | PYSIDE_VERSION = PySide2.__version__
25 | from PySide2 import QtGui, QtCore, QtWidgets
26 | from PySide2.QtGui import *
27 | from PySide2.QtCore import *
28 | from PySide2.QtWidgets import *
29 | from shiboken2 import wrapInstance
30 |
31 | import logging
32 | logging.basicConfig()
33 | log = logging.getLogger(__name__)
34 | log.setLevel(logging.INFO)
35 |
36 |
37 | # Static variables
38 | SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)).replace('\\', '/')
39 | SSD_SOLVER_PLUGIN_BASE_NAME = "SSDSolverCmd"
40 | DELTA_MUSH_PLUGIN_BASE_NAME = "wbDeltaMushDeformer"
41 | MAIN_WINDOW = "DeformationLearningSolverWin"
42 |
43 |
44 | #----------------------------------------------------------------------
45 | def getMayaWindow():
46 | ptr = omui.MQtUtil.mainWindow()
47 | if ptr:
48 | return wrapInstance(long(ptr), QWidget)
49 |
50 | #----------------------------------------------------------------------
51 | def show():
52 | """"""
53 | from DLS.widget import mainWindow
54 | reload(mainWindow)
55 |
56 | if cmds.window(MAIN_WINDOW, ex=1):
57 | cmds.deleteUI(MAIN_WINDOW)
58 |
59 | parent = getMayaWindow()
60 | win = mainWindow.MainWindow(parent)
61 |
62 | win.setWindowFlags(Qt.Window) # Make this widget a standalone window
63 | # identify a Maya-managed floating window,
64 | # which handles the z order properly and saves its positions
65 | win.setProperty("saveWindowPref", True )
66 |
67 | win.setAttribute(Qt.WA_DeleteOnClose)
68 | win.show()
69 |
70 | #----------------------------------------------------------------------
71 | def getEnviron():
72 | """"""
73 | return __ENVIRONMENT_NAME__
74 |
75 |
76 | #----------------------------------------------------------------------
77 | def loadSSDSolverPlugin():
78 | """"""
79 | os = cmds.about(os=1)
80 |
81 | if os == 'win64':
82 | pluginName = '%s.mll' % (SSD_SOLVER_PLUGIN_BASE_NAME)
83 | elif os == 'mac':
84 | pluginName = '%s.bundle' % (SSD_SOLVER_PLUGIN_BASE_NAME)
85 | elif os == 'linux64':
86 | pluginName = '%s.so' % (SSD_SOLVER_PLUGIN_BASE_NAME)
87 |
88 | if not cmds.pluginInfo(pluginName, q=True, l=True ):
89 | try:
90 | cmds.loadPlugin(pluginName)
91 | pluginVers = cmds.pluginInfo(pluginName, q=1, v=1)
92 | log.info('Plug-in: %s v%s loaded success!' % (pluginName, pluginVers))
93 | except:
94 | log.info('Plug-in: %s, was not found on MAYA_PLUG_IN_PATH.' % (pluginName))
95 | else:
96 | pluginVers = cmds.pluginInfo(pluginName, q=1, v=1)
97 | log.info('Plug-in: %s v%s has been loaded!' % (pluginName, pluginVers))
98 |
99 | #----------------------------------------------------------------------
100 | def loadDeltaMushPlugin():
101 | """"""
102 | os = cmds.about(os=1)
103 |
104 | if os == 'win64':
105 | pluginName = '%s.mll' % (DELTA_MUSH_PLUGIN_BASE_NAME)
106 | elif os == 'mac':
107 | pluginName = '%s.bundle' % (DELTA_MUSH_PLUGIN_BASE_NAME)
108 | elif os == 'linux64':
109 | pluginName = '%s.so' % (DELTA_MUSH_PLUGIN_BASE_NAME)
110 |
111 | if not cmds.pluginInfo(pluginName, q=True, l=True ):
112 | try:
113 | cmds.loadPlugin(pluginName)
114 | pluginVers = cmds.pluginInfo(pluginName, q=1, v=1)
115 | log.info('Plug-in: %s v%s loaded success!' % (pluginName, pluginVers))
116 | except:
117 | log.info('Plug-in: %s, was not found on MAYA_PLUG_IN_PATH.' % (pluginName))
118 | else:
119 | pluginVers = cmds.pluginInfo(pluginName, q=1, v=1)
120 | log.info('Plug-in: %s v%s has been loaded!' % (pluginName, pluginVers))
121 |
122 | #----------------------------------------------------------------------
123 | def loadPlugin():
124 | """"""
125 | loadSSDSolverPlugin()
126 | loadDeltaMushPlugin()
127 |
128 | #----------------------------------------------------------------------
129 | def mayaVersion():
130 | """
131 | need to manage this better and use the API version,
132 | eg: 2013.5 returns 2013
133 | """
134 | return mel.eval('getApplicationVersionAsFloat')
135 |
136 | #----------------------------------------------------------------------
137 | def getModulePath():
138 | '''
139 | Returns the Main path to the root module folder
140 | '''
141 | return os.path.join(os.path.dirname(SCRIPT_DIRECTORY),'').replace('\\', '/')
142 |
143 | #----------------------------------------------------------------------
144 | def getVersion():
145 | return __buildVersionID__
146 |
147 | #----------------------------------------------------------------------
148 | def getAuthor():
149 | return __author__
150 |
151 | #----------------------------------------------------------------------
152 | def getMainWindowName():
153 | return MAIN_WINDOW
154 |
155 | # BOOT FUNCTS - Add and Build --------------------------------------------------------------
156 |
157 | def addScriptsPath(path):
158 | '''
159 | Add additional folders to the ScriptPath
160 | '''
161 | scriptsPath = os.environ.get('MAYA_SCRIPT_PATH')
162 |
163 | if os.path.exists(path):
164 | if not path in scriptsPath:
165 | log.info('Adding To Script Paths : %s' % path)
166 | os.environ['MAYA_SCRIPT_PATH']+='%s%s' % (os.pathsep, path)
167 | else:
168 | log.info('Deformation Learning Script Path already setup : %s' % path)
169 | else:
170 | log.debug('Given Script Path is invalid : %s' % path)
171 |
172 |
173 | #=========================================================================================
174 | # BOOT CALL ------------------------------------------------------------------------------
175 | #=========================================================================================
176 |
177 | def launch():
178 | '''
179 | Main entry point
180 | '''
181 | log.info('Deformation Learning v%s : Author: %s' % (getVersion(), getAuthor()))
182 | log.info('Deformation Learning Setup Calls :: Booting from >> %s' % getModulePath())
183 |
184 | # Add module to environment
185 | os.environ[__ENVIRONMENT_NAME__] = getModulePath()
186 | # addScriptsPath(os.environ[__ENVIRONMENT_NAME__])
187 |
188 | # Load Plug-in
189 | loadPlugin()
190 |
191 | # launch UI
192 | show()
193 |
194 | log.info('Deformation Learning initialize Complete!')
195 |
196 | def interface():
197 | show()
198 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/aboutDialog.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | import os
6 |
7 | try:
8 | from PySide import QtGui, QtCore
9 | from PySide.QtGui import *
10 | from PySide.QtCore import *
11 | except ImportError:
12 | from PySide2 import QtGui, QtCore, QtWidgets
13 | from PySide2.QtGui import *
14 | from PySide2.QtCore import *
15 | from PySide2.QtWidgets import *
16 |
17 | from DLS.widget import utils
18 |
19 |
20 | uifile = os.path.join(utils.SCRIPT_DIRECTORY, "ui/aboutDialog.ui")
21 |
22 |
23 | ########################################################################
24 | class AboutDialog(QDialog):
25 | """"""
26 | _TITLE = 'Utility'
27 |
28 | #----------------------------------------------------------------------
29 | def __init__(self, parent=None):
30 | """Constructor"""
31 | super(AboutDialog, self).__init__(parent)
32 | utils.loadUi(uifile, self)
33 | self.initWidgets()
34 |
35 | #----------------------------------------------------------------------
36 | def initWidgets(self):
37 | """"""
38 | cp = QDesktopWidget().screenGeometry().center()
39 | self.move(cp)
40 |
41 |
42 | #----------------------------------------------------------------------
43 | def main():
44 | import sys
45 | app = QApplication(sys.argv)
46 | window = AboutDialog()
47 | window.show()
48 | app.exec_()
49 |
50 |
51 | if __name__ == "__main__":
52 | main()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/axisOptionWindow.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | import os
6 |
7 | try:
8 | from PySide import QtGui, QtCore
9 | from PySide.QtGui import *
10 | from PySide.QtCore import *
11 | except ImportError:
12 | from PySide2 import QtGui, QtCore, QtWidgets
13 | from PySide2.QtGui import *
14 | from PySide2.QtCore import *
15 | from PySide2.QtWidgets import *
16 |
17 | from DLS.widget import utils
18 | from DLS.widget import baseOptionWindow
19 |
20 | #reload(baseOptionWindow)
21 |
22 |
23 | uifile = os.path.join(utils.SCRIPT_DIRECTORY, "ui/axisWindow.ui")
24 | cfgfile = os.path.join(utils.SCRIPT_DIRECTORY, "config.ini")
25 |
26 |
27 | ########################################################################
28 | class AxisOptionWindow(baseOptionWindow.BaseOptionWindow):
29 | """"""
30 | _TITLE = 'Axis Options'
31 |
32 | #----------------------------------------------------------------------
33 | def __init__(self, parent=None):
34 | """Constructor"""
35 | super(AxisOptionWindow, self).__init__(parent)
36 | #utils.loadUi(uifile, self)
37 | #self.initWidgets()
38 |
39 | #----------------------------------------------------------------------
40 | def initWidgets(self):
41 | """"""
42 | self.readSettings()
43 |
44 | self.setWindowTitle(self._TITLE)
45 | cp = QDesktopWidget().screenGeometry().center()
46 | self.move(cp)
47 |
48 | # Add actions
49 | actionReset = self.findChild(QAction, "actionReset")
50 | if actionReset != None:
51 | actionReset.triggered.connect(self.resetSettings)
52 |
53 | #----------------------------------------------------------------------
54 | def isX(self):
55 | """"""
56 | x_chk = self.findChild(QCheckBox, "x_chk")
57 | if x_chk != None:
58 | return x_chk.isChecked()
59 | return True
60 |
61 | #----------------------------------------------------------------------
62 | def setX(self, val):
63 | """"""
64 | x_chk = self.findChild(QCheckBox, "x_chk")
65 | if x_chk != None:
66 | x_chk.setChecked(val)
67 |
68 | #----------------------------------------------------------------------
69 | def isY(self):
70 | """"""
71 | y_chk = self.findChild(QCheckBox, "y_chk")
72 | if y_chk != None:
73 | return y_chk.isChecked()
74 | return True
75 |
76 | #----------------------------------------------------------------------
77 | def setY(self, val):
78 | """"""
79 | y_chk = self.findChild(QCheckBox, "y_chk")
80 | if y_chk != None:
81 | y_chk.setChecked(val)
82 |
83 | #----------------------------------------------------------------------
84 | def isZ(self):
85 | """"""
86 | z_chk = self.findChild(QCheckBox, "z_chk")
87 | if z_chk != None:
88 | return z_chk.isChecked()
89 | return True
90 |
91 | #----------------------------------------------------------------------
92 | def setZ(self, val):
93 | """"""
94 | z_chk = self.findChild(QCheckBox, "z_chk")
95 | if z_chk != None:
96 | z_chk.setChecked(val)
97 |
98 |
99 | ########################################################################
100 | class TranslateAxisOptionWindow(AxisOptionWindow):
101 | """"""
102 | _TITLE = 'Translate Axis Options'
103 |
104 | #----------------------------------------------------------------------
105 | def __init__(self, parent=None):
106 | """Constructor"""
107 | super(TranslateAxisOptionWindow, self).__init__(parent)
108 | utils.loadUi(uifile, self)
109 | self.initWidgets()
110 |
111 | #----------------------------------------------------------------------
112 | def resetSettings(self):
113 | settings = QSettings(cfgfile, QSettings.IniFormat)
114 |
115 | settings.beginGroup("Default")
116 | self.setX(bool(int(settings.value("translateX"))))
117 | self.setY(bool(int(settings.value("translateY"))))
118 | self.setZ(bool(int(settings.value("translateZ"))))
119 | settings.endGroup()
120 |
121 | #----------------------------------------------------------------------
122 | def readSettings(self):
123 | settings = QSettings(cfgfile, QSettings.IniFormat)
124 |
125 | settings.beginGroup("Custom")
126 | self.setX(bool(int(settings.value("translateX"))))
127 | self.setY(bool(int(settings.value("translateY"))))
128 | self.setZ(bool(int(settings.value("translateZ"))))
129 | settings.endGroup()
130 |
131 | #----------------------------------------------------------------------
132 | def writeSettings(self):
133 | settings = QSettings(cfgfile, QSettings.IniFormat)
134 |
135 | settings.beginGroup("Custom")
136 | settings.setValue("translateX", int(self.isX()))
137 | settings.setValue("translateY", int(self.isY()))
138 | settings.setValue("translateZ", int(self.isZ()))
139 | settings.endGroup()
140 |
141 |
142 | ########################################################################
143 | class RotateAxisOptionWindow(AxisOptionWindow):
144 | """"""
145 | _TITLE = 'Rotate Axis Options'
146 |
147 | #----------------------------------------------------------------------
148 | def __init__(self, parent=None):
149 | """Constructor"""
150 | super(RotateAxisOptionWindow, self).__init__(parent)
151 | utils.loadUi(uifile, self)
152 | self.initWidgets()
153 |
154 | #----------------------------------------------------------------------
155 | def resetSettings(self):
156 | settings = QSettings(cfgfile, QSettings.IniFormat)
157 |
158 | settings.beginGroup("Default")
159 | self.setX(bool(int(settings.value("rotateX"))))
160 | self.setY(bool(int(settings.value("rotateY"))))
161 | self.setZ(bool(int(settings.value("rotateZ"))))
162 | settings.endGroup()
163 |
164 | #----------------------------------------------------------------------
165 | def readSettings(self):
166 | settings = QSettings(cfgfile, QSettings.IniFormat)
167 |
168 | settings.beginGroup("Custom")
169 | self.setX(bool(int(settings.value("rotateX"))))
170 | self.setY(bool(int(settings.value("rotateY"))))
171 | self.setZ(bool(int(settings.value("rotateZ"))))
172 | settings.endGroup()
173 |
174 | #----------------------------------------------------------------------
175 | def writeSettings(self):
176 | settings = QSettings(cfgfile, QSettings.IniFormat)
177 |
178 | settings.beginGroup("Custom")
179 | settings.setValue("rotateX", int(self.isX()))
180 | settings.setValue("rotateY", int(self.isY()))
181 | settings.setValue("rotateZ", int(self.isZ()))
182 | settings.endGroup()
183 |
184 |
185 | ########################################################################
186 | class ScaleAxisOptionWindow(AxisOptionWindow):
187 | """"""
188 | _TITLE = 'Scale Axis Options'
189 |
190 | #----------------------------------------------------------------------
191 | def __init__(self, parent=None):
192 | """Constructor"""
193 | super(ScaleAxisOptionWindow, self).__init__(parent)
194 | utils.loadUi(uifile, self)
195 | self.initWidgets()
196 |
197 | #----------------------------------------------------------------------
198 | def resetSettings(self):
199 | settings = QSettings(cfgfile, QSettings.IniFormat)
200 |
201 | settings.beginGroup("Default")
202 | self.setX(bool(int(settings.value("scaleX"))))
203 | self.setY(bool(int(settings.value("scaleY"))))
204 | self.setZ(bool(int(settings.value("scaleZ"))))
205 | settings.endGroup()
206 |
207 | #----------------------------------------------------------------------
208 | def readSettings(self):
209 | settings = QSettings(cfgfile, QSettings.IniFormat)
210 |
211 | settings.beginGroup("Custom")
212 | self.setX(bool(int(settings.value("scaleX"))))
213 | self.setY(bool(int(settings.value("scaleY"))))
214 | self.setZ(bool(int(settings.value("scaleZ"))))
215 | settings.endGroup()
216 |
217 | #----------------------------------------------------------------------
218 | def writeSettings(self):
219 | settings = QSettings(cfgfile, QSettings.IniFormat)
220 |
221 | settings.beginGroup("Custom")
222 | settings.setValue("scaleX", int(self.isX()))
223 | settings.setValue("scaleY", int(self.isY()))
224 | settings.setValue("scaleZ", int(self.isZ()))
225 | settings.endGroup()
226 |
227 | #----------------------------------------------------------------------
228 | def main():
229 | import sys
230 | app = QApplication(sys.argv)
231 | window = ScaleAxisOptionWindow()
232 | window.show()
233 | app.exec_()
234 |
235 |
236 | if __name__ == "__main__":
237 | main()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/baseOptionWindow.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | try:
6 | from PySide import QtGui, QtCore
7 | from PySide.QtGui import *
8 | from PySide.QtCore import *
9 | except ImportError:
10 | from PySide2 import QtGui, QtCore, QtWidgets
11 | from PySide2.QtGui import *
12 | from PySide2.QtCore import *
13 | from PySide2.QtWidgets import *
14 |
15 |
16 | ########################################################################
17 | class BaseOptionWindow(QMainWindow):
18 | """"""
19 | _TITLE = ''
20 |
21 | #----------------------------------------------------------------------
22 | def __init__(self, parent = None):
23 | """Constructor"""
24 | super(BaseOptionWindow, self).__init__(parent)
25 | #QMainWindow.__init__(self, parent)
26 | #self.initWidgets()
27 |
28 | #----------------------------------------------------------------------
29 | def initWidgets(self):
30 | NotImplemented
31 |
32 | #----------------------------------------------------------------------
33 | def resetSettings(self):
34 | NotImplemented
35 |
36 | #----------------------------------------------------------------------
37 | def readSettings(self):
38 | NotImplemented
39 |
40 | #----------------------------------------------------------------------
41 | def writeSettings(self):
42 | NotImplemented
43 |
44 | #----------------------------------------------------------------------
45 | @Slot()
46 | def on_save_btn_clicked(self):
47 | self.writeSettings()
48 | self.close()
49 |
50 | #----------------------------------------------------------------------
51 | @Slot()
52 | def on_cancel_btn_clicked(self):
53 | self.close()
54 |
55 | #----------------------------------------------------------------------
56 | def showUI(self):
57 | """"""
58 | self.readSettings()
59 | self.show()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/baseTab.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | try:
6 | from PySide import QtGui, QtCore
7 | from PySide.QtGui import *
8 | from PySide.QtCore import *
9 | from PySide.QtUiTools import QUiLoader
10 | except ImportError:
11 | from PySide2 import QtGui, QtCore, QtWidgets
12 | from PySide2.QtGui import *
13 | from PySide2.QtCore import *
14 | from PySide2.QtWidgets import *
15 | from PySide2.QtUiTools import QUiLoader
16 |
17 | from DLS.widget import utils
18 | #reload(utils)
19 |
20 |
21 | ########################################################################
22 | class BaseTab(QWidget):
23 | _TITLE = 'Untitle'
24 |
25 | #----------------------------------------------------------------------
26 | def __init__(self, parent=None):
27 | super(BaseTab, self).__init__(parent)
28 | #self.parent = parent
29 | #loader = QUiLoader()
30 | #f = QFile(uifile)
31 | #f.open(QFile.ReadOnly)
32 | #widget = loader.load(f, self)
33 | #f.close()
34 |
35 | #layout = QVBoxLayout()
36 | #layout.addWidget(widget)
37 | #self.setLayout(layout)
38 | #utils.loadUi(uifile)
39 |
40 | #----------------------------------------------------------------------
41 | def title(self):
42 | return self._TITLE
43 |
44 | #----------------------------------------------------------------------
45 | def readSettings(self):
46 | pass
47 |
48 | #----------------------------------------------------------------------
49 | def writeSettings(self):
50 | pass
51 |
52 | #----------------------------------------------------------------------
53 | def resetSettings(self):
54 | pass
55 |
56 | #----------------------------------------------------------------------
57 | def closeEvent(self, event):
58 | """"""
59 | self.writeSettings()
60 | event.accept()
61 |
62 |
63 | def main():
64 | import sys
65 | app = QApplication(sys.argv)
66 | window = BaseTab()
67 | window.show()
68 | app.exec_()
69 |
70 |
71 | if __name__ == "__main__":
72 | main()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/config.ini:
--------------------------------------------------------------------------------
1 | [Custom]
2 | epsilon=1
3 | isBlendshape=0
4 | isCustomAttrs=0
5 | isDeleteDeltaMush=0
6 | isKeepOriginal=1
7 | isRotate=1
8 | isScale=0
9 | isTranslate=0
10 | maxInfs=4
11 | maxIters=10
12 | numBones=1
13 | pruneBeblow=0
14 | rotateMax=90
15 | rotateMin=-90
16 | rotateX=1
17 | rotateY=1
18 | rotateZ=1
19 | scaleMax=1
20 | scaleMin=-1
21 | scaleX=1
22 | scaleY=1
23 | scaleZ=1
24 | skipTips=1
25 | translateMax=1
26 | translateMin=-1
27 | translateX=1
28 | translateY=1
29 | translateZ=1
30 | useBuildInDeltaMush=0
31 |
32 | [Default]
33 | blendshapeName=
34 | epsilon=1
35 | isBlendshape=0
36 | isCustomAttrs=0
37 | isDeleteDeltaMush=0
38 | isKeepOriginal=1
39 | isRotate=1
40 | isScale=0
41 | isTranslate=0
42 | maxInfs=4
43 | maxIters=10
44 | numBones=1
45 | pruneBeblow=0.0
46 | rotateMax=90.0
47 | rotateMin=-90.0
48 | rotateX=1
49 | rotateY=1
50 | rotateZ=1
51 | scaleMax=1.0
52 | scaleMin=-1.0
53 | scaleX=1
54 | scaleY=1
55 | scaleZ=1
56 | skipTips=1
57 | translateMax=1.0
58 | translateMin=-1.0
59 | translateX=1
60 | translateY=1
61 | translateZ=1
62 | useBuildInDeltaMush=0
63 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/customAttributeEditor.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | import os
6 |
7 | try:
8 | from PySide import QtGui, QtCore
9 | from PySide.QtGui import *
10 | from PySide.QtCore import *
11 | except ImportError:
12 | from PySide2 import QtGui, QtCore, QtWidgets
13 | from PySide2.QtGui import *
14 | from PySide2.QtCore import *
15 | from PySide2.QtWidgets import *
16 |
17 | import maya.cmds as cmds
18 | import maya.OpenMaya as om
19 |
20 |
21 | from DLS.widget import baseOptionWindow
22 | from DLS.widget import utils
23 | from DLS.startup import setup
24 |
25 |
26 | uifile = os.path.join(utils.SCRIPT_DIRECTORY, "ui/customAttributeEditor.ui")
27 | cfgfile = os.path.join(utils.SCRIPT_DIRECTORY, "config.ini")
28 |
29 |
30 | ########################################################################
31 | class CustomAttributeEditor(baseOptionWindow.BaseOptionWindow):
32 | """
33 | self.data = {node1: [[attr1, min, max], [attr2, min, max], ...],
34 | node2: [[attr1, min, max], [attr2, min, max], ...],
35 | ...}
36 | """
37 |
38 | _TITLE = 'Custom Attributes Editor'
39 | _HEAD_LABLE = ['Attribute','Min','Max']
40 |
41 | #----------------------------------------------------------------------
42 | def __init__(self, data, parent=None):
43 | """Constructor"""
44 | super(CustomAttributeEditor, self).__init__(parent)
45 | utils.loadUi(uifile, self)
46 | self.parent = parent
47 | self.table = None
48 | self.attrs = []
49 | self.minVals = []
50 | self.maxVals = []
51 | self.data = data
52 |
53 | self.initWidgets()
54 |
55 | #----------------------------------------------------------------------
56 | def initWidgets(self):
57 | """"""
58 | self.setWindowTitle(self._TITLE)
59 | cp = QDesktopWidget().screenGeometry().center()
60 | self.move(cp)
61 |
62 | # Set table
63 | self.table = self.findChild(QTableWidget, "data_table")
64 | self.table.setColumnCount(3)
65 | self.table.setHorizontalHeaderLabels(self._HEAD_LABLE)
66 | self.table.setAlternatingRowColors(True)
67 | self.table.setColumnWidth(1, 56)
68 | self.table.setColumnWidth(2, 56)
69 |
70 | if setup.PYSIDE_VERSION < 2.0:
71 | self.table.horizontalHeader().setResizeMode(0, QHeaderView.Stretch)
72 | else:
73 | self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
74 |
75 | # Fill table
76 | i = 0
77 | for node, attrVals in self.data.iteritems():
78 | for vals in attrVals:
79 | attr, minVal, maxVal = vals
80 | name = "%s.%s" % (node, attr)
81 | self.appendRow()
82 | self.setRow(i, [name, minVal, maxVal])
83 | i += 1
84 |
85 | # Set delete row action
86 | delAction = QAction(self)
87 | delAction.setObjectName("del_action")
88 | delAction.triggered.connect(self.removeRow)
89 | delAction.setShortcut(QKeySequence.Delete)
90 | delAction.setShortcutContext(Qt.WidgetWithChildrenShortcut)
91 | self.addAction(delAction)
92 |
93 | # Set signal functions
94 | self.table.itemChanged.connect(self.setItems)
95 |
96 | #----------------------------------------------------------------------
97 | def numRow(self):
98 | return self.table.rowCount()
99 |
100 | #----------------------------------------------------------------------
101 | def numColumn(self):
102 | return self.table.columnCount()
103 |
104 | #----------------------------------------------------------------------
105 | def appendRow(self):
106 | self.table.insertRow(self.numRow())
107 | for i in xrange(self.numColumn()):
108 | self.table.setItem(self.numRow()-1, i, QTableWidgetItem('0'))
109 |
110 | #----------------------------------------------------------------------
111 | def setRow(self, row, data):
112 | """
113 | Args:
114 | row (int)
115 | data (list)
116 | """
117 | for i in xrange(len(data)):
118 | self.table.item(row, i).setText(str(data[i]))
119 |
120 | #----------------------------------------------------------------------
121 | def getDataOnRow(self, row):
122 | """
123 | Args:
124 | row (int)
125 | """
126 | data = []
127 | for i in xrange(self.numColumn()):
128 | val = self.table.item(row, i).text()
129 | if i > 0: val = float(val)
130 | data.append(val)
131 | return data
132 |
133 | #----------------------------------------------------------------------
134 | def setItems(self, item):
135 | """
136 | Args:
137 | item (QTableWidgetItem)
138 | """
139 | self.table.blockSignals(True)
140 |
141 | value = item.text()
142 | dataType = item.type()
143 | for cellIdx in self.table.selectedIndexes():
144 | currCell = self.table.item(cellIdx.row(), cellIdx.column())
145 | if currCell.type() == dataType:
146 | currCell.setText(value)
147 |
148 | self.table.blockSignals(False)
149 |
150 | #----------------------------------------------------------------------
151 | def removeRow(self):
152 | """"""
153 | selRanges = self.table.selectedRanges()
154 | for sel in reversed(selRanges):
155 | if sel.columnCount() == 3:
156 | for i in xrange(sel.bottomRow(), sel.topRow()-1, -1):
157 | self.table.removeRow(i)
158 | else:
159 | # Set each cell's value to 0
160 | for i in xrange(sel.topRow(), sel.bottomRow()+1):
161 | for j in xrange(sel.leftColumn(), sel.rightColumn()+1):
162 | item = QTableWidgetItem('0')
163 | self.table.setItem(i, j, item)
164 |
165 | #----------------------------------------------------------------------
166 | def saveData(self):
167 | """"""
168 | self.data.clear()
169 | for i in xrange(self.numRow()):
170 | nodeAttr, minVal, maxVal = self.getDataOnRow(i)
171 | node, attr = nodeAttr.split('.')
172 | if not self.data.has_key(node):
173 | self.data[node] = []
174 | self.data[node].append([attr, minVal, maxVal])
175 |
176 | #----------------------------------------------------------------------
177 | @Slot()
178 | def on_add_btn_clicked(self):
179 |
180 | selNodes = cmds.ls(sl=1, ap=1)
181 | if not selNodes:
182 | om.MGlobal.displayError("Please select some nodes and attributes.")
183 | return
184 |
185 | selAttrs = (cmds.channelBox("mainChannelBox", q=1, sma=1) or []) \
186 | + (cmds.channelBox("mainChannelBox", q=1, sha=1) or []) \
187 | + (cmds.channelBox("mainChannelBox", q=1, ssa=1) or []) \
188 | + (cmds.channelBox("mainChannelBox", q=1, soa=1) or [])
189 |
190 | if not selAttrs:
191 | selAttrs = cmds.listAttr(selNodes, v=1, k=1, sn=1)
192 | selAttrs = list(set(selAttrs))
193 | try:
194 | selAttrs.remove('v')
195 | except:
196 | pass
197 |
198 | self.table.clearSelection()
199 |
200 | for node in selNodes:
201 | for attr in selAttrs:
202 | name = "%s.%s" % (node, attr)
203 | minVal, maxVal = 0.0, 1.0
204 | hasMinVal, hasMaxVal = False, False
205 |
206 | if not cmds.objExists(name):
207 | continue
208 |
209 | # Set minVal
210 | if cmds.attributeQuery(attr, node=node, minExists=1):
211 | minVal = cmds.attributeQuery(attr, node=node, min=1)[0]
212 | hasMinVal = True
213 |
214 | if cmds.attributeQuery(attr, node=node, softMinExists=1):
215 | minVal = cmds.attributeQuery(attr, node=node, smn=1)[0]
216 | hasMinVal = True
217 |
218 | # Set maxVal
219 | if cmds.attributeQuery(attr, node=node, maxExists=1):
220 | maxVal = cmds.attributeQuery(attr, node=node, max=1)[0]
221 | hasMaxVal = True
222 |
223 | if cmds.attributeQuery(attr, node=node, softMaxExists=1):
224 | maxVal = cmds.attributeQuery(attr, node=node, smx=1)[0]
225 | hasMaxVal = True
226 |
227 | currVal = cmds.getAttr(name)
228 | if hasMinVal: minVal = minVal - currVal
229 | if hasMaxVal: maxVal = maxVal - currVal
230 |
231 | self.appendRow()
232 | self.setRow(self.numRow()-1, [name, minVal, maxVal])
233 |
234 | #----------------------------------------------------------------------
235 | @Slot()
236 | def on_clear_btn_clicked(self):
237 | for i in xrange(self.numRow()-1, -1, -1):
238 | self.table.removeRow(i)
239 |
240 | #----------------------------------------------------------------------
241 | @Slot()
242 | def on_save_btn_clicked(self):
243 | self.saveData()
244 | self.close()
245 |
246 |
247 |
248 | #----------------------------------------------------------------------
249 | def main():
250 | import sys
251 | app = QApplication(sys.argv)
252 | window = CustomAttributeEditor([])
253 | window.show()
254 | app.exec_()
255 |
256 |
257 | if __name__ == "__main__":
258 | main()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/learningTab.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | import os
6 |
7 | try:
8 | from PySide import QtGui, QtCore
9 | from PySide.QtGui import *
10 | from PySide.QtCore import *
11 | except ImportError:
12 | from PySide2 import QtGui, QtCore, QtWidgets
13 | from PySide2.QtGui import *
14 | from PySide2.QtCore import *
15 | from PySide2.QtWidgets import *
16 |
17 | import maya.cmds as cmds
18 |
19 | from DLS.widget import baseTab
20 | from DLS.widget import utils
21 |
22 | from DLS.core import learningFunc
23 |
24 |
25 | reload(learningFunc)
26 | #reload(baseTab)
27 | #reload(utils)
28 |
29 |
30 | TAB = ''
31 | uifile = os.path.join(utils.SCRIPT_DIRECTORY, "ui/learningTab.ui")
32 | cfgfile = os.path.join(utils.SCRIPT_DIRECTORY, "config.ini")
33 | ENABLE = True
34 | INDEX = 1
35 |
36 |
37 | ########################################################################
38 | class LearningTab(baseTab.BaseTab):
39 | """"""
40 | _TITLE = 'Learning'
41 |
42 | #----------------------------------------------------------------------
43 | def __init__(self, parent=None):
44 | """Constructor"""
45 | super(LearningTab, self).__init__(parent)
46 | utils.loadUi(uifile, self)
47 | self.initWidgets()
48 |
49 | #----------------------------------------------------------------------
50 | def initWidgets(self):
51 | """"""
52 | self.readSettings()
53 |
54 | # Set transformation widgets
55 | doubleVal = QDoubleValidator(decimals=3, parent=self)
56 |
57 | # Set time range widgets
58 | timeSlider_rbtn = self.findChild(QRadioButton, "timeSlider_rbtn")
59 | if timeSlider_rbtn != None:
60 | timeSlider_rbtn.setChecked(True)
61 |
62 | startEnd_rbtn = self.findChild(QRadioButton, "startEnd_rbtn")
63 | if startEnd_rbtn != None:
64 | startEnd_rbtn.setChecked(False)
65 |
66 | startTime_edit = self.findChild(QLineEdit, "startTime_edit")
67 | if startTime_edit != None:
68 | startTime_edit.setEnabled(False)
69 | startTime_edit.setValidator(doubleVal)
70 |
71 | endTime_edit = self.findChild(QLineEdit, "endTime_edit")
72 | if endTime_edit != None:
73 | endTime_edit.setEnabled(False)
74 | endTime_edit.setValidator(doubleVal)
75 |
76 | #----------------------------------------------------------------------
77 | def getNumBones(self):
78 | """"""
79 | numBones_spn = self.findChild(QSpinBox, "numBones_spn")
80 | if numBones_spn != None:
81 | return numBones_spn.value()
82 | return 1
83 |
84 | #----------------------------------------------------------------------
85 | def setNumBones(self, val):
86 | """"""
87 | numBones_spn = self.findChild(QSpinBox, "numBones_spn")
88 | if numBones_spn != None:
89 | numBones_spn.setValue(val)
90 |
91 | #----------------------------------------------------------------------
92 | def getMaxInfs(self):
93 | """"""
94 | maxInfs_spn = self.findChild(QSpinBox, "maxInfs_spn")
95 | if maxInfs_spn != None:
96 | return maxInfs_spn.value()
97 | return 4
98 |
99 | #----------------------------------------------------------------------
100 | def setMaxInfs(self, val):
101 | """"""
102 | maxInfs_spn = self.findChild(QSpinBox, "maxInfs_spn")
103 | if maxInfs_spn != None:
104 | maxInfs_spn.setValue(val)
105 |
106 | #----------------------------------------------------------------------
107 | def getEpsilon(self):
108 | """"""
109 | epsilon_spn = self.findChild(QDoubleSpinBox, "epsilon_spn")
110 | if epsilon_spn != None:
111 | return epsilon_spn.value()
112 | return 1.0
113 |
114 | #----------------------------------------------------------------------
115 | def setEpsilon(self, val):
116 | """"""
117 | epsilon_spn = self.findChild(QDoubleSpinBox, "epsilon_spn")
118 | if epsilon_spn != None:
119 | epsilon_spn.setValue(val)
120 |
121 | #----------------------------------------------------------------------
122 | def getMaxIters(self):
123 | """"""
124 | maxIters_spn = self.findChild(QSpinBox, "maxIters_spn")
125 | if maxIters_spn != None:
126 | return maxIters_spn.value()
127 |
128 | #----------------------------------------------------------------------
129 | def setMaxIters(self, val):
130 | """"""
131 | maxIters_spn = self.findChild(QSpinBox, "maxIters_spn")
132 | if maxIters_spn != None:
133 | maxIters_spn.setValue(val)
134 |
135 | #----------------------------------------------------------------------
136 | def getTargetMesh(self):
137 | """"""
138 | targetMesh_edit = self.findChild(QLineEdit, "targetMesh_edit")
139 | if targetMesh_edit != None:
140 | return str(targetMesh_edit.text())
141 |
142 | #----------------------------------------------------------------------
143 | def setTargetMesh(self, val):
144 | """"""
145 | targetMesh_edit = self.findChild(QLineEdit, "targetMesh_edit")
146 | if targetMesh_edit != None:
147 | targetMesh_edit.setText(val)
148 |
149 | #----------------------------------------------------------------------
150 | def isAlternativeUpdate(self):
151 | """"""
152 | alternativeUpdate_chk = self.findChild(QCheckBox, "alternativeUpdate_chk")
153 | if alternativeUpdate_chk != None:
154 | return alternativeUpdate_chk.isChecked()
155 | return True
156 |
157 | #----------------------------------------------------------------------
158 | def setAlternativeUpdate(self, val):
159 | """"""
160 | alternativeUpdate_chk = self.findChild(QCheckBox, "alternativeUpdate_chk")
161 | if alternativeUpdate_chk != None:
162 | alternativeUpdate_chk.setChecked(val)
163 |
164 | #----------------------------------------------------------------------
165 | def getStartTime(self):
166 | """"""
167 | startTime_edit = self.findChild(QLineEdit, "startTime_edit")
168 | if startTime_edit != None:
169 | return float(startTime_edit.text())
170 | return 0.0
171 |
172 | #----------------------------------------------------------------------
173 | def getEndTime(self):
174 | """"""
175 | endTime_edit = self.findChild(QLineEdit, "endTime_edit")
176 | if endTime_edit != None:
177 | return float(endTime_edit.text())
178 | return 0.0
179 |
180 | #----------------------------------------------------------------------
181 | def isTimeSlider(self):
182 | """"""
183 | timeSlider_rbtn = self.findChild(QRadioButton, "timeSlider_rbtn")
184 | if timeSlider_rbtn != None:
185 | return timeSlider_rbtn.isChecked()
186 | return True
187 |
188 | #----------------------------------------------------------------------
189 | def isStartEnd(self):
190 | """"""
191 | startEnd_rbtn = self.findChild(QRadioButton, "startEnd_rbtn")
192 | if startEnd_rbtn != None:
193 | return startEnd_rbtn.isChecked()
194 |
195 | #----------------------------------------------------------------------
196 | def getTimeRange(self):
197 | """"""
198 | if self.isStartEnd():
199 | start = int(self.getStartTime())
200 | end = int(self.getEndTime())
201 | return start, end
202 |
203 | start = int(cmds.playbackOptions(q=1, min=1))
204 | end = int(cmds.playbackOptions(q=1, max=1))
205 | return start, end
206 |
207 | #----------------------------------------------------------------------
208 | def readSettings(self):
209 | settings = QSettings(cfgfile, QSettings.IniFormat)
210 |
211 | settings.beginGroup("Custom")
212 | self.setNumBones(int(settings.value("numBones")))
213 | self.setMaxInfs(int(settings.value("maxInfs")))
214 | self.setEpsilon(float(settings.value("epsilon")))
215 | self.setMaxIters(float(settings.value("maxIters")))
216 | settings.endGroup()
217 |
218 | #----------------------------------------------------------------------
219 | def writeSettings(self):
220 | settings = QSettings(cfgfile, QSettings.IniFormat)
221 |
222 | settings.beginGroup("Custom")
223 | settings.setValue("numBones", self.getNumBones())
224 | settings.setValue("maxInfs", self.getMaxInfs())
225 | settings.setValue("epsilon", float(self.getEpsilon()))
226 | settings.setValue("maxIters", self.getMaxIters())
227 | settings.endGroup()
228 |
229 | #----------------------------------------------------------------------
230 | def resetSettings(self):
231 | settings = QSettings(cfgfile, QSettings.IniFormat)
232 |
233 | settings.beginGroup("Default")
234 | self.setNumBones(int(settings.value("numBones")))
235 | self.setMaxInfs(int(settings.value("maxInfs")))
236 | self.setEpsilon(float(settings.value("epsilon")))
237 | self.setMaxIters(int(settings.value("maxIters")))
238 | settings.endGroup()
239 |
240 | self.setTargetMesh("")
241 | self.setAlternativeUpdate(False)
242 |
243 | #----------------------------------------------------------------------
244 | @Slot()
245 | def on_loadTargetMesh_btn_clicked(self):
246 | mesh = learningFunc.getMeshFromSelection()
247 | self.setTargetMesh(mesh)
248 |
249 | #----------------------------------------------------------------------
250 | @Slot(bool)
251 | def on_startEnd_rbtn_toggled(self, isChecked):
252 | startTime_edit = self.findChild(QLineEdit, "startTime_edit")
253 | if startTime_edit != None:
254 | startTime_edit.setEnabled(isChecked)
255 |
256 | endTime_edit = self.findChild(QLineEdit, "endTime_edit")
257 | if endTime_edit != None:
258 | endTime_edit.setEnabled(isChecked)
259 |
260 | #----------------------------------------------------------------------
261 | @Slot()
262 | def on_solve_btn_clicked(self):
263 | settings = QSettings(cfgfile, QSettings.IniFormat)
264 |
265 | # Read global settings
266 | settings.beginGroup("Custom")
267 | pruneBelow = float(settings.value("pruneBeblow"))
268 | isKeepOriginal = bool(int(settings.value("isKeepOriginal")))
269 | isDeleteDeltaMush = bool(int(settings.value("isDeleteDeltaMush")))
270 | settings.endGroup()
271 |
272 | # Read local settings
273 | numBones = self.getNumBones()
274 | maxInfs = self.getMaxInfs()
275 | start, end = self.getTimeRange()
276 | maxIters = self.getMaxIters()
277 | epilon = self.getEpsilon()
278 | targetMesh = self.getTargetMesh()
279 | isAlternativeUpdate = self.isAlternativeUpdate()
280 | learningFunc.solve(numBones, maxInfs, targetMesh, isAlternativeUpdate,
281 | start, end, maxIters,isKeepOriginal, pruneBelow,
282 | epilon, isDeleteDeltaMush)
283 |
284 | #----------------------------------------------------------------------
285 | @Slot()
286 | def on_measure_btn_clicked(self):
287 | start, end = self.getTimeRange()
288 | learningFunc.measure(start, end)
289 |
290 |
291 | #----------------------------------------------------------------------
292 | def getTab():
293 | """"""
294 | return LearningTab
295 |
296 | #----------------------------------------------------------------------
297 | def main():
298 | import sys
299 | app = QApplication(sys.argv)
300 | window = LearningTab()
301 | window.show()
302 | app.exec_()
303 |
304 |
305 | if __name__ == "__main__":
306 | main()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/mainWindow.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | import os
6 | try:
7 | from PySide import QtGui, QtCore
8 | from PySide.QtGui import *
9 | from PySide.QtCore import *
10 | except ImportError:
11 | from PySide2 import QtGui, QtCore, QtWidgets
12 | from PySide2.QtGui import *
13 | from PySide2.QtCore import *
14 | from PySide2.QtWidgets import *
15 |
16 | from DLS.widget import optionWindow
17 | from DLS.widget import aboutDialog
18 | from DLS.widget import utils
19 | from DLS.startup import setup
20 | from DLS.core import miscFunc, samplingFunc
21 |
22 | reload(miscFunc)
23 | reload(samplingFunc)
24 | #reload(optionWindow)
25 | #reload(aboutDialog)
26 | #reload(utils)
27 |
28 | cfgfile = os.path.join(utils.SCRIPT_DIRECTORY, "config.ini")
29 |
30 | ########################################################################
31 | class MainWindow(QMainWindow):
32 | """"""
33 | _TITLE = 'Deformation Learning Solver'
34 |
35 | #----------------------------------------------------------------------
36 | def __init__(self, parent=None):
37 | """Constructor"""
38 | super(MainWindow, self).__init__(parent)
39 |
40 | self.setObjectName(setup.getMainWindowName())
41 | #self.parent = parent # this's extremely important! without this line
42 | # "Internal C++ object already deleted" happen
43 | self.initWidgets()
44 |
45 | #----------------------------------------------------------------------
46 | def initWidgets(self):
47 | """"""
48 | self.setWindowTitle(self._TITLE)
49 | self.resize(100, 100)
50 |
51 | # Add actions
52 | openAbout = QAction("&About", self)
53 | openAbout.triggered.connect(self.showAbout)
54 |
55 | openOptions = QAction("&Options", self)
56 | openOptions.triggered.connect(self.showOption)
57 |
58 | resetSettings = QAction("&Reset", self)
59 | resetSettings.triggered.connect(self.resetSettings)
60 |
61 | selectAllBelow = QAction("Select All &Below", self)
62 | selectAllBelow.triggered.connect(self.selectAllBelowCmd)
63 |
64 | selectInfluenceJoints = QAction("Select Influence &Joints", self)
65 | selectInfluenceJoints.triggered.connect(self.selectInfluenceJointsCmd)
66 |
67 | applyRigidSkin = QAction("Apply &Rigid Skin", self)
68 | applyRigidSkin.triggered.connect(self.applyRigidSkinCmd)
69 |
70 | deleteAnimations = QAction("Delete &Animations", self)
71 | deleteAnimations.triggered.connect(self.deleteAnimationsCmd)
72 |
73 | applyDeltaMush = QAction("Apply &Delta Mush", self)
74 | applyDeltaMush.triggered.connect(self.applyDeltaMushCmd)
75 |
76 | # Add menu bar
77 | bar = self.menuBar()
78 | editMenu = bar.addMenu("&Edit")
79 | editMenu.addAction(openOptions)
80 | editMenu.addAction(resetSettings)
81 |
82 | toolMenu = bar.addMenu("&Tool")
83 | toolMenu.addAction(selectAllBelow)
84 | toolMenu.addAction(selectInfluenceJoints)
85 | toolMenu.addAction(applyRigidSkin)
86 | toolMenu.addSeparator()
87 | toolMenu.addAction(deleteAnimations)
88 | toolMenu.addSeparator()
89 | toolMenu.addAction(applyDeltaMush)
90 |
91 | helpMenu = bar.addMenu("&Help")
92 | helpMenu.addAction(openAbout)
93 |
94 | # Add base frame
95 | frame = QFrame(self)
96 | layout = QVBoxLayout(self)
97 | frame.setLayout(layout)
98 |
99 | tabWidget = QTabWidget(self)
100 | tabWidget.setObjectName("allFuncs_tab")
101 | layout.addWidget(tabWidget)
102 |
103 | self.setCentralWidget(frame)
104 |
105 | # Add tabs dynamically
106 | for cls in utils.findAllTabs():
107 | tab = cls(self)
108 | self.addTab(tab, tabWidget)
109 |
110 | tabWidget.setCurrentIndex(0)
111 |
112 | #----------------------------------------------------------------------
113 | def addTab(self, tab, tabWidget):
114 | """
115 | adds tab object to tab UI, creating it's ui and attaching to main window
116 | """
117 | tabWidget.addTab(tab, tab.title())
118 |
119 | #----------------------------------------------------------------------
120 | def showAbout(self):
121 | """"""
122 | aboutDialog.AboutDialog(self).show()
123 |
124 | #----------------------------------------------------------------------
125 | def showOption(self):
126 | """"""
127 | optionWindow.OptionWindow(self).show()
128 |
129 | #----------------------------------------------------------------------
130 | def resetSettings(self):
131 | allFuncs_tab = self.findChild(QTabWidget, "allFuncs_tab")
132 | for i in xrange(allFuncs_tab.count()):
133 | allFuncs_tab.widget(i).resetSettings()
134 |
135 | #----------------------------------------------------------------------
136 | def selectAllBelowCmd(self):
137 | settings = QSettings(cfgfile, QSettings.IniFormat)
138 |
139 | settings.beginGroup("Custom")
140 | skipTips = bool(int(settings.value("skipTips")))
141 | settings.endGroup()
142 |
143 | miscFunc.selectAllBelow(skipTips)
144 |
145 | #----------------------------------------------------------------------
146 | def selectInfluenceJointsCmd(self):
147 | miscFunc.selectInfluenceJoints()
148 |
149 | #----------------------------------------------------------------------
150 | def applyRigidSkinCmd(self):
151 | miscFunc.applyRigidSkin()
152 |
153 | #----------------------------------------------------------------------
154 | def applyDeltaMushCmd(self):
155 | settings = QSettings(cfgfile, QSettings.IniFormat)
156 |
157 | settings.beginGroup("Custom")
158 | useBuildInDeltaMush = bool(int(settings.value("useBuildInDeltaMush")))
159 | settings.endGroup()
160 |
161 | miscFunc.applyDeltaMush(useBuildIn=useBuildInDeltaMush)
162 |
163 | #----------------------------------------------------------------------
164 | def deleteAnimationsCmd(self):
165 | samplingFunc.deleteAnimations()
166 |
167 | #----------------------------------------------------------------------
168 | def closeEvent(self, event):
169 | """"""
170 | allFuncs_tab = self.findChild(QTabWidget, "allFuncs_tab")
171 | for i in xrange(allFuncs_tab.count()):
172 | allFuncs_tab.widget(i).closeEvent(event)
173 |
174 | event.accept()
175 |
176 |
177 | #----------------------------------------------------------------------
178 | def main():
179 | import sys
180 | app = QApplication(sys.argv)
181 | window = MainWindow()
182 | window.show()
183 | app.exec_()
184 |
185 |
186 | if __name__ == "__main__":
187 | main()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/miscTab.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | import os
6 |
7 | try:
8 | from PySide import QtGui, QtCore
9 | from PySide.QtGui import *
10 | from PySide.QtCore import *
11 | except ImportError:
12 | from PySide2 import QtGui, QtCore, QtWidgets
13 | from PySide2.QtGui import *
14 | from PySide2.QtCore import *
15 | from PySide2.QtWidgets import *
16 |
17 | from DLS.widget import baseTab
18 | from DLS.widget import utils
19 | from DLS.core import miscFunc
20 |
21 | #reload(baseTab)
22 | #reload(utils)
23 | reload(miscFunc)
24 |
25 |
26 | TAB = ''
27 | uifile = os.path.join(utils.SCRIPT_DIRECTORY, "ui/miscTab.ui")
28 | ENABLE = False
29 | INDEX = 3
30 |
31 |
32 | ########################################################################
33 | class MiscTab(baseTab.BaseTab):
34 | """"""
35 | _TITLE = 'Misc'
36 |
37 | #----------------------------------------------------------------------
38 | def __init__(self, parent=None):
39 | """Constructor"""
40 | super(MiscTab, self).__init__(parent)
41 | utils.loadUi(uifile, self)
42 | self.initWidgets()
43 |
44 | #----------------------------------------------------------------------
45 | def initWidgets(self):
46 | """"""
47 | pass
48 |
49 | #----------------------------------------------------------------------
50 | @Slot()
51 | def on_applyRigidSkinWeights_btn_clicked(self):
52 | miscFunc.applyRigidSkin()
53 |
54 | #----------------------------------------------------------------------
55 | @Slot()
56 | def on_applyDeltaMushDeformer_btn_clicked(self):
57 | miscFunc.applyDeltaMushDeformer()
58 |
59 | #----------------------------------------------------------------------
60 | @Slot()
61 | def on_transSkinWeights_btn_clicked(self):
62 | msg = b"This's transfer skin weights function"
63 | QMessageBox.information(self, self.trUtf8(b'Informations'),
64 | self.trUtf8(msg))
65 |
66 | #----------------------------------------------------------------------
67 | @Slot()
68 | def on_transBlendshapAttrs_btn_clicked(self):
69 | msg = b"This's transfer blendshape function"
70 | QMessageBox.information(self, self.trUtf8(b'Informations'),
71 | self.trUtf8(msg))
72 |
73 |
74 | #----------------------------------------------------------------------
75 | def getTab():
76 | """"""
77 | return MiscTab
78 |
79 | #----------------------------------------------------------------------
80 | def main():
81 | import sys
82 | app = QApplication(sys.argv)
83 | window = MiscTab()
84 | window.show()
85 | app.exec_()
86 |
87 |
88 | if __name__ == "__main__":
89 | main()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/optionWindow.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | import os
6 |
7 | try:
8 | from PySide import QtGui, QtCore
9 | from PySide.QtGui import *
10 | from PySide.QtCore import *
11 | except ImportError:
12 | from PySide2 import QtGui, QtCore, QtWidgets
13 | from PySide2.QtGui import *
14 | from PySide2.QtCore import *
15 | from PySide2.QtWidgets import *
16 | from DLS.widget import utils
17 | from DLS.widget import baseOptionWindow
18 |
19 | from DLS.startup import setup
20 |
21 | #reload(baseOptionWindow)
22 |
23 |
24 | uifile = os.path.join(utils.SCRIPT_DIRECTORY, "ui/optionWindow.ui")
25 | cfgfile = os.path.join(utils.SCRIPT_DIRECTORY, "config.ini")
26 |
27 |
28 | ########################################################################
29 | class OptionWindow(baseOptionWindow.BaseOptionWindow):
30 | """"""
31 | _TITLE = 'Options'
32 |
33 | #----------------------------------------------------------------------
34 | def __init__(self, parent=None):
35 | """Constructor"""
36 | super(OptionWindow, self).__init__(parent)
37 | utils.loadUi(uifile, self)
38 | self.initWidgets()
39 |
40 | #----------------------------------------------------------------------
41 | def initWidgets(self):
42 | """"""
43 | self.readSettings()
44 |
45 | self.setWindowTitle(self._TITLE)
46 | cp = QDesktopWidget().screenGeometry().center()
47 | self.move(cp)
48 |
49 | # Add actions
50 | actionReset = self.findChild(QAction, "actionReset")
51 | if actionReset != None:
52 | actionReset.triggered.connect(self.resetSettings)
53 |
54 | # Connect signal and slot
55 | pruneBelow_spn = self.findChild(QDoubleSpinBox, "pruneBelow_spn")
56 | if pruneBelow_spn != None:
57 | pruneBelow_spn.valueChanged.connect(self.changePruneBelow_slider)
58 |
59 | pruneBelow_slider = self.findChild(QSlider, "pruneBelow_slider")
60 | if pruneBelow_slider != None:
61 | pruneBelow_slider.valueChanged.connect(self.changePruneBelow_spn)
62 |
63 | # Set use build-in delta mush
64 | if setup.mayaVersion() >= 2016:
65 | self.setUseBuildInDeltaMushEnable(True)
66 |
67 | #----------------------------------------------------------------------
68 | def getPruneBelow(self):
69 | """"""
70 | pruneBelow_spn = self.findChild(QDoubleSpinBox, "pruneBelow_spn")
71 | if pruneBelow_spn != None:
72 | return pruneBelow_spn.value()
73 | return 0.0
74 |
75 | #----------------------------------------------------------------------
76 | def setPruneBelow(self, val):
77 | """"""
78 | pruneBelow_spn = self.findChild(QDoubleSpinBox, "pruneBelow_spn")
79 | if pruneBelow_spn != None:
80 | pruneBelow_spn.setValue(val)
81 |
82 | #----------------------------------------------------------------------
83 | def isKeepOriginal(self):
84 | """"""
85 | keepOriginal_chk = self.findChild(QCheckBox, "keepOriginal_chk")
86 | if keepOriginal_chk != None:
87 | return keepOriginal_chk.isChecked()
88 | return True
89 |
90 | #----------------------------------------------------------------------
91 | def setKeepOriginal(self, val):
92 | """"""
93 | keepOriginal_chk = self.findChild(QCheckBox, "keepOriginal_chk")
94 | if keepOriginal_chk != None:
95 | keepOriginal_chk.setChecked(val)
96 |
97 | #----------------------------------------------------------------------
98 | def isDeleteDeltaMush(self):
99 | """"""
100 | deleteDeltaMush_chk = self.findChild(QCheckBox, "deleteDeltaMush_chk")
101 | if deleteDeltaMush_chk != None:
102 | return deleteDeltaMush_chk.isChecked()
103 | return False
104 |
105 | #----------------------------------------------------------------------
106 | def setDeleteDeltaMush(self, val):
107 | """"""
108 | deleteDeltaMush_chk = self.findChild(QCheckBox, "deleteDeltaMush_chk")
109 | if deleteDeltaMush_chk != None:
110 | deleteDeltaMush_chk.setChecked(val)
111 |
112 | #----------------------------------------------------------------------
113 | def setUseBuildInDeltaMush(self, val):
114 | """"""
115 | useBuildInDeltaMush_chk = self.findChild(QCheckBox, "useBuildInDeltaMush_chk")
116 | if useBuildInDeltaMush_chk != None:
117 | useBuildInDeltaMush_chk.setChecked(val)
118 |
119 | #----------------------------------------------------------------------
120 | def setUseBuildInDeltaMushEnable(self, val):
121 | """"""
122 | useBuildInDeltaMush_chk = self.findChild(QCheckBox, "useBuildInDeltaMush_chk")
123 | if useBuildInDeltaMush_chk != None:
124 | useBuildInDeltaMush_chk.setEnabled(val)
125 |
126 | #----------------------------------------------------------------------
127 | def useBuildInDeltaMush(self):
128 | """"""
129 | useBuildInDeltaMush_chk = self.findChild(QCheckBox, "useBuildInDeltaMush_chk")
130 | if useBuildInDeltaMush_chk != None:
131 | return useBuildInDeltaMush_chk.isEnabled() and useBuildInDeltaMush_chk.isChecked()
132 |
133 | #----------------------------------------------------------------------
134 | def setSkipTips(self, val):
135 | """"""
136 | skipTips_chk = self.findChild(QCheckBox, "skipTips_chk")
137 | if skipTips_chk != None:
138 | skipTips_chk.setChecked(val)
139 |
140 | #----------------------------------------------------------------------
141 | def skipTips(self):
142 | """"""
143 | skipTips_chk = self.findChild(QCheckBox, "skipTips_chk")
144 | if skipTips_chk != None:
145 | return skipTips_chk.isChecked()
146 |
147 | #----------------------------------------------------------------------
148 | def resetSettings(self):
149 | settings = QSettings(cfgfile, QSettings.IniFormat)
150 |
151 | settings.beginGroup("Default")
152 | self.setPruneBelow(float(settings.value("pruneBeblow")))
153 | self.setKeepOriginal(bool(int(settings.value("isKeepOriginal"))))
154 | self.setDeleteDeltaMush(bool(int(settings.value("isDeleteDeltaMush"))))
155 | self.setUseBuildInDeltaMush(bool(int(settings.value("useBuildInDeltaMush"))))
156 | self.setSkipTips(bool(int(settings.value("skipTips"))))
157 | settings.endGroup()
158 |
159 | #----------------------------------------------------------------------
160 | def readSettings(self):
161 | settings = QSettings(cfgfile, QSettings.IniFormat)
162 |
163 | settings.beginGroup("Custom")
164 | self.setPruneBelow(float(settings.value("pruneBeblow")))
165 | self.setKeepOriginal(bool(int(settings.value("isKeepOriginal"))))
166 | self.setDeleteDeltaMush(bool(int(settings.value("isDeleteDeltaMush"))))
167 | self.setUseBuildInDeltaMush(bool(int(settings.value("useBuildInDeltaMush"))))
168 | self.setSkipTips(bool(int(settings.value("skipTips"))))
169 | settings.endGroup()
170 |
171 | #----------------------------------------------------------------------
172 | def writeSettings(self):
173 | settings = QSettings(cfgfile, QSettings.IniFormat)
174 |
175 | settings.beginGroup("Custom")
176 | settings.setValue("pruneBeblow", float(self.getPruneBelow()))
177 | settings.setValue("isKeepOriginal", int(self.isKeepOriginal()))
178 | settings.setValue("isDeleteDeltaMush", int(self.isDeleteDeltaMush()))
179 | settings.setValue("useBuildInDeltaMush", int(self.useBuildInDeltaMush()))
180 | settings.setValue("skipTips", int(self.skipTips()))
181 | settings.endGroup()
182 |
183 | #----------------------------------------------------------------------
184 | @Slot()
185 | def changePruneBelow_spn(self):
186 | """"""
187 | val = 0
188 | pruneBelow_slider = self.findChild(QSlider, "pruneBelow_slider")
189 | if pruneBelow_slider != None:
190 | val = float(pruneBelow_slider.value()) / 100000
191 |
192 | pruneBelow_spn = self.findChild(QDoubleSpinBox, "pruneBelow_spn")
193 | if pruneBelow_spn != None:
194 | pruneBelow_spn.setValue(val)
195 |
196 | #----------------------------------------------------------------------
197 | @Slot()
198 | def changePruneBelow_slider(self):
199 | """"""
200 | val = 0
201 | pruneBelow_spn = self.findChild(QDoubleSpinBox, "pruneBelow_spn")
202 | if pruneBelow_spn != None:
203 | val = int(pruneBelow_spn.value() * 100000)
204 |
205 | pruneBelow_slider = self.findChild(QSlider, "pruneBelow_slider")
206 | if pruneBelow_slider != None:
207 | pruneBelow_slider.setValue(val)
208 |
209 |
210 | #----------------------------------------------------------------------
211 | def main():
212 | import sys
213 | app = QApplication(sys.argv)
214 | window = OptionWindow()
215 | window.show()
216 | app.exec_()
217 |
218 |
219 | if __name__ == "__main__":
220 | main()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/samplingTab.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 | import os
6 |
7 | try:
8 | from PySide import QtGui, QtCore
9 | from PySide.QtGui import *
10 | from PySide.QtCore import *
11 | except ImportError:
12 | from PySide2 import QtGui, QtCore, QtWidgets
13 | from PySide2.QtGui import *
14 | from PySide2.QtCore import *
15 | from PySide2.QtWidgets import *
16 |
17 | import maya.OpenMaya as om
18 |
19 | from DLS.widget import utils
20 |
21 | from DLS.core import samplingFunc
22 | from DLS.widget import baseTab
23 | from DLS.widget import axisOptionWindow
24 | from DLS.widget import customAttributeEditor
25 |
26 |
27 | #reload(baseTab)
28 | #reload(utils)
29 | reload(samplingFunc)
30 | #reload(axisOptionWindow)
31 | reload(customAttributeEditor)
32 |
33 | TAB = ''
34 | uifile = os.path.join(utils.SCRIPT_DIRECTORY, "ui/samplingTab.ui")
35 | cfgfile = os.path.join(utils.SCRIPT_DIRECTORY, "config.ini")
36 | ENABLE = True
37 | INDEX = 2
38 |
39 |
40 | ########################################################################
41 | class SamplingTab(baseTab.BaseTab):
42 | """
43 | self.attrData = {node1: [[attr1, min, max], [attr2, min, max], ...],
44 | node2: [[attr1, min, max], [attr2, min, max], ...],
45 | ...}
46 | """
47 | _TITLE = 'Sampling'
48 |
49 | #----------------------------------------------------------------------
50 | def __init__(self, parent=None):
51 | """Constructor"""
52 | super(SamplingTab, self).__init__(parent)
53 | utils.loadUi(uifile, self)
54 | self.attrData = {}
55 | self.initWidgets()
56 |
57 | #----------------------------------------------------------------------
58 | def initWidgets(self):
59 | """"""
60 | self.readSettings()
61 |
62 | doubleVal = QDoubleValidator(decimals=3, parent=self)
63 |
64 | # Set transformation widgets
65 | rotateMin_edit = self.findChild(QLineEdit, "rotateMin_edit")
66 | if rotateMin_edit != None:
67 | rotateMin_edit.setValidator(doubleVal)
68 |
69 | rotateMax_edit = self.findChild(QLineEdit, "rotateMax_edit")
70 | if rotateMax_edit != None:
71 | rotateMax_edit.setValidator(doubleVal)
72 |
73 | translateMin_edit = self.findChild(QLineEdit, "translateMin_edit")
74 | if translateMin_edit != None:
75 | translateMin_edit.setValidator(doubleVal)
76 |
77 | translateMax_edit = self.findChild(QLineEdit, "translateMax_edit")
78 | if translateMax_edit != None:
79 | translateMax_edit.setValidator(doubleVal)
80 |
81 | scaleMin_edit = self.findChild(QLineEdit, "scaleMin_edit")
82 | if scaleMin_edit != None:
83 | scaleMin_edit.setValidator(doubleVal)
84 |
85 | scaleMax_edit = self.findChild(QLineEdit, "scaleMax_edit")
86 | if scaleMax_edit != None:
87 | scaleMax_edit.setValidator(doubleVal)
88 |
89 | # Set blendshape widgets
90 | rx = QRegExp("^[a-zA-Z][a-zA-Z0-9_]+")
91 | val = QRegExpValidator(rx, self)
92 | blendshape_edit = self.findChild(QLineEdit, "blendshape_edit")
93 | if blendshape_edit != None:
94 | blendshape_edit.setValidator(val)
95 |
96 | #----------------------------------------------------------------------
97 | def getTranslateMin(self):
98 | """"""
99 | translateMin_edit = self.findChild(QLineEdit, "translateMin_edit")
100 | if translateMin_edit != None:
101 | return float(translateMin_edit.text())
102 | return -1.0
103 |
104 | #----------------------------------------------------------------------
105 | def setTranslateMin(self, val):
106 | """"""
107 | translateMin_edit = self.findChild(QLineEdit, "translateMin_edit")
108 | if translateMin_edit != None:
109 | translateMin_edit.setText(str(val))
110 |
111 | #----------------------------------------------------------------------
112 | def getTranslateMax(self):
113 | """"""
114 | translateMax_edit = self.findChild(QLineEdit, "translateMax_edit")
115 | if translateMax_edit != None:
116 | return float(translateMax_edit.text())
117 | return 1.0
118 |
119 | #----------------------------------------------------------------------
120 | def setTranslateMax(self, val):
121 | """"""
122 | translateMax_edit = self.findChild(QLineEdit, "translateMax_edit")
123 | if translateMax_edit != None:
124 | translateMax_edit.setText(str(val))
125 |
126 | #----------------------------------------------------------------------
127 | def getRotateMin(self):
128 | """"""
129 | rotateMin_edit = self.findChild(QLineEdit, "rotateMin_edit")
130 | if rotateMin_edit != None:
131 | return float(rotateMin_edit.text())
132 | return -90.0
133 |
134 | #----------------------------------------------------------------------
135 | def setRotateMin(self, val):
136 | """"""
137 | rotateMin_edit = self.findChild(QLineEdit, "rotateMin_edit")
138 | if rotateMin_edit != None:
139 | rotateMin_edit.setText(str(val))
140 |
141 | #----------------------------------------------------------------------
142 | def getRotateMax(self):
143 | """"""
144 | rotateMax_edit = self.findChild(QLineEdit, "rotateMax_edit")
145 | if rotateMax_edit != None:
146 | return float(rotateMax_edit.text())
147 | return 90.0
148 |
149 | #----------------------------------------------------------------------
150 | def setRotateMax(self, val):
151 | """"""
152 | rotateMax_edit = self.findChild(QLineEdit, "rotateMax_edit")
153 | if rotateMax_edit != None:
154 | rotateMax_edit.setText(str(val))
155 |
156 | #----------------------------------------------------------------------
157 | def getScaleMin(self):
158 | """"""
159 | scaleMin_edit = self.findChild(QLineEdit, "scaleMin_edit")
160 | if scaleMin_edit != None:
161 | return float(scaleMin_edit.text())
162 | return -1.0
163 |
164 | #----------------------------------------------------------------------
165 | def setScaleMin(self, val):
166 | """"""
167 | scaleMin_edit = self.findChild(QLineEdit, "scaleMin_edit")
168 | if scaleMin_edit != None:
169 | scaleMin_edit.setText(str(val))
170 |
171 | #----------------------------------------------------------------------
172 | def getScaleMax(self):
173 | """"""
174 | scaleMax_edit = self.findChild(QLineEdit, "scaleMax_edit")
175 | if scaleMax_edit != None:
176 | return float(scaleMax_edit.text())
177 | return 1.0
178 |
179 | #----------------------------------------------------------------------
180 | def setScaleMax(self, val):
181 | """"""
182 | scaleMax_edit = self.findChild(QLineEdit, "scaleMax_edit")
183 | if scaleMax_edit != None:
184 | scaleMax_edit.setText(str(val))
185 |
186 | #----------------------------------------------------------------------
187 | def getBlendshapeName(self):
188 | """"""
189 | blendshape_edit = self.findChild(QLineEdit, "blendshape_edit")
190 | if blendshape_edit != None:
191 | return str(blendshape_edit.text())
192 |
193 | #----------------------------------------------------------------------
194 | def setBlendshapeName(self, val):
195 | """"""
196 | blendshape_edit = self.findChild(QLineEdit, "blendshape_edit")
197 | if blendshape_edit != None:
198 | blendshape_edit.setText(str(val))
199 |
200 | #----------------------------------------------------------------------
201 | def isTranslate(self):
202 | """"""
203 | translate_chk = self.findChild(QCheckBox, "translate_chk")
204 | if translate_chk != None:
205 | return translate_chk.isChecked()
206 | return False
207 |
208 | #----------------------------------------------------------------------
209 | def setTranslate(self, val):
210 | """"""
211 | translate_chk = self.findChild(QCheckBox, "translate_chk")
212 | if translate_chk != None:
213 | translate_chk.setChecked(val)
214 | translate_chk.click()
215 | translate_chk.click()
216 |
217 | #----------------------------------------------------------------------
218 | def isRotate(self):
219 | """"""
220 | rotate_chk = self.findChild(QCheckBox, "rotate_chk")
221 | if rotate_chk != None:
222 | return rotate_chk.isChecked()
223 | return True
224 |
225 | #----------------------------------------------------------------------
226 | def setRotate(self, val):
227 | """"""
228 | rotate_chk = self.findChild(QCheckBox, "rotate_chk")
229 | if rotate_chk != None:
230 | rotate_chk.setChecked(val)
231 | rotate_chk.click()
232 | rotate_chk.click()
233 |
234 | #----------------------------------------------------------------------
235 | def isScale(self):
236 | """"""
237 | scale_chk = self.findChild(QCheckBox, "scale_chk")
238 | if scale_chk != None:
239 | return scale_chk.isChecked()
240 | return False
241 |
242 | #----------------------------------------------------------------------
243 | def setScale(self, val):
244 | """"""
245 | scale_chk = self.findChild(QCheckBox, "scale_chk")
246 | if scale_chk != None:
247 | scale_chk.setChecked(val)
248 | scale_chk.click()
249 | scale_chk.click()
250 |
251 | #----------------------------------------------------------------------
252 | def isTransform(self):
253 | """"""
254 | transformOptions_frame = self.findChild(QFrame, "transformOptions_frame")
255 | if transformOptions_frame != None:
256 | return transformOptions_frame.isEnabled()
257 | return False
258 |
259 | #----------------------------------------------------------------------
260 | def isBlendshape(self):
261 | """"""
262 | blendshape_chk = self.findChild(QCheckBox, "blendshape_chk")
263 | if blendshape_chk != None:
264 | return blendshape_chk.isChecked()
265 | return False
266 |
267 | #----------------------------------------------------------------------
268 | def setBlendshape(self, val):
269 | """"""
270 | blendshape_chk = self.findChild(QCheckBox, "blendshape_chk")
271 | if blendshape_chk != None:
272 | blendshape_chk.setChecked(val)
273 | blendshape_chk.click()
274 | blendshape_chk.click()
275 |
276 | #----------------------------------------------------------------------
277 | def isCustomAttrs(self):
278 | """"""
279 | customAttrs_chk = self.findChild(QCheckBox, "customAttrs_chk")
280 | if customAttrs_chk != None:
281 | return customAttrs_chk.isChecked()
282 | return False
283 |
284 | #----------------------------------------------------------------------
285 | def setCustomAttrs(self, val):
286 | """"""
287 | customAttrs_chk = self.findChild(QCheckBox, "customAttrs_chk")
288 | if customAttrs_chk != None:
289 | customAttrs_chk.setChecked(val)
290 | customAttrs_chk.click()
291 | customAttrs_chk.click()
292 |
293 | #----------------------------------------------------------------------
294 | def resetSettings(self):
295 | """"""
296 | settings = QSettings(cfgfile, QSettings.IniFormat)
297 |
298 | settings.beginGroup("Default")
299 | self.setBlendshape(bool(int(settings.value("isBlendshape"))))
300 | self.setBlendshapeName(settings.value("blendshapeName"))
301 |
302 | self.setTranslate(bool(int(settings.value("isTranslate"))))
303 | self.setTranslateMin(float(settings.value("translateMin")))
304 | self.setTranslateMax(float(settings.value("translateMax")))
305 |
306 | self.setRotate(bool(int(settings.value("isRotate"))))
307 | self.setRotateMin(float(settings.value("rotateMin")))
308 | self.setRotateMax(float(settings.value("rotateMax")))
309 |
310 | self.setScale(bool(int(settings.value("isScale"))))
311 | self.setScaleMin(float(settings.value("scaleMin")))
312 | self.setScaleMax(float(settings.value("scaleMax")))
313 |
314 | self.setCustomAttrs(bool(int(settings.value("isCustomAttrs"))))
315 |
316 | settings.endGroup()
317 |
318 | #----------------------------------------------------------------------
319 | def readSettings(self):
320 | """"""
321 | settings = QSettings(cfgfile, QSettings.IniFormat)
322 |
323 | settings.beginGroup("Custom")
324 | self.setBlendshape(bool(int(settings.value("isBlendshape"))))
325 |
326 | self.setTranslate(bool(int(settings.value("isTranslate"))))
327 | self.setTranslateMin(float(settings.value("translateMin")))
328 | self.setTranslateMax(float(settings.value("translateMax")))
329 |
330 | self.setRotate(bool(int(settings.value("isRotate"))))
331 | self.setRotateMin(float(settings.value("rotateMin")))
332 | self.setRotateMax(float(settings.value("rotateMax")))
333 |
334 | self.setScale(bool(int(settings.value("isScale"))))
335 | self.setScaleMin(float(settings.value("scaleMin")))
336 | self.setScaleMax(float(settings.value("scaleMax")))
337 |
338 | self.setCustomAttrs(bool(int(settings.value("isCustomAttrs"))))
339 |
340 | settings.endGroup()
341 |
342 | #----------------------------------------------------------------------
343 | def writeSettings(self):
344 | """"""
345 | settings = QSettings(cfgfile, QSettings.IniFormat)
346 |
347 | settings.beginGroup("Custom")
348 | settings.setValue("isTranslate", int(self.isTranslate()))
349 | settings.setValue("translateMin", self.getTranslateMin())
350 | settings.setValue("translateMax", self.getTranslateMax())
351 |
352 | settings.setValue("isRotate", int(self.isRotate()))
353 | settings.setValue("rotateMin", self.getRotateMin())
354 | settings.setValue("rotateMax", self.getRotateMax())
355 |
356 | settings.setValue("isScale", int(self.isScale()))
357 | settings.setValue("scaleMin", self.getScaleMin())
358 | settings.setValue("scaleMax", self.getScaleMax())
359 |
360 | settings.setValue("isBlendshape", int(self.isBlendshape()))
361 |
362 | settings.setValue("isCustomAttrs", int(self.isCustomAttrs()))
363 |
364 | settings.endGroup()
365 |
366 | #----------------------------------------------------------------------
367 | @Slot(bool)
368 | def on_translate_chk_clicked(self, isChecked):
369 | translateMin_edit = self.findChild(QLineEdit, "translateMin_edit")
370 | if translateMin_edit != None:
371 | translateMin_edit.setEnabled(isChecked)
372 |
373 | translateMax_edit = self.findChild(QLineEdit, "translateMax_edit")
374 | if translateMax_edit != None:
375 | translateMax_edit.setEnabled(isChecked)
376 |
377 | #----------------------------------------------------------------------
378 | @Slot()
379 | def on_translateOpt_btn_clicked(self):
380 | axisOptionWindow.TranslateAxisOptionWindow(self).show()
381 |
382 | #----------------------------------------------------------------------
383 | @Slot(bool)
384 | def on_rotate_chk_clicked(self, isChecked):
385 | rotateMin_edit = self.findChild(QLineEdit, "rotateMin_edit")
386 | if rotateMin_edit != None:
387 | rotateMin_edit.setEnabled(isChecked)
388 |
389 | rotateMax_edit = self.findChild(QLineEdit, "rotateMax_edit")
390 | if rotateMax_edit != None:
391 | rotateMax_edit.setEnabled(isChecked)
392 |
393 | #----------------------------------------------------------------------
394 | @Slot()
395 | def on_rotateOpt_btn_clicked(self):
396 | axisOptionWindow.RotateAxisOptionWindow(self).show()
397 |
398 | #----------------------------------------------------------------------
399 | @Slot(bool)
400 | def on_scale_chk_clicked(self, isChecked):
401 | scaleMin_edit = self.findChild(QLineEdit, "scaleMin_edit")
402 | if scaleMin_edit != None:
403 | scaleMin_edit.setEnabled(isChecked)
404 |
405 | scaleMax_edit = self.findChild(QLineEdit, "scaleMax_edit")
406 | if scaleMax_edit != None:
407 | scaleMax_edit.setEnabled(isChecked)
408 |
409 | #----------------------------------------------------------------------
410 | @Slot()
411 | def on_scaleOpt_btn_clicked(self):
412 | axisOptionWindow.ScaleAxisOptionWindow(self).show()
413 |
414 | #----------------------------------------------------------------------
415 | @Slot(bool)
416 | def on_blendshape_chk_clicked(self, isChecked):
417 | transformOptions_frame = self.findChild(QFrame, "transformOptions_frame")
418 | if transformOptions_frame != None:
419 | transformOptions_frame.setEnabled(not isChecked)
420 |
421 | blendshape_edit = self.findChild(QLineEdit, "blendshape_edit")
422 | if blendshape_edit != None:
423 | blendshape_edit.setEnabled(isChecked)
424 |
425 | loadBlendshape_btn = self.findChild(QPushButton, "loadBlendshape_btn")
426 | if loadBlendshape_btn != None:
427 | loadBlendshape_btn.setEnabled(isChecked)
428 |
429 | customAttrsOptions_frame = self.findChild(QFrame, "customAttrsOptions_frame")
430 | if customAttrsOptions_frame != None:
431 | customAttrsOptions_frame.setEnabled(not isChecked)
432 |
433 | #----------------------------------------------------------------------
434 | @Slot()
435 | def on_loadBlendshape_btn_clicked(self):
436 | blendshape = samplingFunc.getBlendshapeFromSelection()
437 |
438 | blendshape_edit = self.findChild(QLineEdit, "blendshape_edit")
439 | if blendshape_edit != None:
440 | blendshape_edit.setText(blendshape)
441 |
442 | #----------------------------------------------------------------------
443 | @Slot(bool)
444 | def on_customAttrs_chk_clicked(self, isChecked):
445 | transformOptions_frame = self.findChild(QFrame, "transformOptions_frame")
446 | if transformOptions_frame != None:
447 | transformOptions_frame.setEnabled(not isChecked)
448 |
449 | blendshapeOptions_frame = self.findChild(QFrame, "blendshapeOptions_frame")
450 | if blendshapeOptions_frame != None:
451 | blendshapeOptions_frame.setEnabled(not isChecked)
452 |
453 | openCustomAttrsEditor_btn = self.findChild(QPushButton, "openCustomAttrsEditor_btn")
454 | if openCustomAttrsEditor_btn != None:
455 | openCustomAttrsEditor_btn.setEnabled(isChecked)
456 |
457 | #----------------------------------------------------------------------
458 | @Slot()
459 | def on_openCustomAttrsEditor_btn_clicked(self):
460 | editor = customAttributeEditor.CustomAttributeEditor(self.attrData, self)
461 | editor.showUI()
462 |
463 | #----------------------------------------------------------------------
464 | @Slot()
465 | def on_run_btn_clicked(self):
466 | # Sample transform attributes
467 | if self.isTransform():
468 | translateMin = self.getTranslateMin()
469 | translateMax = self.getTranslateMax()
470 | rotateMin = self.getRotateMin()
471 | rotateMax = self.getRotateMax()
472 | scaleMin = self.getScaleMin()
473 | scaleMax = self.getScaleMax()
474 | isTranslate = self.isTranslate()
475 | isRotate = self.isRotate()
476 | isScale = self.isScale()
477 |
478 | translateAttrs = []
479 | rotateAttrs = []
480 | scaleAttrs = []
481 |
482 | # Parse axis settings
483 | settings = QSettings(cfgfile, QSettings.IniFormat)
484 | settings.beginGroup("Custom")
485 | if bool(int(settings.value("translateX"))): translateAttrs.append("tx")
486 | if bool(int(settings.value("translateY"))): translateAttrs.append("ty")
487 | if bool(int(settings.value("translateZ"))): translateAttrs.append("tz")
488 |
489 | if bool(int(settings.value("rotateX"))): rotateAttrs.append("rx")
490 | if bool(int(settings.value("rotateY"))): rotateAttrs.append("ry")
491 | if bool(int(settings.value("rotateZ"))): rotateAttrs.append("rz")
492 |
493 | if bool(int(settings.value("scaleX"))): scaleAttrs.append("sx")
494 | if bool(int(settings.value("scaleY"))): scaleAttrs.append("sy")
495 | if bool(int(settings.value("scaleZ"))): scaleAttrs.append("sz")
496 | settings.endGroup()
497 |
498 |
499 | samplingFunc.transformSampling(translateMin,
500 | translateMax,
501 | rotateMin,
502 | rotateMax,
503 | scaleMin,
504 | scaleMax,
505 | isTranslate,
506 | isRotate,
507 | isScale,
508 | translateAttrs,
509 | rotateAttrs,
510 | scaleAttrs)
511 |
512 | # Sample blendshape attributes
513 | if self.isBlendshape():
514 | blendshape = self.getBlendshapeName()
515 | if blendshape:
516 | samplingFunc.blendShapeSampling(blendshape)
517 | else:
518 | om.MGlobal.displayError("Please load blendshape first.")
519 | return
520 |
521 | # Sample custom attributes
522 | if self.isCustomAttrs():
523 | if self.attrData:
524 | samplingFunc.customAttrsSampling(self.attrData)
525 | else:
526 | om.MGlobal.displayError("Please append attributes for sampling first.")
527 | return
528 |
529 |
530 | #----------------------------------------------------------------------
531 | def getTab():
532 | """"""
533 | return SamplingTab
534 |
535 | #----------------------------------------------------------------------
536 | def main():
537 | import sys
538 | app = QApplication(sys.argv)
539 | window = SamplingTab()
540 | window.show()
541 | app.exec_()
542 |
543 |
544 | if __name__ == "__main__":
545 | main()
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/ui/aboutDialog.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | about_dialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 190
10 | 131
11 |
12 |
13 |
14 | About
15 |
16 |
17 | -
18 |
19 |
20 |
21 | 75
22 | true
23 |
24 |
25 |
26 | Deformation Learning Solver
27 |
28 |
29 | Qt::AlignCenter
30 |
31 |
32 |
33 | -
34 |
35 |
36 | QFrame::Box
37 |
38 |
39 | QFrame::Sunken
40 |
41 |
42 |
-
43 |
44 |
-
45 |
46 |
-
47 |
48 |
49 | Author:
50 |
51 |
52 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
53 |
54 |
55 |
56 | -
57 |
58 |
59 | Contact:
60 |
61 |
62 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
63 |
64 |
65 |
66 | -
67 |
68 |
69 | Website:
70 |
71 |
72 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
73 |
74 |
75 |
76 | -
77 |
78 |
79 | Version:
80 |
81 |
82 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
83 |
84 |
85 |
86 |
87 |
88 | -
89 |
90 |
-
91 |
92 |
93 | Webber Huang
94 |
95 |
96 |
97 | -
98 |
99 |
100 | xracz.fx@gmail.com
101 |
102 |
103 |
104 | -
105 |
106 |
107 | http://riggingtd.com
108 |
109 |
110 |
111 | -
112 |
113 |
114 | 1.5.5
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/ui/axisWindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 176
10 | 89
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
-
21 |
22 |
23 | X
24 |
25 |
26 | true
27 |
28 |
29 |
30 | -
31 |
32 |
33 | Y
34 |
35 |
36 | true
37 |
38 |
39 |
40 | -
41 |
42 |
43 | Z
44 |
45 |
46 | true
47 |
48 |
49 |
50 |
51 |
52 | -
53 |
54 |
-
55 |
56 |
57 | Save
58 |
59 |
60 |
61 | -
62 |
63 |
64 | Cancel
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
89 |
90 |
91 | Reset
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/ui/customAttributeEditor.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 270
10 | 311
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
-
21 |
22 |
23 | Add
24 |
25 |
26 |
27 | -
28 |
29 |
30 | Clear
31 |
32 |
33 |
34 |
35 |
36 | -
37 |
38 |
39 | -
40 |
41 |
-
42 |
43 |
44 | Save
45 |
46 |
47 |
48 | -
49 |
50 |
51 | Cancel
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Reset
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/ui/learningTab.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 272
10 | 250
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 | QFrame::NoFrame
21 |
22 |
23 | QFrame::Plain
24 |
25 |
26 |
27 | 2
28 |
29 |
30 | 2
31 |
32 |
-
33 |
34 |
-
35 |
36 |
37 | Num of Bones:
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 | 48
46 | 16777215
47 |
48 |
49 |
50 | false
51 |
52 |
53 | true
54 |
55 |
56 | 1
57 |
58 |
59 | 999999999
60 |
61 |
62 | 1
63 |
64 |
65 |
66 | -
67 |
68 |
69 | Max Infs:
70 |
71 |
72 |
73 | -
74 |
75 |
76 |
77 | 48
78 | 16777215
79 |
80 |
81 |
82 | 1
83 |
84 |
85 | 999999999
86 |
87 |
88 | 4
89 |
90 |
91 |
92 | -
93 |
94 |
95 | Epsilon:
96 |
97 |
98 |
99 | -
100 |
101 |
102 |
103 | 48
104 | 16777215
105 |
106 |
107 |
108 |
109 |
110 |
111 | 0.100000000000000
112 |
113 |
114 | 1.000000000000000
115 |
116 |
117 |
118 | -
119 |
120 |
121 | Max Iters:
122 |
123 |
124 |
125 | -
126 |
127 |
128 |
129 | 48
130 | 16777215
131 |
132 |
133 |
134 | 999999999
135 |
136 |
137 | 10
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | -
147 |
148 |
149 | Qt::Horizontal
150 |
151 |
152 |
153 | -
154 |
155 |
156 | true
157 |
158 |
159 | QFrame::NoFrame
160 |
161 |
162 | QFrame::Plain
163 |
164 |
165 |
166 | 2
167 |
168 |
169 | 2
170 |
171 |
-
172 |
173 |
-
174 |
175 |
176 | Target Mesh:
177 |
178 |
179 |
180 | -
181 |
182 |
183 | true
184 |
185 |
186 |
187 | -
188 |
189 |
190 | true
191 |
192 |
193 |
194 | 32
195 | 16777215
196 |
197 |
198 |
199 | <--
200 |
201 |
202 |
203 |
204 |
205 | -
206 |
207 |
208 | Alternative Update
209 |
210 |
211 |
212 |
213 |
214 |
215 | -
216 |
217 |
218 | Qt::Horizontal
219 |
220 |
221 |
222 | -
223 |
224 |
225 | true
226 |
227 |
228 | false
229 |
230 |
231 | QFrame::NoFrame
232 |
233 |
234 | QFrame::Plain
235 |
236 |
237 | 1
238 |
239 |
240 | 0
241 |
242 |
243 |
244 | 2
245 |
246 |
247 | 2
248 |
249 |
-
250 |
251 |
-
252 |
253 |
254 | Time Range:
255 |
256 |
257 |
258 | -
259 |
260 |
261 | Start/End:
262 |
263 |
264 |
265 |
266 |
267 | -
268 |
269 |
-
270 |
271 |
-
272 |
273 |
274 | Time Slider
275 |
276 |
277 |
278 | -
279 |
280 |
281 | Start/End
282 |
283 |
284 |
285 |
286 |
287 | -
288 |
289 |
-
290 |
291 |
292 | 0.0
293 |
294 |
295 |
296 | -
297 |
298 |
299 | 0.0
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 | -
311 |
312 |
-
313 |
314 |
315 | Solve
316 |
317 |
318 |
319 | -
320 |
321 |
322 | Measure
323 |
324 |
325 |
326 |
327 |
328 |
329 | timeRangeOptions_frame
330 | break2_line
331 | targetMesh_frame
332 | break1_line
333 | frame
334 |
335 |
336 |
337 |
338 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/ui/miscTab.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 175
10 | 165
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 | Apply Rigid Skin Weights
21 |
22 |
23 |
24 | -
25 |
26 |
27 | Apply Delta Mush Deformer
28 |
29 |
30 |
31 | -
32 |
33 |
34 | Transfer Skin Weights
35 |
36 |
37 |
38 | -
39 |
40 |
41 | Transfer Blendshape Attributes
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/ui/optionWindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | option_win
4 |
5 |
6 |
7 | 0
8 | 0
9 | 258
10 | 247
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
21 | QFrame::NoFrame
22 |
23 |
24 | QFrame::Raised
25 |
26 |
27 |
-
28 |
29 |
30 |
31 | 0
32 | 0
33 |
34 |
35 |
36 | Prune Small Weights
37 |
38 |
39 |
40 | QLayout::SetDefaultConstraint
41 |
42 |
-
43 |
44 |
45 | Qt::Horizontal
46 |
47 |
48 | QSizePolicy::MinimumExpanding
49 |
50 |
51 |
52 | 8
53 | 20
54 |
55 |
56 |
57 |
58 | -
59 |
60 |
61 | QLayout::SetDefaultConstraint
62 |
63 |
-
64 |
65 |
66 |
67 | 0
68 | 0
69 |
70 |
71 |
72 | Prune below:
73 |
74 |
75 |
76 | -
77 |
78 |
79 |
80 | 0
81 | 0
82 |
83 |
84 |
85 | false
86 |
87 |
88 | true
89 |
90 |
91 | QAbstractSpinBox::NoButtons
92 |
93 |
94 | false
95 |
96 |
97 | 4
98 |
99 |
100 | 0.100000000000000
101 |
102 |
103 | 0.005000000000000
104 |
105 |
106 | 0.000000000000000
107 |
108 |
109 |
110 | -
111 |
112 |
113 |
114 | 72
115 | 0
116 |
117 |
118 |
119 | 10000
120 |
121 |
122 | 1
123 |
124 |
125 | 100
126 |
127 |
128 | 0
129 |
130 |
131 | Qt::Horizontal
132 |
133 |
134 | false
135 |
136 |
137 | false
138 |
139 |
140 | QSlider::NoTicks
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | -
150 |
151 |
152 | Qt::Vertical
153 |
154 |
155 | QSizePolicy::MinimumExpanding
156 |
157 |
158 |
159 | 20
160 | 4
161 |
162 |
163 |
164 |
165 | -
166 |
167 |
168 | Keep original
169 |
170 |
171 | true
172 |
173 |
174 |
175 | -
176 |
177 |
178 | Skip tips for select all below
179 |
180 |
181 | true
182 |
183 |
184 |
185 | -
186 |
187 |
188 | false
189 |
190 |
191 | Use build-in delta mush (2016+)
192 |
193 |
194 | false
195 |
196 |
197 |
198 | -
199 |
200 |
201 | Delete delta mush after solving
202 |
203 |
204 | false
205 |
206 |
207 |
208 |
209 |
210 |
211 | -
212 |
213 |
-
214 |
215 |
216 | Save
217 |
218 |
219 |
220 | -
221 |
222 |
223 | Cancel
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
248 |
249 |
250 | Reset
251 |
252 |
253 |
254 |
255 |
256 |
257 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/ui/samplingTab.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 255
10 | 243
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 | true
21 |
22 |
23 | QFrame::NoFrame
24 |
25 |
26 | QFrame::Plain
27 |
28 |
29 |
30 | 2
31 |
32 |
33 | 2
34 |
35 |
-
36 |
37 |
-
38 |
39 |
40 | Min
41 |
42 |
43 |
44 | -
45 |
46 |
47 | Max
48 |
49 |
50 |
51 | -
52 |
53 |
54 | true
55 |
56 |
57 | Translate:
58 |
59 |
60 |
61 | -
62 |
63 |
64 | -1.0
65 |
66 |
67 |
68 | -
69 |
70 |
71 | 1.0
72 |
73 |
74 |
75 | -
76 |
77 |
78 |
79 | 20
80 | 16777215
81 |
82 |
83 |
84 | ...
85 |
86 |
87 |
88 | -
89 |
90 |
91 | Rotate:
92 |
93 |
94 |
95 | -
96 |
97 |
98 | -90.0
99 |
100 |
101 |
102 | -
103 |
104 |
105 | 90.0
106 |
107 |
108 |
109 | -
110 |
111 |
112 |
113 | 20
114 | 16777215
115 |
116 |
117 |
118 | ...
119 |
120 |
121 |
122 | -
123 |
124 |
125 | Scale:
126 |
127 |
128 |
129 | -
130 |
131 |
132 | -1.0
133 |
134 |
135 |
136 | -
137 |
138 |
139 | true
140 |
141 |
142 | 1.0
143 |
144 |
145 |
146 | -
147 |
148 |
149 |
150 | 20
151 | 16777215
152 |
153 |
154 |
155 | ...
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | -
165 |
166 |
167 | Qt::Horizontal
168 |
169 |
170 |
171 | -
172 |
173 |
174 | true
175 |
176 |
177 | QFrame::NoFrame
178 |
179 |
180 | QFrame::Plain
181 |
182 |
183 |
184 | 6
185 |
186 |
187 | 2
188 |
189 |
190 | 2
191 |
192 |
-
193 |
194 |
-
195 |
196 |
197 | true
198 |
199 |
200 | Blend Shape:
201 |
202 |
203 | true
204 |
205 |
206 | false
207 |
208 |
209 |
210 | -
211 |
212 |
213 | true
214 |
215 |
216 |
217 | -
218 |
219 |
220 | true
221 |
222 |
223 |
224 | 32
225 | 16777215
226 |
227 |
228 |
229 | <--
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 | -
239 |
240 |
241 | Qt::Horizontal
242 |
243 |
244 |
245 | -
246 |
247 |
248 | true
249 |
250 |
251 | QFrame::NoFrame
252 |
253 |
254 | QFrame::Plain
255 |
256 |
257 |
258 | 2
259 |
260 |
261 | 2
262 |
263 |
-
264 |
265 |
266 | 4
267 |
268 |
-
269 |
270 |
271 |
272 | 14
273 | 16777215
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 | -
282 |
283 |
284 | true
285 |
286 |
287 |
288 | 16777215
289 | 16777215
290 |
291 |
292 |
293 | Custom Attributes
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 | -
303 |
304 |
-
305 |
306 |
307 | Run
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
--------------------------------------------------------------------------------
/DeformationLearningSolver/scripts/DLS/widget/utils.py:
--------------------------------------------------------------------------------
1 | __author__ = "Webber Huang"
2 | __contact__ = "xracz.fx@gmail.com"
3 | __website__ = "http://riggingtd.com"
4 |
5 |
6 | import os
7 | import sys
8 |
9 | try:
10 | from PySide.QtCore import Slot, QMetaObject
11 | from PySide.QtUiTools import QUiLoader
12 | from PySide.QtGui import QApplication, QMainWindow, QMessageBox
13 | except ImportError:
14 | from PySide2.QtCore import Slot, QMetaObject
15 | from PySide2.QtUiTools import QUiLoader
16 | from PySide2.QtWidgets import QApplication, QMainWindow, QMessageBox
17 |
18 |
19 | SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)).replace('\\', '/')
20 |
21 | #----------------------------------------------------------------------
22 | def findAllFiles(fileDirectory, fileExtension):
23 | """
24 | Args:
25 | fileDirectory (str)
26 | fileExtension (str)
27 |
28 | Returns:
29 | list
30 | """
31 | return [f for f in os.listdir(fileDirectory) if f.lower().endswith(fileExtension)]
32 |
33 | #----------------------------------------------------------------------
34 | def findAllModules():
35 | """
36 | Returns:
37 | list
38 | """
39 | allPyFiles = findAllFiles(SCRIPT_DIRECTORY, ".py")
40 | return [f.split('.')[0] for f in allPyFiles if not f.startswith("__init__")]
41 |
42 | #----------------------------------------------------------------------
43 | def findAllTabs():
44 | """
45 | Returns:
46 | list
47 | """
48 | tabModules = []
49 | for m in findAllModules():
50 | mod = __import__("DLS.widget.%s" % m, '', '', [m])
51 | if hasattr(mod, 'TAB') and mod.ENABLE:
52 | reload(mod)
53 | tabModules.append(mod)
54 |
55 | tabModules.sort(key=lambda m: m.INDEX)
56 | return [m.getTab() for m in tabModules]
57 |
58 | #----------------------------------------------------------------------
59 | class UiLoader(QUiLoader):
60 | """
61 | Subclass :class:`~PySide.QtUiTools.QUiLoader` to create the user interface
62 | in a base instance.
63 |
64 | Unlike :class:`~PySide.QtUiTools.QUiLoader` itself this class does not
65 | create a new instance of the top-level widget, but creates the user
66 | interface in an existing instance of the top-level class.
67 |
68 | This mimics the behaviour of :func:`PyQt4.uic.loadUi`.
69 | """
70 |
71 | def __init__(self, baseinstance):
72 | """
73 | Create a loader for the given ``baseinstance``.
74 |
75 | The user interface is created in ``baseinstance``, which must be an
76 | instance of the top-level class in the user interface to load, or a
77 | subclass thereof.
78 |
79 | ``parent`` is the parent object of this loader.
80 | """
81 | QUiLoader.__init__(self, baseinstance)
82 | self.baseinstance = baseinstance
83 |
84 | def createWidget(self, class_name, parent=None, name=''):
85 | if parent is None and self.baseinstance:
86 | # supposed to create the top-level widget, return the base instance
87 | # instead
88 | return self.baseinstance
89 | else:
90 | # create a new widget for child widgets
91 | widget = QUiLoader.createWidget(self, class_name, parent, name)
92 | if self.baseinstance:
93 | # set an attribute for the new child widget on the base
94 | # instance, just like PyQt4.uic.loadUi does.
95 | setattr(self.baseinstance, name, widget)
96 | return widget
97 |
98 |
99 | def loadUi(uifile, baseinstance=None):
100 | """
101 | Dynamically load a user interface from the given ``uifile``.
102 |
103 | ``uifile`` is a string containing a file name of the UI file to load.
104 |
105 | If ``baseinstance`` is ``None``, the a new instance of the top-level widget
106 | will be created. Otherwise, the user interface is created within the given
107 | ``baseinstance``. In this case ``baseinstance`` must be an instance of the
108 | top-level widget class in the UI file to load, or a subclass thereof. In
109 | other words, if you've created a ``QMainWindow`` interface in the designer,
110 | ``baseinstance`` must be a ``QMainWindow`` or a subclass thereof, too. You
111 | cannot load a ``QMainWindow`` UI file with a plain
112 | :class:`~PySide.QtGui.QWidget` as ``baseinstance``.
113 |
114 | :method:`~PySide.QtCore.QMetaObject.connectSlotsByName()` is called on the
115 | created user interface, so you can implemented your slots according to its
116 | conventions in your widget class.
117 |
118 | Return ``baseinstance``, if ``baseinstance`` is not ``None``. Otherwise
119 | return the newly created instance of the user interface.
120 | """
121 | loader = UiLoader(baseinstance)
122 | widget = loader.load(uifile)
123 | QMetaObject.connectSlotsByName(widget)
124 | return widget
125 |
126 |
127 | class MainWindow(QMainWindow):
128 |
129 | def __init__(self, parent=None):
130 | QMainWindow.__init__(self, parent)
131 | loadUi(os.path.join(SCRIPT_DIRECTORY, 'mainwindow.ui'), self)
132 |
133 | @Slot(bool)
134 | def on_clickMe_clicked(self, is_checked):
135 | if is_checked:
136 | message = self.trUtf8(b'I am checked now.')
137 | else:
138 | message = self.trUtf8(b'I am unchecked now.')
139 | QMessageBox.information(self, self.trUtf8(b'You clicked me'), message)
140 |
141 | @Slot()
142 | def on_actionHello_triggered(self):
143 | QMessageBox.information(self, self.trUtf8(b'Hello world'),
144 | self.trUtf8(b'Greetings to the world.'))
145 |
146 |
147 | def main():
148 | app = QApplication(sys.argv)
149 | window = MainWindow()
150 | window.show()
151 | app.exec_()
152 |
153 |
154 | if __name__ == '__main__':
155 | main()
156 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2016, Webber Huang
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Deformation Learning Solver for Autodesk Maya
2 |
3 | **This project has been DEPRECATED and is no longer being supported.** This is just my personal experiment project that I never expected people taking it seriously, companies use this tool will end up implementing their own version, and I'm not allowed to share or sell the source code in any way, sorry about that.
4 |
5 | Please find the alternative solution from **EA's [Dem Bones](https://github.com/electronicarts/dem-bones)**, it's reliable in terms of performance and accuracy, I highly recommend everyone adapt this implementaion to your own project.
6 |
7 | Any query regarding to DLS won't get replied, thanks for your understanding.
8 |
9 | ------------------------------------------
10 |
11 | Deformation Learning Solver is based on Smooth Skinning Decomposition with Rigid Bones which was an automated algorithm to extract the linear blend skinning (LBS) from a set of example poses, and made to convert any deformation approximation to joints and it's skinning-based. This allows there to be a savings in computing resources and a smaller data footprint.
12 |
13 | This tool haven't be verified in real production yet, since this's just a personal research project to learn SSDR and skinning technique in deep, please feel free to test it at your own risk.
14 |
15 | ## License: BSD 3-Clause
16 |
17 | ## Contact:
18 | * Author: [Webber Huang](https://uk.linkedin.com/in/webber-huang-aab076100)
19 | * Project: [https://github.com/WebberHuang/DeformationLearningSolver](https://github.com/WebberHuang/DeformationLearningSolver)
20 |
21 | ## Demo:
22 | * [Deformation Learning Solver](https://vimeo.com/130998850)
23 | * [Deformation Learning Solver v1.5](https://vimeo.com/138048608)
24 |
25 | ## Requires:
26 | Maya 2014 x64 and above, Windows, Linux and OS X
27 |
28 | The solver has been compiled success on these platforms:
29 |
30 | * Windows 7 64bit, Visual Studio 2013
31 | * CentOS 7, GCC 4.8.3 with -std=c++11
32 | * OS X 10.10, Xcode 6.1 with -std=c++11
33 |
34 | ## Install:
35 | * This tool is module based, you can place "DeformationLearningSolver" folder to any where.
36 |
37 | * Launch maya, drag install.mel into scene, a new icon will be created in current shelf, launch Deformation Learning Solver by clicking the icon.
38 |
39 | ### Manual Install:
40 | * What 'install.mel' does is to create 'DeformationLearningSolver.mod' in */YOUR/HOME/DIRECTORY/maya/modules* (ie. *C:/Users/YourName/Documents/maya/modules*), and setup the installation path, then maya will find this tool automatically. In the same way, you can put 'DeformationLearningSolver.mod' into any directory existing in 'MAYA\_MODULE\_PATH', then change the paths in it and make them point to the right position, maya will find it without difficulty.
41 |
42 | * There's a backup of 'DeformationLearningSolver.mod' in 'modules' folder, you can copy and paste it to anywhere rather than modify it, otherwise, 'install.mel' will fail to install.
43 |
44 | * Launch it with these python commands:
45 | > import DLS
46 | > DLS.launch()
47 |
48 | ## Features:
49 | * Convert deformation animation such as blend shapes, to skinned, weighted and bone joint animation.
50 | * Approximate deformation animation by solving the skinning weights with existing joints and joint animations.
51 | * Reverse skeleton animations from animated sequences with existing joints and skinning weights.
52 |
53 | ## Limitations:
54 | * Work with single mesh each time.
55 |
56 | ## Plug-ins:
57 | These plug-ins are included in this tool
58 |
59 | * SSDSolverCmd: the core functions of SSDR.
60 | * wbDeltaMushDeformer: a deformer based on [Delta Mush: Smoothing Deformations While Preserving Detail](http://dl.acm.org/citation.cfm?id=2633376), it's also a component in AdvanceSkeleton since 5.0.
61 |
62 | ## Usage:
63 | - There's no document for this tool, the only instruction you can find are those two Demos mentioned above.
64 |
65 | - This tool can either solve the best weight map with pre-define joints by user or extract specify number of joints, animations and weight map from a mesh sequences, the first case is extremely fast since it only need to solve the weight map with one iteration.
66 |
67 | - To solve weight map from existing joints, please bind mesh with skin cluster first, this tool will find joints involve, then put them into solver. Otherwise, it will solve mesh sequences with specify number of joints within max iterations.
68 |
69 | ### Parameters:
70 | Here are key parameters you should understand:
71 |
72 | - **Num of Bones**: specifies the number of joints will be created.
73 | - **Max Infs**: specifies the maximum number of weighted influences for a given point.
74 | - **Epsilon**: the computation will finish before it reaches the max iteration if the subtraction between Current Total Error and Previous Total Error is less than epsilon.
75 | - **Max Iters**: in general, more iterations can result in more accurate approximation, but I found 10 is sufficient in most cases.
76 | - **Target Mesh**: input animated mesh here will enable reverse enginnering feature as showed in [Demo v1.5](https://vimeo.com/138048608).
77 |
78 | ## History:
79 | #### 2017-11-13: v1.5.5 by Webber Huang
80 | - FIXED: unable to support arbitrary FPS
81 |
82 | #### 2017-07-31: v1.5.4 by Webber Huang
83 | - UPDATE: wbDeltaMush v1.8.1, fixed crash issue when mesh contains wrong UV
84 | - Compile against Maya 2017
85 |
86 | #### 2015-11-21: v1.5.3 by Webber Huang
87 | - UPDATE: wbDeltaMush v1.8.0, better performance and minor bugs fixed
88 |
89 | #### 2015-09-02: v1.5.0 by Webber Huang
90 | - NEW: wbDeltaMush is included
91 | - NEW: reverse bone animation from animated sequence
92 | - NEW: alternative update with existing bones and weights
93 | - NEW: a editor for sampling any attribute
94 | - UPDATE: parallelize bone transformation updating function, 30~40% faster than before
95 | - minor bugs fixed
96 |
97 | #### 2015-06-18: v1.0.0 by Webber Huang
98 | - Initial release
99 |
100 |
101 | ## References:
102 | 1. B. H. Le and Z. Deng, “Smooth Skinning Decomposition with Rigid Bones,” ACM Trans. Graph., vol. 31, no. 6, pp. 199:1–199:10, Nov. 2012.
103 |
--------------------------------------------------------------------------------