Source code for bgdev.utils.locators

"""Utility methods about locators.

:created: 05/03/2017
:author: Benoit GIELLY <benoit.gielly@gmail.com>
"""
from __future__ import absolute_import

import logging

import bgdev.utils.decorator
import bgdev.utils.vector
from maya import cmds
import pymel.core as pm

LOG = logging.getLogger(__name__)


[docs]@bgdev.utils.decorator.UNDO_REPEAT def create_aim_locator( middle=False, aim_vector=(1, 0, 0), up_vector=(0, 1, 0) ): """Create a locator that's oriented on the selection. If selection is 2 or 3, it will use the second as the aim axis, and the third as up. If middle is set to False, it will snap it to the first selected. Args: middle (bool): snap in between points 1 and 2 if True, else on point 1. aim_vector (tuple): default aim vector for the aimConstraint. up_vector (tuple): default up vector for the aimConstraint. Returns: str: The locator created. Raises: RuntimeError: If nothing is selected. """ # make sure orderedSelection is enabled if not cmds.selectPref(query=True, trackSelectionOrder=True): cmds.selectPref(trackSelectionOrder=True) cmds.select(clear=True) cmds.warning( "Selection Order was disabled. " "Please run the tool again!" ) return None # get selection selection = cmds.ls(orderedSelection=True, flatten=True) if not selection: raise RuntimeError("You must select at least 1 node or component!") # get matrix array matrix_array = bgdev.utils.vector.get_matrix_from_nodes( selection, middle, aim_vector, up_vector ) # create name string _split = selection[0].rsplit("_", 1)[0] if "." in selection[0]: _split = selection[0].rsplit(".", 1)[0].replace("Shape", "") name = _split + "_locator" if _split else selection[0] + "_locator" name = name + "#" if cmds.objExists(name) else name # create locator and set matrix locator = cmds.spaceLocator(name=name)[0] cmds.xform(locator, matrix=matrix_array, worldSpace=True) cmds.setAttr(locator + ".scale", 1, 1, 1) cmds.isolateSelect("modelPanel4", addDagObject=locator) # try to set locator scale distance = 2 try: furthest_node = bgdev.utils.vector.get_closest_point( locator, selection, furthest=True ) distance = bgdev.utils.vector.get_distance_between( locator, furthest_node ) except ValueError: pass if distance > 2: cmds.setAttr(locator + ".localScale", *[distance / 2.0] * 3) return locator
[docs]def locator_on_selection(method="matrix"): """Create and snap a locator on selected nodes. Args: method (str): "matrix" uses Maya's xform command with matrix flag enabled. "pivot" uses Maya's xform command with rotatePivot flag enabled. "manip" queries Maya's move manipulator position and orientation. """ # get selection selection = cmds.ls(selection=True, flatten=True) for each in selection: name = each + ("locator" if each.endswith("]") else "_locator") if cmds.objExists(name): name += "#" if method == "matrix": matrix = cmds.xform(each, query=True, matrix=True, worldSpace=True) locator = cmds.spaceLocator(name=name)[0] cmds.xform(locator, matrix=matrix, worldSpace=True) elif method == "translation": position = cmds.xform( each, query=True, worldSpace=True, translation=True ) rotation = cmds.xform( each, query=True, rotation=True, worldSpace=True ) locator = cmds.spaceLocator(name=name)[0] cmds.xform( locator, translation=position, rotation=rotation, worldSpace=True, ) elif method == "pivot": position = cmds.xform( each, query=True, worldSpace=True, rotatePivot=True ) rotation = cmds.xform( each, query=True, rotation=True, worldSpace=True ) locator = cmds.spaceLocator(name=name)[0] cmds.xform( locator, translation=position, rotation=rotation, worldSpace=True, ) elif method == "manip": position = cmds.manipMoveContext("Move", query=True, position=True) rotation = cmds.manipPivot(query=True, orientation=True)[0] locator = cmds.spaceLocator(name=name)[0] cmds.xform( locator, translation=position, rotation=rotation, worldSpace=True, ) else: continue # set locator scale furthest_node = bgdev.utils.vector.get_closest_point( locator, selection, furthest=True ) distance = ( bgdev.utils.vector.get_distance_between(locator, furthest_node) or 10 ) cmds.setAttr(locator + ".localScale", *[distance / 10.0] * 3) cmds.isolateSelect("modelPanel4", addDagObject=locator)
[docs]def attach_locators_to_curve(): """Attach a locator on each curve CVs.""" selection = pm.ls(selection=True) curve = [x for x in selection if x.getShape().type() == "nurbsCurve"][0] locator = [x for x in selection if x.getShape().type() != "nurbsCurve"] if not locator: for i, point in enumerate(curve.getShape().getCVs()): loc = pm.spaceLocator(name=curve + "{0:02d}_pos".format(i + 1)) pm.xform(loc, translation=point, worldSpace=True) locator.append(loc) for i, point in enumerate(curve.comp("point")): if locator: loc = bgdev.utils.vector.get_closest_point(point, locator) else: pos = point.getPosition(space="world") loc = pm.spaceLocator() loc.setTranslation(pos, space="world") shp = loc.getShape() shp.wp[0] >> curve.cp[i] # pylint: disable=pointless-statement