# -*- coding: utf-8 -*- """ :author: Jeremy Ernst :description: This module contains a class for creating a user interface for storing new bind poses, removing bind poses, and setting the active bind pose. """ import json from functools import partial import os import artv2.utilities.interface_utilities as interface_utils import artv2.utilities.component_utilities as component_utils import artv2.utilities.general_utilities as utils from artv2.third_party.Qt import QtWidgets, QtCore import artv2.tools.system.logger.output_logger as logger import artv2.components.base_components.rig_asset as rig import pymel.core as pm # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # class PoseManagerUI(interface_utils.ARTv2Window): """ Creates a user interface that allows the user to create new bind poses, set the active bind pose, or remove bind poses. This is invoked from the RigBuilderUI toolbar. :param parent: the instance of the RigBuilderUI this widget will be parented to. .. figure:: /images/pose_manager_overview.gif :width: 717px :align: center :height: 557px :figclass: align-center this example shows two poses that have been saved with the pose manager. One for the pose the model was delivered in and one for the pose we want to build the rig in. """ SETTINGS_NAME = "PoseManagerWIN" WINDOW_NAME = "artv2_pose_manager_window" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def __init__(self, parent=None): super(PoseManagerUI, self).__init__(194, 236, "Pose Manager", parent) self.logger = logger.OutputLogger(self.__class__.__name__) self.parent_inst = parent self.contents_layout = None self.scroll_contents = None self.scroll_area = None self._build_interface() self._populate_scroll() # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _build_interface(self): menu_bar = self.menuBar() menu = menu_bar.addMenu("Help") menu.addAction("Documentation", self._launch_help) main_widget = QtWidgets.QWidget() self.main_layout = QtWidgets.QVBoxLayout(main_widget) self.setCentralWidget(main_widget) self._build_scroll_layout() button = QtWidgets.QPushButton("Save New Pose") button.clicked.connect(self._save_pose) self.main_layout.addWidget(button) asset = component_utils.get_rig_asset_node() if asset.has_skeleton.get(): button.setEnabled(False) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _build_scroll_layout(self): self.scroll_contents = QtWidgets.QFrame() self.scroll_contents.setObjectName("light") self.scroll_contents.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.scroll_area = QtWidgets.QScrollArea() self.main_layout.addWidget(self.scroll_area) self.scroll_area.setWidgetResizable(True) self.scroll_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) self.scroll_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.scroll_area.setWidget(self.scroll_contents) self.contents_layout = QtWidgets.QVBoxLayout(self.scroll_contents) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _populate_scroll(self): poses = self._get_poses() if poses: for each in poses: self._add_pose_widget(each) spacer = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.contents_layout.addSpacerItem(spacer) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _add_pose_widget(self, name): layout = QtWidgets.QHBoxLayout() layout.setSpacing(2) self.contents_layout.addLayout(layout) pose_button = QtWidgets.QPushButton(name) pose_button.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) pose_button.customContextMenuRequested.connect(partial(self._context_menu, pose_button)) pose_button.clicked.connect(partial(self._set_pose, pose_button)) layout.addWidget(pose_button) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _context_menu(self, button, point): menu = QtWidgets.QMenu(self) menu.addAction("Remove Pose", partial(self._remove_pose, button)) parent_position = button.mapToGlobal(QtCore.QPoint(0, 0)) menu.move(parent_position + point) menu.exec_() # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _set_pose(self, button): name = button.text() self.logger.interface("{0}._set_pose: Setting pose {1}".format(self.__class__.__name__, name)) asset = component_utils.get_rig_asset_node() asset_instance = rig.RigAsset(network_node=asset.name()) asset_instance.load_dag_pose(name) del asset_instance # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _remove_pose(self, button): name = button.text() self.logger.interface("{0}._remove_pose: Removing pose {1}".format(self.__class__.__name__, name)) asset = component_utils.get_rig_asset_node() asset_instance = rig.RigAsset(network_node=asset.name()) asset_instance.remove_dag_pose(name) interface_utils.clear_layout(self.contents_layout) self._populate_scroll() del asset_instance # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _save_pose(self): name, okay = QtWidgets.QInputDialog.getText(self, "Add Pose", "Pose Name:", QtWidgets.QLineEdit.Normal, "") if okay and name: self.logger.interface("{0}._save_pose: Saving pose {1}".format(self.__class__.__name__, name)) asset = component_utils.get_rig_asset_node() asset_instance = rig.RigAsset(network_node=asset.name()) asset_instance.save_dag_pose(name) interface_utils.clear_layout(self.contents_layout) self._populate_scroll() del asset_instance # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @staticmethod def _get_poses(): asset = component_utils.get_rig_asset_node() if asset.hasAttr("dag_poses"): pose_data = json.loads(asset.dag_poses.get()) return pose_data return None # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @staticmethod def _launch_help(): html_file = os.path.join(utils.return_settings()[0], "docs", "build", "sections", "rigging_tools", "pose_manager.html") utils.launch_web_docs(html_file) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def show_window(parent): """ Shows the PoseManagerUI instance """ if pm.window("artv2_pose_manager_window", exists=True): pm.deleteUI("artv2_pose_manager_window") gui = PoseManagerUI(parent) gui.show()