Untitled

 avatar
unknown
plain_text
3 years ago
14 kB
6
Indexable
# iRig
import rig_factory.build.utilities.controller_utilities as cut
import rig_factory.utilities.face_utilities.face_utilities as fut
import rig_factory.build.utilities.build_utilities as but
import rig_factory.object_versions as obs

# Maya module
import maya.cmds as mc


def auto_individual_lid_shapes(controller, vertical_lid_driver_dict, horizontal_lid_driver_value):
    """
    Creates individual lid shapes automatically based on the main lid shapes
    """

    # Find on face eye container parts
    left_eye_container = controller.root.find_first_part(
        obs.PartGroup,
        root_name='Eye',
        side='left'
    )
    right_eye_container = controller.root.find_first_part(
        obs.PartGroup,
        root_name='Eye',
        side='right'
    )

    lid_part, lid_up_mid_part, lid_down_mid_part, lid_up_out_part, lid_down_out_part = left_eye_container.parts[0:5]

    if not left_eye_container:
        raise Exception('No Eye container found')

    # Check if face network created, if not, import from build directory
    face_network = controller.face_network
    if not face_network:
        if not controller.face_network:
            face_blueprint_path = '{0}/face_blueprint.json'.format(controller.build_directory)
            but.build_face_heirarchy(
                controller,
                face_blueprint_path=face_blueprint_path
            )

    # If the main lid/blink shapes are missing, abort
    if not controller.named_objects.get('L_Face_LidUprVertical_Grp', None) and not \
        controller.named_objects.get('L_Face_LidLwrVertical_Grp', None):
        raise StandardError('Missing main lid shapes, aborting...')

    # Assigning an index/segment to determine which control is the inner/middle/outer
    # 0 == inner, 1 == middle, 2 == outer
    vertical_face_group_names = {
        'L_Face_UpLidInVertical_Grp': 0,
        'L_Face_DownLidInVertical_Grp': 0,
        'L_Face_UpLidMidVertical_Grp': 1,
        'L_Face_DownLidMidVertical_Grp': 1,
        'L_Face_UpLidOutVertical_Grp': 2,
        'L_Face_DownLidOutVertical_Grp': 2,
    }
    horizontal_face_group_names = {
        'L_Face_UpLidInHorizontal_Grp': 0,
        'L_Face_DownLidInHorizontal_Grp': 0,
        'L_Face_UpLidMidHorizontal_Grp': 1,
        'L_Face_DownLidMidHorizontal_Grp': 1,
        'L_Face_UpLidOutHorizontal_Grp': 2,
        'L_Face_DownLidOutHorizontal_Grp': 2,
    }

    # Define settings to use for a remap node which will be used to grab the transforms from secondary handles
    remap_settings = {
        0: {
            0: {
                'value_Position': 0.0,
                'value_FloatValue': 1.0
            },
            1: {
                'value_Position': 0.5,
                'value_FloatValue': 0.0
            }
        },
        1: {
            0: {
                'value_Position': 0.0,
                'value_FloatValue': 0.0
            },
            1: {
                'value_Position': 0.5,
                'value_FloatValue': 1.0
            },
            2: {
                'value_Position': 1.0,
                'value_FloatValue': 0.0
            }
        },
        2: {
            0: {
                'value_Position': 0.5,
                'value_FloatValue': 0.0
            },
            1: {
                'value_Position': 1.0,
                'value_FloatValue': 1.0
            }
        }
    }

    # Separate upper and lower face groups into separate lists
    upper_vertical_face_group_names = [x for x in vertical_face_group_names if 'UpLid' in x]
    lower_vertical_face_group_names = [x for x in vertical_face_group_names if 'DownLid' in x]
    upper_horizontal_face_group_names = [x for x in horizontal_face_group_names if 'UpLid' in x]
    lower_horizontal_face_group_names = [x for x in horizontal_face_group_names if 'DownLid' in x]

    for side in vertical_lid_driver_dict:
        face_group_positions = {}  # Dict for storing postions of the handles after triggering main shapes

        # Define variables needed depending on which side is being used
        if side == 'Upr':
            filtered_vertical_face_group_names = upper_vertical_face_group_names
            all_handles = [lid_part.upper_handles, lid_up_mid_part.handles, lid_up_out_part.handles]
            secondary_handles = lid_part.upper_spline_handles
            driver_group = controller.named_objects['L_Face_LidUprVertical_Grp']
        elif side == 'Lwr':
            filtered_vertical_face_group_names = lower_vertical_face_group_names
            all_handles = [lid_part.lower_handles, lid_down_mid_part.handles, lid_down_out_part.handles]
            secondary_handles = lid_part.lower_spline_handles
            driver_group = controller.named_objects['L_Face_LidLwrVertical_Grp']

        # Check to see if individual lid shapes already exist based on list defined earlier
        for face_group_name in vertical_face_group_names:
            face_group = controller.named_objects.get(face_group_name, None)
            if not face_group:
                raise StandardError('Missing {0}'.format(face_group_name))

        for driver_value, driven_value in vertical_lid_driver_dict[side].items():
            # Trigger the lid shape needed for individual shapes
            driver_group.driver_plug.set_value(driver_value)
            for face_group_name in filtered_vertical_face_group_names:
                data = {}
                segment = vertical_face_group_names[face_group_name]
                handles = [x[segment] for x in all_handles]
                # Get position and store them
                for handle in handles:
                    translation = mc.xform(
                        handle,
                        query=True,
                        worldSpace=True,
                        translation=True
                    )
                    rotation = mc.xform(
                        handle,
                        query=True,
                        worldSpace=True,
                        rotation=True
                    )
                    data[handle] = [translation, rotation]

                for secondary_handle in secondary_handles:
                    translation = mc.xform(
                        secondary_handle.drv,
                        query=True,
                        objectSpace=True,
                        translation=True
                    )
                    rotation = mc.xform(
                        secondary_handle.drv,
                        query=True,
                        objectSpace=True,
                        rotation=True
                    )
                    data[secondary_handle] = [translation, rotation]

                face_group_positions[segment] = data

            # Reset shape before triggering individual shapes
            controller.face_network.reset_driver_plugs()
            for face_group_name in filtered_vertical_face_group_names:
                face_group = controller.named_objects[face_group_name]
                segment = vertical_face_group_names[face_group_name]
                data = face_group_positions.get(segment)
                handles = [x[segment] for x in all_handles]
                driven_face_target_index = None

                # Find which index of face target is equal to the correct driven value
                for i, face_target in enumerate(face_group.face_targets):
                    if face_target.driver_value == driven_value:
                        driven_face_target_index = i
                        break

                if not driven_face_target_index:
                    raise Exception('{0} does not seem to be a valid driver value at {1}'.format(
                        face_group.name, driven_value
                    ))

                # Set position of controls
                for handle in handles:
                    translation, rotation = data[handle]
                    mc.xform(
                        handle,
                        worldSpace=True,
                        translation=translation
                    )
                    mc.xform(
                        handle,
                        worldSpace=True,
                        rotation=rotation
                    )

                # Need to ramp off secondary handles for each sections
                remap = mc.createNode('remapValue')
                attr_data = remap_settings[segment]
                for index in attr_data:
                    remap_data = attr_data[index]
                    for attr, value in remap_data.items():
                        mc.setAttr(
                            '{0}.value[{1}].{2}'.format(remap, index, attr),
                            value
                        )
                        mc.setAttr(
                            '{0}.value[{1}].value_Interp'.format(remap, index),
                            3
                        )
                for i, secondary_handle in enumerate(secondary_handles):
                    # Find value at point of remap
                    remap_value = i / (len(secondary_handles) - 1.0)
                    mc.setAttr('{0}.inputValue'.format(remap), remap_value)
                    out_value = mc.getAttr('{0}.outValue'.format(remap))

                    translation, rotation = data[secondary_handle]
                    mc.xform(
                        secondary_handle,
                        objectSpace=True,
                        translation=[x * out_value for x in translation]
                    )
                    mc.xform(
                        secondary_handle,
                        objectSpace=True,
                        rotation=[x * out_value for x in rotation]
                    )

                #  Update sdks
                fut.update_face_target_sdks(
                    face_group.face_targets[driven_face_target_index],
                    consolidate_surfaces=True,
                    consolidate_groups=True
                )
                controller.face_network.reset_driver_plugs()

                mc.delete(remap)

    # Horizontal lid shapes
    for side in ['Upr', 'Lwr']:
        # Define variables needed depending on which side is being used
        if side == 'Upr':
            filtered_horizontal_face_group_names = upper_horizontal_face_group_names
            lid_handles = lid_part.upper_handles
            mid_lid_handles = lid_up_mid_part.handles

        elif side == 'Lwr':
            filtered_horizontal_face_group_names = lower_horizontal_face_group_names
            lid_handles = lid_part.lower_handles
            mid_lid_handles = lid_down_mid_part.handles

        for face_group_name in filtered_horizontal_face_group_names:
            # Check to see if individual lid shapes already exist based on list defined earlier
            face_group = controller.named_objects.get(face_group_name, None)
            if not face_group:
                raise StandardError('Missing {0}'.format(face_group_name))

            face_group = controller.named_objects[face_group_name]
            segment = horizontal_face_group_names[face_group_name]
            handles = [x[segment] for x in [lid_handles, mid_lid_handles]]

            driver_values = [-1.0, 1.0]
            for driver_value in driver_values:
                # Find which index of face target is equal to the correct driven value
                for i, face_target in enumerate(face_group.face_targets):
                    if face_target.driver_value == driver_value:
                        driven_face_target_index = i
                        if driver_value < 0.0:
                            horizontal_update_driver_value = -horizontal_lid_driver_value
                        else:
                            horizontal_update_driver_value = horizontal_lid_driver_value
                        break

                if not driven_face_target_index:
                    raise Exception('{0} does not seem to be a valid driver value at {1}'.format(
                        face_group.name, driver_value
                    ))

                # Set position of controls
                for handle in handles:
                    if handle in lid_handles:
                        mc.setAttr(
                            '{0}.ParameterU'.format(handle),
                            horizontal_update_driver_value
                        )
                    elif handle in mid_lid_handles:
                        mc.setAttr(
                            '{0}.ParameterU'.format(handle),
                            horizontal_update_driver_value / 2.0
                        )

                # Update sdks
                fut.update_face_target_sdks(
                    face_group.face_targets[driven_face_target_index],
                    consolidate_surfaces=True,
                    consolidate_groups=True
                )
                controller.face_network.reset_driver_plugs()

    print 'Done'


controller = cut.get_controller()

vertical_lid_driver_dict = {
    'Upr': {-0.25: -1.0, 0.25: 1.0},  # For example, -0.25 of the main lid shape will drive -1.0 of individual shape
    'Lwr': {-0.5: -1.0, 0.3: 1.0}
}
horizontal_lid_driver_value = 0.1  # This will move the parameterU attribute by +-x amount

auto_individual_lid_shapes(controller, vertical_lid_driver_dict, horizontal_lid_driver_value)
Editor is loading...