# -*- coding: utf-8 -*- """ :author: Jeremy Ernst :description: This module contains a class that is a context menu for installed components in the scene. The context menu provides functions for manipulating the components. Things like copy/paste settings or transforms, duplicating, creating a mirror, mirroring transforms, renaming, deleting, etc. """ from artv2.third_party.Qt import QtWidgets, QtCore import artv2.utilities.component_utilities as component_utils from artv2.tools.rigging.rig_builder.mirror_component_widget import MirrorComponentWidget from artv2.tools.rigging.rig_builder.rename_widget import RenameComponentWidget from artv2.tools.rigging.rig_builder.set_parent_widget import SetParentWidget from artv2.tools.rigging.rig_builder.set_mirror_widget import SetMirrorWidget import artv2.utilities.interface_utilities as interface_utils import artv2.tools.system.logger.output_logger as logger import artv2.utilities.error_utilities as errors import pymel.core as pm class ComponentContextMenu(QtWidgets.QMenu): """ This class creates a custom QMenu that serves as a context menu for installed components in the scene. The context menu provides functions for manipulating the components. Things like copy/paste settings or transforms, duplicating, creating a mirror, mirroring transforms, renaming, deleting, etc. It is instantiated from the RigBuilderUI class when an item has a menu requested. :param metanode: the string name of the network node for that component, which can then be used to access that component's instance. :param list_widget: the instance of the InstalledComponentsWidget in the RigBuilderUI that contains the items. :param point: the coordinates of the cursor when the menu was requested. :param parent: the instance of the RigBuilderUI which will be this widget's parent. .. image:: /images/component_context.png """ component_added = QtCore.Signal() # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def __init__(self, metanode, list_widget, point, parent=None): super(ComponentContextMenu, self).__init__(parent) self.logger = logger.OutputLogger(self.__class__.__name__) self.setMinimumWidth(interface_utils.scale_by_dpi(200)) self.setMaximumWidth(interface_utils.scale_by_dpi(200)) self.metanode = pm.PyNode(metanode) self.list_widget = list_widget self.point = point self._parent = parent self._build_menu() # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _build_menu(self): copy_settings = QtWidgets.QAction("Copy Settings", self) copy_settings.triggered.connect(self._copy_settings) self.addAction(copy_settings) paste_settings = QtWidgets.QAction("Paste Settings", self) paste_settings.triggered.connect(self._paste_settings) self.addAction(paste_settings) reset_settings = QtWidgets.QAction("Reset Settings", self) reset_settings.triggered.connect(self._reset_settings) self.addAction(reset_settings) self.addSeparator() copy_transforms = QtWidgets.QAction("Copy Transforms", self) copy_transforms.triggered.connect(self._copy_transforms) self.addAction(copy_transforms) paste_transforms = QtWidgets.QAction("Paste Transforms", self) paste_transforms.triggered.connect(self._paste_transforms) self.addAction(paste_transforms) reset_transforms = QtWidgets.QAction("Reset Transforms", self) reset_transforms.triggered.connect(self._reset_transforms) self.addAction(reset_transforms) self.addSeparator() duplicate = QtWidgets.QAction("Duplicate", self) duplicate.triggered.connect(self._duplicate) self.addAction(duplicate) create_mirror = QtWidgets.QAction("Create Mirror of Component", self) create_mirror.triggered.connect(self._mirror_component) self.addAction(create_mirror) mirror_transforms = QtWidgets.QAction("Mirror Transforms", self) mirror_transforms.triggered.connect(self._mirror_transforms) self.addAction(mirror_transforms) bake_offsets = QtWidgets.QAction("Bake Offsets", self) bake_offsets.triggered.connect(self._bake_offsets) self.addAction(bake_offsets) self.addSeparator() change_name = QtWidgets.QAction("Rename", self) change_name.triggered.connect(self._rename_component) self.addAction(change_name) set_parent = QtWidgets.QAction("Set Parent", self) set_parent.triggered.connect(self._change_parent) self.addAction(set_parent) set_mirror = QtWidgets.QAction("Set Mirror Component", self) set_mirror.triggered.connect(self._set_mirror) self.addAction(set_mirror) delete = QtWidgets.QAction("Delete Component", self) delete.triggered.connect(self._delete) self.addAction(delete) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _copy_settings(self): self.logger.interface("{0}._copy_settings: Copying settings for {1}".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) inst.copy_settings() del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _paste_settings(self): self.logger.interface("{0}._paste_settings: Pasting settings for {1}".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) inst.paste_settings() del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _reset_settings(self): self.logger.interface("{0}._reset_settings: Resetting settings for {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) inst.reset_settings() del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _copy_transforms(self): self.logger.interface("{0}._copy_transforms: Copying transforms for {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) inst.joint_mover.copy_transforms() del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _paste_transforms(self): self.logger.interface("{0}._paste_transforms: Pasting transforms for {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) inst.joint_mover.paste_transforms() del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _bake_offsets(self): self.logger.interface("{0}._bake_offsets: Baking offsets on {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) inst.joint_mover.bake_offsets() del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _reset_transforms(self): self.logger.interface("{0}._reset_transforms: Resetting transforms for {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) inst.joint_mover.reset_movers("all") del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _duplicate(self): if self.metanode.parentComponentBone.get(): self.logger.interface("{0}._duplicate: Duplicating {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) new_inst = inst.duplicate() new_inst.joint_mover.aim_helper.toggle_aim_mode() self.component_added.emit() del inst else: errors.raise_error("Cannot create a duplicate of a root.") # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _mirror_component(self): self.logger.interface("{0}._mirror_component: Creating a mirror of {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) has_sides = inst.has_sides del inst if has_sides: widget = MirrorComponentWidget(self.metanode, self, self._parent) pos = self.point parent_position = self.list_widget.mapToGlobal(QtCore.QPoint(0, 0)) widget.move(parent_position + pos) widget.show() else: errors.raise_error("Cannot create a mirror of this component.") # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _mirror_transforms(self): self.logger.interface("{0}._mirror_transforms: Mirroring transforms for {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) inst.joint_mover.mirror_transforms() del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _rename_component(self): self.logger.interface("{0}._rename_component: Renaming {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) widget = RenameComponentWidget(self.metanode, self, self._parent) pos = self.point parent_position = self.list_widget.mapToGlobal(QtCore.QPoint(0, 0)) widget.move(parent_position + pos) widget.show() # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _change_parent(self): self.logger.interface("{0}._change_parent: Changing parent for {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) widget = SetParentWidget(self.metanode, self._parent) pos = self.point parent_position = self.list_widget.mapToGlobal(QtCore.QPoint(0, 0)) widget.move(parent_position + pos) widget.show() # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _set_mirror(self): self.logger.interface("{0}._set_mirror: Setting mirror component for {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) widget = SetMirrorWidget(self.metanode, self._parent) pos = self.point parent_position = self.list_widget.mapToGlobal(QtCore.QPoint(0, 0)) widget.move(parent_position + pos) widget.show() # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _delete(self): self.logger.interface("{0}._delete: Deleting {1}" "".format(self.__class__.__name__, self.metanode.componentName.get())) inst = component_utils.get_component_instance(self.metanode) inst.delete() self.component_added.emit() del inst