From 6ce5db02eba60b81ac34c0046e2f6bb91d9ddd24 Mon Sep 17 00:00:00 2001 From: Joji Date: Sun, 6 Aug 2023 12:19:45 -0700 Subject: [PATCH 1/3] Fixed a bug that can't import/export a SDK file from each QAction GUI. When export/import_SDKs_action is triggered, it sends False by default to the method, which is why the path argument receives False. To avoid this behavior and ensure None is passed instead, I used a lambda function. --- release/scripts/mgear/rigbits/sdk_manager/SDK_manager_ui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/mgear/rigbits/sdk_manager/SDK_manager_ui.py b/release/scripts/mgear/rigbits/sdk_manager/SDK_manager_ui.py index 3909374b..0c2a6f2b 100644 --- a/release/scripts/mgear/rigbits/sdk_manager/SDK_manager_ui.py +++ b/release/scripts/mgear/rigbits/sdk_manager/SDK_manager_ui.py @@ -303,8 +303,8 @@ def create_connections(self): # - M E N U - B A R - # # ================================================================# # File - self.export_SDKs_action.triggered.connect(self.export_SDKs) - self.import_SDKs_action.triggered.connect(self.import_SDKs) + self.export_SDKs_action.triggered.connect(lambda: self.export_SDKs()) + self.import_SDKs_action.triggered.connect(lambda: self.import_SDKs()) # Select self.select_all_sdk_ctls.triggered.connect( From eebffb89d4513fce50d3b2a6446d2c1ce8399c24 Mon Sep 17 00:00:00 2001 From: Joji Date: Sun, 13 Aug 2023 15:23:04 -0700 Subject: [PATCH 2/3] Fixed a bug related to the Mirror Control Shape tool. reported by remicc http://forum.mgear-framework.com/t/bug-naming-rules-mirror-shape/3389 --- .../scripts/mgear/rigbits/mirror_controls.py | 218 ++++++++++-------- 1 file changed, 118 insertions(+), 100 deletions(-) diff --git a/release/scripts/mgear/rigbits/mirror_controls.py b/release/scripts/mgear/rigbits/mirror_controls.py index 953cfeed..1c36812e 100644 --- a/release/scripts/mgear/rigbits/mirror_controls.py +++ b/release/scripts/mgear/rigbits/mirror_controls.py @@ -1,116 +1,134 @@ -import pymel.core as pc +import pymel.core as pm from maya.app.general.mayaMixin import MayaQWidgetDockableMixin import mgear -from mgear.vendor.Qt import QtCore, QtWidgets - - -def mirror_selection(): - pairs = [] - for source in pc.selected(): - target = get_opposite_control(source) - if target: - pairs.append([source, target]) - - mirror_pairs(pairs) - - -def get_controls_without_string(exclusion_string): - nodes = [] - - # Find controllers set - rig_models = [ - item for item in pc.ls(transforms=True) if item.hasAttr("is_rig") - ] - controllers_set = None - for node in rig_models[0].rigGroups.inputs(): - if node.name().endswith("controllers_grp"): - controllers_set = node - break - - # Collect all transforms from set and subsets. - nodes = [] - for node in controllers_set.members(): - if node.nodeType() == "objectSet": - nodes.extend(node.members()) - else: - nodes.append(node) - - # Find all nodes without exclusion_string - nodes = [x for x in nodes if exclusion_string not in x.name()] - - return nodes - -def get_opposite_control(node): - target_name = mgear.core.string.convertRLName(node.name()) - target = None - if pc.objExists(target_name): - target = pc.PyNode(target_name) - return target - - -def mirror_left_to_right(): - pairs = [] - for source in get_controls_without_string("_R"): - target = get_opposite_control(source) - if target: - pairs.append([source, target]) - - mirror_pairs(pairs) - - -def mirror_right_to_left(): - pairs = [] - for source in get_controls_without_string("_L"): - target = get_opposite_control(source) - if target: - pairs.append([source, target]) - - mirror_pairs(pairs) +from mgear.vendor.Qt import QtCore, QtWidgets -def mirror_pairs(pairs): - # Modify control shapes - for source, target in pairs: - # Copy shapes - source_copy = pc.duplicate(source)[0] +class MirrorController: + def __init__(self): + pass + + @staticmethod + def get_opposite_control(node): + side_l = node.attr("L_custom_side_label").get() + side_r = node.attr("R_custom_side_label").get() + side = node.attr("side_label").get() + + target_name = None + if side == "L": + target_name = node.name().replace(side_l, side_r) + elif side == "R": + target_name = node.name().replace(side_r, side_l) + + if target_name and pm.objExists(target_name): + return pm.PyNode(target_name) + return None + + @staticmethod + def get_specific_side_controls(side="L"): + # Find controllers set + rig_models = [item for item in pm.ls(transforms=True) if item.hasAttr("is_rig")] + controllers_set = None + for node in rig_models[0].rigGroups.inputs(): + if node.name().endswith("controllers_grp"): + controllers_set = node + break + + # Collect all transforms from set and subsets. + nodes = [] + for node in controllers_set.members(): + if node.nodeType() == "objectSet": + nodes.extend(node.members()) + else: + nodes.append(node) + + side_name = None + side_ctl = [node for node in nodes if node.hasAttr("{}_custom_side_label".format(side))] + if side_ctl: + side_name = side_ctl[0].attr("{}_custom_side_label".format(side)).get() + + # Find all nodes without exclusion_string + nodes = [x for x in nodes if side_name in x.name()] + return nodes + + @staticmethod + def copy_and_prepare_source(source): + source_copy = pm.duplicate(source)[0] mgear.core.attribute.setKeyableAttributes( source_copy, ["tx", "ty", "tz", "ro", "rx", "ry", "rz", "sx", "sy", "sz"] ) - # Delete children except shapes for child in source_copy.getChildren(): if child.nodeType() != "nurbsCurve": - pc.delete(child) + pm.delete(child) + return source_copy + + def mirror_pairs(self, pairs): + # Modify control shapes + for source, target in pairs: + source_copy = self.copy_and_prepare_source(source) + + pm.select(clear=True) + + # Mirror a source copy under a group node + grp = pm.group(world=True) + pm.parent(source_copy, grp) + grp.scaleX.set(-1) + + # Re-parent, freeze transforms and match color + pm.parent(source_copy, target) + pm.makeIdentity(source_copy, apply=True, t=1, r=1, s=1, n=0) + pm.parent(source_copy, target.getParent()) + + target_color = mgear.core.curve.get_color(target) + if target_color: + mgear.core.curve.set_color(source_copy, target_color) + + # Replace shape + mgear.rigbits.replaceShape(source_copy, [target]) + + # Clean up + pm.delete(grp) + pm.delete(source_copy) + + def mirror_selection(self): + pairs = [] + for source in pm.selected(): + target = self.get_opposite_control(source) + if not target: + continue + pairs.append([source, target]) + + self.mirror_pairs(pairs) - # Mirror - pc.select(clear=True) - grp = pc.group(world=True) - pc.parent(source_copy, grp) - grp.scaleX.set(-1) + def mirror_left_to_right(self): + pairs = [] + for source in self.get_specific_side_controls(side="L"): + target = self.get_opposite_control(source) + if target: + pairs.append([source, target]) - # Reparent, freeze transforms and match color - pc.parent(source_copy, target) - pc.makeIdentity(source_copy, apply=True, t=1, r=1, s=1, n=0) - pc.parent(source_copy, target.getParent()) - targetColor = mgear.core.curve.get_color(target) - if targetColor: - mgear.core.curve.set_color(source_copy, targetColor) + self.mirror_pairs(pairs) - # Replace shape - mgear.rigbits.replaceShape(source_copy, [target]) + def mirror_right_to_left(self): + pairs = [] + for source in self.get_specific_side_controls(side="R"): + target = self.get_opposite_control(source) + if target: + pairs.append([source, target]) - # Clean up - pc.delete(grp) - pc.delete(source_copy) + self.mirror_pairs(pairs) -class mirror_controls_ui(MayaQWidgetDockableMixin, QtWidgets.QDialog): +class MirrorControlsUi(MayaQWidgetDockableMixin, QtWidgets.QDialog): def __init__(self, parent=None): - super(mirror_controls_ui, self).__init__(parent) + super(MirrorControlsUi, self).__init__(parent) + + self.func = MirrorController() self.setWindowTitle("Mirror Controls") self.setWindowFlags(QtCore.Qt.Window) @@ -134,26 +152,26 @@ def __init__(self, parent=None): self.mirror_button.clicked.connect(self.mirror_button_pressed) def mirror_button_pressed(self): - pc.system.undoInfo(openChunk=True) + pm.system.undoInfo(openChunk=True) # Store selection - selection = pc.selected() + selection = pm.selected() if self.selection_button.isChecked(): - mirror_selection() + self.func.mirror_selection() if self.left_to_right_button.isChecked(): - mirror_left_to_right() + self.func.mirror_left_to_right() if self.right_to_left_button.isChecked(): - mirror_right_to_left() + self.func.mirror_right_to_left() # Restore selection - pc.select(selection) + pm.select(selection) - pc.system.undoInfo(closeChunk=True) + pm.system.undoInfo(closeChunk=True) def show(*args): - mgear.core.pyqt.showDialog(mirror_controls_ui) + mgear.core.pyqt.showDialog(MirrorControlsUi) if __name__ == "__main__": From ebb6add4d569afe15061f325360f1be1aa4649dc Mon Sep 17 00:00:00 2001 From: Joji Nishimura Date: Sun, 13 Aug 2023 15:36:46 -0700 Subject: [PATCH 3/3] Sorry, I accidently commit a file for another pull request. --- .../scripts/mgear/rigbits/mirror_controls.py | 178 ------------------ 1 file changed, 178 deletions(-) delete mode 100644 release/scripts/mgear/rigbits/mirror_controls.py diff --git a/release/scripts/mgear/rigbits/mirror_controls.py b/release/scripts/mgear/rigbits/mirror_controls.py deleted file mode 100644 index 1c36812e..00000000 --- a/release/scripts/mgear/rigbits/mirror_controls.py +++ /dev/null @@ -1,178 +0,0 @@ -import pymel.core as pm -from maya.app.general.mayaMixin import MayaQWidgetDockableMixin - -import mgear - -from mgear.vendor.Qt import QtCore, QtWidgets - - -class MirrorController: - def __init__(self): - pass - - @staticmethod - def get_opposite_control(node): - side_l = node.attr("L_custom_side_label").get() - side_r = node.attr("R_custom_side_label").get() - side = node.attr("side_label").get() - - target_name = None - if side == "L": - target_name = node.name().replace(side_l, side_r) - elif side == "R": - target_name = node.name().replace(side_r, side_l) - - if target_name and pm.objExists(target_name): - return pm.PyNode(target_name) - return None - - @staticmethod - def get_specific_side_controls(side="L"): - # Find controllers set - rig_models = [item for item in pm.ls(transforms=True) if item.hasAttr("is_rig")] - controllers_set = None - for node in rig_models[0].rigGroups.inputs(): - if node.name().endswith("controllers_grp"): - controllers_set = node - break - - # Collect all transforms from set and subsets. - nodes = [] - for node in controllers_set.members(): - if node.nodeType() == "objectSet": - nodes.extend(node.members()) - else: - nodes.append(node) - - side_name = None - side_ctl = [node for node in nodes if node.hasAttr("{}_custom_side_label".format(side))] - if side_ctl: - side_name = side_ctl[0].attr("{}_custom_side_label".format(side)).get() - - # Find all nodes without exclusion_string - nodes = [x for x in nodes if side_name in x.name()] - return nodes - - @staticmethod - def copy_and_prepare_source(source): - source_copy = pm.duplicate(source)[0] - mgear.core.attribute.setKeyableAttributes( - source_copy, - ["tx", "ty", "tz", "ro", "rx", "ry", "rz", "sx", "sy", "sz"] - ) - - for child in source_copy.getChildren(): - if child.nodeType() != "nurbsCurve": - pm.delete(child) - return source_copy - - def mirror_pairs(self, pairs): - # Modify control shapes - for source, target in pairs: - source_copy = self.copy_and_prepare_source(source) - - pm.select(clear=True) - - # Mirror a source copy under a group node - grp = pm.group(world=True) - pm.parent(source_copy, grp) - grp.scaleX.set(-1) - - # Re-parent, freeze transforms and match color - pm.parent(source_copy, target) - pm.makeIdentity(source_copy, apply=True, t=1, r=1, s=1, n=0) - pm.parent(source_copy, target.getParent()) - - target_color = mgear.core.curve.get_color(target) - if target_color: - mgear.core.curve.set_color(source_copy, target_color) - - # Replace shape - mgear.rigbits.replaceShape(source_copy, [target]) - - # Clean up - pm.delete(grp) - pm.delete(source_copy) - - def mirror_selection(self): - pairs = [] - for source in pm.selected(): - target = self.get_opposite_control(source) - if not target: - continue - pairs.append([source, target]) - - self.mirror_pairs(pairs) - - def mirror_left_to_right(self): - pairs = [] - for source in self.get_specific_side_controls(side="L"): - target = self.get_opposite_control(source) - if target: - pairs.append([source, target]) - - self.mirror_pairs(pairs) - - def mirror_right_to_left(self): - pairs = [] - for source in self.get_specific_side_controls(side="R"): - target = self.get_opposite_control(source) - if target: - pairs.append([source, target]) - - self.mirror_pairs(pairs) - - -class MirrorControlsUi(MayaQWidgetDockableMixin, QtWidgets.QDialog): - - def __init__(self, parent=None): - super(MirrorControlsUi, self).__init__(parent) - - self.func = MirrorController() - - self.setWindowTitle("Mirror Controls") - self.setWindowFlags(QtCore.Qt.Window) - self.setAttribute(QtCore.Qt.WA_DeleteOnClose, 1) - self.setMinimumSize(QtCore.QSize(350, 0)) - - layout = QtWidgets.QVBoxLayout(self) - self.selection_button = QtWidgets.QRadioButton("Selection") - self.selection_button.setChecked(True) - layout.addWidget(self.selection_button) - - self.left_to_right_button = QtWidgets.QRadioButton("Left to Right") - layout.addWidget(self.left_to_right_button) - - self.right_to_left_button = QtWidgets.QRadioButton("Right to Left") - layout.addWidget(self.right_to_left_button) - - self.mirror_button = QtWidgets.QPushButton("Mirror Controls") - layout.addWidget(self.mirror_button) - - self.mirror_button.clicked.connect(self.mirror_button_pressed) - - def mirror_button_pressed(self): - pm.system.undoInfo(openChunk=True) - - # Store selection - selection = pm.selected() - - if self.selection_button.isChecked(): - self.func.mirror_selection() - if self.left_to_right_button.isChecked(): - self.func.mirror_left_to_right() - if self.right_to_left_button.isChecked(): - self.func.mirror_right_to_left() - - # Restore selection - pm.select(selection) - - pm.system.undoInfo(closeChunk=True) - - -def show(*args): - mgear.core.pyqt.showDialog(MirrorControlsUi) - - -if __name__ == "__main__": - show()