From c6b3fc3c6c847b5de1a1f78af0f5c963dbe2f91a Mon Sep 17 00:00:00 2001
From: ordinc <35759494+ordinc@users.noreply.github.com>
Date: Thu, 4 Sep 2025 21:12:47 +0800
Subject: [PATCH 1/3] Add compatible component related functions
---
release/scripts/mgear/core/dagmenu.py | 7 +++++++
.../mgear/shifter/guide_manager_component.py | 20 +++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/release/scripts/mgear/core/dagmenu.py b/release/scripts/mgear/core/dagmenu.py
index a8dacbed..4786ddfe 100644
--- a/release/scripts/mgear/core/dagmenu.py
+++ b/release/scripts/mgear/core/dagmenu.py
@@ -42,6 +42,7 @@
from .six import string_types
from mgear.vendor.Qt import QtWidgets
+from mgear.compatible import compatible_comp_dagmenu
def __change_rotate_order_callback(*args):
@@ -821,6 +822,12 @@ def mgear_dagmenu_guide_fill(parent_menu, current_guide_locator):
command=guide_template.updateGuide,
image="mgear_loader.svg",
)
+ cmds.menuItem(
+ parent=parent_menu,
+ label="Update Setected Components Type",
+ command=compatible_comp_dagmenu.update_component_type_and_update_guide_with_dagmenu,
+ image="mgear_loader.svg",
+ )
cmds.menuItem(
parent=parent_menu,
label="Reload Components",
diff --git a/release/scripts/mgear/shifter/guide_manager_component.py b/release/scripts/mgear/shifter/guide_manager_component.py
index 98c1ec06..5c209d66 100644
--- a/release/scripts/mgear/shifter/guide_manager_component.py
+++ b/release/scripts/mgear/shifter/guide_manager_component.py
@@ -13,8 +13,12 @@
from mgear import shifter
from mgear.shifter import guide_manager
from mgear.shifter import guide_manager_component_ui as gmcUI
+from mgear.compatible import guide_manager_compatible_comp as gmcc
+
import importlib
+importlib.reload(gmcc)
+
PY2 = sys.version_info[0] == 2
@@ -157,10 +161,15 @@ def _component_menu(self, QPos):
return
self.comp_menu = QtWidgets.QMenu()
parentPosition = comp_widget.mapToGlobal(QtCore.QPoint(0, 0))
+ menu_item_00 = self.comp_menu.addAction(
+ "Syn The Selected Component Type To The Type Selected In The Manager"
+ )
+ self.comp_menu.addSeparator()
menu_item_01 = self.comp_menu.addAction("Draw Component")
self.comp_menu.addSeparator()
menu_item_02 = self.comp_menu.addAction("Refresh List")
+ menu_item_00.triggered.connect(self.set_component)
menu_item_01.triggered.connect(self.draw_component)
menu_item_02.triggered.connect(self._refreshList)
@@ -226,6 +235,9 @@ def create_connections(self):
self.gmcUIInst.search_lineEdit.customContextMenuRequested.connect(
self._search_menu
)
+ self.gmcUIInst.update_guide_checkBox.stateChanged.connect(
+ self.on_update_changed
+ )
#############
# SLOTS
@@ -271,6 +283,14 @@ def draw_component(self, parent=None):
for x in self.gmcUIInst.component_listView.selectedIndexes():
guide_manager.draw_comp(x.data(), parent, showUI)
+ def on_update_changed(self, state):
+ self.update_flag = self.gmcUIInst.update_guide_checkBox.isChecked()
+
+ def set_component(self):
+ self.update_flag = self.gmcUIInst.update_guide_checkBox.isChecked()
+ for x in self.gmcUIInst.component_listView.selectedIndexes():
+ gmcc.update_component_type_and_update_guide(x.data(), self.update_flag)
+
def filter_changed(self, filter_str):
"""Filter out the elements in the list view"""
# pyside2
From 59d66cf9cbb54d1b24fd28ec218a14b6d52772e4 Mon Sep 17 00:00:00 2001
From: ordinc <35759494+ordinc@users.noreply.github.com>
Date: Thu, 4 Sep 2025 21:15:09 +0800
Subject: [PATCH 2/3] compatible components modules
Add functional modules related to compatible components
---
release/scripts/mgear/compatible/__init__.py | 0
.../mgear/compatible/compatible_comp.py | 47 ++++++
.../compatible/compatible_comp_dagmenu.py | 123 ++++++++++++++
.../mgear/compatible/compatible_comp_ui.py | 58 +++++++
.../mgear/compatible/compatible_comp_ui.ui | 107 ++++++++++++
.../compatible_components_dagmenu.py | 123 ++++++++++++++
.../guide_manager_compatible_comp.py | 152 ++++++++++++++++++
7 files changed, 610 insertions(+)
create mode 100644 release/scripts/mgear/compatible/__init__.py
create mode 100644 release/scripts/mgear/compatible/compatible_comp.py
create mode 100644 release/scripts/mgear/compatible/compatible_comp_dagmenu.py
create mode 100644 release/scripts/mgear/compatible/compatible_comp_ui.py
create mode 100644 release/scripts/mgear/compatible/compatible_comp_ui.ui
create mode 100644 release/scripts/mgear/compatible/compatible_components_dagmenu.py
create mode 100644 release/scripts/mgear/compatible/guide_manager_compatible_comp.py
diff --git a/release/scripts/mgear/compatible/__init__.py b/release/scripts/mgear/compatible/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/release/scripts/mgear/compatible/compatible_comp.py b/release/scripts/mgear/compatible/compatible_comp.py
new file mode 100644
index 00000000..d61adf17
--- /dev/null
+++ b/release/scripts/mgear/compatible/compatible_comp.py
@@ -0,0 +1,47 @@
+import importlib
+import mgear.pymaya as pm
+from mgear.vendor.Qt import QtCore, QtWidgets
+import mgear.compatible.compatible_comp_ui as rcUI
+
+importlib.reload(rcUI)
+
+
+class RelatedComponents(QtWidgets.QDialog, rcUI.Ui_Dialog):
+ def __init__(self, related_components, parent=None):
+ self.toolName = "RelatedComponents"
+ super(RelatedComponents, self).__init__(parent)
+ self.setupUi(self)
+ self.result_components = None
+ self.update_flag = False
+ self.components_comboBox.addItems(related_components)
+ self.create_connections()
+ self.setWindowTitle("Related Components")
+ self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
+
+ def create_connections(self):
+ self.buttonBox.accepted.connect(self.ok)
+ self.update_checkBox.stateChanged.connect(self.on_update_changed)
+
+ def on_update_changed(self, state):
+ self.update_flag = state == QtCore.Qt.Checked
+
+ def ok(self):
+ self.result_components = str(self.components_comboBox.currentText())
+ self.update_flag = self.update_checkBox.isChecked()
+
+ def cancel(self):
+ pm.displayWarning("User cancels update.")
+
+
+def exec_window(related_components, *args):
+ windw = RelatedComponents(related_components)
+ if windw.exec_():
+ return windw
+
+
+if __name__ == "__main__":
+ sample_components = ["Arm", "Leg", "Spine"]
+ w = exec_window(sample_components)
+ if w:
+ print(f"Selected: {w.result_components}")
+ print(f"Update enabled: {w.update_flag}")
diff --git a/release/scripts/mgear/compatible/compatible_comp_dagmenu.py b/release/scripts/mgear/compatible/compatible_comp_dagmenu.py
new file mode 100644
index 00000000..78e15e01
--- /dev/null
+++ b/release/scripts/mgear/compatible/compatible_comp_dagmenu.py
@@ -0,0 +1,123 @@
+import re
+import importlib
+
+import maya.cmds as cmds
+import mgear.pymaya as pm
+from mgear.shifter import guide_template
+from mgear.compatible import compatible_comp as rc
+from mgear.compatible import (
+ guide_manager_compatible_comp as gmcr,
+)
+
+importlib.reload(rc)
+importlib.reload(gmcr)
+
+SPECIAL_TYPES = ["EPIC", "lite"]
+
+
+def update_component_type_and_update_guide_with_dagmenu(*args):
+ """
+ Updates the component type of selected guide components and optionally refreshes the guide.
+ Provides a user interface for selecting related component types and filtering methods.
+
+ Features:
+ - Validates selected components and their types
+ - Provides filtering options for related components
+ - Updates component types while maintaining guide structure
+ - Optionally refreshes the guide template after update
+
+ """
+ roots = gmcr.get_comp_root()
+
+ if not roots:
+ pm.displayWarning("No components selected.")
+ return
+
+ if not gmcr.are_comp_names_identical(roots):
+ pm.displayWarning("Selected components are not of the same comp type.")
+ return
+
+ root_comp_type = roots[0].getAttr("comp_type")
+ if not isinstance(root_comp_type, str):
+ cmds.error(
+ f"Expected string type for comp_type, but got {type(root_comp_type).__name__}"
+ )
+ elif not root_comp_type:
+ cmds.error("comp_type is empty or invalid")
+ if not re.fullmatch(r"^[a-zA-Z]+(?:_[a-zA-Z0-9_-]+)?$", root_comp_type):
+ cmds.error(
+ f"Invalid format: '{root_comp_type}'\n"
+ "Correct format should be: BASE_TYPE or BASE_TYPE_SUB_TYPE\n"
+ "Examples: EPIC_spine or arm_2jnt"
+ )
+
+ type_parts = root_comp_type.split("_")
+ base_type = type_parts[0]
+ sub_type = type_parts[1] if len(type_parts) > 1 else ""
+ all_components = gmcr.get_component_list()
+
+ buttons = []
+ if base_type in SPECIAL_TYPES:
+ buttons = [
+ f"Only match '{base_type}' type",
+ f"Match all containing '{sub_type}' type",
+ "Cancel",
+ ]
+ else:
+ buttons = [
+ f"Only match '{base_type}' type",
+ f"Match all containing '{base_type}' type",
+ "Cancel",
+ ]
+
+ choice = pm.confirmDialog(
+ title="Select Related Component Scope",
+ message="Please select the scope of related components to include",
+ button=buttons,
+ defaultButton=f"Match all containing '{base_type}' type",
+ cancelButton="Cancel",
+ dismissString="Cancel",
+ )
+ if choice == "Cancel":
+ return
+
+ related_components = []
+ for component in all_components:
+ comp_parts = component.split("_")
+ if choice == f"Only match '{base_type}' type":
+ if base_type in SPECIAL_TYPES:
+ if (
+ len(comp_parts) > 1
+ and comp_parts[0] == base_type
+ and comp_parts[1] == sub_type
+ ):
+ related_components.append(component)
+ else:
+ if comp_parts[0] == base_type:
+ related_components.append(component)
+ else:
+ if base_type in SPECIAL_TYPES:
+ if len(comp_parts) > 1 and comp_parts[1] == sub_type:
+ related_components.append(component)
+ elif sub_type and sub_type in component:
+ related_components.append(component)
+ else:
+ if base_type in component:
+ related_components.append(component)
+
+ if not related_components:
+ pm.displayWarning(f"No components related to '{root_comp_type}' found.")
+ return
+
+ custom_window = rc.exec_window(related_components)
+ if not custom_window or not custom_window.result_components:
+ return
+
+ gmcr.set_selected_component_type_is_manager_current_selected_Component(
+ roots, custom_window.result_components
+ )
+
+ if custom_window.update_flag:
+ pm.select(roots)
+ guide_template.updateGuide()
+ pm.select(clear=True)
diff --git a/release/scripts/mgear/compatible/compatible_comp_ui.py b/release/scripts/mgear/compatible/compatible_comp_ui.py
new file mode 100644
index 00000000..7f944fb8
--- /dev/null
+++ b/release/scripts/mgear/compatible/compatible_comp_ui.py
@@ -0,0 +1,58 @@
+from mgear.vendor.Qt import QtCore, QtWidgets
+
+
+class Ui_Dialog(object):
+ def setupUi(self, Dialog):
+ Dialog.setObjectName("Dialog")
+ Dialog.resize(236, 113)
+ self.gridLayout = QtWidgets.QGridLayout(Dialog)
+ self.gridLayout.setObjectName("gridLayout")
+ self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
+ self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
+ self.buttonBox.setStandardButtons(
+ QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
+ )
+ self.buttonBox.setObjectName("buttonBox")
+ self.gridLayout.addWidget(self.buttonBox, 3, 0, 1, 1)
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.components_label = QtWidgets.QLabel(Dialog)
+ sizePolicy = QtWidgets.QSizePolicy(
+ QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred
+ )
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(
+ self.components_label.sizePolicy().hasHeightForWidth()
+ )
+ self.components_label.setSizePolicy(sizePolicy)
+ self.components_label.setObjectName("components_label")
+ self.horizontalLayout_2.addWidget(self.components_label)
+ self.components_comboBox = QtWidgets.QComboBox(Dialog)
+ self.components_comboBox.setObjectName("components_comboBox")
+ self.horizontalLayout_2.addWidget(self.components_comboBox)
+ self.gridLayout.addLayout(self.horizontalLayout_2, 0, 0, 1, 1)
+ spacerItem = QtWidgets.QSpacerItem(
+ 20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding
+ )
+ self.gridLayout.addItem(spacerItem, 4, 0, 1, 1)
+ self.update_checkBox = QtWidgets.QCheckBox(Dialog)
+ self.update_checkBox.setLayoutDirection(QtCore.Qt.RightToLeft)
+ self.update_checkBox.setObjectName("update_checkBox")
+ self.update_checkBox.setChecked(True)
+ self.gridLayout.addWidget(self.update_checkBox, 1, 0, 1, 1)
+
+ self.retranslateUi(Dialog)
+ self.buttonBox.accepted.connect(Dialog.accept)
+ self.buttonBox.rejected.connect(Dialog.reject)
+
+ def retranslateUi(self, Dialog):
+ Dialog.setWindowTitle(
+ QtWidgets.QApplication.translate("Dialog", "Dialog", None, -1)
+ )
+ self.components_label.setText(
+ QtWidgets.QApplication.translate("Dialog", "Related components:", None, -1)
+ )
+ self.update_checkBox.setText(
+ QtWidgets.QApplication.translate("Dialog", "Update Guide", None, -1)
+ )
diff --git a/release/scripts/mgear/compatible/compatible_comp_ui.ui b/release/scripts/mgear/compatible/compatible_comp_ui.ui
new file mode 100644
index 00000000..dd705b66
--- /dev/null
+++ b/release/scripts/mgear/compatible/compatible_comp_ui.ui
@@ -0,0 +1,107 @@
+
+
Draw selected component.
", None, -1)) self.draw_pushButton.setText(gqt.fakeTranslate("Form", "Draw Component", None, -1)) self.showUI_checkBox.setText(gqt.fakeTranslate("Form", "Show Setting After Create New Component.", None, -1)) + self.update_guide_checkBox.setText( + gqt.fakeTranslate( + "Form", + "Update Guide After Setting The Specified Component Type.", + None, + -1, + ) + ) + from mgear.core.widgets import DragQListView