both_constrain

both_constrain
一つのオブジェクトに両手を追随させて、両手持ちっぽく見せるツール


.py実行ファイルのダウンロードリンクは以下

https://mega.nz/file/6iBCSJoS#3rJcBmbcrSDcN1AQPKxsumY9gt2hcyND5DhLo_CX_YQ


```

# -*- coding: utf-8 -*-
from maya import OpenMayaUI
from PySide2 import QtWidgets, QtCore
import shiboken2 as shiboken
import maya.cmds as cmds

ptr = OpenMayaUI.MQtUtil.mainWindow()
parent = shiboken.wrapInstance(int(ptr), QtWidgets.QMainWindow)

# UIの書式設定
class LocatorGUI(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(LocatorGUI, self).__init__(parent)

        self.setWindowTitle("both constrain")
        self.resize(300, 200)

        self.central_widget = QtWidgets.QWidget()
        self.setCentralWidget(self.central_widget)

        self.main_layout = QtWidgets.QVBoxLayout(self.central_widget)

        # Step1 GroupBoxの書式設定
        self.step1_group = QtWidgets.QGroupBox("Step1")
        self.step1_layout = QtWidgets.QVBoxLayout(self.step1_group)
        self.select_object_button = QtWidgets.QPushButton("オブシェクトを指定")
        self.select_object_button.clicked.connect(self.select_object)
        self.confirm_button = QtWidgets.QPushButton("確定")
        self.confirm_button.setEnabled(False)
        self.confirm_button.clicked.connect(self.confirm_object)

        self.step1_layout.addWidget(QtWidgets.QLabel("一つのオブシェクトを指定し、確定を押下して下さい"))
        self.step1_layout.addWidget(self.select_object_button)
        self.step1_layout.addWidget(self.confirm_button)

        self.step1_group.setLayout(self.step1_layout)

        # Step2 GroupBoxの書式設定
        self.step2_group = QtWidgets.QGroupBox("Step2")
        self.step2_layout = QtWidgets.QVBoxLayout(self.step2_group)
        self.strong_button = QtWidgets.QPushButton("Strong")
        self.strong_button.setEnabled(False)
        self.strong_button.clicked.connect(self.strong_object)
        self.weak_button = QtWidgets.QPushButton("Weak")
        self.weak_button.setEnabled(False)
        self.weak_button.clicked.connect(self.weak_object)

        self.step2_layout.addWidget(QtWidgets.QLabel("Strong＝利き手を指定してください"))
        self.step2_layout.addWidget(self.strong_button)
        self.step2_layout.addWidget(QtWidgets.QLabel("Weak＝添える手を指定してください"))

        self.step2_layout.addWidget(self.weak_button)

        self.step2_group.setLayout(self.step2_layout)

        self.main_layout.addWidget(self.step1_group)
        self.main_layout.addWidget(self.step2_group)
        # グループボックスの余白、色指定
        self.setStyleSheet(
            '''
            QGroupBox {
                border: 2px solid #256d7b;
                border-radius: 6px;
                margin-top: 2em;
                font-size: 12px;
            }

            QGroupBox::title {
                color: #fff;
                background-color: #256d7b;
                subcontrol-origin: margin;
                padding: 0.5em 0.7em;
                border-top-left-radius: 6px;
                border-top-right-radius: 6px;
            }
            '''
        )

    def select_object(self):
        selected_objects = cmds.ls(selection=True, dag=True)
        if not selected_objects:
            cmds.warning("Please select an object.")
            return
        self.selected_object = selected_objects[0]
        self.confirm_button.setEnabled(True) #ボタンのグレイアウトを解除

    def confirm_object(self):
        try:
            selected_object = self.selected_object
        except AttributeError:
            cmds.warning("Please select an object.")
            return

        group = cmds.group(selected_object, name=selected_object + "_group")
        bbox = cmds.exactWorldBoundingBox(selected_object)
        bbox_center = [(bbox[0] + bbox[3]) / 2, (bbox[1] + bbox[4]) / 2, (bbox[2] + bbox[5]) / 2]

        self.strong_locator = cmds.spaceLocator(name=selected_object + "_strong")[0]
        cmds.parent(self.strong_locator, selected_object)
        cmds.move(bbox_center[0], bbox_center[1], bbox_center[2], self.strong_locator)

        self.weak_locator = cmds.spaceLocator(name=selected_object + "_weak")[0]
        cmds.parent(self.weak_locator, self.strong_locator)
        cmds.xform(self.weak_locator, translation=bbox_center, worldSpace=True)

        self.strong_button.setEnabled(True) #ボタンのグレイアウトを解除


    def strong_object(self):
        selected_objects = cmds.ls(selection=True, type="transform")
        if not selected_objects:
            cmds.warning("Please select an object to constrain to the strong locator.")
            return
        selected_strong_object = selected_objects[0]

        try:
            strong_locator = self.strong_locator
        except AttributeError:
            cmds.warning("Strong locator not found. Please confirm the initial object.")
            return

        cmds.parentConstraint(strong_locator, selected_strong_object, mo=False)
        self.weak_button.setEnabled(True) #ボタンのグレイアウトを解除

    def weak_object(self):
        selected_objects = cmds.ls(selection=True, type="transform")
        if not selected_objects:
            cmds.warning("Please select an object to constrain to the weak locator.")
            return
        selected_weak_object = selected_objects[0]

        try:
            weak_locator = self.weak_locator
        except AttributeError:
            cmds.warning("Weak locator not found. Please confirm the initial object.")
            return

        cmds.parentConstraint(weak_locator, selected_weak_object, mo=False)

        self.confirm_button.setEnabled(False) #ボタンを再度グレイアウト
        self.strong_button.setEnabled(False)
        self.weak_button.setEnabled(False)

        self.selected_object = None # 選択したオブジェクトのリスト・インスタンス変数をリセット

def main():
    locator_gui = LocatorGUI(parent)
    locator_gui.show()

main()


```