def set_data(self, value): """ Set the internal frame data using once function call. Expected data structure is:: { 'number': int or float, 'tags': list of strs, } :param value: Data structure with both 'number' and 'tags' keys. :type value: dict :return: None """ assert isinstance(value, dict) num = value.get('number') tags = value.get('tags') if num is None: msg = 'Data is not valid, number value not valid; {0}' msg = msg.format(value) raise excep.NotValid(msg) if tags is None: msg = 'Data is not valid, tags value not valid; {0}' msg = msg.format(value) raise excep.NotValid(msg) self.set_number(num) self.set_tags(tags) return
def _compile(self, prog_fn=None, status_fn=None): """ Take the data in this class and compile it into keyword argument flags. :return: list of keyword arguments. :rtype: list of dict """ # TODO: Cache the compiled result internally to speed up # 'is_valid' then '_compile' calls. # If the class attributes haven't been changed, re-use the previously # generated arguments. if len(self._kwargs_list) > 0: return self._kwargs_list # Re-compile the arguments. kwargs_list = [] col_node = self.get_node() # Check Solvers sol_list = self.get_solver_list() sol_enabled_list = filter(lambda x: x.get_enabled() is True, sol_list) if len(sol_enabled_list) == 0: msg = 'Collection is not valid, no enabled Solvers given; ' msg += 'collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Check Markers mkr_list = self.get_marker_list() if len(mkr_list) == 0: msg = 'Collection is not valid, no Markers given; collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Check Attributes attr_list = self.get_attribute_list() if len(attr_list) == 0: msg = 'Collection is not valid, no Attributes given; collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Compile all the solvers for sol in sol_enabled_list: if sol.get_frame_list_length() == 0: raise excep.NotValid(msg) kwargs = self.__compile_solver(sol, mkr_list, attr_list) if isinstance(kwargs, dict): kwargs_list.append(kwargs) else: msg = 'Collection is not valid, failed to compile solver;' msg += ' collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Set arguments self._kwargs_list = kwargs_list # save a copy return self._kwargs_list
def collection_compile(col_node, sol_list, mkr_list, attr_list, withtest=False, prog_fn=None, status_fn=None): """ Take the data in this class and compile it into actions to run. :return: list of SolverActions. :rtype: [SolverAction, ..] """ action_list = [] vaction_list = [] if len(sol_list) == 0: msg = 'Collection is not valid, no Solvers given; ' msg += 'collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) sol_enabled_list = [sol for sol in sol_list if sol.get_enabled() is True] if len(sol_enabled_list) == 0: msg = 'Collection is not valid, no enabled Solvers given; ' msg += 'collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) if len(mkr_list) == 0: msg = 'Collection is not valid, no Markers given; collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) if len(attr_list) == 0: msg = 'Collection is not valid, no Attributes given; collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Compile all the solvers msg = 'Collection is not valid, failed to compile solver;' msg += ' collection={0}' msg = msg.format(repr(col_node)) for sol in sol_enabled_list: assert isinstance(sol, solverbase.SolverBase) for action, vaction in sol.compile(mkr_list, attr_list, withtest=withtest): if not isinstance(action, api_action.Action): raise excep.NotValid(msg) assert action.func is not None assert action.args is not None assert action.kwargs is not None action_list.append(action) vaction_list.append(vaction) assert len(action_list) == len(vaction_list) return action_list, vaction_list
def _link_to_marker_group(self, mkr_grp): """ Parent a marker under a Marker Group. """ assert isinstance(mkr_grp, markergroup.MarkerGroup) mkr_node = self.get_node() mkr_grp_node = mkr_grp.get_node() # Make sure the camera is valid for us to link to. if mkr_grp.is_valid() is False: msg = 'Cannot link Marker to Marker Group; Marker Group is not valid.' msg += ' marker={0} marker group={1}' msg = msg.format(repr(mkr_node), repr(mkr_grp_node)) raise excep.NotValid(msg) # Check if we're trying to link the the camera that we're already # linked to. current_mkr_grp = self.get_marker_group() if current_mkr_grp is not None: assert isinstance(current_mkr_grp, markergroup.MarkerGroup) current_mkr_grp = current_mkr_grp.get_node() if current_mkr_grp == mkr_grp_node: msg = 'Marker is already linked to Marker Group, skipping.' msg += ' marker={0} marker group={1}' msg = msg.format(repr(mkr_node), repr(mkr_grp_node)) raise excep.AlreadyLinked(msg) # Move the marker under the marker group, make sure the relative # marker attribute values are maintained. maya.cmds.parent(mkr_node, mkr_grp_node, relative=True) return
def _link_to_camera(self, cam): """ Parent a marker under the marker group which is under the given camera. If there is no marker group, one is created. :param cam: The camera to connect this Marker to. :type cam: None or Camera :returns: None """ assert isinstance(cam, camera.Camera) mkr_node = self.get_node() if mkr_node is None: LOG.warn('Could not get Marker node. self=%r', self) return cam_tfm = cam.get_transform_node() cam_shp = cam.get_shape_node() # Make sure the camera is valid for us to link to. if cam.is_valid() is False: msg = 'Cannot link Marker to Camera; Camera is not valid.' msg += ' marker={0} camera={1}' msg = msg.format(repr(mkr_node), repr(cam_shp)) raise excep.NotValid(msg) # Check if we're trying to link the the camera that we're already # linked to. current_cam = self.get_camera() if current_cam is not None: assert isinstance(current_cam, camera.Camera) current_cam_shp = current_cam.get_shape_node() if current_cam_shp == cam_shp: msg = 'Marker is already linked to camera, skipping.' msg += ' marker={0} camera={1}' msg = msg.format(repr(mkr_node), repr(cam_shp)) raise excep.AlreadyLinked(msg) # Create Marker Group mkr_grp = None mkr_grp_nodes = maya.cmds.ls(cam_tfm, dag=True, long=True, type='mmMarkerGroupTransform') or [] mkr_grp_nodes = sorted(mkr_grp_nodes) if len(mkr_grp_nodes) == 0: mkr_grp = markergroup.MarkerGroup().create_node(cam=cam) else: mkr_grp = markergroup.MarkerGroup(node=mkr_grp_nodes[0]) # Link to Marker Group self.set_marker_group(mkr_grp) return
def add_frame(self, frm): assert isinstance(frm, frame.Frame) key = 'frame_list' frm_list_data = self._data.get(key) if frm_list_data is None: frm_list_data = [] # check we won't get a double up. add_frm_data = frm.get_data() for frm_data in frm_list_data: if frm_data.get('number') == add_frm_data.get('number'): msg = 'Frame already added to the solver, cannot add again: {0}' msg = msg.format(add_frm_data) raise excep.NotValid(msg) frm_list_data.append(add_frm_data) self._data[key] = frm_list_data return
def attributes_compile_flags(attr_list, use_animated, use_static): # Get Attributes attrs = [] for attr in attr_list: assert isinstance(attr, attribute.Attribute) if attr.is_locked(): continue name = attr.get_name() node_name = attr.get_node() attr_name = attr.get_attr() # If the user does not specify a min/max value then we get it # from Maya directly, if Maya doesn't have one, we leave # min/max_value as None and pass it to the mmSolver command # indicating there is no bound. min_value = attr.get_min_value() max_value = attr.get_max_value() if min_value is None: min_exists = maya.cmds.attributeQuery( attr_name, node=node_name, minExists=True, ) if min_exists: min_value = maya.cmds.attributeQuery( attr_name, node=node_name, minimum=True, ) if len(min_value) == 1: min_value = min_value[0] else: msg = 'Cannot handle attributes with multiple ' msg += 'minimum values; node={0} attr={1}' msg = msg.format(node_name, attr_name) raise excep.NotValid(msg) if max_value is None: max_exists = maya.cmds.attributeQuery( attr_name, node=node_name, maxExists=True, ) if max_exists is True: max_value = maya.cmds.attributeQuery( attr_name, node=node_name, maximum=True, ) if len(max_value) == 1: max_value = max_value[0] else: msg = 'Cannot handle attributes with multiple ' msg += 'maximum values; node={0} attr={1}' msg = msg.format(node_name, attr_name) raise excep.NotValid(msg) # Scale and Offset scale_value = None offset_value = None attr_type = maya.cmds.attributeQuery(attr_name, node=node_name, attributeType=True) if attr_type.endswith('Angle'): offset_value = 360.0 animated = attr.is_animated() static = attr.is_static() use = False if use_animated and animated is True: use = True if use_static and static is True: use = True if use is True: attrs.append((name, str(min_value), str(max_value), str(offset_value), str(scale_value))) return attrs
def _compile(self, prog_fn=None, status_fn=None): """ Take the data in this class and compile it into keyword argument flags. :return: list of keyword arguments. :rtype: list of dict """ # TODO: Cache the compiled result internally to speed up # 'is_valid' then '_compile' calls. # If the class attributes haven't been changed, re-use the previously # generated arguments. if len(self._kwargs_list) > 0: return self._kwargs_list # Re-compile the arguments. kwargs_list = [] col_node = self.get_node() # Check Solvers sol_list = self.get_solver_list() sol_enabled_list = [sol for sol in sol_list if sol.get_enabled() is True] if len(sol_enabled_list) == 0: msg = 'Collection is not valid, no enabled Solvers given; ' msg += 'collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Check Markers mkr_list = self.get_marker_list() if len(mkr_list) == 0: msg = 'Collection is not valid, no Markers given; collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Check Attributes attr_list = self.get_attribute_list() if len(attr_list) == 0: msg = 'Collection is not valid, no Attributes given; collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Compile all the solvers for i, sol in enumerate(sol_enabled_list): if sol.get_frame_list_length() == 0: msg = 'Collection is not valid, no frames to solve;' msg += ' collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) kwargs = self.__compile_solver(sol, mkr_list, attr_list) debug_file = maya.cmds.file(query=True, sceneName=True) debug_file = os.path.basename(debug_file) debug_file, ext = os.path.splitext(debug_file) # TODO: Find a way to set the default directory path. debug_file_path = os.path.join( os.path.expanduser('~/'), debug_file + '_' + str(i).zfill(6) + '.log') if len(debug_file) > 0 and debug_file_path is not None: kwargs['debugFile'] = debug_file_path if isinstance(kwargs, dict): kwargs_list.append(kwargs) else: msg = 'Collection is not valid, failed to compile solver;' msg += ' collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Set arguments self._kwargs_list = kwargs_list # save a copy return self._kwargs_list
def __compile_solver(self, sol, mkr_list, attr_list, prog_fn=None): """ Compiles data given into flags for a single run of 'mmSolver'. :param sol: The solver to compile :type sol: Solver :param mkr_list: Markers to measure :type mkr_list: list of Marker :param attr_list: Attributes to solve for :type attr_list: list of Attribute :param prog_fn: Progress Function, with signature f(int) :type prog_fn: function :return: The keyword arguments for the mmSolver command. :rtype: None or dict """ assert isinstance(sol, solver.Solver) assert isinstance(mkr_list, list) assert isinstance(attr_list, list) assert sol.get_frame_list_length() > 0 kwargs = dict() kwargs['camera'] = [] kwargs['marker'] = [] kwargs['attr'] = [] kwargs['frame'] = [] # Get Markers and Cameras added_cameras = [] markers = [] cameras = [] for mkr in mkr_list: assert isinstance(mkr, marker.Marker) mkr_node = mkr.get_node() assert isinstance(mkr_node, basestring) bnd = mkr.get_bundle() if bnd is None: msg = 'Cannot find bundle from marker, skipping; mkr_node={0}' msg = msg.format(repr(mkr_node)) LOG.warning(msg) continue bnd_node = bnd.get_node() if bnd_node is None: msg = 'Bundle node is invalid, skipping; mkr_node={0}' msg = msg.format(repr(mkr_node)) LOG.warning(msg) continue cam = mkr.get_camera() if cam is None: msg = 'Cannot find camera from marker; mkr={0}' msg = msg.format(mkr.get_node()) LOG.warning(msg) cam_tfm_node = cam.get_transform_node() cam_shp_node = cam.get_shape_node() assert isinstance(cam_tfm_node, basestring) assert isinstance(cam_shp_node, basestring) markers.append((mkr_node, cam_shp_node, bnd_node)) if cam_shp_node not in added_cameras: cameras.append((cam_tfm_node, cam_shp_node)) added_cameras.append(cam_shp_node) if len(markers) == 0: LOG.warning('No Markers found!') return None if len(cameras) == 0: LOG.warning('No Cameras found!') return None # Get Attributes use_animated = sol.get_attributes_use_animated() use_static = sol.get_attributes_use_static() attrs = [] for attr in attr_list: assert isinstance(attr, attribute.Attribute) if attr.is_locked(): continue name = attr.get_name() node_name = attr.get_node() attr_name = attr.get_attr() # If the user does not specify a min/max value then we get it # from Maya directly, if Maya doesn't have one, we leave # min/max_value as None and pass it to the mmSolver command # indicating there is no bound. min_value = attr.get_min_value() max_value = attr.get_max_value() if min_value is None: min_exists = maya.cmds.attributeQuery( attr_name, node=node_name, minExists=True, ) if min_exists: min_value = maya.cmds.attributeQuery( attr_name, node=node_name, minimum=True, ) if len(min_value) == 1: min_value = min_value[0] else: msg = 'Cannot handle attributes with multiple ' msg += 'minimum values; node={0} attr={1}' msg = msg.format(node_name, attr_name) raise excep.NotValid(msg) if max_value is None: max_exists = maya.cmds.attributeQuery( attr_name, node=node_name, maxExists=True, ) if max_exists is True: max_value = maya.cmds.attributeQuery( attr_name, node=node_name, maximum=True, ) if len(max_value) == 1: max_value = max_value[0] else: msg = 'Cannot handle attributes with multiple ' msg += 'maximum values; node={0} attr={1}' msg = msg.format(node_name, attr_name) raise excep.NotValid(msg) animated = attr.is_animated() static = attr.is_static() use = False if use_animated and animated is True: use = True if use_static and static is True: use = True if use is True: attrs.append((name, str(min_value), str(max_value))) if len(attrs) == 0: LOG.warning('No Attributes found!') return None # Get Frames frm_list = sol.get_frame_list() frame_use_tags = sol.get_frames_use_tags() frames = [] for frm in frm_list: num = frm.get_number() tags = frm.get_tags() use = False if len(frame_use_tags) > 0 and len(tags) > 0: for tag in frame_use_tags: if tag in tags: use = True break else: use = True if use is True: frames.append(num) if len(frames) == 0: LOG.warning('No Frames found!') return None kwargs['marker'] = markers kwargs['camera'] = cameras kwargs['attr'] = attrs kwargs['frame'] = frames solver_type = sol.get_solver_type() if solver_type is not None: kwargs['solverType'] = solver_type iterations = sol.get_max_iterations() if iterations is not None: kwargs['iterations'] = iterations verbose = sol.get_verbose() if verbose is not None: kwargs['verbose'] = verbose delta_factor = sol.get_delta_factor() if delta_factor is not None: kwargs['delta'] = delta_factor auto_diff_type = sol.get_auto_diff_type() if auto_diff_type is not None: kwargs['autoDiffType'] = auto_diff_type tau_factor = sol.get_tau_factor() if tau_factor is not None: kwargs['tauFactor'] = tau_factor gradient_error_factor = sol.get_gradient_error_factor() if gradient_error_factor is not None: kwargs['epsilon1'] = gradient_error_factor parameter_error_factor = sol.get_parameter_error_factor() if parameter_error_factor is not None: kwargs['epsilon2'] = parameter_error_factor error_factor = sol.get_error_factor() if error_factor is not None: kwargs['epsilon3'] = error_factor # msg = 'kwargs:\n' + pprint.pformat(kwargs) # LOG.debug(msg) return kwargs
def create_node(self, name='marker1', colour=None, cam=None, mkr_grp=None, bnd=None): """ Create a marker node network from scratch. :param name: Name of the marker to create. :type name: str :param colour: Colour of marker as R, G and B. 'None' will leave as default. :type colour: (float, float, float) or None :param cam: The camera to create the marker underneath. :type cam: Camera :param mkr_grp: The marker group to create the marker underneath. :type mkr_grp: MarkerGroup :param bnd: The bundle to attach to the newly created marker. :type bnd: Bundle :return: Marker object with newly created node. :rtype: Marker """ assert isinstance(name, (str, unicode)) if cam is not None: if mkr_grp is not None: msg = 'Cannot specify both camera and marker group, ' msg += 'please choose only one.' raise excep.NotValid(msg) assert isinstance(cam, camera.Camera) if mkr_grp is not None: if cam is not None: msg = 'Cannot specify both camera and marker group, ' msg += 'please choose only one.' raise excep.NotValid(msg) assert isinstance(mkr_grp, markergroup.MarkerGroup) if bnd is not None: assert isinstance(bnd, mmSolver._api.bundle.Bundle) if colour is not None: assert isinstance(colour, (tuple, list)) assert len(colour) == 3 # Transform tfm = maya.cmds.createNode(const.MARKER_TRANSFORM_NODE_TYPE, name=name) tfm = node_utils.get_long_name(tfm) maya.cmds.setAttr(tfm + '.tz', -1.0) maya.cmds.setAttr(tfm + '.tz', lock=True) maya.cmds.setAttr(tfm + '.rx', lock=True) maya.cmds.setAttr(tfm + '.ry', lock=True) maya.cmds.setAttr(tfm + '.rz', lock=True) maya.cmds.setAttr(tfm + '.sx', lock=True) maya.cmds.setAttr(tfm + '.sy', lock=True) maya.cmds.setAttr(tfm + '.sz', lock=True) maya.cmds.setAttr(tfm + '.shxy', lock=True) maya.cmds.setAttr(tfm + '.shxz', lock=True) maya.cmds.setAttr(tfm + '.shyz', lock=True) maya.cmds.setAttr(tfm + '.tz', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.rx', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.ry', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.rz', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.sx', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.sy', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.sz', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.shxy', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.shxz', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.shyz', keyable=False, channelBox=False) # Shape Node shp_name = tfm.rpartition('|')[-1] + 'Shape' shp = maya.cmds.createNode(const.MARKER_SHAPE_NODE_TYPE, name=shp_name, parent=tfm) maya.cmds.setAttr(shp + '.localScaleX', 0.01) maya.cmds.setAttr(shp + '.localScaleY', 0.01) maya.cmds.setAttr(shp + '.localScaleZ', 0.0) maya.cmds.setAttr(shp + '.localScaleZ', lock=True) # Add attrs _create_marker_attributes(tfm) src = '{0}.{1}'.format(tfm, const.MARKER_ATTR_LONG_NAME_ENABLE) dst = '{0}.{1}'.format(tfm, 'lodVisibility') maya.cmds.connectAttr(src, dst) self.set_node(tfm) # Set Colour (default is red) if colour is not None: self.set_colour_rgb(colour) else: red = (1.0, 0.0, 0.0) self.set_colour_rgb(red) # Link to Camera if cam is not None: self.set_camera(cam) # Link to MarkerGroup if mkr_grp is not None: self.set_marker_group(mkr_grp) # Link to Bundle if bnd is not None: self.set_bundle(bnd) return self
def create_node(self, name='marker1', colour=None, cam=None, mkr_grp=None, bnd=None): """ Create a marker node network from scratch. :param name: Name of the marker to create. :type name: str :param colour: Colour of marker as R, G and B. 'None' will leave as default. :type colour: (float, float, float) or None :param cam: The camera to create the marker underneath. :type cam: Camera :param mkr_grp: The marker group to create the marker underneath. :type mkr_grp: MarkerGroup :param bnd: The bundle to attach to the newly created marker. :type bnd: Bundle :return: Marker object with newly created node. :rtype: Marker """ assert isinstance(name, (str, unicode)) if cam is not None: if mkr_grp is not None: msg = 'Cannot specify both camera and marker group, ' msg += 'please choose only one.' raise excep.NotValid(msg) assert isinstance(cam, camera.Camera) if mkr_grp is not None: if cam is not None: msg = 'Cannot specify both camera and marker group, ' msg += 'please choose only one.' raise excep.NotValid(msg) assert isinstance(mkr_grp, markergroup.MarkerGroup) if bnd is not None: assert isinstance(bnd, mmSolver._api.bundle.Bundle) if colour is not None: assert isinstance(colour, (tuple, list)) assert len(colour) == 3 # Transform tfm = maya.cmds.createNode('transform', name=name) tfm = api_utils.get_long_name(tfm) maya.cmds.setAttr(tfm + '.tz', -1.0) maya.cmds.setAttr(tfm + '.tz', lock=True) maya.cmds.setAttr(tfm + '.rx', lock=True) maya.cmds.setAttr(tfm + '.ry', lock=True) maya.cmds.setAttr(tfm + '.rz', lock=True) maya.cmds.setAttr(tfm + '.sx', lock=True) maya.cmds.setAttr(tfm + '.sy', lock=True) maya.cmds.setAttr(tfm + '.sz', lock=True) maya.cmds.setAttr(tfm + '.tz', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.rx', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.ry', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.rz', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.sx', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.sy', keyable=False, channelBox=False) maya.cmds.setAttr(tfm + '.sz', keyable=False, channelBox=False) # Shape Node shp_name = tfm.rpartition('|')[-1] + 'Shape' shp = maya.cmds.createNode('locator', name=shp_name, parent=tfm) maya.cmds.setAttr(shp + '.localScaleX', 0.01) maya.cmds.setAttr(shp + '.localScaleY', 0.01) maya.cmds.setAttr(shp + '.localScaleZ', 0.0) maya.cmds.setAttr(shp + '.localScaleZ', lock=True) # Add attrs maya.cmds.addAttr(tfm, longName='enable', at='short', minValue=0, maxValue=1, defaultValue=1) maya.cmds.addAttr(tfm, longName='weight', at='double', minValue=0.0, defaultValue=1.0) maya.cmds.addAttr(tfm, longName='bundle', at='message') maya.cmds.addAttr(tfm, longName='markerName', dt='string') maya.cmds.addAttr(tfm, longName='markerId', at='long', defaultValue=-1) maya.cmds.setAttr(tfm + '.enable', keyable=True, channelBox=True) maya.cmds.setAttr(tfm + '.weight', keyable=True, channelBox=True) maya.cmds.setAttr(tfm + '.markerName', lock=True) maya.cmds.connectAttr(tfm + '.enable', tfm + '.lodVisibility') self.set_node(tfm) # Set Colour (default is red) if colour is not None: self.set_colour_rgb(colour) else: red = (1.0, 0.0, 0.0) self.set_colour_rgb(red) # Link to Camera if cam is not None: self.set_camera(cam) # Link to MarkerGroup if mkr_grp is not None: self.set_marker_group(mkr_grp) # Link to Bundle if bnd is not None: self.set_bundle(bnd) return self
def collection_compile(col, sol_list, mkr_list, attr_list, withtest=False, prog_fn=None, status_fn=None): """ Take the data in this class and compile it into actions to run. :return: list of SolverActions. :rtype: [SolverAction, ..] """ col_node = col.get_node() action_list = [] vaction_list = [] if len(sol_list) == 0: msg = 'Collection is not valid, no Solvers given; ' msg += 'collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) sol_enabled_list = [sol for sol in sol_list if sol.get_enabled() is True] if len(sol_enabled_list) == 0: msg = 'Collection is not valid, no enabled Solvers given; ' msg += 'collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) if len(mkr_list) == 0: msg = 'Collection is not valid, no Markers given; collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) if len(attr_list) == 0: msg = 'Collection is not valid, no Attributes given; collection={0}' msg = msg.format(repr(col_node)) raise excep.NotValid(msg) # Query and cache static values from Maya, so we don't need to # re-compute the values inside Solvers. attr_static_values = get_attributes_static_values(col, attr_list) attr_stiff_static_values = get_attr_stiffness_static_values(col, attr_list) attr_smooth_static_values = get_attr_smoothness_static_values( col, attr_list) mkr_static_values = get_markers_static_values(mkr_list) precomputed_data = { solverbase.MARKER_STATIC_VALUES_KEY: mkr_static_values, solverbase.ATTR_STATIC_VALUES_KEY: attr_static_values, solverbase.ATTR_STIFFNESS_STATIC_VALUES_KEY: attr_stiff_static_values, solverbase.ATTR_SMOOTHNESS_STATIC_VALUES_KEY: attr_smooth_static_values, } # Compile all the solvers msg = 'Collection is not valid, failed to compile solver;' msg += ' collection={0}' msg = msg.format(repr(col_node)) for sol in sol_enabled_list: assert isinstance(sol, solverbase.SolverBase) sol.set_precomputed_data(precomputed_data) for action, vaction in sol.compile(col, mkr_list, attr_list, withtest=withtest): if not isinstance(action, api_action.Action): raise excep.NotValid(msg) assert action.func is not None assert action.args is not None assert action.kwargs is not None action_list.append(action) vaction_list.append(vaction) assert len(action_list) == len(vaction_list) return action_list, vaction_list
def attributes_compile_flags(col, attr_list, use_animated, use_static, attr_static_values=None): """ Compile Attributes into flags for mmSolver. :param col: Collection to be used for min/max values, :type col: Collection :param attr_list: List of Attributes to compile :type attr_list: [Attribute, ..] :param use_animated: Should we compile Attributes that are animated? :type use_animated: bool :param use_static: Should we compile Attributes that are static? :type use_static: bool :param attr_static_values: Attribute static values that can optionally be used to speed up compiling. :returns: List of tuples. Attributes in a form to be given to the mmSolver command. :rtype: [(str, str, str, str, str), ..] """ assert isinstance(use_animated, bool) assert isinstance(use_static, bool) if attr_static_values is None: attr_static_values = dict() assert isinstance(attr_static_values, dict) attrs = [] for attr in attr_list: assert isinstance(attr, attribute.Attribute) name = attr.get_name() attr_cache = DictGetOrCall(attr_static_values.get(name, dict())) locked = attr_cache.get_or_call('is_locked', attr.is_locked) if locked is True: continue node_name = attr_cache.get_or_call('node_name', attr.get_node) attr_name = attr_cache.get_or_call('attr_name', attr.get_attr) # If the user does not specify a min/max value then we get it # from Maya directly, if Maya doesn't have one, we leave # min/max_value as None and pass it to the mmSolver command # indicating there is no bound. # Minimum Value min_value = None min_enable = attr_cache.get_or_call( 'solver_min_enable', lambda: col.get_attribute_min_enable(attr)) if min_enable is True: min_value = attr_cache.get_or_call( 'solver_min_value', lambda: col.get_attribute_min_value(attr)) maya_min_exists = attr_cache.get_or_call( 'maya_min_exists', lambda: _get_maya_min_exists_from_attr(node_name, attr_name)) if maya_min_exists is True: maya_min_value = attr_cache.get_or_call( 'maya_min_value', lambda: _get_maya_min_value_from_attr(node_name, attr_name)) if len(maya_min_value) == 1: maya_min_value = maya_min_value[0] else: msg = 'Cannot handle attributes with multiple ' msg += 'minimum values; node={0} attr={1}' msg = msg.format(repr(node_name), repr(attr_name)) raise excep.NotValid(msg) if min_value is None: min_value = maya_min_value else: min_value = max(min_value, maya_min_value) # Maximum Value max_value = None max_enable = attr_cache.get_or_call( 'solver_max_enable', lambda: col.get_attribute_max_enable(attr)) if max_enable is True: max_value = attr_cache.get_or_call( 'solver_max_value', lambda: col.get_attribute_max_value(attr)) maya_max_exists = attr_cache.get_or_call( 'maya_max_exists', lambda: _get_maya_max_exists_from_attr(node_name, attr_name)) if maya_max_exists is True: maya_max_value = attr_cache.get_or_call( 'maya_max_value', lambda: _get_maya_max_value_from_attr(node_name, attr_name)) if len(maya_max_value) == 1: maya_max_value = maya_max_value[0] else: msg = 'Cannot handle attributes with multiple ' msg += 'maximum values; node={0} attr={1}' msg = msg.format(repr(node_name), repr(attr_name)) raise excep.NotValid(msg) if max_value is None: max_value = maya_max_value else: max_value = min(max_value, maya_max_value) # Scale and Offset scale_value = None offset_value = None attr_type = attr_cache.get_or_call( 'attribute_type', lambda: _get_attribute_type_from_attr(node_name, attr_name)) if attr_type.endswith('Angle'): offset_value = 360.0 animated = attr_cache.get_or_call('is_animated', attr.is_animated) static = attr_cache.get_or_call('is_static', attr.is_static) use = False if use_animated and animated is True: use = True if use_static and static is True: use = True if use is True: attrs.append((name, str(min_value), str(max_value), str(offset_value), str(scale_value))) return attrs