Source code for bgdev.utils.controler

"""Utilities for controlers.

Mostly, controler shapes creation (needs to be turned into data)

:author: Benoit GIELLY <benoit.gielly@gmail.com>
"""
from __future__ import print_function

import logging
import os

import bgdev.utils.color
from maya import cmds
import yaml

LOG = logging.getLogger(__name__)


[docs]def select_all(): """Select all controlers in the current scene.""" nodes = get_all_controls() + get_all_controls("*") cmds.select(nodes)
[docs]def select_rig_controls(): """Select all controlers from selected rig(s).""" nodes = get_rig_controls() cmds.select(nodes)
[docs]def get_all_controls(namespace=""): """Get all rig controlers in the scene.""" controlers = set() # get controls using CONTROLS set if cmds.objExists(namespace + ":CONTROLS"): controlers.update(cmds.sets(namespace + ":CONTROLS", query=True) or []) # get controlers using suffix controlers.update(cmds.ls(namespace + ":*_ctrl")) # get controlers using TSM3 attribute for ctrl in cmds.ls(namespace + ":*.TSM3Control"): controlers.add(ctrl.split(".")[0]) for ctrl in cmds.ls(namespace + ":*TSM3_root"): controlers.add(ctrl.split(".")[0]) return sorted(controlers)
[docs]def get_rig_controls(): """Query all controlers of the selected rig(s).""" ctrls = [] selection = cmds.ls(selection=True) if not selection: LOG.warning("Please, select any node from a rig!") return ctrls namespaces = list({x.rpartition(":")[0] for x in selection}) for each in namespaces: ctrls.extend(get_all_controls(each)) return ctrls
[docs]def get_ctrl_data(name, variant=0): """Query the controler data from its name.""" path = os.path.join( os.path.dirname(__file__), "controlers", name + ".yaml" ) if not os.path.exists(path): msg = ( "%r doesn't exists. " "You can list them using the `list_controlers()` method." ) LOG.warning(msg, name) return None with open(path, "r") as stream: data = yaml.load(stream) return data.get("variant%s" % variant)
[docs]def list_controlers(): """List all the available controls.""" path = os.path.join(os.path.dirname(__file__), "controlers") ctrls = [] for each in os.listdir(path): if each.endswith(".yaml"): ctrls.append(os.path.join(path, each)) msg = "\nAvailable controls are (variants, name):\n" for each in ctrls: with open(each, "r") as stream: data = yaml.load(stream) name = os.path.splitext(os.path.basename(each))[0] msg += "\t%s %r\n" % (len(data), name) print(msg)
[docs]def create_control( # pylint: disable=too-many-arguments ctrl, variant=0, name=None, size=1.0, normal=(0, 1, 0), color="yellow" ): """Create a controler based on its name and variant. Args: ctrl (str): The type of controler you want to create. Use :func:`list_controlers` method to know which ones are available. variant (int): Which variant of the controler type you want. name (str): Rename the controler with the given name. size (float): Scale the controler using given size value. normal (tuple): Which axis should the controler aim to when created. Default axis is +Y color (str): The name of the CSS color to apply as an RGB override. Uses the PySide2 StyleSheet API to convert names to RGB color. Returns: tuple: The controler and its shape. """ flags = get_ctrl_data(ctrl, variant) if not flags: return None curve = cmds.curve(**flags) curve = cmds.rename(curve, name or ctrl + "1") shape = cmds.listRelatives(curve, shapes=True)[0] cmds.scale(*[size] * 3 + [curve + ".cv[*]"], relative=True) # swap X and Z (Y being the default normal-axis for all shapes) normal = normal[-1], normal[1], normal[0] normal = [x * 90 for x in normal] cmds.rotate(*normal + [curve + ".cv[*]"], relative=True) curve = cmds.rename(curve, name or ctrl + "1") shape = cmds.listRelatives(curve, shapes=True)[0] # set shape color rgba = bgdev.utils.color.convert_css_color(color) cmds.setAttr(shape + ".overrideEnabled", True) cmds.setAttr(shape + ".overrideRGBColors", True) cmds.setAttr(shape + ".overrideColorRGB", *rgba) return curve, shape