Skip to content

Commit

Permalink
V1.1.10
Browse files Browse the repository at this point in the history
Updating validateInteractiveNormalization to get around edgcase error when running mc.skinPercent(skinCluster, normalize=True) on certain skinClusters.
  • Loading branch information
AKEric committed Jun 4, 2024
1 parent 7eed643 commit a4327b0
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 19 deletions.
9 changes: 8 additions & 1 deletion skinner/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,16 @@
'weight difference threhold' value. Changing the default post smooth diff
value from .01 to .25, to help resolve odd skinning bugs.
2022-03-31 : v1.1.8 : Bugfixing string formatting error in core -> setWeights.
2022-05-18 : v1.1.9 : Updating core.closestPointKdTree to allow numNeighbors=1.
Before that it would be auto-set to 2, based on my not understanding how
the ndarray return values worked. Also updating it to support older versions
of KDTree that don't have the 'workers' arg.
2022-07-18 : v1.1.10 : Updating validateInteractiveNormalization to get around
edgcase error when running mc.skinPercent(skinCluster, normalize=True) on
certain skinClusters.
"""
__author__ = "Eric Pavey"
__version__ = "1.1.8"
__version__ = "1.1.10"
__source__ = "https://github.com/AKEric/skinner"
__documentation__ = "https://github.com/AKEric/skinner/blob/main/README.md"
__licence__ = "https://github.com/AKEric/skinner/blob/main/LICENSE.md"
34 changes: 22 additions & 12 deletions skinner/core.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
r"""
Name : skinner.core.py
Author : Eric Pavey - [email protected] - https://github.com/AKEric/skinner
Author : Eric Pavey - [email protected] - www.akeric.com
Creation Date : 2019-09-28
Description :
Import/export skin weights. It just works, fast.
Expand Down Expand Up @@ -87,6 +87,10 @@
Changing the default post smooth diff value from .01 to .25, to help resolve
odd skinning bugs.
2022-03-31 : v1.1.8 : Bugfixing string formatting error in setWeights.
2022-05-18 : v1.1.9 : Updating closestPointKdTree to allow numNeighbors=1.
Before that it would be auto-set to 2, based on my not understanding how
the ndarray return values worked. Also updating it to support older versions
of KDTree that don't have the 'workers' arg.
Examples:
Expand Down Expand Up @@ -222,11 +226,7 @@ def closestPointKdTree(points:np.ndarray, targets:np.ndarray, numNeighbors:int)
targets : ndarray[n][3] : All the 3D points being tested against: Their
order represents the vert index order. They're what the kdTree is being
made on; What originally had weights saved on them.
numNeighbors : int : The number of closest neighbors to find/return. Note
that how the KDTree returns its values, if you pass numNeighbors=1 to it,
it won't generate the correct type of nested numpy arrays. Thus, internally,
if ther user passes in numNeighbors=1, the code swiches it to numNeighbors=2.
Just be aware the return will affected as such.
numNeighbors : int : The number of closest neighbors to find/return.
Return : tuple : both are ndarrays of the same length in the vert order of the
passed in points array. It is the direct return from KDTree.query()
Expand All @@ -244,16 +244,26 @@ def closestPointKdTree(points:np.ndarray, targets:np.ndarray, numNeighbors:int)
raise ImportError("Unable to import the scipy.spatial module to access the KDTree class")
if len(targets) < numNeighbors:
numNeighbors = len(targets)
if numNeighbors == 1:
# Why? See docstring above.
numNeighbors = 2

workers = 1 # The KDTree.query default : Use 1 processor.
if gMultiThread:
workers = -1 # use all'dem
# Build and query a kdTree for our target points, then return the results
# checking them against our sample points:
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.KDTree.query.html#scipy.spatial.KDTree.query
return KDTree(targets).query(points, numNeighbors, workers=workers)
try:
distances, indexes = KDTree(targets).query(points, numNeighbors, workers=workers)
except:
# Older versions of KDTree don't support the workers arg.
distances, indexes = KDTree(targets).query(points, numNeighbors)

if numNeighbors == 1:
# If we only query one closest distance, numpy will return an array of scalars,
# not an array of arrays. For consistency, we want it to always return
# an array of arrays.
distances = [[item] for item in distances]
indexes = [[item] for item in indexes]
return (distances, indexes)

def closestPointBruteForce(points:np.ndarray, targets:np.ndarray, numNeighbors:int) -> tuple:
r"""
Expand Down Expand Up @@ -1971,7 +1981,7 @@ def setWeights(items:list, skinChunks=None, filePath=None, createMissingInfluenc
# Validation complete

timeStart = time.time()
mc.undoInfo(openChunk=True)
mc.undoInfo(openChunk=True, chunkName="setWeights")
try:
#-------------------------------------------------------------
# Based on what was proivded to import on, break it down to individual verts:
Expand Down Expand Up @@ -2532,7 +2542,7 @@ def setWeights(items:list, skinChunks=None, filePath=None, createMissingInfluenc
# To get that, we need to 'unpack' our current weights 'list of sublists':
arrayWeights = om2.MDoubleArray([item for item in itertools.chain(*weights)])

mc.undoInfo(openChunk=True)
mc.undoInfo(openChunk=True, chunkName="setWeights undoHack")
try:
# Hack the undo queue: Put in dummy values.
inf = infDags[0].fullPathName()
Expand Down
18 changes: 14 additions & 4 deletions skinner/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
r"""
Name : skinner.utils.py
Author : Eric Pavey - [email protected] - https://github.com/AKEric/skinner
Author : Eric Pavey - [email protected] - www.akeric.com
Creation Date : 2021-10-23
Description :
Various utils/tools used in different Skinner modules.
Expand All @@ -17,6 +17,9 @@
2022-03-03 : v1.1.6 : Updating ProgressWindow to print stack trace if exceptions
are encountered. Bugfixing getAtBindPose to skip past skinClusters missing
connected dagPose nodes.
2022-07-18 : v1.1.10 : Updating validateInteractiveNormalization to get around
edgcase error when running mc.skinPercent(skinCluster, normalize=True) on
certain skinClusters.
"""
import re
import os
Expand Down Expand Up @@ -264,15 +267,22 @@ def validateInteractiveNormalization(skinClusters:list, promptOnNonInteractiveNo
print(" ", ni)
if promptOnNonInteractiveNormalization:
result = mc.confirmDialog(title="Warning",
message=f"Found {len(nonInteractive)} skinCluster node(s) that don't have their 'normalizeWeights' set to 'interactive'.\n\nSkinner only supports normalized weights:\n\nDo you want skinner to auto convert your skinClusters to 'interactive' normalization? If not, the tool will exit.",
message=f"Found {len(nonInteractive)} skinCluster node(s) that don't have their 'normalizeWeights' set to 'interactive'.\n\nSkinner only supports normalized weights:\n\nDo you want skinner to auto convert your skinClusters to 'interactive' normalization? If not, the tool will exit.\n\nIf you don't understand what this means, it's generally safe to 'Convert'.",
button=("Convert", "Exit"))
if result == "Exit":
raise Exception("User exited tool based on incompatible skinCluster.normalizeWeight values.")
mc.undoInfo(openChunk=True)
mc.undoInfo(openChunk=True, chunkName="validateInteractiveNormalization")
try:
for skinCluster in nonInteractive:
mc.setAttr(f"{skinCluster}.normalizeWeights", 1) # 0 = none, 1 = interactive, 2 = post
mc.skinPercent(skinCluster, normalize=True) # normalize!
try:
# There ahve been times Maya has errored here, simply saying
# "No objects found.", and nothing else. But skipping this
# if it fails seems to be ok,
mc.skinPercent(skinCluster, normalize=True) # normalize!
except:
pass
print(" NORM2 END")
print("Skinner: updated the above skinCluster nodes to use 'interactive' weight normalization.")
finally:
mc.undoInfo(closeChunk=True)
Expand Down
4 changes: 2 additions & 2 deletions skinner/window.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
r"""
Name : skinner.window.py
Author : Eric Pavey - [email protected] - https://github.com/AKEric/skinner
Author : Eric Pavey - [email protected] - www.akeric.com
Creation Date : 2019-09-28
Description : Window / UI code for the skinner tool. For the back-end API code,
see skinner.core.py
Expand Down Expand Up @@ -1145,7 +1145,7 @@ def importSkin(self, mode="browser"):
closestNeighborCount = int(self.widget_nearestNeighborNum.text())
closestNeighborDistMult = float(self.widget_nearestNeighborDistMult.text())

mc.undoInfo(openChunk=True)
mc.undoInfo(openChunk=True, chunkName="importSkin")

result = core.importSkin(items=None, filePaths=paths, verbose=verbose,
printOverview=printOverview, printOverviewMode=printOverviewMode,
Expand Down

0 comments on commit a4327b0

Please sign in to comment.